Merge mozilla-central into the static-xpcom-registration branch.
authorBenjamin Smedberg <benjamin@smedbergs.us>
Wed, 23 Jun 2010 17:26:25 -0400
changeset 47039 aae6f414c19ac3d7847712e6f9f20cfbc7ecf191
parent 47038 c0c2402ce4f746f5df9eabd8d3d3b938a10f27b4 (current diff)
parent 44206 2f83edbbeef0de7dd901411d270da61106c8afae (diff)
child 47040 fa3febb60a8ca125cc55c8c9b20c24ebc94c9ff1
push idunknown
push userunknown
push dateunknown
milestone1.9.3a6pre
Merge mozilla-central into the static-xpcom-registration branch.
.hgtags
browser/components/nsBrowserGlue.js
browser/installer/package-manifest.in
content/base/src/nsContentUtils.cpp
content/xul/templates/src/nsXULContentBuilder.cpp
layout/build/nsLayoutStatics.cpp
media/libvorbis/bug498855.patch
media/libvorbis/bug550184.patch
modules/plugin/base/src/nsPluginHost.cpp
netwerk/cache/nsCacheService.cpp
netwerk/cache/nsCacheService.h
other-licenses/nsis/Contrib/ShellLink/ConvFunc.h
other-licenses/nsis/Contrib/ShellLink/Readme.html
other-licenses/nsis/Contrib/ShellLink/ShellLink.cpp
other-licenses/nsis/Contrib/ShellLink/ShellLink.dsp
other-licenses/nsis/Contrib/ShellLink/ShellLink.dsw
other-licenses/nsis/Contrib/UAC/History.txt
other-licenses/nsis/Contrib/UAC/License.txt
other-licenses/nsis/Contrib/UAC/NSISUtil.h
other-licenses/nsis/Contrib/UAC/RunAs.cpp
other-licenses/nsis/Contrib/UAC/UAC Readme.html
other-licenses/nsis/Contrib/UAC/UAC.dsp
other-licenses/nsis/Contrib/UAC/UAC.dsw
other-licenses/nsis/Contrib/UAC/resource.h
other-licenses/nsis/Contrib/UAC/resource.rc
other-licenses/nsis/Contrib/UAC/uac.cpp
other-licenses/nsis/Contrib/UAC/uac.h
toolkit/components/autocomplete/src/nsAutoCompleteController.cpp
toolkit/components/console/Makefile.in
toolkit/components/places/src/nsNavHistory.cpp
toolkit/components/prompts/src/nsPrompter.js
toolkit/mozapps/installer/CFGParser.pm
toolkit/mozapps/installer/make-installjsremoves.pl
toolkit/mozapps/installer/makecfgini.pl
toolkit/mozapps/installer/makeinstallini.pl
toolkit/mozapps/installer/windows/nsis/check-locales.pl
toolkit/mozapps/installer/windows/nsis/make-installremoves.pl
toolkit/xre/nsXREDirProvider.cpp
--- a/accessible/src/base/nsAccessNode.cpp
+++ b/accessible/src/base/nsAccessNode.cpp
@@ -252,41 +252,23 @@ void nsAccessNode::ShutdownXPAccessibili
   if (gApplicationAccessible) {
     gApplicationAccessible->Shutdown();
     NS_RELEASE(gApplicationAccessible);
   }
 
   NotifyA11yInitOrShutdown(PR_FALSE);
 }
 
-PRBool
-nsAccessNode::IsDefunct()
+already_AddRefed<nsIPresShell>
+nsAccessNode::GetPresShell()
 {
-  if (!mContent)
-    return PR_TRUE;
-
-  // Call GetPresShell() since the accessible may be shut down in it.
-  nsCOMPtr<nsIPresShell> presShell(GetPresShell());
-  return !presShell;
-}
-
-already_AddRefed<nsIPresShell> nsAccessNode::GetPresShell()
-{
-  nsIPresShell *presShell = nsnull;
+  nsIPresShell* presShell = nsnull;
   if (mWeakShell)
     CallQueryReferent(mWeakShell.get(), &presShell);
-  if (!presShell) {
-    if (mWeakShell) {
-      // If our pres shell has died, but we're still holding onto
-      // a weak reference, our accessibles are no longer relevant
-      // and should be shut down
-      Shutdown();
-    }
-    return nsnull;
-  }
+
   return presShell;
 }
 
 // nsAccessNode protected
 nsPresContext* nsAccessNode::GetPresContext()
 {
   nsCOMPtr<nsIPresShell> presShell(GetPresShell());
   if (!presShell) {
--- a/accessible/src/base/nsAccessNode.h
+++ b/accessible/src/base/nsAccessNode.h
@@ -115,20 +115,20 @@ public:
   /**
    * Return focused node within accessible window.
    *
    * XXX: it shouldn't break us if we return focused node not depending on
    * window so that we can turn this method into util method.
    */
   already_AddRefed<nsINode> GetCurrentFocus();
 
-    /**
-     * Returns true when the accessible is defunct.
-     */
-    virtual PRBool IsDefunct();
+  /**
+   * Returns true when the accessible is defunct.
+   */
+  virtual PRBool IsDefunct() { return !mContent; }
 
   /**
    * Initialize the access node object, add it to the cache.
    */
   virtual PRBool Init();
 
   /**
    * Shutdown the access node object.
--- a/accessible/src/base/nsRootAccessible.cpp
+++ b/accessible/src/base/nsRootAccessible.cpp
@@ -71,16 +71,17 @@
 #include "nsISelectionPrivate.h"
 #include "nsIServiceManager.h"
 #include "nsPIDOMWindow.h"
 #include "nsIWebBrowserChrome.h"
 #include "nsReadableUtils.h"
 #include "nsRootAccessible.h"
 #include "nsIDOMNSEventTarget.h"
 #include "nsIDOMDocumentEvent.h"
+#include "nsIPrivateDOMEvent.h"
 #include "nsFocusManager.h"
 #include "mozilla/dom/Element.h"
 
 
 #ifdef MOZ_XUL
 #include "nsXULTreeAccessible.h"
 #include "nsIXULDocument.h"
 #include "nsIXULWindow.h"
@@ -478,16 +479,19 @@ nsRootAccessible::FireCurrentFocusEvent(
         // then simulate the focus event for the document.
         nsINode *document = targetNode->GetOwnerDoc();
         if (targetNode == nsCoreUtils::GetRoleContent(document)) {
           HandleEventWithTarget(event, document);
           return;
         }
 
         // Otherwise simulate the focus event for currently focused node.
+        nsCOMPtr<nsIPrivateDOMEvent> privateEvent(do_QueryInterface(event));
+        nsCOMPtr<nsIDOMEventTarget> target(do_QueryInterface(focusedNode));
+        privateEvent->SetTarget(target);
         HandleEventWithTarget(event, targetNode);
       }
     }
   }
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsIDOMEventListener
--- a/accessible/src/html/nsHTMLSelectAccessible.cpp
+++ b/accessible/src/html/nsHTMLSelectAccessible.cpp
@@ -469,17 +469,17 @@ nsHTMLSelectOptionAccessible::GetNameInt
     return NS_OK;
   }
 
   return NS_OK;
 }
 
 nsIFrame* nsHTMLSelectOptionAccessible::GetBoundsFrame()
 {
-  PRUint32 state;
+  PRUint32 state = 0;
   nsCOMPtr<nsIContent> content = GetSelectState(&state);
   if (state & nsIAccessibleStates::STATE_COLLAPSED) {
     if (content) {
       return content->GetPrimaryFrame();
     }
 
     return nsnull;
   }
@@ -499,17 +499,17 @@ nsresult
 nsHTMLSelectOptionAccessible::GetStateInternal(PRUint32 *aState,
                                                PRUint32 *aExtraState)
 {
   // Upcall to nsAccessible, but skip nsHyperTextAccessible impl
   // because we don't want EXT_STATE_EDITABLE or EXT_STATE_SELECTABLE_TEXT
   nsresult rv = nsAccessible::GetStateInternal(aState, aExtraState);
   NS_ENSURE_A11Y_SUCCESS(rv, rv);
 
-  PRUint32 selectState, selectExtState;
+  PRUint32 selectState = 0, selectExtState = 0;
   nsCOMPtr<nsIContent> selectContent = GetSelectState(&selectState,
                                                       &selectExtState);
   if (selectState & nsIAccessibleStates::STATE_INVISIBLE) {
     return NS_OK;
   }
 
   NS_ENSURE_TRUE(selectContent, NS_ERROR_FAILURE);
 
@@ -794,29 +794,34 @@ nsHTMLSelectOptionAccessible::SelectionC
   PRUint32 eventType;
   if (state & nsIAccessibleStates::STATE_SELECTED) {
     eventType = nsIAccessibleEvent::EVENT_SELECTION_ADD;
   }
   else {
     eventType = nsIAccessibleEvent::EVENT_SELECTION_REMOVE;
   }
 
-  nsRefPtr<nsAccEvent> setAddRemoveEvent =
+  nsRefPtr<nsAccEvent> selAddRemoveEvent =
     new nsAccEvent(eventType, option);
 
-  if (setAddRemoveEvent)
-    option->GetDocAccessible()->FireDelayedAccessibleEvent(setAddRemoveEvent);
+  if (selAddRemoveEvent)
+    option->GetDocAccessible()->FireDelayedAccessibleEvent(selAddRemoveEvent);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsHTMLSelectOptionAccessible: private methods
 
 nsIContent* nsHTMLSelectOptionAccessible::GetSelectState(PRUint32* aState,
                                                          PRUint32* aExtraState)
 {
+  *aState = 0;
+
+  if (aExtraState)
+    *aExtraState = 0;
+
   nsIContent *content = mContent;
   while (content && content->Tag() != nsAccessibilityAtoms::select) {
     content = content->GetParent();
   }
 
   nsCOMPtr<nsIDOMNode> selectNode(do_QueryInterface(content));
   if (selectNode) {
     nsCOMPtr<nsIAccessible> selAcc;
--- a/browser/base/content/browser-menubar.inc
+++ b/browser/base/content/browser-menubar.inc
@@ -606,16 +606,21 @@
                         accesskey="&inspectMenu.accesskey;"
                         key="key_inspect"
                         command="Tools:Inspect"/>
               <menuitem id="javascriptConsole"
                         label="&errorConsoleCmd.label;"
                         accesskey="&errorConsoleCmd.accesskey;"
                         key="key_errorConsole"
                         oncommand="toJavaScriptConsole();"/>
+              <menuitem id="headsUpDisplayConsole"
+                        label="&hudConsoleCmd.label;"
+                        accesskey="&hudConsoleCmd.accesskey;"
+                        key="key_hudConsole"
+                        oncommand="HUDConsoleUI.toggleHUD();"/>
               <menuitem id="menu_pageInfo"
                         accesskey="&pageInfoCmd.accesskey;"
                         label="&pageInfoCmd.label;"
 #ifndef XP_WIN
                         key="key_viewInfo"
 #endif
                         command="View:PageInfo"/>
               <menuseparator id="sanitizeSeparator"/>
--- a/browser/base/content/browser-sets.inc
+++ b/browser/base/content/browser-sets.inc
@@ -217,16 +217,17 @@
 #endif
 #ifdef XP_GNOME
     <key id="key_search2" key="&searchFocusUnix.commandkey;" command="Tools:Search" modifiers="accel"/>
     <key id="key_openDownloads" key="&downloadsUnix.commandkey;" command="Tools:Downloads" modifiers="accel,shift"/>
 #else
     <key id="key_openDownloads" key="&downloads.commandkey;" command="Tools:Downloads" modifiers="accel"/>
 #endif
     <key id="key_errorConsole" key="&errorConsoleCmd.commandkey;" oncommand="toJavaScriptConsole();" modifiers="accel,shift"/>
+    <key id="key_hudConsole" key="&hudConsoleCmd.commandkey;" oncommand="HUDConsoleUI.toggleHUD();" modifiers="accel,shift"/>
     <key id="key_inspect" key="&inspectMenu.commandkey;" command="Tools:Inspect" modifiers="accel,shift"/>
     <key id="openFileKb" key="&openFileCmd.commandkey;" command="Browser:OpenFile"  modifiers="accel"/>
     <key id="key_savePage" key="&savePageCmd.commandkey;" command="Browser:SavePage" modifiers="accel"/>
     <key id="printKb" key="&printCmd.commandkey;" command="cmd_print"  modifiers="accel"/>
     <key id="key_close" key="&closeCmd.key;" command="cmd_close" modifiers="accel"/>
     <key id="key_closeWindow" key="&closeCmd.key;" command="cmd_closeWindow" modifiers="accel,shift"/>
     <key id="key_undo"
          key="&undoCmd.key;"
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -134,16 +134,24 @@ XPCOMUtils.defineLazyGetter(window, "gFi
   Cu.import("resource://gre/modules/PluralForm.jsm");
   return this.PluralForm;
 });
 __defineSetter__("PluralForm", function (val) {
   delete this.PluralForm;
   return this.PluralForm = val;
 });
 
+XPCOMUtils.defineLazyGetter(this, "PopupNotifications", function () {
+  let tmp = {};
+  Cu.import("resource://gre/modules/PopupNotifications.jsm", tmp);
+  return new tmp.PopupNotifications(gBrowser,
+                                    document.getElementById("notification-popup"),
+                                    document.getElementById("notification-popup-box"));
+});
+
 let gInitialPages = [
   "about:blank",
   "about:privatebrowsing",
   "about:sessionrestore"
 ];
 
 #include browser-fullZoom.js
 #include inspector.js
@@ -983,24 +991,16 @@ function BrowserStartup() {
     }
     // Note: loadOneOrMoreURIs *must not* be called if window.arguments.length >= 3.
     // Such callers expect that window.arguments[0] is handled as a single URI.
     else
       loadOneOrMoreURIs(uriToLoad);
   }
 
   if (window.opener && !window.opener.closed) {
-    let openerFindBar = window.opener.gFindBarInitialized ?
-                        window.opener.gFindBar : null;
-    if (openerFindBar &&
-        !openerFindBar.hidden &&
-        openerFindBar.findMode == openerFindBar.FIND_NORMAL) {
-      gFindBar.open();
-    }
-
     let openerSidebarBox = window.opener.document.getElementById("sidebar-box");
     // If the opener had a sidebar, open the same sidebar in our window.
     // The opener can be the hidden window too, if we're coming from the state
     // where no windows are open, and the hidden window has no sidebar box.
     if (openerSidebarBox && !openerSidebarBox.hidden) {
       let sidebarCmd = openerSidebarBox.getAttribute("sidebarcommand");
       let sidebarCmdElem = document.getElementById(sidebarCmd);
 
@@ -4093,16 +4093,18 @@ var XULBrowserWindow = {
       let newIndexOfHash = newSpec.indexOf("#");
       if (newIndexOfHash != -1)
         newSpec = newSpec.substr(0, newSpec.indexOf("#"));
       if (newSpec != oldSpec) {
         // Remove all the notifications, except for those which want to
         // persist across the first location change.
         let nBox = gBrowser.getNotificationBox(selectedBrowser);
         nBox.removeTransientNotifications();
+
+        PopupNotifications.locationChange();
       }
     }
 
     // Disable menu entries for images, enable otherwise
     if (content.document && mimeTypeIsTextBased(content.document.contentType))
       this.isImage.removeAttribute('disabled');
     else
       this.isImage.setAttribute('disabled', 'true');
@@ -7666,8 +7668,19 @@ var TabContextMenu = {
     // XXXzeniko should't we just disable this item as we disable
     // the tabbrowser-multiple items above - for consistency?
     document.getElementById("context_undoCloseTab").hidden =
       Cc["@mozilla.org/browser/sessionstore;1"].
       getService(Ci.nsISessionStore).
       getClosedTabCount(window) == 0;
   }
 };
+
+XPCOMUtils.defineLazyGetter(this, "HUDConsoleUI", function () {
+  Cu.import("resource://gre/modules/HUDService.jsm");
+  try {
+    return HUDService.consoleUI;
+  }
+  catch (ex) {
+    Components.utils.reportError(ex);
+  }
+});
+
--- a/browser/base/content/browser.xul
+++ b/browser/base/content/browser.xul
@@ -239,55 +239,57 @@
           <splitter class="tree-splitter"/>
           <treecol id="colNodeValue" label="nodeValue"
                    persist="width,hidden,ordinal" flex="1"/>
         </treecols>
         <treechildren id="inspector-tree-body"/>
       </tree>
     </panel>
 
-    <popup id="toolbar-context-menu"
-           onpopupshowing="onViewToolbarsPopupShowing(event);">
+    <menupopup id="toolbar-context-menu"
+               onpopupshowing="onViewToolbarsPopupShowing(event);">
       <menuseparator/>
       <menuitem command="cmd_ToggleTabsOnTop"
                 type="checkbox"
                 label="&viewTabsOnTop.label;"
                 accesskey="&viewTabsOnTop.accesskey;"/>
       <menuseparator/>
       <menuitem command="cmd_CustomizeToolbars"
                 label="&viewCustomizeToolbar.label;"
                 accesskey="&viewCustomizeToolbar.accesskey;"/>
-    </popup>
+    </menupopup>
 
-    <popup id="blockedPopupOptions" 
-           onpopupshowing="gPopupBlockerObserver.fillPopupList(event);">
+    <menupopup id="blockedPopupOptions" 
+               onpopupshowing="gPopupBlockerObserver.fillPopupList(event);">
       <menuitem observes="blockedPopupAllowSite"/>
       <menuitem observes="blockedPopupEditSettings"/>
       <menuitem observes="blockedPopupDontShowMessage"/>
       <menuseparator observes="blockedPopupsSeparator"/>
-    </popup>
+    </menupopup>
 
     <menupopup id="autohide-context"
            onpopupshowing="FullScreen.getAutohide(this.firstChild);">
       <menuitem type="checkbox" label="&fullScreenAutohide.label;"
                 accesskey="&fullScreenAutohide.accesskey;"
                 oncommand="FullScreen.setAutohide();"/>
       <menuseparator/>
       <menuitem label="&fullScreenExit.label;"
                 accesskey="&fullScreenExit.accesskey;"
                 oncommand="BrowserFullScreen();"/>
     </menupopup>
 
-    <popup id="contentAreaContextMenu"
-           onpopupshowing="if (event.target != this) return true; updateEditUIVisibility(); gContextMenu = new nsContextMenu(this, window.getBrowser()); return gContextMenu.shouldDisplay;"
-           onpopuphiding="if (event.target == this) { gContextMenu = null; updateEditUIVisibility(); }">
+    <menupopup id="contentAreaContextMenu"
+               onpopupshowing="if (event.target != this) return true; updateEditUIVisibility(); gContextMenu = new nsContextMenu(this, window.getBrowser()); return gContextMenu.shouldDisplay;"
+               onpopuphiding="if (event.target == this) { gContextMenu = null; updateEditUIVisibility(); }">
 #include browser-context.inc
-    </popup>
+    </menupopup>
 
-    <popup id="placesContext"/>
+    <menupopup id="placesContext"/>
+
+    <panel id="notification-popup" position="after_start" noautofocus="true" hidden="true"/>
 
     <!-- Popup for site identity information -->
     <panel id="identity-popup" position="after_start" hidden="true" noautofocus="true"
            onpopupshown="document.getElementById('identity-popup-more-info-button').focus();"
            level="top">
       <hbox id="identity-popup-container" align="top">
         <image id="identity-popup-icon"/>
         <vbox id="identity-popup-content-box">
@@ -602,16 +604,19 @@
                  oninput="gBrowser.userTypedValue = this.value;"
                  ontextentered="this.handleCommand(param);"
                  ontextreverted="return this.handleRevert();"
                  pageproxystate="invalid"
                  onsearchbegin="LocationBarHelpers._searchBegin();"
                  onsearchcomplete="LocationBarHelpers._searchComplete();"
                  onfocus="document.getElementById('identity-box').style.MozUserFocus= 'normal'"
                  onblur="setTimeout(function() document.getElementById('identity-box').style.MozUserFocus = '', 0);">
+          <box id="notification-popup-box" hidden="true" align="center">
+            <image id="geo-notification-icon"/>
+          </box>
           <!-- Use onclick instead of normal popup= syntax since the popup
                code fires onmousedown, and hence eats our favicon drag events.
                We only add the identity-box button to the tab order when the location bar
                has focus, otherwise pressing F6 focuses it instead of the location bar -->
           <box id="identity-box" role="button"
                onclick="gIdentityHandler.handleIdentityButtonEvent(event);"
                onkeypress="gIdentityHandler.handleIdentityButtonEvent(event);">
             <hbox id="identity-box-inner" align="center">
--- a/browser/base/content/pageinfo/pageInfo.js
+++ b/browser/base/content/pageinfo/pageInfo.js
@@ -535,32 +535,32 @@ function goThroughFrames(aDocument, aWin
 
 function processFrames()
 {
   if (gFrameList.length) {
     var doc = gFrameList[0];
     onProcessFrame.forEach(function(func) { func(doc); });
     var iterator = doc.createTreeWalker(doc, NodeFilter.SHOW_ELEMENT, grabAll, true);
     gFrameList.shift();
-    setTimeout(doGrab, 16, iterator);
+    setTimeout(doGrab, 10, iterator);
     onFinished.push(selectImage);
   }
   else
     onFinished.forEach(function(func) { func(); });
 }
 
 function doGrab(iterator)
 {
-  for (var i = 0; i < 50; ++i)
+  for (var i = 0; i < 500; ++i)
     if (!iterator.nextNode()) {
       processFrames();
       return;
     }
 
-  setTimeout(doGrab, 16, iterator);
+  setTimeout(doGrab, 10, iterator);
 }
 
 function addImage(url, type, alt, elem, isBg)
 {
   if (!url)
     return;
 
   if (!gImageHash.hasOwnProperty(url))
@@ -976,22 +976,18 @@ function makePreview(row)
     document.getElementById("brokenimagecontainer").collapsed = true;
   }
 #ifdef MOZ_MEDIA
   else if (item instanceof HTMLVideoElement && isProtocolAllowed) {
     newImage = document.createElementNS("http://www.w3.org/1999/xhtml", "video");
     newImage.id = "thepreviewimage";
     newImage.mozLoadFrom(item);
     newImage.controls = true;
-    physWidth = item.videoWidth;
-    physHeight = item.videoHeight;
-    width = item.width != -1 ? item.width : physWidth;
-    height = item.height != -1 ? item.height : physHeight;
-    newImage.width = width;
-    newImage.height = height;
+    width = physWidth = item.videoWidth;
+    height = physHeight = item.videoHeight;
 
     document.getElementById("theimagecontainer").collapsed = false;
     document.getElementById("brokenimagecontainer").collapsed = true;
   }
   else if (item instanceof HTMLAudioElement && isProtocolAllowed) {
     newImage = new Audio;
     newImage.id = "thepreviewimage";
     newImage.src = url;
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -2782,22 +2782,27 @@
       <handler event="dblclick"><![CDATA[
         // See hack note in the tabbrowser-close-button binding
         if (!this._blockDblClick && event.button == 0 &&
             event.originalTarget.localName == "box")
           BrowserOpenTab();
       ]]></handler>
 
       <handler event="click"><![CDATA[
-        if (event.button != 1 || event.target.localName != "tab")
+        if (event.button != 1)
           return;
 
-        if (this.childNodes.length > 1 ||
-            !this._closeWindowWithLastTab)
-          this.tabbrowser.removeTab(event.target);
+        if (event.target.localName == "tab") {
+          if (this.childNodes.length > 1 || !this._closeWindowWithLastTab)
+            this.tabbrowser.removeTab(event.target);
+        } else if (event.originalTarget.localName == "box") {
+          BrowserOpenTab();
+        } else {
+          return;
+        }
 
         event.stopPropagation();
       ]]></handler>
 
       <handler event="keypress"><![CDATA[
         if (event.altKey || event.shiftKey ||
 #ifdef XP_MACOSX
             !event.metaKey)
--- a/browser/base/content/test/Makefile.in
+++ b/browser/base/content/test/Makefile.in
@@ -109,16 +109,17 @@ endif
                  browser_bug419612.js \
                  browser_bug420160.js \
                  browser_bug422590.js \
                  browser_bug424101.js \
                  browser_bug427559.js \
                  browser_bug432599.js \
                  browser_bug435035.js \
                  browser_bug441778.js \
+                 browser_popupNotification.js \
                  browser_bug455852.js \
                  browser_bug462673.js \
                  browser_bug477014.js \
                  browser_bug479408.js \
                  browser_bug479408_sample.html \
                  browser_bug481560.js \
                  browser_bug484315.js \
                  browser_bug491431.js \
--- a/browser/base/content/test/browser_overflowScroll.js
+++ b/browser/base/content/test/browser_overflowScroll.js
@@ -59,18 +59,22 @@ function runOverflowTests(aEvent) {
 
   element = elementFromPoint(left(scrollbox) - width(scrollbox));
   EventUtils.synthesizeMouse(upButton, 0, 0, {clickCount: 2});
   isLeft(element, "Scrolled one page of tabs with a double click");
 
   EventUtils.synthesizeMouse(upButton, 0, 0, {clickCount: 3});
   isLeft(tabContainer.firstChild, "Scrolled to the start with a triple click");
 
+  for (var i = 2; i; i--)
+    EventUtils.synthesizeMouseScroll(scrollbox, 0, 0, {axis: "horizontal", delta: -1});
+  isLeft(tabContainer.firstChild, "Remained at the start with the mouse wheel");
+
   element = nextRightElement();
-  EventUtils.synthesizeMouseScroll(scrollbox, 0, 0, {delta: 1});
+  EventUtils.synthesizeMouseScroll(scrollbox, 0, 0, {axis: "horizontal", delta: 1});
   isRight(element, "Scrolled one tab to the right with the mouse wheel");
 
   while (tabContainer.childNodes.length > 1)
     gBrowser.removeTab(tabContainer.lastChild);
 
   tabstrip.smoothScroll = originalSmoothScroll;
   finish();
 }
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/browser_popupNotification.js
@@ -0,0 +1,383 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is browser popup notification test code.
+ *
+ * The Initial Developer of the Original Code is
+ * the Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Gavin Sharp <gavin@gavinsharp.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+function test() {
+  waitForExplicitFinish();
+
+  ok(PopupNotifications, "PopupNotifications object exists");
+  ok(PopupNotifications.panel, "PopupNotifications panel exists");
+
+  registerCleanupFunction(cleanUp);
+
+  runNextTest();
+}
+
+function cleanUp() {
+  for (var topic in gActiveObservers)
+    Services.obs.removeObserver(gActiveObservers[topic], topic);
+  for (var eventName in gActiveListeners)
+    PopupNotifications.panel.removeEventListener(eventName, gActiveListeners[eventName], false);
+}
+
+var gActiveListeners = {};
+var gActiveObservers = {};
+
+function runNextTest() {
+  let nextTest = tests[gTestIndex];
+
+  function goNext() {
+    if (++gTestIndex == tests.length)
+      executeSoon(finish);
+    else
+      executeSoon(runNextTest);
+  }
+
+  function addObserver(topic) {
+    function observer() {
+      Services.obs.removeObserver(observer, "PopupNotifications-" + topic);
+      delete gActiveObservers["PopupNotifications-" + topic];
+
+      info("[Test #" + gTestIndex + "] observer for " + topic + " called");
+      nextTest[topic]();
+      goNext();
+    }
+    Services.obs.addObserver(observer, "PopupNotifications-" + topic, false);
+    gActiveObservers["PopupNotifications-" + topic] = observer;
+  }
+
+  if (nextTest.backgroundShow) {
+    addObserver("backgroundShow");
+  } else if (nextTest.updateNotShowing) {
+    addObserver("updateNotShowing");
+  } else {
+    doOnPopupEvent("popupshowing", function () {
+      info("[Test #" + gTestIndex + "] popup showing");
+    });
+    doOnPopupEvent("popupshown", function () {
+      info("[Test #" + gTestIndex + "] popup shown");
+      nextTest.onShown(this);
+    });
+  
+    doOnPopupEvent("popuphidden", function () {
+      info("[Test #" + gTestIndex + "] popup hidden");
+      nextTest.onHidden(this);
+  
+      goNext();
+    });
+    info("[Test #" + gTestIndex + "] added listeners; panel state: " + PopupNotifications.isPanelOpen);
+  }
+
+  info("[Test #" + gTestIndex + "] running test");
+  nextTest.run();
+}
+
+function doOnPopupEvent(eventName, callback) {
+  gActiveListeners[eventName] = function (event) {
+    if (event.target != PopupNotifications.panel)
+      return;
+    PopupNotifications.panel.removeEventListener(eventName, gActiveListeners[eventName], false);
+    delete gActiveListeners[eventName];
+
+    callback.call(PopupNotifications.panel);
+  }
+  PopupNotifications.panel.addEventListener(eventName, gActiveListeners[eventName], false);
+}
+
+var gTestIndex = 0;
+var gNewTab;
+
+function basicNotification() {
+  var self = this;
+  this.browser = gBrowser.selectedBrowser;
+  this.id = "test-notification";
+  this.message = "This is popup notification " + this.id + " from test " + gTestIndex;
+  this.anchorID = null;
+  this.mainAction = {
+    label: "Main Action",
+    accessKey: "M",
+    callback: function () {
+      self.mainActionClicked = true;
+    }
+  };
+  this.secondaryActions = [
+    {
+      label: "Secondary Action",
+      accessKey: "S",
+      callback: function () {
+        self.secondaryActionClicked = true;
+      }
+    }
+  ];
+}
+
+var wrongBrowserNotificationObject = new basicNotification();
+var wrongBrowserNotification;
+
+var tests = [
+  { // Test #0
+    run: function () {
+      this.notifyObj = new basicNotification(),
+      showNotification(this.notifyObj);
+    },
+    onShown: function (popup) {
+      checkPopup(popup, this.notifyObj);
+      triggerMainCommand(popup);
+    },
+    onHidden: function (popup) {
+      ok(this.notifyObj.mainActionClicked, "mainAction was clicked");
+    }
+  },
+  { // Test #1
+    run: function () {
+      this.notifyObj = new basicNotification(),
+      showNotification(this.notifyObj);
+    },
+    onShown: function (popup) {
+      checkPopup(popup, this.notifyObj);
+      triggerSecondaryCommand(popup, 0);
+    },
+    onHidden: function (popup) {
+      ok(this.notifyObj.secondaryActionClicked, "secondaryAction was clicked");
+    }
+  },
+  { // Test #2
+    run: function () {
+      this.notifyObj = new basicNotification(),
+      this.notification = showNotification(this.notifyObj);
+    },
+    onShown: function (popup) {
+      checkPopup(popup, this.notifyObj);
+      dismissNotification(popup);
+    },
+    onHidden: function (popup) {
+      this.notification.remove();
+    }
+  },
+  // test opening a notification for a background browser
+  { // Test #3
+    run: function () {
+      gNewTab = gBrowser.addTab("about:blank");
+      isnot(gBrowser.selectedTab, gNewTab, "new tab isn't selected");
+      wrongBrowserNotificationObject.browser = gBrowser.getBrowserForTab(gNewTab);
+      wrongBrowserNotification = showNotification(wrongBrowserNotificationObject);
+    },
+    backgroundShow: function () {
+      is(PopupNotifications.isPanelOpen, false, "panel isn't open");
+      ok(!wrongBrowserNotificationObject.mainActionClicked, "main action wasn't clicked");
+      ok(!wrongBrowserNotificationObject.secondaryActionClicked, "secondary action wasn't clicked");
+    }
+  },
+  // now select that browser and test to see that the notification appeared
+  { // Test #4
+    run: function () {
+      this.oldSelectedTab = gBrowser.selectedTab;
+      gBrowser.selectedTab = gNewTab;
+    },
+    onShown: function (popup) {
+      checkPopup(popup, wrongBrowserNotificationObject);
+      is(PopupNotifications.isPanelOpen, true, "isPanelOpen getter doesn't lie");
+
+      // switch back to the old browser
+      gBrowser.selectedTab = this.oldSelectedTab;
+
+    },
+    onHidden: function (popup) {
+      // actually remove the notification to prevent it from reappearing
+      wrongBrowserNotification.remove();
+      wrongBrowserNotification = null;
+    }
+  },
+  // test that the removed notification isn't shown on browser re-select
+  { // Test #5
+    run: function () {
+      gBrowser.selectedTab = gNewTab;
+    },
+    updateNotShowing: function () {
+      is(PopupNotifications.isPanelOpen, false, "panel isn't open");
+      gBrowser.removeTab(gNewTab);
+    }
+  },
+  // Test that two notifications with the same ID result in a single displayed
+  // notification.
+  { // Test #6
+    run: function () {
+      this.notifyObj = new basicNotification(),
+      // Show the same notification twice
+      this.notification1 = showNotification(this.notifyObj);
+      this.notification2 = showNotification(this.notifyObj);
+    },
+    onShown: function (popup) {
+      checkPopup(popup, this.notifyObj);
+      dismissNotification(popup);
+    },
+    onHidden: function (popup) {
+    }
+  },
+  // Test that two notifications with different IDs are displayed
+  { // Test #7
+    run: function () {
+      this.testNotif1 = new basicNotification();
+      this.testNotif1.message += " 1";
+      showNotification(this.testNotif1);
+      this.testNotif2 = new basicNotification();
+      this.testNotif2.message += " 2";
+      this.testNotif2.id = "test-notification-2";
+      showNotification(this.testNotif2);
+    },
+    onShown: function (popup) {
+      is(popup.childNodes.length, 2, "two notifications are shown");
+      // Trigger the main command for the first notification, and the secondary
+      // for the second. Need to do mainCommand first since the secondaryCommand
+      // triggering is async.
+      triggerMainCommand(popup);
+      is(popup.childNodes.length, 1, "only one notification left");
+      triggerSecondaryCommand(popup, 0);
+    },
+    onHidden: function (popup) {
+      ok(this.testNotif1.mainActionClicked, "main action #1 was clicked");
+      ok(!this.testNotif1.secondaryActionClicked, "secondary action #1 wasn't clicked");
+
+      ok(!this.testNotif2.mainActionClicked, "main action #2 wasn't clicked");
+      ok(this.testNotif2.secondaryActionClicked, "secondary action #2 was clicked");
+    }
+  },
+  // Test notification without mainAction
+  { // Test #8
+    run: function () {
+      this.notifyObj = new basicNotification(),
+      this.notifyObj.mainAction = null;
+      showNotification(this.notifyObj);
+    },
+    onShown: function (popup) {
+      checkPopup(popup, this.notifyObj);
+      dismissNotification(popup);
+    },
+    onHidden: function (popup) {
+    }
+  },
+  // Test two notifications with different anchors
+  { // Test #9
+    run: function () {
+      this.notifyObj = new basicNotification(),
+      this.firstNotification = showNotification(this.notifyObj);
+      this.notifyObj2 = new basicNotification();
+      this.notifyObj2.id += "-2";
+      this.notifyObj2.anchorID = "urlbar";
+      // Second showNotification() overrides the first
+      this.secondNotification = showNotification(this.notifyObj2);
+    },
+    onShown: function (popup) {
+      // This also checks that only one element is shown.
+      checkPopup(popup, this.notifyObj2);
+      dismissNotification(popup);
+    },
+    onHidden: function (popup) {
+      // Remove the first notification
+      this.firstNotification.remove();
+    }
+  },
+];
+
+function showNotification(notifyObj) {
+  return PopupNotifications.show(notifyObj.browser,
+                                 notifyObj.id,
+                                 notifyObj.message,
+                                 notifyObj.anchorID,
+                                 notifyObj.mainAction,
+                                 notifyObj.secondaryActions);
+}
+
+function checkPopup(popup, notificationObj) {
+  info("[Test #" + gTestIndex + "] checking popup");
+  let notifications = popup.childNodes;
+
+  is(notifications.length, 1, "only one notification displayed");
+  let notification = notifications[0];
+  is(notification.getAttribute("label"), notificationObj.message, "message matches");
+  is(notification.id, notificationObj.id, "id matches");
+  if (notificationObj.mainAction) {
+    is(notification.getAttribute("buttonlabel"), notificationObj.mainAction.label, "main action label matches");
+    is(notification.getAttribute("buttonaccesskey"), notificationObj.mainAction.accessKey, "main action accesskey matches");
+  }
+  let actualSecondaryActions = notification.childNodes;
+  let secondaryActions = notificationObj.secondaryActions || [];
+  is(actualSecondaryActions.length, secondaryActions.length, actualSecondaryActions.length + " secondary actions");
+  secondaryActions.forEach(function (a, i) {
+    is(actualSecondaryActions[i].getAttribute("label"), a.label, "label for secondary action " + i + " matches");
+    is(actualSecondaryActions[i].getAttribute("accesskey"), a.accessKey, "accessKey for secondary action " + i + " matches");
+  });
+}
+
+function triggerMainCommand(popup) {
+  info("[Test #" + gTestIndex + "] triggering main command");
+  let notifications = popup.childNodes;
+  ok(notifications.length > 0, "at least one notification displayed");
+  let notification = notifications[0];
+
+  // 20, 10 so that the inner button is hit
+  EventUtils.synthesizeMouse(notification.button, 20, 10, {});
+}
+
+function triggerSecondaryCommand(popup, index) {
+  info("[Test #" + gTestIndex + "] triggering secondary command");
+  let notifications = popup.childNodes;
+  ok(notifications.length > 0, "at least one notification displayed");
+  let notification = notifications[0];
+
+  notification.button.focus();
+
+  popup.addEventListener("popupshown", function () {
+    popup.removeEventListener("popupshown", arguments.callee, false);
+
+    // Press down until the desired command is selected
+    for (let i = 0; i <= index; i++)
+      EventUtils.synthesizeKey("VK_DOWN", {});
+
+    // Activate
+    EventUtils.synthesizeKey("VK_ENTER", {});
+  }, false);
+
+  // One down event to open the popup
+  EventUtils.synthesizeKey("VK_DOWN", { altKey: (navigator.platform.indexOf("Mac") == -1) });
+}
+
+function dismissNotification(popup) {
+  info("[Test #" + gTestIndex + "] dismissing notification");
+  executeSoon(function () {
+    EventUtils.synthesizeKey("VK_ESCAPE", {});
+  });
+}
--- a/browser/base/content/urlbarBindings.xml
+++ b/browser/base/content/urlbarBindings.xml
@@ -33,17 +33,19 @@
 # use your version of this file under the terms of the MPL, indicate your
 # decision by deleting the provisions above and replace them with the notice
 # and other provisions required by the GPL or the LGPL. If you do not delete
 # the provisions above, a recipient may use your version of this file under
 # the terms of any one of the MPL, the GPL or the LGPL.
 #
 # ***** END LICENSE BLOCK *****
 
-<bindings id="urlbarBindings" xmlns="http://www.mozilla.org/xbl">
+<bindings id="urlbarBindings" xmlns="http://www.mozilla.org/xbl"
+          xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+          xmlns:xbl="http://www.mozilla.org/xbl">
 
   <binding id="urlbar" extends="chrome://global/content/bindings/autocomplete.xml#autocomplete">
     <implementation implements="nsIObserver, nsIDOMEventListener">
       <constructor><![CDATA[
         this._prefs = Components.classes["@mozilla.org/preferences-service;1"]
                                 .getService(Components.interfaces.nsIPrefService)
                                 .getBranch("browser.urlbar.")
                                 .QueryInterface(Components.interfaces.nsIPrefBranch2);
@@ -674,10 +676,9 @@
             }
             return label;
           ]]>
         </body>
       </method>
 
     </implementation>
   </binding>
-
 </bindings>
--- a/browser/base/content/web-panels.xul
+++ b/browser/base/content/web-panels.xul
@@ -75,24 +75,24 @@
              oncommand="getPanelBrowser().webNavigation.goForward();"
              disabled="true"/>
     <command id="Browser:Stop" oncommand="PanelBrowserStop();"/>
     <command id="Browser:Reload" oncommand="PanelBrowserReload();"/>
   </commandset>
 
   <popupset id="mainPopupSet">
     <tooltip id="aHTMLTooltip" onpopupshowing="return FillInHTMLTooltip(document.tooltipNode);"/>
-    <popup id="contentAreaContextMenu"
-           onpopupshowing="if (event.target != this)
-                             return true;
-                           gContextMenu = new nsContextMenu(this, getPanelBrowser());
-                           return gContextMenu.shouldDisplay;"
-           onpopuphiding="if (event.target == this)
-                            gContextMenu = null;">
+    <menupopup id="contentAreaContextMenu"
+               onpopupshowing="if (event.target != this)
+                                 return true;
+                               gContextMenu = new nsContextMenu(this, getPanelBrowser());
+                               return gContextMenu.shouldDisplay;"
+               onpopuphiding="if (event.target == this)
+                                gContextMenu = null;">
 #include browser-context.inc
-    </popup>
+    </menupopup>
   </popupset>
 
   <commandset id="editMenuCommands"/> 
   <browser id="web-panels-browser" persist="cachedurl" type="content" flex="1"
            context="contentAreaContextMenu" tooltip="aHTMLTooltip"
            onclick="return window.parent.contentAreaClick(event, true);"/>
 </page>
--- a/browser/components/nsBrowserGlue.js
+++ b/browser/components/nsBrowserGlue.js
@@ -1245,133 +1245,102 @@ BrowserGlue.prototype = {
 }
 
 function GeolocationPrompt() {}
 
 GeolocationPrompt.prototype = {
   classID:          Components.ID("{C6E8C44D-9F39-4AF7-BCC0-76E38A8310F5}"),
 
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIGeolocationPrompt]),
- 
+
   prompt: function GP_prompt(request) {
-    var result = Services.perms.testExactPermission(request.requestingURI, "geo");
+    var requestingURI = request.requestingURI;
+
+    // Ignore requests from non-nsIStandardURLs
+    if (!(requestingURI instanceof Ci.nsIStandardURL))
+      return;
+
+    var result = Services.perms.testExactPermission(requestingURI, "geo");
 
     if (result == Ci.nsIPermissionManager.ALLOW_ACTION) {
       request.allow();
       return;
     }
     
     if (result == Ci.nsIPermissionManager.DENY_ACTION) {
       request.cancel();
       return;
     }
 
-    function setPagePermission(uri, allow) {
-      if (allow == true)
-        Services.perms.add(uri, "geo", Ci.nsIPermissionManager.ALLOW_ACTION);
-      else
-        Services.perms.add(uri, "geo", Ci.nsIPermissionManager.DENY_ACTION);
-    }
-
     function getChromeWindow(aWindow) {
       var chromeWin = aWindow 
         .QueryInterface(Ci.nsIInterfaceRequestor)
         .getInterface(Ci.nsIWebNavigation)
         .QueryInterface(Ci.nsIDocShellTreeItem)
         .rootTreeItem
         .QueryInterface(Ci.nsIInterfaceRequestor)
         .getInterface(Ci.nsIDOMWindow)
         .QueryInterface(Ci.nsIDOMChromeWindow);
       return chromeWin;
     }
 
-    var requestingWindow = request.requestingWindow.top;
-    var chromeWindowObject = getChromeWindow(requestingWindow).wrappedJSObject;
-    var tabbrowser = chromeWindowObject.gBrowser;
-    var browser = tabbrowser.getBrowserForDocument(requestingWindow.document);
-    var notificationBox = tabbrowser.getNotificationBox(browser);
+    var browserBundle = Services.strings.createBundle("chrome://browser/locale/browser.properties");
 
-    var notification = notificationBox.getNotificationWithValue("geolocation");
-    if (!notification) {
-      var browserBundle = Services.strings.createBundle("chrome://browser/locale/browser.properties");
+    var mainAction = {
+      label: browserBundle.GetStringFromName("geolocation.shareLocation"),
+      accessKey: browserBundle.GetStringFromName("geolocation.shareLocation.accesskey"),
+      callback: function(notification) {
+        request.allow();
+      },
+    };
 
-      var buttons = [{
-              label: browserBundle.GetStringFromName("geolocation.shareLocation"),
-              accessKey: browserBundle.GetStringFromName("geolocation.shareLocation.accesskey"),
-              callback: function(notification) {
-                  var elements = notification.getElementsByClassName("rememberChoice");
-                  if (elements.length && elements[0].checked)
-                      setPagePermission(request.requestingURI, true);
-                  request.allow(); 
-              },
-          },
-          {
-              label: browserBundle.GetStringFromName("geolocation.dontShareLocation"),
-              accessKey: browserBundle.GetStringFromName("geolocation.dontShareLocation.accesskey"),
-              callback: function(notification) {
-                  var elements = notification.getElementsByClassName("rememberChoice");
-                  if (elements.length && elements[0].checked)
-                      setPagePermission(request.requestingURI, false);
-                  request.cancel();
-              },
-          }];
-      
-      var message;
+    // XXX Bug 573536
+    // browserBundle.GetStringFromName("geolocation.learnMore")
+    //var formatter = Cc["@mozilla.org/toolkit/URLFormatterService;1"].getService(Ci.nsIURLFormatter);
+    //link.href = formatter.formatURLPref("browser.geolocation.warning.infoURL");
+
+    var message;
+    var secondaryActions = [];
 
-      // Different message/info if it is a local file
-      if (request.requestingURI.schemeIs("file")) {
-        message = browserBundle.formatStringFromName("geolocation.fileWantsToKnow",
-                                                     [request.requestingURI.path], 1);
-      } else {
-        message = browserBundle.formatStringFromName("geolocation.siteWantsToKnow",
-                                                     [request.requestingURI.host], 1);
-      }
+    // Different message/options if it is a local file
+    if (requestingURI.schemeIs("file")) {
+      message = browserBundle.formatStringFromName("geolocation.fileWantsToKnow",
+                                                   [request.requestingURI.path], 1);
+    } else {
+      message = browserBundle.formatStringFromName("geolocation.siteWantsToKnow",
+                                                   [requestingURI.host], 1);
 
-      var newBar = notificationBox.appendNotification(message,
-                                                      "geolocation",
-                                                      "chrome://browser/skin/Geo.png",
-                                                      notificationBox.PRIORITY_INFO_HIGH,
-                                                      buttons);
-
-      // For whatever reason, if we do this immediately
-      // (eg, without the setTimeout), the "link"
-      // element does not show up in the notification
-      // bar.
-      function geolocation_hacks_to_notification () {
-
-        // Never show a remember checkbox inside the private browsing mode
-        var inPrivateBrowsing = Cc["@mozilla.org/privatebrowsing;1"].
-                                getService(Ci.nsIPrivateBrowsingService).
-                                privateBrowsingEnabled;
-
-        // don't show "Remember for this site" checkbox for file:
-        var host;
-        try {
-            host = request.requestingURI.host;
-        } catch (ex) {}
+      // Don't offer to "always/never share" in PB mode
+      var inPrivateBrowsing = Cc["@mozilla.org/privatebrowsing;1"].
+                              getService(Ci.nsIPrivateBrowsingService).
+                              privateBrowsingEnabled;
 
-        if (!inPrivateBrowsing && host) {
-          var checkbox = newBar.ownerDocument.createElementNS(XULNS, "checkbox");
-          checkbox.className = "rememberChoice";
-          checkbox.setAttribute("label", browserBundle.GetStringFromName("geolocation.remember"));
-          checkbox.setAttribute("accesskey", browserBundle.GetStringFromName("geolocation.remember.accesskey"));
-          newBar.appendChild(checkbox);
-        }
+      if (!inPrivateBrowsing) {
+        secondaryActions.push({
+          label: browserBundle.GetStringFromName("geolocation.alwaysShare"),
+          accessKey: browserBundle.GetStringFromName("geolocation.alwaysShare.accesskey"),
+          callback: function () {
+            Services.perms.add(requestingURI, "geo", Ci.nsIPermissionManager.ALLOW_ACTION);
+            request.allow();
+          }
+        });
+        secondaryActions.push({
+          label: browserBundle.GetStringFromName("geolocation.neverShare"),
+          accessKey: browserBundle.GetStringFromName("geolocation.neverShare.accesskey"),
+          callback: function () {
+            Services.perms.add(requestingURI, "geo", Ci.nsIPermissionManager.DENY_ACTION);
+            request.cancel();
+          }
+        });
+      }
+    }
 
-        var link = newBar.ownerDocument.createElementNS(XULNS, "label");
-        link.className = "text-link";
-        link.setAttribute("value", browserBundle.GetStringFromName("geolocation.learnMore"));
-
-        var formatter = Cc["@mozilla.org/toolkit/URLFormatterService;1"].getService(Ci.nsIURLFormatter);
-        link.href = formatter.formatURLPref("browser.geolocation.warning.infoURL");
+    var requestingWindow = request.requestingWindow.top;
+    var chromeWin = getChromeWindow(requestingWindow).wrappedJSObject;
+    var browser = chromeWin.gBrowser.getBrowserForDocument(requestingWindow.document);
 
-        var description = newBar.ownerDocument.getAnonymousElementByAttribute(newBar, "anonid", "messageText");
-        description.appendChild(link);
-      };
-
-      chromeWindowObject.setTimeout(geolocation_hacks_to_notification, 0);
-
-    }
+    chromeWin.PopupNotifications.show(browser, "geolocation", message, "geo-notification-icon",
+                                      mainAction, secondaryActions);
   },
 };
 
 var components = [BrowserGlue, GeolocationPrompt];
 var NSGetFactory = XPCOMUtils.generateNSGetFactory(components);
--- a/browser/components/places/content/bookmarksPanel.xul
+++ b/browser/components/places/content/bookmarksPanel.xul
@@ -54,17 +54,17 @@
 
   <script type="application/javascript" 
           src="chrome://browser/content/bookmarks/sidebarUtils.js"/>
   <script type="application/javascript" 
           src="chrome://browser/content/bookmarks/bookmarksPanel.js"/>
 
   <commandset id="placesCommands"/>
   <commandset id="editMenuCommands"/>
-  <popup id="placesContext"/>
+  <menupopup id="placesContext"/>
 
   <!-- Bookmarks and history tooltip -->
   <tooltip id="bhTooltip"/>
 
   <hbox id="sidebar-search-container" align="center">
     <label id="sidebar-search-label"
            value="&search.label;" accesskey="&search.accesskey;" control="search-box"/>
     <textbox id="search-box" flex="1" type="search" class="compact"
--- a/browser/components/places/content/history-panel.xul
+++ b/browser/components/places/content/history-panel.xul
@@ -70,17 +70,17 @@
 
   <keyset id="editMenuKeys">
 #ifdef XP_MACOSX
     <key id="key_delete2" keycode="VK_BACK" command="cmd_delete"/>
 #endif
   </keyset>
 
   <!-- required to overlay the context menu -->
-  <popup id="placesContext" />
+  <menupopup id="placesContext"/>
 
   <!-- Bookmarks and history tooltip -->
   <tooltip id="bhTooltip"/>
 
   <hbox id="sidebar-search-container" align="center">
     <label id="sidebar-search-label"
            value="&find.label;" accesskey="&find.accesskey;" 
            control="search-box"/>
--- a/browser/components/places/content/places.xul
+++ b/browser/components/places/content/places.xul
@@ -174,20 +174,20 @@
 
   <keyset id="editMenuKeys">
 #ifdef XP_MACOSX
     <key id="key_delete2" keycode="VK_BACK" command="cmd_delete"/>
 #endif
   </keyset>
 
   <popupset id="placesPopupset">
-    <popup id="placesContext"/>
-    <popup id="placesColumnsContext"
-           onpopupshowing="ViewMenu.fillWithColumns(event, null, null, 'checkbox', null);"
-           oncommand="ViewMenu.showHideColumn(event.target); event.stopPropagation();"/>
+    <menupopup id="placesContext"/>
+    <menupopup id="placesColumnsContext"
+               onpopupshowing="ViewMenu.fillWithColumns(event, null, null, 'checkbox', null);"
+               oncommand="ViewMenu.showHideColumn(event.target); event.stopPropagation();"/>
   </popupset>
 
   <toolbox id="placesToolbox">
     <toolbar class="chromeclass-toolbar" id="placesToolbar" align="center">
       <toolbarbutton id="back-button" class="toolbarbutton-1 chromeclass-toolbar-additional"
                      command="OrganizerCommand:Back"
                      tooltiptext="&backButton.tooltip;"
                      disabled="true"/>
--- a/browser/components/places/content/placesOverlay.xul
+++ b/browser/components/places/content/placesOverlay.xul
@@ -118,20 +118,20 @@
     <command id="placesCmd_copy"
              oncommand="goDoPlacesCommand('placesCmd_copy');"/>
     <command id="placesCmd_paste"
              oncommand="goDoPlacesCommand('placesCmd_paste');"/>
     <command id="placesCmd_delete"
              oncommand="goDoPlacesCommand('placesCmd_delete');"/>
   </commandset>
 
-  <popup id="placesContext"
-         onpopupshowing="this._view = PlacesUIUtils.getViewForNode(document.popupNode);
-                         return this._view.buildContextMenu(this);"
-         onpopuphiding="this._view.destroyContextMenu();">
+  <menupopup id="placesContext"
+             onpopupshowing="this._view = PlacesUIUtils.getViewForNode(document.popupNode);
+                             return this._view.buildContextMenu(this);"
+             onpopuphiding="this._view.destroyContextMenu();">
     <menuitem id="placesContext_open"
               command="placesCmd_open"
               label="&cmd.open.label;"
               accesskey="&cmd.open.accesskey;"
               default="true"
               selectiontype="single"
               selection="link"/>
     <menuitem id="placesContext_open:newwindow"
@@ -253,11 +253,11 @@
               selection="folder"/>
     <menuseparator id="placesContext_sortSeparator"/>
     <menuitem id="placesContext_show:info"
               command="placesCmd_show:info"
               label="&cmd.properties.label;" 
               accesskey="&cmd.properties.accesskey;"
               selection="bookmark|folder|query"
               forcehideselection="livemarkChild"/>
-  </popup>
+  </menupopup>
 
 </overlay>
--- a/browser/components/places/content/treeView.js
+++ b/browser/components/places/content/treeView.js
@@ -782,16 +782,20 @@ PlacesTreeView.prototype = {
   },
 
   _invalidateCellValue: function PTV__invalidateCellValue(aNode,
                                                           aColumnType) {
     NS_ASSERT(this._result, "Got a notification but have no result!");
     if (!this._tree || !this._result)
       return;
 
+    // Nothing to do for the root node.
+    if (aNode == this._rootNode)
+      return;
+
     let row = this._getRowForNode(aNode);
     if (row == -1)
       return;
 
     let column = this._findColumnByType(aColumnType);
     if (column && !column.element.hidden)
       this._tree.invalidateCell(row, column);
 
--- a/browser/components/places/tests/chrome/Makefile.in
+++ b/browser/components/places/tests/chrome/Makefile.in
@@ -45,12 +45,13 @@ include $(topsrcdir)/config/rules.mk
 
 _CHROME_TEST_FILES = \
 	test_treeview_date.xul \
 	test_bug485100-change-case-loses-tag.xul \
 	test_bug427633_no_newfolder_if_noip.xul \
 	test_0_multiple_left_pane.xul \
 	test_0_bug510634.xul \
 	test_bug549192.xul \
+	test_bug549491.xul \
 	$(NULL)
 
 libs:: $(_CHROME_TEST_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/chrome/$(relativesrcdir)
--- a/browser/components/places/tests/chrome/test_bug549192.xul
+++ b/browser/components/places/tests/chrome/test_bug549192.xul
@@ -40,23 +40,25 @@
      * https://bugzilla.mozilla.org/show_bug.cgi?id=549192
      *
      * Ensures that history views are updated after deleting entries.
      */
 
     SimpleTest.waitForExplicitFinish();
 
     function runTest() {
+      // The mochitest page is added to history.
+      waitForClearHistory(continue_test);
+    }
+
+    function continue_test() {
       const Cc = Components.classes;
       const Ci = Components.interfaces;
       Components.utils.import("resource://gre/modules/Services.jsm");
 
-      // Cleanup.
-      PlacesUtils.bhistory.removeAllPages();
-
       // Add some visits.
       let vtime = Date.now() * 1000;
       const ttype = PlacesUtils.history.TRANSITION_TYPED;
       PlacesUtils.history
                  .addVisit(Services.io.newURI("http://example.tld/", null, null),
                            vtime, null, ttype, false, 0);
       PlacesUtils.history
                  .addVisit(Services.io.newURI("http://example2.tld/", null, null),
@@ -71,28 +73,48 @@
       let queryURI = PlacesUtils.history.queriesToQueryString([query], 1, opts);
 
       // Setup the places tree contents.
       var tree = document.getElementById("tree");
       tree.place = queryURI;
 
       // loop through the rows and check formatting
       let treeView = tree.view;
+      for (let i = 0; i < rc; i++) {
+        selection.select(rc);
+        let node = tree.selectedNode;
+        ok(true, "found " + node.title);
+      }
       let rc = treeView.rowCount;
-      ok(rc == 3, "Rows found.");
+      is(rc, 3, "Rows found.");
       let selection = treeView.selection;
       for (let i = 0; i < rc; i++) {
         selection.select(0);
         let node = tree.selectedNode;
         tree.controller.remove("Removing page");
         ok(treeView.treeIndexForNode(node) == Ci.nsINavHistoryResultTreeViewer.INDEX_INVISIBLE,
            node.uri + " removed.");
         ok(treeView.rowCount == rc - i - 1, "Rows count decreased");
       }
 
       // Cleanup.
-      PlacesUtils.bhistory.removeAllPages();
+      waitForClearHistory(SimpleTest.finish);
+    }
 
-      SimpleTest.finish();
-    }
+    /**
+     * Clears history invoking callback when done.
+     */
+    function waitForClearHistory(aCallback) {
+      const TOPIC_EXPIRATION_FINISHED = "places-expiration-finished";
+      let observer = {
+        observe: function(aSubject, aTopic, aData) {
+          Services.obs.removeObserver(this, TOPIC_EXPIRATION_FINISHED);
+          aCallback();
+        }
+      };
+      Services.obs.addObserver(observer, TOPIC_EXPIRATION_FINISHED, false);
+      let hs = Cc["@mozilla.org/browser/nav-history-service;1"].
+               getService(Ci.nsINavHistoryService);
+      hs.QueryInterface(Ci.nsIBrowserHistory).removeAllPages();
+   }
 
   ]]></script>
 </window>
