Merge mozilla-central to tracemonkey.
authorRobert Sayre <sayrer@gmail.com>
Tue, 20 Jul 2010 15:07:03 -0700
changeset 48514 7497dbffa9a7e09bc8bdd7d3c695cadd1c53976e
parent 48512 5384ab5eb6c19553014439f6c76a1845517122a0 (current diff)
parent 47986 3cc0b56a0519077a197c2e026d200d9ecb2becae (diff)
child 48515 6d7b95761119b268a7d4b470bcd9b1bbd63656a7
push id1
push userroot
push dateTue, 26 Apr 2011 22:38:44 +0000
treeherdermozilla-beta@bfdb6e623a36 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone2.0b2pre
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge mozilla-central to tracemonkey.
browser/components/privatebrowsing/test/browser/browser_privatebrowsing_contextmenu_blockimage.js
browser/themes/winstripe/browser/tabbrowser/alltabs-aero.png
browser/themes/winstripe/browser/tabbrowser/newtab-aero.png
browser/themes/winstripe/browser/tabbrowser/tab-arrow-left-aero.png
browser/themes/winstripe/browser/tabbrowser/tab-arrow-right-aero.png
browser/themes/winstripe/browser/tabbrowser/tab-arrow-right.png
browser/themes/winstripe/browser/tabbrowser/tabDragIndicator-aero.png
content/base/public/nsContentUtils.h
content/base/src/nsContentUtils.cpp
content/base/src/nsFrameMessageManager.cpp
content/base/src/nsInProcessTabChildGlobal.cpp
content/canvas/src/CustomQS_WebGL.h
content/canvas/test/webgl/conformance/bug-31889.html
content/canvas/test/webgl/conformance/bug-32364.html
content/canvas/test/webgl/conformance/bug-32456.html
content/canvas/test/webgl/conformance/bug-32619.html
content/canvas/test/webgl/conformance/bug-32692.html
content/canvas/test/webgl/conformance/bug-32888.html
content/canvas/test/webgl/conformance/gl-bindattribLocation-test.html
content/canvas/test/webgl/conformance/gl-vertexattrib.html
content/canvas/test/webgl/conformance/readpixels-test.html
content/canvas/test/webgl/conformance/resources/array-unit-tests.js
content/canvas/test/webgl/conformance/resources/error-reporting.js
content/canvas/test/webgl/conformance/resources/get-active-test.js
content/canvas/test/webgl/conformance/resources/gl-object-get-calls.js
content/canvas/test/webgl/conformance/resources/incorrect-context-object-behaviour.js
content/canvas/test/webgl/conformance/resources/index-validation.js
content/canvas/test/webgl/conformance/resources/null-object-behaviour.js
content/canvas/test/webgl/conformance/resources/uniform-location.js
content/canvas/test/webgl/conformance/resources/utils3d.js
content/canvas/test/webgl/test_list.txt.js
content/html/content/public/nsIOptionElement.h
content/html/document/src/nsHTMLDocument.cpp
content/svg/content/src/nsSVGAnimatedLengthList.cpp
content/svg/content/src/nsSVGAnimatedLengthList.h
content/svg/content/src/nsSVGLength.cpp
content/svg/content/src/nsSVGLength.h
content/svg/content/src/nsSVGLengthList.cpp
content/svg/content/src/nsSVGLengthList.h
content/xbl/public/nsIXBLDocumentInfo.h
content/xbl/src/nsBindingManager.cpp
content/xbl/src/nsXBLBinding.cpp
content/xbl/src/nsXBLDocumentInfo.cpp
dom/base/nsDOMClassInfo.cpp
dom/base/nsDOMWindowUtils.cpp
dom/base/nsGlobalWindow.cpp
dom/interfaces/geolocation/nsIGeolocationProvider.idl
dom/ipc/ContentProcessChild.cpp
dom/ipc/ContentProcessChild.h
dom/ipc/ContentProcessParent.cpp
dom/ipc/ContentProcessParent.h
dom/ipc/ContentProcessProcess.cpp
dom/ipc/ContentProcessProcess.h
dom/ipc/PContentProcess.ipdl
dom/ipc/PIFrameEmbedding.ipdl
dom/ipc/TabChild.cpp
dom/src/geolocation/AndroidLocationProvider.cpp
dom/src/geolocation/AndroidLocationProvider.h
dom/src/geolocation/GPSDGeolocationProvider.js
dom/src/geolocation/GPSDGeolocationProvider.manifest
dom/src/geolocation/MaemoLocationProvider.cpp
dom/src/geolocation/MaemoLocationProvider.h
dom/src/geolocation/NetworkGeolocationProvider.js
dom/src/geolocation/NetworkGeolocationProvider.manifest
dom/src/geolocation/WinMobileLocationProvider.cpp
dom/src/geolocation/WinMobileLocationProvider.h
editor/docs/Editor_Embedding_Guide.html
editor/docs/midas-spec.html
gfx/src/thebes/crashtests/306902-1.xml
gfx/src/thebes/crashtests/383872-1.svg
gfx/src/thebes/crashtests/423110-1.xhtml
gfx/src/thebes/crashtests/445711.html
gfx/src/thebes/crashtests/crashtests.list
gfx/src/thebes/utils/Makefile.in
gfx/src/thebes/utils/gfxBlur.cpp
gfx/src/thebes/utils/gfxBlur.h
gfx/src/thebes/utils/gfxThebesUtils.cpp
gfx/src/thebes/utils/gfxThebesUtils.h
gfx/src/thebes/utils/nsCoreAnimationSupport.h
gfx/src/thebes/utils/nsCoreAnimationSupport.mm
gfx/tests/coverage/Makefile.in
gfx/tests/coverage/main.cpp
gfx/tests/coverage/nsCoverage.cpp
gfx/thebes/crashtests/122875-1.html
gfx/thebes/crashtests/156882-1.html
gfx/thebes/crashtests/157320-1.html
gfx/thebes/crashtests/199379-1.html
gfx/thebes/crashtests/206561-1.html
gfx/thebes/crashtests/248518-1.html
gfx/thebes/crashtests/306649-1.xml
gfx/thebes/crashtests/333861-1.html
gfx/thebes/crashtests/334735-1.html
gfx/thebes/crashtests/345576-1.html
gfx/thebes/crashtests/345629-1.html
gfx/thebes/crashtests/348462-1.html
gfx/thebes/crashtests/348462-2.html
gfx/thebes/crashtests/369688-1.html
gfx/thebes/crashtests/369947-1.html
gfx/thebes/crashtests/372094-1.xhtml
gfx/thebes/crashtests/376627-1.html
gfx/thebes/crashtests/377231-1.html
gfx/thebes/crashtests/377232-1.xhtml
gfx/thebes/crashtests/377461-1.xhtml
gfx/thebes/crashtests/383473-1.html
gfx/thebes/crashtests/385228-1.svg
gfx/thebes/crashtests/385228-2.svg
gfx/thebes/crashtests/385289-1.xhtml
gfx/thebes/crashtests/385417-1.html
gfx/thebes/crashtests/385417-2.html
gfx/thebes/crashtests/385423-1.html
gfx/thebes/crashtests/385423-2.html
gfx/thebes/crashtests/385719-1.html
gfx/thebes/crashtests/389326-1-inner.xhtml
gfx/thebes/crashtests/389326-1.html
gfx/thebes/crashtests/393746-1.xhtml
gfx/thebes/crashtests/393749-1.html
gfx/thebes/crashtests/393822-1.html
gfx/thebes/crashtests/394246-1.html
gfx/thebes/crashtests/394246-2.html
gfx/thebes/crashtests/394384-1.html
gfx/thebes/crashtests/395335-1.xhtml
gfx/thebes/crashtests/395458-1.html
gfx/thebes/crashtests/396321-1.svg
gfx/thebes/crashtests/398042-1.xhtml
gfx/thebes/crashtests/398042-2.xhtml
gfx/thebes/crashtests/402307-1.html
gfx/thebes/crashtests/403464-1.html
gfx/thebes/crashtests/404112-1.html
gfx/thebes/crashtests/404112-2.html
gfx/thebes/crashtests/405268-1.xhtml
gfx/thebes/crashtests/407761-1.html
gfx/thebes/crashtests/407842.html
gfx/thebes/crashtests/408754-1.html
gfx/thebes/crashtests/410728-1.xml
gfx/thebes/crashtests/416637-1.html
gfx/thebes/crashtests/419095-1.html
gfx/thebes/crashtests/419255-1.html
gfx/thebes/crashtests/420945-1.html
gfx/thebes/crashtests/420962-1.html
gfx/thebes/crashtests/421393-1.html
gfx/thebes/crashtests/421813-1.html
gfx/thebes/crashtests/423270-1.html
gfx/thebes/crashtests/429899-1.html
gfx/thebes/crashtests/441360.html
gfx/thebes/crashtests/441360_data.gif
gfx/thebes/crashtests/463307-1.html
gfx/thebes/crashtests/467703-1.xhtml
gfx/thebes/crashtests/467873-1.html
gfx/thebes/crashtests/470418-1.html
gfx/thebes/crashtests/474410-1.html
gfx/thebes/crashtests/483120-1.xhtml
gfx/thebes/crashtests/483120-2.xhtml
gfx/thebes/crashtests/487549-1.html
gfx/thebes/crashtests/487549-bad_kern_table.ttf
gfx/thebes/crashtests/487724-1.html
gfx/thebes/crashtests/490777-1.html
gfx/thebes/crashtests/532726-1.html
gfx/thebes/crashtests/538065-1.html
gfx/thebes/crashtests/546870-1.html
gfx/thebes/crashtests/balinese-letter-spacing.html
gfx/thebes/crashtests/crashtests.list
gfx/thebes/mochitest/Makefile.in
gfx/thebes/mochitest/test_bug509244.html
gfx/thebes/mochitest/test_bug513439.html
gfx/thebes/test/Makefile.in
gfx/thebes/test/gfxColorManagementTest.cmtest
gfx/thebes/test/gfxColorManagementTest.cpp
gfx/thebes/test/gfxFontSelectionTest.cpp
gfx/thebes/test/gfxFontSelectionTests.h
gfx/thebes/test/gfxSurfaceRefCountTest.cpp
gfx/thebes/test/gfxTestCocoaHelper.h
gfx/thebes/test/gfxTestCocoaHelper.mm
gfx/thebes/test/gfxTextRunPerfTest.cpp
gfx/thebes/test/gfxWordCacheTest.cpp
gfx/thebes/test/per-word-runs.h
gfx/thebes/test/process-textruns.pl
gfx/thebes/test/testprofiles/DELL2407WFP-2B283C91.icc
gfx/thebes/test/testprofiles/G22LWk-2489A79.icc
gfx/thebes/test/testprofiles/MBP20080419-1.icc
gfx/thebes/test/testprofiles/PhLCD17a.icm
gfx/thebes/test/testprofiles/identity.icc
gfx/thebes/test/testprofiles/murphy.icc
gfx/thebes/test/testprofiles/sRGB_IEC61966-2-1_noBPC.icc
gfx/thebes/test/testprofiles/sRGB_IEC61966-2-1_withBPC.icc
gfx/thebes/test/testprofiles/sRGB_v4_ICC_preference.icc
ipc/testshell/TestShellParent.cpp
ipc/testshell/XPCShellEnvironment.cpp
js/ipc/ObjectWrapperChild.cpp
js/ipc/ObjectWrapperParent.cpp
js/jetpack/JetpackParent.cpp
js/src/Makefile.in
js/src/configure.in
js/src/ctypes/CTypes.cpp
js/src/ctypes/Library.cpp
js/src/jstypedarray.cpp
js/src/xpconnect/src/dom_quickstubs.qsconf
js/src/xpconnect/src/xpcprivate.h
js/src/xpconnect/src/xpcquickstubs.cpp
js/src/xpconnect/src/xpcquickstubs.h
js/src/xpconnect/src/xpcstring.cpp
layout/style/nsCSSDeclaration.cpp
layout/style/nsCSSDeclaration.h
layout/style/nsCSSLoader.cpp
layout/style/nsCSSLoader.h
modules/plugin/base/src/nsNPAPIPlugin.cpp
modules/plugin/base/src/nsNPAPIPlugin.h
security/nss/lib/pki1/Makefile
security/nss/lib/pki1/atav.c
security/nss/lib/pki1/config.mk
security/nss/lib/pki1/genname.c
security/nss/lib/pki1/gnseq.c
security/nss/lib/pki1/manifest.mn
security/nss/lib/pki1/name.c
security/nss/lib/pki1/nsspki1.h
security/nss/lib/pki1/nsspki1t.h
security/nss/lib/pki1/oid.c
security/nss/lib/pki1/oiddata.c
security/nss/lib/pki1/oiddata.h
security/nss/lib/pki1/oidgen.perl
security/nss/lib/pki1/oids.txt
security/nss/lib/pki1/pki1.h
security/nss/lib/pki1/pki1t.h
security/nss/lib/pki1/rdn.c
security/nss/lib/pki1/rdnseq.c
security/patches/bug-519550.patch
toolkit/themes/winstripe/global/icons/close-aero.png
toolkit/themes/winstripe/global/icons/closeSidebar-aero.png
toolkit/themes/winstripe/global/icons/closeSidebar.png
xpcom/io/nsLocalFileOSX.h
xpcom/io/nsLocalFileOSX.mm
--- a/accessible/src/base/AccGroupInfo.cpp
+++ b/accessible/src/base/AccGroupInfo.cpp
@@ -35,16 +35,17 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "AccGroupInfo.h"
 
 AccGroupInfo::AccGroupInfo(nsAccessible* aItem, PRUint32 aRole) :
   mPosInSet(0), mSetSize(0), mParent(nsnull)
 {
+  MOZ_COUNT_CTOR(AccGroupInfo);
   nsAccessible* parent = aItem->GetParent();
   if (!parent)
     return;
 
   PRInt32 indexInParent = aItem->GetIndexInParent();
   PRInt32 level = nsAccUtils::GetARIAOrDefaultLevel(aItem);
 
   // Compute position in set.
--- a/accessible/src/base/AccGroupInfo.h
+++ b/accessible/src/base/AccGroupInfo.h
@@ -43,17 +43,17 @@
 
 /**
  * Calculate and store group information.
  */
 class AccGroupInfo
 {
 public:
   AccGroupInfo(nsAccessible* aItem, PRUint32 aRole);
-  ~AccGroupInfo() { }
+  ~AccGroupInfo() { MOZ_COUNT_DTOR(AccGroupInfo); }
 
   PRInt32 PosInSet() const { return mPosInSet; }
   PRUint32 SetSize() const { return mSetSize; }
   nsAccessible* GetConceptualParent() const { return mParent; }
 
   /**
    * Create group info.
    */
--- a/accessible/src/base/nsARIAGridAccessible.cpp
+++ b/accessible/src/base/nsARIAGridAccessible.cpp
@@ -480,28 +480,28 @@ nsARIAGridAccessible::GetSelectedCells(n
   nsresult rv = NS_OK;
   nsCOMPtr<nsIMutableArray> selCells =
     do_CreateInstance(NS_ARRAY_CONTRACTID, &rv);
   NS_ENSURE_SUCCESS(rv, rv);
 
   AccIterator rowIter(this, filters::GetRow);
 
   nsAccessible *row = nsnull;
-  while (row = rowIter.GetNext()) {
+  while ((row = rowIter.GetNext())) {
     AccIterator cellIter(row, filters::GetCell);
     nsAccessible *cell = nsnull;
 
     if (nsAccUtils::IsARIASelected(row)) {
-      while (cell = cellIter.GetNext())
+      while ((cell = cellIter.GetNext()))
         selCells->AppendElement(static_cast<nsIAccessible *>(cell), PR_FALSE);
 
       continue;
     }
 
-    while (cell = cellIter.GetNext()) {
+    while ((cell = cellIter.GetNext())) {
       if (nsAccUtils::IsARIASelected(cell))
         selCells->AppendElement(static_cast<nsIAccessible *>(cell), PR_FALSE);
     }
   }
 
   NS_ADDREF(*aCells = selCells);
   return NS_OK;
 }
@@ -524,28 +524,28 @@ nsARIAGridAccessible::GetSelectedCellInd
   PRInt32 colCount = 0;
   GetColumnCount(&colCount);
 
   nsTArray<PRInt32> selCells(rowCount * colCount);
 
   AccIterator rowIter(this, filters::GetRow);
 
   nsAccessible *row = nsnull;
-  for (PRInt32 rowIdx = 0; row = rowIter.GetNext(); rowIdx++) {
+  for (PRInt32 rowIdx = 0; (row = rowIter.GetNext()); rowIdx++) {
     if (nsAccUtils::IsARIASelected(row)) {
       for (PRInt32 colIdx = 0; colIdx < colCount; colIdx++)
         selCells.AppendElement(rowIdx * colCount + colIdx);
 
       continue;
     }
 
     AccIterator cellIter(row, filters::GetCell);
     nsAccessible *cell = nsnull;
 
-    for (PRInt32 colIdx = 0; cell = cellIter.GetNext(); colIdx++) {
+    for (PRInt32 colIdx = 0; (cell = cellIter.GetNext()); colIdx++) {
       if (nsAccUtils::IsARIASelected(cell))
         selCells.AppendElement(rowIdx * colCount + colIdx);
     }
   }
 
   PRUint32 selCellsCount = selCells.Length();
   if (!selCellsCount)
     return NS_OK;
@@ -584,17 +584,17 @@ nsARIAGridAccessible::GetSelectedRowIndi
   if (!rowCount)
     return NS_OK;
 
   nsTArray<PRInt32> selRows(rowCount);
 
   AccIterator rowIter(this, filters::GetRow);
 
   nsAccessible *row = nsnull;
-  for (PRInt32 rowIdx = 0; row = rowIter.GetNext(); rowIdx++) {
+  for (PRInt32 rowIdx = 0; (row = rowIter.GetNext()); rowIdx++) {
     if (nsAccUtils::IsARIASelected(row)) {
       selRows.AppendElement(rowIdx);
       continue;
     }
 
     AccIterator cellIter(row, filters::GetCell);
     nsAccessible *cell = cellIter.GetNext();
     if (!cell)
@@ -630,17 +630,17 @@ nsARIAGridAccessible::SelectRow(PRInt32 
   NS_ENSURE_ARG(IsValidRow(aRow));
 
   if (IsDefunct())
     return NS_ERROR_FAILURE;
 
   AccIterator rowIter(this, filters::GetRow);
 
   nsAccessible *row = nsnull;
-  for (PRInt32 rowIdx = 0; row = rowIter.GetNext(); rowIdx++) {
+  for (PRInt32 rowIdx = 0; (row = rowIter.GetNext()); rowIdx++) {
     nsresult rv = SetARIASelected(row, rowIdx == aRow);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
@@ -882,17 +882,17 @@ nsARIAGridAccessible::GetSelectedColumns
   do {
     if (nsAccUtils::IsARIASelected(row))
       continue;
 
     PRInt32 colIdx = 0;
 
     AccIterator cellIter(row, filters::GetCell);
     nsAccessible *cell = nsnull;
-    for (colIdx = 0; cell = cellIter.GetNext(); colIdx++) {
+    for (colIdx = 0; (cell = cellIter.GetNext()); colIdx++) {
       if (isColSelArray.SafeElementAt(colIdx, PR_FALSE) &&
           !nsAccUtils::IsARIASelected(cell)) {
         isColSelArray[colIdx] = PR_FALSE;
         selColCount--;
       }
     }
   } while ((row = rowIter.GetNext()));
 
--- a/accessible/src/base/nsAccDocManager.cpp
+++ b/accessible/src/base/nsAccDocManager.cpp
@@ -1,9 +1,9 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* ***** 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/
  *
@@ -541,18 +541,16 @@ nsAccDocManager::ShutdownDocAccessiblesI
 ////////////////////////////////////////////////////////////////////////////////
 // nsAccDocManager static
 
 PLDHashOperator
 nsAccDocManager::ClearDocCacheEntry(const void* aKey,
                                     nsRefPtr<nsDocAccessible>& aDocAccessible,
                                     void* aUserArg)
 {
-  nsAccDocManager *accDocMgr = static_cast<nsAccDocManager*>(aUserArg);
-
   NS_ASSERTION(aDocAccessible,
                "Calling ClearDocCacheEntry with a NULL pointer!");
 
   if (aDocAccessible)
     aDocAccessible->Shutdown();
 
   return PL_DHASH_REMOVE;
 }
--- a/accessible/src/base/nsAccessible.cpp
+++ b/accessible/src/base/nsAccessible.cpp
@@ -2183,19 +2183,17 @@ nsAccessible::GetRelationByType(PRUint32
     }
 
   case nsIAccessibleRelation::RELATION_DEFAULT_BUTTON:
     {
       if (mContent->IsHTML()) {
         // HTML form controls implements nsIFormControl interface.
         nsCOMPtr<nsIFormControl> control(do_QueryInterface(mContent));
         if (control) {
-          nsCOMPtr<nsIDOMHTMLFormElement> htmlform;
-          control->GetForm(getter_AddRefs(htmlform));
-          nsCOMPtr<nsIForm> form(do_QueryInterface(htmlform));
+          nsCOMPtr<nsIForm> form(do_QueryInterface(control->GetFormElement()));
           if (form) {
             nsCOMPtr<nsIContent> formContent =
               do_QueryInterface(form->GetDefaultSubmitElement());
             return nsRelUtils::AddTargetFromContent(aRelationType, aRelation,
                                                     formContent);
           }
         }
       }
@@ -2744,16 +2742,24 @@ nsAccessible::BindToParent(nsAccessible*
       mParent->InvalidateChildren();
   }
 
   mParent = aParent;
   mIndexInParent = aIndexInParent;
 }
 
 void
+nsAccessible::UnbindFromParent()
+{
+  mParent = nsnull;
+  mIndexInParent = -1;
+  mGroupInfo = nsnull;
+}
+
+void
 nsAccessible::InvalidateChildren()
 {
   PRInt32 childCount = mChildren.Length();
   for (PRInt32 childIdx = 0; childIdx < childCount; childIdx++) {
     nsAccessible* child = mChildren.ElementAt(childIdx);
     child->UnbindFromParent();
   }
 
--- a/accessible/src/base/nsAccessible.h
+++ b/accessible/src/base/nsAccessible.h
@@ -320,22 +320,17 @@ protected:
    * Cache accessible children.
    */
   virtual void CacheChildren();
 
   /**
    * Set accessible parent and index in parent.
    */
   void BindToParent(nsAccessible* aParent, PRUint32 aIndexInParent);
-  void UnbindFromParent()
-  {
-    mParent = nsnull;
-    mIndexInParent = -1;
-    mGroupInfo = nsnull;
-  }
+  void UnbindFromParent();
 
   /**
    * Return sibling accessible at the given offset.
    */
   virtual nsAccessible* GetSiblingAtOffset(PRInt32 aOffset,
                                            nsresult *aError = nsnull);
 
   //////////////////////////////////////////////////////////////////////////////
@@ -455,10 +450,9 @@ protected:
   friend class AccGroupInfo;
 
   nsRoleMapEntry *mRoleMapEntry; // Non-null indicates author-supplied role; possibly state & value as well
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsAccessible,
                               NS_ACCESSIBLE_IMPL_IID)
 
-#endif  
-
+#endif
--- a/accessible/src/base/nsCoreUtils.cpp
+++ b/accessible/src/base/nsCoreUtils.cpp
@@ -158,35 +158,31 @@ PRBool
 nsCoreUtils::DispatchMouseEvent(PRUint32 aEventType,
                                 nsIPresShell *aPresShell,
                                 nsIContent *aContent)
 {
   nsIFrame *frame = aContent->GetPrimaryFrame();
   if (!frame)
     return PR_FALSE;
 
-  nsIFrame* rootFrame = aPresShell->GetRootFrame();
-  if (!rootFrame)
+  // Compute x and y coordinates.
+  nsPoint point;
+  nsCOMPtr<nsIWidget> widget = frame->GetNearestWidget(point);
+  if (!widget)
     return PR_FALSE;
 
-  nsCOMPtr<nsIWidget> rootWidget = rootFrame->GetNearestWidget();
-  if (!rootWidget)
-    return PR_FALSE;
-
-  // Compute x and y coordinates.
-  nsPoint point = frame->GetOffsetToExternal(rootFrame);
   nsSize size = frame->GetSize();
 
   nsPresContext* presContext = aPresShell->GetPresContext();
 
   PRInt32 x = presContext->AppUnitsToDevPixels(point.x + size.width / 2);
   PRInt32 y = presContext->AppUnitsToDevPixels(point.y + size.height / 2);
 
   // Fire mouse event.
-  DispatchMouseEvent(aEventType, x, y, aContent, frame, aPresShell, rootWidget);
+  DispatchMouseEvent(aEventType, x, y, aContent, frame, aPresShell, widget);
   return PR_TRUE;
 }
 
 void
 nsCoreUtils::DispatchMouseEvent(PRUint32 aEventType, PRInt32 aX, PRInt32 aY,
                                 nsIContent *aContent, nsIFrame *aFrame,
                                 nsIPresShell *aPresShell, nsIWidget *aRootWidget)
 {
--- a/accessible/src/base/nsDocAccessible.cpp
+++ b/accessible/src/base/nsDocAccessible.cpp
@@ -86,17 +86,17 @@ nsIAtom *nsDocAccessible::gLastFocusedFr
 
 ////////////////////////////////////////////////////////////////////////////////
 // Constructor/desctructor
 
 nsDocAccessible::
   nsDocAccessible(nsIDocument *aDocument, nsIContent *aRootContent,
                   nsIWeakReference *aShell) :
   nsHyperTextAccessibleWrap(aRootContent, aShell), mWnd(nsnull),
-  mDocument(aDocument), mIsLoaded(PR_FALSE), mScrollPositionChangedTicks(0)
+  mDocument(aDocument), mScrollPositionChangedTicks(0), mIsLoaded(PR_FALSE)
 {
   // XXX aaronl should we use an algorithm for the initial cache size?
   mAccessibleCache.Init(kDefaultCacheSize);
 
   // For GTK+ native window, we do nothing here.
   if (!mDocument)
     return;
 
--- a/accessible/src/html/nsHyperTextAccessible.cpp
+++ b/accessible/src/html/nsHyperTextAccessible.cpp
@@ -807,17 +807,17 @@ nsHyperTextAccessible::GetRelativeOffset
     // and we're actually at the start of the paragraph
     hyperTextOffset = 0;
   }  
   else if (aAmount == eSelectBeginLine) {
     nsAccessible *firstChild = mChildren.SafeElementAt(0, nsnull);
     // For line selection with needsStart, set start of line exactly to line break
     if (pos.mContentOffset == 0 && firstChild &&
         nsAccUtils::Role(firstChild) == nsIAccessibleRole::ROLE_STATICTEXT &&
-        nsAccUtils::TextLength(firstChild) == hyperTextOffset) {
+        static_cast<PRInt32>(nsAccUtils::TextLength(firstChild)) == hyperTextOffset) {
       // XXX Bullet hack -- we should remove this once list bullets use anonymous content
       hyperTextOffset = 0;
     }
     if (!aNeedsStart && hyperTextOffset > 0) {
       -- hyperTextOffset;
     }
   }
   else if (aAmount == eSelectEndLine && finalAccessible) { 
--- a/accessible/src/xul/nsXULTreeAccessible.cpp
+++ b/accessible/src/xul/nsXULTreeAccessible.cpp
@@ -657,18 +657,18 @@ nsXULTreeAccessible::CreateTreeItemAcces
 ////////////////////////////////////////////////////////////////////////////////
 // nsXULTreeItemAccessibleBase
 ////////////////////////////////////////////////////////////////////////////////
 
 nsXULTreeItemAccessibleBase::
   nsXULTreeItemAccessibleBase(nsIContent *aContent, nsIWeakReference *aShell,
                               nsAccessible *aParent, nsITreeBoxObject *aTree,
                               nsITreeView *aTreeView, PRInt32 aRow) :
-  mTree(aTree), mTreeView(aTreeView), mRow(aRow),
-  nsAccessibleWrap(aContent, aShell)
+  nsAccessibleWrap(aContent, aShell),
+  mTree(aTree), mTreeView(aTreeView), mRow(aRow)
 {
   mParent = aParent;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsXULTreeItemAccessibleBase: nsISupports implementation
 
 NS_IMPL_ISUPPORTS_INHERITED1(nsXULTreeItemAccessibleBase,
--- a/browser/app/profile/extensions/testpilot@labs.mozilla.com/chrome.manifest
+++ b/browser/app/profile/extensions/testpilot@labs.mozilla.com/chrome.manifest
@@ -3,8 +3,12 @@ content testpilot content/
 skin testpilot skin skin/all/
 skin testpilot-os skin skin/linux/ os=Linux
 skin testpilot-os skin skin/mac/ os=Darwin
 skin testpilot-os skin skin/win/ os=WINNT
 overlay chrome://browser/content/browser.xul chrome://testpilot/content/tp-browser.xul application={ec8030f7-c20a-464f-9b0e-13a3a9e97384} appversion<=3.6.*
 overlay chrome://browser/content/browser.xul chrome://testpilot/content/feedback-browser.xul application={ec8030f7-c20a-464f-9b0e-13a3a9e97384} appversion>3.7a1pre
 # For the menubar on Mac
 overlay chrome://testpilot/content/all-studies-window.xul chrome://browser/content/macBrowserOverlay.xul application={ec8030f7-c20a-464f-9b0e-13a3a9e97384} os=Darwin
+
+component {e6e5e58f-7977-485a-b076-2f74bee2677b} components/TestPilot.js
+contract @mozilla.org/testpilot/service;1 {e6e5e58f-7977-485a-b076-2f74bee2677b}
+category profile-after-change testpilot @mozilla.org/testpilot/service;1
--- a/browser/app/profile/extensions/testpilot@labs.mozilla.com/components/TestPilot.js
+++ b/browser/app/profile/extensions/testpilot@labs.mozilla.com/components/TestPilot.js
@@ -41,27 +41,27 @@ const Cu = Components.utils;
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 
 function TestPilotComponent() {}
 TestPilotComponent.prototype = {
   classDescription: "Test Pilot Component",
   contractID: "@mozilla.org/testpilot/service;1",
   classID: Components.ID("{e6e5e58f-7977-485a-b076-2f74bee2677b}"),
-  _xpcom_categories: [{ category: "app-startup", service: true }],
+  _xpcom_categories: [{ category: "profile-after-change" }],
   _startupTimer: null,
 
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver,
                                          Ci.nsISupportsWeakReference]),
 
   observe: function TPC__observe(subject, topic, data) {
     let os = Cc["@mozilla.org/observer-service;1"].
         getService(Ci.nsIObserverService);
     switch (topic) {
-    case "app-startup":
+    case "profile-after-change":
       os.addObserver(this, "sessionstore-windows-restored", true);
       break;
     case "sessionstore-windows-restored":
       /* Stop oberver, to ensure that globalStartup doesn't get
        * called more than once. */
       os.removeObserver(this, "sessionstore-windows-restored", false);
       /* Call global startup on a timer so that it's off of the main
        * thread... delay a few seconds to give firefox time to finish
@@ -73,12 +73,14 @@ TestPilotComponent.prototype = {
            Cu.import("resource://testpilot/modules/setup.js");
            TestPilotSetup.globalStartup();
          }}, 10000, Ci.nsITimer.TYPE_ONE_SHOT);
       break;
     }
   }
 };
 
-function NSGetModule(compMgr, fileSpec) {
-  return XPCOMUtils.generateModule([TestPilotComponent]);
-}
-
+const components = [TestPilotComponent];
+var NSGetFactory, NSGetModule;
+if (XPCOMUtils.generateNSGetFactory)
+  NSGetFactory = XPCOMUtils.generateNSGetFactory(components);
+else
+  NSGetModule = XPCOMUtils.generateNSGetModule(components);
--- a/browser/app/profile/extensions/testpilot@labs.mozilla.com/content/all-studies-window.js
+++ b/browser/app/profile/extensions/testpilot@labs.mozilla.com/content/all-studies-window.js
@@ -205,16 +205,17 @@ var TestPilotXulWindow = {
   },
 
   onLoad: function () {
     Components.utils.import("resource://testpilot/modules/Observers.js");
     Components.utils.import("resource://testpilot/modules/setup.js");
     Components.utils.import("resource://testpilot/modules/tasks.js");
 
     this._stringBundle = document.getElementById("testpilot-stringbundle");
+    this.sizeWindow();
     this._init(false);
     Observers.add("testpilot:task:changed", this._onTaskStatusChanged, this);
   },
 
   onUnload: function() {
     Observers.remove("testpilot:task:changed", this._onTaskStatusChanged, this);
   },
 
@@ -236,18 +237,18 @@ var TestPilotXulWindow = {
     if (TestPilotSetup.startupComplete) {
       experiments = TestPilotSetup.getAllTasks();
       if (experiments.length > 0 ) {
         ready = true;
       }
     }
 
     if (!ready) {
-      // If you opened the window before tasks are done loading, exit now but try
-      // again in a few seconds.
+      // If you opened the window before tasks are done loading, exit now
+      // but try again in a few seconds.
       window.setTimeout(
         function() { TestPilotXulWindow._init(aReload); }, 2000);
       return;
     }
 
     let numFinishedStudies = 0;
     let numCurrentStudies = 0;
 
@@ -414,17 +415,38 @@ var TestPilotXulWindow = {
         this._stringBundle.getString("testpilot.studiesWindow.proposeStudy"),
         PROPOSE_STUDY_URL, true);
       document.getElementById("current-studies-listbox").appendChild(newRow);
     }
 
     // Show number of studies the user finished on badge:
     document.getElementById("num-finished-badge").setAttribute(
       "value", numFinishedStudies);
+  },
 
+  sizeWindow: function() {
+    // Size listboxes based on available screen size, then size window to fit
+    // list boxes.
+    let currList = document.getElementById("current-studies-listbox");
+    let finList = document.getElementById("finished-studies-listbox");
+    let resultsList = document.getElementById("study-results-listbox");
+
+    let screenWidth = window.screen.availWidth;
+    let screenHeight = window.screen.availHeight;
+    let width = screenWidth >= 800 ? 700 : screenWidth - 100;
+    let height = screenHeight >= 800 ? 700 : screenHeight - 100;
+
+    height -= 130; // Or whatever is height of title bar plus windowdragbox
+
+    currList.width = width;
+    currList.height = height;
+    finList.width = width;
+    finList.height = height;
+    resultsList.width = width;
+    resultsList.height = height;
     window.sizeToContent();
   },
 
   focusPane: function(paneIndex) {
     document.getElementById("tp-xulwindow-deck").selectedIndex = paneIndex;
 
     // When you focus the 'study findings' tab, any results there which
     // are still marked "new" should have their status changed as the user
--- a/browser/app/profile/extensions/testpilot@labs.mozilla.com/content/browser.css
+++ b/browser/app/profile/extensions/testpilot@labs.mozilla.com/content/browser.css
@@ -128,21 +128,16 @@ image.study-result {
   margin-right: 8px;
 }
 
 /* All studies window */
 .pilot-largetext {
   font-size: 16px;
 }
 
-#test-pilot-all-studies-window {
-  min-width: 720px !important;
-  min-height: 500px !important;
-}
-
 #test-pilot-all-studies-window > .prefWindow-dlgbuttons {
     display: none;
 }
 
 .paneSelector {
     margin: 0 !important;
 }
 
@@ -169,23 +164,22 @@ image.study-result {
     font-weight: bold;
     padding: 2px;
     -moz-border-radius: 100%;
     margin-right: 25px;
     margin-bottom: 13px;
 }
 
 richlistbox.tp-study-list {
-    height: 522px;
-    width: 502px;
     overflow: auto;
     margin: 0px;
 }
 
 .tp-tab-panel {
+    background-color: -moz-dialog;
     padding: 0px;
 }
 
 description.study-description {
     width: 350px;
 }
 
 description.study-title {
--- a/browser/app/profile/extensions/testpilot@labs.mozilla.com/content/experiment-page.js
+++ b/browser/app/profile/extensions/testpilot@labs.mozilla.com/content/experiment-page.js
@@ -66,28 +66,35 @@ var stringBundle;
     // If always-submit-checkbox is checked, set the pref
     if (task._recursAutomatically) {
       let checkBox = document.getElementById("always-submit-checkbox");
       if (checkBox && checkBox.checked) {
         task.setRecurPref(TaskConstants.ALWAYS_SUBMIT);
       }
     }
 
+    // Study web content must provide an element with id 'upload-status'.
+    // Fill it first with a message about data being uploaded; if there's
+    // an error, replace it with the error message.
     let uploadStatus = document.getElementById("upload-status");
     uploadStatus.innerHTML =
       stringBundle.GetStringFromName("testpilot.statusPage.uploadingData");
     task.upload( function(success) {
       if (success) {
         window.location =
 	  "chrome://testpilot/content/status.html?eid=" + eid;
       } else {
-        uploadStatus.innerHTML =
-	  "<p>" +
-	  stringBundle.GetStringFromName("testpilot.statusPage.uploadError") +
-	  "</p>";
+        // Replace 'now uploading' message
+        let errorParagraph = document.createElement("p");
+        errorParagraph.innerHTML = stringBundle.GetStringFromName("testpilot.statusPage.uploadErrorMsg");
+        let willRetryParagraph = document.createElement("p");
+        willRetryParagraph.innerHTML = stringBundle.GetStringFromName("testpilot.statusPage.willRetry");
+        uploadStatus.innerHTML = "";
+        uploadStatus.appendChild(errorParagraph);
+        uploadStatus.appendChild(willRetryParagraph);
       }
     });
   }
 
   function deleteData() {
     Components.utils.import("resource://testpilot/modules/setup.js");
     Components.utils.import("resource://testpilot/modules/tasks.js");
     let eid = parseInt(getUrlParam("eid"));
@@ -231,37 +238,34 @@ var stringBundle;
       span.innerHTML =
         stringBundle.formatStringFromName(
 	  "testpilot.statusPage.endOn", [endDate.toLocaleString()], 1);
     }
   }
 
   function showMetaData() {
     Components.utils.import("resource://testpilot/modules/metadata.js");
+    Components.utils.import("resource://gre/modules/PluralForm.jsm");
     MetadataCollector.getMetadata(function(md) {
       var mdLocale = document.getElementById("md-locale");
       if (mdLocale)
         mdLocale.innerHTML = md.location;
       var mdVersion = document.getElementById("md-version");
       if (mdVersion)
         mdVersion.innerHTML = md.version;
       var mdOs = document.getElementById("md-os");
       if (mdOs)
         mdOs.innerHTML = md.operatingSystem;
       var mdNumExt = document.getElementById("md-num-ext");
       if (mdNumExt) {
+        // This computes the correctly localized singular or plural string
+        // of the number of extensions, e.g. "1 extension", "2 extensions", etc.
+        let str = stringBundle.GetStringFromName("testpilot.statusPage.numExtensions");
         var numExt = md.extensions.length;
-        if (numExt == 1) {
-          mdNumExt.innerHTML =
-            stringBundle.GetStringFromName("testpilot.statusPage.extension");
-        } else {
-          mdNumExt.innerHTML =
-            stringBundle.formatStringFromName(
-            "testpilot.statusPage.extensions", [numExt], 1);
-        }
+        mdNumExt.innerHTML = PluralForm.get(numExt, str).replace("#1", numExt);
       }
     });
   }
 
   function onQuitPageLoad() {
     Components.utils.import("resource://testpilot/modules/setup.js");
     setStrings(PAGE_TYPE_QUIT);
     let eid = parseInt(getUrlParam("eid"));
@@ -358,16 +362,18 @@ var stringBundle;
   }
 
   function loadExperimentPage() {
     Components.utils.import("resource://testpilot/modules/setup.js");
     Components.utils.import("resource://testpilot/modules/tasks.js");
     var contentDiv = document.getElementById("experiment-specific-text");
     var dataPrivacyDiv = document.getElementById("data-privacy-text");
     // Get experimentID from the GET args of page
+    // TODO no reason actually to do parseInt here -- all it accomplishes
+    // is preventing us from using non-numeric study IDs.
     var eid = parseInt(getUrlParam("eid"));
     var experiment = TestPilotSetup.getTaskById(eid);
     if (!experiment) {
       // Possible that experiments aren't done loading yet.  Try again in
       // a few seconds.
       contentDiv.innerHTML =
         stringBundle.GetStringFromName("testpilot.statusPage.loading");
       window.setTimeout(function() { loadExperimentPage(); }, 2000);
@@ -438,17 +444,17 @@ var stringBundle;
 	  stringKey: "testpilot.page.testpilotOnTwitter" },
 	{ id: "optional-message",
 	  stringKey: "testpilot.quitPage.optionalMessage" },
 	{ id: "reason-text",
 	  stringKey: "testpilot.quitPage.reason" },
 	{ id: "recur-options",
 	  stringKey: "testpilot.quitPage.recurringStudy" },
 	{ id: "quit-forever-text",
-	  stringKey: "testpilot.quitPage.quitFoever" },
+	  stringKey: "testpilot.quitPage.quitForever" },
 	{ id: "quit-study-link",
 	  stringKey: "testpilot.quitPage.quitStudy" }
       ];
     }
     mapLength = map.length;
     for (let i = 0; i < mapLength; i++) {
       let entry = map[i];
       document.getElementById(entry.id).innerHTML =
--- a/browser/app/profile/extensions/testpilot@labs.mozilla.com/content/welcome-page.js
+++ b/browser/app/profile/extensions/testpilot@labs.mozilla.com/content/welcome-page.js
@@ -82,18 +82,16 @@ var TestPilotWelcomePage = {
       { id: "testpilot-addon-text",
         stringKey: "testpilot.welcomePage.testpilotAddon" },
       { id: "icon-explanation-text",
         stringKey: "testpilot.welcomePage.iconExplanation" },
       { id: "icon-explanation-more-text",
         stringKey: "testpilot.welcomePage.moreIconExplanation" },
       { id: "notification-info-text",
 	stringKey: "testpilot.welcomePage.notificationInfo" },
-      { id: "copyright-text",
-	stringKey: "testpilot.welcomePage.copyright" },
       { id: "privacy-policy-link",
 	stringKey: "testpilot.welcomePage.privacyPolicy" },
       { id: "legal-notices-link",
 	stringKey: "testpilot.welcomePage.legalNotices" }
       ];
 
     let mapLength = map.length;
     for (let i = 0; i < mapLength; i++) {
--- a/browser/app/profile/extensions/testpilot@labs.mozilla.com/content/welcome.html
+++ b/browser/app/profile/extensions/testpilot@labs.mozilla.com/content/welcome.html
@@ -40,16 +40,15 @@
             <span id="icon-explanation-more-text"></span>
           </p>
           <p class="embiggened" id="notification-info-text"></p>
         </div>
       </div>
     </div>
     <div id="footer">
       <img class="mozLogo" src="chrome://testpilot/skin/mozilla-logo.png">
-        <span id="copyright-text"></span>&nbsp; &nbsp;
         <a href="http://www.mozilla.com/en-US/privacy-policy.html"
           id="privacy-policy-link"></a> &nbsp; &nbsp;
         <a href="http://www.mozilla.com/en-US/about/legal.html"
           id="legal-notices-link"></a>
     </div>
   </div>
 </body></html>
\ No newline at end of file
--- a/browser/app/profile/extensions/testpilot@labs.mozilla.com/content/window-utils.js
+++ b/browser/app/profile/extensions/testpilot@labs.mozilla.com/content/window-utils.js
@@ -49,17 +49,18 @@ var TestPilotWindowUtils;
                  getService(Components.interfaces.nsIWindowMediator);
       let allStudiesWindow = wm.getMostRecentWindow(ALL_STUDIES_WINDOW_TYPE);
 
       if (allStudiesWindow) {
         allStudiesWindow.focus();
       } else {
         allStudiesWindow = window.openDialog(
           "chrome://testpilot/content/all-studies-window.xul",
-          ALL_STUDIES_WINDOW_NAME, "chrome,titlebar,centerscreen,dialog=no");
+          ALL_STUDIES_WINDOW_NAME,
+          "chrome,titlebar,centerscreen,dialog=no");
       }
     },
 
     openInTab: function(url) {
       let wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
                  .getService(Components.interfaces.nsIWindowMediator);
       let enumerator = wm.getEnumerator("navigator:browser");
       let found = false;
@@ -125,15 +126,20 @@ var TestPilotWindowUtils;
       /* Make the window smaller and dialog-boxier
        * Links to discussion group, twitter, etc should open in new
        * tab in main browser window, if we have these links here at all!!
        * Maybe just one link to the main Test Pilot website. */
 
       // TODO this window opening triggers studies' window-open code.
       // Is that what we want or not?
 
+      let screenWidth = window.screen.availWidth;
+      let screenHeight = window.screen.availHeight;
+      let width = screenWidth >= 1200 ? 1000 : screenWidth - 200;
+      let height = screenHeight >= 1000 ? 800 : screenHeight - 200;
+
       let win = window.open(url, "TestPilotStudyDetailWindow",
                            "chrome,centerscreen,resizable=yes,scrollbars=yes," +
-                           "status=no,width=1000,height=800");
+                           "status=no,width=" + width + ",height=" + height);
       win.focus();
     }
   };
-}());
\ No newline at end of file
+}());
--- a/browser/app/profile/extensions/testpilot@labs.mozilla.com/install.rdf
+++ b/browser/app/profile/extensions/testpilot@labs.mozilla.com/install.rdf
@@ -1,24 +1,24 @@
 <?xml version="1.0"?>
 
 <RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
      xmlns:em="http://www.mozilla.org/2004/em-rdf#">
   <Description about="urn:mozilla:install-manifest">
     <em:id>testpilot@labs.mozilla.com</em:id>
-    <em:version>1.0rc1</em:version>
+    <em:version>1.0</em:version>
     <em:type>2</em:type>
 
     <!-- Target Application this extension can install into, 
          with minimum and maximum supported versions. --> 
     <em:targetApplication>
       <Description>
         <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
         <em:minVersion>3.5</em:minVersion>
-        <em:maxVersion>4.0b1</em:maxVersion>
+        <em:maxVersion>4.0b2</em:maxVersion>
       </Description>
     </em:targetApplication>
    
     <!-- Front End MetaData -->
     <em:name>Feedback</em:name>
     <em:description>Help make Firefox better by giving feedback.</em:description>
     <em:creator>Mozilla Corporation</em:creator>
     <em:homepageURL>http://testpilot.mozillalabs.com/</em:homepageURL>
--- a/browser/app/profile/extensions/testpilot@labs.mozilla.com/modules/metadata.js
+++ b/browser/app/profile/extensions/testpilot@labs.mozilla.com/modules/metadata.js
@@ -115,19 +115,18 @@ let MetadataCollector = {
         Application.prefs.getValue(prefName, "");
       accessibilities.push({ name: prefName, value: prefValue });
     }
 
     return accessibilities;
   },
 
   getLocation: function MetadataCollector_getLocation() {
-    //navitagor.geolocation; // or nsIDOMGeoGeolocation
     // we don't want the lat/long, we just want the country
-
+    // so use the Locale.
     return Application.prefs.getValue(LOCALE_PREF, "");
   },
 
   getVersion: function MetadataCollector_getVersion() {
     return Application.version;
   },
 
   getOperatingSystem: function MetadataCollector_getOSVersion() {
--- a/browser/app/profile/extensions/testpilot@labs.mozilla.com/modules/remote-experiment-loader.js
+++ b/browser/app/profile/extensions/testpilot@labs.mozilla.com/modules/remote-experiment-loader.js
@@ -214,16 +214,44 @@ exports.RemoteExperimentLoader.prototype
     let self = this;
     this._loader = Cuddlefish.Loader(
       {fs: new SecurableModule.CompositeFileSystem(
          [self._jarStore, Cuddlefish.parentLoader.fs]),
        console: this._expLogger
       });
   },
 
+  getLocalizedStudyInfo: function(studiesIndex) {
+    let prefs = require("preferences-service");
+    let myLocale = prefs.get("general.useragent.locale", "");
+    let studiesToLoad = [];
+    for each (let set in studiesIndex) {
+      // First try for specific locale, e.g. pt-BR for brazillian portugese
+      if (set[myLocale]) {
+        studiesToLoad.push(set[myLocale]);
+        continue;
+      }
+      // If that's not there, look for the language, e.g. just "pt":
+      let hyphen = myLocale.indexOf("-");
+      if (hyphen > -1) {
+        let lang = myLocale.slice(0, hyphen);
+        if (set[lang]) {
+          studiesToLoad.push(set[lang]);
+          continue;
+        }
+      }
+      // If that's not there either, look for one called "default":
+      if(set["default"]) {
+        studiesToLoad.push(set["default"]);
+      }
+      // If none of those are there, load nothing.
+    }
+    return studiesToLoad;
+  },
+
   checkForUpdates: function(callback) {
     /* Callback will be called with true or false
      * to let us know whether there are any updates, so that client code can
      * restart any experiment whose code has changed. */
     let prefs = require("preferences-service");
     let indexFileName = prefs.get("extensions.testpilot.indexFileName",
                                   "index.json");
     let self = this;
@@ -239,24 +267,24 @@ exports.RemoteExperimentLoader.prototype
         try {
           data = JSON.parse(data);
         } catch (e) {
           self._logger.warn("Error parsing index.json: " + e );
           callback(false);
           return;
         }
 
-        // Cache study results...
+        // Cache study results and legacy studies.
         self._studyResults = data.results;
         self._legacyStudies = data.legacy;
 
-        /* Go through each file indicated in index.json, attempt to load it into
-         * codeStorage (replacing any older version there).
+        /* Go through each record indicated in index.json for our locale;
+         * download the specified .jar file (replacing any version on disk)
          */
-        let jarFiles = data.experiment_jars;
+        let jarFiles = self.getLocalizedStudyInfo(data.new_experiments);
         let numFilesToDload = jarFiles.length;
 
         for each (let j in jarFiles) {
           let filename = j.jarfile;
           let hash = j.hash;
           if (j.studyfile) {
             self._experimentFileNames.push(j.studyfile);
           }
--- a/browser/app/profile/extensions/testpilot@labs.mozilla.com/modules/setup.js
+++ b/browser/app/profile/extensions/testpilot@labs.mozilla.com/modules/setup.js
@@ -556,17 +556,17 @@ let TestPilotSetup = {
       for (i = 0; i < this.taskList.length; i++) {
         task = this.taskList[i];
         if (task.status == TaskConstants.STATUS_PENDING ||
             task.status == TaskConstants.STATUS_NEW) {
           if (task.taskType == TaskConstants.TYPE_EXPERIMENT) {
 	    this._showNotification(
 	      task, false,
 	      this._stringBundle.formatStringFromName(
-		"testpilot.notification.newTestPilotStudy.message",
+		"testpilot.notification.newTestPilotStudy.pre.message",
 		[task.title], 1),
 	      this._stringBundle.GetStringFromName(
 		"testpilot.notification.newTestPilotStudy"),
 	      "new-study", false, false,
 	      this._stringBundle.GetStringFromName("testpilot.moreInfo"),
 	      task.defaultUrl, false, function() {
                 /* on close callback (Bug 575767) -- when the "new study
                  * starting" popup is dismissed, then the study can start. */
@@ -673,17 +673,17 @@ let TestPilotSetup = {
     } else {
       return false; // versionString is the same as or older than my version
     }
   },
 
   _isNewerThanFirefox: function TPS__isNewerThanFirefox(versionString) {
     let result = Cc["@mozilla.org/xpcom/version-comparator;1"]
                    .getService(Ci.nsIVersionComparator)
-                   .compare(self._application.version, versionString);
+                   .compare(this._application.version, versionString);
     if (result < 0) {
       return true; // versionString is newer than Firefox
     } else {
       return false; // versionString is the same as or older than Firefox
     }
   },
 
   _experimentRequirementsAreMet: function TPS__requirementsMet(experiment) {
@@ -724,17 +724,17 @@ let TestPilotSetup = {
 
       // Minimum firefox version:
       if (minFxVer && this._isNewerThanFirefox(minFxVer)) {
         logger.warn("Not loading " + expName);
         logger.warn("Because it requires Firefox version " + minFxVer);
         return false;
       }
     } catch (e) {
-      logger.warn("Error in requirements check " + expName + ": " +  e);
+      logger.warn("Error in requirements check " +  e);
     }
     return true;
   },
 
   checkForTasks: function TPS_checkForTasks(callback) {
     let logger = this._logger;
     if (! this._remoteExperimentLoader ) {
       logger.trace("Now requiring remote experiment loader:");
--- a/browser/app/profile/extensions/testpilot@labs.mozilla.com/modules/tasks.js
+++ b/browser/app/profile/extensions/testpilot@labs.mozilla.com/modules/tasks.js
@@ -747,17 +747,17 @@ TestPilotExperiment.prototype = {
       let req = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"]
                   .createInstance( Ci.nsIXMLHttpRequest );
       req.open('POST', url, true);
       req.setRequestHeader("Content-type", "application/json");
       req.setRequestHeader("Content-length", dataString.length);
       req.setRequestHeader("Connection", "close");
       req.onreadystatechange = function(aEvt) {
         if (req.readyState == 4) {
-          if (req.status == 201) {
+          if (req.status == 200 || req.status == 201 || req.status == 202) {
             let location = req.getResponseHeader("Location");
   	    self._logger.info("DATA WAS POSTED SUCCESSFULLY " + location);
             if (self._uploadRetryTimer) {
               self._uploadRetryTimer.cancel(); // Stop retrying - it worked!
             }
             self.changeStatus(TaskConstants.STATUS_SUBMITTED);
             self._dateForDataDeletion = Date.now() + TIME_FOR_DATA_DELETION;
             self._expirationDateForDataSubmission = null;
@@ -817,17 +817,17 @@ TestPilotExperiment.prototype = {
 	  createInstance(Ci.nsIXMLHttpRequest);
       logger.trace("Posting " + dataString + " to " + url);
       req.open('POST', url, true);
       req.setRequestHeader("Content-type", "application/json");
       req.setRequestHeader("Content-length", dataString.length);
       req.setRequestHeader("Connection", "close");
       req.onreadystatechange = function(aEvt) {
         if (req.readyState == 4) {
-          if (req.status == 200) {
+          if (req.status == 200 || req.status == 201 || req.status == 202) {
 	    logger.info("Quit reason posted successfully " + req.responseText);
     	    callback(true);
 	  } else {
 	    logger.warn(req.status + " posting error " + req.responseText);
 	    callback(false);
 	  }
 	}
       };
@@ -931,16 +931,19 @@ TestPilotBuiltinSurvey.prototype = {
   _prependMetadataToJSON: function TestPilotSurvey__prependToJson(callback) {
     let json = {};
     let self = this;
     MetadataCollector.getMetadata(function(md) {
       json.metadata = md;
       // Include guid of the study that this survey is related to, so we
       // can match them up server-side.
       let guid = Application.prefs.getValue(GUID_PREF_PREFIX + self._studyId, "");
+      /* TODO if the guid for that study ID hasn't been set yet, set it!  And
+       * then use it on the study.  That way it won't matter whether the
+       * study or the survey gets run first.*/
       json.metadata.task_guid = guid;
       let pref = SURVEY_ANSWER_PREFIX + self._id;
       let surveyAnswers = JSON.parse(Application.prefs.getValue(pref, "{}"));
       json.survey_data = sanitizeJSONStrings(surveyAnswers);
       callback(JSON.stringify(json));
     });
   },
 
@@ -948,33 +951,33 @@ TestPilotBuiltinSurvey.prototype = {
   // from study._upload().
   _upload: function TestPilotSurvey__upload(callback, retryCount) {
     let self = this;
     this._prependMetadataToJSON(function(params) {
       let req =
         Cc["@mozilla.org/xmlextras/xmlhttprequest;1"].
           createInstance(Ci.nsIXMLHttpRequest);
       let url = self.uploadUrl;
-
       req.open("POST", url, true);
       req.setRequestHeader("Content-type", "application/json");
       req.setRequestHeader("Content-length", params.length);
       req.setRequestHeader("Connection", "close");
       req.onreadystatechange = function(aEvt) {
         if (req.readyState == 4) {
-          if (req.status == 200) {
+          if (req.status == 200 || req.status == 201 ||
+             req.status == 202) {
             self._logger.info(
 	    "DATA WAS POSTED SUCCESSFULLY " + req.responseText);
             if (self._uploadRetryTimer) {
               self._uploadRetryTimer.cancel(); // Stop retrying - it worked!
 	    }
             self.changeStatus(TaskConstants.STATUS_SUBMITTED);
 	    callback(true);
 	  } else {
-	    self._logger.warn("ERROR POSTING DATA: " + req.responseText);
+	    self._logger.warn(req.status + " ERROR POSTING DATA: " + req.responseText);
 	    self._uploadRetryTimer =
 	      Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
 
 	    if (!retryCount) {
               retryCount = 0;
 	    }
 	    let interval =
               Application.prefs.getValue(RETRY_INTERVAL_PREF, 3600000); // 1 hour
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -51,16 +51,20 @@
 pref("general.startup.browser", true);
 
 pref("browser.chromeURL","chrome://browser/content/");
 pref("browser.hiddenWindowChromeURL", "chrome://browser/content/hiddenWindow.xul");
 
 // Enables some extra Extension System Logging (can reduce performance)
 pref("extensions.logging.enabled", false);
 
+// Preferences for the Get Add-ons pane
+pref("extensions.getAddons.maxResults", 15);
+pref("extensions.getAddons.search.url", "https://services.addons.mozilla.org/%LOCALE%/%APP%/api/%API_VERSION%/search/%TERMS%/all/%MAX_RESULTS%/%OS%/%VERSION%");
+
 // Preferences for AMO integration
 pref("extensions.webservice.discoverURL", "https://services.addons.mozilla.org/%LOCALE%/%APP%/discovery/%VERSION%/%OS%");
 
 // Blocklist preferences
 pref("extensions.blocklist.enabled", true);
 pref("extensions.blocklist.interval", 86400);
 // Controls what level the blocklist switches from warning about items to forcibly
 // blocking them.
--- a/browser/base/Makefile.in
+++ b/browser/base/Makefile.in
@@ -51,16 +51,17 @@ CHROME_DEPS += $(abs_srcdir)/content/ove
 
 ifdef ENABLE_TESTS
 DIRS += content/test
 endif
 
 EXTRA_JS_MODULES = \
 	content/openLocationLastURL.jsm \
 	content/NetworkPrioritizer.jsm \
+	content/stylePanel.jsm \
 	$(NULL)
 
 include $(topsrcdir)/config/rules.mk
 
 PRE_RELEASE_SUFFIX := $(shell $(PYTHON) $(topsrcdir)/config/printprereleasesuffix.py \
                         $(shell cat $(srcdir)/../config/version.txt))
 
 DEFINES += \
--- a/browser/base/content/browser-context.inc
+++ b/browser/base/content/browser-context.inc
@@ -147,20 +147,16 @@
       <menuitem id="context-sendimage" 
                 label="&sendImageCmd.label;"
                 accesskey="&sendImageCmd.accesskey;"
                 oncommand="gContextMenu.sendMedia();"/>
       <menuitem id="context-setDesktopBackground"
                 label="&setDesktopBackgroundCmd.label;"
                 accesskey="&setDesktopBackgroundCmd.accesskey;"
                 oncommand="gContextMenu.setDesktopBackground();"/>
-      <menuitem id="context-blockimage"
-                type="checkbox"
-                accesskey="&blockImageCmd.accesskey;"
-                oncommand="gContextMenu.toggleImageBlocking(this.getAttribute('checked') == 'true');"/>
       <menuitem id="context-viewimageinfo"
                 label="&viewImageInfoCmd.label;"
                 accesskey="&viewImageInfoCmd.accesskey;"
                 oncommand="gContextMenu.viewImageInfo();"/>
       <menuitem id="context-savevideo"
                 label="&saveVideoCmd.label;"
                 accesskey="&saveVideoCmd.accesskey;"
                 oncommand="gContextMenu.saveMedia();"/>
--- a/browser/base/content/browser-menubar.inc
+++ b/browser/base/content/browser-menubar.inc
@@ -208,17 +208,18 @@
             <menu id="view-menu" label="&viewMenu.label;"
                   accesskey="&viewMenu.accesskey;">
               <menupopup id="menu_viewPopup">
                 <menu id="viewToolbarsMenu"
                       label="&viewToolbarsMenu.label;"
                       accesskey="&viewToolbarsMenu.accesskey;">
                   <menupopup onpopupshowing="onViewToolbarsPopupShowing(event);">
                     <menuseparator/>
-                    <menuitem command="cmd_ToggleTabsOnTop"
+                    <menuitem id="menu_tabsOnTop"
+                              command="cmd_ToggleTabsOnTop"
                               type="checkbox"
                               label="&viewTabsOnTop.label;"
                               accesskey="&viewTabsOnTop.accesskey;"/>
                     <menuseparator/>
                     <menuitem id="menu_customizeToolbars"
                               label="&viewCustomizeToolbar.label;"
                               accesskey="&viewCustomizeToolbar.accesskey;"
                               command="cmd_CustomizeToolbars"/>
--- a/browser/base/content/browser-places.js
+++ b/browser/base/content/browser-places.js
@@ -1062,55 +1062,56 @@ var PlacesStarButton = {
 };
 
 
 // This object handles the initialization and uninitialization of the bookmarks
 // toolbar.  updateState is called when the browser window is opened and
 // after closing the toolbar customization dialog.
 let PlacesToolbarHelper = {
   _place: "place:folder=TOOLBAR",
-  _cachedElt: null,
 
-  onBrowserWindowClose: function PTH_onBrowserWindowClose() {
-    if (this._cachedElt)
-      this._cachedElt._placesView.uninit();
+  get _viewElt() {
+    return document.getElementById("PlacesToolbar");
   },
 
-  updateState: function PTH_updateState() {
-    let currentElt = document.getElementById("PlacesToolbar");
+  init: function PTH_init() {
+    let viewElt = this._viewElt;
+    if (!viewElt || viewElt._placesView)
+      return;
 
-    // Bail out if the state has not changed.
-    if (currentElt == this._cachedElt)
+    // If the bookmarks toolbar item is hidden because the parent toolbar is
+    // collapsed or hidden (i.e. in a popup), spare the initialization.
+    let toolbar = viewElt.parentNode.parentNode;
+    if (toolbar.collapsed ||
+        getComputedStyle(toolbar, "").display == "none")
       return;
 
-    if (!this._cachedElt) {
-      // The toolbar has been added.
-      new PlacesToolbar(this._place);
-      this._cachedElt = currentElt;
-    }
-    else {
-      // The toolbar has been removed.
-      this._cachedElt._placesView.uninit();
-      this._cachedElt = null;
-    }
+    new PlacesToolbar(this._place);
+  },
+
+  customizeStart: function PTH_customizeStart() {
+    let viewElt = this._viewElt;
+    if (viewElt && viewElt._placesView)
+      viewElt._placesView.uninit();
+  },
+
+  customizeDone: function PTH_customizeDone() {
+    this.init();
   }
 };
 
 
 // Handles the bookmarks menu button shown when the main menubar is hidden.
 let BookmarksMenuButton = {
   get button() {
-    delete this.button;
-    return this.button = document.getElementById("bookmarks-menu-button");
+    return document.getElementById("bookmarks-menu-button");
   },
 
-  get navbarButtonContainer() {
-    delete this.navbarButtonContainer;
-    return this.navbarButtonContainer =
-             document.getElementById("bookmarks-menu-button-container");
+  get buttonContainer() {
+    return document.getElementById("bookmarks-menu-button-container");
   },
 
   get personalToolbar() {
     delete this.personalToolbar;
     return this.personalToolbar = document.getElementById("PersonalToolbar");
   },
 
   get bookmarksToolbarItem() {
@@ -1147,55 +1148,97 @@ let BookmarksMenuButton = {
         PlacesUtils.getString("UnsortedBookmarksFolderTitle");
     }
 
     // Update View Bookmarks Toolbar checkbox menuitem.
     viewToolbar.setAttribute("checked", !this.personalToolbar.collapsed);
 
     // Hide Bookmarks Toolbar menu if the button is next to the bookmarks
     // toolbar item, show them otherwise.
-    let bookmarksToolbarElt =
-      document.getElementById("BMB_bookmarksToolbarFolderMenu");
-    bookmarksToolbarElt.collapsed =
-      this.button.parentNode == this.bookmarksToolbarItem;
+    let button = this.button;
+    document.getElementById("BMB_bookmarksToolbarFolderMenu").collapsed =
+      button && button.parentNode == this.bookmarksToolbarItem;
   },
 
   updatePosition: function BMB_updatePosition() {
     this._popupNeedsUpdating = true;
 
+    let button = this.button;
+    if (!button)
+      return;
+
+    // If the toolbar containing bookmarks is visible, we want to move the
+    // button to bookmarksToolbarItem.
     let bookmarksToolbarItem = this.bookmarksToolbarItem;
-    if (bookmarksToolbarItem && !bookmarksToolbarItem.parentNode.collapsed) {
-      if (this.button.parentNode != bookmarksToolbarItem) {
-        this.resetView();
-        bookmarksToolbarItem.appendChild(this.button);
+    let bookmarksOnVisibleToolbar = bookmarksToolbarItem &&
+                                    !bookmarksToolbarItem.parentNode.collapsed &&
+                                    bookmarksToolbarItem.parentNode.getAttribute("autohide") != "true";
+
+    // If the container has been moved by the user to the toolbar containing
+    // bookmarks, we want to preserve the desired position.
+    let container = this.buttonContainer;
+    let containerNearBookmarks = container && bookmarksToolbarItem &&
+                                 container.parentNode == bookmarksToolbarItem.parentNode;
+
+    if (bookmarksOnVisibleToolbar && !containerNearBookmarks) {
+      if (button.parentNode != bookmarksToolbarItem) {
+        this._uninitView();
+        bookmarksToolbarItem.appendChild(button);
       }
-      this.button.classList.add("bookmark-item");
-      this.button.classList.remove("toolbarbutton-1");
     }
     else {
-      if (this.button.parentNode != this.navbarButtonContainer) {
-        this.resetView();
-        this.navbarButtonContainer.appendChild(this.button);
+      if (container && button.parentNode != container) {
+        this._uninitView();
+        container.appendChild(button);
       }
-      this.button.classList.remove("bookmark-item");
-      this.button.classList.add("toolbarbutton-1");
+    }
+    this._updateStyle();
+  },
+
+  _updateStyle: function BMB__updateStyle() {
+    let button = this.button;
+    if (!button)
+      return;
+
+    let container = this.buttonContainer;
+    let containerOnPersonalToolbar = container &&
+                                     (container.parentNode == this.personalToolbar ||
+                                      container.parentNode.parentNode == this.personalToolbar);
+
+    if (button.parentNode == this.bookmarksToolbarItem ||
+        containerOnPersonalToolbar) {
+      button.classList.add("bookmark-item");
+      button.classList.remove("toolbarbutton-1");
+    }
+    else {
+      button.classList.remove("bookmark-item");
+      button.classList.add("toolbarbutton-1");
     }
   },
 
-  resetView: function BMB_resetView() {
+  _uninitView: function BMB__uninitView() {
     // When an element with a placesView attached is removed and re-inserted,
     // XBL reapplies the binding causing any kind of issues and possible leaks,
     // so kill current view and let popupshowing generate a new one.
-    if (this.button._placesView)
-      this.button._placesView.uninit();
+    let button = this.button;
+    if (button && button._placesView)
+      button._placesView.uninit();
   },
 
   customizeStart: function BMB_customizeStart() {
-    var bmToolbarItem = this.bookmarksToolbarItem;
-    if (this.button.parentNode == bmToolbarItem)
-      bmToolbarItem.removeChild(this.button);
+    this._uninitView();
+    let button = this.button;
+    let container = this.buttonContainer;
+    if (button && container && button.parentNode != container) {
+      // Move button back to the container, so user can move or remove it.
+      container.appendChild(button);
+      this._updateStyle();
+    }
+  },
+
+  customizeChange: function BMB_customizeChange() {
+    this._updateStyle();
   },
 
   customizeDone: function BMB_customizeDone() {
-    this.resetView();
     this.updatePosition();
   }
 };
--- a/browser/base/content/browser-sets.inc
+++ b/browser/base/content/browser-sets.inc
@@ -136,16 +136,29 @@
 
   <commandset id="placesCommands">
     <command id="Browser:ShowAllBookmarks"
              oncommand="PlacesCommandHook.showPlacesOrganizer('AllBookmarks');"/>
     <command id="Browser:ShowAllHistory"
              oncommand="PlacesCommandHook.showPlacesOrganizer('History');"/>
   </commandset>
 
+  <commandset id="inspectorCommands">
+    <command id="Inspector:Inspect"
+             oncommand="InspectorUI.toggleInspection();"/>
+    <command id="Inspector:Previous"
+             oncommand="InspectorUI.inspectPrevious();"
+             disabled="true"/>
+    <command id="Inspector:Next"
+             oncommand="InspectorUI.inspectNext();"
+             disabled="true"/>
+    <command id="Inspector:Style"
+             oncommand="InspectorUI.toggleStylePanel();"/>
+  </commandset>
+
   <broadcasterset id="mainBroadcasterSet">
     <broadcaster id="viewBookmarksSidebar" autoCheck="false" label="&bookmarksButton.label;"
                  type="checkbox" group="sidebar" sidebarurl="chrome://browser/content/bookmarks/bookmarksPanel.xul"
                  oncommand="toggleSidebar('viewBookmarksSidebar');"/>
 
     <!-- for both places and non-places, the sidebar lives at
          chrome://browser/content/history/history-panel.xul so there are no
          problems when switching between versions -->
--- a/browser/base/content/browser.css
+++ b/browser/base/content/browser.css
@@ -314,22 +314,16 @@ window[chromehidden~="toolbar"] toolbar:
   -moz-binding: url("chrome://browser/content/browser-tabPreviews.xml#allTabs-preview");
 }
 
 #allTabs-tab-close-button {
   -moz-binding: url("chrome://global/content/bindings/toolbarbutton.xml#toolbarbutton-image");
   margin: 0;
 }
 
-/* Inspector / Highlighter */
-
-#highlighter-panel {
-  -moz-appearance: none;
-  -moz-window-shadow: none;
-}
 
 /* notification anchors should only be visible when their associated
    notifications are */
 .notification-anchor-icon {
   display: none;
 }
 
 #notification-popup-box[anchorid="geo-notification-icon"] > #geo-notification-icon,
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -1414,17 +1414,17 @@ function delayedStartup(isLoadingBlank, 
   try {
     Cc["@mozilla.org/browser/sessionstore;1"]
       .getService(Ci.nsISessionStore)
       .init(window);
   } catch (ex) {
     dump("nsSessionStore could not be initialized: " + ex + "\n");
   }
 
-  PlacesToolbarHelper.updateState();
+  PlacesToolbarHelper.init();
 
   // bookmark-all-tabs command
   gBookmarkAllTabsHandler.init();
 
   // Attach a listener to watch for "command" events bubbling up from error
   // pages.  This lets us fix bugs like 401575 which require error page UI to
   // do privileged things, without letting error pages have any privilege
   // themselves.
@@ -2670,25 +2670,19 @@ var PrintPreviewListener = {
     gBrowser.selectedTab = this._tabBeforePrintPreview;
     this._tabBeforePrintPreview = null;
     gBrowser.removeTab(this._printPreviewTab);
     this._printPreviewTab = null;
     gInPrintPreviewMode = false;
     this._toggleAffectedChrome();
   },
   _toggleAffectedChrome: function () {
-    // chrome to toggle includes:
-    //   (*) menubar
-    //   (*) navigation bar
-    //   (*) bookmarks toolbar
-    //   (*) tabstrip
-    //   (*) browser messages
-    //   (*) sidebar
-    //   (*) find bar
-    //   (*) statusbar
+#ifdef MENUBAR_CAN_AUTOHIDE
+    updateAppButtonDisplay();
+#endif
 
     gNavToolbox.hidden = gInPrintPreviewMode;
 
     if (gInPrintPreviewMode)
       this._hideChrome();
     else
       this._showChrome();
 
@@ -3421,16 +3415,17 @@ function BrowserCustomizeToolbar()
   cmd.setAttribute("disabled", "true");
 
   var splitter = document.getElementById("urlbar-search-splitter");
   if (splitter)
     splitter.parentNode.removeChild(splitter);
 
   CombinedStopReload.uninit();
 
+  PlacesToolbarHelper.customizeStart();
   BookmarksMenuButton.customizeStart();
 
   var customizeURL = "chrome://global/content/customizeToolbar.xul";
   gCustomizeSheet = getBoolPref("toolbar.customization.usesheet", false);
 
   if (gCustomizeSheet) {
     var sheetFrame = document.getElementById("customizeToolbarSheetIFrame");
     var panel = document.getElementById("customizeToolbarSheetPopup");
@@ -3484,17 +3479,17 @@ function BrowserToolboxCustomizeDone(aTo
         document.getElementById('Browser:Back').hasAttribute('disabled') &&
         document.getElementById('Browser:Forward').hasAttribute('disabled');
 
 #ifndef XP_MACOSX
     updateEditUIVisibility();
 #endif
   }
 
-  PlacesToolbarHelper.updateState();
+  PlacesToolbarHelper.customizeDone();
   BookmarksMenuButton.customizeDone();
 
   UpdateUrlbarSearchSplitterState();
 
   CombinedStopReload.init();
 
   // Update the urlbar
   if (gURLBar) {
@@ -3518,17 +3513,17 @@ function BrowserToolboxCustomizeDone(aTo
 
   // XXX Shouldn't have to do this, but I do
   if (!gCustomizeSheet)
     window.focus();
 }
 
 function BrowserToolboxCustomizeChange() {
   gHomeButton.updatePersonalToolbarStyle();
-
+  BookmarksMenuButton.customizeChange();
   allTabs.readPref();
 }
 
 /**
  * Update the global flag that tracks whether or not any edit UI (the Edit menu,
  * edit-related items in the context menu, and edit-related toolbar buttons
  * is visible, then update the edit commands' enabled state accordingly.  We use
  * this flag to skip updating the edit commands on focus or selection changes
@@ -3805,17 +3800,18 @@ var FullScreen =
     }
     else {
       gBrowser.mPanelContainer.removeEventListener("mousemove",
                                                    this._collapseCallback, false);
     }
 
     // Hiding/collapsing the toolbox interferes with the tab bar's scrollbox,
     // so we just move it off-screen instead. See bug 430687.
-    gNavToolbox.style.marginTop = aShow ? "" : -gNavToolbox.clientHeight + "px";
+    gNavToolbox.style.marginTop =
+      aShow ? "" : -gNavToolbox.getBoundingClientRect().height + "px";
 
     document.getElementById("fullscr-toggler").collapsed = aShow;
     this._isChromeCollapsed = !aShow;
     if (gPrefService.getIntPref("browser.fullscreen.animateUp") == 2)
       this._shouldAnimate = true;
   },
 
   showXULChrome: function(aTag, aShow)
@@ -4674,54 +4670,63 @@ function onViewToolbarsPopupShowing(aEve
     }
     toolbar = toolbar.nextSibling;
   }
 }
 
 function onViewToolbarCommand(aEvent) {
   var index = aEvent.originalTarget.getAttribute("toolbarindex");
   var toolbar = gNavToolbox.childNodes[index];
+  var visible = aEvent.originalTarget.getAttribute("checked") == "true";
+  setToolbarVisibility(toolbar, visible);
+}
+
+function setToolbarVisibility(toolbar, visible) {
   var hidingAttribute = toolbar.getAttribute("type") == "menubar" ?
                         "autohide" : "collapsed";
 
-  toolbar.setAttribute(hidingAttribute,
-                       aEvent.originalTarget.getAttribute("checked") != "true");
+  toolbar.setAttribute(hidingAttribute, !visible);
   document.persist(toolbar.id, hidingAttribute);
 
+  PlacesToolbarHelper.init();
   BookmarksMenuButton.updatePosition();
 
 #ifdef MENUBAR_CAN_AUTOHIDE
   updateAppButtonDisplay();
 #endif
 }
 
 var TabsOnTop = {
   toggle: function () {
     this.enabled = !this.enabled;
   },
   syncCommand: function () {
     let enabled = this.enabled;
     document.getElementById("cmd_ToggleTabsOnTop")
             .setAttribute("checked", enabled);
     document.documentElement.setAttribute("tabsontop", enabled);
+    document.getElementById("TabsToolbar").setAttribute("tabsontop", enabled);
+    gBrowser.tabContainer.setAttribute("tabsontop", enabled);
   },
   get enabled () {
     return gNavToolbox.getAttribute("tabsontop") == "true";
   },
   set enabled (val) {
     gNavToolbox.setAttribute("tabsontop", !!val);
     this.syncCommand();
 
     return val;
   }
 }
 
 #ifdef MENUBAR_CAN_AUTOHIDE
 function updateAppButtonDisplay() {
-  var displayAppButton = window.menubar.visible &&
+  var displayAppButton =
+    !gInPrintPreviewMode &&
+    window.menubar.visible &&
     document.getElementById("toolbar-menubar").getAttribute("autohide") == "true";
 
   document.getElementById("appmenu-button-container").hidden = !displayAppButton;
 
   if (displayAppButton)
     document.documentElement.setAttribute("chromemargin", "0,-1,-1,-1");
   else
     document.documentElement.removeAttribute("chromemargin");
@@ -7745,16 +7750,21 @@ function switchToTabHavingURI(aURI, aOpe
 }
 
 var TabContextMenu = {
   contextTab: null,
   updateContextMenu: function updateContextMenu(aPopupMenu) {
     this.contextTab = document.popupNode.localName == "tab" ?
                       document.popupNode : gBrowser.selectedTab;
     var disabled = gBrowser.tabs.length == 1;
+
+    // Enable the "Close Tab" menuitem when the window doesn't close with the last tab.
+    document.getElementById("context_closeTab").disabled =
+      disabled && gBrowser.tabContainer._closeWindowWithLastTab;
+
     var menuItems = aPopupMenu.getElementsByAttribute("tbattr", "tabbrowser-multiple");
     for (var i = 0; i < menuItems.length; i++)
       menuItems[i].disabled = disabled;
 
     // Session store
     // XXXzeniko should't we just disable this item as we disable
     // the tabbrowser-multiple items above - for consistency?
     document.getElementById("context_undoCloseTab").hidden =
--- a/browser/base/content/browser.xul
+++ b/browser/base/content/browser.xul
@@ -81,17 +81,16 @@
         titlemodifier_privatebrowsing="&mainWindow.titlemodifier;@PRE_RELEASE_SUFFIX@ &mainWindow.titlePrivateBrowsingSuffix;"
 #endif
         titlemenuseparator="&mainWindow.titlemodifiermenuseparator;"
         lightweightthemes="true"
         lightweightthemesfooter="browser-bottombox"
         windowtype="navigator:browser"
         screenX="4" screenY="4"
         browsingmode="normal"
-        toggletoolbar="true"
         persist="screenX screenY width height sizemode"> 
 
 # All JS files which are not content (only) dependent that browser.xul
 # wishes to include *must* go into the global-scripts.inc file
 # so that they can be shared by macBrowserOverlay.xul.
 #include global-scripts.inc
 <script type="application/javascript" src="chrome://browser/content/nsContextMenu.js"/>
 
@@ -142,17 +141,16 @@
                 accesskey="&bookmarkAllTabs.accesskey;"
                 command="Browser:BookmarkAllTabs"/>
       <menuitem id="context_undoCloseTab"
                 label="&undoCloseTab.label;"
                 accesskey="&undoCloseTab.accesskey;"
                 command="History:UndoCloseTab"/>
       <menuseparator/>
       <menuitem id="context_closeTab" label="&closeTab.label;" accesskey="&closeTab.accesskey;"
-                tbattr="tabbrowser-multiple"
                 oncommand="gBrowser.removeTab(TabContextMenu.contextTab);"/>
     </menupopup>
 
     <menupopup id="backForwardMenu"
                onpopupshowing="return FillHistoryMenu(event.target);"
                oncommand="gotoHistoryIndex(event);"
                onclick="checkForMiddleClick(this, event);"/>
     <tooltip id="aHTMLTooltip" onpopupshowing="return FillInHTMLTooltip(document.tooltipNode);"/>
@@ -230,29 +228,76 @@
            onmousemove="InspectorUI.highlighter.handleMouseMove(event);"/>
 
     <panel id="inspector-panel"
            orient="vertical"
            hidden="true"
            ignorekeys="true"
            noautofocus="true"
            noautohide="true"
-           level="top"
-           aria-labelledby="inspectPagePanelTitle">
-      <tree id="inspector-tree" class="plain" seltype="single" treelines="true"
-            onselect="InspectorUI.onTreeSelected()" flex="1">
+           level="top">
+      <toolbar id="inspector-toolbar"
+               nowindowdrag="true">
+        <toolbarbutton id="inspector-inspect-toolbutton"
+                       label="&inspectButton.label;"
+                       accesskey="&inspectButton.accesskey;"
+                       class="toolbarbutton-text"
+                       command="Inspector:Inspect"/>
+        <toolbarbutton id="inspector-previous-toolbutton"
+                       label="&inspectPreviousButton.label;"
+                       accesskey="&inspectPreviousButton.accesskey;"
+                       class="toolbarbutton-text"
+                       command="Inspector:Previous"/>
+        <toolbarbutton id="inspector-next-toolbutton"
+                       label="&inspectNextButton.label;"
+                       accesskey="&inspectNextButton.accesskey;"
+                       class="toolbarbutton-text"
+                       command="Inspector:Next"/>
+        <toolbarbutton id="inspector-style-toolbutton"
+                       label="&inspectStyleButton.label;"
+                       accesskey="&inspectStyleButton.accesskey;"
+                       class="toolbarbutton-text"
+                       command="Inspector:Style"/>
+      </toolbar>
+      <tree id="inspector-tree" class="plain"
+            seltype="single"
+            treelines="true"
+            onselect="InspectorUI.onTreeSelected()"
+            flex="1">
         <treecols>
           <treecol id="colNodeName" label="nodeName" primary="true"
                    persist="width,hidden,ordinal" flex="1"/>
           <splitter class="tree-splitter"/>
           <treecol id="colNodeValue" label="nodeValue"
                    persist="width,hidden,ordinal" flex="1"/>
         </treecols>
         <treechildren id="inspector-tree-body"/>
       </tree>
+      <hbox align="end">
+        <spacer flex="1" />
+        <resizer dir="bottomend" />
+      </hbox>
+    </panel>
+
+    <panel id="inspector-style-panel"
+           hidden="true"
+           orient="vertical"
+           ignorekeys="true"
+           noautofocus="true"
+           noautohide="true"
+           level="top">
+        <toolbar id="inspector-style-toolbar"
+                 nowindowdrag="true">
+          <label>&inspectStylePanelTitle.label;</label>
+        </toolbar>
+        <listbox id="inspector-style-listbox" flex="1"/>
+        <hbox align="end">
+          <spacer flex="1" />
+          <resizer dir="bottomend" />
+        </hbox>
     </panel>
 
     <menupopup id="toolbar-context-menu"
                onpopupshowing="onViewToolbarsPopupShowing(event);">
       <menuseparator/>
       <menuitem command="cmd_ToggleTabsOnTop"
                 type="checkbox"
                 label="&viewTabsOnTop.label;"
@@ -389,17 +434,17 @@
   </popupset>
 
 #ifdef MENUBAR_CAN_AUTOHIDE
   <hbox id="appmenu-button-container">
     <button id="appmenu-button"
             type="menu"
             label="&brandShortName;"
             style="-moz-user-focus: ignore;">
-      <menupopup>
+      <menupopup id="appmenu-popup">
         <menuitem id="appmenu_newNavigator"
                   label="&newNavigatorCmd.label;"
                   command="cmd_newNavigator"/>
         <menuseparator/>
         <menuitem id="appmenu_savePage"
                   label="&savePageCmd.label;"
                   command="Browser:SavePage"/>
         <menuitem id="appmenu_sendLink"
@@ -505,16 +550,19 @@
   <toolbox id="navigator-toolbox"
            defaultmode="icons" mode="icons"
 #ifdef WINCE
            defaulticonsize="small" iconsize="small"
 #endif
 #ifdef XP_WIN
            tabsontop="true"
 #endif
+#ifdef XP_MACOSX
+           tabsontop="true"
+#endif
            persist="tabsontop">
     <!-- Menu -->
     <toolbar type="menubar" id="toolbar-menubar" class="chromeclass-menubar" customizable="true"
              defaultset="menubar-items"
              mode="icons" iconsize="small" defaulticonsize="small"
              lockiconsize="true"
 #ifdef MENUBAR_CAN_AUTOHIDE
              toolbarname="&menubarCmd.label;"
@@ -666,17 +714,18 @@
 
       <toolbaritem id="search-container" title="&searchItem.title;"
                    align="center" class="chromeclass-toolbar-additional"
                    flex="100" persist="width" removable="true">
         <searchbar id="searchbar" flex="1"/>
       </toolbaritem>
 
       <toolbaritem id="bookmarks-menu-button-container"
-                   class="chromeclass-toolbar-additional">
+                   class="chromeclass-toolbar-additional"
+                   removable="true">
         <toolbarbutton id="bookmarks-menu-button"
                        type="menu"
                        class="toolbarbutton-1"
                        label="&bookmarksMenuButton.label;"
                        tooltiptext="&bookmarksMenuButton.tooltip;"
                        ondragenter="PlacesMenuDNDHandler.onDragEnter(event);"
                        ondragover="PlacesMenuDNDHandler.onDragOver(event);"
                        ondragleave="PlacesMenuDNDHandler.onDragLeave(event);"
@@ -809,17 +858,16 @@
              iconsize="small" defaulticonsize="small" lockiconsize="true"
              aria-label="&tabsToolbar.label;"
              context="toolbar-context-menu"
              defaultset="tabbrowser-tabs,new-tab-button,alltabs-button,tabs-closebutton"
              collapsed="true">
 
       <tabs id="tabbrowser-tabs"
             class="tabbrowser-tabs"
-            context="tabContextMenu"
             tabbrowser="content"
             flex="1"
             setfocus="false"
             tooltip="tabbrowser-tab-tooltip">
         <tab class="tabbrowser-tab" selected="true"/>
       </tabs>
 
       <toolbarbutton id="new-tab-button"
--- a/browser/base/content/inspector.js
+++ b/browser/base/content/inspector.js
@@ -122,25 +122,25 @@ PanelHighlighter.prototype = {
     } else {
       this.highlightVisibleRegion(rect);
     }
   },
 
   /**
    * Highlight the given node.
    *
-   * @param element
+   * @param aNode
    *        a DOM element to be highlighted
-   * @param params
+   * @param aParams
    *        extra parameters object
    */
-  highlightNode: function PanelHighlighter_highlightNode(element, params)
+  highlightNode: function PanelHighlighter_highlightNode(aNode, aParams)
   {
-    this.node = element;
-    this.highlight(params && params.scroll);
+    this.node = aNode;
+    this.highlight(aParams && aParams.scroll);
   },
 
   /**
    * Highlight the visible region of the region described by aRect, if any.
    *
    * @param aRect
    * @returns boolean
    *          was a region highlighted?
@@ -208,28 +208,28 @@ PanelHighlighter.prototype = {
   get isHighlighting()
   {
     return this.panel.state == "open";
   },
 
   /**
    * Return the midpoint of a line from pointA to pointB.
    *
-   * @param pointA
+   * @param aPointA
    *        An object with x and y properties.
-   * @param pointB
+   * @param aPointB
    *        An object with x and y properties.
    * @returns aPoint
    *          An object with x and y properties.
    */
-  midPoint: function PanelHighlighter_midPoint(pointA, pointB)
+  midPoint: function PanelHighlighter_midPoint(aPointA, aPointB)
   {
     let pointC = { };
-    pointC.x = (pointB.x - pointA.x) / 2 + pointA.x;
-    pointC.y = (pointB.y - pointA.y) / 2 + pointA.y;
+    pointC.x = (aPointB.x - aPointA.x) / 2 + aPointA.x;
+    pointC.y = (aPointB.y - aPointA.y) / 2 + aPointA.y;
     return pointC;
   },
 
   /**
    * Return the node under the highlighter rectangle. Useful for testing.
    * Calculation based on midpoint of diagonal from top left to bottom right
    * of panel.
    *
@@ -298,27 +298,27 @@ PanelHighlighter.prototype = {
   },
 
   /////////////////////////////////////////////////////////////////////////
   //// Event Handling
 
   /**
    * Handle mousemoves in panel when InspectorUI.inspecting is true.
    *
-   * @param event
+   * @param aEvent
    *        The MouseEvent triggering the method.
    */
-  handleMouseMove: function PanelHighlighter_handleMouseMove(event)
+  handleMouseMove: function PanelHighlighter_handleMouseMove(aEvent)
   {
     if (!InspectorUI.inspecting) {
       return;
     }
     let browserRect = this.browser.getBoundingClientRect();
-    let element = this.win.document.elementFromPoint(event.clientX -
-      browserRect.left, event.clientY - browserRect.top);
+    let element = this.win.document.elementFromPoint(aEvent.clientX -
+      browserRect.left, aEvent.clientY - browserRect.top);
     if (element && element != this.node) {
       InspectorUI.inspectNode(element);
     }
   },
 };
 
 ///////////////////////////////////////////////////////////////////////////
 //// InspectorTreeView
@@ -457,17 +457,17 @@ InspectorTreeView.prototype = {
       }
     }
 
     // We have all the ancestors, now open them one-by-one from the top
     // to bottom.
     let lastIndex;
     let view = this.tree.treeBoxObject.view;
 
-    for (let i = line.length - 1; i >= 0; i--) {
+    for (let i = line.length - 1; i >= 0; --i) {
       index = this.view.getRowIndexFromNode(line[i]);
       if (index < 0) {
         // Can't find the row, so stop trying to descend.
         break;
       }
       if (i > 0 && !view.isContainerOpen(index)) {
         view.toggleOpenState(index);
       }
@@ -487,53 +487,92 @@ InspectorTreeView.prototype = {
 //// InspectorUI
 
 /**
  * Main controller class for the Inspector.
  */
 var InspectorUI = {
   browser: null,
   _showTreePanel: true,
-  _showStylePanel: false,
+  _showStylePanel: true,
   _showDOMPanel: false,
   highlightColor: "#EEEE66",
   highlightThickness: 4,
   highlightOpacity: 0.4,
   selectEventsSuppressed: false,
   inspecting: false,
 
   /**
    * Toggle the inspector interface elements on or off.
    *
-   * @param event
+   * @param aEvent
    *        The event that requested the UI change. Toolbar button or menu.
    */
-  toggleInspectorUI: function InspectorUI_toggleInspectorUI()
+  toggleInspectorUI: function IUI_toggleInspectorUI(aEvent)
   {
     if (this.isPanelOpen) {
       this.closeInspectorUI();
     } else {
       this.openInspectorUI();
     }
   },
 
   /**
+   * Toggle the status of the inspector, starting or stopping it. Invoked
+   * from the toolbar's Inspect button.
+   */
+  toggleInspection: function IUI_toggleInspection()
+  {
+    if (this.inspecting) {
+      this.stopInspecting();
+    } else {
+      this.startInspecting();
+    }
+  },
+
+  /**
+   * Toggle the style panel. Invoked from the toolbar's Style button.
+   */
+  toggleStylePanel: function IUI_toggleStylePanel()
+  {
+    if (this._showStylePanel) {
+      this.stylePanel.hidePopup();
+    } else {
+      this.openStylePanel();
+      if (this.treeView.selectedNode) {
+        this.updateStylePanel(this.treeView.selectedNode);
+      }
+    }
+    this._showStylePanel = !this._showStylePanel;
+  },
+
+  /**
    * Is the tree panel open?
    *
    * @returns boolean
    */
   get isPanelOpen()
   {
     return this.treePanel && this.treePanel.state == "open";
   },
 
   /**
+   * Is the style panel open?
+   *
+   * @returns boolean
+   */
+  get isStylePanelOpen()
+  {
+    return this.stylePanel && this.stylePanel.state == "open";
+  },
+
+  /**
    * Open the inspector's tree panel and initialize it.
    */
-  openTreePanel: function InspectorUI_openTreePanel()
+  openTreePanel: function IUI_openTreePanel()
   {
     if (!this.treePanel) {
       this.treePanel = document.getElementById("inspector-panel");
       this.treePanel.hidden = false;
     }
     if (!this.isPanelOpen) {
       const panelWidthRatio = 7 / 8;
       const panelHeightRatio = 1 / 5;
@@ -541,126 +580,274 @@ var InspectorUI = {
       this.treePanel.openPopup(bar, "overlap", 120, -120, false, false);
       this.treePanel.sizeTo(this.win.outerWidth * panelWidthRatio, 
         this.win.outerHeight * panelHeightRatio);
       this.tree = document.getElementById("inspector-tree");
       this.createDocumentModel();
     }
   },
 
-  openStylePanel: function InspectorUI_openStylePanel()
+  /**
+   * Open the style panel if not already onscreen.
+   */
+  openStylePanel: function IUI_openStylePanel()
   {
-    // # todo
+    if (!this.stylePanel) {
+      this.stylePanel = document.getElementById("inspector-style-panel");
+      this.stylePanel.hidden = false;
+    }
+    if (!this.isStylePanelOpen) {
+      // open at top right of browser panel, offset by 20px from top.
+      this.stylePanel.openPopup(this.browser, "end_before", 0, 20, false, false);
+      // size panel to 200px wide by half browser height - 60.
+      this.stylePanel.sizeTo(200, this.win.outerHeight / 2 - 60);
+    }
   },
 
-  openDOMPanel: function InspectorUI_openDOMPanel()
+  /**
+   * Toggle the dimmed (semi-transparent) state for a panel by setting or
+   * removing a dimmed attribute.
+   *
+   * @param aDim
+   *        The panel to be dimmed.
+   */
+  toggleDimForPanel: function IUI_toggleDimForPanel(aDim)
   {
-    // # todo
+    if (aDim.hasAttribute("dimmed")) {
+      aDim.removeAttribute("dimmed");
+    } else {
+      aDim.setAttribute("dimmed", "true");
+    }
+  },
+
+  openDOMPanel: function IUI_openDOMPanel()
+  {
+    // # todo bug 561782
   },
 
   /**
    * Open inspector UI. tree, style and DOM panels if enabled. Add listeners for
-   * document scrolling and tabContainer.TabSelect.
+   * document scrolling, resize and tabContainer.TabSelect.
    */
-  openInspectorUI: function InspectorUI_openInspectorUI()
+  openInspectorUI: function IUI_openInspectorUI()
   {
     // initialization
     this.browser = gBrowser.selectedBrowser;
     this.win = this.browser.contentWindow;
+    if (!this.style) {
+      Cu.import("resource:///modules/stylePanel.jsm", this);
+      this.style.initialize();
+    }
 
     // open inspector UI
     if (this._showTreePanel) {
       this.openTreePanel();
     }
     if (this._showStylePanel) {
+      this.styleBox = document.getElementById("inspector-style-listbox");
+      this.clearStylePanel();
       this.openStylePanel();
     }
     if (this._showDOMPanel) {
       this.openDOMPanel();
     }
+    this.inspectorBundle = Services.strings.createBundle("chrome://browser/locale/inspector.properties");
     this.initializeHighlighter();
     this.startInspecting();
     this.win.document.addEventListener("scroll", this, false);
+    this.win.addEventListener("resize", this, false);
     gBrowser.tabContainer.addEventListener("TabSelect", this, false);
     this.inspectCmd.setAttribute("checked", true);
   },
 
   /**
    * Initialize highlighter.
    */
-  initializeHighlighter: function InspectorUI_initializeHighlighter()
+  initializeHighlighter: function IUI_initializeHighlighter()
   {
     this.highlighter = new PanelHighlighter(this.browser, this.highlightColor,
       this.highlightThickness, this.highlightOpacity);
   },
 
   /**
    * Close inspector UI and associated panels. Unhighlight and stop inspecting.
-   * Remove event listeners for document scrolling and
+   * Remove event listeners for document scrolling, resize and
    * tabContainer.TabSelect.
    */
-  closeInspectorUI: function InspectorUI_closeInspectorUI()
+  closeInspectorUI: function IUI_closeInspectorUI()
   {
     this.win.document.removeEventListener("scroll", this, false);
+    this.win.removeEventListener("resize", this, false);
     gBrowser.tabContainer.removeEventListener("TabSelect", this, false);
     this.stopInspecting();
     if (this.highlighter && this.highlighter.isHighlighting) {
       this.highlighter.unhighlight();
     }
     if (this.isPanelOpen) {
       this.treePanel.hidePopup();
       this.treeView.destroy();
     }
+    if (this.isStylePanelOpen) {
+      this.stylePanel.hidePopup();
+    }
     this.inspectCmd.setAttribute("checked", false);
     this.browser = this.win = null; // null out references to browser and window
   },
 
   /**
    * Begin inspecting webpage, attach page event listeners, activate
    * highlighter event listeners.
    */
-  startInspecting: function InspectorUI_startInspecting()
+  startInspecting: function IUI_startInspecting()
   {
     this.attachPageListeners();
     this.inspecting = true;
+    this.toggleDimForPanel(this.stylePanel);
   },
 
   /**
    * Stop inspecting webpage, detach page listeners, disable highlighter
    * event listeners.
    */
-  stopInspecting: function InspectorUI_stopInspecting()
+  stopInspecting: function IUI_stopInspecting()
   {
     if (!this.inspecting)
       return;
     this.detachPageListeners();
     this.inspecting = false;
+    this.toggleDimForPanel(this.stylePanel);
+    if (this.treeView.selection) {
+      this.updateStylePanel(this.treeView.selectedNode);
+    }
   },
 
   /////////////////////////////////////////////////////////////////////////
   //// Model Creation Methods
 
   /**
    * Create treeView object from content window.
    */
-  createDocumentModel: function InspectorUI_createDocumentModel()
+  createDocumentModel: function IUI_createDocumentModel()
   {
     this.treeView = new InspectorTreeView(this.win);
   },
 
+  /**
+   * add a new item to the listbox
+   *
+   * @param aLabel
+   *        A bit of text to put in the listitem's label attribute.
+   * @param aType
+   *        The type of item.
+   * @param content
+   *        Text content or value of the listitem.
+   */
+  addStyleItem: function IUI_addStyleItem(aLabel, aType, aContent)
+  {
+    let itemLabelString = this.inspectorBundle.GetStringFromName("style.styleItemLabel");
+    let item = document.createElement("listitem");
+
+    // Do not localize these strings
+    let label = aLabel;
+    item.className = "style-" + aType;
+    if (aContent) {
+      label = itemLabelString.replace("#1", aLabel);
+      label = label.replace("#2", aContent);
+    }
+    item.setAttribute("label", label);
+
+    this.styleBox.appendChild(item);
+  },
+
+  /**
+   * Create items for each rule included in the given array.
+   *
+   * @param aRules
+   *        an array of rule objects
+   */
+  createStyleRuleItems: function IUI_createStyleRuleItems(aRules)
+  {
+    let selectorLabel = this.inspectorBundle.GetStringFromName("style.selectorLabel");
+
+    aRules.forEach(function(rule) {
+      this.addStyleItem(selectorLabel, "selector", rule.id);
+      rule.properties.forEach(function(property) {
+        if (property.overridden)
+          return; // property marked overridden elsewhere
+        // Do not localize the strings below this line
+        let important = "";
+        if (property.important)
+          important += " !important";
+        this.addStyleItem(property.name, "property", property.value + important);
+      }, this);
+    }, this);
+  },
+
+  /**
+   * Create rule items for each section as well as the element's style rules,
+   * if any.
+   *
+   * @param aRules
+   *        Array of rules corresponding to the element's style object.
+   * @param aSections
+   *        Array of sections encapsulating the inherited rules for selectors
+   *        and elements.
+   */
+  createStyleItems: function IUI_createStyleItems(aRules, aSections)
+  {
+    this.createStyleRuleItems(aRules);
+    let inheritedString = 
+        this.inspectorBundle.GetStringFromName("style.inheritedFrom");
+    aSections.forEach(function(section) {
+      let sectionTitle = section.element.tagName;
+      if (section.element.id)
+        sectionTitle += "#" + section.element.id;
+      let replacedString = inheritedString.replace("#1", sectionTitle);
+      this.addStyleItem(replacedString, "section");
+      this.createStyleRuleItems(section.rules);
+    }, this);
+  },
+
+  /**
+   * Remove all items from the Style Panel's listbox.
+   */
+  clearStylePanel: function IUI_clearStylePanel()
+  {
+    for (let i = this.styleBox.childElementCount; i >= 0; --i)
+      this.styleBox.removeItemAt(i);
+  },
+
+  /**
+   * Update the contents of the style panel with styles for the currently
+   * inspected node.
+   *
+   * @param aNode
+   *        The highlighted node to get styles for.
+   */
+  updateStylePanel: function IUI_updateStylePanel(aNode)
+  {
+    if (this.inspecting || !this.isStylePanelOpen)
+      return;
+    let rules = [], styleSections = [], usedProperties = {};
+    this.style.getInheritedRules(aNode, styleSections, usedProperties);
+    this.style.getElementRules(aNode, rules, usedProperties);
+    this.clearStylePanel();
+    this.createStyleItems(rules, styleSections);
+  },
+
   /////////////////////////////////////////////////////////////////////////
   //// Event Handling
 
   /**
    * Main callback handler for events.
    *
    * @param event
    *        The event to be handled.
    */
-  handleEvent: function InspectorUI_handleEvent(event)
+  handleEvent: function IUI_handleEvent(event)
   {
     switch (event.type) {
       case "TabSelect":
         this.closeInspectorUI();
         break;
       case "keypress":
         switch (event.keyCode) {
           case KeyEvent.DOM_VK_RETURN:
@@ -675,75 +862,78 @@ var InspectorUI = {
         if (element && element != this.node) {
           this.inspectNode(element);
         }
         break;
       case "click":
         this.stopInspecting();
         break;
       case "scroll":
+      case "resize":
         this.highlighter.highlight();
         break;
     }
   },
 
   /**
    * Event fired when a tree row is selected in the tree panel.
    */
-  onTreeSelected: function InspectorUI_onTreeSelected()
+  onTreeSelected: function IUI_onTreeSelected()
   {
     if (this.selectEventsSuppressed) {
       return false;
     }
 
     let treeView = this.treeView;
     let node = treeView.selectedNode;
-    this.highlighter.highlightNode(node); // # todo scrolling causes issues
+    this.highlighter.highlightNode(node);
     this.stopInspecting();
+    this.updateStylePanel(node);
     return true;
   },
 
   /**
    * Attach event listeners to content window and child windows to enable 
    * highlighting and click to stop inspection.
    */
-  attachPageListeners: function InspectorUI_attachPageListeners()
+  attachPageListeners: function IUI_attachPageListeners()
   {
     this.win.addEventListener("keypress", this, true);
     this.browser.addEventListener("mousemove", this, true);
     this.browser.addEventListener("click", this, true);
   },
 
   /**
    * Detach event listeners from content window and child windows
    * to disable highlighting.
    */
-  detachPageListeners: function InspectorUI_detachPageListeners()
+  detachPageListeners: function IUI_detachPageListeners()
   {
     this.win.removeEventListener("keypress", this, true);
     this.browser.removeEventListener("mousemove", this, true);
     this.browser.removeEventListener("click", this, true);
   },
 
   /////////////////////////////////////////////////////////////////////////
   //// Utility Methods
 
   /**
    * inspect the given node, highlighting it on the page and selecting the
    * correct row in the tree panel
    *
-   * @param element
+   * @param aNode
    *        the element in the document to inspect
    */
-  inspectNode: function InspectorUI_inspectNode(element)
+  inspectNode: function IUI_inspectNode(aNode)
   {
-    this.highlighter.highlightNode(element);
+    this.highlighter.highlightNode(aNode);
     this.selectEventsSuppressed = true;
-    this.treeView.selectedNode = element;
+    this.treeView.selectedNode = aNode;
     this.selectEventsSuppressed = false;
+    this.updateStylePanel(aNode);
   },
 
   ///////////////////////////////////////////////////////////////////////////
   //// Utility functions
 
   /**
    * debug logging facility
    * @param msg
--- a/browser/base/content/nsContextMenu.js
+++ b/browser/base/content/nsContextMenu.js
@@ -198,17 +198,17 @@ nsContextMenu.prototype = {
       }
 
       if (uri && uri.host) {
         this.linkURI = uri;
         this.linkURL = this.linkURI.spec;
         onPlainTextLink = true;
       }
     }
- 
+
     var shouldShow = this.onSaveableLink || isMailtoInternal || onPlainTextLink;
     this.showItem("context-openlink", shouldShow);
     this.showItem("context-openlinkintab", shouldShow);
     this.showItem("context-openlinkincurrent", onPlainTextLink);
     this.showItem("context-sep-open", shouldShow);
   },
 
   initNavigationItems: function CM_initNavigationItems() {
@@ -300,17 +300,17 @@ nsContextMenu.prototype = {
     document.getElementById("context-viewbgimage")
             .disabled = !this.hasBGImage;
 
     this.showItem("context-viewimageinfo", this.onImage);
   },
 
   initMiscItems: function CM_initMiscItems() {
     var isTextSelected = this.isTextSelected;
-    
+
     // Use "Bookmark This Link" if on a link.
     this.showItem("context-bookmarkpage",
                   !(this.isContentSelected || this.onTextInput || this.onLink ||
                     this.onImage || this.onVideo || this.onAudio));
     this.showItem("context-bookmarklink", this.onLink && !this.onMailtoLink);
     this.showItem("context-searchselect", isTextSelected);
     this.showItem("context-keywordfield",
                   this.onTextInput && this.onKeywordField);
@@ -326,46 +326,16 @@ nsContextMenu.prototype = {
     }
 
     // BiDi UI
     this.showItem("context-sep-bidi", top.gBidiUI);
     this.showItem("context-bidi-text-direction-toggle",
                   this.onTextInput && top.gBidiUI);
     this.showItem("context-bidi-page-direction-toggle",
                   !this.onTextInput && top.gBidiUI);
-
-    var hostLabel = "";
-    if (this.onImage) {
-      var blockImage = document.getElementById("context-blockimage");
-
-      var uri = this.target
-                    .QueryInterface(Ci.nsIImageLoadingContent)
-                    .currentURI;
-
-      // this throws if the image URI doesn't have a host (eg, data: image URIs)
-      // see bug 293758 for details
-      try {
-        hostLabel = uri.host;
-      } catch (ex) { }
-
-      if (hostLabel) {
-        if (hostLabel.length > 15)
-          hostLabel = hostLabel.substr(0,15) + this.ellipsis;
-        blockImage.label = gNavigatorBundle.getFormattedString("blockImages", [hostLabel]);
-
-        if (this.isImageBlocked())
-          blockImage.setAttribute("checked", "true");
-        else
-          blockImage.removeAttribute("checked");
-      }
-    }
-
-    // Only show the block image item if the image can be blocked
-    this.showItem("context-blockimage", this.onImage && hostLabel &&
-      !gPrivateBrowsingUI.privateBrowsingEnabled);
   },
 
   initSpellingItems: function() {
     var canSpell = InlineSpellCheckerUI.canSpellCheck;
     var onMisspelling = InlineSpellCheckerUI.overMisspelling;
     this.showItem("spell-check-enabled", canSpell);
     this.showItem("spell-separator", canSpell || this.onEditableArea);
     if (canSpell) {
@@ -519,17 +489,17 @@ nsContextMenu.prototype = {
     this.target = aNode;
 
     // First, do checks for nodes that never have children.
     if (this.target.nodeType == Node.ELEMENT_NODE) {
       // See if the user clicked on an image.
       if (this.target instanceof Ci.nsIImageLoadingContent &&
           this.target.currentURI) {
         this.onImage = true;
-                
+
         var request =
           this.target.getRequest(Ci.nsIImageLoadingContent.CURRENT_REQUEST);
         if (request && (request.imageStatus & request.STATUS_SIZE_AVAILABLE))
           this.onLoadedImage = true;
         if (request && (request.imageStatus & request.STATUS_LOAD_COMPLETE))
           this.onCompletedImage = true;
 
         this.mediaURL = this.target.currentURI.spec;
@@ -592,17 +562,17 @@ nsContextMenu.prototype = {
     while (elem) {
       if (elem.nodeType == Node.ELEMENT_NODE) {
         // Link?
         if (!this.onLink &&
              ((elem instanceof HTMLAnchorElement && elem.href) ||
               (elem instanceof HTMLAreaElement && elem.href) ||
               elem instanceof HTMLLinkElement ||
               elem.getAttributeNS("http://www.w3.org/1999/xlink", "type") == "simple")) {
-            
+
           // Target is a link or a descendant of a link.
           this.onLink = true;
 
           // xxxmpc: this is kind of a hack to work around a Gecko bug (see bug 266932)
           // we're going to walk up the DOM looking for a parent link node,
           // this shouldn't be necessary, but we're matching the existing behaviour for left click
           var realLink = elem;
           var parent = elem;
@@ -611,17 +581,17 @@ nsContextMenu.prototype = {
             try {
               if ((parent instanceof HTMLAnchorElement && parent.href) ||
                   (parent instanceof HTMLAreaElement && parent.href) ||
                   parent instanceof HTMLLinkElement ||
                   parent.getAttributeNS("http://www.w3.org/1999/xlink", "type") == "simple")
                 realLink = parent;
             } catch (e) { }
           }
-          
+
           // Remember corresponding element.
           this.link = realLink;
           this.linkURL = this.getLinkURL();
           this.linkURI = this.getLinkURI();
           this.linkProtocol = this.getLinkProtocol();
           this.onMailtoLink = (this.linkProtocol == "mailto");
           this.onSaveableLink = this.isLinkSaveable( this.link );
         }
@@ -643,17 +613,17 @@ nsContextMenu.prototype = {
             this.bgImageURL = makeURLAbsolute(elem.baseURI,
                                               bgImgUrl);
           }
         }
       }
 
       elem = elem.parentNode;
     }
-    
+
     // See if the user clicked on MathML
     const NS_MathML = "http://www.w3.org/1998/Math/MathML";
     if ((this.target.nodeType == Node.TEXT_NODE &&
          this.target.parentNode.namespaceURI == NS_MathML)
          || (this.target.namespaceURI == NS_MathML))
       this.onMathML = true;
 
     // See if the user clicked in a frame.
@@ -933,17 +903,17 @@ nsContextMenu.prototype = {
   saveFrame: function () {
     saveDocument(this.target.ownerDocument);
   },
 
   // Save URL of clicked-on link.
   saveLink: function() {
     // canonical def in nsURILoader.h
     const NS_ERROR_SAVE_LINK_AS_TIMEOUT = 0x805d0020;
-    
+
     var doc =  this.target.ownerDocument;
     urlSecurityCheck(this.linkURL, doc.nodePrincipal);
     var linkText = this.linkText();
     var linkURL = this.linkURL;
 
 
     // an object to proxy the data through to
     // nsIExternalHelperAppService.doContent, which will wait for the
@@ -965,20 +935,20 @@ nsContextMenu.prototype = {
 
         // some other error occured; notify the user...
         if (!Components.isSuccessCode(aRequest.status)) {
           try {
             const sbs = Cc["@mozilla.org/intl/stringbundle;1"].
                         getService(Ci.nsIStringBundleService);
             const bundle = sbs.createBundle(
                     "chrome://mozapps/locale/downloads/downloads.properties");
-            
+
             const title = bundle.GetStringFromName("downloadErrorAlertTitle");
             const msg = bundle.GetStringFromName("downloadErrorGeneric");
-            
+
             const promptSvc = Cc["@mozilla.org/embedcomp/prompt-service;1"].
                               getService(Ci.nsIPromptService);
             promptSvc.alert(doc.defaultView, title, msg);
           } catch (ex) {}
           return;
         }
 
         var extHelperAppSvc = 
@@ -996,17 +966,17 @@ nsContextMenu.prototype = {
         if (aStatusCode == NS_ERROR_SAVE_LINK_AS_TIMEOUT) {
           // do it the old fashioned way, which will pick the best filename
           // it can without waiting.
           saveURL(linkURL, linkText, null, true, false, doc.documentURIObject);
         }
         if (this.extListener)
           this.extListener.onStopRequest(aRequest, aContext, aStatusCode);
       },
-       
+
       onDataAvailable: function saveLinkAs_onDataAvailable(aRequest, aContext,
                                                            aInputStream,
                                                            aOffset, aCount) {
         this.extListener.onDataAvailable(aRequest, aContext, aInputStream,
                                          aOffset, aCount);
       }
     }
 
@@ -1095,63 +1065,16 @@ nsContextMenu.prototype = {
     if (this.onCanvas || this.onImage)
         this.sendMedia();
   },
 
   sendMedia: function() {
     MailIntegration.sendMessage(this.mediaURL, "");
   },
 
-  toggleImageBlocking: function(aBlock) {
-    var permissionmanager = Cc["@mozilla.org/permissionmanager;1"].
-                            getService(Ci.nsIPermissionManager);
-
-    var uri = this.target.QueryInterface(Ci.nsIImageLoadingContent).currentURI;
-
-    if (aBlock)
-      permissionmanager.add(uri, "image", Ci.nsIPermissionManager.DENY_ACTION);
-    else
-      permissionmanager.remove(uri.host, "image");
-
-    var brandBundle = document.getElementById("bundle_brand");
-    var app = brandBundle.getString("brandShortName");
-    var message = gNavigatorBundle.getFormattedString(aBlock ?
-     "imageBlockedWarning" : "imageAllowedWarning", [app, uri.host]);
-
-    var notificationBox = this.browser.getNotificationBox();
-    var notification = notificationBox.getNotificationWithValue("images-blocked");
-
-    if (notification)
-      notification.label = message;
-    else {
-      var self = this;
-      var buttons = [{
-        label: gNavigatorBundle.getString("undo"),
-        accessKey: gNavigatorBundle.getString("undo.accessKey"),
-        callback: function() { self.toggleImageBlocking(!aBlock); }
-      }];
-      const priority = notificationBox.PRIORITY_WARNING_MEDIUM;
-      notificationBox.appendNotification(message, "images-blocked",
-                                         "chrome://browser/skin/Info.png",
-                                         priority, buttons);
-    }
-
-    // Reload the page to show the effect instantly
-    BrowserReload();
-  },
-
-  isImageBlocked: function() {
-    var permissionmanager = Cc["@mozilla.org/permissionmanager;1"].
-                            getService(Ci.nsIPermissionManager);
-
-    var uri = this.target.QueryInterface(Ci.nsIImageLoadingContent).currentURI;
-
-    return permissionmanager.testPermission(uri, "image") == Ci.nsIPermissionManager.DENY_ACTION;
-  },
-
   // Generate email address and put it on clipboard.
   copyEmail: function() {
     // Copy the comma-separated list of email addresses only.
     // There are other ways of embedding email addresses in a mailto:
     // link, but such complex parsing is beyond us.
     var url = this.linkURL;
     var qmark = url.indexOf("?");
     var addresses;
@@ -1243,28 +1166,28 @@ nsContextMenu.prototype = {
     if (!href || !href.match(/\S/)) {
       // Without this we try to save as the current doc,
       // for example, HTML case also throws if empty
       throw "Empty href";
     }
 
     return makeURLAbsolute(this.link.baseURI, href);
   },
-  
+
   getLinkURI: function() {
     try {
       return makeURI(this.linkURL);
     }
     catch (ex) {
      // e.g. empty URL string
     }
 
     return null;
   },
-  
+
   getLinkProtocol: function() {
     if (this.linkURI)
       return this.linkURI.scheme; // can be |undefined|
 
     return null;
   },
 
   // Get text of link.
--- a/browser/base/content/pageinfo/security.js
+++ b/browser/base/content/pageinfo/security.js
@@ -276,24 +276,24 @@ function securityOnLoad() {
   var msg2;
 
   if (info.isBroken) {
     hdr = pkiBundle.getString("pageInfo_MixedContent");
     msg1 = pkiBundle.getString("pageInfo_Privacy_Mixed1");
     msg2 = pkiBundle.getString("pageInfo_Privacy_None2");
   }
   else if (info.encryptionStrength >= 90) {
-    hdr = pkiBundle.getFormattedString("pageInfo_StrongEncryption",
+    hdr = pkiBundle.getFormattedString("pageInfo_StrongEncryptionWithBits",
                                        [info.encryptionAlgorithm, info.encryptionStrength + ""]);
     msg1 = pkiBundle.getString("pageInfo_Privacy_Strong1");
     msg2 = pkiBundle.getString("pageInfo_Privacy_Strong2");
     security._cert = info.cert;
   }
   else if (info.encryptionStrength > 0) {
-    hdr  = pkiBundle.getFormattedString("pageInfo_WeakEncryption",
+    hdr  = pkiBundle.getFormattedString("pageInfo_WeakEncryptionWithBits",
                                         [info.encryptionAlgorithm, info.encryptionStrength + ""]);
     msg1 = pkiBundle.getFormattedString("pageInfo_Privacy_Weak1", [info.hostName]);
     msg2 = pkiBundle.getString("pageInfo_Privacy_Weak2");
   }
   else {
     hdr = pkiBundle.getString("pageInfo_NoEncryption");
     if (info.hostName != null)
       msg1 = pkiBundle.getFormattedString("pageInfo_Privacy_None1", [info.hostName]);
new file mode 100644
--- /dev/null
+++ b/browser/base/content/stylePanel.jsm
@@ -0,0 +1,311 @@
+/*
+ * Software License Agreement (BSD License)
+ *
+ * Copyright (c) 2007, Parakey Inc.
+ * All rights reserved.
+ * 
+ * Redistribution and use of this software in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ * 
+ * * Redistributions of source code must retain the above
+ *   copyright notice, this list of conditions and the
+ *   following disclaimer.
+ * 
+ * * Redistributions in binary form must reproduce the above
+ *   copyright notice, this list of conditions and the
+ *   following disclaimer in the documentation and/or other
+ *   materials provided with the distribution.
+ * 
+ * * Neither the name of Parakey Inc. nor the names of its
+ *   contributors may be used to endorse or promote products
+ *   derived from this software without specific prior
+ *   written permission of Parakey Inc.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Creator:
+ *  Joe Hewitt
+ * Contributors
+ *  John J. Barton (IBM Almaden)
+ *  Jan Odvarko (Mozilla Corp.)
+ *  Max Stepanov (Aptana Inc.)
+ *  Rob Campbell (Mozilla Corp.)
+ *  Hans Hillen (Paciello Group, Mozilla)
+ *  Curtis Bartley (Mozilla Corp.)
+ *  Mike Collins (IBM Almaden)
+ *  Kevin Decker
+ *  Mike Ratcliffe (Comartis AG)
+ *  Hernan Rodríguez Colmeiro
+ *  Austin Andrews
+ *  Christoph Dorn
+ *  Steven Roussey (AppCenter Inc, Network54)
+ */
+
+var EXPORTED_SYMBOLS = ["style"];
+
+const Cc = Components.classes;
+const Ci = Components.interfaces;
+
+var style = {
+
+  /**
+   * initialize domUtils
+   */
+  initialize: function CSS_initialize()
+  {
+    this.domUtils = Cc["@mozilla.org/inspector/dom-utils;1"].
+      getService(Ci["inIDOMUtils"]);
+  },
+
+  /**
+   * Is the given property sheet a system (user agent) stylesheet?
+   *
+   * @param aSheet
+   *        a stylesheet
+   */
+  isSystemStyleSheet: function CSS_isSystemStyleSheet(aSheet)
+  {
+    if (!aSheet)
+      return true;
+
+    let url = aSheet.href;
+
+    if (!url)
+      return false;
+    if (url.length == 0)
+      return true;
+    if (url[0] == 'h') 
+      return false;
+    if (url.substr(0, 9) == "resource:")
+      return true;
+    if (url.substr(0, 7) == "chrome:")
+      return true;
+    if (url  == "XPCSafeJSObjectWrapper.cpp")
+      return true;
+    if (url.substr(0, 6) == "about:")
+      return true;
+
+    return false;
+  },
+
+  /**
+   * Parse properties from a given style object.
+   * Borrowed from Firebug's css.js.
+   *
+   * @param aStyle
+   *        a style object
+   */
+  parseCSSProperties: function CSS_parseCSSProps(aStyle)
+  {
+    let properties = [];
+    let lines = aStyle.cssText.match(/(?:[^;\(]*(?:\([^\)]*?\))?[^;\(]*)*;?/g);
+    let propRE = /\s*([^:\s]*)\s*:\s*(.*?)\s*(! important)?;?$/;
+    let line, i = 0;
+    while(line = lines[i++]) {
+      let match = propRE.exec(line);
+      if (!match)
+        continue;
+      let name = match[1];
+      let value = match[2];
+      let important = !!match[3]; // true if match[3] is non-empty
+      properties.unshift({name: name, value: value, important: important});
+    }
+
+    return properties;
+  },
+
+  /**
+   * Mark properties overridden further up the hierarchy.
+   *
+   * @param aProps
+   *        Array of properties.
+   * @param aUsedProps
+   *        Object of arrays keyed by property name.
+   * @param aInherit
+   *        Boolean of whether or not we are in inherited mode.
+   */
+  markOverriddenProperties: function CSS_markOverriddenProperties(aProps, aUsedProps, aInherit)
+  {
+    for (let i = 0; i < aProps.length; ++i) {
+      let prop = aProps[i];
+      if (aUsedProps.hasOwnProperty(prop.name)) {
+        // all previous occurrences of this property
+        let deadProps = aUsedProps[prop.name];
+        for (let j = 0; j < deadProps.length; ++j) {
+          let deadProp = deadProps[j];
+          if (!deadProp.disabled && !deadProp.wasInherited &&
+              deadProp.important && !prop.important) {
+            prop.overridden = true;  // new occurrence overridden
+          } else if (!prop.disabled) {
+            deadProp.overridden = true;  // previous occurrences overridden
+          } else {
+            aUsedProps[prop.name] = [];
+          }
+
+          prop.wasInherited = aInherit ? true : false;
+          // all occurrences of a property seen so far, by name
+          aUsedProps[prop.name].push(prop);
+        }
+      }
+    }
+  },
+
+  /**
+   * Sort given properties in lexical order by name.
+   *
+   * @param properties
+   *        An array of properties.
+   * @returns sorted array.
+   */
+  sortProperties: function CSS_sortProperties(properties)
+  {
+    properties.sort(function(a, b)
+    {
+      if (a.name < b.name) {
+        return -1;
+      }
+      if (a.name > b.name) {
+        return 1;
+      }
+      return 0;
+    });
+  },
+
+  /**
+   * Get properties for a given element and push them to the rules array.
+   *
+   * @param aNode
+   *        a DOM node
+   * @param rules
+   *        An array of rules to add properties to.
+   * @param usedProps
+   *        Object of arrays keyed by property name.
+   * @param inherit
+   *        boolean determining whether or not we're in inherit mode
+   */
+  getStyleProperties: function CSS_getStyleProperties(aNode, aRules, aUsedProps, aInherit)
+  {
+    let properties = this.parseCSSProperties(aNode.style, aInherit);
+
+    this.sortProperties(properties);
+    this.markOverriddenProperties(properties, aUsedProps, aInherit);
+
+    if (properties.length) {
+      aRules.push({rule: aNode, selector: "element.style",
+        properties: properties, inherited: aInherit});
+    }
+  },
+
+  /**
+   * Get properties for a given rule.
+   *
+   * @param aRule
+   *        A Rule from a stylesheet.
+   */
+  getRuleProperties: function CSS_getRuleProperties(aRule)
+  {
+    let style = aRule.style;
+    return this.parseCSSProperties(style);
+  },
+
+  /**
+   * Recursively get rules for an element's parents and add them to the
+   * sections array.
+   *
+   * @param aNode
+   *        an element in a DOM tree.
+   * @param sections
+   *        an array of sections
+   * @param usedProps
+   *        Object of arrays keyed by property name.
+   */
+  getInheritedRules: function CSS_getInheritedRules(aNode, aSections, aUsedProps)
+  {
+    let parent = aNode.parentNode;
+    if (parent && parent.nodeType == 1) {
+      this.getInheritedRules(parent, aSections, aUsedProps);
+
+      let rules = [];
+      this.getElementRules(parent, rules, aUsedProps, true);
+
+      if (rules.length) {
+        aSections.unshift({element: parent, rules: rules});
+      }
+    }
+  },
+
+  /**
+   * Get the CSS style rules for a given node in the DOM and append them to the
+   * rules array.
+   *
+   * @param aNode
+   *        an element in the DOM tree.
+   * @param aRules
+   *        an array of rules.
+   * @param aUsedProps
+   *        Object of arrays keyed by property name.
+   * @param aInherit
+   *        boolean indicating whether we are in an inherited mode or not
+   */
+  getElementRules: function CSS_getElementRules(aNode, aRules, aUsedProps, aInherit)
+  {
+    let inspectedRules;
+
+    try {
+      inspectedRules = this.domUtils.getCSSStyleRules(aNode);
+    } catch (ex) {
+      Services.console.logStringMessage(ex);
+    }
+
+    if (!inspectedRules)
+      return;
+
+    for (let i = 0; i < inspectedRules.Count(); ++i) {
+      let rule = inspectedRules.GetElementAt(i);
+      let href = rule.parentStyleSheet.href;
+
+      if (!href) {
+        // Null href means inline style.
+        href = aNode.ownerDocument.location.href;
+      }
+
+      let isSystemSheet = this.isSystemStyleSheet(rule.parentStyleSheet);
+
+      if (isSystemSheet)
+        continue;
+
+      let properties = this.getRuleProperties(rule, aInherit);
+      if (aInherit && !properties.length)
+        continue;
+
+      let line = this.domUtils.getRuleLine(rule);
+      let ruleId = rule.selectorText + " " + href + " (" + line + ")";
+
+      let sourceLink = "view-source:" + href + "#" + line;
+
+      this.markOverriddenProperties(properties, aUsedProps, aInherit);
+
+      aRules.unshift(
+        {rule: rule,
+         id: ruleId,
+         selector: rule.selectorText,
+         properties: properties,
+         inherited: aInherit,
+         sourceLink: sourceLink,
+         isSystemSheet: isSystemSheet});
+    }
+
+    if (aNode.style) {
+      this.getStyleProperties(aNode, aRules, aUsedProps, aInherit);
+    }
+  },
+};
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -2379,42 +2379,37 @@
           var tab = this.firstChild;
           tab.setAttribute("label",
                            this.tabbrowser.mStringBundle.getString("tabs.emptyTabTitle"));
           tab.setAttribute("crop", "end");
           tab.setAttribute("validate", "never");
           tab.setAttribute("onerror", "this.removeAttribute('image');");
           this.adjustTabstrip();
 
-          Services.prefs.addObserver("browser.tabs.closeButtons", this._prefObserver, false);
-          Services.prefs.addObserver("browser.tabs.autoHide", this._prefObserver, false);
-          Services.prefs.addObserver("browser.tabs.closeWindowWithLastTab", this._prefObserver, false);
-
+          Services.prefs.addObserver("browser.tabs.", this._prefObserver, false);
           window.addEventListener("resize", this, false);
         ]]>
       </constructor>
 
       <destructor>
         <![CDATA[
-          Services.prefs.removeObserver("browser.tabs.closeButtons", this._prefObserver);
-          Services.prefs.removeObserver("browser.tabs.autoHide", this._prefObserver);
-          Services.prefs.removeObserver("browser.tabs.closeWindowWithLastTab", this._prefObserver);
+          Services.prefs.removeObserver("browser.tabs.", this._prefObserver);
         ]]>
       </destructor>
 
       <field name="tabbrowser" readonly="true">
         document.getElementById(this.getAttribute("tabbrowser"));
       </field>
 
       <field name="tabbox" readonly="true">
         this.tabbrowser.mTabBox;
       </field>
 
       <field name="contextMenu" readonly="true">
-        document.getElementById(this.getAttribute("context"));
+        document.getElementById("tabContextMenu");
       </field>
 
       <field name="mTabstripWidth">0</field>
 
       <field name="mTabstrip">
         document.getAnonymousElementByAttribute(this, "anonid", "arrowscrollbox");
       </field>
 
@@ -2563,17 +2558,17 @@
               break;
           }
         ]]></body>
       </method>
 
       <field name="_animateElement">
         this.mTabstrip._scrollButtonDown;
       </field>
-      
+
       <method name="_notifyBackgroundTab">
         <parameter name="aTab"/>
         <body><![CDATA[
           if (aTab.pinned)
             return;
 
           var scrollRect = this.mTabstrip.scrollClientRect;
           var tab = aTab.getBoundingClientRect();
@@ -2786,17 +2781,17 @@
         dt.mozSetDataAt(TAB_DROP_TYPE, tab, 0);
         let uri = this.tabbrowser.getBrowserForTab(tab).currentURI;
         let spec = uri ? uri.spec : "about:blank";
 
         // We must not set text/x-moz-url or text/plain data here,
         // otherwise trying to deatch the tab by dropping it on the desktop
         // may result in an "internet shortcut"
         dt.mozSetDataAt("text/x-moz-text-internal", spec, 0);
-        
+
         // Set the cursor to an arrow during tab drags.
         dt.mozCursor = "default";
 
         let canvas = tabPreviews.capture(tab, false);
         dt.setDragImage(canvas, 0, 0);
         event.stopPropagation();
       ]]></handler>
 
@@ -3091,26 +3086,27 @@
   </binding>
 
   <binding id="tabbrowser-tab" display="xul:hbox"
            extends="chrome://global/content/bindings/tabbox.xml#tab">
     <resources>
       <stylesheet src="chrome://browser/content/tabbrowser.css"/>
     </resources>
 
-    <content closetabtext="&closeTab.label;">
+    <content context="tabContextMenu" closetabtext="&closeTab.label;">
       <xul:image xbl:inherits="validate,src=image"
                  class="tab-icon-image"
                  role="presentation"/>
       <xul:label flex="1"
                  xbl:inherits="value=label,crop,accesskey"
                  class="tab-text"
                  role="presentation"/>
       <xul:toolbarbutton anonid="close-button"
                          tabindex="-1"
+                         clickthrough="never"
                          class="tab-close-button"/>
     </content>
 
     <implementation>
       <property name="pinned" readonly="true">
         <getter>
           return this.getAttribute("pinned") == "true";
         </getter>
--- a/browser/base/content/test/Makefile.in
+++ b/browser/base/content/test/Makefile.in
@@ -140,16 +140,17 @@ endif
                  browser_ctrlTab.js \
                  browser_discovery.js \
                  browser_drag.js \
                  browser_gestureSupport.js \
                  browser_getshortcutoruri.js \
                  browser_inspector_initialization.js \
                  browser_inspector_treeSelection.js \
                  browser_inspector_highlighter.js \
+                 browser_inspector_stylePanel.js \
                  browser_overflowScroll.js \
                  browser_pageInfo.js \
                  browser_page_style_menu.js \
                  browser_pinnedTabs.js \
                  browser_plainTextLinks.js \
                  browser_pluginnotification.js \
                  browser_popupUI.js \
                  browser_relatedTabs.js \
--- a/browser/base/content/test/browser_inspector_initialization.js
+++ b/browser/base/content/test/browser_inspector_initialization.js
@@ -49,24 +49,24 @@ function startInspectorTests()
 function runInspectorTests(evt)
 {
   if (evt.target.id != "inspector-panel")
     return true;
   document.removeEventListener("popupshown", runInspectorTests, false);
   document.addEventListener("popuphidden", finishInspectorTests, false);
   ok(InspectorUI.inspecting, "Inspector is highlighting");
   ok(InspectorUI.isPanelOpen, "Inspector Tree Panel is open");
-  todo(InspectorUI.isStylePanelOpen, "Inspector Style Panel is open");
+  ok(InspectorUI.isStylePanelOpen, "Inspector Style Panel is open");
   todo(InspectorUI.isDOMPanelOpen, "Inspector DOM Panel is open");
   InspectorUI.toggleInspectorUI();
 }
 
 function finishInspectorTests(evt)
 {
-  if (evt.target.id != "inspector-panel")
+  if (evt.target.id != "inspector-style-panel")
     return true;
   document.removeEventListener("popuphidden", finishInspectorTests, false);
   ok(!InspectorUI.isDOMPanelOpen, "Inspector DOM Panel is closed");
   ok(!InspectorUI.isStylePanelOpen, "Inspector Style Panel is closed");
   ok(!InspectorUI.isPanelOpen, "Inspector Tree Panel is closed");
   ok(!InspectorUI.inspecting, "Inspector is not highlighting");
   gBrowser.removeCurrentTab();
   finish();
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/browser_inspector_stylePanel.js
@@ -0,0 +1,127 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=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 Inspector Style Panel Tests.
+ *
+ * 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):
+ *   Rob Campbell <rcampbell@mozilla.com> (original author)
+ *
+ * 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 ***** */
+
+let doc;
+let spans;
+let testGen;
+
+function createDocument()
+{
+  doc.body.innerHTML = '<div id="first" style="{ margin: 10em; ' +
+    'font-size: 14pt; font-family: helvetica, sans-serif; color: #AAA}">\n' +
+    '<h1>Some header text</h1>\n' +
+    '<p id="salutation" style="{font-size: 12pt}">hi.</p>\n' +
+    '<p id="body" style="{font-size: 12pt}">I am a test-case. This text exists ' +
+    'solely to provide some things to <span style="{color: yellow}">' +
+    'highlight</span> and <span style="{font-weight: bold}">count</span> ' +
+    'style list-items in the box at right. If you are reading this, ' +
+    'you should go do something else instead. Maybe read a book. Or better ' +
+    'yet, write some test-cases for another bit of code. ' +
+    '<span style="{font-style: italic}">Maybe more inspector test-cases!</span></p>\n' +
+    '<p id="closing">end transmission</p>\n' +
+    '</div>';
+  doc.title = "Inspector Style Test";
+  setupStyleTests();
+}
+
+function setupStyleTests()
+{
+  spans = doc.querySelectorAll("span");
+  ok(spans, "captain, we have the spans");
+  document.addEventListener("popupshown", runStyleTests, false);
+  InspectorUI.openInspectorUI();
+}
+
+function spanGenerator()
+{
+  for (var i = 0; i < spans.length; ++i) {
+    InspectorUI.inspectNode(spans[i]);
+    yield;
+  }
+}
+
+function runStyleTests(evt)
+{
+  if (evt.target.id != "inspector-style-panel")
+    return true;
+  document.removeEventListener("popupshown", runStyleTests, false);
+  document.addEventListener("popupshown", performTestComparisons, false);
+  InspectorUI.stopInspecting();
+  testGen = spanGenerator();
+  testGen.next();
+}
+
+function performTestComparisons(evt)
+{
+  if (evt.target.id != "highlighter-panel")
+    return true;
+
+  ok(InspectorUI.treeView.selectedNode, "selection");
+  ok(InspectorUI._showStylePanel, "_showStylePanel");
+  is(InspectorUI.isStylePanelOpen, InspectorUI._showStylePanel, "style panel matches _showStylePanel?");
+  ok(InspectorUI.highlighter.isHighlighting, "panel is highlighting");
+  ok(InspectorUI.styleBox.itemCount > 0, "styleBox has items");
+
+  try {
+    testGen.next();
+  } catch(StopIteration) {
+    document.removeEventListener("popupshown", performTestComparisons, false);
+    finishUp();
+  }
+}
+
+function finishUp() {
+  InspectorUI.closeInspectorUI();
+  gBrowser.removeCurrentTab();
+  finish();
+}
+
+function test()
+{
+  waitForExplicitFinish();
+  gBrowser.selectedTab = gBrowser.addTab();
+  gBrowser.selectedBrowser.addEventListener("load", function() {
+    gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true);
+    doc = content.document;
+    waitForFocus(createDocument, content);
+  }, true);
+  
+  content.location = "data:text/html,basic tests for inspector";
+}
+
--- a/browser/base/content/test/browser_overflowScroll.js
+++ b/browser/base/content/test/browser_overflowScroll.js
@@ -9,16 +9,21 @@ function left(ele)           rect(ele).l
 function right(ele)          rect(ele).right;
 function isLeft(ele, msg)    is(left(ele), left(scrollbox), msg);
 function isRight(ele, msg)   is(right(ele), right(scrollbox), msg);
 function elementFromPoint(x) tabstrip._elementFromPoint(x);
 function nextLeftElement()   elementFromPoint(left(scrollbox) - 1);
 function nextRightElement()  elementFromPoint(right(scrollbox) + 1);
 
 function test() {
+  if (TabsOnTop.enabled) {
+    todo(false, "need to figure out why this doesn't work with tabs on top on OS X and Windows 7 (bug 575748)");
+    return;
+  }
+
   waitForExplicitFinish();
 
   // If the previous (or more) test finished with cleaning up the tabs,
   // there may be some pending animations. That can cause a failure of
   // this tests, so, we should test this in another stack.
   setTimeout(doTest, 0);
 }
 
--- a/browser/base/content/test/test_contextmenu.html
+++ b/browser/base/content/test/test_contextmenu.html
@@ -220,17 +220,16 @@ function runTest(testNum) {
         // Context menu for an image
         checkContextMenu(["context-viewimage",            true,
                           "context-copyimage-contents",   true,
                           "context-copyimage",            true,
                           "---",                          null,
                           "context-saveimage",            true,
                           "context-sendimage",            true,
                           "context-setDesktopBackground", true,
-                          "context-blockimage",           true,
                           "context-viewimageinfo",        true]);
         closeContextMenu();
         openContextMenuFor(canvas); // Invoke context menu for next test.
         break;
 
     case 7:
         // Context menu for a canvas
         checkContextMenu(["context-viewimage",    true,
--- a/browser/base/content/urlbarBindings.xml
+++ b/browser/base/content/urlbarBindings.xml
@@ -135,25 +135,32 @@
       </method>
 
       <method name="handleCommand">
         <parameter name="aTriggeringEvent"/>
         <body><![CDATA[
           if (aTriggeringEvent instanceof MouseEvent && aTriggeringEvent.button == 2)
             return; // Do nothing for right clicks
 
-          var [url, postData] = this._canonizeURL(aTriggeringEvent);
-          if (!url)
-            return;
+          var url = this.value;
+          var postData = null;
 
           var action = this._parseActionUrl(url);
           if (action) {
-            if (action.type == "switchtab")
-              switchToTabHavingURI(action.param);
-            return;
+            url = action.param;
+            if (!(aTriggeringEvent && aTriggeringEvent.altKey)) {
+              if (action.type == "switchtab")
+                switchToTabHavingURI(url);
+              return;
+            }
+          }
+          else {
+            [url, postData] = this._canonizeURL(aTriggeringEvent);
+            if (!url)
+              return;
           }
 
           this.value = url;
           gBrowser.userTypedValue = url;
           try {
             addToUrlbarHistory(url);
           } catch (ex) {
             // Things may go wrong when adding url to session history,
--- a/browser/components/migration/src/nsDogbertProfileMigrator.cpp
+++ b/browser/components/migration/src/nsDogbertProfileMigrator.cpp
@@ -479,17 +479,19 @@ nsDogbertProfileMigrator::CopyPreference
 
 nsresult 
 nsDogbertProfileMigrator::GetHomepage(void* aTransform, nsIPrefBranch* aBranch)
 {
   PrefTransform* xform = (PrefTransform*)aTransform;
   PRInt32 val;
   nsresult rv = aBranch->GetIntPref(xform->sourcePrefName, &val);
   if (NS_SUCCEEDED(rv) && val == 0) {
-    xform->stringValue = "about:blank";
+    xform->stringValue = ToNewCString(NS_LITERAL_CSTRING("about:blank"));
+    if (!xform->stringValue)
+      rv = NS_ERROR_OUT_OF_MEMORY;
     xform->prefHasValue = PR_TRUE;
   }
   return rv;
 }
 
 nsresult 
 nsDogbertProfileMigrator::GetImagePref(void* aTransform, nsIPrefBranch* aBranch)
 {
--- a/browser/components/nsBrowserGlue.js
+++ b/browser/components/nsBrowserGlue.js
@@ -948,29 +948,30 @@ BrowserGlue.prototype = {
     var notifyBox = browser.getNotificationBox();
     var box = notifyBox.appendNotification(text, title, null,
                                            notifyBox.PRIORITY_CRITICAL_MEDIUM,
                                            buttons);
     box.persistence = -1; // Until user closes it
   },
 
   _migrateUI: function BG__migrateUI() {
-    var migration = 0;
+    const UI_VERSION = 2;
+    let currentUIVersion = 0;
     try {
-      migration = Services.prefs.getIntPref("browser.migration.version");
+      currentUIVersion = Services.prefs.getIntPref("browser.migration.version");
     } catch(ex) {}
+    if (currentUIVersion >= UI_VERSION)
+      return;
 
-    if (migration == 0) {
+    this._rdf = Cc["@mozilla.org/rdf/rdf-service;1"].getService(Ci.nsIRDFService);
+    this._dataSource = this._rdf.GetDataSource("rdf:local-store");
+    this._dirty = false;
+
+    if (currentUIVersion < 1) {
       // this code should always migrate pre-FF3 profiles to the current UI state
-
-      // grab the localstore.rdf and make changes needed for new UI
-      this._rdf = Cc["@mozilla.org/rdf/rdf-service;1"].getService(Ci.nsIRDFService);
-      this._dataSource = this._rdf.GetDataSource("rdf:local-store");
-      this._dirty = false;
-
       let currentsetResource = this._rdf.GetResource("currentset");
       let toolbars = ["nav-bar", "toolbar-menubar", "PersonalToolbar"];
       for (let i = 0; i < toolbars.length; i++) {
         let toolbar = this._rdf.GetResource("chrome://browser/content/browser.xul#" + toolbars[i]);
         let currentset = this._getPersist(toolbar, currentsetResource);
         if (!currentset) {
           // toolbar isn't customized
           if (i == 0)
@@ -984,28 +985,45 @@ BrowserGlue.prototype = {
         if (/(?:^|,)back-button(?:$|,)/.test(currentset)) {
           let newset = currentset.replace(/(^|,)back-button($|,)/,
                                           "$1unified-back-forward-button,back-button$2")
           this._setPersist(toolbar, currentsetResource, newset);
           // done migrating
           break;
         }
       }
-
-      // force the RDF to be saved
-      if (this._dirty)
-        this._dataSource.QueryInterface(Ci.nsIRDFRemoteDataSource).Flush();
+    }
 
-      // free up the RDF service
-      this._rdf = null;
-      this._dataSource = null;
+    if (currentUIVersion < 2) {
+      // This code adds the customizable bookmarks button.
+      let currentsetResource = this._rdf.GetResource("currentset");
+      let toolbarResource = this._rdf.GetResource("chrome://browser/content/browser.xul#nav-bar");
+      let currentset = this._getPersist(toolbarResource, currentsetResource);
+      // Need to migrate only if toolbar is customized and the element is not found.
+      if (currentset &&
+          currentset.indexOf("bookmarks-menu-button-container") == -1) {
+        if (currentset.indexOf("fullscreenflex") != -1) {
+          currentset = currentset.replace(/(^|,)fullscreenflex($|,)/,
+                                          "$1bookmarks-menu-button-container,fullscreenflex$2")
+        }
+        else {
+          currentset += ",bookmarks-menu-button-container";
+        }
+        this._setPersist(toolbarResource, currentsetResource, currentset);
+      }
+    }
 
-      // update the migration version
-      Services.prefs.setIntPref("browser.migration.version", 1);
-    }
+    if (this._dirty)
+      this._dataSource.QueryInterface(Ci.nsIRDFRemoteDataSource).Flush();
+
+    delete this._rdf;
+    delete this._dataSource;
+
+    // Update the migration version.
+    Services.prefs.setIntPref("browser.migration.version", UI_VERSION);
   },
 
   _getPersist: function BG__getPersist(aSource, aProperty) {
     var target = this._dataSource.GetTarget(aSource, aProperty, true);
     if (target instanceof Ci.nsIRDFLiteral)
       return target.Value;
     return null;
   },
--- a/browser/components/places/content/places.xul
+++ b/browser/components/places/content/places.xul
@@ -199,17 +199,18 @@
 
 #ifdef XP_MACOSX
         <toolbarbutton type="menu" class="tabbable"
               onpopupshowing="document.getElementById('placeContent').focus()"
 #else
       <menubar id="placesMenu">
         <menu accesskey="&organize.accesskey;" class="menu-iconic"
 #endif
-              id="organizeButton" label="&organize.label;">
+              id="organizeButton" label="&organize.label;"
+              tooltiptext="&organize.tooltip;">
           <menupopup id="organizeButtonPopup">
             <menuitem id="newbookmark"
                       command="placesCmd_new:bookmark"
                       label="&cmd.new_bookmark.label;"
                       accesskey="&cmd.new_bookmark.accesskey;"/>
             <menuitem id="newfolder"
                       command="placesCmd_new:folder"
                       label="&cmd.new_folder.label;"
@@ -282,17 +283,18 @@
           </menupopup>
 #ifdef XP_MACOSX
         </toolbarbutton>
         <toolbarbutton type="menu" class="tabbable"
 #else
         </menu>
         <menu accesskey="&views.accesskey;" class="menu-iconic"
 #endif
-              id="viewMenu" label="&views.label;">
+              id="viewMenu" label="&views.label;"
+              tooltiptext="&views.tooltip;">
           <menupopup id="viewMenuPopup">
 
             <menu id="viewColumns" 
                   label="&view.columns.label;" accesskey="&view.columns.accesskey;">
               <menupopup onpopupshowing="ViewMenu.fillWithColumns(event, null, null, 'checkbox', null);"
                          oncommand="ViewMenu.showHideColumn(event.target); event.stopPropagation();"/>
             </menu>
 
@@ -315,17 +317,18 @@
           </menupopup>
 #ifdef XP_MACOSX
         </toolbarbutton>
         <toolbarbutton type="menu" class="tabbable"
 #else
         </menu>
         <menu accesskey="&maintenance.accesskey;" class="menu-iconic"
 #endif
-              id="maintenanceButton" label="&maintenance.label;">
+              id="maintenanceButton" label="&maintenance.label;"
+              tooltiptext="&maintenance.tooltip;">
           <menupopup id="maintenanceButtonPopup">
             <menuitem id="backupBookmarks"
                       command="OrganizerCommand_backup"
                       label="&cmd.backup.label;"
                       accesskey="&cmd.backup.accesskey;"/>
             <menu id="fileRestoreMenu" label="&cmd.restore2.label;"
                       accesskey="&cmd.restore2.accesskey;">
               <menupopup id="fileRestorePopup" onpopupshowing="PlacesOrganizer.populateRestoreMenu();">
--- a/browser/components/places/tests/browser/browser_drag_bookmarks_on_toolbar.js
+++ b/browser/components/places/tests/browser/browser_drag_bookmarks_on_toolbar.js
@@ -242,25 +242,25 @@ function nextTest() {
     info("Start of test: " + test.desc);
     test.run();
 
     setTimeout(nextTest, 0);
   }
   else {
     // Collapse the personal toolbar if needed.
     if (wasCollapsed)
-      toolbar.collapsed = true;
+      setToolbarVisibility(toolbar, false);
     finish();
   }
 }
 
 let toolbar = document.getElementById("PersonalToolbar");
 let wasCollapsed = toolbar.collapsed;
 
 function test() {
   // Uncollapse the personal toolbar if needed.
   if (wasCollapsed)
-    toolbar.collapsed = false;
+    setToolbarVisibility(toolbar, true);
 
   waitForExplicitFinish();
   nextTest();
 }
 
--- a/browser/components/places/tests/browser/browser_history_sidebar_search.js
+++ b/browser/components/places/tests/browser/browser_history_sidebar_search.js
@@ -47,16 +47,30 @@ var hs = Cc["@mozilla.org/browser/nav-hi
          getService(Ci.nsINavHistoryService);
 var bh = hs.QueryInterface(Ci.nsIBrowserHistory);
 var ios = Cc["@mozilla.org/network/io-service;1"].
           getService(Ci.nsIIOService);
 function uri(spec) {
   return ios.newURI(spec, null, null);
 }
 
+/**
+ * Clears history invoking callback when done.
+ */
+function waitForClearHistory(aCallback) {
+  let observer = {
+    observe: function(aSubject, aTopic, aData) {
+      Services.obs.removeObserver(this, PlacesUtils.TOPIC_EXPIRATION_FINISHED);
+      aCallback(aSubject, aTopic, aData);
+    }
+  };
+  Services.obs.addObserver(observer, PlacesUtils.TOPIC_EXPIRATION_FINISHED, false);
+  PlacesUtils.bhistory.removeAllPages();
+}
+
 var sidebar = document.getElementById("sidebar");
 
 function add_visit(aURI, aDate) {
   var visitId = hs.addVisit(aURI,
                             aDate,
                             null, // no referrer
                             hs.TRANSITION_TYPED, // user typed in URL bar
                             false, // not redirect
@@ -73,18 +87,20 @@ var pages = [
 ];
 // Number of pages that will be filtered out by the search.
 const FILTERED_COUNT = 1;
 
 function test() {
   waitForExplicitFinish();
 
   // Cleanup.
-  bh.removeAllPages();
+  waitForClearHistory(continue_test);
+}
 
+function continue_test() {
   // Add some visited page.
   var time = Date.now();
   for (var i = 0; i < pages.length; i++) {
     add_visit(uri(pages[i]), (time - i) * 1000);
   }
 
   sidebar.addEventListener("load", function() {
     sidebar.removeEventListener("load", arguments.callee, true);
@@ -98,19 +114,17 @@ function test() {
       searchBox.doCommand();
       check_sidebar_tree_order(pages.length - FILTERED_COUNT);
       searchBox.value = "";
       searchBox.doCommand();
       check_sidebar_tree_order(pages.length);
 
       // Cleanup.
       toggleSidebar("viewHistorySidebar", false);
-      bh.removeAllPages();
-
-      finish();
+      waitForClearHistory(finish);
     });
   }, true);
   toggleSidebar("viewHistorySidebar", true);
 }
 
 function check_sidebar_tree_order(aExpectedRows) {
   var tree = sidebar.contentDocument.getElementById("historyTree");
   var treeView = tree.view;
--- a/browser/components/places/tests/browser/browser_views_liveupdate.js
+++ b/browser/components/places/tests/browser/browser_views_liveupdate.js
@@ -43,17 +43,17 @@ const Cc = Components.classes;
 const Ci = Components.interfaces;
 
 let toolbar = document.getElementById("PersonalToolbar");
 let wasCollapsed = toolbar.collapsed;
 
 function test() {
   // Uncollapse the personal toolbar if needed.
   if (wasCollapsed)
-    toolbar.collapsed = false;
+    setToolbarVisibility(toolbar, true);
 
   waitForExplicitFinish();
 
   // Sanity checks.
   ok(PlacesUtils, "PlacesUtils in context");
   ok(PlacesUIUtils, "PlacesUIUtils in context");
 
   // Open bookmarks menu.
@@ -199,17 +199,17 @@ function startTest() {
  * Restores browser state and calls finish.
  */
 function finishTest() {
   // Close bookmarks sidebar.
   toggleSidebar("viewBookmarksSidebar", false);
 
   // Collapse the personal toolbar if needed.
   if (wasCollapsed)
-    toolbar.collapsed = true;
+    setToolbarVisibility(toolbar, false);
 
   finish();
 }
 
 /**
  * The observer is where magic happens, for every change we do it will look for
  * nodes positions in the affected views.
  */
--- a/browser/components/privatebrowsing/test/browser/Makefile.in
+++ b/browser/components/privatebrowsing/test/browser/Makefile.in
@@ -44,17 +44,16 @@ relativesrcdir  = browser/components/pri
 include $(DEPTH)/config/autoconf.mk
 include $(topsrcdir)/config/rules.mk
 
 _BROWSER_TEST_FILES =  \
 		browser_console_clear.js \
 		browser_privatebrowsing_beforeunload.js \
 		browser_privatebrowsing_certexceptionsui.js \
 		browser_privatebrowsing_commandline_toggle.js \
-		browser_privatebrowsing_contextmenu_blockimage.js \
 		browser_privatebrowsing_cookieacceptdialog.js \
 		browser_privatebrowsing_crh.js \
 		browser_privatebrowsing_downloadmonitor.js \
 		browser_privatebrowsing_fastswitch.js \
 		browser_privatebrowsing_findbar.js \
 		browser_privatebrowsing_forgetthissite.js \
 		browser_privatebrowsing_geoprompt.js \
 		browser_privatebrowsing_geoprompt_page.html \
deleted file mode 100644
--- a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_contextmenu_blockimage.js
+++ /dev/null
@@ -1,89 +0,0 @@
-/* ***** 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 Private Browsing Tests.
- *
- * The Initial Developer of the Original Code is
- * Ehsan Akhgari.
- * Portions created by the Initial Developer are Copyright (C) 2009
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Ehsan Akhgari <ehsan.akhgari@gmail.com> (Original Author)
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either of 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 ***** */
-
-// This test makes sure that private browsing mode disables the Block Image
-// context menu item.
-
-function test() {
-  // initialization
-  let pb = Cc["@mozilla.org/privatebrowsing;1"].
-           getService(Ci.nsIPrivateBrowsingService);
-
-  const TEST_URI = "http://mochi.test:8888/browser/browser/components/privatebrowsing/test/browser/ctxmenu.html";
-
-  waitForExplicitFinish();
-
-  function checkBlockImageMenuItem(expectedHidden, callback) {
-    let tab = gBrowser.addTab();
-    gBrowser.selectedTab = tab;
-    let browser = gBrowser.getBrowserForTab(tab);
-    browser.addEventListener("load", function() {
-      browser.removeEventListener("load", arguments.callee, true);
-
-      executeSoon(function() {
-        let contextMenu = document.getElementById("contentAreaContextMenu");
-        let blockImage = document.getElementById("context-blockimage");
-        let image = browser.contentDocument.getElementsByTagName("img")[0];
-        ok(image, "The content image should be accessible");
-
-        contextMenu.addEventListener("popupshown", function() {
-          contextMenu.removeEventListener("popupshown", arguments.callee, false);
-
-          is(blockImage.hidden, expectedHidden,
-             "The Block Image menu item should " + (expectedHidden ? "" : "not ") + "be hidden");
-          contextMenu.hidePopup();
-          gBrowser.removeTab(tab);
-          callback();
-        }, false);
-
-        document.popupNode = image;
-        EventUtils.synthesizeMouse(image, 2, 2,
-                                   {type: "contextmenu", button: 2},
-                                   browser.contentWindow);
-      });
-    }, true);
-    browser.loadURI(TEST_URI);
-  }
-
-  checkBlockImageMenuItem(false, function() {
-    pb.privateBrowsingEnabled = true;
-    checkBlockImageMenuItem(true, function() {
-      pb.privateBrowsingEnabled = false;
-      checkBlockImageMenuItem(false, finish);
-    });
-  });
-}
--- a/browser/components/sessionstore/src/nsSessionStore.js
+++ b/browser/components/sessionstore/src/nsSessionStore.js
@@ -1205,16 +1205,19 @@ SessionStoreService.prototype = {
     // in the URL bar, or a new tab was opened with a URI to load. userTypedClear
     // is used to indicate whether the tab was in some sort of loading state with
     // userTypedValue.
     if (browser.userTypedValue) {
       tabData.userTypedValue = browser.userTypedValue;
       tabData.userTypedClear = browser.userTypedClear;
     }
 
+    if (aTab.pinned)
+      tabData.pinned = true;
+
     var disallow = [];
     for (var i = 0; i < CAPABILITIES.length; i++)
       if (!browser.docShell["allow" + CAPABILITIES[i]])
         disallow.push(CAPABILITIES[i]);
     if (disallow.length > 0)
       tabData.disallow = disallow.join(",");
     else if (tabData.disallow)
       delete tabData.disallow;
@@ -1934,16 +1937,21 @@ SessionStoreService.prototype = {
     for (var t = 0; t < newTabCount; t++) {
       tabs.push(t < openTabCount ?
                 tabbrowser.tabs[t] :
                 tabbrowser.addTab("about:blank", {skipAnimation: true}));
       // when resuming at startup: add additionally requested pages to the end
       if (!aOverwriteTabs && root._firstTabs) {
         tabbrowser.moveTabTo(tabs[t], t);
       }
+
+      if (winData.tabs[t].pinned)
+        tabbrowser.pinTab(tabs[t]);
+      else
+        tabbrowser.unpinTab(tabs[t]);
     }
 
     // when overwriting tabs, remove all superflous ones
     if (aOverwriteTabs && newTabCount < openTabCount) {
       Array.slice(tabbrowser.tabs, newTabCount, openTabCount)
            .forEach(tabbrowser.removeTab, tabbrowser);
     }
     
@@ -2010,48 +2018,54 @@ SessionStoreService.prototype = {
           aWindow.setTimeout(restoreHistoryFunc, 100, this);
           return;
         }
       }
     }
     
     // mark the tabs as loading
     for (t = 0; t < aTabs.length; t++) {
-      var tab = aTabs[t];
-      var browser = tabbrowser.getBrowserForTab(tab);
-      
-      aTabData[t]._tabStillLoading = true;
-      if (!aTabData[t].entries || aTabData[t].entries.length == 0) {
+      let tab = aTabs[t];
+      let browser = tabbrowser.getBrowserForTab(tab);
+      let tabData = aTabData[t];
+
+      if (tabData.pinned)
+        tabbrowser.pinTab(tab);
+      else
+        tabbrowser.unpinTab(tab);
+
+      tabData._tabStillLoading = true;
+      if (!tabData.entries || tabData.entries.length == 0) {
         // make sure to blank out this tab's content
         // (just purging the tab's history won't be enough)
         browser.contentDocument.location = "about:blank";
         continue;
       }
       
       browser.stop(); // in case about:blank isn't done yet
       
       tab.setAttribute("busy", "true");
       tabbrowser.updateIcon(tab);
       tabbrowser.setTabTitleLoading(tab);
       
       // wall-paper fix for bug 439675: make sure that the URL to be loaded
       // is always visible in the address bar
-      let activeIndex = (aTabData[t].index || aTabData[t].entries.length) - 1;
-      let activePageData = aTabData[t].entries[activeIndex] || null;
+      let activeIndex = (tabData.index || tabData.entries.length) - 1;
+      let activePageData = tabData.entries[activeIndex] || null;
       browser.userTypedValue = activePageData ? activePageData.url || null : null;
       
       // keep the data around to prevent dataloss in case
       // a tab gets closed before it's been properly restored
-      browser.__SS_data = aTabData[t];
+      browser.__SS_data = tabData;
     }
     
     if (aTabs.length > 0) {
       // Determine if we can optimize & load visible tabs first
       let maxVisibleTabs = Math.ceil(tabbrowser.tabContainer.mTabstrip.scrollClientSize /
-                                     aTabs[0].clientWidth);
+                                     aTabs[aTabs.length - 1].clientWidth);
 
       // make sure we restore visible tabs first, if there are enough
       if (maxVisibleTabs < aTabs.length && aSelectTab > 1) {
         let firstVisibleTab = 0;
         if (aTabs.length - maxVisibleTabs > aSelectTab) {
           // aSelectTab is leftmost since we scroll to it when possible
           firstVisibleTab = aSelectTab - 1;
         } else {
--- a/browser/installer/package-manifest.in
+++ b/browser/installer/package-manifest.in
@@ -41,20 +41,23 @@
 @BINPATH@/@DLL_PREFIX@mozjs@DLL_SUFFIX@
 @BINPATH@/@DLL_PREFIX@plc4@DLL_SUFFIX@
 @BINPATH@/@DLL_PREFIX@plds4@DLL_SUFFIX@
 @BINPATH@/@DLL_PREFIX@xpcom@DLL_SUFFIX@
 @BINPATH@/@DLL_PREFIX@nspr4@DLL_SUFFIX@
 @BINPATH@/@DLL_PREFIX@mozalloc@DLL_SUFFIX@
 #ifdef XP_MACOSX
 @BINPATH@/XUL
-@BINPATH@/@MOZ_CHILD_PROCESS_NAME@
 #else
 @BINPATH@/@DLL_PREFIX@xul@DLL_SUFFIX@
+#endif
 #ifdef MOZ_IPC
+#ifdef XP_MACOSX
+@BINPATH@/@MOZ_CHILD_PROCESS_NAME@.app/
+#else
 @BINPATH@/@MOZ_CHILD_PROCESS_NAME@
 #endif
 #endif
 #ifdef WINCE
 @BINPATH@/mozce_shunt.dll
 #elifdef XP_WIN32
 #ifndef MOZ_MEMORY
 #if _MSC_VER == 1400
--- a/browser/locales/en-US/chrome/browser/browser.dtd
+++ b/browser/locales/en-US/chrome/browser/browser.dtd
@@ -172,16 +172,26 @@
 <!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 inspectButton.label          "Inspect">
+<!ENTITY inspectButton.accesskey      "I">
+<!ENTITY inspectNextButton.label      "Next">
+<!ENTITY inspectNextButton.accesskey  "N">
+<!ENTITY inspectPreviousButton.label  "Previous">
+<!ENTITY inspectPreviousButton.accesskey "P">
+<!ENTITY inspectStyleButton.label     "Style">
+<!ENTITY inspectStyleButton.accesskey "S">
+<!ENTITY inspectStylePanelTitle.label  "Style">
+
 <!ENTITY fileMenu.label         "File"> 
 <!ENTITY fileMenu.accesskey       "F">
 <!ENTITY newNavigatorCmd.label        "New Window">
 <!ENTITY newNavigatorCmd.key        "N">
 <!ENTITY newNavigatorCmd.accesskey      "N">
 
 <!ENTITY editMenu.label         "Edit"> 
 <!ENTITY editMenu.accesskey       "E"> 
@@ -252,32 +262,32 @@
 <!ENTITY urlbar.placeholder           "Go to a Web Site">
 <!ENTITY urlbar.accesskey             "d">
 <!ENTITY urlbar.switchToTab.label     "Switch to tab:">
 
 <!-- 
   Comment duplicated from browser-sets.inc:
 
   Search Command Key Logic works like this:
-  
+
   Unix: Ctrl+J (0.8, 0.9 support)
         Ctrl+K (cross platform binding)
   Mac:  Ctrl+K (cross platform binding)
   Win:  Ctrl+K (cross platform binding)
         Ctrl+E (IE compat) 
 
   We support Ctrl+K on all platforms now and advertise it in the menu since it is
   our standard - it is a "safe" choice since it is near no harmful keys like "W" as
   "E" is. People mourning the loss of Ctrl+K for emacs compat can switch their GTK
   system setting to use emacs emulation, and we should respect it. Focus-Search-Box
   is a fundamental keybinding and we are maintaining a XP binding so that it is easy
   for people to switch to Linux.
 
   Do *not* tamper with these values without talking to ben@mozilla.org
-  
+
  -->
 <!ENTITY searchFocus.commandkey       "k">
 <!ENTITY searchFocus.commandkey2      "e">
 <!ENTITY searchFocusUnix.commandkey   "j">
 
 <!ENTITY openLinkCmd.label            "Open Link in New Window">
 <!ENTITY openLinkCmd.accesskey        "W">
 <!ENTITY openLinkCmdInCurrent.label     "Open Link">
@@ -356,17 +366,16 @@
 <!ENTITY copyImageCmd.label           "Copy Image Location">
 <!ENTITY copyImageCmd.accesskey       "o">
 <!ENTITY copyImageContentsCmd.label   "Copy Image">
 <!ENTITY copyImageContentsCmd.accesskey  "y"> 
 <!ENTITY copyVideoURLCmd.label        "Copy Video Location">
 <!ENTITY copyVideoURLCmd.accesskey    "o">
 <!ENTITY copyAudioURLCmd.label        "Copy Audio Location">
 <!ENTITY copyAudioURLCmd.accesskey    "o">
-<!ENTITY blockImageCmd.accesskey      "B">
 <!ENTITY copyEmailCmd.label           "Copy Email Address">
 <!ENTITY copyEmailCmd.accesskey       "E">
 <!ENTITY thisFrameMenu.label              "This Frame">
 <!ENTITY thisFrameMenu.accesskey          "h">
 
 <!-- Media (video/audio) controls -->
 <!ENTITY mediaPlay.label             "Play">
 <!ENTITY mediaPlay.accesskey         "P">
--- a/browser/locales/en-US/chrome/browser/browser.properties
+++ b/browser/locales/en-US/chrome/browser/browser.properties
@@ -13,18 +13,16 @@ droponhomemsg=Do you want this document 
 
 # context menu strings
 
 # LOCALIZATION NOTE (contextMenuSearchText): %1$S is the search engine,
 # %2$S is the selection string.
 contextMenuSearchText=Search %1$S for "%2$S"
 contextMenuSearchText.accesskey=S
 
-blockImages=Block Images from %S
-
 # bookmark dialog strings
 
 bookmarkAllTabsDefault=[Folder Name]
 
 xpinstallPromptWarning=%S prevented this site (%S) from asking you to install software on your computer.
 xpinstallPromptAllowButton=Allow
 # Accessibility Note:
 # Be sure you do not choose an accesskey that is used elsewhere in the active context (e.g. main menu bar, submenu of the warning popup button)
@@ -75,21 +73,16 @@ popupWarningButton.accesskey=O
 popupWarningButtonUnix=Preferences
 popupWarningButtonUnix.accesskey=P
 popupAllow=Allow pop-ups for %S
 popupBlock=Block pop-ups for %S
 popupWarningDontShowFromMessage=Don't show this message when pop-ups are blocked
 popupWarningDontShowFromStatusbar=Don't show info message when pop-ups are blocked
 popupShowPopupPrefix=Show '%S'
 
-imageBlockedWarning=%S will now always block images from %S.
-imageAllowedWarning=%S will now allow images from %S.
-undo=Undo
-undo.accessKey=U
-
 # missing plugin installer
 missingpluginsMessage.title=Additional plugins are required to display all the media on this page.
 missingpluginsMessage.button.label=Install Missing Plugins…
 missingpluginsMessage.button.accesskey=I
 outdatedpluginsMessage.title=Some plugins used by this page are out of date.
 outdatedpluginsMessage.updateButton.label=Update Plugins…
 outdatedpluginsMessage.updateButton.accesskey=U
 blockedpluginsMessage.title=Some plugins required by this page have been blocked for your protection.
new file mode 100644
--- /dev/null
+++ b/browser/locales/en-US/chrome/browser/inspector.properties
@@ -0,0 +1,11 @@
+# LOCALIZATION NOTE  (style.selectorLabel): Used in the Inspector style panel
+#  to label a CSS Selector.
+style.selectorLabel=Selector
+
+# LOCALIZATION NOTE  (style.inheritedFrom): used in Style panel in
+#  inspector. Describes which tagname[#id] the properties are inherited from.
+style.inheritedFrom=Inherited from: #1
+
+# LOCALIZATION NOTE (style.styleItemLabel: used in Style panel in inspector.
+#  Used for construction of list items, #1 = label, #2 = content.
+style.styleItemLabel=#1: #2
--- a/browser/locales/en-US/chrome/browser/places/places.dtd
+++ b/browser/locales/en-US/chrome/browser/places/places.dtd
@@ -1,23 +1,25 @@
 <!-- LOCALIZATION NOTE (places.library.title): use "Library", "Archive" or "Repository" -->
 <!ENTITY places.library.title  "Library">
 <!ENTITY places.library.width  "700">
 <!ENTITY places.library.height "500">
 <!ENTITY organize.label        "Organize">
 <!ENTITY organize.accesskey    "O">
+<!ENTITY organize.tooltip      "Organize your bookmarks">
 
 <!ENTITY file.accesskey                 "F">
 <!ENTITY file.close.label               "Close">
 <!ENTITY file.close.accesskey           "C">
 <!ENTITY cmd.close.key                  "w">
 <!ENTITY edit.label                     "Edit">
 <!ENTITY edit.accesskey                 "E">
 <!ENTITY views.label                    "Views">
 <!ENTITY views.accesskey                "V">
+<!ENTITY views.tooltip                  "Change your view">
 <!ENTITY view.columns.label             "Show Columns">
 <!ENTITY view.columns.accesskey         "C">
 <!ENTITY view.sort.label                "Sort">
 <!ENTITY view.sort.accesskey            "S">
 <!ENTITY view.unsorted.label            "Unsorted">
 <!ENTITY view.unsorted.accesskey        "U">
 <!ENTITY view.sortAscending.label       "A > Z Sort Order">
 <!ENTITY view.sortAscending.accesskey   "A">
@@ -102,16 +104,17 @@
 <!ENTITY search.scopeHistory.accesskey             "H">
 <!ENTITY saveSearch.label                          "Save">
 <!ENTITY saveSearch.accesskey                      "S">
 
 <!ENTITY cmd.find.key  "f">
 
 <!ENTITY maintenance.label      "Import and Backup">
 <!ENTITY maintenance.accesskey  "I">
+<!ENTITY maintenance.tooltip    "Import and backup your bookmarks">
 
 <!ENTITY backCmd.label       "Back">
 <!ENTITY backButton.tooltip  "Go back">
 
 <!ENTITY forwardCmd.label       "Forward">
 <!ENTITY forwardButton.tooltip  "Go forward">
 
 <!ENTITY detailsPane.more.label "More">
--- a/browser/locales/en-US/feedback/main.dtd
+++ b/browser/locales/en-US/feedback/main.dtd
@@ -10,21 +10,21 @@
 <!ENTITY testpilot.about.label                      "About Test Pilot">
 
 <!-- all studies window -->
 <!ENTITY testpilot.studiesWindow.title                  "Your Test Pilot Studies">
 <!ENTITY testpilot.studiesWindow.currentStudies.label   "Current Studies">
 <!ENTITY testpilot.studiesWindow.finishedStudies.label  "Finished Studies">
 <!ENTITY testpilot.studiesWindow.studyFindings.label    "Study Findings">
 <!ENTITY testpilot.studiesWindow.settings.label         "Settings">
-<!ENTITY testpilot.studiesWindow.stillLoadingMessage    "Loading, please wait...">
+<!ENTITY testpilot.studiesWindow.stillLoadingMessage    "Loading, please wait…">
 
 <!-- raw data dialog -->
 <!ENTITY testpilot.rawDataWindow.title                  "Test Pilot: Raw Data">
 
 <!-- notification -->
 <!ENTITY testpilot.notification.close.tooltip            "Close">
 
 <!-- Firefox 4 beta version UI -->
 <!ENTITY testpilot.enable.label                        "Turn On User Studies">
 <!ENTITY testpilot.feedbackbutton.label                "Feedback">
-<!ENTITY testpilot.happy.label        "Firefox Made Me Happy Because...">
-<!ENTITY testpilot.sad.label          "Firefox Made Me Sad Because...">
+<!ENTITY testpilot.happy.label        "Firefox Made Me Happy Because…">
+<!ENTITY testpilot.sad.label          "Firefox Made Me Sad Because…">
--- a/browser/locales/en-US/feedback/main.properties
+++ b/browser/locales/en-US/feedback/main.properties
@@ -5,88 +5,90 @@ testpilot.submit = Submit
 testpilot.takeSurvey = Take the Survey
 
 # Feedback button menu
 testpilot.turnOn = Turn On User Studies
 testpilot.turnOff = Turn Off User Studies
 
 # studies window
 testpilot.studiesWindow.noStudies = We are working on a new study now; it will knock on your door soon! Stay Tuned!
-testpilot.studiesWindow.uploading = Uploading...
+testpilot.studiesWindow.uploading = Uploading…
 testpilot.studiesWindow.unableToReachServer = Unable to reach Mozilla; please try again later.
 testpilot.studiesWindow.thanksForContributing = Thanks for contributing!
 testpilot.studiesWindow.finishedOn = Finished on %S
 testpilot.studiesWindow.canceledStudy = (You canceled this study)
 testpilot.studiesWindow.willStart = Will start on %S
 testpilot.studiesWindow.gatheringData = Currently gathering data.
 testpilot.studiesWindow.willFinish = Will finish on %S
 testpilot.studiesWindow.proposeStudy = Propose your own study
 
 # for pages
-testpilot.page.commentsAndDiscussions = Comments & Discussions &raquo;
-testpilot.page.proposeATest = Propose a Test &raquo;
-testpilot.page.testpilotOnTwitter = @MozTestPilot on Twitter &raquo;
+testpilot.page.commentsAndDiscussions = Comments & Discussions »
+testpilot.page.proposeATest = Propose a Test »
+testpilot.page.testpilotOnTwitter = @MozTestPilot on Twitter »
 
 # status page
-testpilot.statusPage.uploadingData = Now uploading data...
-testpilot.statusPage.uploadError =
-  Oops! There was an error connecting to the Mozilla servers.  Maybe your network connection is down?</p><p>Test Pilot will retry automatically, so it's OK to close this page now.
+testpilot.statusPage.uploadingData = Now uploading data…
+testpilot.statusPage.uploadErrorMsg = Oops! There was an error connecting to the Mozilla servers.  Maybe your network connection is down?
+testpilot.statusPage.willRetry = Test Pilot will retry automatically, so it's OK to close this page now.
 testpilot.statusPage.endedAlready = (It has already ended and you should not be seeing this page)
 testpilot.statusPage.todayAt =  today, at %S
 testpilot.statusPage.endOn = on %S
-testpilot.statusPage.extension = 1 extension
-testpilot.statusPage.extensions = %S extension
+# LOCALIZATION NOTE (numExtensions): Semi-colon list of plural forms.
+# See: http://developer.mozilla.org/en/docs/Localization_and_Plurals
+# #1 = number of extensions
+# example: "2 extensions"
+testpilot.statusPage.numExtensions = #1 extension;#1 extensions
 testpilot.statusPage.recursEveryNumberOfDays = This test recurs every %S days. Each time it completes:
 testpilot.statusPage.askMeBeforeSubmitData = Ask me whether I want to submit my data.
 testpilot.statusPage.alwaysSubmitData = Always submit my data, and don't ask me about it.
 testpilot.statusPage.neverSubmitData = Never submit my data, and don't ask me about it.
-testpilot.statusPage.loading = Loading, please wait a moment...
+testpilot.statusPage.loading = Loading, please wait a moment…
 
 # quit page
 testpilot.quitPage.aboutToQuit = You are about to quit the "%S" study.
 testpilot.quitPage.optionalMessage = (Optional) If you have a minute, please let us know why you have chosen to quit the study.
 testpilot.quitPage.reason = Reason:
 testpilot.quitPage.recurringStudy = This is a recurring study. Normally we will let you know the next time we run the study.  If you never want to hear about this study again, check the box below:
-testpilot.quitPage.quitFoever = Quit this recurring study.
-testpilot.quitPage.quitStudy = Quit the Study &raquo;
+testpilot.quitPage.quitForever = Quit this recurring study.
+testpilot.quitPage.quitStudy = Quit the Study »
 
 # welcome page
 testpilot.welcomePage.thankYou = Thank You for Joining the Test Pilot Team!
 testpilot.welcomePage.gettingStarted = Getting Started
 testpilot.welcomePage.pleaseTake = Please take the
 testpilot.welcomePage.backgroundSurvey = Pilot Background Survey
 testpilot.welcomePage.clickToOpenStudiesWindow = Click here to see the studies that are currently running.
 testpilot.welcomePage.testpilotAddon = Test Pilot Add-on
-testpilot.welcomePage.iconExplanation = &laquo; look for this icon in the bottom right of the browser window.
+testpilot.welcomePage.iconExplanation = « look for this icon in the bottom right of the browser window.
 testpilot.welcomePage.moreIconExplanation = You can click on it to get the main Test Pilot menu.
 testpilot.welcomePage.notificationInfo = The icon will pop up a notification when a study needs your attention.
-testpilot.welcomePage.copyright = Copyright &copy; 2005-2009 Mozilla. All rights reserved.
 testpilot.welcomePage.privacyPolicy = Privacy Policy
 testpilot.welcomePage.legalNotices = Legal Notices
 
 # survey page
 testpilot.surveyPage.saveAnswers = Save Answers
 testpilot.surveyPage.submitAnswers = Submit Answers
 testpilot.surveyPage.changeAnswers = Change Answers
-testpilot.surveyPage.loading = Loading, please wait a moment...
+testpilot.surveyPage.loading = Loading, please wait a moment…
 testpilot.surveyPage.thankYouForFinishingSurvey = Thank you for finishing this survey. Your answers will be uploaded along with the next set of experimental data.
 testpilot.surveyPage.reviewOrChangeYourAnswers = If you would like to review or change your answers, you can do so at any time using the button below.
 
 # modules/task.js
-testpilot.finishedTask.finishedStudy = Excellent! You finished the %S Study!
+testpilot.finishedTask.finishedStudy = Excellent! You finished the "%S" Study!
 testpilot.finishedTask.allRelatedDataDeleted = All data related to this study has been removed from your computer.
 
 # modules/setup.js
-testpilot.notification.update = Update...
+testpilot.notification.update = Update…
 testpilot.notification.thankYouForUploadingData = Thanks!
 testpilot.notification.thankYouForUploadingData.message = Thank you for uploading your data.
 testpilot.notification.readyToSubmit = Ready to Submit
 testpilot.notification.readyToSubmit.message = The Test Pilot "%S" study is finished gathering data and is ready to submit.
 testpilot.notification.newTestPilotStudy = New Test Pilot Study
-testpilot.notification.newTestPilotStudy.message = The Test Pilot "%S" study is now beginning.
+testpilot.notification.newTestPilotStudy.pre.message = The Test Pilot "%S" study is about to begin.
 testpilot.notification.newTestPilotSurvey = New Test Pilot Survey
 testpilot.notification.newTestPilotSurvey.message = The Test Pilot "%S" survey is available.
 testpilot.notification.newTestPilotResults = New Test Pilot Results
 testpilot.notification.newTestPilotResults.message = New results are now available for the Test Pilot "%S" study.
 testpilot.notification.autoUploadedData = Thank you!
 testpilot.notification.autoUploadedData.message = The Test Pilot "%S" study is completed and your data has been submitted!
 testpilot.notification.extensionUpdate = Extension Update
 testpilot.notification.extensionUpdate.message = One of your studies requires a newer version of Test Pilot. You can get the latest version using the Add-ons window.
--- a/browser/locales/jar.mn
+++ b/browser/locales/jar.mn
@@ -6,16 +6,17 @@
     locale/browser/aboutDialog.dtd                 (%chrome/browser/aboutDialog.dtd)
     locale/browser/aboutPrivateBrowsing.dtd        (%chrome/browser/aboutPrivateBrowsing.dtd)
     locale/browser/aboutRobots.dtd                 (%chrome/browser/aboutRobots.dtd)
     locale/browser/aboutSessionRestore.dtd         (%chrome/browser/aboutSessionRestore.dtd)
     locale/browser/credits.dtd                     (%chrome/browser/credits.dtd)
 *   locale/browser/browser.dtd                     (%chrome/browser/browser.dtd)
     locale/browser/baseMenuOverlay.dtd             (%chrome/browser/baseMenuOverlay.dtd)
     locale/browser/browser.properties              (%chrome/browser/browser.properties)
+    locale/browser/inspector.properties            (%chrome/browser/inspector.properties)
     locale/browser/openLocation.dtd                (%chrome/browser/openLocation.dtd)
     locale/browser/openLocation.properties         (%chrome/browser/openLocation.properties)
 *   locale/browser/pageInfo.dtd                    (%chrome/browser/pageInfo.dtd)
     locale/browser/pageInfo.properties             (%chrome/browser/pageInfo.properties)
     locale/browser/pageReportFirstTime.dtd         (%chrome/browser/pageReportFirstTime.dtd)
     locale/browser/quitDialog.properties           (%chrome/browser/quitDialog.properties)
 *   locale/browser/safeMode.dtd                    (%chrome/browser/safeMode.dtd)
     locale/browser/sanitize.dtd                    (%chrome/browser/sanitize.dtd)
--- a/browser/locales/shipped-locales
+++ b/browser/locales/shipped-locales
@@ -1,1 +1,24 @@
+be
+cs
+de
+el
 en-US
+es-AR
+es-ES
+et
+fr
+ga-IE
+is
+it
+nb-NO
+nl
+nn-NO
+pl
+pt-BR
+pt-PT
+ru
+sk
+sv-SE
+uk
+zh-CN
+zh-TW
--- a/browser/themes/gnomestripe/browser/browser.css
+++ b/browser/themes/gnomestripe/browser/browser.css
@@ -1183,17 +1183,18 @@ statusbarpanel#statusbar-display {
 #TabsToolbar {
   -moz-appearance: none;
   min-height: 0;
   padding: 0;
   -moz-box-shadow: ThreeDShadow 0 -1px inset;
 }
 
 #TabsToolbar > toolbarbutton,
-#TabsToolbar > toolbarpaletteitem > toolbarbutton {
+#TabsToolbar > toolbarpaletteitem > toolbarbutton,
+#TabsToolbar > #bookmarks-menu-button-container > #bookmarks-menu-button {
   margin-bottom: 1px;
 }
 
 .tabbrowser-tab {
   padding: 0 2px 2px;
   margin-bottom: 1px;
   min-height: 25px; /* reserve space for the sometimes hidden close button */
 }
@@ -1499,8 +1500,31 @@ toolbar[mode="text"] toolbarbutton.chevr
 #allTabs-filter {
   -moz-margin-start: 36px;
   -moz-margin-end: 0;
 }
 
 .allTabs-preview-label {
   -moz-transform: translate(0, 2px);
 }
+
+/* Inspector / Highlighter */
+
+#highlighter-panel {
+  -moz-appearance: none;
+  -moz-window-shadow: none;
+}
+
+listitem.style-selector {
+  background-color: DarkGray;
+  color: white;
+}
+
+listitem.style-section {
+  background-color: LightGray;
+  color: black;
+  font-weight: bold;
+}
+
+panel[dimmed="true"] {
+  opacity: 0.5;
+}
+
--- a/browser/themes/pinstripe/browser/browser.css
+++ b/browser/themes/pinstripe/browser/browser.css
@@ -69,53 +69,43 @@
 
 .tabbrowser-tab:-moz-lwtheme[selected="true"] {
   background-color: transparent !important;
 }
 .tabbrowser-tab:-moz-lwtheme:not([selected="true"]):not(:hover) > .tab-text {
   opacity: .8;
 }
 
-.tabs-newtab-button:-moz-lwtheme {
+#tabbrowser-tabs[tabsontop="false"] > .tabbrowser-arrowscrollbox > .tabs-newtab-button:-moz-lwtheme {
   width: auto;
   -moz-box-flex: 1;
   -moz-box-pack: start;
   border-style: none;
   background: none;
 }
 
-.tabbrowser-tab:-moz-lwtheme-brighttext {
-  -moz-border-left-colors: rgba(255,255,255,.1) rgba(255,255,255,.6) rgba(255,255,255,.2);
-  -moz-border-bottom-colors: rgba(255,255,255,.1) rgba(255,255,255,.6) rgba(255,255,255,.2);
-  -moz-border-right-colors: rgba(255,255,255,.1) rgba(255,255,255,.6) rgba(255,255,255,.2);
-}
-
-.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 > 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"]) {
+#tabbrowser-tabs[tabsontop="false"] > .tabbrowser-arrowscrollbox > .tabs-newtab-button:-moz-lwtheme-darktext,
+#TabsToolbar[tabsontop="false"] > toolbarbutton:-moz-lwtheme-darktext,
+#TabsToolbar[tabsontop="false"] > toolbarpaletteitem > toolbarbutton:-moz-lwtheme-darktext,
+#TabsToolbar[tabsontop="false"] > #bookmarks-menu-button-container > #bookmarks-menu-button:-moz-lwtheme-darktext,
+#TabsToolbar[tabsontop="false"] #tabs-closebutton:-moz-lwtheme-darktext,
+#tabbrowser-tabs[tabsontop="false"] > .tabbrowser-arrowscrollbox > .scrollbutton-up:-moz-lwtheme-darktext,
+#tabbrowser-tabs[tabsontop="false"] > .tabbrowser-arrowscrollbox > .scrollbutton-down:-moz-lwtheme-darktext,
+#tabbrowser-tabs[tabsontop="false"] > .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 > 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"]) {
+#tabbrowser-tabs[tabsontop="false"] > .tabbrowser-arrowscrollbox > .tabs-newtab-button:-moz-lwtheme-brighttext,
+#TabsToolbar[tabsontop="false"] > toolbarbutton:-moz-lwtheme-brighttext,
+#TabsToolbar[tabsontop="false"] > toolbarpaletteitem > toolbarbutton:-moz-lwtheme-brighttext,
+#TabsToolbar[tabsontop="false"] > #bookmarks-menu-button-container > #bookmarks-menu-button:-moz-lwtheme-brighttext,
+#TabsToolbar[tabsontop="false"] #tabs-closebutton:-moz-lwtheme-brighttext,
+#tabbrowser-tabs[tabsontop="false"] > .tabbrowser-arrowscrollbox > .scrollbutton-up:-moz-lwtheme-brighttext,
+#tabbrowser-tabs[tabsontop="false"] > .tabbrowser-arrowscrollbox > .scrollbutton-down:-moz-lwtheme-brighttext,
+#tabbrowser-tabs[tabsontop="false"] > .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;
 }
 
@@ -123,30 +113,40 @@
   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 {
+#PersonalToolbar:not(:-moz-lwtheme),
+#navigator-toolbox[tabsontop="true"] > toolbar:not(#TabsToolbar):not(:-moz-lwtheme) {
   -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);
 }
 
-#PersonalToolbar:-moz-window-inactive {
+#PersonalToolbar:not(:-moz-lwtheme):-moz-window-inactive,
+#navigator-toolbox[tabsontop="true"] > toolbar:not(#TabsToolbar):not(:-moz-lwtheme):-moz-window-inactive {
   background-color: -moz-mac-chrome-inactive;
   border-bottom-color: rgba(0, 0, 0, 0.32);
 }
 
+#navigator-toolbox[tabsontop="true"] > #nav-bar,
+#navigator-toolbox[tabsontop="true"]:not([customizing]) > #nav-bar[collapsed="true"] + toolbar,
+#navigator-toolbox[tabsontop="true"]:not([customizing]) > #nav-bar[collapsed="true"] + #customToolbars + #PersonalToolbar {
+  padding-top: 4px !important;
+  background-image: -moz-linear-gradient(rgba(255,255,255,.58), rgba(255,255,255,0)) !important; /* override lwtheme style */
+  -moz-background-origin: border !important;
+}
+
+/* ----- BOOKMARK TOOLBAR ----- */
+
 #personal-bookmarks {
   min-height: 17px; /* 16px button height + 1px margin-bottom */
 }
 
 toolbarbutton.chevron {
   list-style-image: url("chrome://global/skin/icons/chevron.png");
   margin: 1px 0 0;
   padding: 0;
@@ -1340,21 +1340,16 @@ sidebarheader > .tabs-closebutton > .too
 #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[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 {
   list-style-image: url("chrome://mozapps/skin/places/defaultFavicon.png");
 }
 
 .openintabs-menuitem {
   list-style-image: none;
 }
 
@@ -1363,16 +1358,19 @@ toolbarbutton.chevron > .toolbarbutton-m
 .tabbrowser-tabbox {
   margin: 0;
 }
 
 .tab-icon-image {
   width: 16px;
   height: 16px;
   list-style-image: url("chrome://global/skin/tree/item.png");
+}
+
+.tabbrowser-tab[pinned] > .tab-icon-image {
   margin-top: 2px;
 }
 
 .tabbrowser-tab[busy] > .tab-icon-image {
   list-style-image: url("chrome://browser/skin/tabbrowser/progress.png") !important;
   -moz-image-region: rect(0, 16px, 16px, 0);
 }
 .tabbrowser-tab[busy][stalled] > .tab-icon-image {
@@ -1403,64 +1401,90 @@ toolbarbutton.chevron > .toolbarbutton-m
   -moz-image-region: rect(0, 144px, 16px, 128px);
 }
 
 .tabbrowser-tab:not(:hover):not([selected="true"]) > .tab-icon-image {
   opacity: .6;
 }
 
 .tabbrowser-tab > .tab-text {
-  margin-top: 3px;
+  margin-top: 1px;
   margin-bottom: 0;
   font: message-box;
   font-weight: bold;
 }
 
 .tabbrowser-tab,
 .tabs-newtab-button {
   -moz-appearance: none;
   -moz-border-radius: 0 0 6px 6px;
   color: #222;
   text-shadow: 0 1px 0 rgba(255, 255, 255, 0.4);
   margin: 0 0 1px;
-  padding: 0 5px;
+  padding: 2px 5px 0;
   border-style: none solid solid;
   border-width: 3px;
-  -moz-border-right-colors: rgba(0, 0, 0, .08) rgba(0, 0, 0, .17) rgba(180, 180, 180, .29);
-  -moz-border-bottom-colors: rgba(0, 0, 0, .08) rgba(0, 0, 0, .17) rgba(180, 180, 180, .29);
-  -moz-border-left-colors: rgba(0, 0, 0, .08) rgba(0, 0, 0, .17) rgba(180, 180, 180, .29);
+  -moz-border-top-colors: rgba(0,0,0,.04) rgba(0,0,0,.17) rgba(255,255,255,.35);
+  -moz-border-bottom-colors: rgba(0,0,0,.04) rgba(0,0,0,.17) rgba(255,255,255,.25);
+  -moz-border-right-colors: rgba(0,0,0,.04) rgba(0,0,0,.17) rgba(255,255,255,.1);
+  -moz-border-left-colors: rgba(0,0,0,.04) rgba(0,0,0,.17) rgba(255,255,255,.1);
   background-clip: padding-box;
   text-align: center;
   height: 24px;
   background-image: url(chrome://browser/skin/tabbrowser/tab-bkgnd.png);
 }
 
+#tabbrowser-tabs[tabsontop="true"] > .tabbrowser-tab,
+#tabbrowser-tabs[tabsontop="true"] > .tabbrowser-arrowscrollbox > .tabs-newtab-button {
+  border-top-style: solid;
+  border-bottom-style: none;
+  -moz-border-radius: 6px 6px 0 0;
+  padding-top: 0;
+  padding-bottom: 2px;
+  margin-top: 1px;
+  margin-bottom: 0;
+  background-image: -moz-linear-gradient(rgba(255,255,255,.2), rgba(255,255,255,0));
+}
+
 .tabs-newtab-button {
   width: 34px;
-  padding-top: 1px;
+}
+
+.tabs-newtab-button > .toolbarbutton-icon {
+  margin-top: -1px;
+}
+
+#tabbrowser-tabs[tabsontop="true"] > .tabbrowser-arrowscrollbox > .tabs-newtab-button > .toolbarbutton-icon {
+  margin-top: 0;
+  margin-bottom: -1px;
 }
 
 .tabs-newtab-button > .toolbarbutton-icon:-moz-window-inactive {
   opacity: 0.75;
 }
 
 .tabbrowser-tab[selected="true"] {
-  padding: 0 6px 1px;
-  border-width: 2px;
-  -moz-border-left-colors: rgba(0, 0, 0, .1) rgba(0, 0, 0, .2);
-  -moz-border-bottom-colors: rgba(0, 0, 0, .1) rgba(0, 0, 0, .2);
-  -moz-border-right-colors: rgba(0, 0, 0, .1) rgba(0, 0, 0, .2);
+  -moz-border-bottom-colors: rgba(0,0,0,.04) rgba(0,0,0,.17) rgba(255,255,255,.3);
+  -moz-border-right-colors: rgba(0,0,0,.04) rgba(0,0,0,.17) rgba(255,255,255,.3);
+  -moz-border-left-colors: rgba(0,0,0,.04) rgba(0,0,0,.17) rgba(255,255,255,.35);
   background-image: none;
   background-color: -moz-mac-chrome-active;
 }
 
 .tabbrowser-tab[selected="true"]:-moz-window-inactive {
   background-color: -moz-mac-chrome-inactive;
 }
 
+#tabbrowser-tabs[tabsontop="true"] > .tabbrowser-tab[selected="true"] {
+  -moz-border-top-colors: rgba(0,0,0,.04) rgba(0,0,0,.17) rgba(255,255,255,.9);
+  -moz-border-right-colors: rgba(0,0,0,.04) rgba(0,0,0,.17) rgba(255,255,255,.6);
+  -moz-border-left-colors: rgba(0,0,0,.04) rgba(0,0,0,.17) rgba(255,255,255,.6);
+  background-image: -moz-linear-gradient(rgba(255,255,255,.7), rgba(255,255,255,.58));
+}
+
 .tabbrowser-tab:focus > .tab-text {
   -moz-box-shadow: @focusRingShadow@;
 }
 
 .tabbrowser-tab[selected="true"],
 .tabbrowser-tab:hover {
   color: #000000;
 }
@@ -1469,30 +1493,33 @@ toolbarbutton.chevron > .toolbarbutton-m
   color: #575757;
 }
 
 .tabbrowser-tab:-moz-lwtheme {
   color: inherit;
   text-shadow: inherit;
 }
 
-#TabsToolbar {
-  -moz-appearance: none;
+#TabsToolbar[tabsontop="true"]:not(:-moz-lwtheme) {
+  padding-bottom: 1px;
+  -moz-box-shadow: 0 -6px 5px -5px rgba(0,0,0,.3) inset,
+                   0 -2px 0 rgba(0,0,0,.2) inset;
 }
 
-#navigator-toolbox:not([tabsontop="true"]) > #TabsToolbar {
+#TabsToolbar[tabsontop="false"] {
+  -moz-appearance: none;
   margin-top: -1px;
   border-bottom: 1px solid #404040;
 }
 
-#TabsToolbar:not(:-moz-lwtheme) {
+#TabsToolbar[tabsontop="false"]:not(:-moz-lwtheme) {
   background: #9B9B9B url("chrome://browser/skin/tabbrowser/tabbrowser-tabs-bkgnd.png") repeat-x;
 }
 
-#TabsToolbar:not(:-moz-lwtheme):-moz-window-inactive {
+#TabsToolbar[tabsontop="false"]:not(:-moz-lwtheme):-moz-window-inactive {
   background-color: #e2e2e2;
 }
 
 .tabbrowser-tabs {
   -moz-box-align: stretch;
   height: 25px;
 }
 
@@ -1510,26 +1537,25 @@ toolbarbutton.chevron > .toolbarbutton-m
 }
 
 /**
  * In-tab close button
  */
 
 .tab-close-button > .toolbarbutton-icon {
   -moz-margin-end: 0px !important;
-  margin-top: 1px;
   padding: 0;
 }
 
 .tab-close-button {
   list-style-image: url("chrome://global/skin/icons/closetab.png");
   -moz-appearance: none;
   border: none !important;
   padding: 0;
-  margin: 1px 0 0;
+  margin: 0;
   background: none;
   cursor: default;
 }
 
 .tab-close-button:hover {
   list-style-image: url("chrome://global/skin/icons/closetab-hover.png");
 }
 
@@ -1572,85 +1598,90 @@ toolbarbutton.chevron > .toolbarbutton-m
   border-left: 2px solid;
   -moz-border-left-colors: rgba(0,0,0,0.25) rgba(255,255,255,0.15);
   list-style-image: url("chrome://browser/skin/tabbrowser/tab-arrow-right.png");
 }
 
 .tabbrowser-arrowscrollbox > .scrollbutton-up:hover,
 .tabbrowser-arrowscrollbox > .scrollbutton-down:hover {
   -moz-image-region: rect(0, 22px, 17px, 11px);
-  background-color: rgba(0,0,0,0.10);
-  -moz-transition: none;
 }
 
 .tabbrowser-arrowscrollbox > .scrollbutton-up:hover:active,
 .tabbrowser-arrowscrollbox > .scrollbutton-down:hover:active {
   -moz-image-region: rect(0, 44px, 17px, 33px);
-  background-color: rgba(0,0,0,0.20);
 }
 
 .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 toolbar buttons
  */
 
 #TabsToolbar > toolbarbutton,
 #TabsToolbar > toolbarpaletteitem > toolbarbutton,
+#TabsToolbar > #bookmarks-menu-button-container > #bookmarks-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 {
   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 > #bookmarks-menu-button-container > #bookmarks-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 > toolbarbutton > .toolbarbutton-icon,
 #TabsToolbar > toolbarpaletteitem > toolbarbutton > .toolbarbutton-icon,
+#TabsToolbar > #bookmarks-menu-button-container > #bookmarks-menu-button > .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;
 }
 
+.tabbrowser-arrowscrollbox > .scrollbutton-up:not([disabled="true"]):hover,
+.tabbrowser-arrowscrollbox > .scrollbutton-down:not([disabled="true"]):hover,
 #TabsToolbar > toolbarbutton:not([type="menu-button"]):not([disabled="true"]):not([open="true"]):hover,
+#TabsToolbar > #bookmarks-menu-button-container > #bookmarks-menu-button: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;
+  background-image: -moz-linear-gradient(transparent, rgba(0,0,0,.15)) !important;
 }
 
+.tabbrowser-arrowscrollbox > .scrollbutton-up:not([disabled="true"]):hover:active,
+.tabbrowser-arrowscrollbox > .scrollbutton-down:not([disabled="true"]):hover:active,
 #TabsToolbar > toolbarbutton:not([type="menu-button"]):not([disabled="true"]):hover:active,
+#TabsToolbar > #bookmarks-menu-button-container > #bookmarks-menu-button: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;
+  background-image: -moz-linear-gradient(transparent, rgba(0,0,0,.3)) !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);
 }
@@ -2029,8 +2060,31 @@ toolbarbutton.chevron > .toolbarbutton-m
 
 .allTabs-preview:not(:hover):not([closebuttonhover]) > html|canvas {
   opacity: .8;
 }
 
 .allTabs-preview:focus > * > .allTabs-preview-inner {
   -moz-box-shadow: @focusRingShadow@;
 }
+
+/* Inspector / Highlighter */
+
+#highlighter-panel {
+  -moz-appearance: none;
+  -moz-window-shadow: none;
+}
+
+listitem.style-selector {
+  background-color: DarkGray;
+  color: white;
+}
+
+listitem.style-section {
+  background-color: LightGray;
+  color: black;
+  font-weight: bold;
+}
+
+panel[dimmed="true"] {
+  opacity: 0.5;
+}
+
--- a/browser/themes/winstripe/browser/browser.css
+++ b/browser/themes/winstripe/browser/browser.css
@@ -415,17 +415,18 @@ toolbarbutton[type="menu-button"][open="
 }
 
 toolbar[mode="full"] .toolbarbutton-1,
 toolbar[mode="full"] .toolbarbutton-menubutton-button {
   min-width: 57px;
 }
 
 #TabsToolbar > .toolbarbutton-1,
-#TabsToolbar > toolbarpaletteitem > .toolbarbutton-1 {
+#TabsToolbar > toolbarpaletteitem > .toolbarbutton-1,
+#TabsToolbar > #bookmarks-menu-button-container > #bookmarks-menu-button {
   -moz-appearance: toolbarbutton;
   margin: 0;
   padding: 0 3px;
   border: none !important;
   color: inherit !important;
   background: transparent !important;
   text-shadow: inherit !important;
   -moz-box-shadow: none !important;
@@ -1226,107 +1227,96 @@ richlistitem[type="action"][actiontype="
 /* Tab DnD indicator */
 .tab-drop-indicator {
   list-style-image: url(chrome://browser/skin/tabbrowser/tabDragIndicator.png);
 }
 
 /* Tab close button */
 .tab-close-button {
   -moz-appearance: none;
-  -moz-image-region: rect(0px, 56px, 14px, 42px);
+  -moz-image-region: rect(0, 64px, 16px, 48px);
   border: none;
   padding: 0px;
   list-style-image: url("chrome://global/skin/icons/close.png");
 }
 
 .tab-close-button:-moz-system-metric(touch-enabled) {
   -moz-transform: scale(1.2);
 }
 
 .tab-close-button:hover,
 .tabbrowser-tab[selected="true"] > .tab-close-button:hover {
-  -moz-image-region: rect(0px, 28px, 14px, 14px);
+  -moz-image-region: rect(0, 32px, 16px, 16px);
 }
 
 .tab-close-button:hover:active,
 .tabbrowser-tab[selected="true"] > .tab-close-button:hover:active {
-  -moz-image-region: rect(0px, 42px, 14px, 28px);
+  -moz-image-region: rect(0, 48px, 16px, 32px);
 }
 
 .tabbrowser-tab[selected="true"] > .tab-close-button {
-  -moz-image-region: rect(0px, 14px, 14px, 0px);
+  -moz-image-region: rect(0, 16px, 16px, 0);
   /* Make this button focusable so clicking on it will not focus the tab while
      it's getting closed */
   -moz-user-focus: normal;
 }
 
 .tab-close-button:focus {
   outline: none !important;
 }
 
 /* Tab scrollbox arrow, tabstrip new tab and all-tabs buttons */
 
 @media all and (-moz-touch-enabled) {
   .tabbrowser-arrowscrollbox > .scrollbutton-up,
   .tabbrowser-arrowscrollbox > .scrollbutton-down,
   #TabsToolbar > toolbarbutton,
-  #TabsToolbar > toolbarpaletteitem > toolbarbutton {
+  #TabsToolbar > toolbarpaletteitem > toolbarbutton,
+  #TabsToolbar > #bookmarks-menu-button-container > #bookmarks-menu-button {
     min-width: .81cm;
   }
 
   .tabs-newtab-button {
     min-width: 1cm;
   }
 }
 
 .tabbrowser-arrowscrollbox > .scrollbutton-up,
 .tabbrowser-arrowscrollbox > .scrollbutton-down {
+  list-style-image: url("chrome://browser/skin/tabbrowser/tab-arrow-left.png");
   -moz-image-region: rect(0, 15px, 17px, 0);
   margin: 0;
   padding-top: 0;
   padding-bottom: 0;
 }
 
-.tabbrowser-arrowscrollbox > .scrollbutton-up:not([disabled="true"]):hover,
-.tabbrowser-arrowscrollbox > .scrollbutton-down:not([disabled="true"]):hover {
-  -moz-image-region: rect(0, 30px, 17px, 15px);
-}
-
 .tabbrowser-arrowscrollbox > .scrollbutton-up[disabled="true"],
 .tabbrowser-arrowscrollbox > .scrollbutton-down[disabled="true"] {
   opacity: .4;
 }
 
 .tabbrowser-arrowscrollbox > .scrollbutton-up:not([disabled="true"]):hover:active,
 .tabbrowser-arrowscrollbox > .scrollbutton-down:not([disabled="true"]):hover:active {
-  -moz-image-region: rect(0, 45px, 17px, 30px);
+  -moz-image-region: rect(0, 30px, 17px, 15px);
 }
 
-.tabbrowser-arrowscrollbox > .scrollbutton-up:-moz-locale-dir(ltr) {
-  list-style-image: url("chrome://browser/skin/tabbrowser/tab-arrow-left.png");
-}
-
-.tabbrowser-arrowscrollbox > .scrollbutton-up:-moz-locale-dir(rtl) {
-  list-style-image: url("chrome://browser/skin/tabbrowser/tab-arrow-right.png");
+.tabbrowser-arrowscrollbox > .scrollbutton-up:-moz-locale-dir(rtl) > .toolbarbutton-icon,
+.tabbrowser-arrowscrollbox > .scrollbutton-down:-moz-locale-dir(ltr) > .toolbarbutton-icon {
+  -moz-transform: scaleX(-1);
 }
 
 .tabbrowser-arrowscrollbox > .scrollbutton-down {
-  list-style-image: url("chrome://browser/skin/tabbrowser/tab-arrow-right.png");
   -moz-transition: 1s background-color ease-out;
 }
 
 .tabbrowser-arrowscrollbox > .scrollbutton-down[notifybgtab] {
   background-color: Highlight;
   -moz-transition: none;
 }
 
-.tabbrowser-arrowscrollbox > .scrollbutton-down:-moz-locale-dir(rtl) {
-  list-style-image: url("chrome://browser/skin/tabbrowser/tab-arrow-left.png");
-}
-
 .tabs-newtab-button > .toolbarbutton-icon,
 #TabsToolbar > #new-tab-button > .toolbarbutton-icon,
 #TabsToolbar > toolbarpaletteitem > #new-tab-button > .toolbarbutton-icon,
 #alltabs-button > .toolbarbutton-icon {
   width: auto;
   height: auto;
 }
 
@@ -1348,21 +1338,21 @@ richlistitem[type="action"][actiontype="
 
 .tabs-newtab-button:hover:active,
 #TabsToolbar > #new-tab-button:hover:active {
   -moz-image-region: rect(0, 32px, 18px, 16px);
 }
 
 #alltabs-button {
   list-style-image: url("chrome://browser/skin/tabbrowser/alltabs.png");
-  -moz-image-region: rect(0, 14px, 17px, 0);
+  -moz-image-region: rect(0, 14px, 16px, 0);
 }
 
 #alltabs-button:hover:active {
-  -moz-image-region: rect(0, 28px, 17px, 14px);
+  -moz-image-region: rect(0, 28px, 16px, 14px);
 }
 
 #alltabs-button[type="menu"] {
   list-style-image: url("chrome://browser/skin/mainwindow-dropdown-arrow.png");
   -moz-image-region: rect(0, 13px, 11px, 0);
 }
 
 #alltabs-button[type="menu"] > .toolbarbutton-icon {
@@ -1391,38 +1381,34 @@ richlistitem[type="action"][actiontype="
 .alltabs-item[busy] > .menu-iconic-left > .menu-iconic-icon {
   list-style-image: url("chrome://global/skin/icons/loading_16.png");
 }
 
 /* Tabstrip close button */
 .tabs-closebutton {
   -moz-appearance: none;
   list-style-image: url("chrome://global/skin/icons/close.png");
-  -moz-image-region: rect(0px, 14px, 14px, 0px);
+  -moz-image-region: rect(0, 16px, 16px, 0);
   padding: 4px 2px;
   margin: 0px;
   border: none;
 }
 
 .tabs-closebutton > .toolbarbutton-icon {
   -moz-margin-end: 0px !important;
   -moz-padding-end: 2px !important;
   -moz-padding-start: 2px !important;
 }
 
 .tabs-closebutton:hover {
-  -moz-image-region: rect(0px, 28px, 14px, 14px);
+  -moz-image-region: rect(0, 32px, 16px, 16px);
 }
 
 .tabs-closebutton:hover:active {
-  -moz-image-region: rect(0px, 42px, 14px, 28px);
-}
-
-#sidebar-header > .tabs-closebutton {
-  list-style-image: url("chrome://global/skin/icons/closeSidebar.png");
+  -moz-image-region: rect(0, 48px, 16px, 32px);
 }
 
 toolbarbutton.chevron {
   list-style-image: url("chrome://global/skin/toolbar/chevron.gif") !important;
 }
 
 toolbarbutton.chevron:-moz-locale-dir(rtl) > .toolbarbutton-icon {
   -moz-transform: scaleX(-1);
@@ -1786,8 +1772,31 @@ toolbarbutton.bookmark-item[dragover="tr
 
 .allTabs-preview:not(:hover):not([closebuttonhover]) > html|canvas {
   opacity: .8;
 }
 
 .allTabs-preview:focus > * > .allTabs-preview-inner {
   outline: 1px dotted -moz-dialogText;
 }
+
+/* Inspector / Highlighter */
+
+#highlighter-panel {
+  -moz-appearance: none;
+  -moz-window-shadow: none;
+}
+
+listitem.style-selector {
+  background-color: DarkGray;
+  color: white;
+}
+
+listitem.style-section {
+  background-color: LightGray;
+  color: black;
+  font-weight: bold;
+}
+
+panel[dimmed="true"] {
+  opacity: 0.5;
+}
+
--- a/browser/themes/winstripe/browser/jar.mn
+++ b/browser/themes/winstripe/browser/jar.mn
@@ -78,17 +78,16 @@ browser.jar:
         skin/classic/browser/preferences/preferences.css             (preferences/preferences.css)
         skin/classic/browser/preferences/applications.css            (preferences/applications.css)
         skin/classic/browser/tabbrowser/alltabs.png                             (tabbrowser/alltabs.png)
         skin/classic/browser/tabbrowser/newtab.png                              (tabbrowser/newtab.png)
         skin/classic/browser/tabbrowser/progress.png                            (tabbrowser/progress.png)
         skin/classic/browser/tabbrowser/progress-pulsing.png                    (tabbrowser/progress-pulsing.png)
         skin/classic/browser/tabbrowser/tab.png                                 (tabbrowser/tab.png)
         skin/classic/browser/tabbrowser/tab-arrow-left.png                      (tabbrowser/tab-arrow-left.png)
-        skin/classic/browser/tabbrowser/tab-arrow-right.png                     (tabbrowser/tab-arrow-right.png)
         skin/classic/browser/tabbrowser/tabDragIndicator.png                    (tabbrowser/tabDragIndicator.png)
 
 #ifdef XP_WIN
 browser.jar:
 % skin browser classic/1.0 %skin/classic/aero/browser/ os=WINNT osversion>=6
         skin/classic/aero/browser/sanitizeDialog.css                       (sanitizeDialog.css)
 *       skin/classic/aero/browser/aboutPrivateBrowsing.css           (aboutPrivateBrowsing.css)
 *       skin/classic/aero/browser/aboutSessionRestore.css            (aboutSessionRestore.css)
@@ -160,17 +159,16 @@ browser.jar:
         skin/classic/aero/browser/preferences/alwaysAsk.png          (preferences/alwaysAsk-aero.png)
         skin/classic/aero/browser/preferences/application.png        (preferences/application-aero.png)
         skin/classic/aero/browser/preferences/mail.png               (preferences/mail-aero.png)
         skin/classic/aero/browser/preferences/Options.png            (preferences/Options-aero.png)
         skin/classic/aero/browser/preferences/plugin.png             (preferences/plugin-aero.png)
         skin/classic/aero/browser/preferences/saveFile.png           (preferences/saveFile-aero.png)
         skin/classic/aero/browser/preferences/preferences.css        (preferences/preferences.css)
         skin/classic/aero/browser/preferences/applications.css       (preferences/applications.css)
-        skin/classic/aero/browser/tabbrowser/alltabs.png                        (tabbrowser/alltabs-aero.png)
-        skin/classic/aero/browser/tabbrowser/newtab.png                         (tabbrowser/newtab-aero.png)
+        skin/classic/aero/browser/tabbrowser/alltabs.png                        (tabbrowser/alltabs.png)
+        skin/classic/aero/browser/tabbrowser/newtab.png                         (tabbrowser/newtab.png)
         skin/classic/aero/browser/tabbrowser/progress.png                       (tabbrowser/progress.png)
         skin/classic/aero/browser/tabbrowser/progress-pulsing.png               (tabbrowser/progress-pulsing.png)
         skin/classic/aero/browser/tabbrowser/tab.png                            (tabbrowser/tab.png)
-        skin/classic/aero/browser/tabbrowser/tab-arrow-left.png                 (tabbrowser/tab-arrow-left-aero.png)
-        skin/classic/aero/browser/tabbrowser/tab-arrow-right.png                (tabbrowser/tab-arrow-right-aero.png)
-        skin/classic/aero/browser/tabbrowser/tabDragIndicator.png               (tabbrowser/tabDragIndicator-aero.png)
+        skin/classic/aero/browser/tabbrowser/tab-arrow-left.png                 (tabbrowser/tab-arrow-left.png)
+        skin/classic/aero/browser/tabbrowser/tabDragIndicator.png               (tabbrowser/tabDragIndicator.png)
 #endif
deleted file mode 100644
index 54a0b63fe6d3f94c83acbb27cde0842c5d2317a0..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
index 272cf6e8d17eb94be649fda14ba00f38deceb6ae..172d425f803abf31a0760b741dc67026690d8148
GIT binary patch
literal 584
zc$@)90=NB%P)<h;3K|Lk000e1NJLTq000~S000mO1^@s61<xPv00009a7bBm000XU
z000XU0RWnu7ytkOAY({UO#lFTB>(_`g8%^e{{R4h=>PzAFaQARU;qF*m;eA5Z<1fd
zMgRZ-&PhZ;RCwClmCa5XQ5c3F{>6?&tFfs8TBxytAyPq&b=8aMqIW>ApqJ1^FTsoG
zN|PE)T!}SRG!Vo|DM}~cFb>nrIe64brwhZPUvd`nyx%$Rmosl>e2(KV%JMVf3IZHA
zFN4515EVlV088|Q6xIW}Tm8u!MbpFz05)I>Eut_3FiJ_Rpb*D_lpNqMbpup^j(FC9
z3=sC%*9R&<TN*@x;Cv!p)}GB_Tr~Jms}})WSoEG@_~VE7Ut^g(oytC+K7V-!;KDT3
z&<~K#=7_&cQ#(5uj+R==k$91&etP2e-U9%yRyRnjY*5ppL&1dwP_A$QV4FQ0vrAxL
z-JUqGaLg{Y*+cCWWdqoaDpu?XcB6VLJY+V2&v6`%o0m_4)RZ<>kZRkw-UD!9)vf;I
zFM(!(Y+-`D?AiOxK7b25C?(PFghZNnvHK-WyqJ2WA%Ml#3+08yEUlk9+uJ)ufX&Uf
z<>{GOjt&nv{C-rFy-M`?$IwJnLq9-nIZwW@%6YvuJn_v+k>~LQkx2OQLt`2p+Io|#
zmOk8g)zTRYhcJ!KqlP9XLbL7>nr|XB(tQfZ6ed{n2+b}~DJ5x3!;yX3eE<F5;?DrN
WGymvyx-HNE0000<MNUMnLSTXq3;NRl
deleted file mode 100644
index 833502603068ddcf86a60752bb38373ee87f48da..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
index 14a9b93e2e0d2a3328d5648b7995352b45df6d99..404f3af1cafe487d668a64e062d9e4c79d1b2882
GIT binary patch
literal 603
zc$@)S0;K(kP)<h;3K|Lk000e1NJLTq001BW000sQ1^@s6I>_8o0000PbVXQnQ*UN;
zcVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBUz{YgYYRCwBA{Qv(y!$1PYLE(VAFFv4)
zvj8y{5OYHL-+}lW5dT3|q%0u-rps2JCrf`<s3BM(HUQGB2sMZSs_{M$e<IRjMC)h5
zVF1YGECD{AXFwQg5GM&C3)a7D`NT6Ij88wV5CA(&T27G|$Kup4V_->8KMR&P11S^+
z39_-VBdZmL(*Ll;DOUZQ{K5qFv*3s`ND5_SMCO8ABZVVQvFc~#<Rqw{1v$>VT%FEv
z^YDTNxOsUQBxK~k?1Z?OGhaV{2D86@`OL6w_dXM-o=@m;&MPJj7T^_^VvsYo2D7i6
zJ$mNz%V%Kr=T}b|+#>Vg`cYiW$;HLMFDL|NvvF`Rz={Yiprcq=SRvu}?=Q}X=a-ac
z5L43yvpM($7}$CEAz`nm&cH1s4oL{iELhV3C{F(D+q)+nSu!FzZYGFcv2+oN`1>zE
z{y_CGAnWfd%|}r;{q$|H{sIRhBylH(m8T!V^}`$hN)Y#f2ERZ`MC_kFet=nc7D)XB
z;<spthyhtY&|nn(UtYfiORhZ4hEqRsLGcN#ppg3c1KAF+=I1y<AFKYqzkd<bkE<L2
zxsu__=T8`7L;|qdkIx@LouZ6WKQ0G=<MiaoQ|UP3oDcx(Z_h|bheW|coceJ&069%C
pV2N`=069(I)z3KM+XDar1^{xD&@(t_kg5Ox002ovPDHLkV1h__2C)DD
deleted file mode 100644
index 3482d7e5850069b9bf69282c0548450d47bf63a5..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
index c93d1fc3aa5159d43f5f68c7c8281d6681602eda..0ef2b1ae61e2d4396ac70fab94dab6a7b49ef1aa
GIT binary patch
literal 460
zc%17D@N?(olHy`uVBq!ia0vp^azHG|!3-q-?s(%0q*es@gn;Nf&)*Y?UVixc;{6vj
z4NbNBS!zvl)LQ0g8(ZjG*t*Z(9vB{DYGr5Izua=-3ad#gZJgblJbnB^A_C@b4vL5g
zn!h<@`QFflTO$)vVw2KilhYH@vy!s%Iop<T3yBMKt`O{7CnPN=CZ{MibC1Nt4RUJQ
zDhm$im{{qX+Zb5c8(G;cc78Vx=vJ+gAirP+Miw@9E>SUY2}xNkZDTjz8DOw<>2fgG
zi~uvk13v?Gt@Lzp4ABT)d-1r?Aq4@p1Sglv3IZl&y&I?BIQ@J7Obf{f8-utzx3}AG
z-pt@sufZ?eWUKzSLCyC~%83?_j-xui7v1=-$$0ASfn^qcl?{q(xqMrg)%=X*e$HFA
z#>?4d#SXp7I|fspTLx7Ad9_i(uRkw#!K`E9{c~E=EaGEswPj83$e(9vyxMionk8v>
zZ``vk5S}UzWJUOEY>ePh{I@4**0v4J`}ZA*%nv-p{r#BF&r3i@GkCiCxvX<aXaWEg
CQq4;M
deleted file mode 100644
index cb4bfe53e181b20d5520f1cd9cc3fd852bf7849b..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index 86db7ae18a081bed201c6c9505593c11807ab038..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index f2876e3852feee7f8f5df0be013d3f0c2e4ab25e..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
index d32b79cfab76093c36c45e7b643ad9429925b3f4..8556c0df2677d4f262be559bdd63ffe21fba83a9
GIT binary patch
literal 3152
zc$@)H46pNvP)<h;3K|Lk000e1NJLTq000XB000XJ1^@s6sjPP<00009a7bBm000XU
z000XU0RWnu7ytkYPiaF#P*7-ZbZ>KLZ*U+<Lqi~Na&Km7Y-Iodc-oy)XH-+^7Crag
z^g>IBfRsybQWXdwQbLP>6p<z>Aqfylh#{fb6;Z(vMMVS~$e@S=j*ftg6;Uh<iVD~V
z<RPMtgQJLw%KPDaqifc@_vX$1wbwr9tn;0-&j-K=43<bUQ8j=JsX`tR;Dg7+#^K~H
zK!FM*Z~zbpvt%K2{UZSY_<lS*D<Z%Lz5oGu(+dayz)hRLFdT>f59&ghTmgWD0l;*T
zI7<kC6aYYajzXpYKt=(8otP$50H6c_V9R4-;{Z@C0AMG7=F<Rxo%or10RUT+Ar%3j
zkpLhQWr#!oXgdI`&sK^>09Y^p6lP1rIRMx#05C~cW=H_Aw*bJ-5DT&Z2n+x)QHX^p
z00esgV8|mQcmRZ%02D^@S3L16t`O%c004NIvOKvYIYoh62rY33S640`D9%Y2D-<?i
z0%4j!F2Z@488U%158(66005wo6%pWr^Zj_v4zAA5HjcIqUoGmt2LB>rV&neh&#Q1i
z007~1e$oCcFS8neI|hJl{-P!B1ZZ9hpmq0)X0i`JwE&>$+E?>%_<lS*MWK+n+1cgf
z<k(8YLR(?VSAG6x!e78w{cQPuJpA|d;J)G{fihizM+Erb!p!tcr5w+a34~(Y=8s4G
zw+sLL9n&JjNn*KJDiq^U5^;`1nvC-@r6P$!k}1U{(*I=Q-z@tBKHoI}uxdU5dyy@u
zU1J0GOD7Ombim^G008p4Z^6_k2m^p<gW=D2|L;HjN1!DDfM!XOaR2~bL?kX$%CkSm
z2mk;?pn)o|K^yeJ7%adB9Ki+L!3+FgHiSYX#KJ-lLJDMn9CBbOtb#%)hRv`YDqt_v
zKpix|QD}yfa1JiQRk#j4a1Z)n2%f<xynzV>LC6RbVIkUx0b+_+BaR3cnT7Zv!AJxW
zizFb)h!jyGOOZ85F;a?DAXP{m@;!0_Ifq<Ex{*7`05XF7hP+2Hl!3BQJ=6@fL%FCo
z8iYoo3(#bAF`ADSpqtQgv>H8(HlgRxt7s3}k3K`kFu>>-2Q$QMFfPW!La{h336o>X
zu_CMttHv6zR;&ZNiS=X8v3CR#fknUxHUxJ<AYmRsNLWl*PS{AOARHt#5!wki2?K;t
z!Y3k=s7tgax)J%r7-BLphge7~Bi0g+6E6^Zh(p9TBoc{3GAFr^0!gu?RMHaCM$&Fl
zBk3%un>0uoBa_M6WNWeqIg~6QE69c9o#eyhGvpiOA@W-aonk<7r1(?fC{oI5N*U!4
z<uv66WtcKSRim0x-Ke2d5jBrmLam{;Qm;{ms1r1GnmNsb7D-E`t)i9F8fX`2_i3-_
zbh;7Ul^#x)&{xvS=|||7=mYe33=M`AgU5(xC>fg=2N-7=cNnjjOr{yriy6mMFgG#l
znCF=fnQv8CDz++o6_Lscl}eQ+l^ZHARH>?_s@|##Rr6KLRFA1%Q+=*RRWnoLsR`7U
zt5vF<Q0r40Q)j6=sE4X&sBct1q<&fbi3VB2Ov6t@q*0);U*o*SAPZv|vv@2aYYnT0
zb%8a+Cb7-ge0D0knEf5Qi#@8Tp*ce{N;6lpQuCB%KL_KOarm5cP6_8Ir<e17iry6O
zDdH&`rZh~sF=bq9s+O0QSgS~@QL9Jmy*94xr=6y~MY~!1fet~(N+(<=M`w@D1)b+p
z*;C!83a1uLJv#NSE~;y#8=<>IcfW3@?wFpwUVxrVZ>QdQz32KIeJ}k~{cZZE^+ya?
z2D1z#2HOnI7(B%_ac?{wFUQ;QQA1tBKtrWrm0_3Rgps+?Jfqb{jYbcQX~taRB;#$y
zZN{S}1|}gUOHJxc?wV3fxuz+mJ4`!F$IZ;mqRrNsHJd##*D~ju=bP7?-?v~|cv>vB
zsJ6IeNwVZxrdjT`yl#bBIa#GxRa#xMMy;K#CDyyGyQdMSxlWT#tDe?p!?5wT$+oGt
z8L;Kp2HUQ-ZMJ=3XJQv;x5ci*?vuTfeY$;({XGW_huIFR9a<fJbF^|4I#xQ~n$Dc=
zKYhjYmgz5NSkDm8*fZm{6U!;YX`NG>(?@3)XSs8O^N5RyOM=TTmp(3=8^+zpz2r)C
z^>JO{deZfso3oq3?Wo(Y?l$ge?uXo;%ru`Vo>?<<(8I_>;8Eq#KMS9gFl*neeosSB
zfoHYnBQIkwkyowPu(zdms`p{<7e4kra-ZWq<2*OsGTvEV%s0Td$hXT+!*8Bnh2KMe
zBmZRodjHV?r+_5^X9J0WL4jKW`}lf%A-|44I@@LTvf1rHjG(ze6+w@Jt%Bvjts!X0
z?2xS?_ve_-k<Mujg;0Lz*3buG=3$G&ehepthlN*$KaOySSQ^nWmo<0M+(UEUMEXRQ
zMBbZcF;6+KElM>iKB_KiJlZ$9G`c^=E@oNG)mWWaNo-3TIW8)$Hg0Ub-~8?KhvJ>$
z3*&nim@mj(aCxE5!t{lw7O5^0EIO7zOo&c6l<+|iDySBWCGrz@C5{St!X3hAA}`T4
z(TLbXTq+(;@<=L8dXnssyft|w#WSTW<++3>sgS%(4NTpeI-VAqb|7ssJvzNHgOZVu
zaYCvgO_R1~>SyL=cFU|~g|hy|Zi}}s9+d~lYqOB71z9Z$wnC=pR9Yz4DhIM>Wmjgu
z&56o6maCpC&F##y%G;1PobR9i?GnNg;gYtchD%p19a!eQtZF&3JaKv33gZ<8D~47E
ztUS1iwkmDaPpj=$m#%)jCVEY4fnLGNg2A-`YwHVD3gv};>)hAvT~AmqS>Lr``i7kw
zJ{5_It`yrBmlc25DBO7E8;5VoznR>Ww5hAaxn$2~(q`%A-YuS64wkBy=9dm`4cXeX
z4c}I@?e+FW+b@^RDBHV(wnMq2zdX3SWv9u`%{xC-q*U}&`cyXV(%rRT*Z6MH?i+i&
z_B8C(+grT%{XWUQ+f@NoP1R=AW&26{v-dx)iK^-Nmiuj8txj!m?Z*Ss1N{dh4z}01
z)YTo*JycSU)+_5r4#yw9{+;i4Ee$peRgIj+;v;ZGdF1K$3E%e~4LaI(jC-u%2h$&R
z9cLXcYC@Xwnns&bn)_Q~Te?roKGD|d-g^8;+aC{{G(1^(O7m37Y1-+6)01cN&y1aw
zoqc{T`P^XJqPBbIW6s}d4{z_f5Om?vMgNQEJG?v2T=KYd^0M3I6IZxbny)%vZR&LD
zJpPl@Psh8QyPB@KTx+@RdcC!KX7}kEo;S|j^u2lU7XQ}Oo;f|;z4Ll+_r>@1-xl3|
zawq-H%e&ckC+@AhPrP6BK<z=<L*0kfKU@CX*zeqbYQT4(^U>T#_XdT7&;F71j}Joy
zkC~6lh7E@6o;W@^IpRNZ{ptLtL(gQ-CY~4mqW;US7Zxvm_|@yz&e53Bp_lTPlfP|z
zrTyx_>lv@x#=^!PzR7qqF<$gm`|ZJZ+;<)Cqu&ot<a{81DF0~rvGr5Xr~8u`lav1h
z1DNytV>2z=0000WV@Og>004R=004l4008;_004mL004C`008P>0026e000+nl3&F}
z0004dNkl<Zc-l;n%}N_#7=@qr%Y5_Gj83N7_)|p@b=!b;?=^S_#oK75?N)3NY6Ta9
z(2|7|DvG^_QnV2*iOoimCRCE@5MvUO$#l^scy{MJhqF17FJA+U02A}GGv6K#Jp!QJ
z?huqO$(JjOKoR(D@K4Hj?S+NKrzA(lLEx^@By-ZkD1g2L@I4RTPaq<gW*x`2?_&(W
z1AG8&YAoAAMCgPere*ebfVu(9_L8{kV%s(%LfGvx=y^Tl0CO@nJ^v}D_41Qciiyc7
z;;xG*q1kLvC=~gb%W;uCXXbHoJ9b$pCQdUM&vN2Z3E#)EEwrJD#T2I2gkgvA(PVmW
z|LC1kBH69?n;(Z0gI|K1Yv@K8+CU-*ZvNnyD!sG&VI3%`YOV2AiJZQE_42b9e{fK#
zTya~g@vBs%Rj;StY;3LrC7`N+R<+hRRwCb5Upzl_Eq##tamHN`q}SeV^ou}S{y!*y
q9vW~`-6%>uTUlAUzX-H}=<fg{fr1V1p#z%$0000<MNUMnLSTZ{p5UVZ
--- a/build/autoconf/moznbytetype.m4
+++ b/build/autoconf/moznbytetype.m4
@@ -55,17 +55,17 @@ dnl The simplest approach would simply b
 dnl   printf ("%d\n", sizeof ($type));
 dnl But that won't work when cross-compiling; this will.
 AC_CACHE_CHECK([for a $2-byte type], moz_cv_n_byte_type_$1, [
   moz_cv_n_byte_type_$1=
   for type in $3; do
     AC_TRY_COMPILE([],
                    [
                      int a[sizeof ($type) == $2 ? 1 : -1];
-                     return;
+                     return 0;
                    ],
                    [moz_cv_n_byte_type_$1=$type; break], [])
   done
   if test ! "$moz_cv_n_byte_type_$1"; then
     AC_MSG_ERROR([Couldn't find a $2-byte type])
   fi
 ])
 AC_DEFINE_UNQUOTED($1, [$moz_cv_n_byte_type_$1],
@@ -86,17 +86,17 @@ dnl MOZ_SIZE_OF_TYPE([JS_BYTES_PER_WORD]
 AC_DEFUN(MOZ_SIZE_OF_TYPE,
 [
 AC_CACHE_CHECK([for the size of $2], moz_cv_size_of_$1, [
   moz_cv_size_of_$1=
   for size in $3; do
     AC_TRY_COMPILE([],
                    [
                      int a[sizeof ($2) == $size ? 1 : -1];
-                     return;
+                     return 0;
                    ],
                    [moz_cv_size_of_$1=$size; break], [])
   done
   if test ! "$moz_cv_size_of_$1"; then
     AC_MSG_ERROR([No size found for $2])
   fi
 ])
 AC_DEFINE_UNQUOTED($1, [$moz_cv_size_of_$1])
@@ -119,17 +119,17 @@ AC_CACHE_CHECK([for the alignment of $2]
   moz_cv_align_of_$1=
   for align in $3; do
     AC_TRY_COMPILE([
                      #include <stddef.h>
                      struct aligner { char c; $2 a; };
                    ],
                    [
                      int a[offsetof(struct aligner, a) == $align ? 1 : -1];
-                     return;
+                     return 0;
                    ],
                    [moz_cv_align_of_$1=$align; break], [])
   done
   if test ! "$moz_cv_align_of_$1"; then
     AC_MSG_ERROR([No alignment found for $2])
   fi
 ])
 AC_DEFINE_UNQUOTED($1, [$moz_cv_align_of_$1])
--- a/build/mobile/devicemanager.py
+++ b/build/mobile/devicemanager.py
@@ -14,17 +14,18 @@
 # The Original Code is Test Automation Framework.
 #
 # The Initial Developer of the Original Code is Joel Maher.
 #
 # Portions created by the Initial Developer are Copyright (C) 2009
 # the Initial Developer. All Rights Reserved.
 #
 # Contributor(s):
-# Joel Maher <joel.maher@gmail.com> (Original Developer)
+#   Joel Maher <joel.maher@gmail.com> (Original Developer)
+#   Clint Talbert <cmtalbert@gmail.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
@@ -59,30 +60,68 @@ class DeviceManager:
   port = 0
   debug = 3
   _redo = False
   deviceRoot = None
   tempRoot = os.getcwd()
   base_prompt = '\$\>'
   prompt_sep = '\x00'
   prompt_regex = '.*' + base_prompt + prompt_sep
+  agentErrorRE = re.compile('^##AGENT-ERROR##.*')
 
-  def __init__(self, host, port = 27020):
+  def __init__(self, host, port = 20701):
     self.host = host
     self.port = port
     self._sock = None
     self.getDeviceRoot()
 
-  def sendCMD(self, cmdline, newline = True, sleep = 0):
-    promptre = re.compile(self.prompt_regex + '$')
+  def cmdNeedsResponse(self, cmd):
+    """ Not all commands need a response from the agent:
+        * if the cmd matches the pushRE then it is the first half of push
+          and therefore we want to wait until the second half before looking
+          for a response
+        * rebt obviously doesn't get a response
+        * uninstall performs a reboot to ensure starting in a clean state and
+          so also doesn't look for a response
+    """
+    noResponseCmds = [re.compile('^push .*$'),
+                      re.compile('^rebt'),
+                      re.compile('^uninst .*$')]
+
+    for c in noResponseCmds:
+      if (c.match(cmd)):
+        return False
+    
+    # If the command is not in our list, then it gets a response
+    return True
 
-    # TODO: any commands that don't output anything and quit need to match this RE
-    pushre = re.compile('^push .*$')
+  def shouldCmdCloseSocket(self, cmd):
+    """ Some commands need to close the socket after they are sent:
+    * push
+    * rebt
+    * uninst
+    * quit
+    """
+    
+    socketClosingCmds = [re.compile('^push .*$'),
+                         re.compile('^quit.*'),
+                         re.compile('^rebt.*'),
+                         re.compile('^uninst .*$')]
+
+    for c in socketClosingCmds:
+      if (c.match(cmd)):
+        return True
+
+    return False
+
+  def sendCMD(self, cmdline, newline = True):
+    promptre = re.compile(self.prompt_regex + '$')
     data = ""
-    noQuit = False
+    shouldCloseSocket = False
+    recvGuard = 1000
 
     if (self._sock == None):
       try:
         if (self.debug >= 1):
           print "reconnecting socket"
         self._sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
       except:
         self._redo = True
@@ -96,53 +135,73 @@ class DeviceManager:
         self._sock.recv(1024)
       except:
         self._redo = True
         self._sock.close()
         self._sock = None
         if (self.debug >= 2):
           print "unable to connect socket"
         return None
-      
+    
     for cmd in cmdline:
-      if (cmd == 'quit'): break
       if newline: cmd += '\r\n'
       
       try:
-        self._sock.send(cmd)
+        numbytes = self._sock.send(cmd)
+        if (numbytes != len(cmd)):
+          print "ERROR: our cmd was " + str(len(cmd)) + " bytes and we only sent " + str(numbytes)
+          return None
         if (self.debug >= 4): print "send cmd: " + str(cmd)
       except:
         self._redo = True
         self._sock.close()
         self._sock = None
         return None
       
-      if (pushre.match(cmd) or cmd == 'rebt'):
-        noQuit = True
-      elif noQuit == False:
-        time.sleep(int(sleep))
+      # Check if the command should close the socket
+      shouldCloseSocket = self.shouldCmdCloseSocket(cmd)
+
+      # Handle responses from commands
+      if (self.cmdNeedsResponse(cmd)):
         found = False
-        while (found == False):
+        loopguard = 0
+        # TODO: We had an old sleep here but we don't need it
+
+        while (found == False and (loopguard < recvGuard)):
           if (self.debug >= 4): print "recv'ing..."
-          
+
+          # Get our response
           try:
             temp = self._sock.recv(1024)
+            if (self.debug >= 4): print "response: " + str(temp)
           except:
             self._redo = True
             self._sock.close()
             self._sock = None
             return None
+
+          # If something goes wrong in the agent it will send back a string that
+          # starts with '##AGENT-ERROR##'
+          if (self.agentErrorRE.match(temp)):
+            data = temp
+            break
+
           lines = temp.split('\n')
+
           for line in lines:
             if (promptre.match(line)):
               found = True
           data += temp
 
-    time.sleep(int(sleep))
-    if (noQuit == True):
+          # If we violently lose the connection to the device, this loop tends to spin,
+          # this guard prevents that
+          loopguard = loopguard + 1
+
+    # TODO: We had an old sleep here but we don't need it
+    if (shouldCloseSocket == True):
       try:
         self._sock.close()
         self._sock = None
       except:
         self._redo = True
         self._sock = None
         return None
 
@@ -175,38 +234,49 @@ class DeviceManager:
       return ''
 
     if self.mkDirs(destname) == None:
       print "unable to make dirs: " + destname
       return None
 
     if (self.debug >= 2): print "sending: push " + destname
     
-    # sleep 5 seconds / MB
     filesize = os.path.getsize(localname)
-    sleepsize = 1024 * 1024
-    sleepTime = (int(filesize / sleepsize) * 5) + 2
     f = open(localname, 'rb')
     data = f.read()
     f.close()
-    retVal = self.sendCMD(['push ' + destname + '\r\n', data], newline = False, sleep = sleepTime)
-    if (retVal == None):
-      if (self.debug >= 2): print "Error in sendCMD, not validating push"
-      return None
+    retVal = self.sendCMD(['push ' + destname + ' ' + str(filesize) + '\r\n', data], newline = False)
+    
+    if (self.debug >= 3): print "push returned: " + str(retVal)
 
-    if (self.validateFile(destname, localname) == False):
-      if (self.debug >= 2): print "file did not copy as expected"
+    validated = False
+    if (retVal):
+      retline = self.stripPrompt(retVal).strip() 
+      if (retline == None or self.agentErrorRE.match(retVal)):
+        # Then we failed to get back a hash from agent, try manual validation
+        validated = self.validateFile(destname, localname)
+      else:
+        # Then we obtained a hash from push
+        localHash = self.getLocalHash(localname)
+        if (str(localHash) == str(retline)):
+          validated = True
+    else:
+      # We got nothing back from sendCMD, try manual validation
+      validated = self.validateFile(destname, localname)
+
+    if (validated):
+      if (self.debug >= 2): print "Push File Validated!"
+      return True
+    else:
+      if (self.debug >= 2): print "Push File Failed to Validate!"
       return None
-
-    return retVal
   
   def mkDir(self, name):
     return self.sendCMD(['mkdr ' + name])
   
-  
   # make directory structure on the device
   def mkDirs(self, filename):
     parts = filename.split('/')
     name = ""
     for part in parts:
       if (part == parts[-1]): break
       if (part != ""):
         name += '/' + part
@@ -220,28 +290,25 @@ class DeviceManager:
     if (self.debug >= 2): print "pushing directory: " + localDir + " to " + remoteDir
     for root, dirs, files in os.walk(localDir):
       parts = root.split(localDir)
       for file in files:
         remoteRoot = remoteDir + '/' + parts[1]
         remoteName = remoteRoot + '/' + file
         if (parts[1] == ""): remoteRoot = remoteDir
         if (self.pushFile(os.path.join(root, file), remoteName) == None):
-          time.sleep(5)
           self.removeFile(remoteName)
-          time.sleep(5)
           if (self.pushFile(os.path.join(root, file), remoteName) == None):
             return None
     return True
 
-
   def dirExists(self, dirname):
     match = ".*" + dirname + "$"
     dirre = re.compile(match)
-    data = self.sendCMD(['cd ' + dirname, 'cwd', 'quit'], sleep = 1)
+    data = self.sendCMD(['cd ' + dirname, 'cwd'])
     if (data == None):
       return None
     retVal = self.stripPrompt(data)
     data = retVal.split('\n')
     found = False
     for d in data:
       if (dirre.match(d)): 
         found = True
@@ -258,34 +325,32 @@ class DeviceManager:
       if (f == s[-1]):
         return True
     return False
 
   # list files on the device, requires cd to directory first
   def listFiles(self, rootdir):
     if (self.dirExists(rootdir) == False):
       return []  
-    data = self.sendCMD(['cd ' + rootdir, 'ls', 'quit'], sleep=1)
+    data = self.sendCMD(['cd ' + rootdir, 'ls'])
     if (data == None):
       return None
     retVal = self.stripPrompt(data)
     return retVal.split('\n')
 
   def removeFile(self, filename):
     if (self.debug>= 2): print "removing file: " + filename
-    return self.sendCMD(['rm ' + filename, 'quit'])
-  
-  
+    return self.sendCMD(['rm ' + filename])
+    
   # does a recursive delete of directory on the device: rm -Rf remoteDir
   def removeDir(self, remoteDir):
-    self.sendCMD(['rmdr ' + remoteDir], sleep = 5)
-
+    self.sendCMD(['rmdr ' + remoteDir])
 
   def getProcessList(self):
-    data = self.sendCMD(['ps'], sleep = 3)
+    data = self.sendCMD(['ps'])
     if (data == None):
       return None
       
     retVal = self.stripPrompt(data)
     lines = retVal.split('\n')
     files = []
     for line in lines:
       if (line.strip() != ''):
@@ -293,17 +358,17 @@ class DeviceManager:
         if (len(pidproc) == 2):
           files += [[pidproc[0], pidproc[1]]]
         elif (len(pidproc) == 3):
           #android returns <userID> <procID> <procName>
           files += [[pidproc[1], pidproc[2], pidproc[0]]]     
     return files
 
   def getMemInfo(self):
-    data = self.sendCMD(['mems', 'quit'])
+    data = self.sendCMD(['mems'])
     if (data == None):
       return None
     retVal = self.stripPrompt(data)
     # TODO: this is hardcoded for now
     fhandle = open("memlog.txt", 'a')
     fhandle.write("\n")
     fhandle.write(retVal)
     fhandle.close()
@@ -355,18 +420,16 @@ class DeviceManager:
     try:
       if (self.processExist(process) == None):
         return None
       return 1
     except:
       return None
     return 1
   
-
-
   # iterates process list and returns pid if exists, otherwise ''
   def processExist(self, appname):
     pid = ''
   
     pieces = appname.split(' ')
     parts = pieces[0].split('/')
     app = parts[-1]
     procre = re.compile('.*' + app + '.*')
@@ -376,47 +439,44 @@ class DeviceManager:
       return None
       
     for proc in procList:
       if (procre.match(proc[1])):
         pid = proc[0]
         break
     return pid
 
-
   def killProcess(self, appname):
     if (self.sendCMD(['kill ' + appname]) == None):
       return None
 
     return True
 
   def getTempDir(self):
     retVal = ''
-    data = self.sendCMD(['tmpd', 'quit'])
+    data = self.sendCMD(['tmpd'])
     if (data == None):
       return None
     return self.stripPrompt(data).strip('\n')
-
   
   # copy file from device (remoteFile) to host (localFile)
   def getFile(self, remoteFile, localFile = ''):
     if localFile == '':
         localFile = os.path.join(self.tempRoot, "temp.txt")
   
     promptre = re.compile(self.prompt_regex + '.*')
-    data = self.sendCMD(['cat ' + remoteFile, 'quit'], sleep = 5)
+    data = self.sendCMD(['cat ' + remoteFile])
     if (data == None):
       return None
     retVal = self.stripPrompt(data)
     fhandle = open(localFile, 'wb')
     fhandle.write(retVal)
     fhandle.close()
     return retVal
-  
-  
+    
   # copy directory structure from device (remoteDir) to host (localDir)
   def getDirectory(self, remoteDir, localDir):
     if (self.debug >= 2): print "getting files in '" + remoteDir + "'"
     filelist = self.listFiles(remoteDir)
     if (filelist == None):
       return None
     if (self.debug >= 3): print filelist
     if not os.path.exists(localDir):
@@ -427,40 +487,37 @@ class DeviceManager:
     for f in filelist:
       if (isFile.match(f)):
         if (self.getFile(remoteDir + '/' + f, os.path.join(localDir, f)) == None):
           return None
       else:
         if (self.getDirectory(remoteDir + '/' + f, os.path.join(localDir, f)) == None):
           return None
 
-
   # true/false check if the two files have the same md5 sum
   def validateFile(self, remoteFile, localFile):
     remoteHash = self.getRemoteHash(remoteFile)
     localHash = self.getLocalHash(localFile)
 
     if (remoteHash == localHash):
         return True
 
     return False
-
   
   # return the md5 sum of a remote file
   def getRemoteHash(self, filename):
-      data = self.sendCMD(['hash ' + filename, 'quit'], sleep = 1)
+      data = self.sendCMD(['hash ' + filename])
       if (data == None):
           return ''
       retVal = self.stripPrompt(data)
       if (retVal != None):
         retVal = retVal.strip('\n')
       if (self.debug >= 3): print "remote hash returned: '" + retVal + "'"
       return retVal
     
-
   # return the md5 sum of a file on the host
   def getLocalHash(self, filename):
       file = open(filename, 'rb')
       if (file == None):
           return None
 
       try:
         mdsum = hashlib.md5()
@@ -487,17 +544,17 @@ class DeviceManager:
   # /tests
   #       /<fennec>|<firefox>  --> approot
   #       /profile
   #       /xpcshell
   #       /reftest
   #       /mochitest
   def getDeviceRoot(self):
     if (not self.deviceRoot):
-      data = self.sendCMD(['testroot'], sleep = 1)
+      data = self.sendCMD(['testroot'])
       if (data == None):
         return '/tests'
       self.deviceRoot = self.stripPrompt(data).strip('\n') + '/tests'
 
     if (not self.dirExists(self.deviceRoot)):
       self.mkDir(self.deviceRoot)
 
     return self.deviceRoot
@@ -545,17 +602,16 @@ class DeviceManager:
       dir = '/' + filename
     elif self.fileExists(self.getDeviceRoot() + '/' + filename):
       dir = self.getDeviceRoot() + '/' + filename
     else:
       return None
 
     return self.sendCMD(['cd ' + dir, 'unzp ' + filename])
 
-
   def reboot(self, wait = False):
     self.sendCMD(['rebt'])
 
     if wait == True:
       time.sleep(30)
       timeout = 270
       done = False
       while (not done):
@@ -577,75 +633,86 @@ class DeviceManager:
         remoteRoot = remoteDir + '/' + parts[1]
         remoteRoot = remoteRoot.replace('/', '/')
         if (parts[1] == ""): remoteRoot = remoteDir
         remoteName = remoteRoot + '/' + file
         if (self.validateFile(remoteName, os.path.join(root, file)) <> True):
             return None
     return True
 
-  #TODO: make this simpler by doing a single directive at a time
   # Returns information about the device:
   # Directive indicates the information you want to get, your choices are:
   # os - name of the os
   # id - unique id of the device
   # uptime - uptime of the device
   # systime - system time of the device
   # screen - screen resolution
   # memory - memory stats
   # process - list of running processes (same as ps)
   # disk - total, free, available bytes on disk
   # power - power status (charge, battery temp)
-  # all - all of them
-  def getInfo(self, directive):
+  # all - all of them - or call it with no parameters to get all the information
+  def getInfo(self, directive=None):
     data = None
-    if (directive in ('os','id','uptime','systime','screen','memory','process',
-                      'disk','power')):
-      data = self.sendCMD(['info ' + directive, 'quit'], sleep = 1)
-    else:
-      directive = None
-      data = self.sendCMD(['info', 'quit'], sleep = 1)
+    result = {}
+    collapseSpaces = re.compile('  +')
 
-    if (data is None):
-      return None
-      
-    data = self.stripPrompt(data)
-    result = {}
-        
-    if directive:
-      result[directive] = data.split('\n')
-      for i in range(len(result[directive])):
-        if (len(result[directive][i]) != 0):
-          result[directive][i] = result[directive][i].strip()
-
-      # Get rid of any empty attributes
-      result[directive].remove('')
+    directives = ['os', 'id','uptime','systime','screen','memory','process',
+                  'disk','power']
+    if (directive in directives):
+      directives = [directive]
 
-    else:
-      lines = data.split('\n')
-      result['id'] = lines[0]
-      result['os'] = lines[1]
-      result['systime'] = lines[2]
-      result['uptime'] = lines[3]
-      result['screen'] = lines[4]
-      result['memory'] = lines[5]
-      if (lines[6] == 'Power status'):
-        tmp = []
-        for i in range(4):
-          tmp.append(line[7 + i])
-        result['power'] = tmp
-      tmp = []
+    for d in directives:
+      data = self.sendCMD(['info ' + d])
+      if (data is None):
+        continue
+      data = self.stripPrompt(data)
+      data = collapseSpaces.sub(' ', data)
+      result[d] = data.split('\n')
 
-      # Linenum is the line where the process list begins
-      linenum = 11
-      for j in range(len(lines) - linenum):
-        if (lines[j + linenum].strip() != ''):
-          procline = lines[j + linenum].split('\t')
+    # Get rid of any 0 length members of the arrays
+    for v in result.itervalues():
+      while '' in v:
+        v.remove('')
+    
+    # Format the process output
+    if 'process' in result:
+      proclist = []
+      for l in result['process']:
+        if l:
+          proclist.append(l.split('\t'))
+      result['process'] = proclist
 
-          if len(procline) == 2:
-            tmp.append([procline[0], procline[1]])
-          elif len(procline) == 3:
-            # Android has <userid> <procid> <procname>
-            # We put the userid to achieve a common format
-            tmp.append([procline[1], procline[2], procline[0]])
-      result['process'] = tmp
+    print "results: " + str(result)
     return result
 
+  """
+  Installs the application onto the device
+  Application bundle - path to the application bundle on the device
+  Destination - destination directory of where application should be
+                installed to (optional)
+  Returns True or False depending on what we get back
+  TODO: we need a real way to know if this works or not
+  """
+  def installApp(self, appBundlePath, destPath=None):
+    cmd = 'inst ' + appBundlePath
+    if destPath:
+      cmd += ' ' + destPath
+    data = self.sendCMD([cmd])
+    if (data is None):
+      return False
+    else:
+      return True
+
+  """
+  Uninstalls the named application from device and causes a reboot.
+  Takes an optional argument of installation path - the path to where the application
+  was installed.
+  Returns True, but it doesn't mean anything other than the command was sent,
+  the reboot happens and we don't know if this succeeds or not.
+  """
+  def uninstallAppAndReboot(self, appName, installPath=None):
+    cmd = 'uninst ' + appName
+    if installPath:
+      cmd += ' ' + installPath
+    self.sendCMD([cmd])
+    return True
+
--- a/build/mobile/sutagent/android/ASMozStub.java
+++ b/build/mobile/sutagent/android/ASMozStub.java
@@ -34,78 +34,81 @@
  * 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.app.NotificationManager;
+import android.content.Context;
 import android.content.Intent;
 // import android.os.Binder;
+import android.os.Handler;
 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;
+	private ServerSocket cmdChnl = null;
+	private ServerSocket dataChnl = null;
+	private Handler handler = new Handler();
+	RunCmdThread runCmdThrd = null;
+	RunDataThread runDataThrd = null;
+	Thread monitor = null;
+	Timer timer = 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 = new RunCmdThread(cmdChnl, this, handler);
 			runCmdThrd.start();
 			Toast.makeText(this, "Command channel port 20701 ...", Toast.LENGTH_LONG).show();
 			
 			dataChnl = new ServerSocket(20700);
-			runDataThrd = new RunDataThread(dataChnl);
+			runDataThrd = new RunDataThread(dataChnl, this);
 			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();
 			}
 		
+		NotificationManager notificationManager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
+		notificationManager.cancel(1959);
+		
 		Toast.makeText(this, "Listener Service destroyed...", Toast.LENGTH_LONG).show();
+		
+		System.exit(0);
 		}
-
 }
--- a/build/mobile/sutagent/android/AlertLooperThread.java
+++ b/build/mobile/sutagent/android/AlertLooperThread.java
@@ -30,29 +30,37 @@
  * 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;
+package com.mozilla.SUTAgentAndroid.service;
 
 import java.util.Timer;
+
+import android.content.ContextWrapper;
 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;
+	private ContextWrapper contextWrapper = null;
+	
+	AlertLooperThread(ContextWrapper ctxW)
+		{
+		this.contextWrapper = ctxW;
+		}
 	
 	public Timer getAlertTimer()
 		{
 		return alertTimer;
 		}
 
 	public void term()
 		{
@@ -76,13 +84,13 @@ class AlertLooperThread extends Thread
     		{
 			public void handleMessage(Message msg)
         		{
 				// process incoming messages here
         		}
     		};
       
     	alertTimer = new Timer();
-    	da = new DoAlert();
+    	da = new DoAlert(contextWrapper);
     	alertTimer.scheduleAtFixedRate(da, 0, 5000);
     	Looper.loop();
 		}
 	}
--- a/build/mobile/sutagent/android/AndroidManifest.xml
+++ b/build/mobile/sutagent/android/AndroidManifest.xml
@@ -49,9 +49,14 @@
 <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>
 
 
 
+
+<uses-permission android:name="android.permission.STATUS_BAR"></uses-permission>
+
+<uses-permission android:name="android.permission.VIBRATE"></uses-permission>
+
 </manifest> 
\ No newline at end of file
--- a/build/mobile/sutagent/android/CmdWorkerThread.java
+++ b/build/mobile/sutagent/android/CmdWorkerThread.java
@@ -30,26 +30,28 @@
  * 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;
+package com.mozilla.SUTAgentAndroid.service;
 
 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 com.mozilla.SUTAgentAndroid.DoCommand;
+
 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)
@@ -96,37 +98,16 @@ public class CmdWorkerThread extends Thr
 				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();
 			}
 		
@@ -134,88 +115,85 @@ public class CmdWorkerThread extends Thr
 			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(theParent.svc);
+
+			int nAvail = cmdIn.available();
+			cmdIn.skip(nAvail);
+				
+			out.print(prompt);
+			out.flush();
+
+			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))
 					{
-					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)
+					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
-						inputLine = "";
-					
-					if ((inputLine += readLine(in)) != null)
+						out.print(prompt);
+					out.flush();
+					if (outputLine.equals("exit"))
+						{
+						theParent.StopListening();
+						bListening = false;
+						}
+					if (outputLine.equals("quit"))
 						{
-						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();
+						bListening = false;
 						}
-					else
-						break;
+					outputLine = null;
+					System.gc();
 					}
-				out.close();
-				out = null;
-				in.close();
-				in = null;
-				socket.close();
+				else
+					break;
 				}
-			}
-		catch (IOException e) {
-			// TODO Auto-generated catch block
-			e.printStackTrace();
-			}
+			out.close();
+			out = null;
+			in.close();
+			in = null;
+			socket.close();
 		}
-
+	catch (IOException e)
+		{
+		// TODO Auto-generated catch block
+		e.printStackTrace();
+		}
+	}
 }
--- a/build/mobile/sutagent/android/DataWorkerThread.java
+++ b/build/mobile/sutagent/android/DataWorkerThread.java
@@ -30,28 +30,31 @@
  * 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;
+package com.mozilla.SUTAgentAndroid.service;
 
 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;
 
+// import com.mozilla.SUTAgentAndroid.DoCommand;
+import com.mozilla.SUTAgentAndroid.SUTAgentAndroid;
+
 public class DataWorkerThread extends Thread
 {
 	private RunDataThread theParent = null;
 	private Socket socket	= null;
 	boolean bListening	= true;
 
 	public DataWorkerThread(RunDataThread theParent, Socket workerSocket)
 		{
@@ -120,41 +123,52 @@ public class DataWorkerThread extends Th
 			sRet = null;
 	
 		return(sRet);
 		}
 
 	public void run()
 		{
 		String	sRet = "";
+		long lEndTime = System.currentTimeMillis() + 60000;
 		
 		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();
+				DoCommand dc = new DoCommand(theParent.svc);
 				
 	    		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 (System.currentTimeMillis() > lEndTime)
+						{
+						cal = Calendar.getInstance();
+			    		sRet = sdf.format(cal.getTime());
+			    		sRet += " Thump thump - " + SUTAgentAndroid.sUniqueID + "\r\n";
+
+			    		out.write(sRet);
+			    		out.flush();
+						
+						lEndTime = System.currentTimeMillis() + 60000;
+						}
+					
 					if (!(in.available() > 0))
 						{
 						socket.setSoTimeout(500);
 						try {
 							int nRead = cmdIn.read();
 							if (nRead == -1)
 								{
 								bListening = false;
@@ -176,25 +190,31 @@ public class DataWorkerThread extends Th
 						outputLine = dc.processCommand(inputLine, out, in, cmdOut);
 						out.print(outputLine + "\n");
 						out.flush();
 						if (outputLine.equals("exit"))
 							{
 							theParent.StopListening();
 							bListening = false;
 							}
+						if (outputLine.equals("quit"))
+							{
+							bListening = false;
+							}
+						outputLine = null;
+						System.gc();
 						}
 					else
 						break;
 					}
 				
-				((SUTAgentAndroid)SUTAgentAndroid.me).StopHeartBeat();
-
 				out.close();
+				out = null;
 				in.close();
+				in = null;
 				socket.close();
 				}
 			}
 		catch (IOException e)
 			{
 			// TODO Auto-generated catch block
 			e.printStackTrace();
 			}
--- a/build/mobile/sutagent/android/DoAlert.java
+++ b/build/mobile/sutagent/android/DoAlert.java
@@ -30,34 +30,35 @@
  * 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;
+package com.mozilla.SUTAgentAndroid.service;
 
 import java.util.TimerTask;
 
 import android.content.Context;
+import android.content.ContextWrapper;
 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()
+	DoAlert(ContextWrapper contextWrapper)
 		{
-		Context	ctx = SUTAgentAndroid.me.getApplication().getApplicationContext();
+		Context	ctx = contextWrapper.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)
 			{
--- a/build/mobile/sutagent/android/DoCommand.java
+++ b/build/mobile/sutagent/android/DoCommand.java
@@ -30,17 +30,17 @@
  * 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;
+package com.mozilla.SUTAgentAndroid.service;
 
 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;
@@ -76,16 +76,18 @@ import org.apache.commons.net.ftp.FTPFil
 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 com.mozilla.SUTAgentAndroid.SUTAgentAndroid;
+
 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;
@@ -93,28 +95,30 @@ 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;
+import android.view.WindowManager;
 
 public class DoCommand {
 	
 	String lineSep = System.getProperty("line.separator");
 	Process	pProc;
 	OutputStream sutIn;
 	InputStream	sutErr;
 	InputStream	sutOut;
-//	Timer alertTimer = null;
 	AlertLooperThread alrt = null;
+	ContextWrapper	contextWrapper = null;
 	
 	String	currentDir = "/";
+	String	sErrorPrefix = "##AGENT-ERROR## ";
 	
 	public enum Command
 		{
 		RUN ("run"),
 		EXEC ("exec"),
 		ARUN ("arun"),
 		KILL ("kill"),
 		PS ("ps"),
@@ -179,17 +183,21 @@ public class DoCommand {
 					retCmd = cmd;
 					break;
 					}
 				}
 			return (retCmd);
 			}
 		}
 	
-//	public String processCommand(String theCmdLine, PrintWriter out, BufferedReader in, OutputStream cmdOut, InputStream cmdIn)
+	public DoCommand(ContextWrapper service)
+		{
+		this.contextWrapper = service;
+		}
+	
 	public String processCommand(String theCmdLine, PrintWriter out, BufferedInputStream in, OutputStream cmdOut)
 		{
 		String 	strReturn = "";
 		Command	cCmd = null;
 		Command cSubCmd = null;
 		
 		String [] Argv = parseCmdLine(theCmdLine);
 		
@@ -208,39 +216,39 @@ public class DoCommand {
 					e.printStackTrace();
 					}
 				break;
 				
 			case CD:
 				if (Argc == 2)
 					strReturn = changeDir(Argv[1]);
 				else
-					strReturn = "Wrong number of arguments for cd command!";
+					strReturn = sErrorPrefix + "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!";
+					strReturn = sErrorPrefix + "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!";
+					strReturn = sErrorPrefix + "Wrong number of arguments for dead command!";
 				break;
 				
 			case PS:
 				strReturn = GetProcessInfo();
 				break;
 				
 			case PUSH:
 				if (Argc == 3)
@@ -254,48 +262,48 @@ public class DoCommand {
 				    catch (NumberFormatException nfe)
 				    	{
 				        System.out.println("NumberFormatException: " + nfe.getMessage());
 				    	}
 					
 					strReturn = Push(Argv[1], in, lArg);
 					}
 				else
-					strReturn = "Wrong number of arguments for push command!";
+					strReturn = sErrorPrefix + "Wrong number of arguments for push command!";
 				break;
 				
 			case INST:
-				if (Argc == 2)
+				if (Argc >= 2)
 					strReturn = InstallApp(Argv[1], cmdOut);
 				else
-					strReturn = "Wrong number of arguments for inst command!";
+					strReturn = sErrorPrefix + "Wrong number of arguments for inst command!";
 				break;
 				
 			case UNINST:
-				if (Argc == 2)
+				if (Argc >= 2)
 					strReturn = UnInstallApp(Argv[1], cmdOut);
 				else
-					strReturn = "Wrong number of arguments for inst command!";
+					strReturn = sErrorPrefix + "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!";
+					strReturn = sErrorPrefix + "Wrong number of arguments for alrt command!";
 					}
 				break;
 				
 			case REBT:
 //				try {
 //					reboot(null);
 //					Power.reboot(null);
 //					Power.shutdown();
@@ -373,94 +381,94 @@ public class DoCommand {
 						}
 					}
 				break;
 				
 			case STAT:
 				if (Argc == 2)
 					strReturn = StatProcess(Argv[1]);
 				else
-					strReturn = "Wrong number of arguments for ping command!";
+					strReturn = sErrorPrefix + "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!";
+					strReturn = sErrorPrefix + "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!";
+					strReturn = sErrorPrefix + "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!";
+					strReturn = sErrorPrefix + "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!";
+					strReturn = sErrorPrefix + "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!";
+					strReturn = sErrorPrefix + "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!";
+					strReturn = sErrorPrefix + "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!";
+					strReturn = sErrorPrefix + "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!";
+					strReturn = sErrorPrefix + "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!";
+					strReturn = sErrorPrefix + "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!";
+					strReturn = sErrorPrefix + "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!";
+					strReturn = sErrorPrefix + "Wrong number of arguments for cp command!";
 				break;
 				
 			case QUIT:
 			case EXIT:
 				strReturn = Argv[0];
 				break;
 				
 			case TEST:
@@ -634,27 +642,27 @@ public class DoCommand {
 				
 					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!";
+					strReturn = sErrorPrefix + "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!";
+					strReturn = sErrorPrefix + "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] : ""));
@@ -664,17 +672,17 @@ public class DoCommand {
 				strReturn = Zip(Argv[1], (Argc == 3 ? Argv[2] : ""));
 				break;
 				
 			case HELP:
 				strReturn = PrintUsage();
 				break;
 				
 			default:
-				strReturn = "[" + Argv[0] + "] command";
+				strReturn = sErrorPrefix + "[" + Argv[0] + "] command";
 				if (Argc > 1)
 					{
 					strReturn += " with arg(s) =";
 					for (int lcv = 1; lcv < Argc; lcv++)
 						{
 						strReturn += " [" + Argv[lcv] + "]";
 						}
 					}
@@ -757,17 +765,17 @@ public class DoCommand {
 			if (rt != null)
 				rt.play();
 			}
 		}
 */
 	public void StartAlert()
 		{
 		// start the alert message
-		alrt = new AlertLooperThread();
+		alrt = new AlertLooperThread(this.contextWrapper);
 		alrt.start();
 		}
 
 	public void StopAlert()
 		{
 		if (alrt == null)
 			return;
 		
@@ -1023,54 +1031,53 @@ public class DoCommand {
 			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();
+					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;
+					// if we aren't just creating a directory
+					if (dstFileName.lastIndexOf('/') != (dstFileName.length() - 1))
+						{
+						// write out the file
+						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;
+						}
 					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";
 			}
@@ -1080,17 +1087,18 @@ public class DoCommand {
 			}
 		
 		return(sRet);
 		}
 	
 	public String StatProcess(String string)
 		{
 		String sRet = "";
-		ActivityManager aMgr = (ActivityManager) SUTAgentAndroid.me.getSystemService(Activity.ACTIVITY_SERVICE);
+//		ActivityManager aMgr = (ActivityManager) SUTAgentAndroid.me.getSystemService(Activity.ACTIVITY_SERVICE);
+		ActivityManager aMgr = (ActivityManager) contextWrapper.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";
@@ -1123,17 +1131,18 @@ public class DoCommand {
 			}
 		
 		return(sRet);
 		}
 	
 	public String GetAppRoot(String AppName)
 		{
 		String sRet = "";
-		Context ctx = SUTAgentAndroid.me.getApplicationContext();
+//		Context ctx = SUTAgentAndroid.me.getApplicationContext();
+		Context ctx = contextWrapper.getApplicationContext();
 		
 		if (ctx != null)
 			{
 			try {
 				Context appCtx = ctx.createPackageContext(AppName, 0);
 				ContextWrapper appCtxW = new ContextWrapper(appCtx);
 				sRet = appCtxW.getPackageResourcePath();
 				appCtxW = null;
@@ -1147,17 +1156,17 @@ public class DoCommand {
 				}
 			}
 		return(sRet);
 		}
 
 	public String changeDir(String newDir)
 		{
 		String	tmpDir	= fixFileName(newDir);
-		String	sRet = "Couldn't change directory to " + tmpDir;
+		String	sRet = sErrorPrefix + "Couldn't change directory to " + tmpDir;
 		
 		File tmpFile = new java.io.File(tmpDir);
 		
 		if (tmpFile.exists())
 			{
 			try {
 				currentDir = tmpFile.getCanonicalPath();
 				sRet = "";
@@ -1187,17 +1196,17 @@ public class DoCommand {
 	    	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;
+		String			sRet 		= sErrorPrefix + "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");
 			}
@@ -1215,31 +1224,31 @@ public class DoCommand {
 				}
 			srcFile.close();
 			byte [] hash = digest.digest();
 			
 			sRet = getHex(hash);
 			}
 		catch (FileNotFoundException e)
 			{
-			// TODO Auto-generated catch block
+			sRet += " file not found";
 			e.printStackTrace();
 			}
 		catch (IOException e)
 			{
-			// TODO Auto-generated catch block
+			sRet += " io exception";
 			e.printStackTrace();
 			} 
 		return(sRet);
 		}
 	
 	public String RemoveFile(String fileName)
 		{
 		String	sTmpFileName = fixFileName(fileName);
-		String	sRet = "Couldn't delete file " + sTmpFileName;
+		String	sRet = sErrorPrefix + "Couldn't delete file " + sTmpFileName;
 		
 		File f = new File(sTmpFileName);
 		
 		if (f.delete())
 			sRet = "deleted " + sTmpFileName;
 		
 		return(sRet);
 		}
@@ -1292,17 +1301,17 @@ public class DoCommand {
 				}
 			else
 				{
 				sRet += "\nUnable to delete directory " + sTmpDir;
 				}
 			}
 		else
 			{
-			sRet += sTmpDir + " is not a directory";
+			sRet += sErrorPrefix + sTmpDir + " is not a directory";
 			}
 		
 		return(sRet);
 		}
 	
 	public String PrintDir(String sDir)
 		{
 		String	sRet = "";
@@ -1327,42 +1336,42 @@ public class DoCommand {
 						}
 					}
 				else
 					sRet = "<empty>";
 				}
 			}
 		else
 			{
-			sRet = sTmpDir + " is not a directory";
+			sRet = sErrorPrefix + 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;
+		String sRet = sErrorPrefix + "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;
+		String sRet = sErrorPrefix + "Could not copy " + sTmpSrcFileName + " to " + sTmpDstFileName;
 		File destFile = null;
 		byte[] buffer = new byte [4096];
 		int	nRead = 0;
 		long lTotalRead = 0;
 		long lTotalWritten = 0;
 		
 		try 
 			{
@@ -1378,17 +1387,17 @@ public class DoCommand {
 			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 + "]";
+				sRet = sErrorPrefix + "Failed to copy " + sTmpSrcFileName + " [length = " + lTotalWritten + "] to " + sTmpDstFileName + " [length = " + lTotalRead + "]";
 			}
 		catch (FileNotFoundException e)
 			{
 			// TODO Auto-generated catch block
 			e.printStackTrace();
 			} 
 		catch (IOException e)
 			{
@@ -1406,29 +1415,29 @@ public class DoCommand {
 		File dir = new File(sTmpDir);
 		
 		if (dir.isDirectory())
 			{
 			sRet = "[" + sDir + "] " + (dir.canWrite() ? "is" : "is not") + " writable";
 			}
 		else
 			{
-			sRet = "[" + sDir + "] is not a directory";
+			sRet = sErrorPrefix + "[" + 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!";
+		String				sRet			= sErrorPrefix + "Push failed!";
 		
 		try {
 			FileOutputStream dstFile = new FileOutputStream(sTmpFileName, false);
 			while((nRead != -1) && (lRead < lSize))
 				{
 				nRead = bufIn.read(buffer);
 				if (nRead != -1)
 					{
@@ -1439,17 +1448,16 @@ public class DoCommand {
 				}
 			
 			dstFile.flush();
 			dstFile.close();
 			
 			if (lRead == lSize)
 				{
 				sRet = HashFile(sTmpFileName);
-				
 				}
 			}
 		catch (IOException e)
 			{
 			e.printStackTrace();
 			}
 		
 		buffer = null;
@@ -1457,17 +1465,17 @@ public class DoCommand {
 		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 sRet = sErrorPrefix + "FTP Get failed for " + sSrcFileName;
 		String strRet = "";
 		int	reply = 0;
 		FileOutputStream outStream = null;
 		String	sTmpDstFileName = fixFileName(sDstFileName);
 		
 		FTPClient ftp = new FTPClient();
 		try 
 			{
@@ -1549,17 +1557,17 @@ public class DoCommand {
 			e.printStackTrace();
 			}
 		return (sRet);
 	}
 	
 	public String Cat(String fileName, OutputStream out)
 		{
 		String	sTmpFileName = fixFileName(fileName);
-		String	sRet = "Could not read the file " + sTmpFileName;
+		String	sRet = sErrorPrefix + "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);
@@ -1576,67 +1584,70 @@ public class DoCommand {
 			sRet = e.toString();
 			}
 		return (sRet);
 		}
 	
 	public String MakeDir(String sDir)
 		{
 		String	sTmpDir = fixFileName(sDir);
-		String sRet = "Could not create the directory " + sTmpDir;
+		String sRet = sErrorPrefix + "Could not create the directory " + sTmpDir;
 		File dir = new File(sTmpDir);
 		
 		if (dir.mkdirs())
 			sRet = sDir + " successfully created";
 		
 		return (sRet);
 		}
-	
+	// move this to SUTAgentAndroid.java
 	public String GetScreenInfo()
 		{
 		String sRet = "";
 		DisplayMetrics metrics = new DisplayMetrics();
-		SUTAgentAndroid.me.getWindowManager().getDefaultDisplay().getMetrics(metrics);
+		WindowManager wMgr = (WindowManager) contextWrapper.getSystemService(Context.WINDOW_SERVICE);
+		wMgr.getDefaultDisplay().getMetrics(metrics);
 		sRet = "X:" + metrics.widthPixels + " Y:" + metrics.heightPixels;
 		return (sRet);
 		}
-	
+	// move this to SUTAgentAndroid.java
 	public int [] GetScreenXY()
 		{
 			int [] nRetXY = new int [2];
 			DisplayMetrics metrics = new DisplayMetrics();
-			SUTAgentAndroid.me.getWindowManager().getDefaultDisplay().getMetrics(metrics);
+			WindowManager wMgr = (WindowManager) contextWrapper.getSystemService(Context.WINDOW_SERVICE);
+			wMgr.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);
+		String sRet = sErrorPrefix + "Unable to kill " + sProcName + "\n";
+//		ActivityManager aMgr = (ActivityManager) SUTAgentAndroid.me.getSystemService(Activity.ACTIVITY_SERVICE);
+		ActivityManager aMgr = (ActivityManager) contextWrapper.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";
+				sRet = sErrorPrefix + "Failed to kill " + nPID + " " + strProcName + "\n";
 
 				theArgs[2] += " " + nPID;
 				
 				try 
 					{
 					pProc = Runtime.getRuntime().exec(theArgs);
 					RedirOutputThread outThrd = new RedirOutputThread(pProc, out);
 					outThrd.start();
@@ -1647,55 +1658,55 @@ public class DoCommand {
 					sRet = e.getMessage();
 					e.printStackTrace();
 					} 
 				catch (InterruptedException e)
 					{
 					// TODO Auto-generated catch block
 					e.printStackTrace();
 					}
-/*
-				SUTAgentAndroid.me.finishActivity(SUTAgentAndroid.START_PRG);
+
+//				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";
+					sRet = sErrorPrefix + "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);
+//		ActivityManager aMgr = (ActivityManager) SUTAgentAndroid.me.getSystemService(Activity.ACTIVITY_SERVICE);
+		ActivityManager aMgr = (ActivityManager) contextWrapper.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++)
@@ -1712,17 +1723,18 @@ public class DoCommand {
 			}
 	
 		return (bRet);
 		}
 
 	public String GetProcessInfo()
 		{
 		String sRet = "";
-		ActivityManager aMgr = (ActivityManager) SUTAgentAndroid.me.getSystemService(Activity.ACTIVITY_SERVICE);
+//		ActivityManager aMgr = (ActivityManager) SUTAgentAndroid.me.getSystemService(Activity.ACTIVITY_SERVICE);
+		ActivityManager aMgr = (ActivityManager) contextWrapper.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++)
@@ -1776,17 +1788,18 @@ public class DoCommand {
 	public String GetMemoryInfo()
 		{
 		String sRet = "PA:" + GetMemoryConfig();
 		return (sRet);
 		}
 
 	public long GetMemoryConfig()
 		{
-		ActivityManager aMgr = (ActivityManager) SUTAgentAndroid.me.getSystemService(Activity.ACTIVITY_SERVICE);
+//		ActivityManager aMgr = (ActivityManager) SUTAgentAndroid.me.getSystemService(Activity.ACTIVITY_SERVICE);
+		ActivityManager aMgr = (ActivityManager) contextWrapper.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);
 		}
 	
@@ -1801,20 +1814,22 @@ public class DoCommand {
 				{
 				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 )
 					{
+					socket.setSoTimeout(30000);
 					while (socket.isInputShutdown() == false)
 						{
 						line = in.readLine();
-						if ((line == null) || (line.contains("OK")))
+						line = line.toLowerCase();
+						if ((line == null) || (line.contains("ok")))
 							{
 							sRet += line;
 							break;
 							}
 						sRet += line;
 						}
 					}
 				out.close();
@@ -1828,16 +1843,17 @@ public class DoCommand {
 			catch (UnknownHostException e)
 				{
 				// TODO Auto-generated catch block
 				e.printStackTrace();
 				}
 			catch (IOException e)
 				{
 				// TODO Auto-generated catch block
+				sRet += "reg exception thrown";
 				e.printStackTrace();
 				}
 			}
 		return(sRet);
 		}
 	
 	public String GetInternetData(String sHost, String sPort, String sURL)
 		{
@@ -2010,17 +2026,18 @@ public class DoCommand {
 			}
 	
 		return (sRet);
 		}
 	
 	public String GetTmpDir()
 	{
 		String 	sRet = "";
-		Context ctx = SUTAgentAndroid.me.getApplicationContext();
+//		Context ctx = SUTAgentAndroid.me.getApplicationContext();
+		Context ctx = contextWrapper.getApplicationContext();
         File dir = ctx.getFilesDir();
         ctx = null;
         try {
 			sRet = dir.getCanonicalPath();
 			} 
         catch (IOException e)
         	{
 			e.printStackTrace();
@@ -2038,17 +2055,17 @@ public class DoCommand {
 			{
 			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";
+			sRet = sErrorPrefix + "[" + sTmpFileName + "] doesn't exist";
 			}
 
 		return(sRet);
 		}
 	
 	public String GetIniData(String sSection, String sKey, String sFile)
 		{
 		String sRet = "";
@@ -2279,26 +2296,26 @@ public class DoCommand {
 
 	public String StartJavaPrg(String [] sArgs)
 		{
 		String sRet = "";
 		String sArgList = "";
 		String sUrl = "";
 		String sRedirFileName = "";
 		
-		Context ctx = SUTAgentAndroid.me.getApplicationContext();
+//		Context ctx = SUTAgentAndroid.me.getApplicationContext();
+		Context ctx = contextWrapper.getApplicationContext();
 		PackageManager pm = ctx.getPackageManager();
 
 		Intent prgIntent = new Intent();
 		prgIntent.setPackage(sArgs[0]);
-//		prgIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+		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;
@@ -2352,18 +2369,19 @@ public class DoCommand {
 				}
 			}
 		else
 			prgIntent.setData(Uri.parse("about:blank"));
 
 		try 
 			{
 //			ctx.startActivity(prgIntent);
+			contextWrapper.startActivity(prgIntent);
 //			SUTAgentAndroid.me.startActivity(prgIntent);
-			SUTAgentAndroid.me.startActivityForResult(prgIntent, SUTAgentAndroid.START_PRG);
+//			SUTAgentAndroid.me.startActivityForResult(prgIntent, SUTAgentAndroid.START_PRG);
 			}
 		catch(ActivityNotFoundException anf)
 			{
 			anf.printStackTrace();
 			}
 		
 		ctx = null;
 		return (sRet);
@@ -2430,17 +2448,16 @@ public class DoCommand {
 		{
 		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" +
--- a/build/mobile/sutagent/android/R.java
+++ b/build/mobile/sutagent/android/R.java
@@ -6,17 +6,22 @@
  */
 
 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 int ateamlogo=0x7f020000;
+        public static final int ic_stat_first=0x7f020001;
+        public static final int ic_stat_neterror=0x7f020002;
+        public static final int ic_stat_second=0x7f020003;
+        public static final int ic_stat_warning=0x7f020004;
+        public static final int icon=0x7f020005;
     }
     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;
     }
--- a/build/mobile/sutagent/android/RedirOutputThread.java
+++ b/build/mobile/sutagent/android/RedirOutputThread.java
@@ -30,25 +30,23 @@
  * 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;
+package com.mozilla.SUTAgentAndroid.service;
 
 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;
 	
@@ -131,17 +129,17 @@ public class RedirOutputThread extends T
 							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();
+//				Toast.makeText(SUTAgentAndroid.me.getApplicationContext(), e.getMessage(), Toast.LENGTH_LONG).show();
 				e.printStackTrace();
 				}
 			}
 		
 		pProc.destroy();
 		buffer = null;
 		System.gc();
 		}
--- a/build/mobile/sutagent/android/RunCmdThread.java
+++ b/build/mobile/sutagent/android/RunCmdThread.java
@@ -30,59 +30,90 @@
  * 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;
+package com.mozilla.SUTAgentAndroid.service;
 
 import java.io.IOException;
+import java.io.InputStream;
 import java.net.ServerSocket;
 import java.net.Socket;
 import java.net.SocketTimeoutException;
 import java.util.ArrayList;
 import java.util.List;
 
-import android.widget.Toast;
+import com.mozilla.SUTAgentAndroid.R;
+import com.mozilla.SUTAgentAndroid.SUTAgentAndroid;
+
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Handler;
 
 public class RunCmdThread extends Thread
 	{
 	private ServerSocket SvrSocket = null;
 	private Socket socket	= null;
+	private Handler handler = null;
 	boolean bListening	= true;
+	boolean bNetError = false;
 	List<CmdWorkerThread> theWorkers = new ArrayList<CmdWorkerThread>();
-	
-	public RunCmdThread(ServerSocket socket)
+	android.app.Service	svc = null;
+
+	public RunCmdThread(ServerSocket socket, android.app.Service service, Handler handler)
 		{
 		super("RunCmdThread");
 		this.SvrSocket = socket;
+		this.svc = service;
+		this.handler = handler;
 		}
 	
 	public void StopListening()
 		{
 		bListening = false;
 		}
 	
 	public void run() {
 		try {
+			int	nIterations = 0;
+			
 			SvrSocket.setSoTimeout(5000);
 			while (bListening)
 				{
 				try 
 					{
 					socket = SvrSocket.accept();
 					CmdWorkerThread theWorker = new CmdWorkerThread(this, socket);
 					theWorker.start();
 					theWorkers.add(theWorker);
 					}
 				catch (SocketTimeoutException toe)
 					{
+					if (++nIterations > 60)
+						{
+						nIterations = 0;
+						String sRet = SendPing("www.mozilla.org");
+						if (sRet.contains("3 received"))
+							handler.post(new doCancelNotification());
+						else
+							handler.post(new doSendNotification("SUTAgent - Network Connectivity Error", sRet));
+						sRet = null;
+						}
+					continue;
+					}
+				catch (IOException e)
+					{
+					e.printStackTrace();
 					continue;
 					}
 				}
 			
 			int nNumWorkers = theWorkers.size();
 			for (int lcv = 0; lcv < nNumWorkers; lcv++)
 				{
 				if (theWorkers.get(lcv).isAlive())
@@ -92,18 +123,196 @@ public class RunCmdThread extends Thread
 						;
 					}
 				}
 			
 			theWorkers.clear();
 			
 			SvrSocket.close();
 			
-			SUTAgentAndroid.me.finish();
+			svc.stopSelf();
+			
+//			SUTAgentAndroid.me.finish();
 			} 
 		catch (IOException e)
 			{
-			Toast.makeText(SUTAgentAndroid.me.getApplicationContext(), e.getMessage(), Toast.LENGTH_LONG).show();
 		    e.printStackTrace();
 			}
 		return;
-	}
+		}
+	
+	private String SendPing(String sIPAddr)
+		{
+		Process	pProc;
+		String sRet = "";
+		String [] theArgs = new String [4];
+		boolean bStillRunning = true;
+		int	nBytesOut = 0;
+		int nBytesErr = 0;
+		int nBytesRead = 0;
+		byte[] buffer = new byte[1024];
+	
+		theArgs[0] = "ping";
+		theArgs[1] = "-c";
+		theArgs[2] = "3";
+		theArgs[3] = sIPAddr;
+	
+		try 
+			{
+			pProc = Runtime.getRuntime().exec(theArgs);
+			
+			InputStream sutOut = pProc.getInputStream();
+			InputStream sutErr = pProc.getErrorStream();
+			
+			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");
+							sRet += sRep;
+							sRep = null;
+							}
+						}
+
+					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");
+							sRet += sRep;
+							sRep = null;
+							}
+						}
+
+					bStillRunning = (IsProcRunning(pProc) || (sutOut.available() > 0) || (sutErr.available() > 0));
+					} 
+				catch (IOException e)
+					{
+					e.printStackTrace();
+					}
+				
+				if ((bStillRunning == true) && (nBytesErr == 0) && (nBytesOut == 0))
+					{
+					try {
+						sleep(2000);
+						}
+					catch (InterruptedException e) {
+						e.printStackTrace();
+						}
+					}
+				}
+
+			pProc.destroy();
+			pProc = null;
+			}
+		catch (IOException e) 
+			{
+			sRet = e.getMessage();
+			e.printStackTrace();
+			}
+
+		return (sRet);
+		}
+	
+	private boolean IsProcRunning(Process pProc)
+		{
+		boolean bRet = false;
+		@SuppressWarnings("unused")
+		int nExitCode = 0;
+
+		try
+			{
+			nExitCode = pProc.exitValue();
+			}
+		catch (IllegalThreadStateException z)
+			{	
+			bRet = true;
+			}
+		catch (Exception e)
+			{
+			e.printStackTrace();
+			}
+
+		return(bRet);
+		}
+
+	private void SendNotification(String tickerText, String expandedText)
+		{
+		NotificationManager notificationManager = (NotificationManager)svc.getSystemService(Context.NOTIFICATION_SERVICE);
+		
+//		int icon = android.R.drawable.stat_notify_more;
+//		int icon = R.drawable.ic_stat_first;
+//		int icon = R.drawable.ic_stat_second;
+//		int icon = R.drawable.ic_stat_neterror;
+		int icon = R.drawable.ateamlogo;
+		long when = System.currentTimeMillis();
+		
+		Notification notification = new Notification(icon, tickerText, when);
+		
+		notification.flags |= (Notification.FLAG_INSISTENT | Notification.FLAG_AUTO_CANCEL);
+		notification.defaults |= Notification.DEFAULT_SOUND;
+		notification.defaults |= Notification.DEFAULT_VIBRATE;
+		notification.defaults |= Notification.DEFAULT_LIGHTS;
+		
+		Context context = svc.getApplicationContext();
+		
+		// Intent to launch an activity when the extended text is clicked
+		Intent intent2 = new Intent(svc, SUTAgentAndroid.class);
+		PendingIntent launchIntent = PendingIntent.getActivity(context, 0, intent2, 0);
+		
+		notification.setLatestEventInfo(context, tickerText, expandedText, launchIntent);
+				
+		notificationManager.notify(1959, notification);
+		}
+	
+	private void CancelNotification()
+		{
+		NotificationManager notificationManager = (NotificationManager)svc.getSystemService(Context.NOTIFICATION_SERVICE);
+		notificationManager.cancel(1959);
+		}
+	
+	class doCancelNotification implements Runnable
+		{
+		public void run()
+			{
+			CancelNotification();
+			}
+		};
+
+	class doSendNotification implements Runnable
+		{
+		private String sTitle = "";
+		private String sBText = "";
+		
+		doSendNotification(String sTitle, String sBodyText)
+			{
+			this.sTitle = sTitle;
+			this.sBText = sBodyText;
+			}
+
+		public void run() 
+			{
+			SendNotification(sTitle, sBText);
+			}
+		};
 }
--- a/build/mobile/sutagent/android/RunDataThread.java
+++ b/build/mobile/sutagent/android/RunDataThread.java
@@ -30,41 +30,41 @@
  * 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;
+package com.mozilla.SUTAgentAndroid.service;
 
 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>();
+	android.app.Service	svc = null;
 	
-	public RunDataThread(ServerSocket socket)
+	public RunDataThread(ServerSocket socket, android.app.Service service)
 		{
 		super("RunDataThread");
 		this.SvrSocket = socket;
+		this.svc = service;
 		}
 	
 	public void StopListening()
 		{
 		bListening = false;
 		}
 
 	public void run() {
@@ -94,17 +94,19 @@ public class RunDataThread extends Threa
 					while(theWorkers.get(lcv).isAlive())
 						;
 					}
 				}
 			
 			theWorkers.clear();
 			
 			SvrSocket.close();
+
+			svc.stopSelf();
 			}
 		catch (IOException e)
 			{
-			Toast.makeText(SUTAgentAndroid.me.getApplicationContext(), e.getMessage(), Toast.LENGTH_LONG).show();
+//			Toast.makeText(SUTAgentAndroid.me.getApplicationContext(), e.getMessage(), Toast.LENGTH_LONG).show();
 			e.printStackTrace();
 			}
 		return;
 		}
 	}
--- a/build/mobile/sutagent/android/SUTAgentAndroid.java
+++ b/build/mobile/sutagent/android/SUTAgentAndroid.java
@@ -37,28 +37,28 @@
 
 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 com.mozilla.SUTAgentAndroid.service.ASMozStub;
+import com.mozilla.SUTAgentAndroid.service.DoCommand;
 
 // import dalvik.system.VMRuntime;
 import android.app.Activity;
 import android.app.KeyguardManager;
 import android.bluetooth.BluetoothAdapter;
 import android.content.BroadcastReceiver;
+// import android.content.ComponentName;
 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;
@@ -73,21 +73,21 @@ 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;
+	public static final int START_PRG = 1959;
 	MenuItem mExitMenuItem;
 	Timer timer = null;
 	
-	public static SUTAgentAndroid me = 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");
@@ -99,16 +99,17 @@ public class SUTAgentAndroid extends Act
     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;
+//    private ComponentName service = null;
 
 	public boolean onCreateOptionsMenu(Menu menu)
 		{
 		mExitMenuItem = menu.add("Exit");
 		mExitMenuItem.setIcon(android.R.drawable.ic_menu_close_clear_cancel);
 		return super.onCreateOptionsMenu(menu);
 		}
 
@@ -150,34 +151,34 @@ public class SUTAgentAndroid extends Act
         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();
+        DoCommand dc = new DoCommand(getApplication());
         
         // 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();
+        	setUpNetwork(sIniFile);
         
-        me = this;
+//        me = this;
         
         WifiInfo wifi;
         WifiManager wifiMan = (WifiManager)getSystemService(Context.WIFI_SERVICE);
         String macAddress = "Unknown";
         if (wifiMan != null) 
         	{
 			wifi = wifiMan.getConnectionInfo();
 			if (wifi != null)
@@ -264,38 +265,40 @@ public class SUTAgentAndroid extends Act
         sRegString += "&HARDWARE=" + HardwareID;
         sRegString += "&POOL=" + Pool;
         
         String sTemp = Uri.encode(sRegString,"=&");
         sRegString = "register " + sTemp;
         
         if (!bNetworkingStarted)
         	{
-        	ToDoListening(1,300,dc);
+        	Thread thread = new Thread(null, doStartService, "StartServiceBkgnd");
+        	thread.start();
+//        	ToDoListening(1,300,dc);
         	bNetworkingStarted = true;
         	String sRegRet = "";
         	if (RegSvrIPAddr.length() > 0)
         		{
         		sRegRet = dc.RegisterTheDevice(RegSvrIPAddr, RegSvrIPPort, sRegString);
-        		if (sRegRet.contains("\"ok\": true"))
+        		if (sRegRet.contains("ok"))
         			{
         			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();
                 }
         	});
@@ -310,41 +313,35 @@ public class SUTAgentAndroid extends Act
     	}
     
     @Override
     public void onDestroy()
     	{
 		super.onDestroy();
     	if (isFinishing())
     		{
-    		StopHeartBeat();
-    		Intent listenerSvc = new Intent();
+    		Intent listenerSvc = new Intent(this, ASMozStub.class);
     		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)
@@ -421,23 +418,31 @@ public class SUTAgentAndroid extends Act
 				sPowerStatus = sb.toString();
 				}
 			};
 			
 		IntentFilter battFilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
 		registerReceiver(battReceiver, battFilter);
     	}
  
-    public boolean setUpNetwork()
+    public boolean setUpNetwork(String sIniFile)
     	{
     	boolean	bRet = false;
     	int	lcv	= 0;
     	int	lcv2 = 0;
     	WifiManager wifi = (WifiManager) getSystemService(Context.WIFI_SERVICE);
     	WifiConfiguration wc = new WifiConfiguration();
+    	DoCommand tmpdc = new DoCommand(getApplication());
+    	
+    	String ssid = tmpdc.GetIniData("Network Settings", "SSID", sIniFile);
+    	String auth = tmpdc.GetIniData("Network Settings", "AUTH", sIniFile);
+    	String encr = tmpdc.GetIniData("Network Settings", "ENCR", sIniFile);
+    	String key = tmpdc.GetIniData("Network Settings", "KEY", sIniFile);
+    	String eap = tmpdc.GetIniData("Network Settings", "EAP", sIniFile);
+    	String adhoc = tmpdc.GetIniData("Network Settings", "ADHOC", sIniFile);
     	
 		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;
@@ -454,37 +459,42 @@ public class SUTAgentAndroid extends Act
     	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 = "\"" + ssid + "\"";
+//    	wc.SSID = "\"Mozilla-G\"";
 //    	wc.SSID = "\"Mozilla\"";
-    	wc.preSharedKey  = null;
+		
+		if (auth.contentEquals("wpa2"))
+			{
+	    	wc.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
+			wc.preSharedKey  = null;
+			}
+		
+		if (encr.contentEquals("aes"))
+			{
+	    	wc.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
+	    	wc.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
+			}
+		
+		if (eap.contentEquals("peap"))
+			{
+	    	wc.eap.setValue("PEAP");
+	    	wc.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_EAP);
+	    	wc.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.IEEE8021X);
+			}
+		
     	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)
     		{
@@ -594,57 +604,71 @@ public class SUTAgentAndroid extends Act
     		}
     	
 		Toast.makeText(getApplication().getApplicationContext(), "Network started and configured", Toast.LENGTH_LONG).show();
     	bRet = true;
     	
     	return(bRet);
     	}
     
+    private Runnable doStartService = new Runnable()
+    	{
+    	public void run()
+    		{
+			Intent listenerService = new Intent();
+			listenerService.setAction("com.mozilla.SUTAgentAndroid.service.LISTENER_SERVICE");
+			startService(listenerService);
+//			service = startService(listenerService);
+    		}
+    	};
+/*
     class ToDoListener extends TimerTask 
     	{
     	boolean 	bFirstRun = true;
     	DoCommand	dc = null;
     	
+    	ToDoListener() {}
+    	
     	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);
+				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.scheduleAtFixedRate(new ToDoListener(dc), delay * 1000, interval * 1000);
 //		timer.schedule(new ToDoListener(dc), delay * 1000);
+		timer.schedule(new ToDoListener(), delay * 1000);
 		}
 
 	class DoHeartBeat extends TimerTask
 		{
     	PrintWriter out;
 	
     	DoHeartBeat(PrintWriter out)
 			{
@@ -681,18 +705,19 @@ public class SUTAgentAndroid extends Act
 		if (timer != null)
 			{
 			timer.cancel();
 			timer.purge();
 			timer = null;
 			System.gc();
 			}
 		}
+*/	
 	
-	public String getLocalIpAddress()
+    public String getLocalIpAddress()
 		{
 		try
     		{
 			for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements();) 
         		{
 				NetworkInterface intf = en.nextElement();
 				for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements();) 
             		{
--- a/chrome/src/nsChromeRegistryChrome.cpp
+++ b/chrome/src/nsChromeRegistryChrome.cpp
@@ -32,17 +32,17 @@
  * 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 ***** */
 
 #ifdef MOZ_IPC
-#include "mozilla/dom/PContentProcessParent.h"
+#include "mozilla/dom/PContentParent.h"
 #include "RegistryMessageUtils.h"
 #include "nsResProtocolHandler.h"
 #endif
 
 #include "nsChromeRegistryChrome.h"
 
 #if defined(XP_WIN)
 #include <windows.h>
@@ -461,17 +461,17 @@ struct EnumerationArgs
 {
   nsTArray<ChromePackage>& packages;
   const nsCString& selectedLocale;
   const nsCString& selectedSkin;
 };
 
 void
 nsChromeRegistryChrome::SendRegisteredChrome(
-    mozilla::dom::PContentProcessParent* aParent)
+    mozilla::dom::PContentParent* aParent)
 {
   nsTArray<ChromePackage> packages;
   nsTArray<ResourceMapping> resources;
   nsTArray<OverrideMapping> overrides;
 
   EnumerationArgs args = {
     packages, mSelectedLocale, mSelectedSkin
   };
--- a/chrome/src/nsChromeRegistryChrome.h
+++ b/chrome/src/nsChromeRegistryChrome.h
@@ -38,17 +38,17 @@
 
 #ifndef nsChromeRegistryChrome_h
 #define nsChromeRegistryChrome_h
 
 #include "nsChromeRegistry.h"
 
 namespace mozilla {
 namespace dom {
-class PContentProcessParent;
+class PContentParent;
 }
 }
 
 class nsIPrefBranch;
 
 class nsChromeRegistryChrome : public nsChromeRegistry
 {
  public:
@@ -71,17 +71,17 @@ class nsChromeRegistryChrome : public ns
 #ifdef MOZ_XUL
   NS_OVERRIDE NS_IMETHOD GetXULOverlays(nsIURI *aURI,
                                         nsISimpleEnumerator **_retval);
   NS_OVERRIDE NS_IMETHOD GetStyleOverlays(nsIURI *aURI,
                                           nsISimpleEnumerator **_retval);
 #endif
   
 #ifdef MOZ_IPC
-  void SendRegisteredChrome(mozilla::dom::PContentProcessParent* aChild);
+  void SendRegisteredChrome(mozilla::dom::PContentParent* aChild);
 #endif
 
  private:
 #ifdef MOZ_IPC
   static PLDHashOperator CollectPackages(PLDHashTable *table,
                                          PLDHashEntryHdr *entry,
                                          PRUint32 number, void *arg);
 #endif
--- a/config/autoconf.mk.in
+++ b/config/autoconf.mk.in
@@ -664,8 +664,9 @@ MOZ_OFFICIAL_BRANDING = @MOZ_OFFICIAL_BR
 HAVE_CLOCK_MONOTONIC = @HAVE_CLOCK_MONOTONIC@
 REALTIME_LIBS = @REALTIME_LIBS@
 
 ANDROID_NDK       = @ANDROID_NDK@
 ANDROID_TOOLCHAIN = @ANDROID_TOOLCHAIN@
 ANDROID_PLATFORM  = @ANDROID_PLATFORM@
 ANDROID_SDK       = @ANDROID_SDK@
 ANDROID_TOOLS     = @ANDROID_TOOLS@
+ANDROID_VERSION   = @ANDROID_VERSION@
--- a/config/rules.mk
+++ b/config/rules.mk
@@ -573,17 +573,17 @@ endif
 # MacOS X specific stuff
 #
 
 ifeq ($(OS_ARCH),Darwin)
 ifdef SHARED_LIBRARY
 ifdef IS_COMPONENT
 EXTRA_DSO_LDOPTS	+= -bundle
 else
-EXTRA_DSO_LDOPTS	+= -dynamiclib -install_name @executable_path/$(SHARED_LIBRARY) -compatibility_version 1 -current_version 1 -single_module
+EXTRA_DSO_LDOPTS	+= -dynamiclib -install_name @loader_path/$(SHARED_LIBRARY) -compatibility_version 1 -current_version 1 -single_module
 endif
 endif
 endif
 
 #
 # On NetBSD a.out systems, use -Bsymbolic.  This fixes what would otherwise be
 # fatal symbol name clashes between components.
 #
@@ -1199,17 +1199,17 @@ ifeq ($(OS_ARCH),OS2)
 	echo DATA    PRELOAD MOVEABLE MULTIPLE NONSHARED >> $@
 	echo EXPORTS >> $@
 ifeq ($(IS_COMPONENT),1)
 ifeq ($(HAS_EXTRAEXPORTS),1)
 ifndef MOZ_OS2_USE_DECLSPEC
 	$(FILTER) $(OBJS) $(SHARED_LIBRARY_LIBS) >> $@
 endif	
 else
-	echo    _NSGetModule >> $@
+	echo    _NSModule >> $@
 endif
 else
 ifndef MOZ_OS2_USE_DECLSPEC
 	$(FILTER) $(OBJS) $(SHARED_LIBRARY_LIBS) >> $@
 endif	
 endif
 	$(ADD_TO_DEF_FILE)
 
--- a/config/stl-headers
+++ b/config/stl-headers
@@ -22,8 +22,9 @@ deque
 iostream
 limits
 list
 map
 memory
 stack
 string
 vector
+set
--- a/configure.in
+++ b/configure.in
@@ -230,17 +230,17 @@ if test ! -z "$L10NBASEDIR"; then
     else
         AC_MSG_ERROR([Invalid value --with-l10n-base, $L10NBASEDIR doesn't exist])
     fi
 fi
 AC_SUBST(L10NBASEDIR)
 
 dnl Check for Perl first -- needed for win32 SDK checks
 MOZ_PATH_PROGS(PERL, $PERL perl5 perl )
-if test -z "$PERL" || test "$PERL" = ":"; then
+if test -z "$PERL" -o "$PERL" = ":"; then
     AC_MSG_ERROR([perl not found in \$PATH])
 fi
 
 dnl ========================================================
 dnl = Android uses a very custom (hacky) toolchain; we need to do this
 dnl = here, so that the compiler checks can succeed
 dnl ========================================================
 
@@ -249,20 +249,22 @@ MOZ_ARG_WITH_STRING(android-ndk,
                           location where the Android NDK can be found],
     android_ndk=$withval)
 
 MOZ_ARG_WITH_STRING(android-toolchain,
 [  --with-android-toolchain=DIR
                           location of the android toolchain, default NDK/build/prebuilt/HOST/arm-eabi-4.4.0],
     android_toolchain=$withval)
 
-MOZ_ARG_WITH_STRING(android-platform,
-[  --with-android-platform=DIR
-                          location of NDK platform dir, default NDK/build/platforms/android-5/arch-arm],
-    android_platform=$withval)
+
+MOZ_ARG_WITH_STRING(android-version,
+[  --with-android-version=VER
+                          android platform version, default 5],
+    android_version=$withval,
+    android_version=5)
 
 MOZ_ARG_WITH_STRING(android-sdk,
 [  --with-android-sdk=DIR
                           location where the Android SDK can be found (base directory, e.g. .../android/platforms/android-6)],
     android_sdk=$withval)
 
 MOZ_ARG_WITH_STRING(android-tools,
 [  --with-android-tools=DIR
@@ -282,17 +284,17 @@ if test "$target" = "arm-android-eabi" ;
         AC_MSG_ERROR([You must specify --with-android-tools=/path/to/sdk/tools when targeting Android.])
     fi
 
     if test -z "$android_toolchain" ; then
         android_toolchain="$android_ndk"/build/prebuilt/`uname -s | tr "[[:upper:]]" "[[:lower:]]"`-x86/arm-eabi-4.4.0
     fi
 
     if test -z "$android_platform" ; then
-       android_platform="$android_ndk"/build/platforms/android-5/arch-arm
+       android_platform="$android_ndk"/build/platforms/android-"$android_version"/arch-"$target_cpu"
     fi
 
     dnl set up compilers
     AS="$android_toolchain"/bin/arm-eabi-as
     CC="$android_toolchain"/bin/arm-eabi-gcc
     CXX="$android_toolchain"/bin/arm-eabi-g++
     CPP="$android_toolchain"/bin/arm-eabi-cpp
     LD="$android_toolchain"/bin/arm-eabi-ld
@@ -324,18 +326,21 @@ if test "$target" = "arm-android-eabi" ;
         HOST_LDFLAGS=" "
     fi
 
     ANDROID_NDK="${android_ndk}"
     ANDROID_TOOLCHAIN="{android_toolchain}"
     ANDROID_PLATFORM="{android_platform}"
     ANDROID_SDK="${android_sdk}"
     ANDROID_TOOLS="${android_tools}"
+    ANDROID_VERSION="${android_version}"
 
     AC_DEFINE(ANDROID)
+    AC_DEFINE_UNQUOTED(ANDROID_VERSION, $android_version)
+    AC_SUBST(ANDROID_VERSION)
     CROSS_COMPILE=1
     MOZ_CHROME_FILE_FORMAT=omni
 fi
 
 AC_SUBST(ANDROID_NDK)
 AC_SUBST(ANDROID_TOOLCHAIN)
 AC_SUBST(ANDROID_PLATFORM)
 AC_SUBST(ANDROID_SDK)
@@ -394,17 +399,17 @@ case "$target" in
     RC="$_pwd/dist/sdk/bin/$target-res.exe"
 
 
     echo -----------------------------------------------------------------------------
 
     ;;
 esac
 
-if test -n "$CROSS_COMPILE" && test "$target" != "$host"; then
+if test -n "$CROSS_COMPILE" -a "$target" != "$host"; then
     echo "cross compiling from $host to $target"
     cross_compiling=yes
 
     _SAVE_CC="$CC"
     _SAVE_CFLAGS="$CFLAGS"
     _SAVE_LDFLAGS="$LDFLAGS"
 
     AC_MSG_CHECKING([for host c compiler])
@@ -997,22 +1002,22 @@ if test -z "$COMPILE_ENVIRONMENT"; then
     NSINSTALL_BIN='$(PYTHON) $(topsrcdir)/config/nsinstall.py'
 fi
 AC_SUBST(NSINSTALL_BIN)
 
 MOZ_PATH_PROG(DOXYGEN, doxygen, :)
 MOZ_PATH_PROG(AUTOCONF, autoconf, :)
 MOZ_PATH_PROG(UNZIP, unzip, :)
 MOZ_PATH_PROGS(ZIP, zip)
-if test -z "$ZIP" || test "$ZIP" = ":"; then
+if test -z "$ZIP" -o "$ZIP" = ":"; then
     AC_MSG_ERROR([zip not found in \$PATH])
 fi
 MOZ_PATH_PROG(SYSTEM_MAKEDEPEND, makedepend)
 MOZ_PATH_PROG(XARGS, xargs)
-if test -z "$XARGS" || test "$XARGS" = ":"; then
+if test -z "$XARGS" -o "$XARGS" = ":"; then
     AC_MSG_ERROR([xargs not found in \$PATH .])
 fi
 
 if test "$COMPILE_ENVIRONMENT"; then
 
 dnl ========================================================
 dnl = Mac OS X toolchain support
 dnl ========================================================
@@ -1045,17 +1050,17 @@ from building Mozilla. Upgrade to Xcode 
     dnl /usr/bin/g(cc|++)-$GCC_VERSION.
     MOZ_PATH_PROGS(PBBUILD, pbbuild xcodebuild pbxbuild)
 
     case "$PBBUILD" in
       *xcodebuild*)
         changequote(,)
         XCODEBUILD_VERSION=`$PBBUILD -version 2>/dev/null | xargs | sed -e 's/.*DevToolsCore-\([0-9]*\).*/\1/'`
         changequote([,])
-        if test -n "$XCODEBUILD_VERSION" && test "$XCODEBUILD_VERSION" -ge 620 ; then
+        if test -n "$XCODEBUILD_VERSION" -a "$XCODEBUILD_VERSION" -ge 620 ; then
           HAS_XCODE_2_1=1;
         fi
       ;;
     esac
 
     dnl sdp was formerly in /Developer/Tools.  As of Mac OS X 10.4 (Darwin 8),
     dnl it has moved into /usr/bin.
     MOZ_PATH_PROG(SDP, sdp, :, [$PATH:/usr/bin:/Developer/Tools])
@@ -2059,22 +2064,16 @@ case "$target" in
 *-freebsd*)
     if test `test -x /usr/bin/objformat && /usr/bin/objformat || echo elf` != "elf"; then
 	DLL_SUFFIX=".so.1.0"
 	DSO_LDOPTS="-shared"
     fi
     if test ! "$GNU_CC"; then
 	DSO_LDOPTS="-Bshareable $DSO_LDOPTS"
     fi
-# Can't have force w/o an unforce.
-#    # Hack for FreeBSD 2.2
-#    if test -z "$MKSHLIB_FORCE_ALL"; then
-#	MKSHLIB_FORCE_ALL='-Wl,-Bforcearchive'
-#	MKSHLIB_UNFORCE_ALL=''
-#    fi
     ;; 
 
 ia64*-hpux*)
     DLL_SUFFIX=".so"
     if test ! "$GNU_CC"; then
        DSO_LDOPTS='-b'
        DSO_CFLAGS=""
        DSO_PIC_CFLAGS=
@@ -2168,22 +2167,22 @@ ia64*-hpux*)
     if test -z "$GNU_CXX"; then
       MIPSPRO_CXX=1
     fi
     ;;
 
 *-*linux*)
     # Note: both GNU_CC and INTEL_CC are set when using Intel's C compiler.
     # Similarly for GNU_CXX and INTEL_CXX.
-    if test "$INTEL_CC" || test "$INTEL_CXX"; then
+    if test "$INTEL_CC" -o "$INTEL_CXX"; then
         # -Os has been broken on Intel's C/C++ compilers for quite a
         # while; Intel recommends against using it.
         MOZ_OPTIMIZE_FLAGS="-O2"
         MOZ_DEBUG_FLAGS="-g"
-    elif test "$GNU_CC" || test "$GNU_CXX"; then
+    elif test "$GNU_CC" -o "$GNU_CXX"; then
         GCC_VERSION=`$CC -v 2>&1 | awk '/^gcc version/ { print $3 }'`
         case $GCC_VERSION in
         4.1.*|4.2.*|4.5.*)
             # -Os is broken on gcc 4.1.x 4.2.x, 4.5.x we need to tweak it to get good results.
             MOZ_OPTIMIZE_SIZE_TWEAK="-finline-limit=50"
         esac
         MOZ_OPTIMIZE_FLAGS="-Os -freorder-blocks -fomit-frame-pointer $MOZ_OPTIMIZE_SIZE_TWEAK"
         MOZ_DEBUG_FLAGS="-g"
@@ -2441,17 +2440,17 @@ ia64*-hpux*)
     case "$host" in
     *-mingw*|*-cygwin*|*-msvc*|*-mks*)
 
     if test -z "$MOZ_TOOLS"; then
         AC_MSG_ERROR([MOZ_TOOLS is not set])
     fi
 
     MOZ_TOOLS_DIR=`cd $MOZ_TOOLS && pwd -W`
-    if test "$?" != "0" || test -z "$MOZ_TOOLS_DIR"; then
+    if test "$?" != "0" -o -z "$MOZ_TOOLS_DIR"; then
         AC_MSG_ERROR([cd \$MOZ_TOOLS failed. MOZ_TOOLS ==? $MOZ_TOOLS])
     fi
     MOZ_TOOLS_BIN_DIR="$(cd "$MOZ_TOOLS_DIR/bin" && pwd)"
     if test `echo ${PATH}: | grep -ic "$MOZ_TOOLS_BINDIR:"` = 0; then
         AC_MSG_ERROR([\$MOZ_TOOLS\\bin must be in your path.])
     fi
     MOZ_TOOLS_DIR=`$CYGPATH_W $MOZ_TOOLS_DIR | $CYGPATH_S`
     ;;
@@ -2713,17 +2712,17 @@ alpha*-*-osf*)
        LIBS="-lCrun -lCstd -lc $LIBS"
        NS_USE_NATIVE=1
        AC_DEFINE(NSCAP_DISABLE_DEBUG_PTR_TYPES)
        CFLAGS="$CFLAGS -xlibmieee -xstrconst -xbuiltin=%all -D__FUNCTION__=__func__"
        CXXFLAGS="$CXXFLAGS -xlibmieee -xbuiltin=%all -features=tmplife,tmplrefstatic,extensions -norunpath -D__FUNCTION__=__func__"
        _MOZ_EXCEPTIONS_FLAGS_ON='-features=except'
        _MOZ_EXCEPTIONS_FLAGS_OFF='-features=no%except'
        LDFLAGS="-xildoff $LDFLAGS"
-       if test -z "$CROSS_COMPILE" && test -f /usr/lib/ld/map.noexstk; then
+       if test -z "$CROSS_COMPILE" -a -f /usr/lib/ld/map.noexstk; then
            _SAVE_LDFLAGS=$LDFLAGS
            LDFLAGS="-M /usr/lib/ld/map.noexstk $LDFLAGS" 
            AC_TRY_LINK([#include <stdio.h>],
                        [printf("Hello World\n");],
                        ,
                        [LDFLAGS=$_SAVE_LDFLAGS])
        fi
        WARNINGS_AS_ERRORS='-Werror'
@@ -2829,17 +2828,17 @@ dnl Any platform that doesn't have MKSHL
 dnl by now will not have any way to link most binaries (tests
 dnl as well as viewer, apprunner, etc.), because some symbols
 dnl will be left out of the "composite" .so's by ld as unneeded.
 dnl So, by defining NO_LD_ARCHIVE_FLAGS for these platforms,
 dnl they can link in the static libs that provide the missing
 dnl symbols.
 dnl ========================================================
 NO_LD_ARCHIVE_FLAGS=
-if test -z "$MKSHLIB_FORCE_ALL" || test -z "$MKSHLIB_UNFORCE_ALL"; then
+if test -z "$MKSHLIB_FORCE_ALL" -o -z "$MKSHLIB_UNFORCE_ALL"; then
     NO_LD_ARCHIVE_FLAGS=1
 fi
 case "$target" in
 *-os2*)
     NO_LD_ARCHIVE_FLAGS=
     ;;
 *-aix4.3*|*-aix5*)
     NO_LD_ARCHIVE_FLAGS=
@@ -3597,17 +3596,17 @@ then
 	dnl See if -pthread is supported.
 	dnl
 	rm -f conftest*
 	ac_cv_have_dash_pthread=no
 	AC_MSG_CHECKING(whether ${CC-cc} accepts -pthread)
 	echo 'int main() { return 0; }' | cat > conftest.c
 	${CC-cc} -pthread -o conftest conftest.c > conftest.out 2>&1
 	if test $? -eq 0; then
-		if test -z "`egrep -i '(unrecognize|unknown)' conftest.out | grep pthread`" && test -z "`egrep -i '(error|incorrect)' conftest.out`" ; then
+		if test -z "`egrep -i '(unrecognize|unknown)' conftest.out | grep pthread`" -a -z "`egrep -i '(error|incorrect)' conftest.out`" ; then
 			ac_cv_have_dash_pthread=yes
 	        case "$target_os" in
 	        freebsd*)
 # Freebsd doesn't use -pthread for compiles, it uses them for linking
                 ;;
 	        *)
 			    CFLAGS="$CFLAGS -pthread"
 			    CXXFLAGS="$CXXFLAGS -pthread"
@@ -3622,17 +3621,17 @@ then
 	dnl See if -pthreads is supported.
 	dnl
     ac_cv_have_dash_pthreads=no
     if test "$ac_cv_have_dash_pthread" = "no"; then
 	    AC_MSG_CHECKING(whether ${CC-cc} accepts -pthreads)
     	echo 'int main() { return 0; }' | cat > conftest.c
 	    ${CC-cc} -pthreads -o conftest conftest.c > conftest.out 2>&1
     	if test $? -eq 0; then
-	    	if test -z "`egrep -i '(unrecognize|unknown)' conftest.out | grep pthreads`" && test -z "`egrep -i '(error|incorrect)' conftest.out`" ; then
+	    	if test -z "`egrep -i '(unrecognize|unknown)' conftest.out | grep pthreads`" -a -z "`egrep -i '(error|incorrect)' conftest.out`" ; then
 			    ac_cv_have_dash_pthreads=yes
 			    CFLAGS="$CFLAGS -pthreads"
 			    CXXFLAGS="$CXXFLAGS -pthreads"
 		    fi
 	    fi
 	    rm -f conftest*
     	AC_MSG_RESULT($ac_cv_have_dash_pthreads)
     fi
@@ -3761,17 +3760,17 @@ if test "$ac_cv_have_clock_monotonic" = 
     REALTIME_LIBS=-lrt
     AC_DEFINE(HAVE_CLOCK_MONOTONIC)
     AC_SUBST(HAVE_CLOCK_MONOTONIC)
     AC_SUBST(REALTIME_LIBS)
 fi
 
 dnl check for wcrtomb/mbrtowc
 dnl =======================================================================
-if test -z "$MACOS_DEPLOYMENT_TARGET" || test "$MACOS_DEPLOYMENT_TARGET" -ge "100300"; then
+if test -z "$MACOS_DEPLOYMENT_TARGET" -o "$MACOS_DEPLOYMENT_TARGET" -ge "100300"; then
 AC_LANG_SAVE
 AC_LANG_CPLUSPLUS
 AC_CACHE_CHECK(for wcrtomb,
     ac_cv_have_wcrtomb,
     [AC_TRY_LINK([#include <wchar.h>],
                  [mbstate_t ps={0};wcrtomb(0,'f',&ps);],
                  ac_cv_have_wcrtomb="yes",
                  ac_cv_have_wcrtomb="no")])
@@ -4540,17 +4539,17 @@ fi
 AC_SUBST(LIBXUL_DIST)
 
 SYSTEM_LIBXUL=
 
 MOZ_ARG_WITH_BOOL(system-libxul,
 [  --with-system-libxul    Use system installed libxul SDK],
     SYSTEM_LIBXUL=1)
 
-if test -n "$SYSTEM_LIBXUL" && test -z "$MOZ_ENABLE_LIBXUL"; then
+if test -n "$SYSTEM_LIBXUL" -a -z "$MOZ_ENABLE_LIBXUL"; then
     AC_MSG_ERROR([--with-system-libxul needs --with-libxul-sdk])
 fi
 
 dnl ========================================================
 dnl = If NSPR was not detected in the system, 
 dnl = use the one in the source tree (mozilla/nsprpub)
 dnl ========================================================
 MOZ_ARG_WITH_BOOL(system-nspr,
@@ -4644,17 +4643,17 @@ else
    NSS_CFLAGS='-I$(LIBXUL_DIST)/include/nss'
    NSS_DEP_LIBS="\
         \$(LIBXUL_DIST)/lib/\$(LIB_PREFIX)crmf.\$(LIB_SUFFIX) \
         \$(LIBXUL_DIST)/lib/\$(DLL_PREFIX)smime$NSS_VERSION\$(DLL_SUFFIX) \
         \$(LIBXUL_DIST)/lib/\$(DLL_PREFIX)ssl$NSS_VERSION\$(DLL_SUFFIX) \
         \$(LIBXUL_DIST)/lib/\$(DLL_PREFIX)nss$NSS_VERSION\$(DLL_SUFFIX) \
         \$(LIBXUL_DIST)/lib/\$(DLL_PREFIX)nssutil$NSS_VERSION\$(DLL_SUFFIX)"
 
-   if test -z "$GNU_CC" && test "$OS_ARCH" = "WINNT" -o "$OS_ARCH" = "WINCE" -o "$OS_ARCH" = "OS2"; then
+   if test -z "$GNU_CC" -a "$OS_ARCH" = "WINNT" -o "$OS_ARCH" = "WINCE" -o "$OS_ARCH" = "OS2"; then
        NSS_LIBS="\
         \$(LIBXUL_DIST)/lib/\$(LIB_PREFIX)crmf.\$(LIB_SUFFIX) \
         \$(LIBXUL_DIST)/lib/\$(LIB_PREFIX)smime$NSS_VERSION.\$(LIB_SUFFIX) \
         \$(LIBXUL_DIST)/lib/\$(LIB_PREFIX)ssl$NSS_VERSION.\$(LIB_SUFFIX) \
         \$(LIBXUL_DIST)/lib/\$(LIB_PREFIX)nss$NSS_VERSION.\$(LIB_SUFFIX) \
         \$(LIBXUL_DIST)/lib/\$(LIB_PREFIX)nssutil$NSS_VERSION.\$(LIB_SUFFIX)"
    else
        NSS_LIBS='$(LIBS_DIR)'" -lcrmf -lsmime$NSS_VERSION -lssl$NSS_VERSION -lnss$NSS_VERSION -lnssutil$NSS_VERSION"
@@ -5574,20 +5573,20 @@ AC_SUBST(MOZ_LIBNOTIFY_CFLAGS)
 AC_SUBST(MOZ_LIBNOTIFY_LIBS)
 
 dnl ========================================================
 dnl = GNOME component (mozgnome)
 dnl ========================================================
 
 # The GNOME component is built if one of 
 # gnome-vfs, gio, gconf or libnotify is available.
-if test "$MOZ_ENABLE_GCONF" || \
-   test "$MOZ_ENABLE_GNOMEVFS" || \
-   test "$MOZ_ENABLE_GIO" || \
-   test "$MOZ_ENABLE_LIBNOTIFY"; then
+if test "$MOZ_ENABLE_GCONF" -o \
+   "$MOZ_ENABLE_GNOMEVFS" -o \
+   "$MOZ_ENABLE_GIO" -o \
+   "$MOZ_ENABLE_LIBNOTIFY"; then
     MOZ_ENABLE_GNOME_COMPONENT=1
 else
     MOZ_ENABLE_GNOME_COMPONENT=
 fi
 AC_SUBST(MOZ_ENABLE_GNOME_COMPONENT)
 
 dnl ========================================================
 dnl = libgnomeui support module
@@ -5625,17 +5624,17 @@ fi
 AC_SUBST(MOZ_ENABLE_GNOMEUI)
 AC_SUBST(MOZ_GNOMEUI_CFLAGS)
 AC_SUBST(MOZ_GNOMEUI_LIBS)
 
 dnl ========================================================
 dnl = dbus support
 dnl ========================================================
 
-if test "$MOZ_ENABLE_GTK2" || test "$MOZ_ENABLE_QT"
+if test "$MOZ_ENABLE_GTK2" -o "$MOZ_ENABLE_QT"
 then
     MOZ_ENABLE_DBUS=1
 
     MOZ_ARG_DISABLE_BOOL(dbus,
     [  --disable-dbus          Disable dbus support ],
         MOZ_ENABLE_DBUS=,
         MOZ_ENABLE_DBUS=1)
 
@@ -6078,18 +6077,18 @@ else
   dnl No path specified, so look for javac and jar in $JAVA_HOME & $PATH.
   JAVA_PATH="$JAVA_HOME/bin:$PATH"
 fi
 
 MOZ_PATH_PROG(JAVA, java, :, [$JAVA_PATH])
 MOZ_PATH_PROG(JAVAC, javac, :, [$JAVA_PATH])
 MOZ_PATH_PROG(JAR, jar, :, [$JAVA_PATH])
 
-if test -n "${JAVA_BIN_PATH}" || test "$OS_TARGET" = Android; then
-  if test -z "$JAVA" || test "$JAVA" = ":" || test -z "$JAVAC" || test "$JAVAC" = ":" || test -z "$JAR" || test "$JAR" = ":"; then
+if test -n "${JAVA_BIN_PATH}" -o "$OS_TARGET" = Android; then
+  if test -z "$JAVA" -o "$JAVA" = ":" -o -z "$JAVAC" -o "$JAVAC" = ":" -o -z "$JAR" -o "$JAR" = ":"; then
     AC_MSG_ERROR([The programs java, javac and jar were not found.  Set \$JAVA_HOME to your java sdk directory or use --with-java-bin-path={java-bin-dir}])
   fi
 fi
 
 if test -n "${MOZ_JAVAXPCOM}"; then
   if test -n "${JAVA_INCLUDE_PATH}"; then
     dnl Make sure jni.h exists in the given include path.
     if test ! -f "$JAVA_INCLUDE_PATH/jni.h"; then
@@ -6134,17 +6133,17 @@ esac
 MOZ_ARG_DISABLE_BOOL(crashreporter,
 [  --disable-crashreporter Disable breakpad crash reporting],
     MOZ_CRASHREPORTER=,
     MOZ_CRASHREPORTER=1)
 
 if test -n "$MOZ_CRASHREPORTER"; then
    AC_DEFINE(MOZ_CRASHREPORTER)
 
-  if (test "$OS_ARCH" = "Linux" || test "$OS_ARCH" = "SunOS") && \
+  if (test "$OS_ARCH" = "Linux" -o "$OS_ARCH" = "SunOS") && \
     test -z "$SKIP_LIBRARY_CHECKS"; then
     PKG_CHECK_MODULES(MOZ_GTHREAD, gthread-2.0)
     AC_SUBST(MOZ_GTHREAD_CFLAGS)
     AC_SUBST(MOZ_GTHREAD_LIBS)
 
     AC_CHECK_HEADERS([curl/curl.h], [], [AC_MSG_ERROR([Couldn't find curl/curl.h which is required for the crash reporter.  Use --disable-crashreporter to disable the crash reporter.])])
   fi
 fi
@@ -6162,58 +6161,58 @@ AC_DEFINE_UNQUOTED(MOZ_CRASHREPORTER_ENA
 
 dnl ========================================================
 dnl = Enable compilation of specific extension modules
 dnl ========================================================
 
 MOZ_ARG_ENABLE_STRING(extensions,
 [  --enable-extensions     Enable extensions],
 [ for option in `echo $enableval | sed 's/,/ /g'`; do
-    if test "$option" = "yes" || test "$option" = "all"; then
+    if test "$option" = "yes" -o "$option" = "all"; then
         AC_MSG_ERROR([--enable-extensions=$option is no longer supported.])
-    elif test "$option" = "no" || test "$option" = "none"; then
+    elif test "$option" = "no" -o "$option" = "none"; then
         MOZ_EXTENSIONS=""
     elif test "$option" = "default"; then
         MOZ_EXTENSIONS="$MOZ_EXTENSIONS $MOZ_EXTENSIONS_DEFAULT"
     elif test `echo "$option" | grep -c \^-` != 0; then
         option=`echo $option | sed 's/^-//'`
         MOZ_EXTENSIONS=`echo "$MOZ_EXTENSIONS" | sed "s/ ${option}//"`
     else
         MOZ_EXTENSIONS="$MOZ_EXTENSIONS $option"
     fi
 done],
     MOZ_EXTENSIONS="$MOZ_EXTENSIONS_DEFAULT")
 
-if test -z "$MOZ_ENABLE_GNOMEVFS" && test -z "$MOZ_GNOMEVFS_LIBS" && test `echo "$MOZ_EXTENSIONS" | grep -c gnomevfs` -ne 0; then
+if test -z "$MOZ_ENABLE_GNOMEVFS" -a -z "$MOZ_GNOMEVFS_LIBS" -a `echo "$MOZ_EXTENSIONS" | grep -c gnomevfs` -ne 0; then
     # Suppress warning on non-X11 platforms
     if test -n "$MOZ_X11"; then
         AC_MSG_WARN([Cannot build gnomevfs without required libraries. Removing gnomevfs from MOZ_EXTENSIONS.])
     fi
     MOZ_EXTENSIONS=`echo $MOZ_EXTENSIONS | sed -e 's|gnomevfs||'`
 fi
 
 dnl Do not build gnomevfs with libxul based apps
-if test -n "$LIBXUL_SDK_DIR" && test `echo "$MOZ_EXTENSIONS" | grep -c gnomevfs` -ne 0; then
+if test -n "$LIBXUL_SDK_DIR" -a `echo "$MOZ_EXTENSIONS" | grep -c gnomevfs` -ne 0; then
     MOZ_EXTENSIONS=`echo $MOZ_EXTENSIONS | sed -e 's|gnomevfs||'`
 fi
 
-if test -z "$MOZ_ENABLE_GIO" && test `echo "$MOZ_EXTENSIONS" | grep -c gio` -ne 0; then
+if test -z "$MOZ_ENABLE_GIO" -a `echo "$MOZ_EXTENSIONS" | grep -c gio` -ne 0; then
     # Suppress warning on non-X11 platforms
     if test -n "$MOZ_X11"; then
         AC_MSG_WARN([Cannot build gio without required libraries. Removing gio from MOZ_EXTENSIONS.])
     fi
     MOZ_EXTENSIONS=`echo $MOZ_EXTENSIONS | sed -e 's|gio||'`
 fi
 
 dnl Do not build gio with libxul based apps
-if test -n "$LIBXUL_SDK_DIR" && test `echo "$MOZ_EXTENSIONS" | grep -c gio` -ne 0; then
+if test -n "$LIBXUL_SDK_DIR" -a `echo "$MOZ_EXTENSIONS" | grep -c gio` -ne 0; then
     MOZ_EXTENSIONS=`echo $MOZ_EXTENSIONS | sed -e 's|gio||'`
 fi
 
-if test -z "$MOZ_JSDEBUGGER" && test `echo "$MOZ_EXTENSIONS" | grep -c venkman` -ne 0; then
+if test -z "$MOZ_JSDEBUGGER" -a `echo "$MOZ_EXTENSIONS" | grep -c venkman` -ne 0; then
     AC_MSG_WARN([Cannot build venkman without JavaScript debug library. Removing venkman from MOZ_EXTENSIONS.])
     MOZ_EXTENSIONS=`echo $MOZ_EXTENSIONS | sed -e 's|venkman||'`
 fi
 
 dnl This might be temporary: build tridentprofile only on Windows
 if test `echo "$MOZ_EXTENSIONS" | grep -c tridentprofile` -ne 0 && test "$OS_ARCH" != "WINNT"; then
     AC_MSG_WARN([tridentprofile extension works only on Windows at this time. Removing tridentprofile from MOZ_EXTENSIONS.])
     MOZ_EXTENSIONS=`echo $MOZ_EXTENSIONS | sed -e 's|tridentprofile||'`
@@ -6221,17 +6220,17 @@ fi
 
 dnl cookie must be built before tridentprofile. put it at list's end.
 if test `echo "$MOZ_EXTENSIONS" | grep -c tridentprofile` -ne 0; then
   MOZ_EXTENSIONS=`echo $MOZ_EXTENSIONS | sed -e 's|tridentprofile||'`
   MOZ_EXTENSIONS="$MOZ_EXTENSIONS tridentprofile"
 fi
 
 dnl xforms requires xtf and schema-validation
-if test -z "$MOZ_XTF" && test `echo "$MOZ_EXTENSIONS" | grep -c xforms` -ne 0; then
+if test -z "$MOZ_XTF" -a `echo "$MOZ_EXTENSIONS" | grep -c xforms` -ne 0; then
     AC_MSG_WARN([Cannot build XForms without XTF support.  Removing XForms from MOZ_EXTENSIONS.])
     MOZ_EXTENSIONS=`echo $MOZ_EXTENSIONS | sed -e 's|xforms||g'`
 fi
 if test `echo "$MOZ_EXTENSIONS" | grep -c xforms` -ne 0 && test `echo "$MOZ_EXTENSIONS" | grep -c schema-validation` -eq 0; then
     AC_MSG_WARN([Cannot build XForms without schema validation.  Removing XForms from MOZ_EXTENSIONS.])
     MOZ_EXTENSIONS=`echo $MOZ_EXTENSIONS | sed -e 's|xforms||g'`
 fi
 
@@ -6279,29 +6278,29 @@ done
 
 dnl ========================================================
 dnl Image decoders
 dnl ========================================================
 case "$MOZ_WIDGET_TOOLKIT" in
 beos|windows|os2|mac|cocoa)
     ;;
 *)
-    if test -z "$MOZ_ENABLE_GTK2" && test -z "$MOZ_ENABLE_QT"; then
+    if test -z "$MOZ_ENABLE_GTK2" -a -z "$MOZ_ENABLE_QT"; then
        MOZ_IMG_DECODERS_DEFAULT=`echo $MOZ_IMG_DECODERS_DEFAULT | sed -e 's|icon||'`
     fi
     ;;
 esac
 
 MOZ_ARG_ENABLE_STRING(image-decoders,
 [  --enable-image-decoders[={mod1,mod2,default,all,none}]
                           Enable specific image decoders],
 [ for option in `echo $enableval | sed 's/,/ /g'`; do
-    if test "$option" = "yes" || test "$option" = "all"; then
+    if test "$option" = "yes" -o "$option" = "all"; then
         MOZ_IMG_DECODERS="$MOZ_IMG_DECODERS $MOZ_IMG_DECODERS_DEFAULT"
-    elif test "$option" = "no" || test "$option" = "none"; then
+    elif test "$option" = "no" -o "$option" = "none"; then
         MOZ_IMG_DECODERS=""
     elif test "$option" = "default"; then
         MOZ_IMG_DECODERS="$MOZ_IMG_DECODERS $MOZ_IMG_DECODERS_DEFAULT"
     elif test `echo "$option" | grep -c \^-` != 0; then
         option=`echo $option | sed 's/^-//'`
         MOZ_IMG_DECODERS=`echo "$MOZ_IMG_DECODERS" | sed "s/ ${option}//"`
     else
         MOZ_IMG_DECODERS="$MOZ_IMG_DECODERS $option"
@@ -6313,19 +6312,19 @@ dnl Dupes are removed in the encoder sec
 
 dnl ========================================================
 dnl Image encoders
 dnl ========================================================
 MOZ_ARG_ENABLE_STRING(image-encoders,
 [  --enable-image-encoders[={mod1,mod2,default,all,none}]
                           Enable specific image encoders],
 [ for option in `echo $enableval | sed 's/,/ /g'`; do
-    if test "$option" = "yes" || test "$option" = "all"; then
+    if test "$option" = "yes" -o "$option" = "all"; then
         addencoder="$MOZ_IMG_ENCODERS_DEFAULT"
-    elif test "$option" = "no" || test "$option" = "none"; then
+    elif test "$option" = "no" -o "$option" = "none"; then
         MOZ_IMG_ENCODERS=""
         addencoder=""
     elif test "$option" = "default"; then
         addencoder="$MOZ_IMG_ENCODERS_DEFAULT"
     elif test `echo "$option" | grep -c \^-` != 0; then
         option=`echo $option | sed 's/^-//'`
         addencoder=`echo "$MOZ_IMG_ENCODERS" | sed "s/ ${option}//"`
     else
@@ -6415,30 +6414,30 @@ MOZ_ARG_DISABLE_BOOL(installer,
     MOZ_INSTALLER=1)
 if test -n "$MOZ_INSTALLER" -a "$OS_ARCH" = "WINNT"; then
     # Disable installer for Windows builds that use the new toolkit if the
     # required major version and minimum minor version of Unicode NSIS isn't in
     # the path.
     REQ_NSIS_MAJOR_VER=2
     MIN_NSIS_MINOR_VER=33
     MOZ_PATH_PROGS(MAKENSISU, $MAKENSISU makensisu-2.46 makensisu makensis)
-    if test -z "$MAKENSISU" || test "$MAKENSISU" = ":"; then
+    if test -z "$MAKENSISU" -o "$MAKENSISU" = ":"; then
         AC_MSG_ERROR([To build the installer you must have the latest MozillaBuild or Unicode NSIS with a major version of $REQ_NSIS_MAJOR_VER and a minimum minor version of $MIN_NSIS_MINOR_VER in your path. To build without the installer reconfigure using --disable-installer.])
     fi
     changequote(,)
     MAKENSISU_VER=`"$MAKENSISU" -version 2>/dev/null | sed -e '/-Unicode/!s/.*//g' -e 's/^v\([0-9]\+\.[0-9]\+\)\-Unicode$/\1/g'`
     changequote([,])
     if test ! "$MAKENSISU_VER" == ""; then
         MAKENSISU_MAJOR_VER=`echo $MAKENSISU_VER | $AWK -F\. '{ print $1 }'`
         MAKENSISU_MINOR_VER=`echo $MAKENSISU_VER | $AWK -F\. '{ print $2 }'`
     fi
     AC_MSG_CHECKING([for Unicode NSIS with major version == $REQ_NSIS_MAJOR_VER and minor version >= $MIN_NSIS_MINOR_VER])
-    if test "$MAKENSISU_VER" == "" ||
-       test ! "$MAKENSISU_MAJOR_VER" == "$REQ_NSIS_MAJOR_VER" ||
-       test ! "$MAKENSISU_MINOR_VER" -ge $MIN_NSIS_MINOR_VER; then
+    if test "$MAKENSISU_VER" == "" -o \
+       ! "$MAKENSISU_MAJOR_VER" == "$REQ_NSIS_MAJOR_VER" -o \
+       ! "$MAKENSISU_MINOR_VER" -ge $MIN_NSIS_MINOR_VER; then
         AC_MSG_RESULT([no])
         AC_MSG_ERROR([To build the installer you must have the latest MozillaBuild or Unicode NSIS with a major version of $REQ_NSIS_MAJOR_VER and a minimum minor version of $MIN_NSIS_MINOR_VER in your path. To build without the installer reconfigure using --disable-installer.])
     fi
     AC_MSG_RESULT([yes])
     MAKENSISU="${CYGWIN_WRAPPER} $MAKENSISU"
 
     # The Windows build for NSIS requires the iconv command line utility to
     # convert the charset of the locale files.
@@ -6960,38 +6959,18 @@ dnl = Debugging Options
 dnl = 
 dnl ========================================================
 MOZ_ARG_HEADER(Debugging and Optimizations)
 
 dnl ========================================================
 dnl = Disable building with debug info.
 dnl = Debugging is OFF by default
 dnl ========================================================
-if test -z "$MOZ_DEBUG_FLAGS"
-then
-    case "$target" in
-    *-irix*)
-        if test "$GNU_CC"; then
-            GCC_VERSION=`$CC -v 2>&1 | awk '/version/ { print $3 }'`
-            case "$GCC_VERSION" in
-            2.95.*)
-                MOZ_DEBUG_FLAGS=""
-                ;;
-            *)
-                MOZ_DEBUG_FLAGS="-g"
-                ;;
-            esac
-        else
-            MOZ_DEBUG_FLAGS="-g"
-        fi
-        ;;
-    *)
-    	MOZ_DEBUG_FLAGS="-g"
-        ;;
-    esac
+if test -z "$MOZ_DEBUG_FLAGS"; then
+  MOZ_DEBUG_FLAGS="-g"
 fi
 
 MOZ_ARG_ENABLE_STRING(debug,
 [  --enable-debug[=DBG]    Enable building with developer debug info
                            (using compiler flags DBG)],
 [ if test "$enableval" != "no"; then
     MOZ_DEBUG=1
     if test -n "$enableval" -a "$enableval" != "yes"; then
@@ -7050,17 +7029,17 @@ if test -z "$MOZ_OPTIMIZE_FLAGS"; then
 	MOZ_OPTIMIZE_FLAGS="-O"
 fi
 
 MOZ_ARG_ENABLE_STRING(optimize,
 [  --disable-optimize      Disable compiler optimization
   --enable-optimize=[OPT] Specify compiler optimization flags [OPT=-O]],
 [ if test "$enableval" != "no"; then
     MOZ_OPTIMIZE=1
-    if test -n "$enableval" && test "$enableval" != "yes"; then
+    if test -n "$enableval" -a "$enableval" != "yes"; then
         MOZ_OPTIMIZE_FLAGS=`echo "$enableval" | sed -e 's|\\\ | |g'`
         MOZ_OPTIMIZE=2
     fi
 else
     MOZ_OPTIMIZE=
 fi ], MOZ_OPTIMIZE=1)
 
 if test "$COMPILE_ENVIRONMENT"; then
@@ -7414,16 +7393,29 @@ dnl ====================================
 MOZ_ARG_ENABLE_BOOL(gczeal,
 [  --enable-gczeal         Enable zealous JavaScript GCing],
     JS_GC_ZEAL=1,
     JS_GC_ZEAL= )
 if test -n "$JS_GC_ZEAL"; then
     AC_DEFINE(JS_GC_ZEAL)
 fi
 
+dnl ======================================================
+dnl = Enable compiling with ccache
+dnl ======================================================
+MOZ_ARG_WITH_STRING(ccache,
+[  --with-ccache=path/to/ccache
+                          Enable compiling with ccache],
+    CCACHE_PATH=$withval,)
+
+if test -n "$CCACHE_PATH"; then
+  CC="$CCACHE_PATH $CC"
+  CXX="$CCACHE_PATH $CXX"
+fi
+
 dnl ========================================================
 dnl = Enable static checking using gcc-dehydra
 dnl ========================================================
 
 MOZ_ARG_WITH_STRING(static-checking,
 [  --with-static-checking=path/to/gcc_dehydra.so
                           Enable static checking of code using GCC-dehydra],
     DEHYDRA_PATH=$withval,
@@ -7544,17 +7536,17 @@ if test "$HAVE_DEMANGLE" -a "$HAVE_GCC3_
     MOZ_DEMANGLE_SYMBOLS=1
     AC_DEFINE(MOZ_DEMANGLE_SYMBOLS)
 fi
 AC_SUBST(MOZ_DEMANGLE_SYMBOLS)
 
 dnl ========================================================
 dnl = Support for gcc stack unwinding (from gcc 3.3)