new file mode 100644
--- /dev/null
+++ b/browser/components/places/tests/chrome/test_bug549491.xul
@@ -0,0 +1,100 @@
+<?xml version="1.0"?>
+
+<!--
+    Any copyright is dedicated to the Public Domain.
+    http://creativecommons.org/licenses/publicdomain/
+   -->
+
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
+                 type="text/css"?>
+
+<?xml-stylesheet href="chrome://browser/content/places/places.css"?>
+<?xml-stylesheet href="chrome://browser/skin/places/places.css"?>
+<?xul-overlay href="chrome://browser/content/places/placesOverlay.xul"?>
+
+<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+        title="549491: 'The root node is never visible' exception when details of the root node are modified "
+        onload="runTest();">
+
+  <script type="application/javascript"
+          src="chrome://mochikit/content/MochiKit/packed.js" />
+  <script type="application/javascript"
+          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
+
+  <body xmlns="http://www.w3.org/1999/xhtml" />
+
+  <tree id="tree"
+        type="places"
+        flatList="true"
+        flex="1">
+    <treecols>
+      <treecol label="Title" id="title" anonid="title" primary="true" ordinal="1" flex="1"/>
+      <splitter class="tree-splitter"/>
+      <treecol label="Date" anonid="date" flex="1"/>
+    </treecols>
+    <treechildren flex="1"/>
+  </tree>
+
+  <script type="application/javascript"><![CDATA[
+    /**
+     * Bug 549491
+     * https://bugzilla.mozilla.org/show_bug.cgi?id=549491
+     *
+     * Ensures that changing the details of places tree's root-node doesn't
+     * throw.
+     */
+
+    SimpleTest.waitForExplicitFinish();
+
+    function runTest() {
+      // The mochitest page is added to history.
+      waitForClearHistory(continue_test);
+    }
+
+    function continue_test() {
+      const Cc = Components.classes;
+      const Ci = Components.interfaces;
+      Components.utils.import("resource://gre/modules/Services.jsm");
+      PlacesUtils.history
+                 .addVisit(Services.io.newURI("http://example.tld/", null, null),
+                           Date.now() * 1000, null, PlacesUtils.history.TRANSITION_TYPED, false, 0);
+
+      // Make a history query.
+      let query = PlacesUtils.history.getNewQuery();
+      let opts = PlacesUtils.history.getNewQueryOptions();
+      let queryURI = PlacesUtils.history.queriesToQueryString([query], 1, opts);
+
+      // Setup the places tree contents.
+      let tree = document.getElementById("tree");
+      tree.place = queryURI;
+
+      let rootNode = tree.result.root;
+      let obs = tree.view.QueryInterface(Ci.nsINavHistoryResultObserver);
+      obs.nodeHistoryDetailsChanged(rootNode, rootNode.time, rootNode.accessCount);
+      obs.nodeTitleChanged(rootNode, rootNode.title);
+      ok(true, "No exceptions thrown");
+
+      // Cleanup.
+      waitForClearHistory(SimpleTest.finish);
+    }
+
+    /**
+     * Clears history invoking callback when done.
+     */
+    function waitForClearHistory(aCallback) {
+      const TOPIC_EXPIRATION_FINISHED = "places-expiration-finished";
+      let observer = {
+        observe: function(aSubject, aTopic, aData) {
+          Services.obs.removeObserver(this, TOPIC_EXPIRATION_FINISHED);
+          aCallback();
+        }
+      };
+      Services.obs.addObserver(observer, TOPIC_EXPIRATION_FINISHED, false);
+      let hs = Cc["@mozilla.org/browser/nav-history-service;1"].
+               getService(Ci.nsINavHistoryService);
+      hs.QueryInterface(Ci.nsIBrowserHistory).removeAllPages();
+   }
+
+  ]]></script>
+</window>
--- a/browser/components/places/tests/chrome/test_treeview_date.xul
+++ b/browser/components/places/tests/chrome/test_treeview_date.xul
@@ -81,16 +81,21 @@
      * https://bugzilla.mozilla.org/show_bug.cgi?id=435322
      *
      * Ensures that date in places treeviews is correctly formatted.
      */
 
     SimpleTest.waitForExplicitFinish();
 
     function runTest() {
+      // The mochitest page is added to history.
+      waitForClearHistory(continue_test);
+    }
+
+    function continue_test() {
       const Cc = Components.classes;
       const Ci = Components.interfaces;
 
       var hs = Cc["@mozilla.org/browser/nav-history-service;1"].
                getService(Ci.nsINavHistoryService);
       var bh = hs.QueryInterface(Ci.nsIBrowserHistory);
       var bs = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].
                getService(Ci.nsINavBookmarksService);
@@ -104,19 +109,16 @@
       }
 
       var midnight = new Date();
       midnight.setHours(0);
       midnight.setMinutes(0);
       midnight.setSeconds(0);
       midnight.setMilliseconds(0);
 
-      // Cleanup.
-      bh.removeAllPages();
-
       // Add a visit 1ms before midnight.
       hs.addVisit(uri("http://before.midnight.com/"),
                   (midnight.getTime() - 1) * 1000,
                   null, hs.TRANSITION_TYPED, false, 0);
 
       // Add a visit at midnight.
       hs.addVisit(uri("http://at.midnight.com/"),
                   (midnight.getTime()) * 1000,
@@ -191,16 +193,31 @@
             case "visitCount":
               is(text, 1, "Visit count is correct");
               break;         
           }
         }
       }
       // Cleanup.
       bs.removeItem(itemId);
-      bh.removeAllPages();
+      waitForClearHistory(SimpleTest.finish);
+    }
 
-      SimpleTest.finish();
-    }
+    /**
+     * Clears history invoking callback when done.
+     */
+    function waitForClearHistory(aCallback) {
+      const TOPIC_EXPIRATION_FINISHED = "places-expiration-finished";
+      let observer = {
+        observe: function(aSubject, aTopic, aData) {
+          Services.obs.removeObserver(this, TOPIC_EXPIRATION_FINISHED);
+          aCallback();
+        }
+      };
+      Services.obs.addObserver(observer, TOPIC_EXPIRATION_FINISHED, false);
+      let hs = Cc["@mozilla.org/browser/nav-history-service;1"].
+               getService(Ci.nsINavHistoryService);
+      hs.QueryInterface(Ci.nsIBrowserHistory).removeAllPages();
+   }
 
   ]]>
   </script>
 </window>
--- a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_geoprompt.js
+++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_geoprompt.js
@@ -46,47 +46,38 @@ function test() {
   const testPageURL = "http://mochi.test:8888/browser/" +
     "browser/components/privatebrowsing/test/browser/browser_privatebrowsing_geoprompt_page.html";
   waitForExplicitFinish();
 
   gBrowser.selectedTab = gBrowser.addTab();
   gBrowser.selectedBrowser.addEventListener("load", function () {
     gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true);
 
-    setTimeout(function() {
-      // Make sure the notification is correctly displayed with a remember control
-      let notificationBox = gBrowser.getNotificationBox();
-      let notification = notificationBox.getNotificationWithValue("geolocation");
-      ok(notification, "Notification box should be displaying outside of private browsing mode");
-      is(notification.getElementsByClassName("rememberChoice").length, 1,
-         "The remember control must be displayed outside of private browsing mode");
-      notificationBox.currentNotification.close();
+    let notification = PopupNotifications.getNotification("geolocation");
+    ok(notification, "Notification should exist");
+    ok(notification.secondaryActions.length > 1, "Secondary actions should exist (always/never remember)");
+    notification.remove();
+
+    gBrowser.removeCurrentTab();
+
+    // enter the private browsing mode
+    pb.privateBrowsingEnabled = true;
+
+    gBrowser.selectedTab = gBrowser.addTab();
+    gBrowser.selectedBrowser.addEventListener("load", function () {
+      gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true);
+
+      // Make sure the notification is correctly displayed without a remember control
+      let notification = PopupNotifications.getNotification("geolocation");
+      ok(notification, "Notification should exist");
+      is(notification.secondaryActions.length, 0, "Secondary actions shouldn't exist (always/never remember)");
+      notification.remove();
 
       gBrowser.removeCurrentTab();
 
-      // enter the private browsing mode
-      pb.privateBrowsingEnabled = true;
-
-      gBrowser.selectedTab = gBrowser.addTab();
-      gBrowser.selectedBrowser.addEventListener("load", function () {
-        gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true);
-
-        setTimeout(function () {
-          // Make sure the notification is correctly displayed without a remember control
-          let notificationBox = gBrowser.getNotificationBox();
-          let notification = notificationBox.getNotificationWithValue("geolocation");
-          ok(notification, "Notification box should be displaying outside of private browsing mode");
-          is(notification.getElementsByClassName("rememberChoice").length, 0,
-             "The remember control must not be displayed inside of private browsing mode");
-          notificationBox.currentNotification.close();
-
-          gBrowser.removeCurrentTab();
-
-          // cleanup
-          pb.privateBrowsingEnabled = false;
-          finish();
-        }, 100); // remember control is added in a setTimeout(0) call
-      }, true);
-      content.location = testPageURL;
-    }, 100); // remember control is added in a setTimeout(0) call
+      // cleanup
+      pb.privateBrowsingEnabled = false;
+      finish();
+    }, true);
+    content.location = testPageURL;
   }, true);
   content.location = testPageURL;
 }
--- a/browser/installer/package-manifest.in
+++ b/browser/installer/package-manifest.in
@@ -141,16 +141,17 @@
 @BINPATH@/components/dom.xpt
 @BINPATH@/components/dom_base.xpt
 @BINPATH@/components/dom_canvas.xpt
 @BINPATH@/components/dom_core.xpt
 @BINPATH@/components/dom_css.xpt
 @BINPATH@/components/dom_events.xpt
 @BINPATH@/components/dom_geolocation.xpt
 @BINPATH@/components/dom_html.xpt
+@BINPATH@/components/dom_indexeddb.xpt
 @BINPATH@/components/dom_offline.xpt
 @BINPATH@/components/dom_json.xpt
 @BINPATH@/components/dom_range.xpt
 @BINPATH@/components/dom_sidebar.xpt
 @BINPATH@/components/dom_storage.xpt
 @BINPATH@/components/dom_stylesheets.xpt
 @BINPATH@/components/dom_threads.xpt
 @BINPATH@/components/dom_traversal.xpt
--- a/browser/installer/removed-files.in
+++ b/browser/installer/removed-files.in
@@ -1,10 +1,10 @@
 # Removed-files.in is processed at build time to create a list of files that
-# should be removed during an application update and by the Windows installer.
+# should be removed during an application update.
 # These files are in alphabetical order, except that files removed only on
 # certain platforms are after all of the regular files and obsolete Talkback and
 # Inspector files are at the very end.
 .autoreg
 @DLL_PREFIX@jsj@DLL_SUFFIX@
 @DLL_PREFIX@sqlite3@DLL_SUFFIX@
 @DLL_PREFIX@xpcom_compat@DLL_SUFFIX@
 @DLL_PREFIX@xpistub@DLL_SUFFIX@
--- a/browser/installer/windows/Makefile.in
+++ b/browser/installer/windows/Makefile.in
@@ -124,20 +124,16 @@ uninstaller::
 	done
 	$(INSTALL) $(addprefix $(srcdir)/,$(INSTALLER_FILES)) $(CONFIG_DIR)
 	for i in $(BRANDING_FILES_CONV); do \
 	  iconv -f UTF-8 -t UTF-16LE $(DIST)/branding/$$i | \
 	    cat $(MOZILLA_DIR)/toolkit/mozapps/installer/windows/nsis/utf16-le-bom.bin - > \
 	    $(CONFIG_DIR)/$$i; \
 	done
 	$(INSTALL) $(addprefix $(DIST)/branding/,$(BRANDING_FILES)) $(CONFIG_DIR)
-ifeq ($(CONFIG_DIR),instgen)
-	$(PERL) $(topsrcdir)/toolkit/mozapps/installer/windows/nsis/make-installremoves.pl \
-	  ../removed-files > $(CONFIG_DIR)/removed-files.log
-endif
 	$(PYTHON) $(topsrcdir)/config/Preprocessor.py -Fsubstitution $(DEFINES) $(ACDEFINES) \
 	  $(srcdir)/nsis/defines.nsi.in | iconv -f UTF-8 -t UTF-16LE | \
 	  cat $(MOZILLA_DIR)/toolkit/mozapps/installer/windows/nsis/utf16-le-bom.bin - > \
 	  $(CONFIG_DIR)/defines.nsi
 	$(PERL) $(topsrcdir)/toolkit/mozapps/installer/windows/nsis/preprocess-locale.pl \
 	  $(topsrcdir) $(call EXPAND_LOCALE_SRCDIR,browser/locales)/installer $(AB_CD) \
 	  $(CONFIG_DIR)
 
--- a/browser/installer/windows/nsis/installer.nsi
+++ b/browser/installer/windows/nsis/installer.nsi
@@ -60,20 +60,16 @@ Var AddStartMenuSC
 Var AddQuickLaunchSC
 Var AddDesktopSC
 Var PageName
 
 ; On Vista and above attempt to elevate Standard Users in addition to users that
 ; are a member of the Administrators group.
 !define NONADMIN_ELEVATE
 
-; Don't use the PreDirectoryCommon macro's code for finding a pre-existing
-; installation directory.
-!define NO_INSTDIR_PREDIRCOMMON
-
 !define AbortSurveyURL "http://www.kampyle.com/feedback_form/ff-feedback-form.php?site_code=8166124&form_id=12116&url="
 
 ; Other included files may depend upon these includes!
 ; The following includes are provided by NSIS.
 !include FileFunc.nsh
 !include LogicLib.nsh
 !include MUI.nsh
 !include WinMessages.nsh
@@ -99,17 +95,16 @@ VIAddVersionKey "OriginalFilename" "setu
 
 ; Must be inserted before other macros that use logging
 !insertmacro _LoggingCommon
 
 ; Most commonly used macros for managing shortcuts
 !insertmacro _LoggingShortcutsCommon
 
 !insertmacro AddDDEHandlerValues
-!insertmacro CanWriteToInstallDir
 !insertmacro ChangeMUIHeaderImage
 !insertmacro CheckForFilesInUse
 !insertmacro CleanUpdatesDir
 !insertmacro CopyFilesFromDir
 !insertmacro CreateRegKey
 !insertmacro FindSMProgramsDir
 !insertmacro GetPathFromString
 !insertmacro GetParent
@@ -127,16 +122,17 @@ VIAddVersionKey "OriginalFilename" "setu
 !include shared.nsh
 
 ; Helper macros for ui callbacks. Insert these after shared.nsh
 !insertmacro CheckCustomCommon
 !insertmacro InstallEndCleanupCommon
 !insertmacro InstallOnInitCommon
 !insertmacro InstallStartCleanupCommon
 !insertmacro LeaveDirectoryCommon
+!insertmacro LeaveOptionsCommon
 !insertmacro OnEndCommon
 !insertmacro PreDirectoryCommon
 
 Name "${BrandFullName}"
 OutFile "setup.exe"
 InstallDirRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${BrandFullNameInternal} (${AppVersion})" "InstallLocation"
 InstallDir "$PROGRAMFILES\${BrandFullName}\"
 ShowInstDetails nevershow
@@ -275,17 +271,16 @@ Section "-Application" APP_IDX
   DetailPrint $(STATUS_INSTALL_LANG)
   SetDetailsPrint none
 
   ${LogHeader} "Installing Localized Files"
   ${CopyFilesFromDir} "$EXEDIR\localized" "$INSTDIR" \
                       "$(ERROR_CREATE_DIRECTORY_PREFIX)" \
                       "$(ERROR_CREATE_DIRECTORY_SUFFIX)"
 
-  ${LogHeader} "Adding Additional Files"
   ; Check if QuickTime is installed and copy the nsIQTScriptablePlugin.xpt from
   ; its plugins directory into the app's components directory.
   ClearErrors
   ReadRegStr $R0 HKLM "Software\Apple Computer, Inc.\QuickTime" "InstallDir"
   ${Unless} ${Errors}
     ${GetLongPath} "$R0" $R0
     ${Unless} "$R0" == ""
       ClearErrors
@@ -480,18 +475,16 @@ Section "-InstallEndCleanup"
         Call SetAsDefaultAppUserHKCU
       ${Else}
         GetFunctionAddress $0 SetAsDefaultAppUserHKCU
         UAC::ExecCodeSegment $0
       ${EndIf}
     ${EndIf}
   ${EndUnless}
 
-  ${LogHeader} "Updating Uninstall Log With Previous Uninstall Log"
-
   ; Win7 taskbar and start menu link maintenance
   ${UpdateShortcutAppModelIDs} "$INSTDIR\${FileMainEXE}" "${AppUserModelID}"
 
   ; Refresh desktop icons
   System::Call "shell32::SHChangeNotify(i, i, i, i) v (0x08000000, 0, 0, 0)"
 
   ${InstallEndCleanupCommon}
 
@@ -716,60 +709,33 @@ Function leaveOptions
   ${EndIf}
   ${MUI_INSTALLOPTIONS_READ} $R0 "options.ini" "Field 2" "State"
   StrCmp $R0 "1" +1 +2
   StrCpy $InstallType ${INSTALLTYPE_BASIC}
   ${MUI_INSTALLOPTIONS_READ} $R0 "options.ini" "Field 3" "State"
   StrCmp $R0 "1" +1 +2
   StrCpy $InstallType ${INSTALLTYPE_CUSTOM}
 
-!ifndef NO_INSTDIR_FROM_REG
-  SetShellVarContext all      ; Set SHCTX to HKLM
-  ${GetSingleInstallPath} "Software\Mozilla\${BrandFullNameInternal}" $R9
-
-  StrCmp "$R9" "false" +1 fix_install_dir
-
-  SetShellVarContext current  ; Set SHCTX to HKCU
-  ${GetSingleInstallPath} "Software\Mozilla\${BrandFullNameInternal}" $R9
-
-  fix_install_dir:
-  StrCmp "$R9" "false" +2 +1
-  StrCpy $INSTDIR "$R9"
-!endif
+  ${LeaveOptionsCommon}
 
-  ; If the user doesn't have write access to the installation directory set
-  ; the installation directory to a subdirectory of the All Users application
-  ; directory and if the user can't write to that location set the installation
-  ; directory to a subdirectory of the users local application directory
-  ; (e.g. non-roaming).
-  ${CanWriteToInstallDir} $R8
-  ${If} "$R8" == "false"
-    SetShellVarContext all      ; Set SHCTX to All Users
-    StrCpy $INSTDIR "$APPDATA\${BrandFullName}\"
-    ${If} ${FileExists} "$INSTDIR"
-      ; Always display the long path if the path already exists.
-      ${GetLongPath} "$INSTDIR" $INSTDIR
-    ${EndIf}
-    ${CanWriteToInstallDir} $R8
-    ${If} "$R8" == "false"
-      StrCpy $INSTDIR "$LOCALAPPDATA\${BrandFullName}\"
-    ${EndIf}
+  ${If} $InstallType == ${INSTALLTYPE_BASIC}
+    Call CheckExistingInstall
   ${EndIf}
 FunctionEnd
 
 Function preDirectory
   StrCpy $PageName "Directory"
   ${PreDirectoryCommon}
 FunctionEnd
 
 Function leaveDirectory
-  ${LeaveDirectoryCommon} "$(WARN_DISK_SPACE)" "$(WARN_WRITE_ACCESS)"
-  ${If} $InstallType != ${INSTALLTYPE_CUSTOM}
+  ${If} $InstallType == ${INSTALLTYPE_BASIC}
     Call CheckExistingInstall
   ${EndIf}
+  ${LeaveDirectoryCommon} "$(WARN_DISK_SPACE)" "$(WARN_WRITE_ACCESS)"
 FunctionEnd
 
 Function preShortcuts
   StrCpy $PageName "Shortcuts"
   ${CheckCustomCommon}
   !insertmacro MUI_HEADER_TEXT "$(SHORTCUTS_PAGE_TITLE)" "$(SHORTCUTS_PAGE_SUBTITLE)"
   !insertmacro MUI_INSTALLOPTIONS_DISPLAY "shortcuts.ini"
 FunctionEnd
@@ -777,16 +743,23 @@ FunctionEnd
 Function leaveShortcuts
   ${MUI_INSTALLOPTIONS_READ} $0 "shortcuts.ini" "Settings" "State"
   ${If} $0 != 0
     Abort
   ${EndIf}
   ${MUI_INSTALLOPTIONS_READ} $AddDesktopSC "shortcuts.ini" "Field 2" "State"
   ${MUI_INSTALLOPTIONS_READ} $AddStartMenuSC "shortcuts.ini" "Field 3" "State"
   ${MUI_INSTALLOPTIONS_READ} $AddQuickLaunchSC "shortcuts.ini" "Field 4" "State"
+
+  ; If Start Menu shortcuts won't be created call CheckExistingInstall here
+  ; since leaveStartMenu will not be called.
+  ${If} $AddStartMenuSC != 1
+  ${AndIf} $InstallType == ${INSTALLTYPE_CUSTOM}
+    Call CheckExistingInstall
+  ${EndIf}
 FunctionEnd
 
 Function preStartMenu
   StrCpy $PageName "StartMenu"
   ; With the Unicode installer the path to the application's Start Menu
   ; directory relative to the Start Menu's Programs directory is written to the
   ; shortcuts log ini file and is used to set the default Start Menu directory.
   ${GetSMProgramsDirRelPath} $0
--- a/browser/installer/windows/nsis/shared.nsh
+++ b/browser/installer/windows/nsis/shared.nsh
@@ -543,17 +543,16 @@
   Push "freebl3.dll"
   Push "nssckbi.dll"
   Push "nspr4.dll"
   Push "nssdbm3.dll"
   Push "mozsqlite3.dll"
   Push "xpcom.dll"
   Push "crashreporter.exe"
   Push "updater.exe"
-  Push "xpicleanup.exe"
   Push "${FileMainEXE}"
 !macroend
 !define PushFilesToCheck "!insertmacro PushFilesToCheck"
 
 
 ; Sets this installation as the default browser by setting the registry keys
 ; under HKEY_CURRENT_USER via registry calls and using the AppAssocReg NSIS
 ; plugin for Vista and above. This is a function instead of a macro so it is
--- a/browser/locales/en-US/chrome/browser/browser.dtd
+++ b/browser/locales/en-US/chrome/browser/browser.dtd
@@ -154,16 +154,20 @@
 <!ENTITY downloadsUnix.commandkey     "y">
 <!ENTITY addons.label                 "Add-ons">
 <!ENTITY addons.accesskey             "A">
 
 <!ENTITY errorConsoleCmd.label        "Error Console">
 <!ENTITY errorConsoleCmd.accesskey    "C">
 <!ENTITY errorConsoleCmd.commandkey   "j">
 
+<!ENTITY hudConsoleCmd.label          "Heads Up Display">
+<!ENTITY hudConsoleCmd.accesskey      "U">
+<!ENTITY hudConsoleCmd.commandkey     "k">
+
 <!ENTITY inspectMenu.label            "Inspect">
 <!ENTITY inspectMenu.accesskey        "T">
 <!ENTITY inspectMenu.commandkey       "I">
 
 <!ENTITY fileMenu.label         "File"> 
 <!ENTITY fileMenu.accesskey       "F">
 <!ENTITY newNavigatorCmd.label        "New Window">
 <!ENTITY newNavigatorCmd.key        "N">
--- a/browser/locales/en-US/chrome/browser/browser.properties
+++ b/browser/locales/en-US/chrome/browser/browser.properties
@@ -196,29 +196,31 @@ pu.notifyButton.label=Details…
 pu.notifyButton.accesskey=D
 # LOCALIZATION NOTE %S will be replaced by the short name of the application.
 puNotifyText=%S has been updated
 puAlertTitle=%S Updated
 puAlertText=Click here for details
 
 # Geolocation UI
 
-# LOCALIZATION NOTE (geolocation.shareLocation geolocation.dontShareLocation): 
+# LOCALIZATION NOTE (geolocation.shareLocation geolocation.dontShareLocation geolocation.alwaysShare geolocation.neverShare): 
 #If you're having trouble with the word Share, please use Allow and Block in your language.
 geolocation.shareLocation=Share Location
 geolocation.shareLocation.accesskey=a
 geolocation.dontShareLocation=Don't Share
 geolocation.dontShareLocation.accesskey=o
+geolocation.alwaysShare=Always Share
+geolocation.alwaysShare.accesskey=A
+geolocation.neverShare=Never Share
+geolocation.neverShare.accesskey=N
 geolocation.siteWantsToKnow=%S wants to know your location.
 geolocation.fileWantsToKnow=The file %S wants to know your location.
 # LOCALIZATION NOTE (geolocation.learnMore): Use the unicode ellipsis char, \u2026,
 # or use "..." if \u2026 doesn't suit traditions in your locale.
 geolocation.learnMore=Learn More…
-geolocation.remember=Remember for this site
-geolocation.remember.accesskey=R
 
 # Phishing/Malware Notification Bar.
 # LOCALIZATION NOTE (notAForgery, notAnAttack)
 # The two button strings will never be shown at the same time, so
 # it's okay for them to have the same access key
 safebrowsing.getMeOutOfHereButton.label=Get me out of here!
 safebrowsing.getMeOutOfHereButton.accessKey=G
 safebrowsing.reportedWebForgery=Reported Web Forgery!
--- a/browser/themes/gnomestripe/browser/browser.css
+++ b/browser/themes/gnomestripe/browser/browser.css
@@ -950,16 +950,44 @@ toolbar[iconsize="small"] #fullscreen-bu
 }
 
 /* Identity popup bounding box */
 #identity-popup-container {
   min-width: 280px;
   padding: 10px;
 }
 
+/* Notification popup */
+#notification-popup {
+  margin: 4px 0;
+  min-width: 280px;
+  padding: 10px;
+}
+
+.popup-notification-icon {
+  width: 64px;
+  height: 64px;
+  -moz-margin-end: 10px;
+}
+
+.popup-notification-icon[popupid="geolocation"] {
+  list-style-image: url(chrome://browser/skin/Geo.png);
+}
+
+/* Notification icon box */
+#notification-popup-box {
+  margin: 0 3px;
+}
+
+#geo-notification-icon {
+  list-style-image: url(chrome://browser/skin/Geo.png);
+  width: 16px;
+  height: 16px;
+}
+
 /* Feed icon */
 #feed-button,
 #feed-button > .button-box,
 #feed-button:hover:active > .button-box {
   padding: 0px;
   margin: 0px;
   border: 0px; 
   background-color: transparent;
index 31167bd90a3b806a4dfd3ad04cccf1cc9811ca72..428c5da24cf12fe406e465892eec73a6fa8479a9
GIT binary patch
literal 11176
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
--- a/browser/themes/pinstripe/browser/browser.css
+++ b/browser/themes/pinstripe/browser/browser.css
@@ -90,58 +90,57 @@
 
 .tabbrowser-tab:-moz-lwtheme-brighttext[selected="true"] {
   -moz-border-left-colors: rgba(255,255,255,.6) rgba(255,255,255,.2);
   -moz-border-bottom-colors: rgba(255,255,255,.6) rgba(255,255,255,.2);
   -moz-border-right-colors: rgba(255,255,255,.6) rgba(255,255,255,.2);
 }
 
 .tabs-newtab-button:-moz-lwtheme-darktext,
-#TabsToolbar > #new-tab-button:-moz-lwtheme-darktext,
-#TabsToolbar > toolbarpaletteitem > #new-tab-button:-moz-lwtheme-darktext,
-#TabsToolbar > #alltabs-button:-moz-lwtheme-darktext,
-#TabsToolbar > toolbarpaletteitem > #alltabs-button:-moz-lwtheme-darktext,
+#TabsToolbar > toolbarbutton:-moz-lwtheme-darktext,
+#TabsToolbar > toolbarpaletteitem > toolbarbutton:-moz-lwtheme-darktext,
 #tabs-closebutton:-moz-lwtheme-darktext,
 .tabbrowser-arrowscrollbox:-moz-lwtheme-darktext > .scrollbutton-up,
 .tabbrowser-arrowscrollbox:-moz-lwtheme-darktext > .scrollbutton-down,
 .tabbrowser-tab:-moz-lwtheme-darktext:not([selected="true"]) {
   -moz-box-shadow: inset 0 1px 0 rgba(50,50,50,.5);
 }
 
 .tabs-newtab-button:-moz-lwtheme-brighttext,
-#TabsToolbar > #new-tab-button:-moz-lwtheme-brighttext,
-#TabsToolbar > toolbarpaletteitem > #new-tab-button:-moz-lwtheme-brighttext,
-#TabsToolbar > #alltabs-button:-moz-lwtheme-brighttext,
-#TabsToolbar > toolbarpaletteitem > #alltabs-button:-moz-lwtheme-brighttext,
+#TabsToolbar > toolbarbutton:-moz-lwtheme-brighttext,
+#TabsToolbar > toolbarpaletteitem > toolbarbutton:-moz-lwtheme-brighttext,
 #tabs-closebutton:-moz-lwtheme-brighttext,
 .tabbrowser-arrowscrollbox:-moz-lwtheme-brighttext > .scrollbutton-up,
 .tabbrowser-arrowscrollbox:-moz-lwtheme-brighttext > .scrollbutton-down,
 .tabbrowser-tab:-moz-lwtheme-brighttext:not([selected="true"]) {
   -moz-box-shadow: inset 0 1px 0 rgba(255,255,255,.6);
 }
 
 #main-window {
   -moz-appearance: none;
   background-color: #eeeeee;
 }
 
 #main-window[chromehidden~="toolbar"][chromehidden~="location"][chromehidden~="directories"] {
   border-top: 1px solid rgba(0,0,0,0.65);
 }
 
+#navigator-toolbox > toolbar:not(#toolbar-menubar):not(#TabsToolbar) {
+  -moz-box-align: center;
+  padding: 2px 4px 4px;
+}
+
 /* ----- BOOKMARK TOOLBAR ----- */
 
 #PersonalToolbar {
   -moz-appearance: none;
   margin-top: -1px; /* overlay the bottom border of the toolbar above us */
   background-color: -moz-mac-chrome-active;
   border-bottom: 1px solid rgba(0, 0, 0, 0.57);
   min-height: 22px;
-  padding: 0 4px 3px;
-  -moz-box-align: center;
 }
 
 #PersonalToolbar:-moz-window-inactive {
   background-color: -moz-mac-chrome-inactive;
   border-bottom-color: rgba(0, 0, 0, 0.32);
 }
 
 #personal-bookmarks {
@@ -290,563 +289,470 @@ toolbarbutton.bookmark-item > menupopup 
 #bookmarksToolbarFolderMenu {
   list-style-image: url("chrome://browser/skin/places/bookmarksToolbar.png");  
 }
 
 /* ----- PRIMARY TOOLBAR BUTTONS ----- */	
 
 .toolbarbutton-1,
 #restore-button,
-#back-forward-dropmarker {
-  min-width: 0px;
-  list-style-image: url("chrome://browser/skin/Toolbar.png");
+toolbarbutton[type="menu-button"] > .toolbarbutton-menubutton-button,
+toolbarbutton[type="menu-button"] > .toolbarbutton-menubutton-dropmarker {
+  margin: 0;
   -moz-box-orient: vertical;
 }
 
-toolbar[mode="text"] .toolbarbutton-1,
-toolbar[mode="text"] .toolbarbutton-menubutton-button {
-  -moz-box-orient: horizontal;
+toolbar[mode="icons"] .toolbarbutton-1:not([type="menu-button"]),
+toolbar[mode="icons"] #restore-button,
+toolbar[mode="icons"] toolbarbutton[type="menu-button"] > .toolbarbutton-menubutton-button,
+toolbar[mode="icons"] toolbarbutton[type="menu-button"] > .toolbarbutton-menubutton-dropmarker {
+  padding: 0 3px;
+  height: 22px;
+  border: 1px solid @toolbarbuttonBorderColor@;
+  -moz-border-radius: @toolbarbuttonCornerRadius@;
+  -moz-box-shadow: 0 1px rgba(255, 255, 255, 0.2);
+  background: @toolbarbuttonBackground@;
+  background-origin: border-box;
+}
+
+toolbar[mode="icons"] .toolbarbutton-1:not([type="menu-button"]),
+toolbar[mode="icons"] #restore-button,
+toolbar[mode="icons"] toolbarbutton[type="menu-button"] > .toolbarbutton-menubutton-button {
+  min-width: 28px;
+}
+
+.toolbarbutton-1 > .toolbarbutton-icon,
+#restore-button > .toolbarbutton-icon,
+toolbarbutton[type="menu-button"] > .toolbarbutton-menubutton-button > .toolbarbutton-icon {
+  padding: 0;
+  max-height: 20px;
 }
 
-toolbar[mode="text"] .toolbarbutton-1 > .toolbarbutton-text {
-  margin: 4px;
+/* Only set the max-width in icon-only mode because it affects the label, too */
+toolbar[mode="icons"] .toolbarbutton-1 > .toolbarbutton-icon,
+toolbar[mode="icons"] #restore-button > .toolbarbutton-icon,
+toolbar[mode="icons"] toolbarbutton[type="menu-button"] > .toolbarbutton-menubutton-button > .toolbarbutton-icon {
+  max-width: 20px;
+}
+
+.toolbarbutton-1[disabled="true"] > .toolbarbutton-icon,
+#restore-button[disabled="true"] > .toolbarbutton-icon,
+toolbarbutton[type="menu-button"] > .toolbarbutton-menubutton-button[disabled="true"] > .toolbarbutton-icon {
+  opacity: .4;
+}
+
+.toolbarbutton-1,
+#restore-button,
+toolbarbutton[type="menu-button"] {
+  margin: 0 4px;
+}
+
+.toolbarbutton-1,
+#restore-button {
+  list-style-image: url("chrome://browser/skin/Toolbar.png");
+}
+
+toolbarbutton[type="menu-button"] > .toolbarbutton-menubutton-dropmarker {
+  list-style-image: url(chrome://browser/skin/toolbarbutton-dropmarker.png);
+}
+
+toolbar[mode="icons"] toolbarbutton[type="menu-button"] > .toolbarbutton-menubutton-dropmarker {
+  width: 14px;
+  padding-top: 2px;
+  -moz-border-start: none !important;
+}
+
+toolbar[mode="icons"] toolbarbutton[type="menu-button"] > .toolbarbutton-menubutton-button:-moz-locale-dir(rtl),
+toolbar[mode="icons"] toolbarbutton[type="menu-button"] > .toolbarbutton-menubutton-dropmarker:-moz-locale-dir(ltr) {
+  -moz-border-radius-topleft: 0;
+  -moz-border-radius-bottomleft: 0;
 }
 
-#nav-bar .toolbarbutton-1,
-#restore-button {
-  padding-top: 0;
-  padding-bottom: 0;
+toolbar[mode="icons"] toolbarbutton[type="menu-button"] > .toolbarbutton-menubutton-button:-moz-locale-dir(ltr),
+toolbar[mode="icons"] toolbarbutton[type="menu-button"] > .toolbarbutton-menubutton-dropmarker:-moz-locale-dir(rtl) {
+  -moz-border-radius-topright: 0;
+  -moz-border-radius-bottomright: 0;
+}
+
+toolbar:not([mode="icons"]) toolbarbutton[type="menu-button"]:not([open="true"]) > .toolbarbutton-menubutton-dropmarker {
+  opacity: .7;
+}
+
+.toolbarbutton-1 > .toolbarbutton-text,
+toolbarbutton[type="menu-button"] > .toolbarbutton-menubutton-button > .toolbarbutton-text {
+  margin: 2px 0 0;
+}
+
+toolbar[mode="icons"] .toolbarbutton-1:not([type="menu-button"]):not([disabled="true"]):active:hover,
+toolbar[mode="icons"] #restore-button:not([disabled="true"]):active:hover,
+toolbar[mode="icons"] .toolbarbutton-1:not([type="menu-button"])[open="true"],
+toolbar[mode="icons"] toolbarbutton[type="menu-button"]:not([disabled="true"]) > .toolbarbutton-menubutton-button:active:hover,
+toolbar[mode="icons"] toolbarbutton[type="menu-button"][open="true"] > .toolbarbutton-menubutton-dropmarker {
+  background: @toolbarbuttonPressedBackgroundColor@;
+  text-shadow: @loweredShadow@;
+  -moz-box-shadow: @toolbarbuttonPressedInnerShadow@, @loweredShadow@;
+}
+
+toolbar[mode="icons"] .toolbarbutton-1:not([type="menu-button"]):not(#fullscreen-button)[checked="true"] {
+  background: #606060;
+  -moz-box-shadow: inset #2A2A2A 0 3px 5px, @loweredShadow@;
+}
+
+toolbar[mode="icons"] .toolbarbutton-1:not([type="menu-button"]):not(#fullscreen-button)[checked="true"]:not([disabled="true"]):active:hover {
+  background: #4E4E4E;
+  -moz-box-shadow: inset #1c1c1c 0 3px 5px;
 }
 
-#navigator-toolbox > toolbar > toolbaritem:-moz-window-inactive,
-#navigator-toolbox > toolbar > toolbarbutton:-moz-window-inactive {
-  opacity: 0.75;
+toolbar[mode="icons"] .toolbarbutton-1:not([type="menu-button"]):-moz-window-inactive,
+toolbar[mode="icons"] #restore-button:-moz-window-inactive,
+toolbar[mode="icons"] toolbarbutton[type="menu-button"] > .toolbarbutton-menubutton-button:-moz-window-inactive,
+toolbar[mode="icons"] toolbarbutton[type="menu-button"] > .toolbarbutton-menubutton-dropmarker:-moz-window-inactive {
+  border-color: @toolbarbuttonInactiveBorderColor@;
+  background-image: @toolbarbuttonInactiveBackgroundImage@;
+}
+
+toolbar[mode="icons"] .toolbarbutton-1:not([type="menu-button"]):not(#fullscreen-button)[checked="true"]:-moz-window-inactive {
+  background: #8E8E8E;
+  -moz-box-shadow: inset rgba(0, 0, 0, 0.5) 0 3px 5px, @loweredShadow@;
 }
 
-#back-button:-moz-locale-dir(rtl) > .toolbarbutton-icon,
-#forward-button:-moz-locale-dir(rtl) > .toolbarbutton-icon,
-#back-forward-dropmarker:-moz-locale-dir(rtl) > .toolbarbutton-icon {
+/* unified back/forward button */
+
+#unified-back-forward-button {
+  -moz-box-align: center;
+}
+
+#back-button:-moz-locale-dir(ltr),
+#forward-button:-moz-locale-dir(rtl) {
+  -moz-image-region: rect(0, 40px, 20px, 20px);
+}
+
+#back-button:-moz-locale-dir(rtl),
+#forward-button:-moz-locale-dir(ltr) {
+  -moz-image-region: rect(0, 60px, 20px, 40px);
+}
+
+toolbar:not([iconsize="small"])[mode="icons"] #back-button {
+  -moz-margin-end: -5px;
+  position: relative;
+  -moz-image-region: rect(0, 20px, 20px, 0);
+}
+
+toolbar:not([iconsize="small"])[mode="icons"] #back-button:-moz-locale-dir(rtl) {
   -moz-transform: scaleX(-1);
 }
 
-/* ----- DEFAULT BACK BUTTON, STAND-ALONE ----- */	
-
-#back-button {
-  -moz-image-region: rect(0px, 36px, 23px, 0px);
-}
-#back-button[disabled="true"] {
-  -moz-image-region: rect(23px, 36px, 46px, 0px);
-}
-#back-button:hover:active:not([disabled]),
-#back-button[open="true"] {
-  -moz-image-region: rect(46px, 36px, 69px, 0px);
+toolbar:not([iconsize="small"])[mode="icons"] #back-button {
+  width: 30px;
+  height: 30px;
+  padding: 4px 5px 4px 3px;
+  -moz-border-radius: 100%;
 }
 
-/* ----- DEFAULT FORWARD BUTTON, STAND-ALONE ----- */	
-
-#forward-button {
-  -moz-image-region: rect(0px, 72px, 23px, 36px);
+toolbar[mode="icons"] #forward-button {
+  -moz-margin-start: 0;
 }
 
-#forward-button[disabled="true"] {
-  -moz-image-region: rect(23px, 72px, 46px, 36px);
+toolbar[mode="icons"]:not([iconsize="small"]) #forward-button {
+  /* 1px to the right */
+  -moz-padding-start: 4px;
+  -moz-padding-end: 2px;
 }
-#forward-button:hover:active:not([disabled]),
-#forward-button[open="true"] {
-  -moz-image-region: rect(46px, 72px, 69px, 36px);
+
+toolbar[iconsize="small"][mode="icons"] #back-button {
+  -moz-margin-end: 0;
 }
 
-/* ----- DEFAULT BACK/FORWARD BUTTONS ----- */
-
-toolbar[mode="icons"] #unified-back-forward-button > #back-button {
-  -moz-image-region: rect(0px, 535px, 33px, 504px);
-  -moz-margin-end: 0;
-  -moz-padding-end: 0;
-  border-left: none;
-  border-right: none;
+toolbar[iconsize="small"][mode="icons"] #back-button {
+  width: 26px;
+  -moz-border-end-width: 0;
+  -moz-padding-end: 2px;
 }
 
-toolbar[mode="icons"] #unified-back-forward-button > #back-button[disabled="true"] {
- -moz-image-region: rect(33px, 535px, 66px, 504px);
-}
-
-toolbar[mode="icons"] #unified-back-forward-button > #back-button:hover:active:not([disabled]),
-toolbar[mode="icons"] #unified-back-forward-button > #back-button[open="true"] {
-  -moz-image-region: rect(66px, 535px, 99px, 504px);
+toolbar[iconsize="small"][mode="icons"] #forward-button  {
+  width: 27px;
+  -moz-padding-start: 2px;
 }
 
-toolbar[mode="icons"] #unified-back-forward-button > #forward-button {
-  -moz-image-region: rect(0px, 560px, 33px, 535px);
-  -moz-margin-start: 0;
-  -moz-margin-end: 0;
-  -moz-padding-start: 0;
-  -moz-padding-end: 0;
-  border-left: none;
-  border-right: none;
+toolbar[mode="icons"]:not([iconsize="small"]) #forward-button:-moz-locale-dir(ltr),
+toolbar[iconsize="small"][mode="icons"] #back-button:-moz-locale-dir(rtl),
+toolbar[iconsize="small"][mode="icons"] #forward-button:-moz-locale-dir(ltr) {
+  -moz-border-radius-topleft: 0;
+  -moz-border-radius-bottomleft: 0;
 }
 
-toolbar[mode="icons"] #unified-back-forward-button > #forward-button[disabled="true"] {
- -moz-image-region: rect(33px, 560px, 66px, 535px);
-}
-
-toolbar[mode="icons"] #unified-back-forward-button > #forward-button:hover:active:not([disabled]),
-toolbar[mode="icons"] #unified-back-forward-button > #forward-button[open="true"] {
-  -moz-image-region: rect(99px, 560px, 132px, 530px);
-  -moz-margin-start: -5px;
+toolbar[mode="icons"]:not([iconsize="small"]) #forward-button:-moz-locale-dir(rtl),
+toolbar[iconsize="small"][mode="icons"] #back-button:-moz-locale-dir(ltr),
+toolbar[iconsize="small"][mode="icons"] #forward-button:-moz-locale-dir(rtl) {
+  -moz-border-radius-topright: 0;
+  -moz-border-radius-bottomright: 0;
 }
 
 #back-forward-dropmarker {
-  -moz-image-region: rect(0px, 571px, 33px, 560px);
-  -moz-margin-start: 0;
-  -moz-margin-end: 3px;
-  -moz-padding-start: 0;
-  -moz-padding-end: 1px;
-  border-left: none;
-  border-right: none;
-}
-
-toolbar[mode="icons"] #back-forward-dropmarker > image {
-  display: -moz-box;
-  margin: 0;
-  padding: 0;
-}
-
-toolbar[mode="icons"] #back-forward-dropmarker > dropmarker {
   display: none;
 }
 
-#back-forward-dropmarker[disabled="true"] {
- -moz-image-region: rect(33px, 571px, 66px, 560px);
-}
-
-#back-forward-dropmarker:hover:active:not([disabled]),
-#back-forward-dropmarker[open="true"] {
-  -moz-image-region: rect(66px, 571px, 99px, 560px);
-}
-
 .unified-nav-back[_moz-menuactive]:-moz-locale-dir(ltr),
 .unified-nav-forward[_moz-menuactive]:-moz-locale-dir(rtl) {
   list-style-image: url("chrome://browser/skin/menu-back.png") !important;
 }
 
 .unified-nav-forward[_moz-menuactive]:-moz-locale-dir(ltr),
 .unified-nav-back[_moz-menuactive]:-moz-locale-dir(rtl) {
   list-style-image: url("chrome://browser/skin/menu-forward.png") !important;
 }
 
 
-/* ----- SMALL BACK BUTTON, PAIRED----- */	
-
-toolbar[mode="icons"][iconsize="small"] #unified-back-forward-button > #back-button {
-  -moz-image-region: rect(0px, 605px, 23px, 571px);
-  -moz-margin-end: 0;
-  -moz-padding-end: 0;
-  border-left: none;
-  border-right: none;
-}
-
-toolbar[mode="icons"][iconsize="small"] #unified-back-forward-button > #back-button[disabled="true"] {
-  -moz-image-region: rect(23px, 605px, 46px, 571px);
-}
-
-toolbar[mode="icons"][iconsize="small"] #unified-back-forward-button > #back-button:hover:active:not([disabled]),
-toolbar[mode="icons"][iconsize="small"] #unified-back-forward-button > #back-button[open="true"] {
-  -moz-image-region: rect(46px, 605px, 69px, 571px);
-}
-
-/* ----- SMALL FORWARD BUTTON, PAIRED ----- */	
+/* reload button */
 
-toolbar[mode="icons"][iconsize="small"] #unified-back-forward-button > #forward-button {
-  -moz-image-region: rect(0px, 638px, 23px, 605px);
-  -moz-margin-start: 0;
-  -moz-padding-start: 0;
-  border-left: none;
-  border-right: none;
-}
-
-toolbar[mode="icons"][iconsize="small"] #unified-back-forward-button > #forward-button[disabled="true"] {
- -moz-image-region: rect(23px, 638px, 46px, 605px);
-}
-
-toolbar[mode="icons"][iconsize="small"] #unified-back-forward-button > #forward-button:hover:active:not([disabled]),
-toolbar[mode="icons"][iconsize="small"] #unified-back-forward-button > #forward-button[open="true"] {
-  -moz-image-region: rect(46px, 638px, 69px, 605px);
-  -moz-margin-start: 0;
-}
-
-/* ----- SMALL BACK/FORWARD DROPMARKER ----- */	
-
-toolbar[iconsize="small"] #unified-back-forward-button > #back-forward-dropmarker {
-  -moz-image-region: rect(0px, 648px, 23px, 638px);
+#reload-button {
+  -moz-image-region: rect(0, 80px, 20px, 60px);
 }
 
-toolbar[iconsize="small"] #unified-back-forward-button > #back-forward-dropmarker[disabled="true"] {
- -moz-image-region: rect(23px, 648px, 46px, 638px);
-}
-
-toolbar[iconsize="small"] #unified-back-forward-button > #back-forward-dropmarker:hover:active:not([disabled]),
-toolbar[iconsize="small"] #unified-back-forward-button > #back-forward-dropmarker[open="true"] {
-  -moz-image-region: rect(46px, 648px, 69px, 638px);
-}
+/* stop button */
 
-/* ----- DEFAULT RELOAD BUTTON ----- */	
-
-#reload-button {
-  -moz-image-region: rect(0px, 108px, 23px, 72px);
-}
-#reload-button[disabled="true"] {
-  -moz-image-region: rect(23px, 108px, 46px, 72px) !important;
-}
-#reload-button:hover:active {
-  -moz-image-region: rect(46px, 108px, 69px, 72px);
+#stop-button {
+  -moz-image-region: rect(0, 100px, 20px, 80px);
 }
 
-/* ----- DEFAULT STOP BUTTON ----- */	
-
-#stop-button {
-  -moz-image-region: rect(0px, 144px, 23px, 108px);
-}
-#stop-button[disabled="true"] {
-  -moz-image-region: rect(23px, 144px, 46px, 108px) !important;
-}
-#stop-button:hover:active {
-  -moz-image-region: rect(46px, 144px, 69px, 108px);
-}
-
-
-/* ----- DEFAULT HOME BUTTON ----- */	
+/* home button */
 
 #home-button {
-  -moz-image-region: rect(0px, 180px, 23px, 144px);
-}
-#home-button[disabled="true"] {
-  -moz-image-region: rect(23px, 180px, 46px, 144px) !important;
-}
-#home-button:hover:active {
-  -moz-image-region: rect(46px, 180px, 69px, 144px);
+  -moz-image-region: rect(0, 120px, 20px, 100px);
 }
 
 #home-button.bookmark-item {
   list-style-image: url("chrome://browser/skin/home.png");
   -moz-image-region: rect(0, 12px, 12px, 0);
 }
 
 #home-button.bookmark-item:hover {
   -moz-image-region: rect(0, 24px, 12px, 12px);
 }
 
 #home-button.bookmark-item > .toolbarbutton-icon {
   display: -moz-box !important;
   -moz-margin-start: -2px;
   -moz-margin-end: 3px;
 }
-/* ----- DEFAULT DOWNLOADS BUTTON ----- */	
+
+/* download manager button */
 
 #downloads-button {
-  -moz-image-region: rect(0px, 216px, 23px, 180px);
-}
-#downloads-button:hover:active {
-  -moz-image-region: rect(46px, 216px, 69px, 180px);
+  -moz-image-region: rect(0, 140px, 20px, 120px);
 }
 
-/* ----- DEFAULT HISTORY BUTTON ----- */	
+/* history sidebar button */
 
 #history-button {
-  -moz-image-region: rect(0px, 252px, 23px, 216px);
-}
-#history-button:hover:active { 
-  -moz-image-region: rect(46px, 252px, 69px, 216px);
-  background-color: transparent;
-  border-color: transparent;
+  -moz-image-region: rect(0, 160px, 20px, 140px);
 }
 
 #history-button[checked="true"] {
-  -moz-image-region: rect(69px, 252px, 92px, 216px);
-  background-color: transparent;
-  border-color: transparent;
-}
-
-#history-button[checked="true"]:hover:active {
-  -moz-image-region: rect(92px, 252px, 115px, 216px);
+  -moz-image-region: rect(20px, 160px, 40px, 140px);
 }
 
-/* ----- DEFAULT BOOKMARKS BUTTON ----- */	
+#history-button[checked="true"]:active:hover {
+  -moz-image-region: rect(40px, 160px, 60px, 140px);
+}
+
+/* bookmark sidebar button */
 
 #bookmarks-button {
-  -moz-image-region: rect(0px, 288px, 23px, 252px);
-}
-#bookmarks-button:hover:active {
-  -moz-image-region: rect(46px, 288px, 69px, 252px);
-  background-color: transparent;
-  border-color: transparent;
+  -moz-image-region: rect(0, 180px, 20px, 160px);
 }
 
 #bookmarks-button[checked="true"] {
-  -moz-image-region: rect(69px, 288px, 92px, 252px);
-  background-color: transparent;
-  border-color: transparent;
+  -moz-image-region: rect(20px, 180px, 40px, 160px);
 }
 
-#bookmarks-button[checked="true"]:hover:active {
-  -moz-image-region: rect(92px, 288px, 115px, 252px);
+#bookmarks-button[checked="true"]:active:hover {
+  -moz-image-region: rect(40px, 180px, 60px, 160px);
 }
 
-/* ----- DEFAULT PRINT BUTTON ----- */	
+/* print button */
 
 #print-button {
-  -moz-image-region: rect(0px, 324px, 23px, 288px);
-}
-#print-button[disabled="true"] {
-  -moz-image-region: rect(23px, 324px, 46px, 288px);
-}
-#print-button:hover:active {
-  -moz-image-region: rect(46px, 324px, 69px, 288px);
+  -moz-image-region: rect(0, 200px, 20px, 180px);
 }
 
-/* ----- TOOLBAR NEW-TAB BUTTON ----- */	
+/* toolbar new tab button */
 
 #new-tab-button {
-  -moz-image-region: rect(0px, 360px, 23px, 324px);
-}
-#new-tab-button:hover:active {
-  -moz-image-region: rect(46px, 360px, 69px, 324px);
+  -moz-image-region: rect(0, 220px, 20px, 200px);
 }
 
-/* ----- DEFAULT NEW-WINDOW BUTTON ----- */	
+/* new window button */
 
 #new-window-button {
-  -moz-image-region: rect(0px, 396px, 23px, 360px);
-}
-#new-window-button:hover:active {
-  -moz-image-region: rect(46px, 396px, 69px, 360px);
+  -moz-image-region: rect(0, 240px, 20px, 220px);
 }
 
-/* ----- DEFAULT CUT BUTTON ----- */	
+/* cut button */
 
 #cut-button {
-  -moz-image-region: rect(0px, 432px, 23px, 396px);
-}
-#cut-button[disabled="true"] {
-  -moz-image-region: rect(23px, 432px, 46px, 396px) !important;
-}
-#cut-button:hover:active,
-#cut-button[checked="true"] {
-  -moz-image-region: rect(46px, 432px, 69px, 396px);
+  -moz-image-region: rect(0, 260px, 20px, 240px);
 }
 
-/* ----- DEFAULT COPY BUTTON ----- */	
+/* copy button */
 
 #copy-button {
-  -moz-image-region: rect(0px, 468px, 23px, 432px);
+  -moz-image-region: rect(0, 280px, 20px, 260px);
 }
-#copy-button[disabled="true"] {
-  -moz-image-region: rect(23px, 468px, 46px, 432px) !important;
-}
-#copy-button:hover:active,
-#copy-button[checked="true"] {
-  -moz-image-region: rect(46px, 468px, 69px, 432px);
+
+/* paste button */
+
+#paste-button {
+  -moz-image-region: rect(0, 300px, 20px, 280px);
 }
 
-/* ----- DEFAULT PASTE BUTTON ----- */	
+/* alltabs button */
 
-#paste-button {
-  -moz-image-region: rect(0px, 504px, 23px, 468px);
+#alltabs-button {
+  -moz-image-region: rect(0, 380px, 20px, 360px);
 }
-#paste-button[disabled="true"] {
-  -moz-image-region: rect(23px, 504px, 46px, 468px) !important;
-}
-#paste-button:hover:active,
-#paste-button[checked="true"] {
-  -moz-image-region: rect(46px, 504px, 69px, 468px);
+
+/* fullscreen button */
+
+#fullscreen-button {
+  -moz-image-region: rect(0, 340px, 20px, 320px);
 }
 
 /* ----- FULLSCREEN AND RESTORE BUTTON ----- */
 
-#fullscreen-button {
-  -moz-image-region: rect(0px, 684px, 23px, 648px);
-}
-
-#fullscreen-button:hover:active {
-  -moz-image-region: rect(46px, 684px, 69px, 648px);
-}
-
 #fullscreen-button[checked="true"],
 #restore-button {
-  background-color: transparent;
-  border-color: transparent;
-  -moz-image-region: rect(0px, 720px, 23px, 684px);
-}
-
-#fullscreen-button[checked="true"]:hover:active,
-#restore-button:hover:active {
-  -moz-image-region: rect(46px, 720px, 69px, 684px);
+  -moz-image-region: rect(0, 360px, 20px, 340px);
 }
 
 /* ----- FULLSCREEN WINDOW CONTROLS ----- */
 
 #minimize-button,
 #close-button,
 #fullscreen-button ~ #window-controls > #restore-button {
   display: none;
 }
 
 /* ::::: nav-bar-inner ::::: */
 
-#urlbar {
-  direction: ltr;
-}
-
-.searchbar-textbox,
-#urlbar {
+#urlbar,
+.searchbar-textbox {
   font: icon;
   width: 7em;
   min-width: 7em;
   -moz-appearance: none;
-  -moz-border-radius: 100%;
   border: 0;
-  padding: 1px;
-  background: -moz-linear-gradient(top, rgba(0,0,0,.55), rgba(0,0,0,.27));
-  -moz-box-shadow: @loweredShadow@;
-  margin-top: 0;
-  margin-bottom: 1px;
+  -moz-box-shadow: 0 1px rgba(255, 255, 255, 0.2);
+  margin: 0 4px;
+  padding: 0;
+  border: 1px solid transparent;
+  background: -moz-linear-gradient(#D6D6D6, #D6D6D6 1px, #F7F7F7 1px, #F7F7F7 2px, #FFF 2px, #FFF),
+              -moz-linear-gradient(rgba(0,0,0,.5), rgba(0,0,0,.2));
+  background-origin: padding-box, border-box;
+  background-clip: padding-box, border-box;
 }
 
-.searchbar-textbox[focused="true"],
-#urlbar[focused="true"] {
-  -moz-box-shadow: 0 0 3px 2px -moz-mac-focusring;
-  background: -moz-mac-focusring -moz-linear-gradient(top, rgba(0,0,0,.1), rgba(0,0,0,.1));
-}
-
-.search-go-container,
-#urlbar > .autocomplete-history-dropmarker {
-  -moz-padding-end: 6px;
-  -moz-border-radius: 100%;
-}
-
-#urlbar > .autocomplete-history-dropmarker {
-  width: 22px;
+#urlbar:-moz-window-inactive,
+.searchbar-textbox:-moz-window-inactive {
+  background-image: -moz-linear-gradient(#D6D6D6, #D6D6D6 1px, #F7F7F7 1px, #F7F7F7 2px, #FFF 2px, #FFF),
+                    -moz-linear-gradient(@toolbarbuttonInactiveBorderColor@, @toolbarbuttonInactiveBorderColor@);
 }
 
-.search-go-container:-moz-locale-dir(ltr),
-#urlbar > .autocomplete-history-dropmarker {
-  -moz-border-radius-topleft: 0;
-  -moz-border-radius-bottomleft: 0;
-}
-
-.search-go-container:-moz-locale-dir(rtl) {
-  -moz-border-radius-topright: 0;
-  -moz-border-radius-bottomright: 0;
+#urlbar[focused="true"],
+.searchbar-textbox[focused="true"] {
+  background-color: -moz-mac-focusring;
+  background-image: -moz-linear-gradient(#D6D6D6, #D6D6D6 1px, #F7F7F7 1px, #F7F7F7 2px, #FFF 2px, #FFF),
+                    -moz-linear-gradient(rgba(0,0,0,.1), rgba(0,0,0,.1));
+  -moz-box-shadow: @focusRingShadow@;
 }
 
-.searchbar-engine-button,
-#identity-box {
-  background: @toolbarbuttonBackground@;
-  color: black;
-  -moz-padding-start: 6px;
-  -moz-padding-end: 16px;
-  -moz-border-radius: 100%;
-  margin: 0;
-  -moz-box-shadow: 0 1px rgba(0,0,0,.3);
+#urlbar {
+  -moz-border-radius: @toolbarbuttonCornerRadius@;
+  direction: ltr;
+  -moz-padding-end: 3px;
 }
 
-.searchbar-textbox[focused="true"] .searchbar-engine-button,
-#urlbar[focused="true"] > #identity-box {
-  -moz-box-shadow: none;
+#identity-box {
+  margin: 1px;
+  -moz-border-radius: 2px;
+  padding: 1px;
+  -moz-box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.1);
+  text-shadow: 0 1px rgba(255, 255, 255, 0.2);
 }
 
-#identity-box:focus:not(:active):not([open="true"]) #page-proxy-stack {
-  -moz-border-radius: 4px;
+
+#identity-box:focus:not(:active):not([open="true"]) {
   -moz-box-shadow: 0 0 3px 1px -moz-mac-focusring inset,
                    0 0 3px 2px -moz-mac-focusring;
 }
 
-.searchbar-engine-button[open="true"],
-.searchbar-engine-button:hover:active,
-#identity-box[open="true"],
-#identity-box:hover:active {
-  margin-top: -1px;
-  margin-bottom: -1px;
-  -moz-margin-start: -1px;
-  padding-top: 1px;
-  padding-bottom: 1px;
-  -moz-padding-start: 7px;
-  -moz-box-shadow: @toolbarbuttonPressedInnerShadow@,
-                   0 0 0 20px rgba(0,0,0,.2) inset !important;
+#identity-box {
+  color: white;
+  text-shadow: 0 1px 1px rgba(0, 0, 0, 0.7);
+  -moz-margin-end: 3px;
+}
+
+#identity-box {
+  background-image: -moz-linear-gradient(#FFF, #DDD);
+}
+
+#identity-box:active:hover,
+#identity-box[open="true"] {
+  -moz-box-shadow: inset 0 2px 7px rgba(0, 0, 0, 0.35),
+                   inset 0 0 0 20px rgba(0, 0, 0, 0.06);
 }
 
 #identity-box.verifiedDomain {
-  background-image: -moz-linear-gradient(top, #E8F2F9, #AED4EA 1px, #87ACCF 50%, #749CC5 50%, #4B6CA4);
+  background-image: -moz-linear-gradient(#588EC6, #3C68AE);
 }
 
 #identity-box.verifiedIdentity {
-  background-image: -moz-linear-gradient(top, #EBF8D2, #D3EEA1 1px, #AAD77B 50%, #96CB60 50%, #6EB142);
+  background-image: -moz-linear-gradient(#84BB40, #5BA020);
 }
 
 #identity-icon-labels {
-  margin: 0 4px;
-}
-
-.searchbar-textbox > .autocomplete-textbox-container > .textbox-input-box,
-#urlbar > .autocomplete-textbox-container > .textbox-input-box {
-  -moz-margin-end: 0;
-  -moz-margin-start: -16px;
-  -moz-padding-start: 10px;
-  height: 20px;
-  -moz-border-radius: 100%;
+  margin: 0 4px 1px;
 }
 
-.searchbar-textbox > .autocomplete-textbox-container > .textbox-input-box,
-#urlbar > .autocomplete-textbox-container > .textbox-input-box,
-.search-go-container,
-#urlbar-icons,
-#urlbar > .autocomplete-history-dropmarker {
-  background: -moz-linear-gradient(#D6D6D6, #D6D6D6 1px, #F7F7F7 1px, #F7F7F7 2px, #FFF 2px, #FFF);
-}
-
-.searchbar-textbox:-moz-locale-dir(ltr) > .autocomplete-textbox-container > .textbox-input-box,
 #urlbar > .autocomplete-textbox-container > .textbox-input-box {
-  -moz-border-radius-topright: 0;
-  -moz-border-radius-bottomright: 0;
-  -moz-box-shadow: 1px 0 rgba(0,0,0,.4) inset;
-}
-
-.searchbar-textbox:-moz-locale-dir(rtl) > .autocomplete-textbox-container > .textbox-input-box {
-  -moz-border-radius-topleft: 0;
-  -moz-border-radius-bottomleft: 0;
-  -moz-box-shadow: -1px 0 rgba(0,0,0,.4) inset;
+  -moz-margin-start: 0;
+  padding: 3px 0 2px;
 }
 
 #urlbar-icons {
   -moz-box-align: center;
 }
 
 #urlbar-search-splitter {
   min-width: 8px;
   width: 8px;
   background-image: none;
-  -moz-margin-start: -4px;
-}
-
-#urlbar-search-splitter + #urlbar-container > #urlbar,
-#urlbar-search-splitter + #search-container > #searchbar > .searchbar-textbox {
-  -moz-margin-start: 0;
+  margin: 0 -4px;
+  position: relative;
+  height: 22px;
 }
 
 #page-proxy-favicon,
 #urlbar-throbber {
   width: 16px;
   height: 16px;
   margin: 0px;
   padding: 0px;
 }
 
 #page-proxy-stack {
+  width: 18px;
+  height: 16px;
+  padding: 0 1px;
+}
+
+#identity-box.verifiedIdentity > hbox > #page-proxy-stack,
+#identity-box.verifiedDomain > hbox > #page-proxy-stack {
   width: 24px;
-  height: 20px;
-  padding: 2px 4px;
+  padding: 0 4px;
 }
 
 #identity-box.verifiedIdentity > hbox > #page-proxy-stack,
 #identity-box.verifiedDomain > hbox > #page-proxy-stack {
   background: url(urlbar-favicon-glow.png) center center no-repeat;
 }
 
 #page-proxy-favicon:not([src]) {
@@ -860,25 +766,21 @@ toolbar[iconsize="small"] #unified-back-
 #urlbar-throbber {
   list-style-image: url("chrome://browser/skin/places/searching_16.png");
 }
 
 #wrapper-urlbar-container[place="palette"] {
   max-width: 20em;
 }
 
-#wrapper-urlbar-container #identity-icon-labels,
-#wrapper-urlbar-container .autocomplete-history-dropmarker > .dropmarker-icon {
+#wrapper-urlbar-container > * > * > * > * > #identity-icon-labels,
+#wrapper-urlbar-container > * > * > .autocomplete-history-dropmarker {
   display: none;
 }
 
-#wrapper-urlbar-container .autocomplete-history-dropmarker {
-  width: 10px;
-}
-
 #urlbar-display {
   margin-top: -2px;
   margin-bottom: -2px;
   padding-top: 3px;
   padding-bottom: 2px;
   -moz-padding-end: 3px;
   color: GrayText;
   -moz-border-end: 1px solid #AAA;
@@ -1427,23 +1329,22 @@ sidebarheader > .tabs-closebutton > .too
 #navigator-throbber[busy="true"] {
   list-style-image: url("chrome://global/skin/icons/loading_16.png");
 }
 
 #wrapper-navigator-throbber > #navigator-throbber {
   list-style-image: url("chrome://global/skin/icons/notloading_16.png");
 }
 
-
 toolbarbutton.chevron > .toolbarbutton-menu-dropmarker {
   display: none;
 }
 
 #nav-bar {
-  padding: 0 4px;
+  padding-top: 0 !important;
 }
 
 #nav-bar[collapsed="true"] + toolbar[customindex] {
  border-top: 2px solid;
  -moz-border-top-colors: rgba(0,0,0,0.35) rgba(255,255,255,0.45);
 } 
 
 .bookmark-item {
@@ -1582,21 +1483,16 @@ toolbarbutton.chevron > .toolbarbutton-m
 #TabsToolbar:not(:-moz-lwtheme) {
   background: #9B9B9B url("chrome://browser/skin/tabbrowser/tabbrowser-tabs-bkgnd.png") repeat-x;
 }
 
 #TabsToolbar:not(:-moz-lwtheme):-moz-window-inactive {
   background-color: #e2e2e2;
 }
 
-#TabsToolbar > toolbarbutton,
-#TabsToolbar > toolbarpaletteitem > toolbarbutton {
-  padding: 0;
-}
-
 .tabbrowser-tabs {
   -moz-box-align: stretch;
   height: 25px;
 }
 
 .tabbrowser-tabs:not([overflow="true"]) {
   -moz-margin-start: 3px;
 }
@@ -1691,38 +1587,69 @@ toolbarbutton.chevron > .toolbarbutton-m
 .tabbrowser-arrowscrollbox > .scrollbutton-up[disabled="true"],
 .tabbrowser-arrowscrollbox > .scrollbutton-down[disabled="true"] {
   -moz-image-region: rect(0, 33px, 17px, 22px) !important;
   background-color: transparent !important; 
 }
 
 
 /**
- * Tabstrip New Tab & All Tabs Buttons
+ * Tabstrip toolbar buttons
  */
 
-#TabsToolbar > #new-tab-button,
-#TabsToolbar > toolbarpaletteitem > #new-tab-button,
-#TabsToolbar > #alltabs-button,
-#TabsToolbar > toolbarpaletteitem > #alltabs-button {
-  -moz-border-start: 2px solid;
-  -moz-border-end: none;
-  -moz-border-left-colors: rgba(0,0,0,0.25) rgba(255,255,255,0.15);
-  -moz-border-right-colors: rgba(0,0,0,0.25) rgba(255,255,255,0.15);
+#TabsToolbar > toolbarbutton,
+#TabsToolbar > toolbarpaletteitem > toolbarbutton,
+#TabsToolbar > toolbarbutton[type="menu-button"] > .toolbarbutton-menubutton-button,
+#TabsToolbar > toolbarpaletteitem > toolbarbutton[type="menu-button"] > .toolbarbutton-menubutton-button,
+#TabsToolbar > toolbarbutton[type="menu-button"] > .toolbarbutton-menubutton-dropmarker,
+#TabsToolbar > toolbarpaletteitem > toolbarbutton[type="menu-button"] > .toolbarbutton-menubutton-dropmarker {
   margin: 0;
+  padding: 0;
+  border: none;
+  -moz-border-radius: 0;
+  background: none;
+  -moz-box-shadow: none;
+}
+
+#TabsToolbar > toolbarbutton:not([type="menu-button"]),
+#TabsToolbar > toolbarpaletteitem > toolbarbutton:not([type="menu-button"]),
+#TabsToolbar > toolbarbutton[type="menu-button"] > .toolbarbutton-menubutton-button,
+#TabsToolbar > toolbarpaletteitem > toolbarbutton[type="menu-button"] > .toolbarbutton-menubutton-button,
+#TabsToolbar > toolbarbutton[type="menu-button"] > .toolbarbutton-menubutton-dropmarker,
+#TabsToolbar > toolbarpaletteitem > toolbarbutton[type="menu-button"] > .toolbarbutton-menubutton-dropmarker {
+  -moz-border-start: 2px solid !important;
+  -moz-border-end: none !important;
+  -moz-border-left-colors: rgba(0,0,0,0.25) rgba(255,255,255,0.15) !important;
+  -moz-border-right-colors: rgba(0,0,0,0.25) rgba(255,255,255,0.15) !important;
+  background-clip: padding-box;
+  margin: 0;
+  padding: 0 1px;
 }
 
 .tabs-newtab-button > .toolbarbutton-icon,
-#TabsToolbar > #new-tab-button > .toolbarbutton-icon,
-#TabsToolbar > toolbarpaletteitem > #new-tab-button > .toolbarbutton-icon,
-#TabsToolbar > #alltabs-button > .toolbarbutton-icon,
-#TabsToolbar > toolbarpaletteitem > #alltabs-button > .toolbarbutton-icon {
+#TabsToolbar > toolbarbutton > .toolbarbutton-icon,
+#TabsToolbar > toolbarpaletteitem > toolbarbutton > .toolbarbutton-icon,
+#TabsToolbar > toolbarbutton[type="menu-button"] > .toolbarbutton-menubutton-button > .toolbarbutton-icon,
+#TabsToolbar > toolbarpaletteitem > toolbarbutton[type="menu-button"] > .toolbarbutton-menubutton-button > .toolbarbutton-icon {
   padding: 0;
 }
 
+#TabsToolbar > toolbarbutton:not([type="menu-button"]):not([disabled="true"]):not([open="true"]):hover,
+#TabsToolbar > toolbarbutton[type="menu-button"] > .toolbarbutton-menubutton-button:not([disabled="true"]):hover,
+#TabsToolbar > toolbarbutton[type="menu-button"]:not([disabled="true"]):not([buttonover="true"]):hover > .toolbarbutton-menubutton-dropmarker {
+  background-color: rgba(0,0,0,0.10) !important;
+}
+
+#TabsToolbar > toolbarbutton:not([type="menu-button"]):not([disabled="true"]):hover:active,
+#TabsToolbar > toolbarbutton[type="menu"][open="true"],
+#TabsToolbar > toolbarbutton[type="menu-button"] > .toolbarbutton-menubutton-button:not([disabled="true"]):hover:active,
+#TabsToolbar > toolbarbutton[type="menu-button"][open="true"]:not([disabled="true"]):hover > .toolbarbutton-menubutton-dropmarker {
+  background-color: rgba(0,0,0,0.20) !important;
+}
+
 .tabs-newtab-button,
 #TabsToolbar > #new-tab-button,
 #TabsToolbar > toolbarpaletteitem > #new-tab-button {
   list-style-image: url(chrome://browser/skin/tabbrowser/newtab.png);
   -moz-image-region: rect(0, 18px, 20px, 0);
 }
 
 .tabs-newtab-button:hover,
@@ -1730,40 +1657,30 @@ toolbarbutton.chevron > .toolbarbutton-m
   -moz-image-region: rect(0, 36px, 20px, 18px);
 }
 
 .tabs-newtab-button:hover:active,
 #TabsToolbar > #new-tab-button:hover:active {
   -moz-image-region: rect(0, 54px, 20px, 36px);
 }
 
-#alltabs-button {
+#TabsToolbar > #alltabs-button {
   list-style-image: url(chrome://browser/skin/tabbrowser/alltabs-box-bkgnd-icon.png);
   -moz-image-region: rect(0, 22px, 20px, 0);
 }
 
-#alltabs-button:hover {
+#TabsToolbar > #alltabs-button:not([disabled="true"]):hover {
   -moz-image-region: rect(0, 44px, 20px, 22px);
 }
 
-#alltabs-button[type="menu"][open="true"],
-#alltabs-button:hover:active {
+#TabsToolbar > #alltabs-button[type="menu"][open="true"]:not([disabled="true"]),
+#TabsToolbar > #alltabs-button:not([disabled="true"]):hover:active {
   -moz-image-region: rect(0, 66px, 20px, 44px);
 }
 
-#TabsToolbar > #new-tab-button:hover,
-#TabsToolbar > #alltabs-button:hover {
-  background-color: rgba(0,0,0,0.10);
-}
-
-#TabsToolbar > #new-tab-button:hover:active,
-#TabsToolbar > #alltabs-button:hover:active {
-  background-color: rgba(0,0,0,0.20);
-}
-
 #alltabs-button[type="menu"] > .toolbarbutton-menu-dropmarker {
   display: none;
 }
 
 #alltabs-button > .toolbarbutton-icon {
   -moz-margin-end: 2px;
 }
 
@@ -1876,35 +1793,72 @@ toolbarbutton.chevron > .toolbarbutton-m
 
 #identity-popup-content-box.verifiedIdentity > #identity-popup-encryption > vbox > #identity-popup-encryption-icon ,
 #identity-popup-content-box.verifiedDomain > #identity-popup-encryption > vbox > #identity-popup-encryption-icon {
   margin-top: 5px;
   list-style-image: url("chrome://browser/skin/Secure-Glyph-White.png");
 }
 
 /* Popup Bounding Box */
-#identity-popup {
+#identity-popup,
+#notification-popup {
   -moz-appearance: none;
   -moz-window-shadow: none;
   background-color: transparent;
-  margin-top: -4px;
-  margin-left: -15px;
+  margin-top: -3px;
+  margin-left: -23px;
   min-width: 280px;
   -moz-border-image: url(chrome://browser/skin/hud-panel.png) 26 18 22 50 / 26px 18px 22px 50px repeat; 
 }
 
-#identity-popup-container {
+#notification-popup {
+  margin-top: -1px;
+  margin-left: -27px;
+}
+
+#notification-popup-box {
+  margin: 0 3px;
+}
+
+#geo-notification-icon {
+  list-style-image: url(chrome://browser/skin/Geo.png);
+  width: 16px;
+  height: 16px;
+  margin: 0 2px;
+}
+
+.popup-notification-description {
+  color: #fff;
+}
+
+.popup-notification-icon {
+  width: 64px;
+  height: 64px;
+  -moz-margin-end: 10px;
+}
+
+.popup-notification-icon[popupid="geolocation"] {
+  list-style-image: url(chrome://browser/skin/Geo.png);
+}
+
+#identity-popup-container,
+#identity-popup-notification-container {
   margin: 4px 3px 2px -30px;
   color: #fff;
 }
 
 #identity-popup-content-box {
   margin-top: 4px;
 }
 
+#identity-popup.verifiedDomain,
+#identity-popup.verifiedIdentity {
+  margin-left: -20px;
+}
+
 /* Popup Buttons */
 #identity-popup-more-info-button {
   @hudButton@
   padding: 1px 9px;
   margin: 10px 0 0;
   min-height: 0px;
 }
 
--- a/browser/themes/pinstripe/browser/jar.mn
+++ b/browser/themes/pinstripe/browser/jar.mn
@@ -32,26 +32,28 @@ browser.jar:
   skin/classic/browser/menu-back.png
   skin/classic/browser/menu-forward.png
   skin/classic/browser/page-livemarks.png
   skin/classic/browser/livemark-item.png
   skin/classic/browser/pageInfo.css
   skin/classic/browser/Popup-blocked.png
   skin/classic/browser/Privacy-16.png
   skin/classic/browser/Privacy-48.png
+  skin/classic/browser/searchbar-dropmarker.png
   skin/classic/browser/searchbar.css
   skin/classic/browser/Search.png
   skin/classic/browser/Search-addengines.png
   skin/classic/browser/section_collapsed.png
   skin/classic/browser/section_expanded.png
   skin/classic/browser/Secure-Glyph-White.png
   skin/classic/browser/Secure-statusbar.png
   skin/classic/browser/Secure-statusbar-broken.png
   skin/classic/browser/Secure-background.gif
   skin/classic/browser/Toolbar.png
+  skin/classic/browser/toolbarbutton-dropmarker.png
   skin/classic/browser/urlbar-favicon-glow.png
   skin/classic/browser/feeds/subscribe.css                  (feeds/subscribe.css)
   skin/classic/browser/feeds/feedIcon.png                   (feeds/feedIcon.png)
   skin/classic/browser/feeds/feedIcon16.png                 (feeds/feedIcon16.png)
   skin/classic/browser/feeds/videoFeedIcon.png              (feeds/videoFeedIcon.png)
   skin/classic/browser/feeds/videoFeedIcon16.png            (feeds/videoFeedIcon16.png)
   skin/classic/browser/feeds/audioFeedIcon.png              (feeds/audioFeedIcon.png)
   skin/classic/browser/feeds/audioFeedIcon16.png            (feeds/audioFeedIcon16.png)
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..bc6d62089dfd43d60c31a50245fc9334bc23d43e
GIT binary patch
literal 145
zc%17D@N?(olHy`uVBq!ia0vp^>_E)I!3HFqj;YoHDb50q$YKTtZeb8+WSBKa0x0P0
z>Eal|A)B0%kl?|Rq^{t`{yXB||Nr*$Cr+Hmsgc~HQZ1%(j!B5Y=oyn}0rN~Fhd(Sw
o*gKn54oIAM!t|&>fLEBA;oBlP&;5%`L6$Ojy85}Sb4q9e0P+?lQvd(}
--- a/browser/themes/pinstripe/browser/searchbar.css
+++ b/browser/themes/pinstripe/browser/searchbar.css
@@ -1,40 +1,46 @@
-.searchbar-engine-image {
-  width: 16px;
-  height: 16px;
-  list-style-image: url("chrome://mozapps/skin/places/defaultFavicon.png");
-  -moz-margin-start: 3px;
+.searchbar-textbox {
+  -moz-border-radius: 100%;
 }
 
 .searchbar-engine-button {
+  -moz-padding-start: 6px;
+  -moz-padding-end: 2px;
+  margin: 0;
+  -moz-margin-end: 2px;
   -moz-appearance: none;
   min-width: 0;
 }
 
-.searchbar-engine-button > .button-box {
-  -moz-appearance: none;
-  padding: 0;
-  -moz-padding-end: 3px;
-  border: 0;
-}
-
-.searchbar-engine-button[addengines="true"] > .button-box {
+.searchbar-engine-button[addengines="true"] {
   background: transparent url(chrome://browser/skin/Search-addengines.png) no-repeat right center;
 }
 
-.searchbar-textbox:-moz-locale-dir(rtl) .searchbar-engine-button[addengines="true"] > .button-box {
+.searchbar-engine-button[addengines="true"]:-moz-locale-dir(rtl) {
   background-position: left center;
 }
 
+.searchbar-textbox > .autocomplete-textbox-container > .textbox-input-box {
+  margin: 0;
+  padding: 3px 0 2px;
+  height: 20px;
+}
+
+.searchbar-engine-image {
+  width: 16px;
+  height: 16px;
+  list-style-image: url("chrome://mozapps/skin/places/defaultFavicon.png");
+}
+
 .searchbar-dropmarker-image {
-  list-style-image: url("chrome://global/skin/arrow/arrow-dn.png");
+  list-style-image: url("chrome://browser/skin/searchbar-dropmarker.png");
   -moz-margin-start: 2px;
-  margin-top: 1px;
 }
 
 .search-go-container {
   -moz-box-align: center;
+  -moz-padding-end: 6px;
 }
 
 .search-go-button {
   list-style-image: url("chrome://browser/skin/Search.png");
 }
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..f4cdb664ba95d3d36ea4074de8dc2e7c4696a931
GIT binary patch
literal 142
zc%17D@N?(olHy`uVBq!ia0vp^>_E)Q!3HEdXMMW?q&N#aB8wRqxP?KOkzv*x380{Z
zr;B3<hir04Xz16(goGPBM_wG5{_@(|=;<-BvEP+WH~dg2+;HRn|Npw1H*NaH;QNz*
nkz-BDQ62+U2_b{f7eWlD_>>vfPV}__n#JJh>gTe~DWM4fwRJ6m
--- a/browser/themes/winstripe/browser/browser-aero.css
+++ b/browser/themes/winstripe/browser/browser-aero.css
@@ -19,16 +19,21 @@
 }
 
 @media all and (-moz-windows-compositor) {
   #main-window:not(:-moz-lwtheme) {
     -moz-appearance: -moz-win-glass;
     background: transparent;
   }
 
+  #main-window:not(:-moz-lwtheme)[inFullscreen="true"] {
+    -moz-appearance: none;
+    background-color: #556;
+  }
+
   #toolbar-menubar:not(:-moz-lwtheme),
   #navigator-toolbox[tabsontop="true"] > #TabsToolbar:not(:-moz-lwtheme),
   #navigator-toolbox:not([tabsontop="true"]) > #nav-bar:not(:-moz-lwtheme),
   #navigator-toolbox:not([tabsontop="true"]) > #nav-bar + #customToolbars + #PersonalToolbar[collapsed="true"] + #TabsToolbar:last-child:not(:-moz-lwtheme) {
     background: transparent !important;
     color: black;
     text-shadow: 0 0 .7em white, 0 0 .7em white, 0 1px 0 rgba(255,255,255,.4);
   }
@@ -97,17 +102,18 @@
     -moz-appearance: -moz-win-browsertabbar-toolbox;
   }
 }
 
 @media all and (-moz-windows-default-theme) {
   /* Bug 413060, comment 16: Vista Aero is a special case where we use a
      tooltip appearance for the address bar popup panels */
   #identity-popup,
-  #editBookmarkPanel {
+  #editBookmarkPanel,
+  #notification-popup {
     -moz-appearance: tooltip;
     color: InfoText;
   }
 
   /* Make the left and right paddings smaller, to compensate for the horizontal
      space added by the tooltip appearance, see bug 432529. */
   #identity-popup-container {
     -moz-padding-start: 6px;
--- a/browser/themes/winstripe/browser/browser.css
+++ b/browser/themes/winstripe/browser/browser.css
@@ -1535,21 +1535,49 @@ toolbarbutton.bookmark-item[dragover="tr
 
 #identity-popup-more-info-button {
   margin-top: 6px;
   margin-bottom: 0;
   -moz-margin-end: 0;
 }
 
 /* Popup Bounding Box */
-#identity-popup {
+#identity-popup,
+#notification-popup {
   -moz-appearance: menupopup;
   color: MenuText;
 }
 
+/* Notification popup */
+#notification-popup {
+  padding: 10px;
+  margin-top: 3px;
+}
+
+.popup-notification-icon {
+  width: 64px;
+  height: 64px;
+  -moz-margin-end: 10px;
+}
+
+.popup-notification-icon[popupid="geolocation"] {
+  list-style-image: url(chrome://browser/skin/Geo.png);
+}
+
+/* Notification icon box */
+#notification-popup-box {
+  margin: 0 3px;
+}
+
+#geo-notification-icon {
+  list-style-image: url(chrome://browser/skin/Geo.png);
+  width: 16px;
+  height: 16px;
+}
+
 #identity-popup-container {
   min-width: 280px;
   padding: 9px;
 }
 
 #download-monitor {
   list-style-image: url("chrome://browser/skin/Toolbar.png");
   -moz-image-region: rect(0, 108px, 18px, 90px);
--- a/build/Makefile.in
+++ b/build/Makefile.in
@@ -66,16 +66,20 @@ DIRS += wince/tools \
 	wince/shunt \
 	$(DEPTH)/memory/mozalloc \
 	$(NULL)
 endif
 endif
 
 DIRS += pgo
 
+ifeq (Android,$(OS_TARGET))
+  DIRS += mobile/sutagent/android
+endif
+
 include $(topsrcdir)/config/rules.mk
 
 # we install to _leaktest/
 TARGET_DEPTH = ..
 include $(srcdir)/automation-build.mk
 
 _LEAKTEST_DIR = $(DEPTH)/_leaktest
 GARBAGE_DIRS += $(_LEAKTEST_DIR)
new file mode 100755
--- /dev/null
+++ b/build/mobile/sutagent/android/ASMozStub.java
@@ -0,0 +1,111 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Android SUTAgent code.
+ *
+ * The Initial Developer of the Original Code is
+ * Bob Moss.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *  Bob Moss <bmoss@mozilla.com>
+ * 
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+package com.mozilla.SUTAgentAndroid.service;
+
+import java.net.ServerSocket;
+import java.util.Timer;
+import com.mozilla.SUTAgentAndroid.RunCmdThread;
+import com.mozilla.SUTAgentAndroid.RunDataThread;
+import android.content.Intent;
+// import android.os.Binder;
+import android.os.IBinder;
+import android.widget.Toast;
+
+public class ASMozStub extends android.app.Service {
+	
+	private ServerSocket cmdChnl;
+	private ServerSocket dataChnl;
+	RunCmdThread runCmdThrd;
+	RunDataThread runDataThrd;
+	Timer	timer;
+//	android.app.Service me;
+//	Binder theBinder = null;
+	
+	@Override
+	public IBinder onBind(Intent intent)
+		{
+//		String sData = intent.getDataString();
+//		return theBinder;
+		return null;
+		}
+	@Override
+	public void onCreate() {
+		super.onCreate();
+//		this.me = this;
+//		theBinder = new Binder();
+		Toast.makeText(this, "Listener Service created...", Toast.LENGTH_LONG).show();
+	}
+
+	public void onStart(Intent intent, int startId) {
+		super.onStart(intent, startId);
+		
+		try {
+			cmdChnl = new ServerSocket(20701);
+			runCmdThrd = new RunCmdThread(cmdChnl);
+			runCmdThrd.start();
+			Toast.makeText(this, "Command channel port 20701 ...", Toast.LENGTH_LONG).show();
+			
+			dataChnl = new ServerSocket(20700);
+			runDataThrd = new RunDataThread(dataChnl);
+			runDataThrd.start();
+			Toast.makeText(this, "Data channel port 20700 ...", Toast.LENGTH_LONG).show();
+			} 
+		catch (Exception e) {
+//			Toast.makeText(getApplication().getApplicationContext(), e.toString(), Toast.LENGTH_LONG).show();
+			}
+		
+		return;
+	}
+	
+	public void onDestroy()
+		{
+		super.onDestroy();
+		if (runCmdThrd.isAlive())
+			{
+			runCmdThrd.StopListening();
+			}
+		
+		if (runDataThrd.isAlive())
+			{
+			runDataThrd.StopListening();
+			}
+		
+		Toast.makeText(this, "Listener Service destroyed...", Toast.LENGTH_LONG).show();
+		}
+
+}
new file mode 100755
--- /dev/null
+++ b/build/mobile/sutagent/android/AlertLooperThread.java
@@ -0,0 +1,88 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Android SUTAgent code.
+ *
+ * The Initial Developer of the Original Code is
+ * Bob Moss.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *  Bob Moss <bmoss@mozilla.com>
+ * 
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+package com.mozilla.SUTAgentAndroid;
+
+import java.util.Timer;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+
+class AlertLooperThread extends Thread
+	{
+	public Handler mHandler;
+	private Looper looper = null;
+	private DoAlert da	= null;
+	private Timer alertTimer = null;
+	
+	public Timer getAlertTimer()
+		{
+		return alertTimer;
+		}
+
+	public void term()
+		{
+		if (da != null)
+			da.term();
+		}
+
+	public void quit()
+		{
+		if (looper != null)
+			looper.quit();
+		}
+
+	public void run()
+		{
+		Looper.prepare();
+    
+		looper = Looper.myLooper();
+      
+		mHandler = new Handler()
+    		{
+			public void handleMessage(Message msg)
+        		{
+				// process incoming messages here
+        		}
+    		};
+      
+    	alertTimer = new Timer();
+    	da = new DoAlert();
+    	alertTimer.scheduleAtFixedRate(da, 0, 5000);
+    	Looper.loop();
+		}
+	}
new file mode 100644
--- /dev/null
+++ b/build/mobile/sutagent/android/AndroidManifest.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+      package="com.mozilla.SUTAgentAndroid"
+      android:versionCode="1"
+      android:versionName="1.0" android:sharedUserId="org.mozilla.sharedID">
+    <application android:icon="@drawable/icon" android:label="@string/app_name" android:debuggable="true">
+        <activity android:name=".SUTAgentAndroid"
+                  android:label="@string/app_name">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+        <receiver android:name=".SUTStartupIntentReceiver">
+            <intent-filter>
+                 <action android:value="android.intent.action.BOOT_COMPLETED" android:name="android.intent.action.BOOT_COMPLETED"/>
+                 <category android:value="android.intent.category.HOME" android:name="android.intent.category.HOME"/>
+            </intent-filter>
+        </receiver>
+        <service android:name=".service.ASMozStub">
+		    <intent-filter>
+			    <action android:name="com.mozilla.SUTAgentAndroid.service.LISTENER_SERVICE" />
+		    </intent-filter>
+	    </service>
+
+    </application>
+    
+    <uses-sdk android:minSdkVersion="5"/>
+
+<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"></uses-permission>
+<uses-permission android:name="android.permission.INTERNET"></uses-permission>
+<uses-permission android:name="android.permission.REBOOT"></uses-permission>
+<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"></uses-permission>
+<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"></uses-permission>
+<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
+<uses-permission android:name="android.permission.RESTART_PACKAGES"></uses-permission>
+<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"></uses-permission>
+<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"></uses-permission>
+<uses-permission android:name="android.permission.CHANGE_CONFIGURATION"></uses-permission>
+<uses-permission android:name="android.permission.READ_PHONE_STATE"></uses-permission>
+<uses-permission android:name="android.permission.BATTERY_STATS"></uses-permission>
+<uses-permission android:name="android.permission.DEVICE_POWER"></uses-permission>
+<uses-permission android:name="android.permission.DISABLE_KEYGUARD"></uses-permission>
+<uses-permission android:name="android.permission.WAKE_LOCK"></uses-permission>
+
+<uses-permission android:name="android.permission.WRITE_SETTINGS"></uses-permission>
+<uses-permission android:name="android.permission.READ_SYNC_SETTINGS"></uses-permission>
+
+<uses-permission android:name="android.permission.BLUETOOTH"></uses-permission>
+
+<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"></uses-permission>
+
+<uses-permission android:name="android.permission.INSTALL_PACKAGES"></uses-permission>
+
+
+
+</manifest> 
\ No newline at end of file
new file mode 100755
--- /dev/null
+++ b/build/mobile/sutagent/android/CmdWorkerThread.java
@@ -0,0 +1,221 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Android SUTAgent code.
+ *
+ * The Initial Developer of the Original Code is
+ * Bob Moss.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *  Bob Moss <bmoss@mozilla.com>
+ * 
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+package com.mozilla.SUTAgentAndroid;
+
+import java.io.BufferedInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.PrintWriter;
+import java.net.Socket;
+import java.net.SocketTimeoutException;
+
+public class CmdWorkerThread extends Thread
+{
+	private RunCmdThread theParent = null;
+	private Socket socket	= null;
+	private String prompt = null;
+	boolean bListening	= true;
+
+	public CmdWorkerThread(RunCmdThread theParent, Socket workerSocket)
+		{
+		super("CmdWorkerThread");
+		this.theParent = theParent;
+		this.socket = workerSocket;
+		byte pr [] = new byte [3];
+		pr[0] = '$';
+		pr[1] = '>';
+		pr[2] = 0;
+		prompt = new String(pr,0,3);
+		}
+
+	public void StopListening()
+		{
+		bListening = false;
+		}
+	
+	private String readLine(BufferedInputStream in)
+		{
+		String sRet = "";
+		int nByte = 0;
+		char cChar = 0;
+		
+		try 
+			{
+			nByte = in.read();
+			while (nByte != -1)
+				{
+				cChar = ((char)(nByte & 0xFF));
+				if ((cChar != '\r') && (cChar != '\n'))
+					sRet += cChar;
+				else
+					break;
+				nByte = in.read();
+				}
+			
+			if ((in.available() > 0) && (cChar != '\n'))
+				{
+				in.mark(1024);
+				nByte = in.read();
+				
+				if (nByte != -1)
+					{
+					cChar = ((char)(nByte & 0xFF));
+					if (cChar != '\n')
+						{
+						in.reset();
+						}
+					}
+/*			
+				while (nByte != -1)
+					{
+					cChar = ((char)(nByte & 0xFF));
+					if ((cChar == '\r') || (cChar == '\n'))
+						{
+						if (in.available() > 0)
+							{
+							in.mark(1024);
+							nByte = in.read();
+							}
+						else
+							nByte = -1;
+						}
+					else
+						{
+						in.reset();
+						break;
+						}
+					}
+*/
+				}
+			}
+		catch (IOException e)
+			{
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+			}
+		
+		if (sRet.length() == 0)
+			sRet = null;
+		
+		return(sRet);
+		}
+
+	public void run()
+		{
+		try {
+			while(bListening)
+				{
+				OutputStream cmdOut = socket.getOutputStream();
+				InputStream cmdIn = socket.getInputStream();
+				PrintWriter out = new PrintWriter(cmdOut, true);
+				BufferedInputStream in = new BufferedInputStream(cmdIn);
+				String inputLine, outputLine;
+				DoCommand dc = new DoCommand();
+
+				int nAvail = cmdIn.available();
+				cmdIn.skip(nAvail);
+				
+				out.print(prompt);
+				out.flush();
+
+				while (bListening)
+					{
+					if (!(in.available() > 0))
+						{
+						socket.setSoTimeout(500);
+						try {
+							int nRead = cmdIn.read();
+							if (nRead == -1)
+								{
+								bListening = false;
+								continue;
+								}
+							else
+								{
+								inputLine = ((char)nRead) + "";
+								socket.setSoTimeout(120000);
+								}
+							}
+						catch(SocketTimeoutException toe)
+							{
+							continue;
+							}
+						}
+					else
+						inputLine = "";
+					
+					if ((inputLine += readLine(in)) != null)
+						{
+						outputLine = dc.processCommand(inputLine, out, in, cmdOut);
+						if (outputLine.length() > 0)
+							{
+							out.print(outputLine + "\n" + prompt);
+							}
+						else
+							out.print(prompt);
+						out.flush();
+						if (outputLine.equals("exit"))
+							{
+							theParent.StopListening();
+							bListening = false;
+							}
+						if (outputLine.equals("quit"))
+							{
+							bListening = false;
+							}
+						outputLine = null;
+						System.gc();
+						}
+					else
+						break;
+					}
+				out.close();
+				out = null;
+				in.close();
+				in = null;
+				socket.close();
+				}
+			}
+		catch (IOException e) {
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+			}
+		}
+
+}
new file mode 100755
--- /dev/null
+++ b/build/mobile/sutagent/android/DataWorkerThread.java
@@ -0,0 +1,202 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Android SUTAgent code.
+ *
+ * The Initial Developer of the Original Code is
+ * Bob Moss.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *  Bob Moss <bmoss@mozilla.com>
+ * 
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+package com.mozilla.SUTAgentAndroid;
+
+import java.io.BufferedInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.PrintWriter;
+import java.net.Socket;
+import java.net.SocketTimeoutException;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+
+public class DataWorkerThread extends Thread
+{
+	private RunDataThread theParent = null;
+	private Socket socket	= null;
+	boolean bListening	= true;
+
+	public DataWorkerThread(RunDataThread theParent, Socket workerSocket)
+		{
+		super("DataWorkerThread");
+		this.theParent = theParent;
+		this.socket = workerSocket;
+		}
+
+	public void StopListening()
+		{
+		bListening = false;
+		}
+
+	private String readLine(BufferedInputStream in)
+		{
+		String sRet = "";
+		int nByte = 0;
+		char cChar = 0;
+	
+		try 
+			{
+			nByte = in.read();
+			while (nByte != -1)
+				{
+				cChar = ((char)(nByte & 0xFF));
+				if ((cChar != '\r') && (cChar != '\n'))
+					sRet += cChar;
+				else
+					break;
+				nByte = in.read();
+				}
+		
+			if (in.available() > 0)
+				{
+				in.mark(1024);
+				nByte = in.read();
+		
+				while (nByte != -1)
+					{
+					cChar = ((char)(nByte & 0xFF));
+					if ((cChar == '\r') || (cChar == '\n'))
+						{
+						if (in.available() > 0)
+							{
+							in.mark(1024);
+							nByte = in.read();
+							}
+						else
+							nByte = -1;
+						}
+					else
+						{
+						in.reset();
+						break;
+						}
+					}
+				}
+			}
+		catch (IOException e)
+			{
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+			}
+	
+		if (sRet.length() == 0)
+			sRet = null;
+	
+		return(sRet);
+		}
+
+	public void run()
+		{
+		String	sRet = "";
+		
+		try {
+			while(bListening)
+				{
+				OutputStream cmdOut = socket.getOutputStream();
+				InputStream cmdIn = socket.getInputStream();
+				PrintWriter out = new PrintWriter(cmdOut, true);
+				BufferedInputStream in = new BufferedInputStream(cmdIn);
+				String inputLine, outputLine;
+				DoCommand dc = new DoCommand();
+				
+	    		Calendar cal = Calendar.getInstance();
+	    		SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd-HH:mm:ss");
+	    		sRet = sdf.format(cal.getTime());
+	    		sRet += " trace output";
+
+				out.println(sRet);
+				out.flush();
+				int nAvail = cmdIn.available();
+				cmdIn.skip(nAvail);
+				
+				((SUTAgentAndroid)SUTAgentAndroid.me).StartHeartBeat(out);
+
+				while (bListening)
+					{
+					if (!(in.available() > 0))
+						{
+						socket.setSoTimeout(500);
+						try {
+							int nRead = cmdIn.read();
+							if (nRead == -1)
+								{
+								bListening = false;
+								continue;
+								}
+							else
+								inputLine = (char)nRead + ""; 
+							}
+						catch(SocketTimeoutException toe)
+							{
+							continue;
+							}
+						}
+					else
+						inputLine = "";
+				
+					if ((inputLine += readLine(in)) != null)
+						{
+						outputLine = dc.processCommand(inputLine, out, in, cmdOut);
+						out.print(outputLine + "\n");
+						out.flush();
+						if (outputLine.equals("exit"))
+							{
+							theParent.StopListening();
+							bListening = false;
+							}
+						}
+					else
+						break;
+					}
+				
+				((SUTAgentAndroid)SUTAgentAndroid.me).StopHeartBeat();
+
+				out.close();
+				in.close();
+				socket.close();
+				}
+			}
+		catch (IOException e)
+			{
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+			}
+		}
+}
new file mode 100755
--- /dev/null
+++ b/build/mobile/sutagent/android/DoAlert.java
@@ -0,0 +1,80 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Android SUTAgent code.
+ *
+ * The Initial Developer of the Original Code is
+ * Bob Moss.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *  Bob Moss <bmoss@mozilla.com>
+ * 
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+package com.mozilla.SUTAgentAndroid;
+
+import java.util.TimerTask;
+
+import android.content.Context;
+import android.media.Ringtone;
+import android.media.RingtoneManager;
+import android.widget.Toast;
+
+class DoAlert extends TimerTask
+	{
+	int	lcv = 0;
+	Toast toast = null;
+	Ringtone rt = null;
+
+	DoAlert()
+		{
+		Context	ctx = SUTAgentAndroid.me.getApplication().getApplicationContext();
+		this.toast = Toast.makeText(ctx, "Help me!", Toast.LENGTH_LONG);
+		rt = RingtoneManager.getRingtone(ctx, RingtoneManager.getDefaultUri(RingtoneManager.TYPE_ALARM));
+		}
+
+	public void term()
+		{
+		if (rt != null)
+			{
+			if (rt.isPlaying())
+				rt.stop();
+			}
+
+		if (toast != null)
+			toast.cancel();
+		}
+
+	public void run ()
+		{
+		String sText =(((lcv++ % 2) == 0)  ? "Help me!" : "I've fallen down!" );
+		toast.setText(sText);
+		toast.show();
+		if (rt != null)
+			rt.play();
+		}
+	}
new file mode 100755
--- /dev/null
+++ b/build/mobile/sutagent/android/DoCommand.java
@@ -0,0 +1,2476 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Android SUTAgent code.
+ *
+ * The Initial Developer of the Original Code is
+ * Bob Moss.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *  Bob Moss <bmoss@mozilla.com>
+ * 
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+package com.mozilla.SUTAgentAndroid;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.BufferedReader;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.PrintWriter;
+import java.net.Socket;
+import java.net.SocketException;
+import java.net.UnknownHostException;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.List;
+import java.util.Timer;
+import java.util.zip.Adler32;
+import java.util.zip.CheckedInputStream;
+import java.util.zip.CheckedOutputStream;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+import java.util.zip.ZipInputStream;
+import java.util.zip.ZipOutputStream;
+
+import org.apache.commons.net.ftp.FTP;
+import org.apache.commons.net.ftp.FTPClient;
+import org.apache.commons.net.ftp.FTPFile;
+import org.apache.commons.net.ftp.FTPReply;
+import org.apache.http.HttpResponse;
+import org.apache.http.HttpStatus;
+import org.apache.http.client.ClientProtocolException;
+import org.apache.http.client.HttpClient;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.impl.client.DefaultHttpClient;
+
+import android.app.Activity;
+import android.app.ActivityManager;
+import android.content.ActivityNotFoundException;
+import android.content.Context;
+import android.content.ContextWrapper;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.net.Uri;
+import android.os.Build;
+import android.os.Environment;
+import android.os.StatFs;
+import android.os.SystemClock;
+import android.util.DisplayMetrics;
+import android.util.Log;
+
+public class DoCommand {
+	
+	String lineSep = System.getProperty("line.separator");
+	Process	pProc;
+	OutputStream sutIn;
+	InputStream	sutErr;
+	InputStream	sutOut;
+//	Timer alertTimer = null;
+	AlertLooperThread alrt = null;
+	
+	String	currentDir = "/";
+	
+	public enum Command
+		{
+		RUN ("run"),
+		EXEC ("exec"),
+		ARUN ("arun"),
+		KILL ("kill"),
+		PS ("ps"),
+		DEVINFO ("info"),
+		OS ("os"),
+		ID ("id"),
+		UPTIME ("uptime"),
+		SYSTIME ("systime"),
+		SCREEN ("screen"),
+		MEMORY ("memory"),
+		POWER ("power"),
+		PROCESS ("process"),
+		GETAPPROOT ("getapproot"),
+		TESTROOT ("testroot"),
+		ALRT ("alrt"),
+		DISK ("disk"),
+		CP ("cp"),
+		TIME ("time"),
+		HASH ("hash"),
+		CD ("cd"),
+		CAT ("cat"),
+		CWD ("cwd"),
+		MV ("mv"),
+		PUSH ("push"),
+		RM ("rm"),
+		PRUNE ("rmdr"),
+		MKDR ("mkdr"),
+		DIRWRITABLE ("dirw"),
+		DEAD ("dead"),
+		MEMS ("mems"),
+		LS ("ls"),
+		TMPD ("tmpd"),
+		PING ("ping"),
+		REBT ("rebt"),
+		UNZP ("unzp"),
+		ZIP ("zip"),
+		CLOK ("clok"),
+		STAT ("stat"),
+		QUIT ("quit"),
+		EXIT ("exit"),
+		HELP ("help"),
+		FTPG ("ftpg"),
+		FTPP ("ftpp"),
+		INST ("inst"),
+		UNINST ("uninst"),
+		TEST ("test"),
+		UNKNOWN ("unknown");
+		
+		private final String theCmd;
+		
+		Command(String theCmd) { this.theCmd = theCmd; }
+
+		public String theCmd() {return theCmd;}
+		
+		public static Command getCmd(String sCmd)
+			{
+			Command retCmd = UNKNOWN;
+			for (Command cmd : Command.values())
+				{
+				if (cmd.theCmd().equalsIgnoreCase(sCmd))
+					{
+					retCmd = cmd;
+					break;
+					}
+				}
+			return (retCmd);
+			}
+		}
+	
+//	public String processCommand(String theCmdLine, PrintWriter out, BufferedReader in, OutputStream cmdOut, InputStream cmdIn)
+	public String processCommand(String theCmdLine, PrintWriter out, BufferedInputStream in, OutputStream cmdOut)
+		{
+		String 	strReturn = "";
+		Command	cCmd = null;
+		Command cSubCmd = null;
+		
+		String [] Argv = parseCmdLine(theCmdLine);
+		
+		int Argc = Argv.length;
+		
+		cCmd = Command.getCmd(Argv[0]);
+		
+		switch(cCmd)
+			{
+			case CWD:
+				try {
+					strReturn = new java.io.File(currentDir).getCanonicalPath();
+					} 
+				catch (IOException e)
+					{
+					e.printStackTrace();
+					}
+				break;
+				
+			case CD:
+				if (Argc == 2)
+					strReturn = changeDir(Argv[1]);
+				else
+					strReturn = "Wrong number of arguments for cd command!";
+				break;
+			
+			case LS:
+				strReturn = PrintDir(((Argc > 1) ? Argv[1] : currentDir));
+				break;
+				
+			case GETAPPROOT:
+				if (Argc == 2)
+					strReturn = GetAppRoot(Argv[1]);
+				else
+					strReturn = "Wrong number of arguments for cd command!";
+				break;
+				
+			case TESTROOT:
+				strReturn = GetTestRoot();
+				break;
+				
+			case DEAD:
+				if (Argc == 2)
+					strReturn = (IsProcessDead(Argv[1]) ? (Argv[1] + " is hung or unresponsive") : (Argv[1] + " is ok"));
+				else
+					strReturn = "Wrong number of arguments for dead command!";
+				break;
+				
+			case PS:
+				strReturn = GetProcessInfo();
+				break;
+				
+			case PUSH:
+				if (Argc == 3)
+					{
+					long lArg = 0;
+				    try
+				    	{
+				        lArg = Long.parseLong(Argv[2].trim());
+				        System.out.println("long l = " + lArg);
+				    	}
+				    catch (NumberFormatException nfe)
+				    	{
+				        System.out.println("NumberFormatException: " + nfe.getMessage());
+				    	}
+					
+					strReturn = Push(Argv[1], in, lArg);
+					}
+				else
+					strReturn = "Wrong number of arguments for push command!";
+				break;
+				
+			case INST:
+				if (Argc == 2)
+					strReturn = InstallApp(Argv[1], cmdOut);
+				else
+					strReturn = "Wrong number of arguments for inst command!";
+				break;
+				
+			case UNINST:
+				if (Argc == 2)
+					strReturn = UnInstallApp(Argv[1], cmdOut);
+				else
+					strReturn = "Wrong number of arguments for inst command!";
+				break;
+				
+			case ALRT:
+				if (Argc == 2)
+					{
+					if (Argv[1].contentEquals("on"))
+						{
+						StartAlert();
+						}
+					else
+						{
+						StopAlert();
+						}
+					}
+				else
+					{
+					strReturn = "Wrong number of arguments for alrt command!";
+					}
+				break;
+				
+			case REBT:
+//				try {
+//					reboot(null);
+//					Power.reboot(null);
+//					Power.shutdown();
+//					}
+//				catch (IOException e)
+//					{
+					// TODO Auto-generated catch block
+//					e.printStackTrace();
+//					}
+				RunReboot(cmdOut);
+				break;
+				
+			case TMPD:
+				strReturn = GetTmpDir();
+				break;
+				
+			case DEVINFO:
+				if (Argc == 1)
+					{
+					strReturn += SUTAgentAndroid.sUniqueID;
+					strReturn += "\n";
+					strReturn += GetOSInfo();
+					strReturn += "\n";
+					strReturn += GetSystemTime();
+					strReturn += "\n";
+					strReturn += GetUptime();
+					strReturn += "\n";
+					strReturn += GetScreenInfo();
+					strReturn += "\n";
+					strReturn += GetMemoryInfo();
+					strReturn += "\n";
+					strReturn += GetPowerInfo();
+					strReturn += "\n";
+					strReturn += GetProcessInfo();
+					}
+				else
+					{
+					cSubCmd = Command.getCmd(Argv[1]);
+					switch(cSubCmd)
+						{
+						case ID:
+							strReturn = SUTAgentAndroid.sUniqueID;
+							break;
+							
+						case SCREEN:
+							strReturn = GetScreenInfo();
+							break;
+							
+						case PROCESS:
+							strReturn = GetProcessInfo();
+							break;
+							
+						case OS:
+							strReturn = GetOSInfo();
+							break;
+							
+						case SYSTIME:
+							strReturn = GetSystemTime();
+							break;
+							
+						case UPTIME:
+							strReturn = GetUptime();
+							break;
+							
+						case MEMORY:
+							strReturn = GetMemoryInfo();
+							break;
+							
+						case POWER:
+							strReturn += GetPowerInfo();
+							break;
+							
+						default:
+							break;
+						}
+					}
+				break;
+				
+			case STAT:
+				if (Argc == 2)
+					strReturn = StatProcess(Argv[1]);
+				else
+					strReturn = "Wrong number of arguments for ping command!";
+				break;
+				
+			case PING:
+				if (Argc == 2)
+					strReturn = SendPing(Argv[1], cmdOut);
+				else
+					strReturn = "Wrong number of arguments for ping command!";
+				break;
+				
+			case HASH:
+				if (Argc == 2)
+					strReturn = HashFile(Argv[1]);
+				else
+					strReturn = "Wrong number of arguments for hash command!";
+				break;
+				
+			case PRUNE:
+				if (Argc == 2)
+					strReturn = PruneDir(Argv[1]);
+				else
+					strReturn = "Wrong number of arguments for prune command!";
+				break;
+				
+			case FTPG:
+				if (Argc == 4)
+					strReturn = FTPGetFile(Argv[1], Argv[2], Argv[3], cmdOut);
+				else
+					strReturn = "Wrong number of arguments for ftpg command!";
+				break;
+				
+			case CAT:
+				if (Argc == 2)
+					strReturn = Cat(Argv[1], cmdOut);
+				else
+					strReturn = "Wrong number of arguments for cat command!";
+				break;
+				
+			case DIRWRITABLE:
+				if (Argc == 2)
+					strReturn = IsDirWritable(Argv[1]);
+				else
+					strReturn = "Wrong number of arguments for dirwritable command!";
+				break;
+				
+			case TIME:
+				if (Argc == 2)
+					strReturn = PrintFileTimestamp(Argv[1]);
+				else
+					strReturn = "Wrong number of arguments for time command!";
+				break;
+				
+			case MKDR:
+				if (Argc == 2)
+					strReturn = MakeDir(Argv[1]);
+				else
+					strReturn = "Wrong number of arguments for mkdr command!";
+				break;
+				
+			case RM:
+				if (Argc == 2)
+					strReturn = RemoveFile(Argv[1]);
+				else
+					strReturn = "Wrong number of arguments for mkdr command!";
+				break;
+				
+			case MV:
+				if (Argc == 3)
+					strReturn = Move(Argv[1], Argv[2]);
+				else
+					strReturn = "Wrong number of arguments for mv command!";
+				break;
+				
+			case CP:
+				if (Argc == 3)
+					strReturn = CopyFile(Argv[1], Argv[2]);
+				else
+					strReturn = "Wrong number of arguments for cp command!";
+				break;
+				
+			case QUIT:
+			case EXIT:
+				strReturn = Argv[0];
+				break;
+				
+			case TEST:
+//				boolean bRet = false;
+/*				
+				byte[] buffer = new byte [4096];
+				int	nRead = 0;
+				long lTotalRead = 0;
+
+				Context ctx = SUTAgentAndroid.me.getApplicationContext();
+
+				FTPClient ftp = new FTPClient();
+				try 
+					{
+					String strRet = "";
+					int	reply = 0;
+					FileOutputStream outStream = null;
+					
+					ftp.connect("ftp.mozilla.org");
+					strRet = ftp.getReplyString();
+					reply = ftp.getReplyCode();
+					
+				    if(!FTPReply.isPositiveCompletion(reply))
+				    	{
+				        ftp.disconnect();
+				        System.err.println("FTP server refused connection.");
+				        System.exit(1);
+				        }
+				    // transfer files
+				    
+				    ftp.login("anonymous", "b@t.com");
+					strRet = ftp.getReplyString();
+					reply = ftp.getReplyCode();
+					
+				    if(!FTPReply.isPositiveCompletion(reply))
+				    	{
+				        ftp.disconnect();
+				        System.err.println("FTP server refused connection.");
+				        System.exit(1);
+				        }
+				    
+				    ftp.enterLocalPassiveMode();
+				    
+				    if (ftp.setFileType(FTP.BINARY_FILE_TYPE))
+				    	{
+				    	File root = Environment.getExternalStorageDirectory();
+				    	if (root.canWrite())
+				    		{
+				    		File outFile = new File(root, "firefox-3.6b4.cab");
+				    		outStream = new FileOutputStream(outFile);
+				    		}
+				    	else
+				    		outStream = ctx.openFileOutput("firefox-3.6b4.cab", Context.MODE_WORLD_READABLE | Context.MODE_WORLD_WRITEABLE);
+//				    	outStream = new FileOutputStream("/sdcard/firefox-3.6b4.cab");
+				    	InputStream ftpIn = ftp.retrieveFileStream("pub/mozilla.org/firefox/releases/3.6b4/wince-arm/en-US/firefox-3.6b4.cab");
+						while ((nRead = ftpIn.read(buffer)) != -1)
+							{
+							lTotalRead += nRead;
+							outStream.write(buffer, 0, nRead);
+							strRet = "\r" + lTotalRead + " bytes received";
+							cmdOut.write(strRet.getBytes());
+							cmdOut.flush();
+							}
+						
+						ftpIn.close();
+						boolean bRet = ftp.completePendingCommand();
+						outStream.flush();
+
+				    	/*				    	
+				    	if (ftp.retrieveFile("pub/mozilla.org/firefox/releases/3.6b4/wince-arm/en-US/firefox-3.6b4.cab", outStream))
+				    		{
+				    		outStream.flush();
+				    		}
+				    	 * /				    		
+			    		outStream.close();
+						strRet = ftp.getReplyString();
+						reply = ftp.getReplyCode();
+				    	}
+					strRet = ftp.getReplyString();
+					reply = ftp.getReplyCode();
+				    ftp.logout();
+				    
+				    strReturn = "\r\n" + strRet; 
+					}
+				catch (SocketException e)
+					{
+					// TODO Auto-generated catch block
+					strReturn = e.getMessage();
+					e.printStackTrace();
+					}
+				catch (IOException e)
+					{
+					// TODO Auto-generated catch block
+					strReturn = e.getMessage();
+					e.printStackTrace();
+					}
+*/				
+//				strReturn = InstallApplication();
+				strReturn = InstallApp(Argv[1], cmdOut);
+				
+//				strReturn = UninstallApplication();
+//				String sPingCheck = SendPing("www.mozilla.org",null);
+//				if (sPingCheck.contains("3 received"))
+//					strReturn = sPingCheck;
+//				RunReboot(cmdOut);
+/*
+				try 
+					{
+					FileOutputStream outFile = ctx.openFileOutput("test.txt", Context.MODE_WORLD_READABLE | Context.MODE_WORLD_WRITEABLE);
+					OutputStreamWriter outS = new OutputStreamWriter(outFile);
+					outS.write("Hello world 1" + lineSep);
+					outS.write("Hello world 2" + lineSep);
+					outS.write("Hello world 3" + lineSep);
+					outS.write("Hello world 4" + lineSep);
+					outS.flush();
+					outS.close();
+					
+					String [] files = ctx.fileList();
+					File aFile   = ctx.getFilesDir();
+					String aPath = aFile.getCanonicalPath();
+					String hold = aFile.getName();
+					
+					strReturn = PrintDir(aPath);
+					strReturn += "\r\n";
+					
+					String src = aPath + "/test.txt";
+					String dst = aPath + "/test2.txt";
+					strReturn += CopyFile(src, dst);
+					strReturn += "\r\n";
+					
+					strReturn += PrintDir(aPath);
+					strReturn += "\r\n";
+					
+					dst = aPath + "/test3.txt";
+					strReturn += Move(src, dst);
+					strReturn += "\r\n";
+					
+					strReturn += PrintDir(aPath);
+					strReturn += "\r\n";
+
+					src = aPath + "/test2.txt";
+					strReturn += RemoveFile(src);
+					strReturn += "\r\n";
+					strReturn += RemoveFile(dst);
+					strReturn += "\r\n";
+					strReturn += PrintDir(aPath);
+					}
+				catch (FileNotFoundException e)
+					{
+					// TODO Auto-generated catch block
+					e.printStackTrace();
+					} 
+				catch (IOException e) 
+					{
+					// TODO Auto-generated catch block
+					e.printStackTrace();
+					}
+*/
+				break;
+				
+			case EXEC:
+			case RUN:
+				if (Argc >= 2)
+					{
+					String [] theArgs = new String [Argc - 1];
+				
+					for (int lcv = 1; lcv < Argc; lcv++)
+						{
+						theArgs[lcv - 1] = Argv[lcv];
+						}
+				
+					if (Argv[1].contains("/") || Argv[1].contains("\\") || !Argv[1].contains("."))
+						strReturn = StartPrg(theArgs, cmdOut);
+					else
+						strReturn = StartJavaPrg(theArgs);
+					}
+				else
+					{
+					strReturn = "Wrong number of arguments for " + Argv[0] + " command!";
+					}
+				break;
+
+			case KILL:
+				if (Argc == 2)
+//					strReturn = NewKillProc(Argv[1], Argv[2], cmdOut);
+//					strReturn = NewKillProc(Argv[1], cmdOut);
+					strReturn = KillProcess(Argv[1], cmdOut);
+				else
+					strReturn = "Wrong number of arguments for kill command!";
+				break;
+				
+			case DISK:
+				strReturn = GetDiskInfo((Argc == 2 ? Argv[1] : "/"));
+				break;
+				
+			case UNZP:
+				strReturn = Unzip(Argv[1], (Argc == 3 ? Argv[2] : ""));
+				break;
+				
+			case ZIP:
+				strReturn = Zip(Argv[1], (Argc == 3 ? Argv[2] : ""));
+				break;
+				
+			case HELP:
+				strReturn = PrintUsage();
+				break;
+				
+			default:
+				strReturn = "[" + Argv[0] + "] command";
+				if (Argc > 1)
+					{
+					strReturn += " with arg(s) =";
+					for (int lcv = 1; lcv < Argc; lcv++)
+						{
+						strReturn += " [" + Argv[lcv] + "]";
+						}
+					}
+				strReturn += " is currently not implemented.";
+				break;
+			}
+		
+		return(strReturn);
+		}
+/*
+	class AlertLooperThread extends Thread
+		{
+	    public Handler mHandler;
+	    private Looper looper = null;
+	    private DoAlert da	= null;
+	    
+	    public void term()
+	    	{
+	    	if (da != null)
+	    		da.term();
+	    	}
+	    
+	    public void quit()
+	    	{
+	    	if (looper != null)
+	    		looper.quit();
+	    	}
+	    
+	    public void run()
+	    	{
+	        Looper.prepare();
+	        
+	        looper = Looper.myLooper();
+	          
+	        mHandler = new Handler()
+	        	{
+	            public void handleMessage(Message msg)
+	            	{
+	                  // process incoming messages here
+	            	}
+	        	};
+	          
+			alertTimer = new Timer();
+			da = new DoAlert();
+    		alertTimer.scheduleAtFixedRate(da, 0, 5000);
+    		Looper.loop();
+	    	}
+		}
+	
+	class DoAlert extends TimerTask
+		{
+		int	lcv = 0;
+		Toast toast = null;
+		Ringtone rt = null;
+		
+		DoAlert()
+			{
+			Context	ctx = SUTAgentAndroid.me.getApplication().getApplicationContext();
+			this.toast = Toast.makeText(ctx, "Help me!", Toast.LENGTH_LONG);
+			rt = RingtoneManager.getRingtone(ctx, RingtoneManager.getDefaultUri(RingtoneManager.TYPE_ALARM));
+			}
+		
+		public void term()
+			{
+			if (rt != null)
+				{
+				if (rt.isPlaying())
+					rt.stop();
+				}
+			
+			if (toast != null)
+				toast.cancel();
+			}
+	
+		public void run ()
+			{
+			String sText =(((lcv++ % 2) == 0)  ? "Help me!" : "I've fallen down!" );
+			toast.setText(sText);
+			toast.show();
+			if (rt != null)
+				rt.play();
+			}
+		}
+*/
+	public void StartAlert()
+		{
+		// start the alert message
+		alrt = new AlertLooperThread();
+		alrt.start();
+		}
+
+	public void StopAlert()
+		{
+		if (alrt == null)
+			return;
+		
+		Timer alertTimer = alrt.getAlertTimer();
+		// stop the alert message
+		if (alertTimer != null)
+			{
+			// Kill the timer
+			alertTimer.cancel();
+			alertTimer.purge();
+			alertTimer = null;
+			// Clear any messages either queued or on screen
+			alrt.term();
+			// Give the messages a chance to be processed
+			try {
+				Thread.sleep(1000);
+				}
+			catch (InterruptedException e)
+				{
+				e.printStackTrace();
+				}
+			// Kill the thread
+			alrt.quit();
+			alrt = null;
+			System.gc();
+			}
+		}
+
+	public String [] parseCmdLine(String theCmdLine) {
+		String	workingString;
+		String	workingString2;
+		List<String> lst = new ArrayList<String>();
+		int nLength = theCmdLine.length();
+		int nFirstSpace = theCmdLine.indexOf(' ');
+		
+		if (nFirstSpace == -1)
+			{
+			String [] theArgs = new String [1];
+			theArgs[0] = new String(theCmdLine);
+			return(theArgs);
+			}
+		
+		// Get the command
+		lst.add(new String(theCmdLine.substring(0, nFirstSpace)));
+		
+		// Jump past the command and trim
+		workingString = (theCmdLine.substring(nFirstSpace + 1, nLength)).trim();
+		
+		while ((nLength = workingString.length()) > 0)
+			{
+			int nEnd = 0;
+			int	nStart = 0;
+			
+			// if we have a quote
+			if (workingString.startsWith("\""))
+				{
+				// point to the first non quote char
+				nStart = 1;
+				// find the matching quote
+				nEnd = workingString.indexOf('"', nStart);
+				// there isn't one
+				if (nEnd == -1)
+					{
+					// point at the quote
+					nStart = 0;
+					// so find the next space
+					nEnd = workingString.indexOf(' ', nStart);
+					// there isn't one of those either
+					if (nEnd == -1)
+						nEnd = nLength;	// Just grab the rest of the cmdline
+					}
+				}
+			else // no quote so find the next space
+				{
+				nEnd = workingString.indexOf(' ', nStart);
+				// there isn't one of those
+				if (nEnd == -1)
+					nEnd = nLength;	// Just grab the rest of the cmdline
+				}
+			
+			// get the substring
+			workingString2 = workingString.substring(nStart, nEnd);
+			
+			// add it to the list
+			lst.add(new String(workingString2));
+			
+			// if we are dealing with a quote
+			if (nStart > 0)
+				nEnd++; //  point past the end one
+			
+			// jump past the substring and trim it
+			workingString = (workingString.substring(nEnd)).trim();
+			}
+		
+		int nItems = lst.size();
+		
+		String [] theArgs = new String [nItems];
+		
+		for (int lcv = 0; lcv < nItems; lcv++)
+			{
+			theArgs[lcv] = lst.get(lcv);
+			}
+	
+		return(theArgs);
+		}
+	
+	public String fixFileName(String fileName)
+		{
+		String	sRet = "";
+		String	sTmpFileName = "";
+		
+		sRet = fileName.replace('\\', '/');
+		
+		if (sRet.startsWith("/"))
+			sTmpFileName = sRet;
+		else
+			sTmpFileName = currentDir + "/" + sRet;
+		
+		sRet = sTmpFileName.replace('\\', '/');
+		sTmpFileName = sRet;
+		sRet = sTmpFileName.replace("//", "/");
+		
+		return(sRet);
+		}
+	
+	public String AddFilesToZip(ZipOutputStream out, String baseDir, String relDir)
+	{
+		final int 			BUFFER 	= 2048;
+		String				sRet	= "";
+		String 				curDir 	= "";
+		String				relFN	= "";
+		BufferedInputStream origin = null;
+	    byte 				data[] = new byte[BUFFER];
+	    
+	    if (relDir.length() > 0)
+	    	curDir = baseDir + "/" + relDir;
+	    else
+	    	curDir = baseDir;
+	    
+		File f = new File(curDir);
+		
+		if (f.isFile())
+			{
+		    try {
+		    	relFN = ((relDir.length() > 0) ? relDir + "/" + f.getName() : f.getName());
+		    	System.out.println("Adding: "+relFN);
+		    	sRet += "Adding: "+	relFN + lineSep;
+		    	FileInputStream fi = new FileInputStream(curDir);
+		    	origin = new BufferedInputStream(fi, BUFFER);
+		    	ZipEntry entry = new ZipEntry(relFN);
+		    	out.putNextEntry(entry);
+		    	int count;
+		    	while((count = origin.read(data, 0, BUFFER)) != -1)
+        			{
+		    		out.write(data, 0, count);
+        			}
+		    	origin.close();
+				}
+		    catch(Exception e)
+		    	{
+			    e.printStackTrace();
+		    	}
+		    
+		    return(sRet);
+			}
+		
+		String	files[] = f.list();
+		
+		if (files != null)
+			{
+			try {
+				for(int i = 0; i < files.length; i++)
+					{
+					f = new File(curDir + "/" + files[i]);
+					if (f.isDirectory())
+						{
+						if (relDir.length() > 0)
+							sRet += AddFilesToZip(out, baseDir, relDir + "/" + files[i]);
+						else
+							sRet += AddFilesToZip(out, baseDir, files[i]);
+						}
+					else
+						{
+						relFN = ((relDir.length() > 0) ? relDir + "/" + files[i] : files[i]);
+						System.out.println("Adding: "+relFN);
+						sRet += "Adding: "+	relFN + lineSep;
+						FileInputStream fi = new FileInputStream(curDir + "/" + files[i]);
+						origin = new BufferedInputStream(fi, BUFFER);
+						ZipEntry entry = new ZipEntry(relFN);
+						out.putNextEntry(entry);
+						int count;
+						while((count = origin.read(data, 0, BUFFER)) != -1)
+		        			{
+							out.write(data, 0, count);
+		        			}
+						origin.close();
+						}
+					}
+	    		}
+			catch(Exception e)
+	    		{
+				e.printStackTrace();
+	    		}
+			}
+
+		return(sRet);
+	}
+	
+	public String Zip(String zipFileName, String srcName)
+		{
+		String	fixedZipFileName = fixFileName(zipFileName);
+		String	fixedSrcName = fixFileName(srcName);
+		String sRet = "";
+		
+		try {
+		    FileOutputStream dest = new FileOutputStream(fixedZipFileName);
+		    CheckedOutputStream checksum = new CheckedOutputStream(dest, new Adler32());
+		    ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(checksum));
+		    out.setMethod(ZipOutputStream.DEFLATED);
+		    
+		    sRet += AddFilesToZip(out, fixedSrcName, "");
+		    
+		    out.close();
+		    System.out.println("checksum:		           "+checksum.getChecksum().getValue());
+	        sRet += "checksum:		           "+checksum.getChecksum().getValue();
+		    }
+		catch(Exception e)
+			{
+		    e.printStackTrace();
+		    }
+		
+		return(sRet);
+	}
+
+	public String Unzip(String zipFileName, String dstDirectory)
+		{
+		String 	sRet = "";
+		String	fixedZipFileName = fixFileName(zipFileName);
+		String	fixedDstDirectory = fixFileName(dstDirectory);
+		String	dstFileName = "";
+		int		nNumExtracted = 0;
+		boolean bRet = false;
+		
+		try {
+			final int BUFFER = 2048;
+			BufferedOutputStream dest = null;
+			ZipFile zipFile = new ZipFile(fixedZipFileName);
+			int nNumEntries = zipFile.size();
+			zipFile.close();
+			
+			FileInputStream fis = new FileInputStream(fixedZipFileName);
+			CheckedInputStream checksum = new CheckedInputStream(fis, new Adler32());
+			ZipInputStream zis = new ZipInputStream(new BufferedInputStream(checksum));
+			ZipEntry entry;
+
+			byte [] data = new byte[BUFFER];
+			
+			while((entry = zis.getNextEntry()) != null)
+        		{
+				System.out.println("Extracting: " + entry);
+//				sRet += "Extracting: " + entry;
+				int count;
+//				byte [] data = new byte[BUFFER];
+				// write the files to the disk
+				if (fixedDstDirectory.length() > 0)
+					dstFileName = fixedDstDirectory + "/" + entry.getName();
+				else
+					dstFileName = entry.getName();
+				
+				String tmpDir = dstFileName.substring(0, dstFileName.lastIndexOf('/'));
+				File tmpFile = new File(tmpDir);
+				if (!tmpFile.exists())
+					{
+					bRet = tmpFile.mkdirs();
+					}
+				else
+					bRet = true;
+				
+				if (bRet)
+					{
+					FileOutputStream fos = new FileOutputStream(dstFileName);
+					dest = new BufferedOutputStream(fos, BUFFER);
+					while ((count = zis.read(data, 0, BUFFER)) != -1)
+        				{
+						dest.write(data, 0, count);
+        				}
+					dest.flush();
+					dest.close();
+					dest = null;
+					fos.close();
+					fos = null;
+//					sRet += " - succeded" + lineSep;
+					nNumExtracted++;
+					}
+				else
+					sRet += " - failed" + lineSep;
+				
+//				data = null;
+        		}
+			
+			data = null;
+			zis.close();
+			System.out.println("Checksum:          "+checksum.getChecksum().getValue());
+			sRet += "Checksum:          "+checksum.getChecksum().getValue();
+			sRet += lineSep + nNumExtracted + " of " + nNumEntries + " sucessfully extracted";
+			}
+		catch(Exception e)
+			{
+			e.printStackTrace();
+			}
+		
+		return(sRet);
+		}
+	
+	public String StatProcess(String string)
+		{
+		String sRet = "";
+		ActivityManager aMgr = (ActivityManager) SUTAgentAndroid.me.getSystemService(Activity.ACTIVITY_SERVICE);
+		int	[] nPids = new int [1];
+		
+		nPids[0] = Integer.parseInt(string);
+		
+		android.os.Debug.MemoryInfo[] mi = aMgr.getProcessMemoryInfo(nPids);
+		
+		sRet  = "Dalvik Private Dirty pages         " + mi[0].dalvikPrivateDirty     + " kb\n";
+		sRet += "Dalvik Proportional Set Size       " + mi[0].dalvikPss              + " kb\n";
+		sRet += "Dalvik Shared Dirty pages          " + mi[0].dalvikSharedDirty      + " kb\n\n";
+		sRet += "Native Private Dirty pages heap    " + mi[0].nativePrivateDirty     + " kb\n";
+		sRet += "Native Proportional Set Size heap  " + mi[0].nativePss              + " kb\n";
+		sRet += "Native Shared Dirty pages heap     " + mi[0].nativeSharedDirty      + " kb\n\n";
+		sRet += "Other Private Dirty pages          " + mi[0].otherPrivateDirty      + " kb\n";
+		sRet += "Other Proportional Set Size        " + mi[0].otherPss               + " kb\n";
+		sRet += "Other Shared Dirty pages           " + mi[0].otherSharedDirty       + " kb\n\n";
+		sRet += "Total Private Dirty Memory         " + mi[0].getTotalPrivateDirty() + " kb\n";
+		sRet += "Total Proportional Set Size Memory " + mi[0].getTotalPss()          + " kb\n";
+		sRet += "Total Shared Dirty Memory          " + mi[0].getTotalSharedDirty()  + " kb";
+		
+		
+		return(sRet);
+		}
+	
+	public String GetTestRoot()
+		{
+		String	sRet = null;
+		
+		if (Environment.getExternalStorageState().equalsIgnoreCase(Environment.MEDIA_MOUNTED))
+			{
+			sRet = Environment.getExternalStorageDirectory().getAbsolutePath();
+			}
+		else
+			{
+			sRet = GetTmpDir();			
+			}
+		
+		return(sRet);
+		}
+	
+	public String GetAppRoot(String AppName)
+		{
+		String sRet = "";
+		Context ctx = SUTAgentAndroid.me.getApplicationContext();
+		
+		if (ctx != null)
+			{
+			try {
+				Context appCtx = ctx.createPackageContext(AppName, 0);
+				ContextWrapper appCtxW = new ContextWrapper(appCtx);
+				sRet = appCtxW.getPackageResourcePath();
+				appCtxW = null;
+				appCtx = null;
+				ctx = null;
+				System.gc();
+				}
+			catch (NameNotFoundException e)
+				{
+				e.printStackTrace();
+				}
+			}
+		return(sRet);
+		}
+
+	public String changeDir(String newDir)
+		{
+		String	tmpDir	= fixFileName(newDir);
+		String	sRet = "Couldn't change directory to " + tmpDir;
+		
+		File tmpFile = new java.io.File(tmpDir);
+		
+		if (tmpFile.exists())
+			{
+			try {
+				currentDir = tmpFile.getCanonicalPath();
+				sRet = "";
+				}
+			catch (IOException e)
+				{
+				// TODO Auto-generated catch block
+				e.printStackTrace();
+				}
+			}
+		
+		return(sRet);
+		}
+	
+	static final String HEXES = "0123456789abcdef";
+	
+	public static String getHex( byte [] raw )
+		{
+	    if ( raw == null )
+	    	{
+	    	return null;
+	    	}
+	    
+	    final StringBuilder hex = new StringBuilder( 2 * raw.length );
+	    for ( final byte b : raw )
+	    	{
+	    	hex.append(HEXES.charAt((b & 0xF0) >> 4)).append(HEXES.charAt((b & 0x0F)));
+	    	}
+	    return hex.toString();
+		}
+
+	public String HashFile(String fileName)
+		{
+		String			sTmpFileName = fixFileName(fileName);
+		String			sRet 		= "Couldn't calculate hash for file " + sTmpFileName;
+		byte[] 			buffer 		= new byte [4096];
+		int				nRead 		= 0;
+		long 			lTotalRead 	= 0;
+		MessageDigest	digest 		= null;
+		
+		try {
+			digest = java.security.MessageDigest.getInstance("MD5");
+			}
+		catch (NoSuchAlgorithmException e) {
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+			}
+		
+		try {
+			FileInputStream srcFile  = new FileInputStream(sTmpFileName);
+			while((nRead = srcFile.read(buffer)) != -1)
+				{
+				digest.update(buffer, 0, nRead);
+				lTotalRead += nRead;
+				}
+			srcFile.close();
+			byte [] hash = digest.digest();
+			
+			sRet = getHex(hash);
+			}
+		catch (FileNotFoundException e)
+			{
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+			}
+		catch (IOException e)
+			{
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+			} 
+		return(sRet);
+		}
+	
+	public String RemoveFile(String fileName)
+		{
+		String	sTmpFileName = fixFileName(fileName);
+		String	sRet = "Couldn't delete file " + sTmpFileName;
+		
+		File f = new File(sTmpFileName);
+		
+		if (f.delete())
+			sRet = "deleted " + sTmpFileName;
+		
+		return(sRet);
+		}
+	
+	public String PruneDir(String sDir)
+		{
+		String	sRet = "";
+		int nFiles = 0;
+		String sSubDir = null;
+		String	sTmpDir = fixFileName(sDir);
+		
+		File dir = new File(sTmpDir);
+		
+		if (dir.isDirectory())
+			{
+			sRet = "Deleting file(s) from " + sTmpDir;
+			
+			File [] files = dir.listFiles();
+			if (files != null)
+				{
+				if ((nFiles = files.length) > 0)
+					{
+					for (int lcv = 0; lcv < nFiles; lcv++)
+						{
+						if (files[lcv].isDirectory())
+							{
+							sSubDir = files[lcv].getAbsolutePath();
+							sRet += "\n" + PruneDir(sSubDir);
+							}
+						else
+							{
+							if (files[lcv].delete())
+								{
+								sRet += "\n\tDeleted " + files[lcv].getName();
+								}
+							else
+								{
+								sRet += "\n\tUnable to delete " + files[lcv].getName();
+								}
+							}
+						}
+					}
+				else
+					sRet += "\n\t<empty>";
+				}
+			
+			if (dir.delete())
+				{
+				sRet += "\nDeleting directory " + sTmpDir;
+				}
+			else
+				{
+				sRet += "\nUnable to delete directory " + sTmpDir;
+				}
+			}
+		else
+			{
+			sRet += sTmpDir + " is not a directory";
+			}
+		
+		return(sRet);
+		}
+	
+	public String PrintDir(String sDir)
+		{
+		String	sRet = "";
+		int nFiles = 0;
+		String	sTmpDir = fixFileName(sDir);
+		
+		File dir = new File(sTmpDir);
+		
+		if (dir.isDirectory())
+			{
+			File [] files = dir.listFiles();
+		
+			if (files != null)
+				{
+				if ((nFiles = files.length) > 0)
+					{
+					for (int lcv = 0; lcv < nFiles; lcv++)
+						{
+						sRet += files[lcv].getName();
+						if (lcv < (nFiles - 1))
+							sRet += "\n";
+						}
+					}
+				else
+					sRet = "<empty>";
+				}
+			}
+		else
+			{
+			sRet = sTmpDir + " is not a directory";
+			}
+		
+		return(sRet);
+		}
+	
+	public String Move(String srcFileName, String dstFileName)
+		{
+		String	sTmpSrcFileName = fixFileName(srcFileName);
+		String	sTmpDstFileName = fixFileName(dstFileName);
+		String sRet = "Could not move " + sTmpSrcFileName + " to " + sTmpDstFileName;
+		
+		File srcFile = new File(sTmpSrcFileName);
+		File dstFile = new File(sTmpDstFileName);
+		
+		if (srcFile.renameTo(dstFile))
+			sRet = sTmpSrcFileName + " moved to " + sTmpDstFileName;
+		
+		return (sRet);
+		}
+	
+	public String CopyFile(String srcFileName, String dstFileName)
+		{
+		String	sTmpSrcFileName = fixFileName(srcFileName);
+		String	sTmpDstFileName = fixFileName(dstFileName);
+		String sRet = "Could not copy " + sTmpSrcFileName + " to " + sTmpDstFileName;
+		File destFile = null;
+		byte[] buffer = new byte [4096];
+		int	nRead = 0;
+		long lTotalRead = 0;
+		long lTotalWritten = 0;
+		
+		try 
+			{
+			FileInputStream srcFile  = new FileInputStream(sTmpSrcFileName);
+			FileOutputStream dstFile = new FileOutputStream(sTmpDstFileName);
+			
+			while((nRead = srcFile.read(buffer)) != -1)
+				{
+				lTotalRead += nRead;
+				dstFile.write(buffer, 0, nRead);
+				}
+			dstFile.flush();
+			dstFile.close();
+			
+			destFile = new File(sTmpDstFileName);
+			lTotalWritten = destFile.length();
+
+			if (lTotalWritten == lTotalRead)
+				sRet = sTmpSrcFileName + " copied to " + sTmpDstFileName;
+			else
+				sRet = "Failed to copy " + sTmpSrcFileName + " [length = " + lTotalWritten + "] to " + sTmpDstFileName + " [length = " + lTotalRead + "]";
+			}
+		catch (FileNotFoundException e)
+			{
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+			} 
+		catch (IOException e)
+			{
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+			}
+
+		return (sRet);
+		}
+	
+	public String IsDirWritable(String sDir)
+		{
+		String sRet = "";
+		String	sTmpDir = fixFileName(sDir);
+		File dir = new File(sTmpDir);
+		
+		if (dir.isDirectory())
+			{
+			sRet = "[" + sDir + "] " + (dir.canWrite() ? "is" : "is not") + " writable";
+			}
+		else
+			{
+			sRet = "[" + sDir + "] is not a directory";
+			}
+		
+		return(sRet);
+		}
+	
+	public String Push(String fileName, BufferedInputStream bufIn, long lSize)
+	{
+		byte []				buffer 			= new byte [8192];
+		int					nRead			= 0;
+		long				lRead			= 0;
+		String				sTmpFileName 	= fixFileName(fileName);
+		String				sRet			= "Push failed!";
+		
+		try {
+			FileOutputStream dstFile = new FileOutputStream(sTmpFileName, false);
+			while((nRead != -1) && (lRead < lSize))
+				{
+				nRead = bufIn.read(buffer);
+				if (nRead != -1)
+					{
+					dstFile.write(buffer, 0, nRead);
+					dstFile.flush();
+					lRead += nRead;
+					}
+				}
+			
+			dstFile.flush();
+			dstFile.close();
+			
+			if (lRead == lSize)
+				{
+				sRet = HashFile(sTmpFileName);
+				
+				}
+			}
+		catch (IOException e)
+			{
+			e.printStackTrace();
+			}
+		
+		buffer = null;
+		
+		return(sRet);
+	}
+	
+	public String FTPGetFile(String sServer, String sSrcFileName, String sDstFileName, OutputStream out)
+		{
+		byte[] buffer = new byte [4096];
+		int	nRead = 0;
+		long lTotalRead = 0;
+		String sRet = "FTP Get failed for " + sSrcFileName;
+		String strRet = "";
+		int	reply = 0;
+		FileOutputStream outStream = null;
+		String	sTmpDstFileName = fixFileName(sDstFileName);
+		
+		FTPClient ftp = new FTPClient();
+		try 
+			{
+			ftp.connect(sServer);
+			reply = ftp.getReplyCode();
+		    if(FTPReply.isPositiveCompletion(reply))
+		    	{
+			    ftp.login("anonymous", "b@t.com");
+				reply = ftp.getReplyCode();
+			    if(FTPReply.isPositiveCompletion(reply))
+			    	{
+				    ftp.enterLocalPassiveMode();
+				    if (ftp.setFileType(FTP.BINARY_FILE_TYPE))
+				    	{
+				    	File dstFile = new File(sTmpDstFileName);
+				    	outStream = new FileOutputStream(dstFile);
+				    	FTPFile [] ftpFiles = ftp.listFiles(sSrcFileName);
+				    	long lFtpSize = ftpFiles[0].getSize();
+				    	if (lFtpSize <= 0)
+				    		lFtpSize = 1;
+				    	
+				    	InputStream ftpIn = ftp.retrieveFileStream(sSrcFileName);
+						while ((nRead = ftpIn.read(buffer)) != -1)
+							{
+							lTotalRead += nRead;
+							outStream.write(buffer, 0, nRead);
+							strRet = "\r" + lTotalRead + " of " + lFtpSize + " bytes received " + ((lTotalRead * 100) / lFtpSize) + "% completed";
+							out.write(strRet.getBytes());
+							out.flush();
+							}
+						ftpIn.close();
+						@SuppressWarnings("unused")
+						boolean bRet = ftp.completePendingCommand();
+						outStream.flush();
+				    	/*				    	
+				    	if (ftp.retrieveFile("pub/mozilla.org/firefox/releases/3.6b4/wince-arm/en-US/firefox-3.6b4.cab", outStream))
+				    		{
+				    		outStream.flush();
+				    		}
+				    	 */				    		
+			    		outStream.close();
+						strRet = ftp.getReplyString();
+						reply = ftp.getReplyCode();
+				    	}
+					strRet = ftp.getReplyString();
+					reply = ftp.getReplyCode();
+				    ftp.logout();
+				    ftp.disconnect();
+				    sRet = "\n" + strRet; 
+			    	}
+			    else
+			    	{
+			        ftp.disconnect();
+			        System.err.println("FTP server refused login.");
+			        }
+		    	}
+		    else
+		    	{
+		        ftp.disconnect();
+		        System.err.println("FTP server refused connection.");
+		        }
+			}
+		catch (SocketException e)
+			{
+			// TODO Auto-generated catch block
+			sRet = e.getMessage();
+			strRet = ftp.getReplyString();
+			reply = ftp.getReplyCode();
+			sRet += "\n" + strRet;
+			e.printStackTrace();
+			}
+		catch (IOException e)
+			{
+			// TODO Auto-generated catch block
+			sRet = e.getMessage();
+			strRet = ftp.getReplyString();
+			reply = ftp.getReplyCode();
+			sRet += "\n" + strRet;
+			e.printStackTrace();
+			}
+		return (sRet);
+	}
+	
+	public String Cat(String fileName, OutputStream out)
+		{
+		String	sTmpFileName = fixFileName(fileName);
+		String	sRet = "Could not read the file " + sTmpFileName;
+		byte[]	buffer = new byte [4096];
+		int		nRead = 0;
+		
+		try {
+			FileInputStream fin = new FileInputStream(sTmpFileName);
+			while ((nRead = fin.read(buffer)) != -1)
+				{
+				out.write(buffer,0,nRead);
+				}
+			out.flush();
+			sRet = "";
+			}
+		catch (FileNotFoundException e)
+			{
+			sRet = e.toString();
+			} 
+		catch (IOException e) 
+			{
+			sRet = e.toString();
+			}
+		return (sRet);
+		}
+	
+	public String MakeDir(String sDir)
+		{
+		String	sTmpDir = fixFileName(sDir);
+		String sRet = "Could not create the directory " + sTmpDir;
+		File dir = new File(sTmpDir);
+		
+		if (dir.mkdirs())
+			sRet = sDir + " successfully created";
+		
+		return (sRet);
+		}
+	
+	public String GetScreenInfo()
+		{
+		String sRet = "";
+		DisplayMetrics metrics = new DisplayMetrics();
+		SUTAgentAndroid.me.getWindowManager().getDefaultDisplay().getMetrics(metrics);
+		sRet = "X:" + metrics.widthPixels + " Y:" + metrics.heightPixels;
+		return (sRet);
+		}
+	
+	public int [] GetScreenXY()
+		{
+			int [] nRetXY = new int [2];
+			DisplayMetrics metrics = new DisplayMetrics();
+			SUTAgentAndroid.me.getWindowManager().getDefaultDisplay().getMetrics(metrics);
+			nRetXY[0] = metrics.widthPixels;
+			nRetXY[1] = metrics.heightPixels;
+			return(nRetXY);
+		}
+	
+	public String KillProcess(String sProcName, OutputStream out)
+		{
+		String [] theArgs = new String [3];
+		
+		theArgs[0] = "su";
+		theArgs[1] = "-c";
+		theArgs[2] = "kill";
+
+		String sRet = "Unable to kill " + sProcName + "\n";
+		ActivityManager aMgr = (ActivityManager) SUTAgentAndroid.me.getSystemService(Activity.ACTIVITY_SERVICE);
+		List <ActivityManager.RunningAppProcessInfo> lProcesses = aMgr.getRunningAppProcesses();
+		int lcv = 0;
+		String strProcName = "";
+		int	nPID = 0;
+		
+		for (lcv = 0; lcv < lProcesses.size(); lcv++)
+			{
+//			if (lProcesses.get(lcv).processName.contentEquals(sProcName))
+			if (lProcesses.get(lcv).processName.contains(sProcName))
+				{
+				strProcName = lProcesses.get(lcv).processName;
+				nPID = lProcesses.get(lcv).pid;
+				sRet = "Failed to kill " + nPID + " " + strProcName + "\n";
+
+				theArgs[2] += " " + nPID;
+				
+				try 
+					{
+					pProc = Runtime.getRuntime().exec(theArgs);
+					RedirOutputThread outThrd = new RedirOutputThread(pProc, out);
+					outThrd.start();
+					outThrd.join(5000);
+					}
+				catch (IOException e) 
+					{
+					sRet = e.getMessage();
+					e.printStackTrace();
+					} 
+				catch (InterruptedException e)
+					{
+					// TODO Auto-generated catch block
+					e.printStackTrace();
+					}
+/*
+				SUTAgentAndroid.me.finishActivity(SUTAgentAndroid.START_PRG);
+				// Give the messages a chance to be processed
+				try {
+					Thread.sleep(2000);
+					}
+				catch (InterruptedException e)
+					{
+					e.printStackTrace();
+					}
+//				aMgr.restartPackage(strProcName);
+ * 
+ */
+				break;
+				}
+			}
+		
+		if (nPID > 0)
+			{
+			sRet = "Successfully killed " + nPID + " " + strProcName + "\n";
+			lProcesses = aMgr.getRunningAppProcesses();
+			for (lcv = 0; lcv < lProcesses.size(); lcv++)
+				{
+//				if (lProcesses.get(lcv).processName.contentEquals(sProcName))
+				if (lProcesses.get(lcv).processName.contains(sProcName))
+					{
+					sRet = "Unable to kill " + nPID + " " + strProcName + "\n";
+					break;
+					}
+				}
+			}
+		
+		return (sRet);
+		}
+
+	public boolean IsProcessDead(String sProcName)
+		{
+		boolean bRet = false;
+		ActivityManager aMgr = (ActivityManager) SUTAgentAndroid.me.getSystemService(Activity.ACTIVITY_SERVICE);
+		List <ActivityManager.ProcessErrorStateInfo> lProcesses = aMgr.getProcessesInErrorState();
+		int lcv = 0;
+//		String strProcName = "";
+//		int	nPID = 0;
+		
+		if (lProcesses != null)
+			{
+			for (lcv = 0; lcv < lProcesses.size(); lcv++)
+				{
+				if (lProcesses.get(lcv).processName.contentEquals(sProcName) && 
+					lProcesses.get(lcv).condition != ActivityManager.ProcessErrorStateInfo.NO_ERROR)
+					{
+//					strProcName = lProcesses.get(lcv).processName;
+//					nPID = lProcesses.get(lcv).pid;
+					bRet = true;
+					break;
+					}
+				}
+			}
+	
+		return (bRet);
+		}
+
+	public String GetProcessInfo()
+		{
+		String sRet = "";
+		ActivityManager aMgr = (ActivityManager) SUTAgentAndroid.me.getSystemService(Activity.ACTIVITY_SERVICE);
+		List <ActivityManager.RunningAppProcessInfo> lProcesses = aMgr.getRunningAppProcesses();
+		int	nProcs = lProcesses.size();
+		int lcv = 0;
+		String strProcName = "";
+		int	nPID = 0;
+		int nUser = 0;
+		
+		for (lcv = 0; lcv < nProcs; lcv++)
+			{
+			strProcName = lProcesses.get(lcv).processName;
+			nPID = lProcesses.get(lcv).pid;
+			nUser = lProcesses.get(lcv).uid;
+			sRet += nUser + "\t" + nPID + "\t" + strProcName;
+			if (lcv < (nProcs - 1))
+				sRet += "\n";
+			}
+			
+		return (sRet);
+		}
+	
+	public String GetOSInfo()
+		{
+		String sRet = "";
+		
+		sRet = Build.DISPLAY;
+		
+		return (sRet);
+		}
+	
+	public String GetPowerInfo()
+		{
+		String sRet = "";
+	
+		sRet = "Power status:\n  AC power " + SUTAgentAndroid.sACStatus + "\n";
+		sRet += "  Battery charge " + SUTAgentAndroid.sPowerStatus + "\n";
+		sRet += "  Remaining charge:      " + SUTAgentAndroid.nChargeLevel + "%\n";
+		sRet += "  Battery Temperature:   " + (((float)(SUTAgentAndroid.nBatteryTemp))/10) + " (c)\n";
+		return (sRet);
+		}
+
+	public String GetDiskInfo(String sPath)
+		{
+		String sRet = "";
+		StatFs statFS = new StatFs(sPath);
+		
+		int nBlockCount = statFS.getBlockCount();
+		int nBlockSize = statFS.getBlockSize();
+		int nBlocksAvail = statFS.getAvailableBlocks();
+		int nBlocksFree = statFS.getFreeBlocks();
+	
+		sRet = "total:     " + (nBlockCount * nBlockSize) + "\nfree:      " + (nBlocksFree * nBlockSize) + "\navailable: " + (nBlocksAvail * nBlockSize);
+	
+		return (sRet);
+		}
+
+	public String GetMemoryInfo()
+		{
+		String sRet = "PA:" + GetMemoryConfig();
+		return (sRet);
+		}
+
+	public long GetMemoryConfig()
+		{
+		ActivityManager aMgr = (ActivityManager) SUTAgentAndroid.me.getSystemService(Activity.ACTIVITY_SERVICE);
+		ActivityManager.MemoryInfo outInfo = new ActivityManager.MemoryInfo();
+		aMgr.getMemoryInfo(outInfo);
+		long lMem = outInfo.availMem;
+//		float fMem = (float) lMem / (float)(1024.0 * 1024.0);
+
+		return (lMem);
+		}
+	
+	public String RegisterTheDevice(String sSrvr, String sPort, String sData)
+		{
+		String sRet = "";
+		String line = "";
+		
+		if (sSrvr != null && sPort != null && sData != null)
+			{
+			try
+				{
+				int nPort = Integer.parseInt(sPort);
+				Socket socket = new Socket(sSrvr, nPort);
+				PrintWriter out = new PrintWriter(socket.getOutputStream(), false);
+				BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
+				out.println(sData);
+				if ( out.checkError() == false )
+					{
+					while (socket.isInputShutdown() == false)
+						{
+						line = in.readLine();
+						if ((line == null) || (line.contains("OK")))
+							{
+							sRet += line;
+							break;
+							}
+						sRet += line;
+						}
+					}
+				out.close();
+				in.close();
+				socket.close();
+				}
+			catch(NumberFormatException e)
+				{
+				e.printStackTrace();
+				} 
+			catch (UnknownHostException e)
+				{
+				// TODO Auto-generated catch block
+				e.printStackTrace();
+				}
+			catch (IOException e)
+				{
+				// TODO Auto-generated catch block
+				e.printStackTrace();
+				}
+			}
+		return(sRet);
+		}
+	
+	public String GetInternetData(String sHost, String sPort, String sURL)
+		{
+		String sRet = "";
+		String sNewURL = "";
+		HttpClient httpClient = new DefaultHttpClient();
+		try 
+			{
+			sNewURL = "http://" + sHost + ((sPort.length() > 0) ? (":" + sPort) : "") + sURL;
+
+			HttpGet request = new HttpGet(sNewURL);
+			HttpResponse response = httpClient.execute(request);
+			int status = response.getStatusLine().getStatusCode();
+			// we assume that the response body contains the error message
+			if (status != HttpStatus.SC_OK)
+				{
+			    ByteArrayOutputStream ostream = new ByteArrayOutputStream();
+			    response.getEntity().writeTo(ostream);
+			    Log.e("HTTP CLIENT", ostream.toString());
+				}
+			else
+				{
+			    InputStream content = response.getEntity().getContent();
+//			    int nAvailable = content.available();
+//			    byte [] data = new byte [nAvailable];
+			    byte [] data = new byte [2048];
+			    int nRead = content.read(data);
+			    sRet = new String(data, 0, nRead);
+			    content.close(); // this will also close the connection
+				}
+			}
+		catch (IllegalArgumentException e)
+			{
+			// TODO Auto-generated catch block
+			sRet = e.getLocalizedMessage();
+			e.printStackTrace();
+			}
+		catch (ClientProtocolException e)
+			{
+			// TODO Auto-generated catch block
+			sRet = e.getLocalizedMessage();
+			e.printStackTrace();
+			}
+		catch (IOException e)
+			{
+			// TODO Auto-generated catch block
+			sRet = e.getLocalizedMessage();
+			e.printStackTrace();
+			}
+		
+		return(sRet);
+		}
+
+	public String GetSystemTime()
+		{
+		String sRet = "";
+		Calendar cal = Calendar.getInstance();
+		SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd hh:mm:ss:SSS");
+		sRet = sdf.format(cal.getTime());
+	
+		return (sRet);
+		}
+	
+	public String GetUptime()
+		{
+		String sRet = "";
+		long lHold = 0;
+		long lUptime = SystemClock.elapsedRealtime();
+		int	nDays = 0;
+		int	nHours = 0;
+		int nMinutes = 0;
+		int nSecs = 0;
+		int nMilliseconds = 0;
+		
+		if (lUptime > 0)
+			{
+			nDays = (int)(lUptime / (24L * 60L * 60L * 1000L));
+			lHold = lUptime % (24L * 60L * 60L * 1000L);
+			nHours = (int)(lHold / (60L * 60L * 1000L));
+			lHold %= 60L * 60L * 1000L;
+			nMinutes = (int)(lHold / (60L * 1000L));
+			lHold %= 60L * 1000L;
+			nSecs = (int)(lHold / 1000L);
+			nMilliseconds = (int)(lHold % 1000);
+			sRet = "" + nDays + " days " + nHours + " hours " + nMinutes + " minutes " + nSecs + " seconds " + nMilliseconds + " ms";
+			}
+
+		return (sRet);
+		}
+/*	
+	private boolean IsProcRunning(Process pProc)
+		{
+		boolean bRet = false;
+		int nExitCode = 0;
+		
+		try
+			{
+			nExitCode = pProc.exitValue();
+			}
+		catch (IllegalThreadStateException z)
+			{	
+			bRet = true;
+			}
+
+		return(bRet);
+		}
+*/
+
+	public String NewKillProc(String sProcId, OutputStream out)
+		{
+		String sRet = "";
+		String [] theArgs = new String [3];
+		
+		theArgs[0] = "su";
+		theArgs[1] = "-c";
+		theArgs[2] = "kill " + sProcId;
+
+		try 
+			{
+			pProc = Runtime.getRuntime().exec(theArgs);
+			RedirOutputThread outThrd = new RedirOutputThread(pProc, out);
+			outThrd.start();
+			outThrd.join(5000);
+			}
+		catch (IOException e) 
+			{
+			sRet = e.getMessage();
+			e.printStackTrace();
+			} 
+		catch (InterruptedException e)
+			{
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+			}
+
+		return(sRet);
+		}
+	
+	public String SendPing(String sIPAddr, OutputStream out)
+		{
+		String sRet = "";
+		String [] theArgs = new String [4];
+		
+		theArgs[0] = "ping";
+		theArgs[1] = "-c";
+		theArgs[2] = "3";
+		theArgs[3] = sIPAddr;
+		
+		try 
+			{
+			pProc = Runtime.getRuntime().exec(theArgs);
+//			sutErr = pProc.getErrorStream(); // Stderr
+//			sutIn = pProc.getOutputStream(); // Stdin
+//			sutOut = pProc.getInputStream(); // Stdout
+			RedirOutputThread outThrd = new RedirOutputThread(pProc, out);
+			outThrd.start();
+			outThrd.join(5000);
+			if (out == null)
+				sRet = outThrd.strOutput;
+			}
+		catch (IOException e) 
+			{
+			sRet = e.getMessage();
+			e.printStackTrace();
+			} 
+		catch (InterruptedException e)
+			{
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+			}
+	
+		return (sRet);
+		}
+	
+	public String GetTmpDir()
+	{
+		String 	sRet = "";
+		Context ctx = SUTAgentAndroid.me.getApplicationContext();
+        File dir = ctx.getFilesDir();
+        ctx = null;
+        try {
+			sRet = dir.getCanonicalPath();
+			} 
+        catch (IOException e)
+        	{
+			e.printStackTrace();
+        	}
+        return(sRet);
+	}
+	
+	public String PrintFileTimestamp(String sFile)
+		{
+		String 	sRet = "";
+		String	sTmpFileName = fixFileName(sFile);
+		File 	theFile = new File(sTmpFileName);
+		
+		if (theFile.exists())
+			{
+			long lModified = theFile.lastModified();
+			Date dtModified = new Date(lModified);
+			SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd hh:mm:ss:SSS");
+			sRet = "Last modified: " + sdf.format(dtModified);
+			}
+		else
+			{
+			sRet = "[" + sTmpFileName + "] doesn't exist";
+			}
+
+		return(sRet);
+		}
+	
+	public String GetIniData(String sSection, String sKey, String sFile)
+		{
+		String sRet = "";
+		String sComp = "";
+		String sLine = "";
+		boolean bFound = false;
+		BufferedReader in = null;
+		String	sTmpFileName = fixFileName(sFile);
+		
+		try {
+			in = new BufferedReader(new FileReader(sTmpFileName));
+			sComp = "[" + sSection + "]";
+			while ((sLine = in.readLine()) != null)
+				{
+				if (sLine.equalsIgnoreCase(sComp))
+					{
+					bFound = true;
+					break;
+					}
+				}
+			
+			if (bFound)
+				{
+				sComp = (sKey + " =").toLowerCase();
+				while ((sLine = in.readLine()) != null)
+					{
+					if (sLine.toLowerCase().contains(sComp))
+						{
+						String [] temp = null;
+						temp = sLine.split("=");
+						if (temp != null)
+							{
+							sRet = temp[1].trim();
+							}
+						break;
+						}
+					}
+				}
+			in.close();
+			}
+		catch (FileNotFoundException e)
+			{
+			sComp = e.toString();
+			} 
+		catch (IOException e) 
+			{
+			sComp = e.toString();
+			}
+		return (sRet);
+		}
+	
+	public String RunReboot(OutputStream out)
+		{
+		String sRet = "";
+		String [] theArgs = new String [3];
+	
+		theArgs[0] = "su";
+		theArgs[1] = "-c";
+		theArgs[2] = "reboot";
+	
+		try 
+			{
+			pProc = Runtime.getRuntime().exec(theArgs);
+			RedirOutputThread outThrd = new RedirOutputThread(pProc, out);
+			outThrd.start();
+			outThrd.join(10000);
+			}
+		catch (IOException e) 
+			{
+			sRet = e.getMessage();
+			e.printStackTrace();
+			} 
+		catch (InterruptedException e)
+			{
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+			}
+
+		return (sRet);
+		}
+	
+	public String UnInstallApp(String sApp, OutputStream out)
+		{
+		String sRet = "";
+		String [] theArgs = new String [3];
+
+		theArgs[0] = "su";
+		theArgs[1] = "-c";
+		theArgs[2] = "pm uninstall " + sApp + ";reboot;exit";
+		
+		try 
+			{
+			pProc = Runtime.getRuntime().exec(theArgs);
+		
+			RedirOutputThread outThrd = new RedirOutputThread(pProc, out);
+			outThrd.start();
+			outThrd.join(60000);
+			int nRet = pProc.exitValue();
+//			boolean bRet = outThrd.isAlive();
+			sRet = "\nuninst complete [" + nRet + "]";
+			}
+		catch (IOException e) 
+			{
+			sRet = e.getMessage();
+			e.printStackTrace();
+			} 
+		catch (InterruptedException e)
+			{
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+			}
+		
+		return (sRet);
+	}
+	
+	public String InstallApp(String sApp, OutputStream out)
+		{
+		String sRet = "";
+		String [] theArgs = new String [3];
+		File	srcFile = new File(sApp);
+//		boolean bDone = false;
+//		int		nExitCode;
+
+		theArgs[0] = "su";
+		theArgs[1] = "-c";
+		theArgs[2] = "mv " + GetTmpDir() + "/" + srcFile.getName() + " /data/local/tmp/" + srcFile.getName() + ";exit";
+//		theArgs[2] += ";chmod 666 /data/local/tmp/" + srcFile.getName();
+//		theArgs[2] += ";pm install /data/local/tmp/" + srcFile.getName() + " Cleanup";
+//		theArgs[2] += ";done;exit";
+		
+		sRet = CopyFile(sApp, GetTmpDir() + "/" + srcFile.getName());
+		try {
+			out.write(sRet.getBytes());
+			out.flush();
+		} catch (IOException e1) {
+			// TODO Auto-generated catch block
+			e1.printStackTrace();
+		}
+//		CopyFile(sApp, GetTmpDir() + "/" + srcFile.getName());
+
+		try 
+			{
+			pProc = Runtime.getRuntime().exec(theArgs);
+			
+			RedirOutputThread outThrd = new RedirOutputThread(pProc, out);
+			outThrd.start();
+			outThrd.join(90000);
+			int nRet = pProc.exitValue();
+//			boolean bRet = outThrd.isAlive();
+			sRet = "\nmove complete [" + nRet + "]";
+			try 
+				{
+				out.write(sRet.getBytes());
+				out.flush();
+				}
+			catch (IOException e1)
+				{
+				// TODO Auto-generated catch block
+				e1.printStackTrace();
+				}
+			
+			theArgs[2] = "chmod 666 /data/local/tmp/" + srcFile.getName() + ";exit";
+			pProc = Runtime.getRuntime().exec(theArgs);
+			RedirOutputThread outThrd2 = new RedirOutputThread(pProc, out);
+			outThrd2.start();
+			outThrd2.join(10000);
+			int nRet2 = pProc.exitValue();
+//			bRet = outThrd2.isAlive();
+			sRet = "\npermission change complete [" + nRet2 + "]\n";
+			try {
+				out.write(sRet.getBytes());
+				out.flush();
+				}
+			catch (IOException e1)
+				{
+				// TODO Auto-generated catch block
+				e1.printStackTrace();
+				}
+			
+			theArgs[2] = "pm install /data/local/tmp/" + srcFile.getName() + " Cleanup" + ";exit";
+			pProc = Runtime.getRuntime().exec(theArgs);
+			RedirOutputThread outThrd3 = new RedirOutputThread(pProc, out);
+			outThrd3.start();
+			outThrd3.join(60000);
+			int nRet3 = pProc.exitValue();
+			sRet = "\ninstallation complete [" + nRet3 + "]";
+			try {
+				out.write(sRet.getBytes());
+				out.flush();
+				}
+			catch (IOException e1)
+				{
+				// TODO Auto-generated catch block
+				e1.printStackTrace();
+				}
+			
+			theArgs[2] = "rm /data/local/tmp/" + srcFile.getName() + ";exit";
+			pProc = Runtime.getRuntime().exec(theArgs);
+			RedirOutputThread outThrd4 = new RedirOutputThread(pProc, out);
+			outThrd4.start();
+			outThrd4.join(60000);
+			int nRet4 = pProc.exitValue();
+			sRet = "\ntmp file removed [" + nRet4 + "]";
+			try {
+				out.write(sRet.getBytes());
+				out.flush();
+				}
+			catch (IOException e1)
+				{
+				// TODO Auto-generated catch block
+				e1.printStackTrace();
+				}
+			sRet = "\nSuccess";
+			}
+		catch (IOException e) 
+			{
+			sRet = e.getMessage();
+			e.printStackTrace();
+			} 
+		catch (InterruptedException e)
+			{
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+			}
+
+		return (sRet);
+		}
+
+	public String StartJavaPrg(String [] sArgs)
+		{
+		String sRet = "";
+		String sArgList = "";
+		String sUrl = "";
+		String sRedirFileName = "";
+		
+		Context ctx = SUTAgentAndroid.me.getApplicationContext();
+		PackageManager pm = ctx.getPackageManager();
+
+		Intent prgIntent = new Intent();
+		prgIntent.setPackage(sArgs[0]);
+//		prgIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+
+		try {
+			PackageInfo pi = pm.getPackageInfo(sArgs[0], PackageManager.GET_ACTIVITIES | PackageManager.GET_INTENT_FILTERS);
+//			ApplicationInfo appinfo = pi.applicationInfo;
+			ActivityInfo [] ai = pi.activities;
+			for (int i = 0; i < ai.length; i++)
+				{
+				ActivityInfo a = ai[i];
+				if (a.name.length() > 0)
+					{
+					prgIntent.setClassName(a.packageName, a.name);
+					break;
+					}
+				}
+			}
+		catch (NameNotFoundException e)
+			{
+			e.printStackTrace();
+			}
+		
+		if (sArgs.length > 1)
+			{
+			if (sArgs[0].contains("android.browser"))
+				prgIntent.setAction(Intent.ACTION_VIEW);
+			
+			if (sArgs[0].contains("fennec"))
+				{
+				sArgList = "";
+				sUrl = "";
+				
+				for (int lcv = 1; lcv < sArgs.length; lcv++)
+					{
+					if (sArgs[lcv].contains("://"))
+						sUrl = sArgs[lcv];
+					else
+						{
+						if (sArgs[lcv].equals(">"))
+							{
+							lcv++;
+							if (lcv < sArgs.length)
+								sRedirFileName = sArgs[lcv++];
+							}
+						else
+							sArgList += " " + sArgs[lcv];
+						}
+					}
+				
+				if (sArgList.length() > 0)
+					prgIntent.putExtra("args", sArgList.trim());
+				
+				if (sUrl.length() > 0)
+					prgIntent.setData(Uri.parse(sUrl.trim()));
+				}
+			else
+				{
+				for (int lcv = 1; lcv < sArgs.length; lcv++)
+					sArgList += " " + sArgs[lcv];
+				
+				prgIntent.setData(Uri.parse(sArgList.trim()));
+				}
+			}
+		else
+			prgIntent.setData(Uri.parse("about:blank"));
+
+		try 
+			{
+//			ctx.startActivity(prgIntent);
+//			SUTAgentAndroid.me.startActivity(prgIntent);
+			SUTAgentAndroid.me.startActivityForResult(prgIntent, SUTAgentAndroid.START_PRG);
+			}
+		catch(ActivityNotFoundException anf)
+			{
+			anf.printStackTrace();
+			}
+		
+		ctx = null;
+		return (sRet);
+		}
+
+	public String StartPrg(String [] progArray, OutputStream out)
+		{
+		String sRet = "";
+		
+		try 
+			{
+			pProc = Runtime.getRuntime().exec(progArray);
+			sutErr = pProc.getErrorStream(); // Stderr
+			sutIn = pProc.getOutputStream(); // Stdin
+			sutOut = pProc.getInputStream(); // Stdout
+			RedirOutputThread outThrd = new RedirOutputThread(pProc, out);
+			outThrd.start();
+			outThrd.join(10000);
+			}
+		catch (IOException e) 
+			{
+			e.printStackTrace();
+			}
+		catch (InterruptedException e)
+			{
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+			}
+
+		return (sRet);
+		}
+/*	
+	public String InstallApplication()
+		{
+		String sRet = "";
+		String sFileName = Environment.getExternalStorageDirectory() + "/org.mozilla.fennec.apk";
+		
+		Intent instIntent = new Intent();
+		
+		instIntent.setAction(android.content.Intent.ACTION_VIEW);
+		instIntent.setDataAndType(Uri.fromFile(new File(sFileName)), "application/vnd.android.package-archive");
+//		instIntent.setDataAndType(Uri.parse("file:///sdcard/org.mozilla.fennec.apk"), "application/vnd.android.package-archive");
+		SUTAgentAndroid.me.startActivity(instIntent);
+		
+//		Instrumentation inst = new Instrumentation();
+//		inst.sendKeyDownUpSync(KeyEvent.KEYCODE_SOFT_LEFT);
+		
+		return(sRet);
+		}
+
+	public String UninstallApplication()
+		{
+		String sRet = "";
+		Uri		pkgURI = Uri.parse("package:" + "org.mozilla.fennec");
+	
+		Intent unInstIntent = new Intent(Intent.ACTION_DELETE, pkgURI);
+	
+		SUTAgentAndroid.me.startActivity(unInstIntent);
+
+		return(sRet);
+		}
+*/
+	private String PrintUsage()
+		{
+		String sRet = "run [executable] [args]  - start program no wait\n" +
+			"exec [executable] [args] - start program wait\n" +
+			"fire [executable] [args] - start program no wait\n" +
+			"arun [executable] [args] - start program no wait\n" +
+			"kill [program name]      - kill program no path\n" +
+			"killall                  - kill all processes started\n" +
+			"ps                       - list of running processes\n" +
+			"nodebug                  - kill debugger loop\n" +
+			"info                     - list of device info\n" +
+			"        [os]             - os version for device\n" +
+			"        [id]             - unique identifier for device\n" +
+			"        [uptime]         - uptime for device\n" +
+			"        [systime]        - current system time on device\n" +
+			"        [screen]         - width, height and bits per pixel for device\n" +
+			"        [memory]         - physical, free, available, storage memory for device\n" +
+			"        [processes]      - list of running processes see 'ps'\n" +
+			"deadman timeout          - set the duration for the deadman timer\n" +
+			"alrt [on/off]            - start or stop sysalert behavior\n" +
+			"disk [arg]               - prints disk space info\n" +
+			"cp file1 file2           - copy file1 to file2 on device\n" +
+			"time file                - timestamp for file on device\n" +
+			"hash file                - generate hash for file on device\n" +
+			"cd directory             - change cwd on device\n" +
+			"cat file                 - cat file on device\n" +
+			"cwd                      - display cwd on device\n" +
+			"mv file1 file2           - move file1 to file2 on device\n" +
+			"push filename            - push file to device\n" +
+			"rm file                  - delete file on device\n" +
+			"rmdr directory           - delete directory on device even if not empty\n" +
+			"mkdr directory           - create directory on device\n" +
+			"dirw directory           - tests whether the directory is writable on the device\n" +
+			"stat processid           - stat process on device\n" +
+			"dead processid           - print whether the process is alive or hung on device\n" +
+			"mems                     - dump memory stats on device\n" +
+			"ls                       - print directory on device\n" +
+			"tmpd                     - print temp directory on device\n" +
+			"ping [hostname/ipaddr]   - ping a network device\n" +
+			"unzp zipfile destdir     - unzip the zipfile into the destination dir\n" +
+			"zip zipfile src          - zip the source file/dir into zipfile\n" +
+			"rebt                     - reboot device\n" +
+			"quit                     - disconnect SUTAgent\n" +
+			"exit                     - close SUTAgent\n" +
+			"help                     - you're reading it";
+		return (sRet);
+		}
+}
new file mode 100755
--- /dev/null
+++ b/build/mobile/sutagent/android/Makefile.in
@@ -0,0 +1,110 @@
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is the Android sutagent for testing.
+#
+# The Initial Developer of the Original Code is
+#   Mozilla Foundation
+# Portions created by the Initial Developer are Copyright (C) 2010
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#   Clint Talbert <ctalbert@mozilla.com>
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH		= ../../../..
+topsrcdir	= @top_srcdir@
+srcdir		= @srcdir@
+VPATH		= @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE = sutAgentAndroid
+
+JAVAFILES = \
+  AlertLooperThread.java \
+  ASMozStub.java \
+  CmdWorkerThread.java \
+  DataWorkerThread.java \
+  DoAlert.java \
+  DoCommand.java \
+  Power.java \
+  RedirOutputThread.java \
+  RunCmdThread.java \
+  RunDataThread.java \
+  SUTAgentAndroid.java \
+  SUTStartupIntentReceiver.java \
+  WifiConfiguration.java \
+  R.java \
+  $(NULL)
+
+RES_FILES = \
+  res/drawable/icon.png \
+  res/layout/main.xml \
+  res/values/strings.xml \
+  $(NULL)
+
+GARBAGE += \
+  AndroidManifest.xml  \
+  classes.dex  \
+  sutAgentAndroid.apk  \
+  $(NULL)
+
+GARBAGE_DIRS += res classes network-libs
+
+JAVA_CLASSPATH = $(ANDROID_SDK)/android.jar:$(srcdir)/network-libs/commons-net-2.0.jar
+
+include $(topsrcdir)/config/rules.mk
+
+# include Android specific java flags - using these instead of what's in rules.mk
+include $(topsrcdir)/config/android-common.mk
+
+tools:: sutAgentAndroid.apk
+
+classes.dex: $(JAVAFILES)
+	$(NSINSTALL) -D classes
+	$(JAVAC) $(JAVAC_FLAGS) -d classes  $(addprefix $(srcdir)/,$(JAVAFILES))
+	$(DX) --dex --output=$@ classes
+
+sutAgentAndroid.ap_: $(srcdir)/AndroidManifest.xml
+	$(AAPT) package -f -M $(srcdir)/AndroidManifest.xml -I $(ANDROID_SDK)/android.jar  -S res -F $@
+
+sutAgentAndroid-unsigned-unaligned.apk: sutAgentAndroid.ap_ classes.dex
+	$(APKBUILDER) $@ -v $(APKBUILDER_FLAGS) -z sutAgentAndroid.ap_ -f classes.dex
+
+sutAgentAndroid-unaligned.apk: sutAgentAndroid-unsigned-unaligned.apk
+	cp  sutAgentAndroid-unsigned-unaligned.apk $@
+ifdef JARSIGNER
+  $(JARSIGNER) $@
+endif
+
+sutAgentAndroid.apk: sutAgentAndroid-unaligned.apk
+	$(ZIPALIGN) -f -v 4 sutAgentAndroid-unaligned.apk $@
+
+export::
+	$(NSINSTALL) -D res
+	@(cd $(srcdir)/res && tar $(TAR_CREATE_FLAGS) - *) | (cd $(DEPTH)/build/mobile/sutagent/android/res && tar -xf -)
+
new file mode 100755
--- /dev/null
+++ b/build/mobile/sutagent/android/Power.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os;
+
+import java.io.IOException;
+
+/**
+ * Class that provides access to some of the power management functions.
+ *
+ * {@hide}
+ */
+public class Power
+{
+    // can't instantiate this class
+    private Power()
+    {
+    }
+
+    /**
+     * Wake lock that ensures that the CPU is running.  The screen might
+     * not be on.
+     */
+    public static final int PARTIAL_WAKE_LOCK = 1;
+
+    /**
+     * Wake lock that ensures that the screen is on.
+     */
+    public static final int FULL_WAKE_LOCK = 2;
+
+    public static native void acquireWakeLock(int lock, String id);
+    public static native void releaseWakeLock(String id);
+
+    /**
+     * Brightness value for fully off
+     */
+    public static final int BRIGHTNESS_OFF = 0;
+
+    /**
+     * Brightness value for dim backlight
+     */
+    public static final int BRIGHTNESS_DIM = 20;
+
+    /**
+     * Brightness value for fully on
+     */
+    public static final int BRIGHTNESS_ON = 255;
+
+    /**
+     * Brightness value to use when battery is low
+     */
+    public static final int BRIGHTNESS_LOW_BATTERY = 10;
+
+    /**
+     * Threshold for BRIGHTNESS_LOW_BATTERY (percentage)
+     * Screen will stay dim if battery level is <= LOW_BATTERY_THRESHOLD
+     */
+    public static final int LOW_BATTERY_THRESHOLD = 10;
+
+    /**
+     * Turn the screen on or off
+     *
+     * @param on Whether you want the screen on or off
+     */
+    public static native int setScreenState(boolean on);
+
+    public static native int setLastUserActivityTimeout(long ms);
+
+    /**
+     * Turn the device off.
+     *
+     * This method is considered deprecated in favor of
+     * {@link android.policy.ShutdownThread.shutdownAfterDisablingRadio()}.
+     *
+     * @deprecated
+     * @hide
+     */
+    @Deprecated
+    public static native void shutdown();
+
+    /**
+     * Reboot the device.
+     * @param reason code to pass to the kernel (e.g. "recovery"), or null.
+     *
+     * @throws IOException if reboot fails for some reason (eg, lack of
+     *         permission)
+     */
+    public static native void reboot(String reason) throws IOException;
+}
new file mode 100755
--- /dev/null
+++ b/build/mobile/sutagent/android/R.java
@@ -0,0 +1,27 @@
+/* AUTO-GENERATED FILE.  DO NOT MODIFY.
+ *
+ * This class was automatically generated by the
+ * aapt tool from the resource data it found.  It
+ * should not be modified by hand.
+ */
+
+package com.mozilla.SUTAgentAndroid;
+
+public final class R {
+    public static final class attr {
+    }
+    public static final class drawable {
+        public static final int icon=0x7f020000;
+    }
+    public static final class id {
+        public static final int Button01=0x7f050001;
+        public static final int Textview01=0x7f050000;
+    }
+    public static final class layout {
+        public static final int main=0x7f030000;
+    }
+    public static final class string {
+        public static final int app_name=0x7f040001;
+        public static final int hello=0x7f040000;
+    }
+}
new file mode 100755
--- /dev/null
+++ b/build/mobile/sutagent/android/RedirOutputThread.java
@@ -0,0 +1,166 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Android SUTAgent code.
+ *
+ * The Initial Developer of the Original Code is
+ * Bob Moss.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *  Bob Moss <bmoss@mozilla.com>
+ * 
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+package com.mozilla.SUTAgentAndroid;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.PrintWriter;
+
+import android.widget.Toast;
+
+public class RedirOutputThread extends Thread
+	{
+	OutputStream out;
+	InputStream	sutErr;
+	InputStream	sutOut;
+	Process pProc;
+	String	strOutput;
+	
+	public RedirOutputThread(Process pProc, OutputStream out)
+		{
+		if (pProc != null)
+			{
+			this.pProc = pProc;
+			sutErr = pProc.getErrorStream(); // Stderr
+			sutOut = pProc.getInputStream(); // Stdout
+			}
+		if (out != null)
+			this.out = out;
+		
+		strOutput = "";
+		}
+	
+	public void run()
+		{
+		boolean bStillRunning = true;
+		int	nBytesOut = 0;
+		int nBytesErr = 0;
+		int nBytesRead = 0;
+		PrintWriter pOut = null;
+		byte[] buffer = new byte[1024];
+		
+		if (out != null)
+			pOut = new PrintWriter(out);
+		else
+			bStillRunning = true;
+		
+		while (bStillRunning) 
+			{
+			try 
+				{
+				if ((nBytesOut = sutOut.available()) > 0)
+					{
+					if (nBytesOut > buffer.length)
+						{
+						buffer = null;
+						System.gc();
+						buffer = new byte[nBytesOut];
+						}
+					nBytesRead = sutOut.read(buffer, 0, nBytesOut);
+					if (nBytesRead == -1)
+						bStillRunning = false;
+					else 
+						{
+						String sRep = new String(buffer,0,nBytesRead).replace("\n", "\r\n");
+						if (pOut != null)
+							{
+							pOut.print(sRep);
+							pOut.flush();
+							}
+						else
+							strOutput += sRep;
+						}
+					}
+
+				if ((nBytesErr = sutErr.available()) > 0)
+					{
+					if (nBytesErr > buffer.length)
+						{
+						buffer = null;
+						System.gc();
+						buffer = new byte[nBytesErr];
+						}
+					nBytesRead = sutErr.read(buffer, 0, nBytesErr);
+					if (nBytesRead == -1)
+						bStillRunning = false;
+					else 
+						{
+						String sRep = new String(buffer,0,nBytesRead).replace("\n", "\r\n");
+						if (pOut != null)
+							{
+							pOut.print(sRep);
+							pOut.flush();
+							}
+						else
+							strOutput += sRep;
+						}
+					}
+
+				bStillRunning = (IsProcRunning(pProc) || (sutOut.available() > 0) || (sutErr.available() > 0));
+				} 
+			catch (IOException e)
+				{
+				Toast.makeText(SUTAgentAndroid.me.getApplicationContext(), e.getMessage(), Toast.LENGTH_LONG).show();
+				e.printStackTrace();
+				}
+			}
+		
+		pProc.destroy();
+		buffer = null;
+		System.gc();
+		}
+	
+	private boolean IsProcRunning(Process pProc)
+		{
+		boolean bRet = false;
+		@SuppressWarnings("unused")
+		int nExitCode = 0;
+	
+		try
+			{
+			nExitCode = pProc.exitValue();
+			}
+		catch (IllegalThreadStateException z)
+			{	
+			bRet = true;
+			}
+
+		return(bRet);
+		}
+	}
new file mode 100755
--- /dev/null
+++ b/build/mobile/sutagent/android/RunCmdThread.java
@@ -0,0 +1,109 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Android SUTAgent code.
+ *
+ * The Initial Developer of the Original Code is
+ * Bob Moss.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *  Bob Moss <bmoss@mozilla.com>
+ * 
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+package com.mozilla.SUTAgentAndroid;
+
+import java.io.IOException;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.SocketTimeoutException;
+import java.util.ArrayList;
+import java.util.List;
+
+import android.widget.Toast;
+
+public class RunCmdThread extends Thread
+	{
+	private ServerSocket SvrSocket = null;
+	private Socket socket	= null;
+	boolean bListening	= true;
+	List<CmdWorkerThread> theWorkers = new ArrayList<CmdWorkerThread>();
+	
+	public RunCmdThread(ServerSocket socket)
+		{
+		super("RunCmdThread");
+		this.SvrSocket = socket;
+		}
+	
+	public void StopListening()
+		{
+		bListening = false;
+		}
+	
+	public void run() {
+		try {
+			SvrSocket.setSoTimeout(5000);
+			while (bListening)
+				{
+				try 
+					{
+					socket = SvrSocket.accept();
+					CmdWorkerThread theWorker = new CmdWorkerThread(this, socket);
+					theWorker.start();
+					theWorkers.add(theWorker);
+					}
+				catch (SocketTimeoutException toe)
+					{
+					continue;
+					}
+				}
+			
+			int nNumWorkers = theWorkers.size();
+			for (int lcv = 0; lcv < nNumWorkers; lcv++)
+				{
+				if (theWorkers.get(lcv).isAlive())
+					{
+					theWorkers.get(lcv).StopListening();
+					while(theWorkers.get(lcv).isAlive())
+						;
+					}
+				}
+			
+			theWorkers.clear();
+			
+			SvrSocket.close();
+			
+			SUTAgentAndroid.me.finish();
+			} 
+		catch (IOException e)
+			{
+			Toast.makeText(SUTAgentAndroid.me.getApplicationContext(), e.getMessage(), Toast.LENGTH_LONG).show();
+		    e.printStackTrace();
+			}
+		return;
+	}
+}
new file mode 100755
--- /dev/null
+++ b/build/mobile/sutagent/android/RunDataThread.java
@@ -0,0 +1,110 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Android SUTAgent code.
+ *
+ * The Initial Developer of the Original Code is
+ * Bob Moss.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *  Bob Moss <bmoss@mozilla.com>
+ * 
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+package com.mozilla.SUTAgentAndroid;
+
+import java.io.IOException;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.SocketTimeoutException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Timer;
+
+import android.widget.Toast;
+
+public class RunDataThread extends Thread
+	{
+	Timer heartBeatTimer;
+	
+	private ServerSocket SvrSocket = null;
+	private Socket socket	= null;
+	boolean bListening	= true;
+	List<DataWorkerThread> theWorkers = new ArrayList<DataWorkerThread>();
+	
+	public RunDataThread(ServerSocket socket)
+		{
+		super("RunDataThread");
+		this.SvrSocket = socket;
+		}
+	
+	public void StopListening()
+		{
+		bListening = false;
+		}
+
+	public void run() {
+		try {
+			SvrSocket.setSoTimeout(5000);
+			while (bListening)
+				{
+				try 
+					{
+					socket = SvrSocket.accept();
+					DataWorkerThread theWorker = new DataWorkerThread(this, socket);
+					theWorker.start();
+					theWorkers.add(theWorker);
+					}
+				catch (SocketTimeoutException toe)
+					{
+					continue;
+					}
+				}
+			
+			int nNumWorkers = theWorkers.size();
+			for (int lcv = 0; lcv < nNumWorkers; lcv++)
+				{
+				if (theWorkers.get(lcv).isAlive())
+					{
+					theWorkers.get(lcv).StopListening();
+					while(theWorkers.get(lcv).isAlive())
+						;
+					}
+				}
+			
+			theWorkers.clear();
+			
+			SvrSocket.close();
+			}
+		catch (IOException e)
+			{
+			Toast.makeText(SUTAgentAndroid.me.getApplicationContext(), e.getMessage(), Toast.LENGTH_LONG).show();
+			e.printStackTrace();
+			}
+		return;
+		}
+	}
new file mode 100755
--- /dev/null
+++ b/build/mobile/sutagent/android/SUTAgentAndroid.java
@@ -0,0 +1,713 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Android SUTAgent code.
+ *
+ * The Initial Developer of the Original Code is
+ * Bob Moss.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *  Bob Moss <bmoss@mozilla.com>
+ * 
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+package com.mozilla.SUTAgentAndroid;
+
+import java.io.File;
+import java.io.PrintWriter;
+import java.net.InetAddress;
+import java.net.NetworkInterface;
+import java.net.SocketException;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.Timer;
+import java.util.TimerTask;
+
+// import dalvik.system.VMRuntime;
+import android.app.Activity;
+import android.app.KeyguardManager;
+import android.bluetooth.BluetoothAdapter;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.net.Uri;
+import android.net.wifi.SupplicantState;
+import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiInfo;
+import android.net.wifi.WifiManager;
+import android.net.wifi.WifiManager.WifiLock;
+import android.os.BatteryManager;
+import android.os.Bundle;
+import android.os.PowerManager;
+import android.telephony.TelephonyManager;
+import android.util.Log;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.Button;
+import android.widget.TextView;
+import android.widget.Toast;
+
+public class SUTAgentAndroid extends Activity 
+	{
+	static final int START_PRG = 1959;
+	MenuItem mExitMenuItem;
+	Timer timer = null;
+	
+	public static SUTAgentAndroid me = null;
+    public static String sUniqueID = null;
+    public static String sLocalIPAddr = null;
+    public static String sACStatus = null;
+    public static String sPowerStatus = null;
+    public static int	nChargeLevel = 0;
+    public static int	nBatteryTemp = 0;
+    
+	String lineSep = System.getProperty("line.separator");
+    public PrintWriter dataOut = null;
+    
+    private static boolean bNetworkingStarted = false;
+    private static String RegSvrIPAddr = "";
+    private static String RegSvrIPPort = "";
+    private static String HardwareID = "";
+    private static String Pool = "";
+    private static String sRegString = "";
+    
+    private WifiLock wl = null;
+    private PowerManager.WakeLock pwl = null;
+    
+    private BroadcastReceiver battReceiver = null;
+
+	public boolean onCreateOptionsMenu(Menu menu)
+		{
+		mExitMenuItem = menu.add("Exit");
+		mExitMenuItem.setIcon(android.R.drawable.ic_menu_close_clear_cancel);
+		return super.onCreateOptionsMenu(menu);
+		}
+
+	public boolean onMenuItemSelected(int featureId, MenuItem item)
+		{
+		if (item == mExitMenuItem)
+			{
+			finish();
+			}
+		return super.onMenuItemSelected(featureId, item);
+		}
+	
+	public static String getRegSvrIPAddr()
+		{
+		return(RegSvrIPAddr);
+		}
+    
+    /** Called when the activity is first created. */
+    @Override
+    public void onCreate(Bundle savedInstanceState)
+    	{
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.main);
+        
+//        long lHeapSize = VMRuntime.getRuntime().getMinimumHeapSize();
+//        lHeapSize = 16000000;
+//        VMRuntime.getRuntime().setMinimumHeapSize(lHeapSize);
+        
+        // Keep phone from locking or remove lock on screen
+        KeyguardManager km = (KeyguardManager)getSystemService(Context.KEYGUARD_SERVICE);
+        if (km != null)
+        	{
+        	KeyguardManager.KeyguardLock kl = km.newKeyguardLock("SUTAgent");
+        	if (kl != null)
+        		kl.disableKeyguard();
+        	}
+        
+        // No sleeping on the job
+        PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
+        if (pm != null)
+        	{
+        	pwl = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK, "SUTAgent");
+        	if (pwl != null)
+        		pwl.acquire();
+        	}
+        
+        DoCommand dc = new DoCommand();
+        
+        // Get configuration settings from "ini" file
+        File dir = getFilesDir();
+        File iniFile = new File(dir, "SUTAgent.ini");
+        String sIniFile = iniFile.getAbsolutePath();
+        
+        SUTAgentAndroid.RegSvrIPAddr = dc.GetIniData("Registration Server", "IPAddr", sIniFile);
+        SUTAgentAndroid.RegSvrIPPort = dc.GetIniData("Registration Server", "PORT", sIniFile);
+        SUTAgentAndroid.HardwareID = dc.GetIniData("Registration Server", "HARDWARE", sIniFile);
+        SUTAgentAndroid.Pool = dc.GetIniData("Registration Server", "POOL", sIniFile);
+
+        TextView  tv = (TextView) this.findViewById(R.id.Textview01);
+
+        if (getLocalIpAddress() == null)
+        	setUpNetwork();
+        
+        me = this;
+        
+        WifiInfo wifi;
+        WifiManager wifiMan = (WifiManager)getSystemService(Context.WIFI_SERVICE);
+        String macAddress = "Unknown";
+        if (wifiMan != null) 
+        	{
+			wifi = wifiMan.getConnectionInfo();
+			if (wifi != null)
+				{
+				macAddress = wifi.getMacAddress();
+				if (macAddress != null)
+					sUniqueID = macAddress;
+				}
+        	}
+        
+        if (sUniqueID == null)
+        	{
+        	BluetoothAdapter ba = BluetoothAdapter.getDefaultAdapter();
+        	if (ba.isEnabled() != true)
+        		{
+        		ba.enable();
+        		while(ba.getState() != BluetoothAdapter.STATE_ON)
+        			{
+					try {
+						Thread.sleep(1000);
+						}
+        			catch (InterruptedException e)
+        				{
+						e.printStackTrace();
+        				}
+        			}
+        		
+            	sUniqueID = ba.getAddress();
+            	
+            	ba.disable();
+        		while(ba.getState() != BluetoothAdapter.STATE_OFF)
+    				{
+        			try {
+        				Thread.sleep(1000);
+						}
+        			catch (InterruptedException e)
+    					{
+        				e.printStackTrace();
+    					}
+    				}
+        		}
+        	else
+        		sUniqueID = ba.getAddress();
+        	}
+
+        if (sUniqueID == null)
+        	{
+        	TelephonyManager mTelephonyMgr = (TelephonyManager)getSystemService(TELEPHONY_SERVICE);
+        	if (mTelephonyMgr != null)
+        		{
+        		sUniqueID = mTelephonyMgr.getDeviceId();
+        		if (sUniqueID == null)
+        			{
+        			sUniqueID = "0011223344556677";
+        			}
+        		}
+        	}
+        
+        sLocalIPAddr = getLocalIpAddress();
+        Toast.makeText(getApplication().getApplicationContext(), "SUTAgent [" + sLocalIPAddr + "] ...", Toast.LENGTH_LONG).show();
+        
+        String sConfig = "Unique ID: " + sUniqueID + lineSep;
+        sConfig += "OS Info" + lineSep;
+        sConfig += "\t" + dc.GetOSInfo() + lineSep;
+        sConfig += "Screen Info" + lineSep;
+        int [] xy = dc.GetScreenXY();
+        sConfig += "\t Width: " + xy[0] + lineSep;
+        sConfig += "\t Height: " + xy[1] + lineSep;
+        sConfig += "Memory Info" + lineSep;
+        sConfig += "\t" + dc.GetMemoryInfo() + lineSep;
+        sConfig += "Network Info" + lineSep;
+        sConfig += "\tMac Address: " + macAddress + lineSep;
+        sConfig += "\tIP Address: " + sLocalIPAddr + lineSep;
+        
+        sRegString = "NAME=" + sUniqueID;
+        sRegString += "&IPADDR=" + sLocalIPAddr;
+        sRegString += "&CMDPORT=" + 20701;
+        sRegString += "&DATAPORT=" + 20700;
+        sRegString += "&OS=Android-" + dc.GetOSInfo();
+        sRegString += "&SCRNWIDTH=" + xy[0];
+        sRegString += "&SCRNHEIGHT=" + xy[1];
+        sRegString += "&BPP=8";
+        sRegString += "&MEMORY=" + dc.GetMemoryConfig();
+        sRegString += "&HARDWARE=" + HardwareID;
+        sRegString += "&POOL=" + Pool;
+        
+        String sTemp = Uri.encode(sRegString,"=&");
+        sRegString = "register " + sTemp;
+        
+        if (!bNetworkingStarted)
+        	{
+        	ToDoListening(1,300,dc);
+        	bNetworkingStarted = true;
+        	String sRegRet = "";
+        	if (RegSvrIPAddr.length() > 0)
+        		{
+        		sRegRet = dc.RegisterTheDevice(RegSvrIPAddr, RegSvrIPPort, sRegString);
+        		if (sRegRet.contains("\"ok\": true"))
+        			{
+        			sConfig += "Registered with testserver" + lineSep;
+        			sConfig += "\tIPAddress: " + RegSvrIPAddr + lineSep;
+        			if (RegSvrIPPort.length() > 0)
+        				sConfig += "\tPort: " + RegSvrIPPort + lineSep;
+        			}
+        		else
+        			sConfig += "Not registered with testserver" + lineSep;
+        		}
+    		else
+    			sConfig += "Not registered with testserver" + lineSep;
+        	}
+        
+        tv.setText(sConfig);
+        
+        monitorBatteryState();
+        
+        final Button goButton = (Button) findViewById(R.id.Button01);
+        goButton.setOnClickListener(new OnClickListener() {
+            public void onClick(View v) {
+    			finish();
+                }
+        	});
+        }
+    
+    protected void onActivityResult(int requestCode, int resultCode, Intent data)
+    	{
+        if (requestCode == START_PRG)
+        	{
+           	Toast.makeText(getApplication().getApplicationContext(), "SUTAgent startprg finished ...", Toast.LENGTH_LONG).show();
+        	}
+    	}
+    
+    @Override
+    public void onDestroy()
+    	{
+		super.onDestroy();
+    	if (isFinishing())
+    		{
+    		StopHeartBeat();
+    		Intent listenerSvc = new Intent();
+    		listenerSvc.setAction("com.mozilla.SUTAgentAndroid.service.LISTENER_SERVICE");
+    		stopService(listenerSvc);
+    		bNetworkingStarted = false;
+			unregisterReceiver(battReceiver);
+	        KeyguardManager km = (KeyguardManager)getSystemService(Context.KEYGUARD_SERVICE);
+	        if (km != null)
+	        	{
+	        	KeyguardManager.KeyguardLock kl = km.newKeyguardLock("SUTAgent");
+	        	if (kl != null)
+	        		kl.reenableKeyguard();
+	        	}
+	        
+//	        TextView  tv = (TextView) this.findViewById(R.id.Textview01);
+//	        if (tv != null)
+//	        	tv.setKeepScreenOn(false);
+	        
+	        if (pwl != null)
+	        	pwl.release();
+	        
+	    	if (wl != null)
+	    		wl.release();
+	    	
+	        System.exit(0);
+    		}
+    	}
+    
+    private void monitorBatteryState() 
+    	{
+		battReceiver = new BroadcastReceiver()
+			{
+			public void onReceive(Context context, Intent intent)
+				{
+				StringBuilder sb = new StringBuilder();
+
+				int rawlevel = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1); // charge level from 0 to scale inclusive
+				int scale = intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1); // Max value for charge level
+				int status = intent.getIntExtra(BatteryManager.EXTRA_STATUS, -1);
+				int health = intent.getIntExtra(BatteryManager.EXTRA_HEALTH, -1);
+				boolean present = intent.getBooleanExtra(BatteryManager.EXTRA_PRESENT, false);
+				int plugged = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1); //0 if the device is not plugged in; 1 if plugged into an AC power adapter; 2 if plugged in via USB.
+//				int voltage = intent.getIntExtra(BatteryManager.EXTRA_VOLTAGE, -1); // voltage in millivolts
+				nBatteryTemp = intent.getIntExtra(BatteryManager.EXTRA_TEMPERATURE, -1); // current battery temperature in tenths of a degree Centigrade
+//				String technology = intent.getStringExtra(BatteryManager.EXTRA_TECHNOLOGY);
+
+				nChargeLevel = -1;  // percentage, or -1 for unknown
+				if (rawlevel >= 0 && scale > 0)
+					{
+					nChargeLevel = (rawlevel * 100) / scale;
+					}
+				
+				if (plugged > 0)
+					sACStatus = "ONLINE";
+				else
+					sACStatus = "OFFLINE";
+				
+				if (present == false)
+					sb.append("NO BATTERY");
+				else
+					{
+					if (nChargeLevel < 10)
+						sb.append("Critical");
+					else if (nChargeLevel < 33)
+						sb.append("LOW");
+					else if (nChargeLevel > 80)
+						sb.append("HIGH");
+					}
+				
+				if (BatteryManager.BATTERY_HEALTH_OVERHEAT == health)
+					{
+					sb.append("Overheated ");
+					sb.append((((float)(nBatteryTemp))/10));
+					sb.append("(C)");
+					}
+				else
+					{
+					switch(status)
+						{
+						case BatteryManager.BATTERY_STATUS_UNKNOWN:
+							// old emulator; maybe also when plugged in with no battery
+							if (present == true)
+								sb.append(" UNKNOWN");
+							break;
+						case BatteryManager.BATTERY_STATUS_CHARGING:
+							sb.append(" CHARGING");
+							break;
+						case BatteryManager.BATTERY_STATUS_DISCHARGING:
+							sb.append(" DISCHARGING");
+							break;
+						case BatteryManager.BATTERY_STATUS_NOT_CHARGING:
+							sb.append(" NOTCHARGING");
+							break;
+						case BatteryManager.BATTERY_STATUS_FULL:
+							sb.append(" FULL");
+							break;
+						default:
+							if (present == true)
+								sb.append("Unknown");
+							break;
+						}
+					}
+				
+				sPowerStatus = sb.toString();
+				}
+			};
+			
+		IntentFilter battFilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
+		registerReceiver(battReceiver, battFilter);
+    	}
+ 
+    public boolean setUpNetwork()
+    	{
+    	boolean	bRet = false;
+    	int	lcv	= 0;
+    	int	lcv2 = 0;
+    	WifiManager wifi = (WifiManager) getSystemService(Context.WIFI_SERVICE);
+    	WifiConfiguration wc = new WifiConfiguration();
+    	
+		Toast.makeText(getApplication().getApplicationContext(), "Starting and configuring network", Toast.LENGTH_LONG).show();
+/*		
+		ContentResolver cr = getContentResolver();
+		int nRet;
+		try {
+			nRet = Settings.System.getInt(cr, Settings.System.WIFI_USE_STATIC_IP);
+			String foo2 = "" + nRet;
+		} catch (SettingNotFoundException e1) {
+			// TODO Auto-generated catch block
+			e1.printStackTrace();
+		}
+*/
+/*    	
+    	wc.SSID = "\"Mozilla-Build\"";
+    	wc.preSharedKey  = "\"MozillaBuildQA500\"";
+    	wc.hiddenSSID = true;
+    	wc.status = WifiConfiguration.Status.ENABLED;    
+    	wc.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);
+    	wc.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
+    	wc.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
+    	wc.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
+    	wc.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);
+    	wc.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
+    	wc.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
+*/    	
+    	wc.SSID = "\"Mozilla-G\"";
+//    	wc.SSID = "\"Mozilla\"";
+    	wc.preSharedKey  = null;
+    	wc.hiddenSSID = false;
+    	wc.status = WifiConfiguration.Status.ENABLED;
+    	
+    	wc.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_EAP);
+    	wc.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.IEEE8021X);
+
+    	wc.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
+//    	wc.allowedProtocols.set(WifiConfiguration.Protocol.WPA);
+
+//    	wc.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);
+    	wc.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
+
+//    	wc.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
+    	wc.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
+//    	wc.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP104);
+//    	wc.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP40);
+    	
+    	wc.eap.setValue("PEAP");
+    	wc.password.setValue("\"password\"");
+    	wc.identity.setValue("\"bmoss@mozilla.com\"");
+    	
+    	if (!wifi.isWifiEnabled())
+    		wifi.setWifiEnabled(true);
+    	
+    	while(wifi.getWifiState() != WifiManager.WIFI_STATE_ENABLED)
+    		{
+    		Thread.yield();
+    		if (++lcv > 10000)
+    			return(bRet);
+    		}
+    	
+    	wl = wifi.createWifiLock(WifiManager.WIFI_MODE_FULL, "SUTAgent");
+    	if (wl != null)
+    		wl.acquire();
+    	
+    	WifiConfiguration	foo = null;
+    	int					nNetworkID = -1;
+    	
+    	List<WifiConfiguration> connsLst =  wifi.getConfiguredNetworks();
+    	int nConns = connsLst.size();
+    	for (int i = 0; i < nConns; i++)
+    		{
+    		
+    		foo = connsLst.get(i);
+    		if (foo.SSID.equalsIgnoreCase(wc.SSID))
+    			{
+    			nNetworkID = foo.networkId;
+    			wc.networkId = foo.networkId;
+    			break;
+    			}
+    		}
+    	
+    	int res;
+    	
+    	if (nNetworkID != -1)
+    		{
+    		res = wifi.updateNetwork(wc);
+    		}
+    	else
+    		{
+        	res = wifi.addNetwork(wc);
+    		}
+    		
+    	Log.d("WifiPreference", "add Network returned " + res );
+    	
+    	boolean b = wifi.enableNetwork(res, true);        
+    	Log.d("WifiPreference", "enableNetwork returned " + b );
+    	
+    	wifi.saveConfiguration();
+    	
+    	WifiInfo wi = wifi.getConnectionInfo();
+    	SupplicantState ss = wi.getSupplicantState();
+    	
+    	lcv = 0;
+    	lcv2 = 0;
+    	
+    	while (ss.compareTo(SupplicantState.COMPLETED) != 0)
+    		{
+    		try {
+				Thread.sleep(1000);
+				}
+    		catch (InterruptedException e)
+    			{
+				e.printStackTrace();
+    			}
+    		
+    		if (wi != null)
+    			wi = null;
+    		if (ss != null)
+    			ss = null;
+    		wi = wifi.getConnectionInfo();
+    		ss = wi.getSupplicantState();
+    		if (++lcv > 60)
+    			{
+    			if (++lcv2 > 5)
+    				{
+    				Toast.makeText(getApplication().getApplicationContext(), "Unable to start and configure network", Toast.LENGTH_LONG).show();
+    				return(bRet);
+    				}
+    			else
+    				{
+    				Toast.makeText(getApplication().getApplicationContext(), "Resetting wifi interface", Toast.LENGTH_LONG).show();
+    		    	if (wl != null)
+    		    		wl.release();
+    	    		wifi.setWifiEnabled(false);
+    	        	while(wifi.getWifiState() != WifiManager.WIFI_STATE_DISABLED)
+    	    			{
+    	        		Thread.yield();
+    	    			}
+    	        	
+    	    		wifi.setWifiEnabled(true);
+    	        	while(wifi.getWifiState() != WifiManager.WIFI_STATE_ENABLED)
+	    				{
+    	        		Thread.yield();
+	    				}
+    	        	b = wifi.enableNetwork(res, true);        
+    	        	Log.d("WifiPreference", "enableNetwork returned " + b );
+    	        	if (wl != null)
+    	        		wl.acquire();
+    	    		lcv = 0;
+    				}
+    			}
+    		}
+    	
+    	lcv = 0;
+    	while(getLocalIpAddress() == null)
+    		{
+    		if (++lcv > 10000)
+    			return(bRet);
+    		}
+    	
+		Toast.makeText(getApplication().getApplicationContext(), "Network started and configured", Toast.LENGTH_LONG).show();
+    	bRet = true;
+    	
+    	return(bRet);
+    	}
+    
+    class ToDoListener extends TimerTask 
+    	{
+    	boolean 	bFirstRun = true;
+    	DoCommand	dc = null;
+    	
+    	ToDoListener(DoCommand dc)
+    		{
+    		this.dc = dc;
+    		}
+    	
+		public void run ()
+			{
+			if (bFirstRun == true)
+				{
+				Intent listenerService = new Intent();
+				listenerService.setAction("com.mozilla.SUTAgentAndroid.service.LISTENER_SERVICE");
+				startService(listenerService);
+				bFirstRun = false;
+				}
+			else
+				{
+				if (dc != null)
+					{
+					String sRet = this.dc.SendPing("www.mozilla.org", null);
+					if (sRet.contains("3 received"))
+						this.dc.StopAlert();
+					else
+						this.dc.StartAlert();
+					sRet = null;
+					System.gc();
+					}	
+				}
+			}
+		}
+	
+	public void ToDoListening(int delay, int interval, DoCommand dc)
+		{
+		if (timer == null)
+			timer = new Timer();
+		timer.scheduleAtFixedRate(new ToDoListener(dc), delay * 1000, interval * 1000);
+//		timer.schedule(new ToDoListener(dc), delay * 1000);
+		}
+
+	class DoHeartBeat extends TimerTask
+		{
+    	PrintWriter out;
+	
+    	DoHeartBeat(PrintWriter out)
+			{
+    		this.out = out;
+			}
+	
+    	public void run ()
+			{
+    		String sRet = "";
+    		
+    		Calendar cal = Calendar.getInstance();
+    		SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd-HH:mm:ss");
+    		sRet = sdf.format(cal.getTime());
+    		sRet += " Thump thump - " + sUniqueID + "\r\n";
+
+    		out.write(sRet);
+    		out.flush();
+			}
+		}
+
+	public void StartHeartBeat(PrintWriter out)
+		{
+		// start the heartbeat
+		this.dataOut = out;
+		if (timer == null)
+			timer = new Timer();
+		timer.scheduleAtFixedRate(new DoHeartBeat(dataOut), 0, 60000);
+		}
+	
+	public void StopHeartBeat()
+		{
+		// stop the heartbeat
+		this.dataOut = null;
+		if (timer != null)
+			{
+			timer.cancel();
+			timer.purge();
+			timer = null;
+			System.gc();
+			}
+		}
+	
+	public String getLocalIpAddress()
+		{
+		try
+    		{
+			for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements();) 
+        		{
+				NetworkInterface intf = en.nextElement();
+				for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements();) 
+            		{
+					InetAddress inetAddress = enumIpAddr.nextElement();
+					if (!inetAddress.isLoopbackAddress()) 
+                		{
+						return inetAddress.getHostAddress().toString();
+                		}
+            		}
+        		}
+    		} 
+		catch (SocketException ex)
+    		{
+			Toast.makeText(getApplication().getApplicationContext(), ex.toString(), Toast.LENGTH_LONG).show();
+    		}
+		return null;
+		}
+}
\ No newline at end of file
new file mode 100755
--- /dev/null
+++ b/build/mobile/sutagent/android/SUTStartupIntentReceiver.java
@@ -0,0 +1,53 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Android SUTAgent code.
+ *
+ * The Initial Developer of the Original Code is
+ * Bob Moss.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *  Bob Moss <bmoss@mozilla.com>
+ * 
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+package com.mozilla.SUTAgentAndroid;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+
+public class SUTStartupIntentReceiver extends BroadcastReceiver
+{
+	@Override
+	public void onReceive(Context context, Intent intent)
+		{
+		Intent mySUTAgentIntent = new Intent(context, SUTAgentAndroid.class);
+		mySUTAgentIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);  
+		context.startActivity(mySUTAgentIntent);
+		}
+}
new file mode 100755
--- /dev/null
+++ b/build/mobile/sutagent/android/WifiConfiguration.java
@@ -0,0 +1,480 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi;
+
+import android.os.Parcelable;
+import android.os.Parcel;
+
+import java.util.BitSet;
+
+/**
+ * A class representing a configured Wi-Fi network, including the
+ * security configuration. Android will not necessarily support
+ * all of these security schemes initially.
+ */
+public class WifiConfiguration implements Parcelable {
+
+    /** {@hide} */
+    public static final String ssidVarName = "ssid";
+    /** {@hide} */
+    public static final String bssidVarName = "bssid";
+    /** {@hide} */
+    public static final String pskVarName = "psk";
+    /** {@hide} */
+    public static final String[] wepKeyVarNames = { "wep_key0", "wep_key1", "wep_key2", "wep_key3" };
+    /** {@hide} */
+    public static final String wepTxKeyIdxVarName = "wep_tx_keyidx";
+    /** {@hide} */
+    public static final String priorityVarName = "priority";
+    /** {@hide} */
+    public static final String hiddenSSIDVarName = "scan_ssid";
+
+    public class EnterpriseField {
+        private String varName;
+        private String value;
+
+        private EnterpriseField(String varName) {
+            this.varName = varName;
+            this.value = null;
+        }
+
+        public void setValue(String value) {
+            this.value = value;
+        }
+
+        public String varName() {
+            return varName;
+        }
+
+        public String value() {
+            return value;
+        }
+    }
+
+    public EnterpriseField eap = new EnterpriseField("eap");
+    public EnterpriseField phase2 = new EnterpriseField("phase2");
+    public EnterpriseField identity = new EnterpriseField("identity");
+    public EnterpriseField anonymous_identity = new EnterpriseField("anonymous_identity");
+    public EnterpriseField password = new EnterpriseField("password");
+    public EnterpriseField client_cert = new EnterpriseField("client_cert");
+    public EnterpriseField private_key = new EnterpriseField("private_key");
+    public EnterpriseField ca_cert = new EnterpriseField("ca_cert");
+
+    public EnterpriseField[] enterpriseFields = {
+            eap, phase2, identity, anonymous_identity, password, client_cert,
+            private_key, ca_cert };
+
+    /**
+     * Recognized key management schemes.
+     */
+    public static class KeyMgmt {
+        private KeyMgmt() { }
+
+        /** WPA is not used; plaintext or static WEP could be used. */
+        public static final int NONE = 0;
+        /** WPA pre-shared key (requires {@code preSharedKey} to be specified). */
+        public static final int WPA_PSK = 1;
+        /** WPA using EAP authentication. Generally used with an external authentication server. */
+        public static final int WPA_EAP = 2;
+        /** IEEE 802.1X using EAP authentication and (optionally) dynamically
+         * generated WEP keys. */
+        public static final int IEEE8021X = 3;
+
+        public static final String varName = "key_mgmt";
+
+        public static final String[] strings = { "NONE", "WPA_PSK", "WPA_EAP", "IEEE8021X" };
+    }
+
+    /**
+     * Recognized security protocols.
+     */
+    public static class Protocol {
+        private Protocol() { }
+
+        /** WPA/IEEE 802.11i/D3.0 */
+        public static final int WPA = 0;
+        /** WPA2/IEEE 802.11i */
+        public static final int RSN = 1;
+
+        public static final String varName = "proto";
+
+        public static final String[] strings = { "WPA", "RSN" };
+    }
+
+    /**
+     * Recognized IEEE 802.11 authentication algorithms.
+     */
+    public static class AuthAlgorithm {
+        private AuthAlgorithm() { }
+
+        /** Open System authentication (required for WPA/WPA2) */
+        public static final int OPEN = 0;
+        /** Shared Key authentication (requires static WEP keys) */
+        public static final int SHARED = 1;
+        /** LEAP/Network EAP (only used with LEAP) */
+        public static final int LEAP = 2;
+
+        public static final String varName = "auth_alg";
+
+        public static final String[] strings = { "OPEN", "SHARED", "LEAP" };
+    }
+
+    /**
+     * Recognized pairwise ciphers for WPA.
+     */
+    public static class PairwiseCipher {
+        private PairwiseCipher() { }
+
+        /** Use only Group keys (deprecated) */
+        public static final int NONE = 0;
+        /** Temporal Key Integrity Protocol [IEEE 802.11i/D7.0] */
+        public static final int TKIP = 1;
+        /** AES in Counter mode with CBC-MAC [RFC 3610, IEEE 802.11i/D7.0] */
+        public static final int CCMP = 2;
+
+        public static final String varName = "pairwise";
+
+        public static final String[] strings = { "NONE", "TKIP", "CCMP" };
+    }
+
+    /**
+     * Recognized group ciphers.
+     * <pre>
+     * CCMP = AES in Counter mode with CBC-MAC [RFC 3610, IEEE 802.11i/D7.0]
+     * TKIP = Temporal Key Integrity Protocol [IEEE 802.11i/D7.0]
+     * WEP104 = WEP (Wired Equivalent Privacy) with 104-bit key
+     * WEP40 = WEP (Wired Equivalent Privacy) with 40-bit key (original 802.11)
+     * </pre>
+     */
+    public static class GroupCipher {
+        private GroupCipher() { }
+
+        /** WEP40 = WEP (Wired Equivalent Privacy) with 40-bit key (original 802.11) */
+        public static final int WEP40 = 0;
+        /** WEP104 = WEP (Wired Equivalent Privacy) with 104-bit key */
+        public static final int WEP104 = 1;
+        /** Temporal Key Integrity Protocol [IEEE 802.11i/D7.0] */
+        public static final int TKIP = 2;
+        /** AES in Counter mode with CBC-MAC [RFC 3610, IEEE 802.11i/D7.0] */
+        public static final int CCMP = 3;
+
+        public static final String varName = "group";
+
+        public static final String[] strings = { "WEP40", "WEP104", "TKIP", "CCMP" };
+    }
+
+    /** Possible status of a network configuration. */
+    public static class Status {
+        private Status() { }
+
+        /** this is the network we are currently connected to */
+        public static final int CURRENT = 0;
+        /** supplicant will not attempt to use this network */
+        public static final int DISABLED = 1;
+        /** supplicant will consider this network available for association */
+        public static final int ENABLED = 2;
+
+        public static final String[] strings = { "current", "disabled", "enabled" };
+    }
+
+    /**
+     * The ID number that the supplicant uses to identify this
+     * network configuration entry. This must be passed as an argument
+     * to most calls into the supplicant.
+     */
+    public int networkId;
+
+    /**
+     * The current status of this network configuration entry.
+     * @see Status
+     */
+    public int status;
+    /**
+     * The network's SSID. Can either be an ASCII string,
+     * which must be enclosed in double quotation marks
+     * (e.g., {@code &quot;MyNetwork&quot;}, or a string of
+     * hex digits,which are not enclosed in quotes
+     * (e.g., {@code 01a243f405}).
+     */
+    public String SSID;
+    /**
+     * When set, this network configuration entry should only be used when
+     * associating with the AP having the specified BSSID. The value is
+     * a string in the format of an Ethernet MAC address, e.g.,
+     * <code>XX:XX:XX:XX:XX:XX</code> where each <code>X</code> is a hex digit.
+     */
+    public String BSSID;
+
+    /**
+     * Pre-shared key for use with WPA-PSK.
+     * <p/>
+     * When the value of this key is read, the actual key is
+     * not returned, just a "*" if the key has a value, or the null
+     * string otherwise.
+     */
+    public String preSharedKey;
+    /**
+     * Up to four WEP keys. Either an ASCII string enclosed in double
+     * quotation marks (e.g., {@code &quot;abcdef&quot;} or a string
+     * of hex digits (e.g., {@code 0102030405}).
+     * <p/>
+     * When the value of one of these keys is read, the actual key is
+     * not returned, just a "*" if the key has a value, or the null
+     * string otherwise.
+     */
+    public String[] wepKeys;
+
+    /** Default WEP key index, ranging from 0 to 3. */
+    public int wepTxKeyIndex;
+
+    /**
+     * Priority determines the preference given to a network by {@code wpa_supplicant}
+     * when choosing an access point with which to associate.
+     */
+    public int priority;
+
+    /**
+     * This is a network that does not broadcast its SSID, so an
+     * SSID-specific probe request must be used for scans.
+     */
+    public boolean hiddenSSID;
+
+    /**
+     * The set of key management protocols supported by this configuration.
+     * See {@link KeyMgmt} for descriptions of the values.
+     * Defaults to WPA-PSK WPA-EAP.
+     */
+    public BitSet allowedKeyManagement;
+    /**
+     * The set of security protocols supported by this configuration.
+     * See {@link Protocol} for descriptions of the values.
+     * Defaults to WPA RSN.
+     */
+    public BitSet allowedProtocols;
+    /**
+     * The set of authentication protocols supported by this configuration.
+     * See {@link AuthAlgorithm} for descriptions of the values.
+     * Defaults to automatic selection.
+     */
+    public BitSet allowedAuthAlgorithms;
+    /**
+     * The set of pairwise ciphers for WPA supported by this configuration.
+     * See {@link PairwiseCipher} for descriptions of the values.
+     * Defaults to CCMP TKIP.
+     */
+    public BitSet allowedPairwiseCiphers;
+    /**
+     * The set of group ciphers supported by this configuration.
+     * See {@link GroupCipher} for descriptions of the values.
+     * Defaults to CCMP TKIP WEP104 WEP40.
+     */
+    public BitSet allowedGroupCiphers;
+
+
+    public WifiConfiguration() {
+        networkId = -1;
+        SSID = null;
+        BSSID = null;
+        priority = 0;
+        hiddenSSID = false;
+        allowedKeyManagement = new BitSet();
+        allowedProtocols = new BitSet();
+        allowedAuthAlgorithms = new BitSet();
+        allowedPairwiseCiphers = new BitSet();
+        allowedGroupCiphers = new BitSet();
+        wepKeys = new String[4];
+        for (int i = 0; i < wepKeys.length; i++)
+            wepKeys[i] = null;
+        for (EnterpriseField field : enterpriseFields) {
+            field.setValue(null);
+        }
+    }
+
+    public String toString() {
+        StringBuffer sbuf = new StringBuffer();
+        if (this.status == WifiConfiguration.Status.CURRENT) {
+            sbuf.append("* ");
+        } else if (this.status == WifiConfiguration.Status.DISABLED) {
+            sbuf.append("- ");
+        }
+        sbuf.append("ID: ").append(this.networkId).append(" SSID: ").append(this.SSID).
+                append(" BSSID: ").append(this.BSSID).append(" PRIO: ").append(this.priority).
+                append('\n');
+        sbuf.append(" KeyMgmt:");
+        for (int k = 0; k < this.allowedKeyManagement.size(); k++) {
+            if (this.allowedKeyManagement.get(k)) {
+                sbuf.append(" ");
+                if (k < KeyMgmt.strings.length) {
+                    sbuf.append(KeyMgmt.strings[k]);
+                } else {
+                    sbuf.append("??");
+                }
+            }
+        }
+        sbuf.append(" Protocols:");
+        for (int p = 0; p < this.allowedProtocols.size(); p++) {
+            if (this.allowedProtocols.get(p)) {
+                sbuf.append(" ");
+                if (p < Protocol.strings.length) {
+                    sbuf.append(Protocol.strings[p]);
+                } else {
+                    sbuf.append("??");
+                }
+            }
+        }
+        sbuf.append('\n');
+        sbuf.append(" AuthAlgorithms:");
+        for (int a = 0; a < this.allowedAuthAlgorithms.size(); a++) {
+            if (this.allowedAuthAlgorithms.get(a)) {
+                sbuf.append(" ");
+                if (a < AuthAlgorithm.strings.length) {
+                    sbuf.append(AuthAlgorithm.strings[a]);
+                } else {
+                    sbuf.append("??");
+                }
+            }
+        }
+        sbuf.append('\n');
+        sbuf.append(" PairwiseCiphers:");
+        for (int pc = 0; pc < this.allowedPairwiseCiphers.size(); pc++) {
+            if (this.allowedPairwiseCiphers.get(pc)) {
+                sbuf.append(" ");
+                if (pc < PairwiseCipher.strings.length) {
+                    sbuf.append(PairwiseCipher.strings[pc]);
+                } else {
+                    sbuf.append("??");
+                }
+            }
+        }
+        sbuf.append('\n');
+        sbuf.append(" GroupCiphers:");
+        for (int gc = 0; gc < this.allowedGroupCiphers.size(); gc++) {
+            if (this.allowedGroupCiphers.get(gc)) {
+                sbuf.append(" ");
+                if (gc < GroupCipher.strings.length) {
+                    sbuf.append(GroupCipher.strings[gc]);
+                } else {
+                    sbuf.append("??");
+                }
+            }
+        }
+        sbuf.append('\n').append(" PSK: ");
+        if (this.preSharedKey != null) {
+            sbuf.append('*');
+        }
+
+        for (EnterpriseField field : enterpriseFields) {
+            sbuf.append('\n').append(" " + field.varName() + ": ");
+            String value = field.value();
+            if (value != null) sbuf.append(value);
+        }
+        sbuf.append('\n');
+        return sbuf.toString();
+    }
+
+    /**
+     * Construct a WifiConfiguration from a scanned network
+     * @param scannedAP the scan result used to construct the config entry
+     * TODO: figure out whether this is a useful way to construct a new entry.
+     *
+    public WifiConfiguration(ScanResult scannedAP) {
+        networkId = -1;
+        SSID = scannedAP.SSID;
+        BSSID = scannedAP.BSSID;
+    }
+    */
+
+    private static BitSet readBitSet(Parcel src) {
+        int cardinality = src.readInt();
+
+        BitSet set = new BitSet();
+        for (int i = 0; i < cardinality; i++)
+            set.set(src.readInt());
+
+        return set;
+    }
+
+    private static void writeBitSet(Parcel dest, BitSet set) {
+        int nextSetBit = -1;
+
+        dest.writeInt(set.cardinality());
+
+        while ((nextSetBit = set.nextSetBit(nextSetBit + 1)) != -1)
+            dest.writeInt(nextSetBit);
+    }
+
+    /** Implement the Parcelable interface {@hide} */
+    public int describeContents() {
+        return 0;
+    }
+
+    /** Implement the Parcelable interface {@hide} */
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeInt(networkId);
+        dest.writeInt(status);
+        dest.writeString(SSID);
+        dest.writeString(BSSID);
+        dest.writeString(preSharedKey);
+        for (String wepKey : wepKeys)
+            dest.writeString(wepKey);
+        dest.writeInt(wepTxKeyIndex);
+        dest.writeInt(priority);
+        dest.writeInt(hiddenSSID ? 1 : 0);
+
+        writeBitSet(dest, allowedKeyManagement);
+        writeBitSet(dest, allowedProtocols);
+        writeBitSet(dest, allowedAuthAlgorithms);
+        writeBitSet(dest, allowedPairwiseCiphers);
+        writeBitSet(dest, allowedGroupCiphers);
+
+        for (EnterpriseField field : enterpriseFields) {
+            dest.writeString(field.value());
+        }
+    }
+
+    /** Implement the Parcelable interface {@hide} */
+    public static final Creator<WifiConfiguration> CREATOR =
+        new Creator<WifiConfiguration>() {
+            public WifiConfiguration createFromParcel(Parcel in) {
+                WifiConfiguration config = new WifiConfiguration();
+                config.networkId = in.readInt();
+                config.status = in.readInt();
+                config.SSID = in.readString();
+                config.BSSID = in.readString();
+                config.preSharedKey = in.readString();
+                for (int i = 0; i < config.wepKeys.length; i++)
+                    config.wepKeys[i] = in.readString();
+                config.wepTxKeyIndex = in.readInt();
+                config.priority = in.readInt();
+                config.hiddenSSID = in.readInt() != 0;
+                config.allowedKeyManagement   = readBitSet(in);
+                config.allowedProtocols       = readBitSet(in);
+                config.allowedAuthAlgorithms  = readBitSet(in);
+                config.allowedPairwiseCiphers = readBitSet(in);
+                config.allowedGroupCiphers    = readBitSet(in);
+
+                for (EnterpriseField field : config.enterpriseFields) {
+                    field.setValue(in.readString());
+                }
+                return config;
+            }
+
+            public WifiConfiguration[] newArray(int size) {
+                return new WifiConfiguration[size];
+            }
+        };
+}
new file mode 100644
--- /dev/null
+++ b/build/mobile/sutagent/android/default.properties
@@ -0,0 +1,13 @@
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+# 
+# This file must be checked in Version Control Systems.
+# 
+# To customize properties used by the Ant build system use,
+# "build.properties", and override values to adapt the script to your
+# project structure.
+
+# Indicates whether an apk should be generated for each density.
+split.density=false
+# Project target.
+target=android-5
new file mode 100755
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..c68405dcd258e618cb9db8886bed618166ecc6f9
GIT binary patch
literal 1714760
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