merge m-c to fx-team
authorTim Taubert <ttaubert@mozilla.com>
Wed, 26 Sep 2012 10:59:07 +0200
changeset 114489 7505bbe999e4dc52b67c5c4df8585d8785a61ceb
parent 114488 37d3286e67bac1ba602d30a6f98758bf08e43c7a (current diff)
parent 114331 e64a78df7258a0650990fdabd9610881f7d11617 (diff)
child 114490 c7ea268e3322b52ff800744bc354563b895a8bad
push id1708
push userakeybl@mozilla.com
push dateMon, 19 Nov 2012 21:10:21 +0000
treeherdermozilla-beta@27b14fe50103 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone18.0a1
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 m-c to fx-team
build/valgrind/i686-redhat-linux-gnu.sup
build/valgrind/x86_64-redhat-linux-gnu.sup
media/webrtc/Android.mk
mobile/android/components/SafeBrowsing.js
toolkit/crashreporter/google-breakpad/.hg_archival.txt
toolkit/crashreporter/google-breakpad/.hgsvnexternals
toolkit/crashreporter/google-breakpad/src/client/linux/android_link.h
toolkit/crashreporter/google-breakpad/src/client/linux/android_ucontext.h
toolkit/crashreporter/google-breakpad/src/client/linux/minidump_writer/linux_dumper_unittest.cc
toolkit/crashreporter/google-breakpad/src/client/linux/minidump_writer/minidump_extension_linux.h
toolkit/crashreporter/google-breakpad/src/client/mac/handler/breakpad_exc_server.c
toolkit/crashreporter/google-breakpad/src/client/mac/handler/breakpad_exc_server.h
toolkit/crashreporter/google-breakpad/src/client/mac/tests/auto_tempdir.h
toolkit/crashreporter/google-breakpad/src/client/windows/tests/crash_generation_app/crash_generation_app.sln
toolkit/crashreporter/google-breakpad/src/client/windows/tests/crash_generation_app/crash_generation_app.vcproj
toolkit/crashreporter/google-breakpad/src/client/windows/tests/crash_generation_app/precompile.cc
toolkit/crashreporter/google-breakpad/src/client/windows/tests/crash_generation_app/precompile.h
toolkit/crashreporter/google-breakpad/src/client/windows/unittests/gtest.gyp
toolkit/crashreporter/google-breakpad/src/common/linux/linux_syscall_support.h
toolkit/crashreporter/google-breakpad/src/common/linux/memory_unittest.cc
toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/network_source_line_resolver.h
toolkit/crashreporter/google-breakpad/src/processor/network_interface.h
toolkit/crashreporter/google-breakpad/src/processor/network_source_line_protocol.h
toolkit/crashreporter/google-breakpad/src/processor/network_source_line_resolver.cc
toolkit/crashreporter/google-breakpad/src/processor/network_source_line_resolver_server_unittest.cc
toolkit/crashreporter/google-breakpad/src/processor/network_source_line_resolver_unittest.cc
toolkit/crashreporter/google-breakpad/src/processor/network_source_line_server.cc
toolkit/crashreporter/google-breakpad/src/processor/network_source_line_server.h
toolkit/crashreporter/google-breakpad/src/processor/network_source_line_server_unittest.cc
toolkit/crashreporter/google-breakpad/src/processor/source_daemon.cc
toolkit/crashreporter/google-breakpad/src/processor/udp_network.cc
toolkit/crashreporter/google-breakpad/src/processor/udp_network.h
toolkit/crashreporter/google-breakpad/src/third_party/linux/include/glog/log_severity.h
toolkit/crashreporter/google-breakpad/src/third_party/linux/include/glog/logging.h
toolkit/crashreporter/google-breakpad/src/third_party/linux/include/glog/raw_logging.h
toolkit/crashreporter/google-breakpad/src/third_party/linux/include/glog/stl_logging.h
toolkit/crashreporter/google-breakpad/src/third_party/linux/include/glog/vlog_is_on.h
widget/gtk2/gtk2compat.h
rename from media/webrtc/Android.mk
rename to Android.mk
--- a/media/webrtc/Android.mk
+++ b/Android.mk
@@ -1,5 +1,5 @@
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
-# empty file to block B2G/Gonk from trying to build anything inside media/webrtc
+# empty file to block B2G/Gonk from trying to build anything inside mozilla-central
--- a/accessible/src/atk/ApplicationAccessibleWrap.cpp
+++ b/accessible/src/atk/ApplicationAccessibleWrap.cpp
@@ -430,26 +430,27 @@ mai_util_remove_key_event_listener (guin
     if (g_hash_table_size(sKey_listener_list) == 0) {
         gtk_key_snooper_remove(sKey_snooper_id);
     }
 }
 
 AtkObject*
 mai_util_get_root(void)
 {
-  if (nsAccessibilityService::IsShutdown()) {
-    // We've shutdown, try to use gail instead
-    // (to avoid assert in spi_atk_tidy_windows())
-    if (gail_get_root)
-      return gail_get_root();
+  ApplicationAccessible* app = ApplicationAcc();
+  if (app)
+    return app->GetAtkObject();
 
-    return nullptr;
-  }
+  // We've shutdown, try to use gail instead
+  // (to avoid assert in spi_atk_tidy_windows())
+  // XXX tbsaunde then why didn't we replace the gail atk_util impl?
+  if (gail_get_root)
+    return gail_get_root();
 
-  return ApplicationAcc()->GetAtkObject();
+  return nullptr;
 }
 
 G_CONST_RETURN gchar *
 mai_util_get_toolkit_name(void)
 {
     return MAI_NAME;
 }
 
--- a/accessible/src/html/HTMLListAccessible.cpp
+++ b/accessible/src/html/HTMLListAccessible.cpp
@@ -163,17 +163,16 @@ HTMLListBulletAccessible::GetFrame() con
 
 ENameValueFlag
 HTMLListBulletAccessible::Name(nsString &aName)
 {
   aName.Truncate();
 
   // Native anonymous content, ARIA can't be used. Get list bullet text.
   nsBlockFrame* blockFrame = do_QueryFrame(mContent->GetPrimaryFrame());
-  NS_ASSERTION(blockFrame, "No frame for list item!");
   if (blockFrame) {
     blockFrame->GetBulletText(aName);
 
     // Append space otherwise bullets are jammed up against list text.
     aName.Append(' ');
   }
 
   return eNameOK;
@@ -192,17 +191,16 @@ HTMLListBulletAccessible::NativeState()
 }
 
 void
 HTMLListBulletAccessible::AppendTextTo(nsAString& aText, uint32_t aStartOffset,
                                        uint32_t aLength)
 {
   nsAutoString bulletText;
   nsBlockFrame* blockFrame = do_QueryFrame(mContent->GetPrimaryFrame());
-  NS_ASSERTION(blockFrame, "No frame for list item!");
   if (blockFrame)
     blockFrame->GetBulletText(bulletText);
 
   aText.Append(Substring(bulletText, aStartOffset, aLength));
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // HTMLListBulletAccessible: public
--- a/accessible/tests/mochitest/events/test_contextmenu.html
+++ b/accessible/tests/mochitest/events/test_contextmenu.html
@@ -96,17 +96,17 @@
       return null;
     }
 
     ////////////////////////////////////////////////////////////////////////////
     // Do tests
 
     var gQueue = null;
     //gA11yEventDumpID = "eventdump"; // debug stuff
-    gA11yEventDumpToConsole = true;
+    //gA11yEventDumpToConsole = true;
 
     function doTests()
     {
       gQueue = new eventQueue();
 
       gQueue.push(new showContextMenu("input"));
       gQueue.push(new selectMenuItem());
       gQueue.push(new closeContextMenu());
--- a/accessible/tests/mochitest/events/test_focus_contextmenu.xul
+++ b/accessible/tests/mochitest/events/test_focus_contextmenu.xul
@@ -17,17 +17,17 @@
           src="../role.js" />
   <script type="application/javascript"
           src="../states.js" />
   <script type="application/javascript"
           src="../events.js" />
 
   <script type="application/javascript">
     //gA11yEventDumpID = "eventdump"; // debug stuff
-    //gA11yEventDumpToConsole = true; // debug stuff
+    gA11yEventDumpToConsole = true; // debug stuff
 
     var gQueue = null;
     function doTests()
     {
       // bug 746183 - Whole file times out on OS X
       if (MAC) {
         todo(false, "Reenable on mac after fixing bug 746183!");
         SimpleTest.finish();
@@ -42,22 +42,19 @@
                                        new invokerChecker(EVENT_MENUPOPUP_START, "contextmenu")));
       gQueue.push(new synthEscapeKey("contextmenu", new focusChecker("button")));
 
       gQueue.push(new synthContextMenu("button",
                                        new invokerChecker(EVENT_MENUPOPUP_START, "contextmenu")));
       gQueue.push(new synthDownKey("contextmenu", new focusChecker("item1")));
       gQueue.push(new synthDownKey("item1", new focusChecker("item2")));
       gQueue.push(new synthRightKey("item2", new focusChecker("item2.1")));
-      if (WIN) {
-        todo(false, "item2.1 and item2 fail too frequently on Windows, bug 691580");
-      } else {
-        gQueue.push(new synthEscapeKey("item2.1", new focusChecker("item2")));
-        gQueue.push(new synthEscapeKey("item2", new focusChecker("button")));
-      }
+      gQueue.push(new synthEscapeKey("item2.1", new focusChecker("item2")));
+      gQueue.push(new synthEscapeKey("item2", new focusChecker("button")));
+
       gQueue.invoke(); // Will call SimpleTest.finish();
     }
 
     SimpleTest.waitForExplicitFinish();
     addA11yLoadEvent(doTests);
   </script>
 
   <hbox flex="1" style="overflow: auto;">
--- a/b2g/chrome/content/shell.js
+++ b/b2g/chrome/content/shell.js
@@ -368,17 +368,18 @@ var shell = {
     if (message.name != 'content-handler') {
       return;
     }
     let handler = message.json;
     new MozActivity({
       name: 'view',
       data: {
         type: handler.type,
-        url: handler.url
+        url: handler.url,
+        extras: handler.extras
       }
     });
   }
 };
 
 function nsBrowserAccess() {
 }
 
--- a/b2g/chrome/content/touchcontrols.css
+++ b/b2g/chrome/content/touchcontrols.css
@@ -135,21 +135,21 @@
 
 .statusIcon {
   margin-bottom: 28px;
   width: 36px;
   height: 36px;
 }
 
 .statusIcon[type="throbber"] {
-  background: url(chrome:///content/images/throbber.png) no-repeat center;
+  background: url("chrome://browser/content/images/throbber.png") no-repeat center;
 }
 
 .statusIcon[type="error"] {
-  background: url(chrome://global/content/images/error.png) no-repeat center;
+  background: url("chrome://browser/content/images/error.png") no-repeat center;
 }
 
 /* CSS Transitions */
 .controlBar:not([immediate]) {
   -moz-transition-property: opacity;
   -moz-transition-duration: 200ms;
 }
 
--- a/b2g/chrome/jar.mn
+++ b/b2g/chrome/jar.mn
@@ -32,10 +32,10 @@ chrome.jar:
   content/images/errorpage-larry-black.png (content/images/errorpage-larry-black.png)
   content/images/errorpage-larry-white.png (content/images/errorpage-larry-white.png)
   content/images/errorpage-warning.png (content/images/errorpage-warning.png)
   content/images/scrubber-hdpi.png     (content/images/scrubber-hdpi.png)
   content/images/unmute-hdpi.png       (content/images/unmute-hdpi.png)
   content/images/pause-hdpi.png        (content/images/pause-hdpi.png)
   content/images/play-hdpi.png         (content/images/play-hdpi.png)
   content/images/mute-hdpi.png         (content/images/mute-hdpi.png)
-  content/images/throbber.png          (content/images/error.png)
-  content/images/error.png             (content/images/throbber.png)
+  content/images/throbber.png          (content/images/throbber.png)
+  content/images/error.png             (content/images/error.png)
--- a/b2g/components/MozKeyboard.js
+++ b/b2g/components/MozKeyboard.js
@@ -44,19 +44,17 @@ MozKeyboard.prototype = {
                      .getInterface(Ci.nsIDOMWindowUtils);
     this.innerWindowID = this._utils.currentInnerWindowID;
 
     this._focusHandler = null;
   },
 
   uninit: function mozKeyboardUninit() {
     Services.obs.removeObserver(this, "inner-window-destroyed");
-    if (this._messageManager) {
-      this._messageManager.removeMessageListener("Forms:Input", this);
-    }
+    this._messageManager = null;
     this._window = null;
     this._utils = null;
     this._focusHandler = null;
   },
 
   sendKey: function mozKeyboardSendKey(keyCode, charCode) {
     charCode = (charCode == undefined) ? keyCode : charCode;
     ["keydown", "keypress", "keyup"].forEach((function sendKey(type) {
@@ -85,17 +83,17 @@ MozKeyboard.prototype = {
   set onfocuschange(val) {
     this._focusHandler = val;
   },
 
   get onfocuschange() {
     return this._focusHandler;
   },
 
-  receiveMessage: function mozKeyboardReceiveMessage(msg) {
+  handleMessage: function mozKeyboardHandleMessage(msg) {
     let handler = this._focusHandler;
     if (!handler || !(handler instanceof Ci.nsIDOMEventListener))
       return;
 
     let detail = {
       "detail": msg.json
     };
 
@@ -112,18 +110,22 @@ MozKeyboard.prototype = {
         this.uninit();
       }
       break;
     }
     case 'remote-browser-frame-shown':
     case 'in-process-browser-frame-shown': {
       let frameLoader = subject.QueryInterface(Ci.nsIFrameLoader);
       let mm = frameLoader.messageManager;
-      this._messageManager = mm;
-      mm.addMessageListener("Forms:Input", this);
+      mm.addMessageListener("Forms:Input", (function receiveMessage(msg) {
+        // Need to save mm here so later the message can be sent back to the
+        // correct app in the methods called by the value selector.
+        this._messageManager = mm;
+        this.handleMessage(msg);
+      }).bind(this));
       try {
         mm.loadFrameScript(kFormsFrameScript, true);
       } catch (e) {
         dump('Error loading ' + kFormsFrameScript + ' as frame script: ' + e + '\n');
       }
       break;
     }
     }
--- a/b2g/components/YoutubeProtocolHandler.js
+++ b/b2g/components/YoutubeProtocolHandler.js
@@ -78,34 +78,42 @@ YoutubeProtocolHandler.prototype = {
       // Recognized mime types, ordered from the less usable to the most usable.
       let recognizedTypes = ["video/webm"];
 #ifdef MOZ_WIDGET_GONK
       recognizedTypes.push("video/mp4");
 #endif
 
       let bestType = -1;
 
+      let extras = { }
+
       streams.forEach(function(aStream) {
         let params = extractParameters(aStream);
         let url = params["url"];
         let type = params["type"] ? params["type"].split(";")[0] : null;
 
         let index;
         if (url && type && ((index = recognizedTypes.indexOf(type)) != -1) &&
             index > bestType) {
           uri = url;
           mimeType = type;
           bestType = index;
         }
+        for (let param in params) {
+          if (["thumbnail_url", "length_seconds", "title"].indexOf(param) != -1) {
+            extras[param] = decodeURIComponent(params[param]);
+          }
+        }
       });
 
       if (uri && mimeType) {
         cpmm.sendAsyncMessage("content-handler", {
           url: uri,
-          type: mimeType
+          type: mimeType,
+          extras: extras
         });
       }
     });
     xhr.send(null);
 
     throw Components.results.NS_ERROR_ILLEGAL_VALUE;
   },
 
--- a/b2g/installer/package-manifest.in
+++ b/b2g/installer/package-manifest.in
@@ -703,16 +703,17 @@ bin/components/@DLL_PREFIX@nkgnomevfs@DL
 @BINPATH@/components/UpdatePrompt.js
 #endif
 @BINPATH@/components/MozKeyboard.js
 @BINPATH@/components/DirectoryProvider.js
 @BINPATH@/components/ActivitiesGlue.js
 @BINPATH@/components/ProcessGlobal.js
 @BINPATH@/components/ContentHandler.js
 @BINPATH@/components/PaymentGlue.js
+@BINPATH@/components/YoutubeProtocolHandler.js
 
 #ifdef XP_MACOSX
 @BINPATH@/@DLL_PREFIX@plugin_child_interpose@DLL_SUFFIX@
 #endif
 
 #ifdef PACKAGE_GAIA
 [gaia]
 @BINPATH@/gaia/*
--- a/browser/base/content/browser-social.js
+++ b/browser/base/content/browser-social.js
@@ -320,17 +320,17 @@ let SocialShareButton = {
 
   // Called once, after window load, when the Social.provider object is initialized
   init: function SSB_init() {
     this.updateButtonHiddenState();
     this.updateProfileInfo();
   },
 
   updateProfileInfo: function SSB_updateProfileInfo() {
-    let profileRow = document.getElementById("editSharePopupHeader");
+    let profileRow = document.getElementById("unsharePopupHeader");
     let profile = Social.provider.profile;
     this.promptImages = null;
     this.promptMessages = null;
     if (profile && profile.displayName) {
       profileRow.hidden = false;
       let portrait = document.getElementById("socialUserPortrait");
       portrait.setAttribute("src", profile.portrait || "chrome://browser/skin/social/social.png");
       let displayName = document.getElementById("socialUserDisplayName");
@@ -379,36 +379,40 @@ let SocialShareButton = {
       // resolve potentially relative URLs then check the scheme is acceptable.
       url = Services.io.newURI(Social.provider.origin, null, null).resolve(url);
       let uri = Services.io.newURI(url, null, null);
       if (!uri.schemeIs("http") && !uri.schemeIs("https") && !uri.schemeIs("data")) {
         return reportError('images["' + sub + '"] does not have a valid scheme');
       }
       promptImages[sub] = url;
     }
-    for (let sub of ["shareTooltip", "unshareTooltip", "sharedLabel", "unsharedLabel"]) {
+    for (let sub of ["shareTooltip", "unshareTooltip",
+                     "sharedLabel", "unsharedLabel", "unshareLabel",
+                     "portraitLabel", 
+                     "unshareConfirmLabel", "unshareConfirmAccessKey",
+                     "unshareCancelLabel", "unshareCancelAccessKey"]) {
       if (typeof data.messages[sub] != "string" || data.messages[sub].length == 0) {
         return reportError('messages["' + sub + '"] is not a valid string');
       }
       promptMessages[sub] = data.messages[sub];
     }
     this.promptImages = promptImages;
     this.promptMessages = promptMessages;
     return true;
   },
 
   get shareButton() {
     return document.getElementById("share-button");
   },
-  get sharePopup() {
-    return document.getElementById("editSharePopup");
+  get unsharePopup() {
+    return document.getElementById("unsharePopup");
   },
 
-  dismissSharePopup: function SSB_dismissSharePopup() {
-    this.sharePopup.hidePopup();
+  dismissUnsharePopup: function SSB_dismissUnsharePopup() {
+    this.unsharePopup.hidePopup();
   },
 
   updateButtonHiddenState: function SSB_updateButtonHiddenState() {
     let shareButton = this.shareButton;
     if (shareButton)
       shareButton.hidden = !Social.uiVisible || this.promptImages == null ||
                            !SocialUI.haveLoggedInUser();
   },
@@ -419,37 +423,52 @@ let SocialShareButton = {
 
     // Don't bubble to the textbox, to avoid unwanted selection of the address.
     aEvent.stopPropagation();
 
     this.sharePage();
   },
 
   panelShown: function SSB_panelShown(aEvent) {
-    let sharePopupOkButton = document.getElementById("editSharePopupOkButton");
-    if (sharePopupOkButton)
-      sharePopupOkButton.focus();
+    function updateElement(id, attrs) {
+      let el = document.getElementById(id);
+      Object.keys(attrs).forEach(function(attr) {
+        el.setAttribute(attr, attrs[attr]);
+      });
+    }
+    let continueSharingButton = document.getElementById("unsharePopupContinueSharingButton");
+    continueSharingButton.focus();
+    updateElement("unsharePopupContinueSharingButton",
+                  {label: this.promptMessages.unshareCancelLabel,
+                   accesskey: this.promptMessages.unshareCancelAccessKey});
+    updateElement("unsharePopupStopSharingButton",
+                  {label: this.promptMessages.unshareConfirmLabel,
+                  accesskey: this.promptMessages.unshareConfirmAccessKey});
+    updateElement("socialUserPortrait",
+                  {"aria-label": this.promptMessages.portraitLabel});
+    updateElement("socialUserRecommendedText",
+                  {value: this.promptMessages.unshareLabel});
   },
 
   sharePage: function SSB_sharePage() {
-    this.sharePopup.hidden = false;
+    this.unsharePopup.hidden = false;
 
     let uri = gBrowser.currentURI;
     if (!Social.isPageShared(uri)) {
       Social.sharePage(uri);
       this.updateShareState();
     } else {
-      this.sharePopup.openPopup(this.shareButton, "bottomcenter topright");
+      this.unsharePopup.openPopup(this.shareButton, "bottomcenter topright");
     }
   },
 
   unsharePage: function SSB_unsharePage() {
     Social.unsharePage(gBrowser.currentURI);
     this.updateShareState();
-    this.dismissSharePopup();
+    this.dismissUnsharePopup();
   },
 
   updateShareState: function SSB_updateShareState() {
     let currentPageShared = Social.isPageShared(gBrowser.currentURI);
 
     // Provide a11y-friendly notification of share.
     let status = document.getElementById("share-button-status");
     if (status) {
--- a/browser/base/content/browser.xul
+++ b/browser/base/content/browser.xul
@@ -66,21 +66,21 @@
 
   <popupset id="mainPopupSet">
     <menupopup id="tabContextMenu"
                onpopupshowing="if (event.target == this) TabContextMenu.updateContextMenu(this);"
                onpopuphidden="if (event.target == this) TabContextMenu.contextTab = null;">
       <menuitem id="context_reloadTab" label="&reloadTab.label;" accesskey="&reloadTab.accesskey;"
                 oncommand="gBrowser.reloadTab(TabContextMenu.contextTab);"/>
       <menuseparator/>
-      <menuitem id="context_pinTab" label="&pinAppTab.label;"
-                accesskey="&pinAppTab.accesskey;"
+      <menuitem id="context_pinTab" label="&pinTab.label;"
+                accesskey="&pinTab.accesskey;"
                 oncommand="gBrowser.pinTab(TabContextMenu.contextTab);"/>
-      <menuitem id="context_unpinTab" label="&unpinAppTab.label;" hidden="true"
-                accesskey="&unpinAppTab.accesskey;"
+      <menuitem id="context_unpinTab" label="&unpinTab.label;" hidden="true"
+                accesskey="&unpinTab.accesskey;"
                 oncommand="gBrowser.unpinTab(TabContextMenu.contextTab);"/>
       <menu id="context_tabViewMenu" label="&moveToGroup.label;"
             accesskey="&moveToGroup.accesskey;">
         <menupopup id="context_tabViewMenuPopup"
                    onpopupshowing="if (event.target == this) TabView.moveToGroupPopupShowing(event);">
           <menuseparator id="context_tabViewNamedGroups" hidden="true"/>
           <menuitem id="context_tabViewNewGroup" label="&moveToNewGroup.label;"
                     oncommand="TabView.moveTabTo(TabContextMenu.contextTab, null);"/>
@@ -211,63 +211,57 @@
                 accesskey="&social.activated.undobutton.accesskey;"
                 onclick="SocialUI.undoActivation();"/>
 #endif
           </hbox>
         </vbox>
       </hbox>
     </panel>
 
-    <panel id="editSharePopup"
+    <panel id="unsharePopup"
            type="arrow"
            orient="vertical"
            ignorekeys="true"
            hidden="true"
            onpopupshown="SocialShareButton.panelShown(event);"
            consumeoutsideclicks="true"
            level="top">
-      <row id="editSharePopupHeader" align="center">
+      <!-- Note that 'label', 'accesskey', 'value' and 'aria-label' attributes
+           for many of these elements are supplied by the provider and filled
+           in at runtime
+      -->
+      <row id="unsharePopupHeader" align="center">
         <vbox align="center">
-          <image id="socialUserPortrait" onclick="SocialUI.showProfile();"
-                 aria-label="&social.sharePopup.portrait.arialabel;"/>
+          <image id="socialUserPortrait" onclick="SocialUI.showProfile();"/>
         </vbox>
-        <vbox id="editSharePopupText">
+        <vbox id="unsharePopupText">
           <button id="socialUserDisplayName" pack="start"
                   oncommand="SocialUI.showProfile();"/>
           <spacer flex="1"/>
-          <label id="socialUserRecommendedText"
-                 value="&social.sharePopup.shared.label;"/>
+          <label id="socialUserRecommendedText"/>
         </vbox>
       </row>
-      <hbox id="editSharePopupBottomButtons" pack="end">
+      <hbox id="unsharePopupBottomButtons" pack="end">
 #ifdef XP_UNIX
-        <button id="editSharePopupUndoButton"
-                class="editSharePopupBottomButton"
-                label="&social.sharePopup.undo.label;"
-                accesskey="&social.sharePopup.undo.accesskey;"
+        <button id="unsharePopupStopSharingButton"
+                class="unsharePopupBottomButton"
                 command="Social:UnsharePage"/>
-        <button id="editSharePopupOkButton"
-                class="editSharePopupBottomButton"
+        <button id="unsharePopupContinueSharingButton"
+                class="unsharePopupBottomButton"
                 default="true"
                 autofocus="autofocus"
-                label="&social.ok.label;"
-                accesskey="&social.ok.accesskey;"
-                oncommand="SocialShareButton.dismissSharePopup();"/>
+                oncommand="SocialShareButton.dismissUnsharePopup();"/>
 #else
-        <button id="editSharePopupOkButton"
-                class="editSharePopupBottomButton"
+        <button id="unsharePopupContinueSharingButton"
+                class="unsharePopupBottomButton"
                 default="true"
                 autofocus="autofocus"
-                label="&social.ok.label;"
-                accesskey="&social.ok.accesskey;"
-                oncommand="SocialShareButton.dismissSharePopup();"/>
-        <button id="editSharePopupUndoButton"
-                class="editSharePopupBottomButton"
-                label="&social.sharePopup.undo.label;"
-                accesskey="&social.sharePopup.undo.accesskey;"
+                oncommand="SocialShareButton.dismissUnsharePopup();"/>
+        <button id="unsharePopupStopSharingButton"
+                class="unsharePopupBottomButton"
                 command="Social:UnsharePage"/>
 #endif
       </hbox>
     </panel>
 
     <panel id="social-notification-panel"
            class="social-panel"
            type="arrow"
--- a/browser/base/content/test/browser_social_shareButton.js
+++ b/browser/base/content/test/browser_social_shareButton.js
@@ -39,36 +39,36 @@ function tabLoaded() {
 
 function testInitial(finishcb) {
   ok(Social.provider, "Social provider is active");
   ok(Social.provider.enabled, "Social provider is enabled");
   let port = Social.provider.getWorkerPort();
   ok(port, "Social provider has a port to its FrameWorker");
   port.close();
 
-  let {shareButton, sharePopup} = SocialShareButton;
+  let {shareButton, unsharePopup} = SocialShareButton;
   ok(shareButton, "share button exists");
-  ok(sharePopup, "share popup exists");
+  ok(unsharePopup, "share popup exists");
 
-  let okButton = document.getElementById("editSharePopupOkButton");
-  let undoButton = document.getElementById("editSharePopupUndoButton");
+  let okButton = document.getElementById("unsharePopupContinueSharingButton");
+  let undoButton = document.getElementById("unsharePopupStopSharingButton");
   let shareStatusLabel = document.getElementById("share-button-status");
 
   // ensure the worker initialization and handshakes are all done and we
   // have a profile and the worker has responsed to the recommend-prompt msg.
   waitForCondition(function() Social.provider.profile && SocialShareButton.promptImages != null, function() {
     is(shareButton.hasAttribute("shared"), false, "Share button should not have 'shared' attribute before share button is clicked");
     // check dom values
     let profile = Social.provider.profile;
     let portrait = document.getElementById("socialUserPortrait").getAttribute("src");
     is(profile.portrait, portrait, "portrait is set");
     let displayName = document.getElementById("socialUserDisplayName");
     is(displayName.label, profile.displayName, "display name is set");
-    ok(!document.getElementById("editSharePopupHeader").hidden, "user profile is visible");
-  
+    ok(!document.getElementById("unsharePopupHeader").hidden, "user profile is visible");
+
     // Check the strings from our worker actually ended up on the button.
     is(shareButton.getAttribute("tooltiptext"), "Share this page", "check tooltip text is correct");
     is(shareStatusLabel.getAttribute("value"), "", "check status label text is blank");
     // Check the relative URL was resolved correctly (note this image has offsets of zero...)
     is(shareButton.style.backgroundImage, 'url("https://example.com/browser/browser/base/content/test/social_share_image.png")', "check image url is correct");
 
     // Test clicking the share button
     shareButton.addEventListener("click", function listener() {
@@ -80,74 +80,87 @@ function testInitial(finishcb) {
       is(shareButton.style.backgroundImage, 'url("https://example.com/browser/browser/base/content/test/social_share_image.png")', "check image url is correct");
       executeSoon(testSecondClick.bind(window, testPopupOKButton));
     });
     EventUtils.synthesizeMouseAtCenter(shareButton, {});
   }, "provider didn't provide user-recommend-prompt response");
 }
 
 function testSecondClick(nextTest) {
-  let {shareButton, sharePopup} = SocialShareButton;
-  sharePopup.addEventListener("popupshown", function listener() {
-    sharePopup.removeEventListener("popupshown", listener);
+  let {shareButton, unsharePopup} = SocialShareButton;
+  unsharePopup.addEventListener("popupshown", function listener() {
+    unsharePopup.removeEventListener("popupshown", listener);
     ok(true, "popup was shown after second click");
     executeSoon(nextTest);
   });
   EventUtils.synthesizeMouseAtCenter(shareButton, {});
 }
 
 function testPopupOKButton() {
-  let {shareButton, sharePopup} = SocialShareButton;
-  let okButton = document.getElementById("editSharePopupOkButton");
-  sharePopup.addEventListener("popuphidden", function listener() {
-    sharePopup.removeEventListener("popuphidden", listener);
+  let {shareButton, unsharePopup} = SocialShareButton;
+  let okButton = document.getElementById("unsharePopupContinueSharingButton");
+  unsharePopup.addEventListener("popuphidden", function listener() {
+    unsharePopup.removeEventListener("popuphidden", listener);
     is(shareButton.hasAttribute("shared"), true, "Share button should still have 'shared' attribute after OK button is clicked");
     executeSoon(testSecondClick.bind(window, testPopupUndoButton));
   });
   EventUtils.synthesizeMouseAtCenter(okButton, {});
 }
 
 function testPopupUndoButton() {
-  let {shareButton, sharePopup} = SocialShareButton;
-  let undoButton = document.getElementById("editSharePopupUndoButton");
-  sharePopup.addEventListener("popuphidden", function listener() {
-    sharePopup.removeEventListener("popuphidden", listener);
+  let {shareButton, unsharePopup} = SocialShareButton;
+  let undoButton = document.getElementById("unsharePopupStopSharingButton");
+  unsharePopup.addEventListener("popuphidden", function listener() {
+    unsharePopup.removeEventListener("popuphidden", listener);
     is(shareButton.hasAttribute("shared"), false, "Share button should not have 'shared' attribute after Undo button is clicked");
     executeSoon(testShortcut);
   });
   EventUtils.synthesizeMouseAtCenter(undoButton, {});
 }
 
 function testShortcut() {
   let keyTarget = window;
   keyTarget.addEventListener("keyup", function listener() {
     keyTarget.removeEventListener("keyup", listener);
     executeSoon(checkShortcutWorked.bind(window, keyTarget));
   });
   EventUtils.synthesizeKey("l", {accelKey: true, shiftKey: true}, keyTarget);
 }
 
 function checkShortcutWorked(keyTarget) {
-  let {sharePopup, shareButton} = SocialShareButton;
+  let {unsharePopup, shareButton} = SocialShareButton;
   is(shareButton.hasAttribute("shared"), true, "Share button should be in the 'shared' state after keyboard shortcut is used");
 
   // Test a second invocation of the shortcut
-  sharePopup.addEventListener("popupshown", function listener() {
-    sharePopup.removeEventListener("popupshown", listener);
+  unsharePopup.addEventListener("popupshown", function listener() {
+    unsharePopup.removeEventListener("popupshown", listener);
     ok(true, "popup was shown after second use of keyboard shortcut");
     executeSoon(checkOKButton);
   });
   EventUtils.synthesizeKey("l", {accelKey: true, shiftKey: true}, keyTarget);
 }
 
 function checkOKButton() {
-  let okButton = document.getElementById("editSharePopupOkButton");
-  let undoButton = document.getElementById("editSharePopupUndoButton");
+  let okButton = document.getElementById("unsharePopupContinueSharingButton");
+  let undoButton = document.getElementById("unsharePopupStopSharingButton");
   is(document.activeElement, okButton, "ok button should be focused by default");
 
+  // the undo button text, label text, access keys, etc  should be as
+  // specified by the provider.
+  function isEltAttr(eltid, attr, expected) {
+    is(document.getElementById(eltid).getAttribute(attr), expected,
+       "element '" + eltid + "' has correct value for attribute '" + attr + "'");
+  }
+  isEltAttr("socialUserRecommendedText", "value", "You have already shared this page");
+  isEltAttr("unsharePopupContinueSharingButton", "label", "Got it!");
+  isEltAttr("unsharePopupContinueSharingButton", "accesskey", "G");
+  isEltAttr("unsharePopupStopSharingButton", "label", "Unshare it!");
+  isEltAttr("unsharePopupStopSharingButton", "accesskey", "U");
+  isEltAttr("socialUserPortrait", "aria-label", "Your pretty face");
+
   // This rest of particular test doesn't really apply on Mac, since buttons
   // aren't focusable by default.
   if (navigator.platform.contains("Mac")) {
     executeSoon(testCloseBySpace);
     return;
   }
 
   let displayName = document.getElementById("socialUserDisplayName");
@@ -178,20 +191,20 @@ function checkNextInTabOrder(element, ne
   // Register a cleanup function to remove the listener in case this test fails
   registerCleanupFunction(function () {
     element.removeEventListener("focus", listener);
   });
   EventUtils.synthesizeKey("VK_TAB", {});
 }
 
 function testCloseBySpace() {
-  let sharePopup = SocialShareButton.sharePopup;
-  is(document.activeElement.id, "editSharePopupOkButton", "testCloseBySpace, the ok button should be focused");
-  sharePopup.addEventListener("popuphidden", function listener() {
-    sharePopup.removeEventListener("popuphidden", listener);
+  let unsharePopup = SocialShareButton.unsharePopup;
+  is(document.activeElement.id, "unsharePopupContinueSharingButton", "testCloseBySpace, the ok button should be focused");
+  unsharePopup.addEventListener("popuphidden", function listener() {
+    unsharePopup.removeEventListener("popuphidden", listener);
     ok(true, "space closed the share popup");
     executeSoon(testStillSharedIn2Tabs);
   });
   EventUtils.synthesizeKey("VK_SPACE", {});
 }
 
 function testStillSharedIn2Tabs() {
   let toShare = "http://example.com";
--- a/browser/base/content/test/social_worker.js
+++ b/browser/base/content/test/social_worker.js
@@ -103,15 +103,21 @@ onconnect = function(e) {
               // absolute to check we handle them too.
               unshare: "https://example.com/browser/browser/base/content/test/social_share_image.png"
             },
             messages: {
               shareTooltip: "Share this page",
               unshareTooltip: "Unshare this page",
               sharedLabel: "This page has been shared",
               unsharedLabel: "This page is no longer shared",
+              unshareLabel: "You have already shared this page",
+              portraitLabel: "Your pretty face",
+              unshareConfirmLabel: "Unshare it!",
+              unshareConfirmAccessKey: "U",
+              unshareCancelLabel: "Got it!",
+              unshareCancelAccessKey: "G"
             }
           }
         });
         break;
     }
   }
 }
--- a/browser/components/preferences/aboutPermissions.js
+++ b/browser/components/preferences/aboutPermissions.js
@@ -756,22 +756,28 @@ let AboutPermissions = {
 
     let permissionMenulist = document.getElementById(aType + "-menulist");
     let permissionValue;
     if (!this._selectedSite) {
       // If there is no selected site, we are updating the default permissions interface.
       permissionValue = PermissionDefaults[aType];
       if (aType == "plugins")
         document.getElementById("plugins-pref-item").hidden = false;
+      else if (aType == "cookie")
+	// cookie-9 corresponds to ALLOW_FIRST_PARTY_ONLY, which is reserved
+	// for site-specific preferences only.
+	document.getElementById("cookie-9").hidden = true;
     } else {
       if (aType == "plugins") {
         document.getElementById("plugins-pref-item").hidden =
           !Services.prefs.getBoolPref("plugins.click_to_play");
         return;
       }
+      if (aType == "cookie")
+        document.getElementById("cookie-9").hidden = false;
       let result = {};
       permissionValue = this._selectedSite.getPermission(aType, result) ?
                         result.value : PermissionDefaults[aType];
     }
 
     permissionMenulist.selectedItem = document.getElementById(aType + "-" + permissionValue);
   },
 
--- a/browser/components/preferences/aboutPermissions.xul
+++ b/browser/components/preferences/aboutPermissions.xul
@@ -122,16 +122,17 @@
           <hbox align="center">
             <menulist id="cookie-menulist"
                       class="pref-menulist"
                       type="cookie"
                       oncommand="AboutPermissions.onPermissionCommand(event);">
               <menupopup>
                 <menuitem id="cookie-1" value="1" label="&permission.allow;"/>
                 <menuitem id="cookie-8" value="8" label="&permission.allowForSession;"/>
+                <menuitem id="cookie-9" value="9" label="&permission.allowFirstPartyOnly;"/>
                 <menuitem id="cookie-2" value="2" label="&permission.block;"/>
               </menupopup>
             </menulist>
             <button id="cookies-clear-all-button"
                     label="&cookie.removeAll;"
                     oncommand="Services.cookies.removeAll();"/>
             <button id="cookies-manage-all-button"
                     label="&cookie.manage;"
--- a/browser/components/preferences/tests/browser_chunk_permissions.js
+++ b/browser/components/preferences/tests/browser_chunk_permissions.js
@@ -9,17 +9,16 @@ const ABOUT_PERMISSIONS_SPEC = "about:pe
 const TEST_URI_1 = NetUtil.newURI("http://mozilla.com/");
 const TEST_URI_2 = NetUtil.newURI("http://mozilla.org/");
 const TEST_URI_3 = NetUtil.newURI("http://wikipedia.org/");
 
 // values from DefaultPermissions object
 const PERM_UNKNOWN = 0;
 const PERM_ALLOW = 1;
 const PERM_DENY = 2;
-const PERM_SESION = 8;
 
 // used to set permissions on test sites
 const TEST_PERMS = {
   "password": PERM_ALLOW,
   "cookie": PERM_ALLOW,
   "geo": PERM_UNKNOWN,
   "indexedDB": PERM_UNKNOWN,
   "popup": PERM_DENY
--- a/browser/components/preferences/tests/browser_permissions.js
+++ b/browser/components/preferences/tests/browser_permissions.js
@@ -11,17 +11,18 @@ const TEST_URI_2 = NetUtil.newURI("http:
 
 const TEST_PRINCIPAL_1 = Services.scriptSecurityManager.getNoAppCodebasePrincipal(TEST_URI_1);
 const TEST_PRINCIPAL_2 = Services.scriptSecurityManager.getNoAppCodebasePrincipal(TEST_URI_2);
 
 // values from DefaultPermissions object
 const PERM_UNKNOWN = 0;
 const PERM_ALLOW = 1;
 const PERM_DENY = 2;
-const PERM_SESION = 8;
+// cookie specific permissions
+const PERM_FIRST_PARTY_ONLY = 9;
 
 // used to set permissions on test sites
 const TEST_PERMS = {
   "password": PERM_ALLOW,
   "cookie": PERM_ALLOW,
   "geo": PERM_UNKNOWN,
   "indexedDB": PERM_UNKNOWN,
   "popup": PERM_DENY,
@@ -248,16 +249,28 @@ var tests = [
     // change a permisssion in the UI
     let geoAllowItem = gBrowser.contentDocument.getElementById("geo-" + PERM_ALLOW);
     geoMenulist.selectedItem = geoAllowItem;
     geoMenulist.doCommand();
     // check to make sure this change is reflected in the permission manager
     is(Services.perms.testPermissionFromPrincipal(TEST_PRINCIPAL_2, "geo"), PERM_ALLOW,
        "permission manager shows that geolocation is allowed");
 
+
+    // change a site-specific cookie permission, just for fun
+    let cookieMenuList = getPermissionMenulist("cookie");
+    let cookieItem = gBrowser.contentDocument.getElementById("cookie-" + PERM_FIRST_PARTY_ONLY);
+    cookieMenuList.selectedItem = cookieItem;
+    cookieMenuList.doCommand();
+    is(cookieMenuList.value, PERM_FIRST_PARTY_ONLY, "menulist correctly shows that " +
+       "first party only cookies are allowed");
+    is(Services.perms.testPermissionFromPrincipal(TEST_PRINCIPAL_2, "cookie"),
+       PERM_FIRST_PARTY_ONLY, "permission manager shows that first party cookies " +
+       "are allowed");
+
     runNextTest();
   },
 
   function test_forget_site() {
     // click "Forget About This Site" button
     gBrowser.contentDocument.getElementById("forget-site-button").doCommand();
 
     is(gSiteLabel.value, "", "site label cleared");
--- a/browser/locales/en-US/chrome/browser/browser.dtd
+++ b/browser/locales/en-US/chrome/browser/browser.dtd
@@ -18,25 +18,25 @@
 <!-- Tab context menu -->
 <!ENTITY  reloadTab.label                    "Reload Tab">
 <!ENTITY  reloadTab.accesskey                "R">
 <!ENTITY  reloadAllTabs.label                "Reload All Tabs">
 <!ENTITY  reloadAllTabs.accesskey            "A">
 <!ENTITY  closeOtherTabs.label               "Close Other Tabs">
 <!ENTITY  closeOtherTabs.accesskey           "o">
 
-<!-- LOCALIZATION NOTE (pinAppTab.label, unpinAppTab.label): "Pin" is being
+<!-- LOCALIZATION NOTE (pinTab.label, unpinTab.label): "Pin" is being
 used as a metaphor for expressing the fact that these tabs are "pinned" to the
 left edge of the tabstrip. Really we just want the string to express the idea
 that this is a lightweight and reversible action that keeps your tab where you
 can reach it easily. -->
-<!ENTITY  pinAppTab.label                    "Pin as App Tab">
-<!ENTITY  pinAppTab.accesskey                "P">
-<!ENTITY  unpinAppTab.label                  "Unpin Tab">
-<!ENTITY  unpinAppTab.accesskey              "b">
+<!ENTITY  pinTab.label                       "Pin Tab">
+<!ENTITY  pinTab.accesskey                   "P">
+<!ENTITY  unpinTab.label                     "Unpin Tab">
+<!ENTITY  unpinTab.accesskey                 "b">
 <!ENTITY  moveToGroup.label                  "Move to Group">
 <!ENTITY  moveToGroup.accesskey              "M">
 <!ENTITY  moveToNewGroup.label               "New Group">
 <!ENTITY  moveToNewWindow.label              "Move to New Window">
 <!ENTITY  moveToNewWindow.accesskey          "W">
 <!ENTITY  bookmarkAllTabs.label              "Bookmark All Tabs…">
 <!ENTITY  bookmarkAllTabs.accesskey          "T">
 <!ENTITY  undoCloseTab.label                 "Undo Close Tab">
@@ -640,26 +640,16 @@ doesn't display any label, but exposes a
 <!ENTITY markupButton.arialabel          "Markup">
 <!-- LOCALIZATION NOTE (markupButton.accesskey): The key bound to the Markup panel's
 toolbar button -->
 <!ENTITY markupButton.accesskey          "M">
 
 <!ENTITY socialToolbar.title        "Social Toolbar Button">
 <!ENTITY social.notLoggedIn.label   "Not logged in">
 
-<!-- LOCALIZATION NOTE (social.ok.label, social.ok.accesskey): this string is
-     used for the "OK" button for two different social panels. One appears when
-     the feature is activated (social.activated.* below), and the other when
-     the user clicks the "Share" button a second time (social.sharePopup.*
-     below). -->
 <!ENTITY social.ok.label       "OK">
 <!ENTITY social.ok.accesskey   "O">
 
-<!ENTITY social.sharePopup.undo.label     "Unshare">
-<!ENTITY social.sharePopup.undo.accesskey "U">
-<!ENTITY social.sharePopup.shared.label   "You shared this page.">
-<!ENTITY social.sharePopup.portrait.arialabel "User profile picture">
-
 <!ENTITY social.toggleSidebar.label "Show sidebar">
 <!ENTITY social.toggleSidebar.accesskey "s">
 
 <!ENTITY social.activated.undobutton.label "Undo">
 <!ENTITY social.activated.undobutton.accesskey "U">
--- a/browser/locales/en-US/chrome/browser/preferences/aboutPermissions.dtd
+++ b/browser/locales/en-US/chrome/browser/preferences/aboutPermissions.dtd
@@ -15,16 +15,17 @@
 
 <!ENTITY header.defaults                 "Default Permissions for All Sites">
 
 <!ENTITY permissions.forgetSite          "Forget About This Site">
 
 <!ENTITY permission.alwaysAsk            "Always Ask">
 <!ENTITY permission.allow                "Allow">
 <!ENTITY permission.allowForSession      "Allow for Session">
+<!ENTITY permission.allowFirstPartyOnly  "Allow First Party Only">
 <!ENTITY permission.block                "Block">
 
 <!ENTITY password.label                  "Store Passwords">
 <!ENTITY password.manage                 "Manage Passwords…">
 
 <!ENTITY cookie.label                    "Set Cookies">
 <!ENTITY cookie.remove                   "Remove Cookies">
 <!ENTITY cookie.manage                   "Manage Cookies…">
--- a/browser/themes/gnomestripe/browser.css
+++ b/browser/themes/gnomestripe/browser.css
@@ -1403,21 +1403,21 @@ richlistitem[type~="action"][actiontype=
   border-top-width: 0;
 }
 
 #socialUserDisplayName:hover {
   color: -moz-nativehyperlinktext;
   text-decoration: underline;
 }
 
-#editSharePopupText {
+#unsharePopupText {
   height: 48px;
 }
 
-#editSharePopupBottomButtons {
+#unsharePopupBottomButtons {
   margin-top: 1em;
 }
 
 /* Star button */
 #star-button {
   padding: 1px;
   list-style-image: url("chrome://browser/skin/places/starPage.png");
 }
@@ -2558,20 +2558,25 @@ html|*#gcli-output-frame {
 .developer-toolbar-button[open=true],
 .developer-toolbar-button:active:hover,
 .developer-toolbar-button[checked=true] {
   border-color: hsla(210,8%,5%,.6);
   background: rgba(0,0,0,.6);
   box-shadow: 0 1px 2px rgba(0,0,0,.5) inset, 0 1px 0 hsla(210,16%,76%,.15);
 }
 
-.developer-toolbar-button[checked=true] {
+.developer-toolbar-button:hover,
+.developer-toolbar-button[checked=true],
+.developer-toolbar-button[open=true] {
   color: hsl(208,100%,60%) !important;
+  text-shadow: 0 0 6px hsl(208,100%,60%);
+}
+
+.developer-toolbar-button[checked=true] {
   background: rgba(0,0,0,.4);
-  text-shadow: 0 0 6px hsl(208,100%,60%);
 }
 
 #developer-toolbar-webconsole {
   -moz-image-region: rect(0, 16px, 16px, 0);
 }
 
 #developer-toolbar-inspector {
   -moz-image-region: rect(16px, 16px, 32px, 0);
--- a/browser/themes/pinstripe/browser.css
+++ b/browser/themes/pinstripe/browser.css
@@ -1275,21 +1275,21 @@ window[tabsontop="false"] richlistitem[t
   border-top-width: 0;
 }
 
 #socialUserDisplayName:hover {
   color: -moz-nativehyperlinktext;
   text-decoration: underline;
 }
 
-#editSharePopupText {
+#unsharePopupText {
   height: 48px;
 }
 
-#editSharePopupBottomButtons {
+#unsharePopupBottomButtons {
   margin-top: 1em;
 }
 
 /* STAR BUTTON */
 #star-button {
   list-style-image: url("chrome://browser/skin/places/star-icons.png");
   -moz-image-region: rect(0, 16px, 16px, 0);
 }
--- a/browser/themes/winstripe/browser.css
+++ b/browser/themes/winstripe/browser.css
@@ -1666,21 +1666,21 @@ richlistitem[type~="action"][actiontype=
   border-top-width: 0;
 }
 
 #socialUserDisplayName:hover {
   color: -moz-nativehyperlinktext;
   text-decoration: underline;
 }
 
-#editSharePopupText {
+#unsharePopupText {
   height: 48px;
 }
 
-#editSharePopupBottomButtons {
+#unsharePopupBottomButtons {
   margin-top: 1em;
 }
 
 /* star button */
 
 #star-button {
   list-style-image: url("chrome://browser/skin/places/bookmark.png");
   -moz-image-region: rect(0px 16px 16px 0px);
@@ -3235,20 +3235,25 @@ html|*#gcli-output-frame {
 .developer-toolbar-button[open=true],
 .developer-toolbar-button:active:hover,
 .developer-toolbar-button[checked=true] {
   border-color: hsla(210,8%,5%,.6);
   background: rgba(0,0,0,.6);
   box-shadow: 0 1px 2px rgba(0,0,0,.5) inset, 0 1px 0 hsla(210,16%,76%,.1);
 }
 
-.developer-toolbar-button[checked=true] {
+.developer-toolbar-button:hover,
+.developer-toolbar-button[checked=true],
+.developer-toolbar-button[open=true] {
   color: hsl(208,100%,60%) !important;
+  text-shadow: 0 0 6px hsl(208,100%,60%);
+}
+
+.developer-toolbar-button[checked=true] {
   background: rgba(0,0,0,.4);
-  text-shadow: 0 0 6px hsl(208,100%,60%);
 }
 
 #developer-toolbar-webconsole {
   -moz-image-region: rect(0, 16px, 16px, 0);
 }
 
 #developer-toolbar-inspector {
   -moz-image-region: rect(16px, 16px, 32px, 0);
--- a/build/Makefile.in
+++ b/build/Makefile.in
@@ -145,17 +145,18 @@ endif
 libs:: $(_LEAKTEST_FILES)
 	$(INSTALL) $^ $(_LEAKTEST_DIR)
 
 ifdef MOZ_VALGRIND
 _VALGRIND_DIR = $(DEPTH)/_valgrind
 GARBAGE_DIRS += $(_VALGRIND_DIR)
 
 _VALGRIND_FILES = \
-		$(topsrcdir)/build/valgrind/i686-redhat-linux-gnu.sup \
+		$(topsrcdir)/build/valgrind/cross-architecture.sup \
+		$(topsrcdir)/build/valgrind/i386-redhat-linux-gnu.sup \
 		$(topsrcdir)/build/valgrind/x86_64-redhat-linux-gnu.sup \
 		$(NULL)
 
 libs:: $(_VALGRIND_FILES)
 	$(INSTALL) $^ $(_VALGRIND_DIR)
 endif
 
 ifdef ENABLE_TESTS
--- a/build/automation.py.in
+++ b/build/automation.py.in
@@ -493,16 +493,19 @@ function FindProxyForURL(url, host)
 
       part += """
 user_pref("network.proxy.type", 2);
 user_pref("network.proxy.autoconfig_url", "%(pacURL)s");
 
 user_pref("camino.use_system_proxy_settings", false); // Camino-only, harmless to others
 """ % {"pacURL": pacURL}
       prefs.append(part)
+    else:
+      part = 'user_pref("network.proxy.type", 0);\n'
+      prefs.append(part)
 
     for v in extraPrefs:
       thispref = v.split("=", 1)
       if len(thispref) < 2:
         print "Error: syntax error in --setpref=" + v
         sys.exit(1)
       part = 'user_pref("%s", %s);\n' % (thispref[0], thispref[1])
       prefs.append(part)
--- a/build/pymake/pymake/data.py
+++ b/build/pymake/pymake/data.py
@@ -1,16 +1,21 @@
 """
 A representation of makefile data structures.
 """
 
 import logging, re, os, sys
 import parserdata, parser, functions, process, util, implicit
 from cStringIO import StringIO
 
+if sys.version_info[0] < 3:
+    str_type = basestring
+else:
+    str_type = str
+
 _log = logging.getLogger('pymake.data')
 
 class DataError(util.MakeError):
     pass
 
 class ResolutionError(DataError):
     """
     Raised when dependency resolution fails, either due to recursion or to missing
@@ -136,17 +141,17 @@ class StringExpansion(BaseExpansion):
 
     This essentially wraps a single str instance.
     """
 
     __slots__ = ('loc', 's',)
     simple = True
 
     def __init__(self, s, loc):
-        assert isinstance(s, str)
+        assert isinstance(s, str_type)
         self.s = s
         self.loc = loc
 
     def lstrip(self):
         self.s = self.s.lstrip()
 
     def rstrip(self):
         self.s = self.s.rstrip()
@@ -222,17 +227,17 @@ class Expansion(BaseExpansion, list):
         return StringExpansion(s, parserdata.Location(path, 1, 0))
 
     def clone(self):
         e = Expansion()
         e.extend(self)
         return e
 
     def appendstr(self, s):
-        assert isinstance(s, str)
+        assert isinstance(s, str_type)
         if s == '':
             return
 
         self.append((s, False))
 
     def appendfunc(self, func):
         assert isinstance(func, functions.Function)
         self.append((func, True))
@@ -316,19 +321,19 @@ class Expansion(BaseExpansion, list):
         assert isinstance(makefile, Makefile)
         assert isinstance(variables, Variables)
         assert isinstance(setting, list)
 
         for e, isfunc in self:
             if isfunc:
                 e.resolve(makefile, variables, fd, setting)
             else:
-                assert isinstance(e, str)
+                assert isinstance(e, str_type)
                 fd.write(e)
-                    
+
     def resolvestr(self, makefile, variables, setting=[]):
         fd = StringIO()
         self.resolve(makefile, variables, fd, setting)
         return fd.getvalue()
 
     def resolvesplit(self, makefile, variables, setting=[]):
         return self.resolvestr(makefile, variables, setting).split()
 
@@ -496,29 +501,29 @@ class Variables(object):
         if self.parent is not None:
             return self.parent.get(name, expand)
 
         return (None, None, None)
 
     def set(self, name, flavor, source, value):
         assert flavor in (self.FLAVOR_RECURSIVE, self.FLAVOR_SIMPLE)
         assert source in (self.SOURCE_OVERRIDE, self.SOURCE_COMMANDLINE, self.SOURCE_MAKEFILE, self.SOURCE_ENVIRONMENT, self.SOURCE_AUTOMATIC, self.SOURCE_IMPLICIT)
-        assert isinstance(value, str), "expected str, got %s" % type(value)
+        assert isinstance(value, str_type), "expected str, got %s" % type(value)
 
         prevflavor, prevsource, prevvalue = self.get(name)
         if prevsource is not None and source > prevsource:
             # TODO: give a location for this warning
             _log.info("not setting variable '%s', set by higher-priority source to value '%s'" % (name, prevvalue))
             return
 
         self._map[name] = flavor, source, value, None
 
     def append(self, name, source, value, variables, makefile):
         assert source in (self.SOURCE_OVERRIDE, self.SOURCE_MAKEFILE, self.SOURCE_AUTOMATIC)
-        assert isinstance(value, str)
+        assert isinstance(value, str_type)
 
         if name not in self._map:
             self._map[name] = self.FLAVOR_APPEND, source, value, None
             return
 
         prevflavor, prevsource, prevvalue, valueexp = self._map[name]
         if source > prevsource:
             # TODO: log a warning?
@@ -641,17 +646,17 @@ class Pattern(object):
 
     def subst(self, replacement, word, mustmatch):
         """
         Given a word, replace the current pattern with the replacement pattern, a la 'patsubst'
 
         @param mustmatch If true and this pattern doesn't match the word, throw a DataError. Otherwise
                          return word unchanged.
         """
-        assert isinstance(replacement, str)
+        assert isinstance(replacement, str_type)
 
         stem = self.match(word)
         if stem is None:
             if mustmatch:
                 raise DataError("target '%s' doesn't match pattern" % (word,))
             return word
 
         if not self.ispattern():
@@ -960,17 +965,17 @@ class Target(object):
 
     The rules associated with this target may be Rule instances or, in the case of static pattern
     rules, PatternRule instances.
     """
 
     wasremade = False
 
     def __init__(self, target, makefile):
-        assert isinstance(target, str)
+        assert isinstance(target, str_type)
         self.target = target
         self.vpathtarget = None
         self.rules = []
         self.variables = Variables(makefile.variables)
         self.explicit = False
         self._state = MAKESTATE_NONE
 
     def addrule(self, rule):
@@ -1682,17 +1687,17 @@ class Makefile(object):
         for p, v in self._patternvariables:
             if p.match(target):
                 yield v
 
     def hastarget(self, target):
         return target in self._targets
 
     def gettarget(self, target):
-        assert isinstance(target, str)
+        assert isinstance(target, str_type)
 
         target = target.rstrip('/')
 
         assert target != '', "empty target?"
 
         if target.find('*') != -1 or target.find('?') != -1 or target.find('[') != -1:
             raise DataError("wildcards should have been expanded by the parser: '%s'" % (target,))
 
copy from build/valgrind/x86_64-redhat-linux-gnu.sup
copy to build/valgrind/cross-architecture.sup
--- a/build/valgrind/x86_64-redhat-linux-gnu.sup
+++ b/build/valgrind/cross-architecture.sup
@@ -1,178 +1,150 @@
+####################
+#  Intended leaks  #
+####################
+
+{
+   PR_SetEnv requires its argument to be leaked, but does not appear on stacks. (See bug 793534 and see bug 793549.)
+   Memcheck:Leak
+   ...
+   fun:_ZL9SaveToEnvPKc
+   ...
+}
+{
+   PR_SetEnv requires its argument to be leaked, but does not appear on stacks. (See bug 793534 and see bug 793549.)
+   Memcheck:Leak
+   ...
+   fun:_ZL13SaveWordToEnvPKcRK19nsACString_internal
+   ...
+}
+{
+   See bug 793535
+   Memcheck:Leak
+   fun:calloc
+   fun:_dlerror_run
+   fun:dlsym
+   ...
+}
+{
+   See bug 793611
+   Memcheck:Leak
+   fun:memalign
+   fun:tls_get_addr_tail
+   fun:__tls_get_addr
+   ...
+}
+
+#################
+#  Other leaks  #
+#################
+
 {
    Bug 793532
    Memcheck:Leak
    fun:malloc
    fun:_ZN8JSObject25allocateSlowArrayElementsEP9JSContext
    ...
 }
-{
-   Bug 793533
-   Memcheck:Leak
-   fun:malloc
-   fun:moz_xmalloc
-   fun:_Z22xpc_CreateGlobalObjectP9JSContextP7JSClassP12nsIPrincipalP11nsISupportsbPP8JSObjectPP13JSCompartment
-   ...
-}
+# Suppressing the suppression(s) to get Valgrind stacks with line numbers
+#{
+#   Bug 793533
+#   Memcheck:Leak
+#   fun:malloc
+#   fun:moz_xmalloc
+#   fun:_Z22xpc_CreateGlobalObjectP9JSContextP7JSClassP12nsIPrincipalP11nsISupportsbPP8JSObjectPP13JSCompartment
+#   ...
+#}
 {
-   This is intended, see bug 793534
-   Memcheck:Leak
-   fun:malloc
-   fun:strdup
-   fun:moz_strdup
-   fun:_ZL9SaveToEnvPKc
-   ...
-}
-{
-   Bug 793535
-   Memcheck:Leak
-   fun:calloc
-   fun:_dlerror_run
-   fun:dlsym
-   fun:PR_SetCurrentThreadName
-   ...
-}
-{
-   Bug 793536
+   Bug 793536 (all 64-bit systems)
    Memcheck:Leak
    fun:malloc
    fun:moz_xmalloc
    fun:_ZNSt11_Deque_baseIN11MessageLoop11PendingTaskESaIS1_EE17_M_initialize_mapEm
    ...
 }
 {
-   Bug 793537
+   Bug 793536 (all 32-bit systems)
    Memcheck:Leak
-   ...
-   obj:/usr/lib64/libpango-1.0.so.0.2800.1
-   ...
-}
-{
-   Bug 793539 which may be fixed or change when bug 713802 is fixed
-   Memcheck:Leak
-   ...
-   obj:/usr/lib64/libgnomevfs-2.so.0.2400.2
+   fun:malloc
+   fun:moz_xmalloc
+   fun:_ZNSt11_Deque_baseIN11MessageLoop11PendingTaskESaIS1_EE17_M_initialize_mapEj
    ...
 }
 {
    Bug 793548
    Memcheck:Leak
    fun:malloc
    fun:moz_xmalloc
    fun:NS_Alloc_P
    fun:_Z12ToNewCStringRK19nsACString_internal
    fun:_ZN13CrashReporter14SetupExtraDataEP7nsIFileRK19nsACString_internal
    ...
 }
-{
-   Bug 793549
-   Memcheck:Leak
-   fun:realloc
-   fun:PR_Realloc
-   fun:GrowStuff
-   ...
-}
-{
-   Bug 793598
-   Memcheck:Leak
-   fun:realloc
-   ...
-   obj:/lib64/libdbus-1.so.3.4.0
-   ...
-}
-{
-   Bug 793600
-   Memcheck:Leak
-   fun:realloc
-   obj:/usr/lib64/libfontconfig.so.1.4.4
-   obj:/usr/lib64/libfontconfig.so.1.4.4
-   fun:FcDefaultSubstitute
-   fun:_ZN17gfxPangoFontGroup11MakeFontSetEP14_PangoLanguagedP9nsAutoRefI10_FcPatternE
-   ...
-}
-{
-   Bug 793601
-   Memcheck:Leak
-   fun:malloc
-   fun:_ZN2js15ArgumentsObject6createEP9JSContextPNS_10StackFrameE
-   ...
-}
-{
-   Bug 793602
-   Memcheck:Leak
-   fun:malloc
-   fun:moz_xmalloc
-   fun:_Z22NS_NewComputedDOMStylePN7mozilla3dom7ElementERK18nsAString_internalP12nsIPresShell
-   fun:_ZN14nsGlobalWindow16GetComputedStyleEP13nsIDOMElementRK18nsAString_internalPP25nsIDOMCSSStyleDeclaration
-   ...
-}
-{
-   Bug 793603
-   Memcheck:Leak
-   fun:malloc
-   fun:moz_xmalloc
-   fun:_ZN18nsDeflateConverter15OnDataAvailableEP10nsIRequestP11nsISupportsP14nsIInputStreammj
-   ...
-}
-{
-   Bug 793605
-   Memcheck:Leak
-   fun:malloc
-   fun:moz_xmalloc
-   fun:_Z30nsStringInputStreamConstructorP11nsISupportsRK4nsIDPPv
-   ...
-}
-{
-   Bug 793606
-   Memcheck:Leak
-   fun:malloc
-   fun:moz_xmalloc
-   fun:_ZL27nsXMLHttpRequestConstructorP11nsISupportsRK4nsIDPPv
-   ...
-}
-{
-   Bug 793607
-   Memcheck:Leak
-   fun:malloc
-   fun:moz_xmalloc
-   fun:_ZN11nsZipWriter14AddEntryStreamERK19nsACString_internalliP14nsIInputStreambj
-   ...
-}
+#{
+#   Bug 793601
+#   Memcheck:Leak
+#   fun:malloc
+#   fun:_ZN2js15ArgumentsObject6createEP9JSContextPNS_10StackFrameE
+#   ...
+#}
+#{
+#   Bug 793602
+#   Memcheck:Leak
+#   fun:malloc
+#   fun:moz_xmalloc
+#   fun:_Z22NS_NewComputedDOMStylePN7mozilla3dom7ElementERK18nsAString_internalP12nsIPresShell
+#   fun:_ZN14nsGlobalWindow16GetComputedStyleEP13nsIDOMElementRK18nsAString_internalPP25nsIDOMCSSStyleDeclaration
+#   ...
+#}
+#{
+#   Bug 793603
+#   Memcheck:Leak
+#   fun:malloc
+#   fun:moz_xmalloc
+#   fun:_ZN18nsDeflateConverter15OnDataAvailableEP10nsIRequestP11nsISupportsP14nsIInputStreammj
+#   ...
+#}
+#{
+#   Bug 793605
+#   Memcheck:Leak
+#   fun:malloc
+#   fun:moz_xmalloc
+#   fun:_Z30nsStringInputStreamConstructorP11nsISupportsRK4nsIDPPv
+#   ...
+#}
+#{
+#   Bug 793606
+#   Memcheck:Leak
+#   fun:malloc
+#   fun:moz_xmalloc
+#   fun:_ZL27nsXMLHttpRequestConstructorP11nsISupportsRK4nsIDPPv
+#   ...
+#}
+#{
+#   Bug 793607
+#   Memcheck:Leak
+#   fun:malloc
+#   fun:moz_xmalloc
+#   fun:_ZN11nsZipWriter14AddEntryStreamERK19nsACString_internalliP14nsIInputStreambj
+#   ...
+#}
 {
    Bug 793608
    Memcheck:Leak
-   fun:malloc
-   fun:__libc_res_nsend
-   fun:__libc_res_nquery
-   fun:__libc_res_nquerydomain
-   fun:__libc_res_nsearch
-   obj:*
+   ...
    fun:gaih_inet
    fun:getaddrinfo
    fun:PR_GetAddrInfoByName
    fun:_ZN14nsHostResolver10ThreadFuncEPv
    fun:_pt_root
    fun:start_thread
    fun:clone
 }
 {
-   Bug 793611
-   Memcheck:Leak
-   fun:memalign
-   fun:tls_get_addr_tail
-   fun:__tls_get_addr
-   fun:_ZN8nsThread16ProcessNextEventEbPb
-   fun:_Z21NS_ProcessNextEvent_PP9nsIThreadb
-   fun:_ZN8nsThread10ThreadFuncEPv
-   fun:_pt_root
-   fun:start_thread
-   fun:clone
-}
-{
    Bug 793615
    Memcheck:Leak
    fun:malloc
    fun:sqlite3MemMalloc
    ...
 }
 {
    Bug 793616
@@ -182,8 +154,86 @@
    fun:__check_pf
    fun:getaddrinfo
    fun:PR_GetAddrInfoByName
    fun:_ZN14nsHostResolver10ThreadFuncEPv
    fun:_pt_root
    fun:start_thread
    fun:clone
 }
+{
+   Bug 794350
+   Memcheck:Leak
+   fun:malloc
+   fun:moz_xmalloc
+   fun:_ZN11MessageLoopC1ENS_4TypeE
+   fun:_ZN4base6Thread10ThreadMainEv
+   fun:_ZL10ThreadFuncPv
+   fun:start_thread
+   fun:clone
+}
+{
+   Bug 794354
+   Memcheck:Leak
+   ...
+   fun:_ZN7mozilla12safebrowsing10Classifier12ApplyUpdatesEP8nsTArrayIPNS0_11TableUpdateE24nsTArrayDefaultAllocatorE
+   fun:_ZN30nsUrlClassifierDBServiceWorker11ApplyUpdateEv
+   fun:_ZN30nsUrlClassifierDBServiceWorker12FinishUpdateEv
+   ...
+}
+{
+   Bug 794358
+   Memcheck:Leak
+   fun:malloc
+   ...
+   fun:PK11_InitPin
+   fun:_ZN11nsPK11Token12InitPasswordEPKt
+   ...
+}
+{
+   Bug 794364
+   Memcheck:Leak
+   fun:malloc
+   fun:_ZN9PICLinker4initEP9JSContext
+   fun:_ZN2js4mjit2ic12GetElementIC13attachGetPropERNS_7VMFrameEN2JS6HandleIP8JSObjectEENS6_INS5_5ValueEEENS6_IPNS_12PropertyNameEEENS5_13MutableHandleISA_EE
+   fun:_ZN2js4mjit2ic12GetElementIC6updateERNS_7VMFrameEN2JS6HandleIP8JSObjectEENS6_INS5_5ValueEEENS6_IlEENS5_13MutableHandleISA_EE
+   fun:_ZN2js4mjit2ic10GetElementERNS_7VMFrameEPNS1_12GetElementICE
+   ...
+}
+{
+   Bug 794365
+   Memcheck:Leak
+   fun:malloc
+   fun:_ZN14JSInlineString8uninlineEP9JSContext
+   ...
+}
+{
+   Bug 794369
+   Memcheck:Leak
+   fun:malloc
+   fun:moz_xmalloc
+   fun:_ZN20mozJSComponentLoader10LoadModuleERN7mozilla12FileLocationE
+   ...
+}
+{
+   Bug 794370
+   Memcheck:Leak
+   fun:malloc
+   fun:moz_xmalloc
+   fun:_ZN22nsComponentManagerImpl15RegisterFactoryERK4nsIDPKcS4_P10nsIFactory
+   ...
+}
+{
+   Bug 794372
+   Memcheck:Leak
+   fun:malloc
+   fun:moz_xmalloc
+   fun:_ZN22nsComponentManagerImpl16RegisterCIDEntryEPKN7mozilla6Module8CIDEntryEPNS_11KnownModuleE
+   ...
+}
+{
+   Bug 794374
+   Memcheck:Leak
+   fun:malloc
+   fun:moz_xmalloc
+   fun:_ZN22nsComponentManagerImpl17ManifestComponentERNS_25ManifestProcessingContextEiPKPc
+   ...
+}
rename from build/valgrind/i686-redhat-linux-gnu.sup
rename to build/valgrind/i386-redhat-linux-gnu.sup
--- a/build/valgrind/i686-redhat-linux-gnu.sup
+++ b/build/valgrind/i386-redhat-linux-gnu.sup
@@ -1,65 +1,17 @@
-{
-   Bug 793532
-   Memcheck:Leak
-   fun:malloc
-   fun:_ZN8JSObject25allocateSlowArrayElementsEP9JSContext
-   ...
-}
-{
-   This is intended, see bug 793534
-   Memcheck:Leak
-   fun:malloc
-   fun:strdup
-   fun:moz_strdup
-   fun:_ZL9SaveToEnvPKc
-   ...
-}
-{
-   Bug 793535
-   Memcheck:Leak
-   fun:calloc
-   fun:_dlerror_run
-   fun:dlsym
-   fun:PR_SetCurrentThreadName
-   ...
-}
-{
-   Bug 793536
-   Memcheck:Leak
-   fun:malloc
-   fun:moz_xmalloc
-   fun:_ZNSt11_Deque_baseIN11MessageLoop11PendingTaskESaIS1_EE17_M_initialize_mapEj
-   ...
-}
+####################################
+#  Leaks in third party libraries  #
+####################################
 {
    Bug 793537
    Memcheck:Leak
    ...
    obj:/usr/lib/libpango-1.0.so.0.2800.1
    ...
 }
 {
    Bug 793539 which may be fixed or change when bug 713802 is fixed
    Memcheck:Leak
    ...
    obj:/usr/lib/libgnomevfs-2.so.0.2400.2
    ...
 }
-{
-   Bug 793548
-   Memcheck:Leak
-   fun:malloc
-   fun:moz_xmalloc
-   fun:NS_Alloc_P
-   fun:_Z12ToNewCStringRK19nsACString_internal
-   fun:_ZN13CrashReporter14SetupExtraDataEP7nsIFileRK19nsACString_internal
-   ...
-}
-{
-   Bug 793549
-   Memcheck:Leak
-   fun:realloc
-   fun:PR_Realloc
-   fun:GrowStuff
-   ...
-}
--- a/build/valgrind/x86_64-redhat-linux-gnu.sup
+++ b/build/valgrind/x86_64-redhat-linux-gnu.sup
@@ -1,189 +1,55 @@
-{
-   Bug 793532
-   Memcheck:Leak
-   fun:malloc
-   fun:_ZN8JSObject25allocateSlowArrayElementsEP9JSContext
-   ...
-}
-{
-   Bug 793533
-   Memcheck:Leak
-   fun:malloc
-   fun:moz_xmalloc
-   fun:_Z22xpc_CreateGlobalObjectP9JSContextP7JSClassP12nsIPrincipalP11nsISupportsbPP8JSObjectPP13JSCompartment
-   ...
-}
-{
-   This is intended, see bug 793534
-   Memcheck:Leak
-   fun:malloc
-   fun:strdup
-   fun:moz_strdup
-   fun:_ZL9SaveToEnvPKc
-   ...
-}
-{
-   Bug 793535
-   Memcheck:Leak
-   fun:calloc
-   fun:_dlerror_run
-   fun:dlsym
-   fun:PR_SetCurrentThreadName
-   ...
-}
-{
-   Bug 793536
-   Memcheck:Leak
-   fun:malloc
-   fun:moz_xmalloc
-   fun:_ZNSt11_Deque_baseIN11MessageLoop11PendingTaskESaIS1_EE17_M_initialize_mapEm
-   ...
-}
+####################################
+#  Leaks in third party libraries  #
+####################################
 {
    Bug 793537
    Memcheck:Leak
    ...
    obj:/usr/lib64/libpango-1.0.so.0.2800.1
    ...
 }
 {
    Bug 793539 which may be fixed or change when bug 713802 is fixed
    Memcheck:Leak
    ...
    obj:/usr/lib64/libgnomevfs-2.so.0.2400.2
    ...
 }
 {
-   Bug 793548
-   Memcheck:Leak
-   fun:malloc
-   fun:moz_xmalloc
-   fun:NS_Alloc_P
-   fun:_Z12ToNewCStringRK19nsACString_internal
-   fun:_ZN13CrashReporter14SetupExtraDataEP7nsIFileRK19nsACString_internal
-   ...
-}
-{
-   Bug 793549
-   Memcheck:Leak
-   fun:realloc
-   fun:PR_Realloc
-   fun:GrowStuff
-   ...
-}
-{
    Bug 793598
    Memcheck:Leak
-   fun:realloc
    ...
    obj:/lib64/libdbus-1.so.3.4.0
    ...
 }
 {
    Bug 793600
    Memcheck:Leak
    fun:realloc
    obj:/usr/lib64/libfontconfig.so.1.4.4
    obj:/usr/lib64/libfontconfig.so.1.4.4
    fun:FcDefaultSubstitute
    fun:_ZN17gfxPangoFontGroup11MakeFontSetEP14_PangoLanguagedP9nsAutoRefI10_FcPatternE
    ...
 }
 {
-   Bug 793601
-   Memcheck:Leak
-   fun:malloc
-   fun:_ZN2js15ArgumentsObject6createEP9JSContextPNS_10StackFrameE
-   ...
-}
-{
-   Bug 793602
+   Bug 794366
    Memcheck:Leak
-   fun:malloc
-   fun:moz_xmalloc
-   fun:_Z22NS_NewComputedDOMStylePN7mozilla3dom7ElementERK18nsAString_internalP12nsIPresShell
-   fun:_ZN14nsGlobalWindow16GetComputedStyleEP13nsIDOMElementRK18nsAString_internalPP25nsIDOMCSSStyleDeclaration
-   ...
-}
-{
-   Bug 793603
-   Memcheck:Leak
-   fun:malloc
-   fun:moz_xmalloc
-   fun:_ZN18nsDeflateConverter15OnDataAvailableEP10nsIRequestP11nsISupportsP14nsIInputStreammj
    ...
-}
-{
-   Bug 793605
-   Memcheck:Leak
-   fun:malloc
-   fun:moz_xmalloc
-   fun:_Z30nsStringInputStreamConstructorP11nsISupportsRK4nsIDPPv
-   ...
-}
-{
-   Bug 793606
-   Memcheck:Leak
-   fun:malloc
-   fun:moz_xmalloc
-   fun:_ZL27nsXMLHttpRequestConstructorP11nsISupportsRK4nsIDPPv
-   ...
-}
-{
-   Bug 793607
-   Memcheck:Leak
-   fun:malloc
-   fun:moz_xmalloc
-   fun:_ZN11nsZipWriter14AddEntryStreamERK19nsACString_internalliP14nsIInputStreambj
+   obj:/usr/lib64/libgtk-x11-2.0.so.0.1800.9
    ...
 }
 {
-   Bug 793608
+   Bug 794368
    Memcheck:Leak
-   fun:malloc
-   fun:__libc_res_nsend
-   fun:__libc_res_nquery
-   fun:__libc_res_nquerydomain
-   fun:__libc_res_nsearch
-   obj:*
-   fun:gaih_inet
-   fun:getaddrinfo
-   fun:PR_GetAddrInfoByName
-   fun:_ZN14nsHostResolver10ThreadFuncEPv
-   fun:_pt_root
-   fun:start_thread
-   fun:clone
-}
-{
-   Bug 793611
-   Memcheck:Leak
-   fun:memalign
-   fun:tls_get_addr_tail
-   fun:__tls_get_addr
-   fun:_ZN8nsThread16ProcessNextEventEbPb
-   fun:_Z21NS_ProcessNextEvent_PP9nsIThreadb
-   fun:_ZN8nsThread10ThreadFuncEPv
-   fun:_pt_root
-   fun:start_thread
-   fun:clone
-}
-{
-   Bug 793615
-   Memcheck:Leak
-   fun:malloc
-   fun:sqlite3MemMalloc
+   ...
+   obj:/usr/lib64/libXrandr.so.2.2.0
    ...
 }
 {
-   Bug 793616
+   Bug 794373
    Memcheck:Leak
-   fun:malloc
-   fun:make_request
-   fun:__check_pf
-   fun:getaddrinfo
-   fun:PR_GetAddrInfoByName
-   fun:_ZN14nsHostResolver10ThreadFuncEPv
-   fun:_pt_root
-   fun:start_thread
-   fun:clone
+   ...
+   obj:/lib64/libgobject-2.0.so.0.2200.5
+   ...
 }
--- a/build/virtualenv/packages.txt
+++ b/build/virtualenv/packages.txt
@@ -3,14 +3,15 @@ manifestdestiny.pth:testing/mozbase/mani
 mozinfo.pth:testing/mozbase/mozinfo
 mozinstall.pth:testing/mozbase/mozinstall
 mozlog.pth:testing/mozbase/mozlog
 mozprocess.pth:testing/mozbase/mozprocess
 mozprofile.pth:testing/mozbase/mozprofile
 mozrunner.pth:testing/mozbase/mozrunner
 blessings.pth:python/blessings
 mozbuild.pth:python/mozbuild
+pymake.pth:build/pymake
 optional:setup.py:python/psutil:build_ext:--inplace
 optional:psutil.pth:python/psutil
 which.pth:python/which
 mozilla.pth:build
 mozilla.pth:config
 copy:build/buildconfig.py
--- a/config/config.mk
+++ b/config/config.mk
@@ -22,16 +22,30 @@ EXIT_ON_ERROR = set -e; # Shell loops co
 ifndef topsrcdir
 topsrcdir	= $(DEPTH)
 endif
 
 ifndef INCLUDED_AUTOCONF_MK
 include $(DEPTH)/config/autoconf.mk
 endif
 
+space = $(NULL) $(NULL)
+
+# Include defs.mk files that can be found in $(srcdir)/$(DEPTH),
+# $(srcdir)/$(DEPTH-1), $(srcdir)/$(DEPTH-2), etc., and $(srcdir)
+# where $(DEPTH-1) is one level less of depth, $(DEPTH-2), two, etc.
+# i.e. for DEPTH=../../.., DEPTH-1 is ../.. and DEPTH-2 is ..
+# These defs.mk files are used to define variables in a directory
+# and all its subdirectories, recursively.
+__depth := $(subst /, ,$(DEPTH))
+ifeq (.,$(__depth))
+__depth :=
+endif
+$(foreach __d,$(__depth) .,$(eval __depth = $(wordlist 2,$(words $(__depth)),$(__depth))$(eval -include $(subst $(space),/,$(strip $(srcdir) $(__depth) defs.mk)))))
+
 COMMA = ,
 
 # Sanity check some variables
 CHECK_VARS := \
  XPI_NAME \
  LIBRARY_NAME \
  MODULE \
  DEPTH \
@@ -46,19 +60,16 @@ CHECK_VARS := \
 # named by $x
 check-variable = $(if $(filter-out 0 1,$(words $($(x))z)),$(error Spaces are not allowed in $(x)))
 
 $(foreach x,$(CHECK_VARS),$(check-variable))
 
 core_abspath = $(if $(findstring :,$(1)),$(1),$(if $(filter /%,$(1)),$(1),$(CURDIR)/$(1)))
 core_realpath = $(if $(realpath $(1)),$(realpath $(1)),$(call core_abspath,$(1)))
 
-nullstr :=
-space :=$(nullstr) # EOL
-
 core_winabspath = $(firstword $(subst /, ,$(call core_abspath,$(1)))):$(subst $(space),,$(patsubst %,\\%,$(wordlist 2,$(words $(subst /, ,$(call core_abspath,$(1)))), $(strip $(subst /, ,$(call core_abspath,$(1)))))))
 
 RM = rm -f
 
 # LIBXUL_DIST is not defined under js/src, thus we make it mean DIST there.
 LIBXUL_DIST ?= $(DIST)
 
 # FINAL_TARGET specifies the location into which we copy end-user-shipped
@@ -809,8 +820,12 @@ EXPAND_LIBNAME_PATH = $(foreach lib,$(1)
 EXPAND_MOZLIBNAME = $(foreach lib,$(1),$(DIST)/lib/$(LIB_PREFIX)$(lib).$(LIB_SUFFIX))
 
 # Include internal ply only if needed
 ifndef MOZ_SYSTEM_PLY
 PLY_INCLUDE = -I$(topsrcdir)/other-licenses/ply
 endif
 
 export CL_INCLUDES_PREFIX
+
+ifeq ($(MOZ_WIDGET_GTK),2)
+MOZ_GTK2_CFLAGS := -I$(topsrcdir)/widget/gtk2/compat $(MOZ_GTK2_CFLAGS)
+endif
--- a/config/rules.mk
+++ b/config/rules.mk
@@ -938,17 +938,17 @@ endif # Sun Studio on Solaris
 
 $(HOST_CMMOBJS): host_%.$(OBJ_SUFFIX): %.mm
 	$(REPORT_BUILD)
 	$(ELOG) $(HOST_CXX) $(HOST_OUTOPTION)$@ -c $(HOST_CXXFLAGS) $(HOST_CMMFLAGS) $(INCLUDES) $(NSPR_CFLAGS) $(_VPATH_SRCS)
 
 $(COBJS): %.$(OBJ_SUFFIX): %.c $(call mkdir_deps,$(MDDEPDIR))
 	$(REPORT_BUILD)
 	@$(MAKE_DEPS_AUTO_CC)
-	$(ELOG) $(CC) $(OUTOPTION)$@ -c $(COMPILE_CFLAGS) $(_VPATH_SRCS)
+	$(ELOG) $(CC) $(OUTOPTION)$@ -c $(COMPILE_CFLAGS) $(TARGET_LOCAL_INCLUDES) $(_VPATH_SRCS)
 
 # DEFINES and ACDEFINES are needed here to enable conditional compilation of Q_OBJECTs:
 # 'moc' only knows about #defines it gets on the command line (-D...), not in
 # included headers like mozilla-config.h
 moc_%.cpp: %.h
 	$(ELOG) $(MOC) $(DEFINES) $(ACDEFINES) $< $(OUTOPTION)$@
 
 moc_%.cc: %.cc
@@ -960,61 +960,61 @@ qrc_%.cpp: %.qrc
 ifdef ASFILES
 # The AS_DASH_C_FLAG is needed cause not all assemblers (Solaris) accept
 # a '-c' flag.
 $(ASOBJS): %.$(OBJ_SUFFIX): %.$(ASM_SUFFIX)
 	$(AS) $(ASOUTOPTION)$@ $(ASFLAGS) $(AS_DASH_C_FLAG) $(_VPATH_SRCS)
 endif
 
 $(SOBJS): %.$(OBJ_SUFFIX): %.S
-	$(AS) -o $@ $(ASFLAGS) -c $<
+	$(AS) -o $@ $(ASFLAGS) $(LOCAL_INCLUDES) $(TARGET_LOCAL_INCLUDES) -c $<
 
 #
 # Please keep the next two rules in sync.
 #
 $(CCOBJS): %.$(OBJ_SUFFIX): %.cc $(call mkdir_deps,$(MDDEPDIR))
 	$(REPORT_BUILD)
 	@$(MAKE_DEPS_AUTO_CXX)
-	$(ELOG) $(CCC) $(OUTOPTION)$@ -c $(COMPILE_CXXFLAGS) $(_VPATH_SRCS)
+	$(ELOG) $(CCC) $(OUTOPTION)$@ -c $(COMPILE_CXXFLAGS) $(TARGET_LOCAL_INCLUDES) $(_VPATH_SRCS)
 
 $(CPPOBJS): %.$(OBJ_SUFFIX): %.cpp $(call mkdir_deps,$(MDDEPDIR))
 	$(REPORT_BUILD)
 	@$(MAKE_DEPS_AUTO_CXX)
-	$(ELOG) $(CCC) $(OUTOPTION)$@ -c $(COMPILE_CXXFLAGS) $(_VPATH_SRCS)
+	$(ELOG) $(CCC) $(OUTOPTION)$@ -c $(COMPILE_CXXFLAGS) $(TARGET_LOCAL_INCLUDES) $(_VPATH_SRCS)
 
 $(CMMOBJS): $(OBJ_PREFIX)%.$(OBJ_SUFFIX): %.mm $(call mkdir_deps,$(MDDEPDIR))
 	$(REPORT_BUILD)
 	@$(MAKE_DEPS_AUTO_CXX)
-	$(ELOG) $(CCC) -o $@ -c $(COMPILE_CXXFLAGS) $(COMPILE_CMMFLAGS) $(_VPATH_SRCS)
+	$(ELOG) $(CCC) -o $@ -c $(COMPILE_CXXFLAGS) $(COMPILE_CMMFLAGS) $(TARGET_LOCAL_INCLUDES) $(_VPATH_SRCS)
 
 $(CMOBJS): $(OBJ_PREFIX)%.$(OBJ_SUFFIX): %.m $(call mkdir_deps,$(MDDEPDIR))
 	$(REPORT_BUILD)
 	@$(MAKE_DEPS_AUTO_CC)
-	$(ELOG) $(CC) -o $@ -c $(COMPILE_CFLAGS) $(COMPILE_CMFLAGS) $(_VPATH_SRCS)
+	$(ELOG) $(CC) -o $@ -c $(COMPILE_CFLAGS) $(COMPILE_CMFLAGS) $(TARGET_LOCAL_INCLUDES) $(_VPATH_SRCS)
 
 %.s: %.cpp $(call mkdir_deps,$(MDDEPDIR))
-	$(CCC) -S $(COMPILE_CXXFLAGS) $(_VPATH_SRCS)
+	$(CCC) -S $(COMPILE_CXXFLAGS) $(TARGET_LOCAL_INCLUDES) $(_VPATH_SRCS)
 
 %.s: %.cc $(call mkdir_deps,$(MDDEPDIR))
-	$(CCC) -S $(COMPILE_CXXFLAGS) $(_VPATH_SRCS)
+	$(CCC) -S $(COMPILE_CXXFLAGS) $(TARGET_LOCAL_INCLUDES) $(_VPATH_SRCS)
 
 %.s: %.c $(call mkdir_deps,$(MDDEPDIR))
-	$(CC) -S $(COMPILE_CFLAGS) $(_VPATH_SRCS)
+	$(CC) -S $(COMPILE_CFLAGS) $(TARGET_LOCAL_INCLUDES) $(_VPATH_SRCS)
 
 %.i: %.cpp $(call mkdir_deps,$(MDDEPDIR))
-	$(CCC) -C -E $(COMPILE_CXXFLAGS) $(_VPATH_SRCS) > $*.i
+	$(CCC) -C -E $(COMPILE_CXXFLAGS) $(TARGET_LOCAL_INCLUDES) $(_VPATH_SRCS) > $*.i
 
 %.i: %.cc $(call mkdir_deps,$(MDDEPDIR))
-	$(CCC) -C -E $(COMPILE_CXXFLAGS) $(_VPATH_SRCS) > $*.i
+	$(CCC) -C -E $(COMPILE_CXXFLAGS) $(TARGET_LOCAL_INCLUDES) $(_VPATH_SRCS) > $*.i
 
 %.i: %.c $(call mkdir_deps,$(MDDEPDIR))
-	$(CC) -C -E $(COMPILE_CFLAGS) $(_VPATH_SRCS) > $*.i
+	$(CC) -C -E $(COMPILE_CFLAGS) $(TARGET_LOCAL_INCLUDES) $(_VPATH_SRCS) > $*.i
 
 %.i: %.mm $(call mkdir_deps,$(MDDEPDIR))
-	$(CCC) -C -E $(COMPILE_CXXFLAGS) $(COMPILE_CMMFLAGS) $(_VPATH_SRCS) > $*.i
+	$(CCC) -C -E $(COMPILE_CXXFLAGS) $(COMPILE_CMMFLAGS) $(TARGET_LOCAL_INCLUDES) $(_VPATH_SRCS) > $*.i
 
 %.res: %.rc
 	@echo Creating Resource file: $@
 ifeq ($(OS_ARCH),OS2)
 	$(RC) $(RCFLAGS:-D%=-d %) -i $(subst /,\,$(srcdir)) -r $< $@
 else
 ifdef GNU_CC
 	$(RC) $(RCFLAGS) $(filter-out -U%,$(DEFINES)) $(INCLUDES:-I%=--include-dir %) $(OUTOPTION)$@ $(_VPATH_SRCS)
--- a/configure.in
+++ b/configure.in
@@ -60,17 +60,17 @@ NSS_VERSION=3
 dnl Set the minimum version of toolkit libs used by mozilla
 dnl ========================================================
 GLIB_VERSION=1.2.0
 PERL_VERSION=5.006
 PYTHON_VERSION_MAJOR=2
 PYTHON_VERSION_MINOR=5
 CAIRO_VERSION=1.10
 PANGO_VERSION=1.14.0
-GTK2_VERSION=2.10.0
+GTK2_VERSION=2.18.0
 WINDRES_VERSION=2.14.90
 W32API_VERSION=3.14
 GNOMEVFS_VERSION=2.0
 GNOMEUI_VERSION=2.2.0
 GCONF_VERSION=1.2.1
 GIO_VERSION=2.18
 STARTUP_NOTIFICATION_VERSION=0.8
 DBUS_VERSION=0.60
@@ -4430,16 +4430,18 @@ MOZ_ARG_HEADER(Toolkit Options)
 MOZ_ARG_WITHOUT_BOOL(x,
 [  --without-x              Build without X11],
     WITHOUT_X11=1)
 
 dnl ========================================================
 dnl = Enable the toolkit as needed                         =
 dnl ========================================================
 
+MOZ_WIDGET_GTK=
+
 case "$MOZ_WIDGET_TOOLKIT" in
 
 cairo-windows)
     MOZ_WIDGET_TOOLKIT=windows
     MOZ_WEBGL=1
     MOZ_PDF_PRINTING=1
     MOZ_INSTRUMENT_EVENT_LOOP=1
     ;;
@@ -4453,17 +4455,18 @@ cairo-gtk2|cairo-gtk2-x11)
 
     AC_DEFINE(MOZ_X11)
     MOZ_X11=1
     USE_FC_FREETYPE=1
 
     TK_CFLAGS='$(MOZ_GTK2_CFLAGS)'
     TK_LIBS='$(MOZ_GTK2_LIBS)'
     AC_DEFINE(MOZ_WIDGET_GTK2)
-    AC_DEFINE(MOZ_WIDGET_GTK,2)
+    MOZ_WIDGET_GTK=2
+    AC_DEFINE_UNQUOTED(MOZ_WIDGET_GTK,$MOZ_WIDGET_GTK)
     MOZ_PDF_PRINTING=1
     MOZ_INSTRUMENT_EVENT_LOOP=1
     ;;
 
 cairo-qt)
     MOZ_WIDGET_TOOLKIT=qt
     MOZ_ENABLE_QT=1
     if test -z "$WITHOUT_X11"; then
@@ -4727,16 +4730,17 @@ AC_SUBST(TK_LIBS)
 AC_SUBST(MOZ_ENABLE_GTK2)
 AC_SUBST(MOZ_ENABLE_QT)
 AC_SUBST(MOZ_ENABLE_QTNETWORK)
 AC_SUBST(MOZ_ENABLE_QMSYSTEM2)
 AC_SUBST(MOZ_ENABLE_QTMOBILITY)
 AC_SUBST(MOZ_ENABLE_XREMOTE)
 AC_SUBST(MOZ_GTK2_CFLAGS)
 AC_SUBST(MOZ_GTK2_LIBS)
+AC_SUBST(MOZ_WIDGET_GTK)
 AC_SUBST(MOZ_QT_CFLAGS)
 AC_SUBST(MOZ_QT_LIBS)
 
 AC_SUBST(MOC)
 AC_SUBST(RCC)
 
 AC_SUBST(MOZ_X11)
 
@@ -8797,18 +8801,22 @@ if test -n "$MOZ_WEBRTC"; then
      ${srcdir}/media/webrtc/trunk/testing/gtest.gyp
    if test "$?" != 0; then
       AC_MSG_ERROR([failed to generate gtest Makefiles])
    fi
 fi
 
 # Generate a JSON config file for unittest harnesses etc to read
 # build configuration details from in a standardized way.
-OS_TARGET=${OS_TARGET} TARGET_CPU=${TARGET_CPU} MOZ_DEBUG=${MOZ_DEBUG} \
-MOZ_WIDGET_TOOLKIT=${MOZ_WIDGET_TOOLKIT} UNIVERSAL_BINARY=${UNIVERSAL_BINARY} \
+OS_TARGET=${OS_TARGET} \
+TARGET_CPU=${TARGET_CPU} \
+MOZ_DEBUG=${MOZ_DEBUG} \
+MOZ_WIDGET_TOOLKIT=${MOZ_WIDGET_TOOLKIT} \
+UNIVERSAL_BINARY=${UNIVERSAL_BINARY} \
+MOZ_CRASHREPORTER=${MOZ_CRASHREPORTER} \
   $PYTHON ${_topsrcdir}/config/writemozinfo.py ./mozinfo.json.tmp
 if cmp -s ./mozinfo.json.tmp ./mozinfo.json; then
   rm ./mozinfo.json.tmp
 else
   mv -f ./mozinfo.json.tmp ./mozinfo.json
 fi
 
 # Run jemalloc configure script
@@ -8883,20 +8891,20 @@ if test "$OS_TARGET" = "Android" -a "$MO
   cache_file=$old_cache_file
   ac_configure_args="$old_ac_configure_args"
   CONFIG_FILES=$old_config_files
 fi
 
 # Run freetype configure script
 
 if test "$MOZ_TREE_FREETYPE"; then
-   export CFLAGS="$CFLAGS -std=c99"
-   export CPPFLAGS="$CPPFLAGS"
-   export CXXFLAGS="$CXXFLAGS"
-   export LDFLAGS="$LDFLAGS"
+   export CFLAGS="$CFLAGS $MOZ_DEBUG_FLAGS -std=c99"
+   export CPPFLAGS="$CPPFLAGS $MOZ_DEBUG_FLAGS"
+   export CXXFLAGS="$CXXFLAGS $MOZ_DEBUG_FLAGS"
+   export LDFLAGS="$LDFLAGS $MOZ_DEBUG_LDFLAGS"
    export CONFIG_FILES="unix-cc.mk:unix-cc.in unix-def.mk:unix-def.in freetype-config freetype2.pc:freetype2.in"
    ac_configure_args="$ac_configure_args --host=$target --disable-shared --with-pic=yes"
    AC_OUTPUT_SUBDIRS(modules/freetype2)
 fi
 
 if test -z "$direct_nspr_config"; then
     dnl ========================================================
     dnl = Setup a nice relatively clean build environment for
--- a/content/base/test/chrome/Makefile.in
+++ b/content/base/test/chrome/Makefile.in
@@ -35,16 +35,17 @@ MOCHITEST_CHROME_FILES = \
     test_bug339494.xul \
     test_bug357450.xul \
     test_bug571390.xul \
     test_bug574596.html \
     test_bug683852.xul \
     test_bug599295.html \
     test_bug650776.html \
     test_bug650784.html \
+    test_bug750096.html \
     test_bug752226-3.xul \
     test_bug752226-4.xul \
     test_bug682305.html \
     test_bug780199.xul \
     test_bug780529.xul \
     $(NULL)
 
 include $(topsrcdir)/config/rules.mk
new file mode 100644
--- /dev/null
+++ b/content/base/test/chrome/test_bug750096.html
@@ -0,0 +1,45 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=750096
+-->
+<head>
+  <meta charset="utf-8">
+  <title>Test for Bug 750096</title>
+  <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=750096">Mozilla Bug 750096</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+  
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 750096 **/
+
+SimpleTest.waitForExplicitFinish();
+
+var u = Components.interfaces.nsIParserUtils;
+var s = Components.classes["@mozilla.org/parserutils;1"]
+        .getService(u);
+
+var elt = document.getElementById("content");
+
+var embed = s.parseFragment("<embed src=\'javascript:this.fail = true;\'>", 0, false, null, elt);
+var img = s.parseFragment("<img src=\'javascript:this.fail = true;\'>", 0, false, null, elt);
+var video = s.parseFragment("<video src=\'javascript:this.fail = true;\'></video>", 0, false, null, elt);
+var object = s.parseFragment("<object data=\'javascript:this.fail = true;\'></object>", 0, false, null, elt);
+var iframe = s.parseFragment("<iframe src=\'javascript:this.fail = true;\'></iframe>", 0, false, null, elt);
+
+setTimeout(function() {
+  ok(!window.fail, "Should not have failed.");
+  SimpleTest.finish();
+}, 0);
+
+</script>
+</pre>
+</body>
+</html>
--- a/content/canvas/src/Makefile.in
+++ b/content/canvas/src/Makefile.in
@@ -47,16 +47,18 @@ CPPSRCS += \
 	WebGLContextUtils.cpp \
 	WebGLContextReporter.cpp \
 	WebGLContextValidate.cpp \
 	WebGLExtensionStandardDerivatives.cpp \
 	WebGLExtensionTextureFilterAnisotropic.cpp \
 	WebGLExtensionLoseContext.cpp \
 	WebGLTexelConversions.cpp \
 	WebGLExtensionCompressedTextureS3TC.cpp \
+	WebGLExtensionCompressedTextureATC.cpp \
+	WebGLExtensionCompressedTexturePVRTC.cpp \
 	WebGLExtensionDepthTexture.cpp \
 	WebGLElementArrayCache.cpp \
 	$(NULL)
 
 DEFINES += -DUSE_ANGLE
 USE_ANGLE=1
 
 else
--- a/content/canvas/src/WebGLContext.cpp
+++ b/content/canvas/src/WebGLContext.cpp
@@ -958,16 +958,26 @@ bool WebGLContext::IsExtensionSupported(
                 isSupported = true;
             } else if (gl->IsExtensionSupported(GLContext::EXT_texture_compression_dxt1) &&
                        gl->IsExtensionSupported(GLContext::ANGLE_texture_compression_dxt3) &&
                        gl->IsExtensionSupported(GLContext::ANGLE_texture_compression_dxt5))
             {
                 isSupported = true;
             }
             break;
+        case WEBGL_compressed_texture_atc:
+            if (gl->IsExtensionSupported(GLContext::AMD_compressed_ATC_texture)) {
+                isSupported = true;
+            }
+            break;
+        case WEBGL_compressed_texture_pvrtc:
+            if (gl->IsExtensionSupported(GLContext::IMG_texture_compression_pvrtc)) {
+                isSupported = true;
+            }
+            break;
         case WEBGL_depth_texture:
             if (gl->IsGLES2() && 
                 gl->IsExtensionSupported(GLContext::OES_packed_depth_stencil) &&
                 gl->IsExtensionSupported(GLContext::OES_depth_texture)) 
             {
                 isSupported = true;
             } else if (!gl->IsGLES2() &&
                        gl->IsExtensionSupported(GLContext::EXT_packed_depth_stencil)) 
@@ -1019,16 +1029,28 @@ WebGLContext::GetExtension(const nsAStri
             ext = WEBGL_lose_context;
     }
     else if (aName.Equals(NS_LITERAL_STRING("MOZ_WEBGL_compressed_texture_s3tc"),
              nsCaseInsensitiveStringComparator()))
     {
         if (IsExtensionSupported(WEBGL_compressed_texture_s3tc))
             ext = WEBGL_compressed_texture_s3tc;
     }
+    else if (aName.Equals(NS_LITERAL_STRING("MOZ_WEBGL_compressed_texture_atc"),
+             nsCaseInsensitiveStringComparator()))
+    {
+        if (IsExtensionSupported(WEBGL_compressed_texture_atc))
+            ext = WEBGL_compressed_texture_atc;
+    }
+    else if (aName.Equals(NS_LITERAL_STRING("MOZ_WEBGL_compressed_texture_pvrtc"),
+             nsCaseInsensitiveStringComparator()))
+    {
+        if (IsExtensionSupported(WEBGL_compressed_texture_pvrtc))
+            ext = WEBGL_compressed_texture_pvrtc;
+    }
     else if (aName.Equals(NS_LITERAL_STRING("MOZ_WEBGL_depth_texture"),
              nsCaseInsensitiveStringComparator()))
     {
         if (IsExtensionSupported(WEBGL_depth_texture))
             ext = WEBGL_depth_texture;
     }
 
     if (ext == WebGLExtensionID_unknown_extension) {
@@ -1044,16 +1066,22 @@ WebGLContext::GetExtension(const nsAStri
                 mExtensions[ext] = new WebGLExtensionTextureFilterAnisotropic(this);
                 break;
             case WEBGL_lose_context:
                 mExtensions[ext] = new WebGLExtensionLoseContext(this);
                 break;
             case WEBGL_compressed_texture_s3tc:
                 mExtensions[ext] = new WebGLExtensionCompressedTextureS3TC(this);
                 break;
+            case WEBGL_compressed_texture_atc:
+                mExtensions[ext] = new WebGLExtensionCompressedTextureATC(this);
+                break;
+            case WEBGL_compressed_texture_pvrtc:
+                mExtensions[ext] = new WebGLExtensionCompressedTexturePVRTC(this);
+                break;
             case WEBGL_depth_texture:
                 mExtensions[ext] = new WebGLExtensionDepthTexture(this);
                 break;
             default:
                 // create a generic WebGLExtension object for any extensions that don't
                 // have any additional tokens or methods. We still need these to be separate
                 // objects in case the user might extend the corresponding JS objects with custom
                 // properties.
@@ -1565,11 +1593,15 @@ WebGLContext::GetSupportedExtensions(Nul
     if (IsExtensionSupported(EXT_texture_filter_anisotropic)) {
         arr.AppendElement(NS_LITERAL_STRING("EXT_texture_filter_anisotropic"));
         arr.AppendElement(NS_LITERAL_STRING("MOZ_EXT_texture_filter_anisotropic"));
     }
     if (IsExtensionSupported(WEBGL_lose_context))
         arr.AppendElement(NS_LITERAL_STRING("MOZ_WEBGL_lose_context"));
     if (IsExtensionSupported(WEBGL_compressed_texture_s3tc))
         arr.AppendElement(NS_LITERAL_STRING("MOZ_WEBGL_compressed_texture_s3tc"));
+    if (IsExtensionSupported(WEBGL_compressed_texture_atc))
+        arr.AppendElement(NS_LITERAL_STRING("MOZ_WEBGL_compressed_texture_atc"));
+    if (IsExtensionSupported(WEBGL_compressed_texture_pvrtc))
+        arr.AppendElement(NS_LITERAL_STRING("MOZ_WEBGL_compressed_texture_pvrtc"));
     if (IsExtensionSupported(WEBGL_depth_texture))
         arr.AppendElement(NS_LITERAL_STRING("MOZ_WEBGL_depth_texture"));
 }
--- a/content/canvas/src/WebGLContext.h
+++ b/content/canvas/src/WebGLContext.h
@@ -456,21 +456,23 @@ struct WebGLContextOptions {
 class WebGLContext :
     public nsIDOMWebGLRenderingContext,
     public nsICanvasRenderingContextInternal,
     public nsSupportsWeakReference,
     public nsITimerCallback,
     public WebGLRectangleObject,
     public nsWrapperCache
 {
+    friend class WebGLContextUserData;
+    friend class WebGLMemoryPressureObserver;
     friend class WebGLMemoryMultiReporterWrapper;
     friend class WebGLExtensionLoseContext;
     friend class WebGLExtensionCompressedTextureS3TC;
-    friend class WebGLContextUserData;
-    friend class WebGLMemoryPressureObserver;
+    friend class WebGLExtensionCompressedTextureATC;
+    friend class WebGLExtensionCompressedTexturePVRTC;
     friend class WebGLExtensionDepthTexture;
 
     enum {
         UNPACK_FLIP_Y_WEBGL = 0x9240,
         UNPACK_PREMULTIPLY_ALPHA_WEBGL = 0x9241,
         CONTEXT_LOST_WEBGL = 0x9242,
         UNPACK_COLORSPACE_CONVERSION_WEBGL = 0x9243,
         BROWSER_DEFAULT_WEBGL = 0x9244
@@ -1165,16 +1167,18 @@ protected:
 
     // extensions
     enum WebGLExtensionID {
         OES_texture_float,
         OES_standard_derivatives,
         EXT_texture_filter_anisotropic,
         WEBGL_lose_context,
         WEBGL_compressed_texture_s3tc,
+        WEBGL_compressed_texture_atc,
+        WEBGL_compressed_texture_pvrtc,
         WEBGL_depth_texture,
         WebGLExtensionID_number_of_extensions,
         WebGLExtensionID_unknown_extension
     };
     nsAutoTArray<nsRefPtr<WebGLExtension>, WebGLExtensionID_number_of_extensions> mExtensions;
 
     // returns true if the extension has been enabled by calling getExtension.
     bool IsExtensionEnabled(WebGLExtensionID ext) {
@@ -1204,17 +1208,17 @@ protected:
     bool ValidateAttribIndex(WebGLuint index, const char *info);
     bool ValidateStencilParamsForDrawCall();
     
     bool ValidateGLSLVariableName(const nsAString& name, const char *info);
     bool ValidateGLSLCharacter(PRUnichar c);
     bool ValidateGLSLString(const nsAString& string, const char *info);
 
     bool ValidateTexImage2DTarget(WebGLenum target, WebGLsizei width, WebGLsizei height, const char* info);
-    bool ValidateCompressedTextureSize(WebGLint level, WebGLenum format, WebGLsizei width, WebGLsizei height, uint32_t byteLength, const char* info);
+    bool ValidateCompressedTextureSize(WebGLenum target, WebGLint level, WebGLenum format, WebGLsizei width, WebGLsizei height, uint32_t byteLength, const char* info);
     bool ValidateLevelWidthHeightForTarget(WebGLenum target, WebGLint level, WebGLsizei width, WebGLsizei height, const char* info);
 
     static uint32_t GetBitsPerTexel(WebGLenum format, WebGLenum type);
 
     void Invalidate();
     void DestroyResourcesAndContext();
 
     void MakeContextCurrent() { gl->MakeCurrent(); }
--- a/content/canvas/src/WebGLContextGL.cpp
+++ b/content/canvas/src/WebGLContextGL.cpp
@@ -4220,27 +4220,23 @@ WebGLContext::CompressedTexImage2D(WebGL
         return;
     }
 
     if (!mCompressedTextureFormats.Contains(internalformat)) {
         ErrorInvalidEnum("compressedTexImage2D: compressed texture format 0x%x is not supported", internalformat);
         return;
     }
 
-    if (!ValidateLevelWidthHeightForTarget(target, level, width, height, "compressedTexImage2D")) {
-        return;
-    }
-
     if (border) {
         ErrorInvalidValue("compressedTexImage2D: border is not 0");
         return;
     }
 
     uint32_t byteLength = view.Length();
-    if (!ValidateCompressedTextureSize(level, internalformat, width, height, byteLength, "compressedTexImage2D")) {
+    if (!ValidateCompressedTextureSize(target, level, internalformat, width, height, byteLength, "compressedTexImage2D")) {
         return;
     }
 
     gl->fCompressedTexImage2D(target, level, internalformat, width, height, border, byteLength, view.Data());
     tex->SetImageInfo(target, level, width, height, internalformat, LOCAL_GL_UNSIGNED_BYTE);
 }
 
 void
@@ -4276,17 +4272,17 @@ WebGLContext::CompressedTexSubImage2D(We
         return;
     }
 
     if (!ValidateLevelWidthHeightForTarget(target, level, width, height, "compressedTexSubImage2D")) {
         return;
     }
 
     uint32_t byteLength = view.Length();
-    if (!ValidateCompressedTextureSize(level, format, width, height, byteLength, "compressedTexSubImage2D")) {
+    if (!ValidateCompressedTextureSize(target, level, format, width, height, byteLength, "compressedTexSubImage2D")) {
         return;
     }
 
     size_t face = WebGLTexture::FaceForTarget(target);
 
     if (!tex->HasImageInfoAt(level, face)) {
         ErrorInvalidOperation("compressedTexSubImage2D: no texture image previously defined for this level and face");
         return;
@@ -4318,16 +4314,29 @@ WebGLContext::CompressedTexSubImage2D(We
                 return;
             }
             if (height % 4 != 0 && height != imageInfo.Height()) {
                 ErrorInvalidOperation("compressedTexSubImage2D: height is not a multiple of 4 or equal to texture height");
                 return;
             }
             break;
         }
+        case LOCAL_GL_COMPRESSED_RGB_PVRTC_4BPPV1:
+        case LOCAL_GL_COMPRESSED_RGB_PVRTC_2BPPV1:
+        case LOCAL_GL_COMPRESSED_RGBA_PVRTC_4BPPV1:
+        case LOCAL_GL_COMPRESSED_RGBA_PVRTC_2BPPV1:
+        {
+            if (xoffset || yoffset ||
+                width != imageInfo.Width() ||
+                height != imageInfo.Height())
+            {
+                ErrorInvalidValue("compressedTexSubImage2D: the update rectangle doesn't match the existing image");
+                return;
+            }
+        }
     }
 
     gl->fCompressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format, byteLength, view.Data());
 
     return;
 }
 
 JS::Value
--- a/content/canvas/src/WebGLContextUtils.cpp
+++ b/content/canvas/src/WebGLContextUtils.cpp
@@ -193,15 +193,22 @@ WebGLContext::IsTextureFormatCompressed(
         case LOCAL_GL_DEPTH_COMPONENT:
         case LOCAL_GL_DEPTH_STENCIL:
             return false;
 
         case LOCAL_GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
         case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
         case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
         case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
+        case LOCAL_GL_ATC_RGB:
+        case LOCAL_GL_ATC_RGBA_EXPLICIT_ALPHA:
+        case LOCAL_GL_ATC_RGBA_INTERPOLATED_ALPHA:
+        case LOCAL_GL_COMPRESSED_RGB_PVRTC_4BPPV1:
+        case LOCAL_GL_COMPRESSED_RGB_PVRTC_2BPPV1:
+        case LOCAL_GL_COMPRESSED_RGBA_PVRTC_4BPPV1:
+        case LOCAL_GL_COMPRESSED_RGBA_PVRTC_2BPPV1:
             return true;
     }
 
     NS_NOTREACHED("Invalid WebGL texture format?");
     NS_ABORT();
     return false;
 }
--- a/content/canvas/src/WebGLContextValidate.cpp
+++ b/content/canvas/src/WebGLContextValidate.cpp
@@ -366,69 +366,97 @@ bool WebGLContext::ValidateTexImage2DTar
         default:
             ErrorInvalidEnum("%s: invalid target enum 0x%x", info, target);
             return false;
     }
 
     return true;
 }
 
-bool WebGLContext::ValidateCompressedTextureSize(WebGLint level, WebGLenum format, WebGLsizei width,
-                                                 WebGLsizei height, uint32_t byteLength, const char* info)
+bool WebGLContext::ValidateCompressedTextureSize(WebGLenum target, WebGLint level,
+                                                 WebGLenum format,
+                                                 WebGLsizei width, WebGLsizei height, uint32_t byteLength, const char* info)
 {
-    CheckedUint32 calculated_byteLength = 0;
-    CheckedUint32 checked_byteLength = byteLength;
-    if (!checked_byteLength.isValid()) {
-        ErrorInvalidValue("%s: data length out of bounds", info);
+    if (!ValidateLevelWidthHeightForTarget(target, level, width, height, info)) {
         return false;
     }
 
+    // negative width and height must already have been handled above
+    MOZ_ASSERT(width >= 0 && height >= 0);
+
+    CheckedUint32 required_byteLength = 0;
+
     switch (format) {
         case LOCAL_GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
         case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+        case LOCAL_GL_ATC_RGB:
         {
-            calculated_byteLength = ((CheckedUint32(width) + 3) / 4) * ((CheckedUint32(height) + 3) / 4) * 8;
-            if (!calculated_byteLength.isValid() || !(checked_byteLength == calculated_byteLength)) {
-                ErrorInvalidValue("%s: data size does not match dimensions", info);
-                return false;
-            }
+            required_byteLength = ((CheckedUint32(width) + 3) / 4) * ((CheckedUint32(height) + 3) / 4) * 8;
             break;
         }
         case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
         case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
+        case LOCAL_GL_ATC_RGBA_EXPLICIT_ALPHA:
+        case LOCAL_GL_ATC_RGBA_INTERPOLATED_ALPHA:
         {
-            calculated_byteLength = ((CheckedUint32(width) + 3) / 4) * ((CheckedUint32(height) + 3) / 4) * 16;
-            if (!calculated_byteLength.isValid() || !(checked_byteLength == calculated_byteLength)) {
-                ErrorInvalidValue("%s: data size does not match dimensions", info);
-                return false;
-            }
+            required_byteLength = ((CheckedUint32(width) + 3) / 4) * ((CheckedUint32(height) + 3) / 4) * 16;
+            break;
+        }
+        case LOCAL_GL_COMPRESSED_RGB_PVRTC_4BPPV1:
+        case LOCAL_GL_COMPRESSED_RGBA_PVRTC_4BPPV1:
+        {
+            required_byteLength = CheckedUint32(NS_MAX(width, 8)) * CheckedUint32(NS_MAX(height, 8)) / 2;
             break;
         }
+        case LOCAL_GL_COMPRESSED_RGB_PVRTC_2BPPV1:
+        case LOCAL_GL_COMPRESSED_RGBA_PVRTC_2BPPV1:
+        {
+            required_byteLength = CheckedUint32(NS_MAX(width, 16)) * CheckedUint32(NS_MAX(height, 8)) / 4;
+            break;
+        }
+    }
+
+    if (!required_byteLength.isValid() || required_byteLength.value() != byteLength) {
+        ErrorInvalidValue("%s: data size does not match dimensions", info);
+        return false;
     }
 
     switch (format) {
         case LOCAL_GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
         case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
         case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
         case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
         {
             if (level == 0 && width % 4 == 0 && height % 4 == 0) {
-                return true;
+                break;
             }
             if (level > 0
                 && (width == 0 || width == 1 || width == 2 || width % 4 == 0)
                 && (height == 0 || height == 1 || height == 2 || height % 4 == 0))
             {
-                return true;
+                break;
+            }
+            ErrorInvalidOperation("%s: level parameter does not match width and height", info);
+            return false;
+        }
+        case LOCAL_GL_COMPRESSED_RGB_PVRTC_4BPPV1:
+        case LOCAL_GL_COMPRESSED_RGB_PVRTC_2BPPV1:
+        case LOCAL_GL_COMPRESSED_RGBA_PVRTC_4BPPV1:
+        case LOCAL_GL_COMPRESSED_RGBA_PVRTC_2BPPV1:
+        {
+            if (!is_pot_assuming_nonnegative(width) ||
+                !is_pot_assuming_nonnegative(height))
+            {
+                ErrorInvalidValue("%s: width and height must be powers of two", info);
+                return false;
             }
         }
     }
 
-    ErrorInvalidOperation("%s: level parameter does not match width and height", info);
-    return false;
+    return true;
 }
 
 bool WebGLContext::ValidateLevelWidthHeightForTarget(WebGLenum target, WebGLint level, WebGLsizei width,
                                                      WebGLsizei height, const char* info)
 {
     WebGLsizei maxTextureSize = MaxTextureSizeForTarget(target);
 
     if (level < 0) {
@@ -478,21 +506,29 @@ uint32_t WebGLContext::GetBitsPerTexel(W
             case LOCAL_GL_LUMINANCE:
                 return 1 * multiplier;
             case LOCAL_GL_LUMINANCE_ALPHA:
                 return 2 * multiplier;
             case LOCAL_GL_RGB:
                 return 3 * multiplier;
             case LOCAL_GL_RGBA:
                 return 4 * multiplier;
+            case LOCAL_GL_COMPRESSED_RGB_PVRTC_2BPPV1:
+            case LOCAL_GL_COMPRESSED_RGBA_PVRTC_2BPPV1:
+                return 2;
             case LOCAL_GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
             case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+            case LOCAL_GL_ATC_RGB:
+            case LOCAL_GL_COMPRESSED_RGB_PVRTC_4BPPV1:
+            case LOCAL_GL_COMPRESSED_RGBA_PVRTC_4BPPV1:
                 return 4;
             case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
             case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
+            case LOCAL_GL_ATC_RGBA_EXPLICIT_ALPHA:
+            case LOCAL_GL_ATC_RGBA_INTERPOLATED_ALPHA:
                 return 8;
             default:
                 break;
         }
     } else if (type == LOCAL_GL_UNSIGNED_SHORT_4_4_4_4 ||
                type == LOCAL_GL_UNSIGNED_SHORT_5_5_5_1 ||
                type == LOCAL_GL_UNSIGNED_SHORT_5_6_5)
     {
new file mode 100644
--- /dev/null
+++ b/content/canvas/src/WebGLExtensionCompressedTextureATC.cpp
@@ -0,0 +1,32 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "WebGLContext.h"
+#include "WebGLExtensions.h"
+
+using namespace mozilla;
+
+WebGLExtensionCompressedTextureATC::WebGLExtensionCompressedTextureATC(WebGLContext* context)
+    : WebGLExtension(context)
+{
+    context->mCompressedTextureFormats.AppendElement(LOCAL_GL_ATC_RGB);
+    context->mCompressedTextureFormats.AppendElement(LOCAL_GL_ATC_RGBA_EXPLICIT_ALPHA);
+    context->mCompressedTextureFormats.AppendElement(LOCAL_GL_ATC_RGBA_INTERPOLATED_ALPHA);
+}
+
+WebGLExtensionCompressedTextureATC::~WebGLExtensionCompressedTextureATC()
+{
+
+}
+
+NS_IMPL_ADDREF_INHERITED(WebGLExtensionCompressedTextureATC, WebGLExtension)
+NS_IMPL_RELEASE_INHERITED(WebGLExtensionCompressedTextureATC, WebGLExtension)
+
+DOMCI_DATA(WebGLExtensionCompressedTextureATC, WebGLExtensionCompressedTextureATC)
+
+NS_INTERFACE_MAP_BEGIN(WebGLExtensionCompressedTextureATC)
+  NS_INTERFACE_MAP_ENTRY(nsIWebGLExtensionCompressedTextureATC)
+  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, WebGLExtension)
+  NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(WebGLExtensionCompressedTextureATC)
+NS_INTERFACE_MAP_END_INHERITING(WebGLExtension)
new file mode 100644
--- /dev/null
+++ b/content/canvas/src/WebGLExtensionCompressedTexturePVRTC.cpp
@@ -0,0 +1,33 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "WebGLContext.h"
+#include "WebGLExtensions.h"
+
+using namespace mozilla;
+
+WebGLExtensionCompressedTexturePVRTC::WebGLExtensionCompressedTexturePVRTC(WebGLContext* context)
+    : WebGLExtension(context)
+{
+    context->mCompressedTextureFormats.AppendElement(LOCAL_GL_COMPRESSED_RGB_PVRTC_4BPPV1);
+    context->mCompressedTextureFormats.AppendElement(LOCAL_GL_COMPRESSED_RGB_PVRTC_2BPPV1);
+    context->mCompressedTextureFormats.AppendElement(LOCAL_GL_COMPRESSED_RGBA_PVRTC_4BPPV1);
+    context->mCompressedTextureFormats.AppendElement(LOCAL_GL_COMPRESSED_RGBA_PVRTC_2BPPV1);
+}
+
+WebGLExtensionCompressedTexturePVRTC::~WebGLExtensionCompressedTexturePVRTC()
+{
+
+}
+
+NS_IMPL_ADDREF_INHERITED(WebGLExtensionCompressedTexturePVRTC, WebGLExtension)
+NS_IMPL_RELEASE_INHERITED(WebGLExtensionCompressedTexturePVRTC, WebGLExtension)
+
+DOMCI_DATA(WebGLExtensionCompressedTexturePVRTC, WebGLExtensionCompressedTexturePVRTC)
+
+NS_INTERFACE_MAP_BEGIN(WebGLExtensionCompressedTexturePVRTC)
+  NS_INTERFACE_MAP_ENTRY(nsIWebGLExtensionCompressedTexturePVRTC)
+  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, WebGLExtension)
+  NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(WebGLExtensionCompressedTexturePVRTC)
+NS_INTERFACE_MAP_END_INHERITING(WebGLExtension)
--- a/content/canvas/src/WebGLExtensions.h
+++ b/content/canvas/src/WebGLExtensions.h
@@ -51,16 +51,40 @@ class WebGLExtensionCompressedTextureS3T
 public:
     WebGLExtensionCompressedTextureS3TC(WebGLContext* context);
     virtual ~WebGLExtensionCompressedTextureS3TC();
 
     NS_DECL_ISUPPORTS_INHERITED
     NS_DECL_NSIWEBGLEXTENSION
 };
 
+class WebGLExtensionCompressedTextureATC :
+    public nsIWebGLExtensionCompressedTextureATC,
+    public WebGLExtension
+{
+public:
+    WebGLExtensionCompressedTextureATC(WebGLContext* context);
+    virtual ~WebGLExtensionCompressedTextureATC();
+
+    NS_DECL_ISUPPORTS_INHERITED
+    NS_DECL_NSIWEBGLEXTENSION
+};
+
+class WebGLExtensionCompressedTexturePVRTC :
+    public nsIWebGLExtensionCompressedTexturePVRTC,
+    public WebGLExtension
+{
+public:
+    WebGLExtensionCompressedTexturePVRTC(WebGLContext* context);
+    virtual ~WebGLExtensionCompressedTexturePVRTC();
+
+    NS_DECL_ISUPPORTS_INHERITED
+    NS_DECL_NSIWEBGLEXTENSION
+};
+
 class WebGLExtensionDepthTexture :
     public nsIWebGLExtensionDepthTexture,
     public WebGLExtension
 {
 public:
     WebGLExtensionDepthTexture(WebGLContext* context);
     virtual ~WebGLExtensionDepthTexture();
 
--- a/content/events/src/nsEventStateManager.cpp
+++ b/content/events/src/nsEventStateManager.cpp
@@ -117,16 +117,17 @@ static uint32_t sESMInstanceCount = 0;
 static int32_t sChromeAccessModifier = 0, sContentAccessModifier = 0;
 int32_t nsEventStateManager::sUserInputEventDepth = 0;
 bool nsEventStateManager::sNormalLMouseEventInProcess = false;
 nsEventStateManager* nsEventStateManager::sActiveESM = nullptr;
 nsIDocument* nsEventStateManager::sMouseOverDocument = nullptr;
 nsWeakFrame nsEventStateManager::sLastDragOverFrame = nullptr;
 nsIntPoint nsEventStateManager::sLastRefPoint = nsIntPoint(0,0);
 nsIntPoint nsEventStateManager::sLastScreenPoint = nsIntPoint(0,0);
+nsIntPoint nsEventStateManager::sSynthCenteringPoint = nsIntPoint(-1,-1);
 nsIntPoint nsEventStateManager::sLastClientPoint = nsIntPoint(0,0);
 bool nsEventStateManager::sIsPointerLocked = false;
 // Reference to the pointer locked element.
 nsWeakPtr nsEventStateManager::sPointerLockedElement;
 // Reference to the document which requested pointer lock.
 nsWeakPtr nsEventStateManager::sPointerLockedDoc;
 nsCOMPtr<nsIContent> nsEventStateManager::sDragOverContent = nullptr;
 
@@ -4084,17 +4085,18 @@ nsEventStateManager::NotifyMouseOver(nsG
   mLastMouseOverElement = aContent;
   
   // Turn recursion protection back off
   mFirstMouseOverEventElement = nullptr;
 }
 
 // Returns the center point of the window's inner content area.
 // This is in widget coordinates, i.e. relative to the widget's top
-// left corner, not in screen coordinates.
+// left corner, not in screen coordinates, the same units that
+// nsDOMUIEvent::refPoint is in.
 static nsIntPoint
 GetWindowInnerRectCenter(nsPIDOMWindow* aWindow,
                          nsIWidget* aWidget,
                          nsPresContext* aContext)
 {
   NS_ENSURE_TRUE(aWindow && aWidget && aContext, nsIntPoint(0,0));
 
   float cssInnerX = 0.0;
@@ -4126,28 +4128,46 @@ nsEventStateManager::GenerateMouseEnterE
     return;
 
   // Hold onto old target content through the event and reset after.
   nsCOMPtr<nsIContent> targetBeforeEvent = mCurrentTargetContent;
 
   switch(aEvent->message) {
   case NS_MOUSE_MOVE:
     {
+      // Mouse movement is reported on the MouseEvent.movement{X,Y} fields.
+      // Movement is calculated in nsDOMUIEvent::GetMovementPoint() as:
+      //   previous_mousemove_refPoint - current_mousemove_refPoint.
       if (sIsPointerLocked && aEvent->widget) {
-        // Perform mouse lock by recentering the mouse directly, and storing
-        // the refpoints so movement deltas can be calculated.
+        // The pointer is locked. If the pointer is not located at the center of
+        // the window, dispatch a synthetic mousemove to return the pointer there.
+        // Doing this between "real" pointer moves gives the impression that the
+        // (locked) pointer can continue moving and won't stop at the screen
+        // boundary. We cancel the synthetic event so that we don't end up
+        // dispatching the centering move event to content.
         nsIntPoint center = GetWindowInnerRectCenter(mDocument->GetWindow(),
                                                      aEvent->widget,
                                                      mPresContext);
         aEvent->lastRefPoint = center;
         if (aEvent->refPoint != center) {
-          // This mouse move doesn't finish at the center of the widget,
-          // dispatch a synthetic mouse move to return the mouse back to
-          // the center.
-          aEvent->widget->SynthesizeNativeMouseMove(center);
+          // Mouse move doesn't finish at the center of the window. Dispatch a
+          // synthetic native mouse event to move the pointer back to the center
+          // of the window, to faciliate more movement. But first, record that
+          // we've dispatched a synthetic mouse movement, so we can cancel it
+          // in the other branch here.
+          sSynthCenteringPoint = center;
+          aEvent->widget->SynthesizeNativeMouseMove(
+            center + aEvent->widget->WidgetToScreenOffset());
+        } else if (aEvent->refPoint == sSynthCenteringPoint) {
+          // This is the "synthetic native" event we dispatched to re-center the
+          // pointer. Cancel it so we don't expose the centering move to content.
+          aEvent->flags |= NS_EVENT_FLAG_STOP_DISPATCH;
+          // Clear sSynthCenteringPoint so we don't cancel other events
+          // targeted at the center.
+          sSynthCenteringPoint = nsIntPoint(-1,-1);
         }
       } else {
         aEvent->lastRefPoint = sLastRefPoint;
       }
 
       // Update the last known refPoint with the current refPoint.
       sLastRefPoint = aEvent->refPoint;
 
@@ -4209,32 +4229,34 @@ nsEventStateManager::SetPointerLock(nsIW
     mPreLockPoint = sLastRefPoint;
 
     // Fire a synthetic mouse move to ensure event state is updated. We first
     // set the mouse to the center of the window, so that the mouse event
     // doesn't report any movement.
     sLastRefPoint = GetWindowInnerRectCenter(aElement->OwnerDoc()->GetWindow(),
                                              aWidget,
                                              mPresContext);
-    aWidget->SynthesizeNativeMouseMove(sLastRefPoint);
+    aWidget->SynthesizeNativeMouseMove(
+      sLastRefPoint + aWidget->WidgetToScreenOffset());
 
     // Retarget all events to this element via capture.
     nsIPresShell::SetCapturingContent(aElement, CAPTURE_POINTERLOCK);
 
     // Suppress DnD
     if (dragService) {
       dragService->Suppress();
     }
   } else {
     // Unlocking, so return pointer to the original position by firing a
     // synthetic mouse event. We first reset sLastRefPoint to its
     // pre-pointerlock position, so that the synthetic mouse event reports
     // no movement.
     sLastRefPoint = mPreLockPoint;
-    aWidget->SynthesizeNativeMouseMove(mPreLockPoint);
+    aWidget->SynthesizeNativeMouseMove(
+      mPreLockPoint + aWidget->WidgetToScreenOffset());
 
     // Don't retarget events to this element any more.
     nsIPresShell::SetCapturingContent(nullptr, CAPTURE_POINTERLOCK);
 
     // Unsuppress DnD
     if (dragService) {
       dragService->Unsuppress();
     }
--- a/content/events/src/nsEventStateManager.h
+++ b/content/events/src/nsEventStateManager.h
@@ -692,16 +692,23 @@ private:
 
   int32_t     mLockCursor;
 
   // Last mouse event refPoint (the offset from the widget's origin in
   // device pixels) when mouse was locked, used to restore mouse position
   // after unlocking.
   nsIntPoint  mPreLockPoint;
 
+  // Stores the refPoint of the last synthetic mouse move we dispatched
+  // to re-center the mouse when we were pointer locked. If this is (-1,-1) it
+  // means we've not recently dispatched a centering event. We use this to
+  // detect when we receive the synth event, so we can cancel and not send it
+  // to content.
+  static nsIntPoint sSynthCenteringPoint;
+
   nsWeakFrame mCurrentTarget;
   nsCOMPtr<nsIContent> mCurrentTargetContent;
   nsWeakFrame mLastMouseOverFrame;
   nsCOMPtr<nsIContent> mLastMouseOverElement;
   static nsWeakFrame sLastDragOverFrame;
 
   // Stores the refPoint (the offset from the widget's origin in device
   // pixels) of the last mouse event.
--- a/dom/apps/src/Webapps.js
+++ b/dom/apps/src/Webapps.js
@@ -60,34 +60,46 @@ WebappsRegistry.prototype = {
       case "Webapps:GetSelf:Return:OK":
         if (msg.apps.length) {
           app = msg.apps[0];
           Services.DOMRequest.fireSuccess(req, createApplicationObject(this._window, app));
         } else {
           Services.DOMRequest.fireSuccess(req, null);
         }
         break;
+      case "Webapps:IsInstalled:Return:OK":
+        Services.DOMRequest.fireSuccess(req, msg.installed);
+        break;
       case "Webapps:GetInstalled:Return:OK":
         Services.DOMRequest.fireSuccess(req, convertAppsArray(msg.apps, this._window));
         break;
-      case "Webapps:GetSelf:Return:KO":
-        Services.DOMRequest.fireError(req, "ERROR");
-        break;
     }
     this.removeRequest(msg.requestID);
   },
 
   _getOrigin: function(aURL) {
     let uri = Services.io.newURI(aURL, null, null);
     return uri.prePath;
   },
 
+  _validateScheme: function(aURL) {
+    let scheme = Services.io.newURI(aURL, null, null).scheme;
+    if (scheme != "http" && scheme != "https") {
+      throw new Components.Exception(
+        "INVALID_URL_SCHEME: '" + scheme + "'; must be 'http' or 'https'",
+        Cr.NS_ERROR_FAILURE
+      );
+    }
+  },
+
   // mozIDOMApplicationRegistry implementation
 
   install: function(aURL, aParams) {
+    this._validateScheme(aURL);
+
     let installURL = this._window.location.href;
     let installOrigin = this._getOrigin(installURL);
     let request = this.createRequest();
     let requestID = this.getRequestId(request);
     let xhr = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"].createInstance(Ci.nsIXMLHttpRequest);
     xhr.open("GET", aURL, true);
     xhr.channel.loadFlags |= Ci.nsIRequest.VALIDATE_ALWAYS;
 
@@ -129,21 +141,34 @@ WebappsRegistry.prototype = {
 
     xhr.send(null);
     return request;
   },
 
   getSelf: function() {
     let request = this.createRequest();
     cpmm.sendAsyncMessage("Webapps:GetSelf", { origin: this._getOrigin(this._window.location.href),
+                                               appId: this._window.document.nodePrincipal.appId,
                                                oid: this._id,
                                                requestID: this.getRequestId(request) });
     return request;
   },
 
+  isInstalled: function(aManifestURL) {
+    let manifestURL = Services.io.newURI(aManifestURL, null, this._window.document.baseURIObject);
+    this._window.document.nodePrincipal.checkMayLoad(manifestURL, true, false);
+
+    let request = this.createRequest();
+    cpmm.sendAsyncMessage("Webapps:IsInstalled", { origin: this._getOrigin(this._window.location.href),
+                                                   manifestURL: manifestURL.spec,
+                                                   oid: this._id,
+                                                   requestID: this.getRequestId(request) });
+    return request;
+  },
+
   getInstalled: function() {
     let request = this.createRequest();
     cpmm.sendAsyncMessage("Webapps:GetInstalled", { origin: this._getOrigin(this._window.location.href),
                                                     oid: this._id,
                                                     requestID: this.getRequestId(request) });
     return request;
   },
 
@@ -157,16 +182,18 @@ WebappsRegistry.prototype = {
     this._mgmt = null;
     cpmm.sendAsyncMessage("Webapps:UnregisterForMessages",
                           ["Webapps:Install:Return:OK"]);
   },
 
   // mozIDOMApplicationRegistry2 implementation
 
   installPackage: function(aPackageURL, aParams) {
+    this._validateScheme(aPackageURL);
+
     let request = this.createRequest();
     let requestID = this.getRequestId(request);
 
     let receipts = (aParams && aParams.receipts &&
                     Array.isArray(aParams.receipts)) ? aParams.receipts : [];
     let categories = (aParams && aParams.categories &&
                       Array.isArray(aParams.categories)) ? aParams.categories : [];
     cpmm.sendAsyncMessage("Webapps:InstallPackage", { url: aPackageURL,
@@ -178,17 +205,18 @@ WebappsRegistry.prototype = {
                                                       installOrigin: this._getOrigin(this._window.location.href) });
     return request;
   },
 
   // nsIDOMGlobalPropertyInitializer implementation
   init: function(aWindow) {
     this.initHelper(aWindow, ["Webapps:Install:Return:OK", "Webapps:Install:Return:KO",
                               "Webapps:GetInstalled:Return:OK",
-                              "Webapps:GetSelf:Return:OK", "Webapps:GetSelf:Return:KO"]);
+                              "Webapps:GetSelf:Return:OK",
+                              "Webapps:IsInstalled:Return:OK" ]);
 
     let util = this._window.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
     this._id = util.outerWindowID;
     cpmm.sendAsyncMessage("Webapps:RegisterForMessages",
                           ["Webapps:Install:Return:OK"]);
   },
 
   classID: Components.ID("{fff440b3-fae2-45c1-bf03-3b5a2e432270}"),
--- a/dom/apps/src/Webapps.jsm
+++ b/dom/apps/src/Webapps.jsm
@@ -51,17 +51,17 @@ XPCOMUtils.defineLazyGetter(this, "msgmg
 let DOMApplicationRegistry = {
   appsFile: null,
   webapps: { },
   children: [ ],
   allAppsLaunchable: false,
 
   init: function() {
     this.messages = ["Webapps:Install", "Webapps:Uninstall",
-                     "Webapps:GetSelf",
+                     "Webapps:GetSelf", "Webapps:IsInstalled",
                      "Webapps:GetInstalled", "Webapps:GetNotInstalled",
                      "Webapps:Launch", "Webapps:GetAll",
                      "Webapps:InstallPackage", "Webapps:GetBasePath",
                      "Webapps:GetList", "Webapps:RegisterForMessages",
                      "Webapps:UnregisterForMessages"];
 
     this.messages.forEach((function(msgName) {
       ppmm.addMessageListener(msgName, this);
@@ -442,16 +442,19 @@ let DOMApplicationRegistry = {
         break;
       case "Webapps:Uninstall":
         Services.obs.notifyObservers(mm, "webapps-uninstall", JSON.stringify(msg));
         this.uninstall(msg);
         break;
       case "Webapps:Launch":
         Services.obs.notifyObservers(mm, "webapps-launch", JSON.stringify(msg));
         break;
+      case "Webapps:IsInstalled":
+        this.isInstalled(msg, mm);
+        break;
       case "Webapps:GetInstalled":
         this.getInstalled(msg, mm);
         break;
       case "Webapps:GetNotInstalled":
         this.getNotInstalled(msg, mm);
         break;
       case "Webapps:GetAll":
         if (msg.hasPrivileges)
@@ -851,32 +854,61 @@ let DOMApplicationRegistry = {
 
     if (!found) {
       aData.mm.broadcastMessage("Webapps:Uninstall:Return:KO", aData);
     }
   },
 
   getSelf: function(aData, aMm) {
     aData.apps = [];
+
+    if (aData.appId == Ci.nsIScriptSecurityManager.NO_APP_ID ||
+        aData.appId == Ci.nsIScriptSecurityManager.UNKNOWN_APP_ID) {
+      aMm.sendAsyncMessage("Webapps:GetSelf:Return:OK", aData);
+      return;
+    }
+
     let tmp = [];
-    let id = this._appId(aData.origin);
 
-    if (id && this._isLaunchable(this.webapps[id].origin)) {
-      let app = AppsUtils.cloneAppObject(this.webapps[id]);
-      aData.apps.push(app);
-      tmp.push({ id: id });
+    for (let id in this.webapps) {
+      if (this.webapps[id].origin == aData.origin &&
+          this.webapps[id].localId == aData.appId &&
+          this._isLaunchable(this.webapps[id].origin)) {
+        let app = AppsUtils.cloneAppObject(this.webapps[id]);
+        aData.apps.push(app);
+        tmp.push({ id: id });
+        break;
+      }
+    }
+
+    if (!aData.apps.length) {
+      aMm.sendAsyncMessage("Webapps:GetSelf:Return:OK", aData);
+      return;
     }
 
     this._readManifests(tmp, (function(aResult) {
       for (let i = 0; i < aResult.length; i++)
         aData.apps[i].manifest = aResult[i].manifest;
       aMm.sendAsyncMessage("Webapps:GetSelf:Return:OK", aData);
     }).bind(this));
   },
 
+  isInstalled: function(aData, aMm) {
+    aData.installed = false;
+
+    for (let appId in this.webapps) {
+      if (this.webapps[appId].manifestURL == aData.manifestURL) {
+        aData.installed = true;
+        break;
+      }
+    }
+
+    aMm.sendAsyncMessage("Webapps:IsInstalled:Return:OK", aData);
+  },
+
   getInstalled: function(aData, aMm) {
     aData.apps = [];
     let tmp = [];
 
     for (let id in this.webapps) {
       if (this.webapps[id].installOrigin == aData.origin &&
           this._isLaunchable(this.webapps[id].origin)) {
         aData.apps.push(AppsUtils.cloneAppObject(this.webapps[id]));
--- a/dom/base/Navigator.cpp
+++ b/dom/base/Navigator.cpp
@@ -1108,46 +1108,26 @@ Navigator::RequestWakeLock(const nsAStri
 
   return pmService->NewWakeLock(aTopic, win, aWakeLock);
 }
 
 //*****************************************************************************
 //    Navigator::nsIDOMNavigatorSms
 //*****************************************************************************
 
-bool
-Navigator::IsSmsSupported() const
-{
-#ifdef MOZ_WEBSMS_BACKEND
-  nsCOMPtr<nsISmsService> smsService = do_GetService(SMS_SERVICE_CONTRACTID);
-  NS_ENSURE_TRUE(smsService, false);
-
-  bool result = false;
-  smsService->HasSupport(&result);
-
-  return result;
-#else
-  return false;
-#endif
-}
-
 NS_IMETHODIMP
 Navigator::GetMozSms(nsIDOMMozSmsManager** aSmsManager)
 {
   *aSmsManager = nullptr;
 
   if (!mSmsManager) {
-    if (!IsSmsSupported()) {
-      return NS_OK;
-    }
-
     nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
     NS_ENSURE_TRUE(window && window->GetDocShell(), NS_OK);
 
-    mSmsManager = SmsManager::CheckPermissionAndCreateInstance(window);
+    mSmsManager = SmsManager::CreateInstanceIfAllowed(window);
     NS_ENSURE_TRUE(mSmsManager, NS_OK);
   }
 
   NS_ADDREF(*aSmsManager = mSmsManager);
 
   return NS_OK;
 }
 
--- a/dom/base/Navigator.h
+++ b/dom/base/Navigator.h
@@ -157,18 +157,16 @@ public:
 
 #ifdef MOZ_SYS_MSG
   // Helper to initialize mMessagesManager.
   nsresult EnsureMessagesManager();
 #endif
   NS_DECL_NSIDOMNAVIGATORCAMERA
 
 private:
-  bool IsSmsSupported() const;
-
   nsRefPtr<nsMimeTypeArray> mMimeTypes;
   nsRefPtr<nsPluginArray> mPlugins;
   nsRefPtr<nsGeolocation> mGeolocation;
   nsRefPtr<nsDesktopNotificationCenter> mNotification;
   nsRefPtr<battery::BatteryManager> mBatteryManager;
   nsRefPtr<power::PowerManager> mPowerManager;
   nsRefPtr<sms::SmsManager> mSmsManager;
 #ifdef MOZ_B2G_RIL
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -1579,16 +1579,22 @@ static nsDOMClassInfoData sClassInfoData
                            DOM_DEFAULT_SCRIPTABLE_FLAGS |
                            nsIXPCScriptable::WANT_ADDPROPERTY)
   NS_DEFINE_CLASSINFO_DATA(WebGLExtensionLoseContext, WebGLExtensionSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS |
                            nsIXPCScriptable::WANT_ADDPROPERTY)
   NS_DEFINE_CLASSINFO_DATA(WebGLExtensionCompressedTextureS3TC, WebGLExtensionSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS |
                            nsIXPCScriptable::WANT_ADDPROPERTY)
+  NS_DEFINE_CLASSINFO_DATA(WebGLExtensionCompressedTextureATC, WebGLExtensionSH,
+                           DOM_DEFAULT_SCRIPTABLE_FLAGS |
+                           nsIXPCScriptable::WANT_ADDPROPERTY)
+  NS_DEFINE_CLASSINFO_DATA(WebGLExtensionCompressedTexturePVRTC, WebGLExtensionSH,
+                           DOM_DEFAULT_SCRIPTABLE_FLAGS |
+                           nsIXPCScriptable::WANT_ADDPROPERTY)
   NS_DEFINE_CLASSINFO_DATA(WebGLExtensionDepthTexture, WebGLExtensionSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS |
                            nsIXPCScriptable::WANT_ADDPROPERTY)
 
   NS_DEFINE_CLASSINFO_DATA(PaintRequest, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(PaintRequestList, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
@@ -4276,16 +4282,24 @@ nsDOMClassInfo::Init()
   DOM_CLASSINFO_MAP_BEGIN(WebGLExtensionLoseContext, nsIWebGLExtensionLoseContext)
     DOM_CLASSINFO_MAP_ENTRY(nsIWebGLExtensionLoseContext)
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(WebGLExtensionCompressedTextureS3TC, nsIWebGLExtensionCompressedTextureS3TC)
     DOM_CLASSINFO_MAP_ENTRY(nsIWebGLExtensionCompressedTextureS3TC)
   DOM_CLASSINFO_MAP_END
 
+  DOM_CLASSINFO_MAP_BEGIN(WebGLExtensionCompressedTextureATC, nsIWebGLExtensionCompressedTextureATC)
+    DOM_CLASSINFO_MAP_ENTRY(nsIWebGLExtensionCompressedTextureATC)
+  DOM_CLASSINFO_MAP_END
+
+  DOM_CLASSINFO_MAP_BEGIN(WebGLExtensionCompressedTexturePVRTC, nsIWebGLExtensionCompressedTexturePVRTC)
+    DOM_CLASSINFO_MAP_ENTRY(nsIWebGLExtensionCompressedTexturePVRTC)
+  DOM_CLASSINFO_MAP_END
+
   DOM_CLASSINFO_MAP_BEGIN(WebGLExtensionDepthTexture, nsIWebGLExtensionDepthTexture)
     DOM_CLASSINFO_MAP_ENTRY(nsIWebGLExtensionDepthTexture)
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(PaintRequest, nsIDOMPaintRequest)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMPaintRequest)
    DOM_CLASSINFO_MAP_END
  
--- a/dom/base/nsDOMClassInfoClasses.h
+++ b/dom/base/nsDOMClassInfoClasses.h
@@ -454,16 +454,18 @@ DOMCI_CLASS(WebGLRenderbuffer)
 DOMCI_CLASS(WebGLUniformLocation)
 DOMCI_CLASS(WebGLShaderPrecisionFormat)
 DOMCI_CLASS(WebGLActiveInfo)
 DOMCI_CLASS(WebGLExtension)
 DOMCI_CLASS(WebGLExtensionStandardDerivatives)
 DOMCI_CLASS(WebGLExtensionTextureFilterAnisotropic)
 DOMCI_CLASS(WebGLExtensionLoseContext)
 DOMCI_CLASS(WebGLExtensionCompressedTextureS3TC)
+DOMCI_CLASS(WebGLExtensionCompressedTextureATC)
+DOMCI_CLASS(WebGLExtensionCompressedTexturePVRTC)
 DOMCI_CLASS(WebGLExtensionDepthTexture)
 
 DOMCI_CLASS(PaintRequest)
 DOMCI_CLASS(PaintRequestList)
 
 DOMCI_CLASS(ScrollAreaEvent)
 
 DOMCI_CLASS(EventListenerInfo)
--- a/dom/base/nsDOMWindowUtils.cpp
+++ b/dom/base/nsDOMWindowUtils.cpp
@@ -2319,16 +2319,20 @@ nsDOMWindowUtils::GetOuterWindowWithId(u
 NS_IMETHODIMP
 nsDOMWindowUtils::WrapDOMFile(nsIFile *aFile,
                               nsIDOMFile **aDOMFile)
 {
   if (!IsUniversalXPConnectCapable()) {
     return NS_ERROR_DOM_SECURITY_ERR;
   }
 
+  if (!aFile) {
+    return NS_ERROR_FAILURE;
+  }
+
   NS_ADDREF(*aDOMFile = new nsDOMFileFile(aFile));
   return NS_OK;
 }
 
 #ifdef DEBUG
 static bool
 CheckLeafLayers(Layer* aLayer, const nsIntPoint& aOffset, nsIntRegion* aCoveredRegion)
 {
--- a/dom/bluetooth/linux/BluetoothDBusService.cpp
+++ b/dom/bluetooth/linux/BluetoothDBusService.cpp
@@ -419,21 +419,25 @@ AgentEventFilter(DBusConnection *conn, D
     const char *uuid;
     if (!dbus_message_get_args(msg, NULL,
                                DBUS_TYPE_OBJECT_PATH, &objectPath,
                                DBUS_TYPE_STRING, &uuid,
                                DBUS_TYPE_INVALID)) {
       LOG("%s: Invalid arguments for Authorize() method", __FUNCTION__);
       errorStr.AssignLiteral("Invalid arguments for Authorize() method");
     } else {
-      nsString deviceAddress = GetAddressFromObjectPath(NS_ConvertUTF8toUTF16(objectPath));
+      nsString deviceAddress =
+        GetAddressFromObjectPath(NS_ConvertUTF8toUTF16(objectPath));
 
-      parameters.AppendElement(BluetoothNamedValue(NS_LITERAL_STRING("deviceAddress"), deviceAddress));
-      parameters.AppendElement(BluetoothNamedValue(NS_LITERAL_STRING("uuid"),
-                                                   NS_ConvertUTF8toUTF16(uuid)));
+      parameters.AppendElement(BluetoothNamedValue(
+                                 NS_LITERAL_STRING("deviceAddress"),
+                                 deviceAddress));
+      parameters.AppendElement(BluetoothNamedValue(
+                                 NS_LITERAL_STRING("uuid"),
+                                 NS_ConvertUTF8toUTF16(uuid)));
 
       // Because we may have authorization request and pairing request from the
       // same remote device at the same time, we need two tables to keep these messages.
       sAuthorizeReqTable.Put(deviceAddress, msg);
 
       // Increase ref count here because we need this message later.
       // It'll be unrefed when setAuthorizationInternal() is called.
       dbus_message_ref(msg);
@@ -447,21 +451,25 @@ AgentEventFilter(DBusConnection *conn, D
     uint32_t passkey;
     if (!dbus_message_get_args(msg, NULL,
                                DBUS_TYPE_OBJECT_PATH, &objectPath,
                                DBUS_TYPE_UINT32, &passkey,
                                DBUS_TYPE_INVALID)) {
       LOG("%s: Invalid arguments for RequestConfirmation() method", __FUNCTION__);
       errorStr.AssignLiteral("Invalid arguments for RequestConfirmation() method");
     } else {
-      nsString address = NS_LITERAL_STRING("address");
-      parameters.AppendElement(BluetoothNamedValue(address, NS_ConvertUTF8toUTF16(objectPath)));
-      parameters.AppendElement(BluetoothNamedValue(NS_LITERAL_STRING("passkey"), passkey));
+      parameters.AppendElement(BluetoothNamedValue(
+                                 NS_LITERAL_STRING("address"),
+                                 NS_ConvertUTF8toUTF16(objectPath)));
+      parameters.AppendElement(BluetoothNamedValue(
+                                 NS_LITERAL_STRING("passkey"),
+                                 passkey));
 
-      KeepDBusPairingMessage(address, msg);
+      KeepDBusPairingMessage(GetAddressFromObjectPath(
+                               NS_ConvertUTF8toUTF16(objectPath)), msg);
 
       BluetoothSignal signal(signalName, signalPath, parameters);
 
       // Fire a Device properties fetcher at the main thread
       nsRefPtr<DevicePropertiesSignalHandler> b =
         new DevicePropertiesSignalHandler(signal);
       if (NS_FAILED(NS_DispatchToMainThread(b))) {
         NS_WARNING("Failed to dispatch to main thread!");
@@ -475,20 +483,22 @@ AgentEventFilter(DBusConnection *conn, D
     // The string can be alphanumeric.
     char *objectPath;
     if (!dbus_message_get_args(msg, NULL,
                                DBUS_TYPE_OBJECT_PATH, &objectPath,
                                DBUS_TYPE_INVALID)) {
       LOG("%s: Invalid arguments for RequestPinCode() method", __FUNCTION__);
       errorStr.AssignLiteral("Invalid arguments for RequestPinCode() method");
     } else {
-      nsString address = NS_LITERAL_STRING("address");
-      parameters.AppendElement(BluetoothNamedValue(address, NS_ConvertUTF8toUTF16(objectPath)));
+      parameters.AppendElement(BluetoothNamedValue(
+                                 NS_LITERAL_STRING("address"),
+                                 NS_ConvertUTF8toUTF16(objectPath)));
 
-      KeepDBusPairingMessage(address, msg);
+      KeepDBusPairingMessage(GetAddressFromObjectPath(
+                               NS_ConvertUTF8toUTF16(objectPath)), msg);
 
       BluetoothSignal signal(signalName, signalPath, parameters);
 
       // Fire a Device properties fetcher at the main thread
       nsRefPtr<DevicePropertiesSignalHandler> b =
         new DevicePropertiesSignalHandler(signal);
       if (NS_FAILED(NS_DispatchToMainThread(b))) {
         NS_WARNING("Failed to dispatch to main thread!");
@@ -501,20 +511,22 @@ AgentEventFilter(DBusConnection *conn, D
     // authentication. The return value should be a numeric value between 0-999999.
     char *objectPath;
     if (!dbus_message_get_args(msg, NULL,
                                DBUS_TYPE_OBJECT_PATH, &objectPath,
                                DBUS_TYPE_INVALID)) {
       LOG("%s: Invalid arguments for RequestPasskey() method", __FUNCTION__);
       errorStr.AssignLiteral("Invalid arguments for RequestPasskey() method");
     } else {
-      nsString address = NS_LITERAL_STRING("address");
-      parameters.AppendElement(BluetoothNamedValue(address, NS_ConvertUTF8toUTF16(objectPath)));
+      parameters.AppendElement(BluetoothNamedValue(
+                                 NS_LITERAL_STRING("address"),
+                                 NS_ConvertUTF8toUTF16(objectPath)));
 
-      KeepDBusPairingMessage(address, msg);
+      KeepDBusPairingMessage(GetAddressFromObjectPath(
+                               NS_ConvertUTF8toUTF16(objectPath)), msg);
 
       BluetoothSignal signal(signalName, signalPath, parameters);
 
       // Fire a Device properties fetcher at the main thread
       nsRefPtr<DevicePropertiesSignalHandler> b =
         new DevicePropertiesSignalHandler(signal);
       if (NS_FAILED(NS_DispatchToMainThread(b))) {
         NS_WARNING("Failed to dispatch to main thread!");
--- a/dom/contacts/ContactManager.js
+++ b/dom/contacts/ContactManager.js
@@ -408,16 +408,17 @@ ContactManager.prototype = {
           });
           this._oncontactchange.handleEvent(event);
         }
         break;
       case "Contacts:Find:Return:KO":
       case "Contact:Save:Return:KO":
       case "Contact:Remove:Return:KO":
       case "Contacts:Clear:Return:KO":
+      case "Contacts:GetSimContacts:Return:KO":
         req = this.getRequest(msg.requestID);
         if (req)
           Services.DOMRequest.fireError(req.request, msg.errorMsg);
         break;
       case "PermissionPromptHelper:AskPermission:OK":
         if (DEBUG) debug("id: " + msg.requestID);
         req = this.getRequest(msg.requestID);
         if (!req) {
@@ -574,16 +575,17 @@ ContactManager.prototype = {
     if (!Services.prefs.getBoolPref("dom.mozContacts.enabled"))
       return null;
 
     this.initHelper(aWindow, ["Contacts:Find:Return:OK", "Contacts:Find:Return:KO",
                               "Contacts:Clear:Return:OK", "Contacts:Clear:Return:KO",
                               "Contact:Save:Return:OK", "Contact:Save:Return:KO",
                               "Contact:Remove:Return:OK", "Contact:Remove:Return:KO",
                               "Contacts:GetSimContacts:Return:OK",
+                              "Contacts:GetSimContacts:Return:KO",
                               "PermissionPromptHelper:AskPermission:OK"]);
   },
 
   // Called from DOMRequestIpcHelper
   uninit: function uninit() {
     if (DEBUG) debug("uninit call");
     if (this._oncontactchange)
       this._oncontactchange = null;
--- a/dom/contacts/fallback/ContactService.jsm
+++ b/dom/contacts/fallback/ContactService.jsm
@@ -144,21 +144,29 @@ let DOMContactManager = {
         break;
       case "Contacts:Clear":
         this._db.clear(
           function() { mm.sendAsyncMessage("Contacts:Clear:Return:OK", { requestID: msg.requestID }); }.bind(this),
           function(aErrorMsg) { mm.sendAsyncMessage("Contacts:Clear:Return:KO", { requestID: msg.requestID, errorMsg: aErrorMsg }); }.bind(this)
         );
         break;
       case "Contacts:GetSimContacts":
-        let callback = function(aContactType, aContacts) {
-          if (DEBUG) debug("got SIM contacts: " + aContactType + " " + JSON.stringify(aContacts));
-          mm.sendAsyncMessage("Contacts:GetSimContacts:Return:OK", {requestID: msg.requestID, contacts: aContacts});
-        };
-        mRIL.getICCContacts(msg.options.contactType, callback);
+        mRIL.getICCContacts(
+          msg.options.contactType,
+          function (aErrorMsg, aType, aContacts) {
+            if (aErrorMsg) {
+              mm.sendAsyncMessage("Contacts:GetSimContacts:Return:KO",
+                                  {requestID: msg.requestID,
+                                   errorMsg: aErrorMsg});
+            } else {
+              mm.sendAsyncMessage("Contacts:GetSimContacts:Return:OK",
+                                  {requestID: msg.requestID,
+                                   contacts: aContacts});
+            }
+          }.bind(this));
         break;
       default:
         if (DEBUG) debug("WRONG MESSAGE NAME: " + aMessage.name);
     }
   }
 }
 
 DOMContactManager.init();
--- a/dom/file/test/Makefile.in
+++ b/dom/file/test/Makefile.in
@@ -26,11 +26,12 @@ MOCHITEST_FILES = \
   test_request_readyState.html \
   test_stream_tracking.html \
   test_success_events_after_abort.html \
   test_truncate.html \
   test_write_read_data.html \
   test_workers.html \
   test_archivereader.html \
   test_archivereader_zip_in_zip.html \
+  test_bug_793311.html \
   $(NULL)
 
 include $(topsrcdir)/config/rules.mk
new file mode 100644
--- /dev/null
+++ b/dom/file/test/test_bug_793311.html
@@ -0,0 +1,28 @@
+<!--
+  Any copyright is dedicated to the Public Domain.
+  http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<html>
+<head>
+  <title>Bug 793311 Test</title>
+
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+
+</head>
+
+<body>
+  <script type="text/javascript;version=1.7">
+  SimpleTest.waitForExplicitFinish();
+
+  try {
+    SpecialPowers.DOMWindowUtils.wrapDOMFile(null);
+    ok(false, "wrapDOMFile(null) throws an exception");
+  } catch(e) {
+    ok(true, "wrapDOMFile(null) throws an exception");
+  }
+  SimpleTest.finish();
+  </script>
+</body>
+
+</html>
--- a/dom/icc/interfaces/SimToolKit.idl
+++ b/dom/icc/interfaces/SimToolKit.idl
@@ -238,16 +238,28 @@ dictionary MozStkSetUpCall
    * The text message used in call set up phase.
    *
    * @see MozStkTextMessage for the detail specification of
    *      callMessage.
    */
   jsval callMessage;
 };
 
+dictionary MozStkSetUpEventList
+{
+  /**
+   * The list of events that needs to provide details to ICC when they happen.
+   * When this valus is null, means an indication to remove the existing list
+   * of events in ME.
+   *
+   * @see nsIDOMMozIccManager.STK_EVENT_TYPE_*
+   */
+   jsval eventList; // unsigned short []
+};
+
 dictionary MozStkCommand
 {
   /**
    * The number of command issued by ICC. And it is assigned
    * by ICC may take any hexadecimal value betweean '01' and 'FE'.
    *
    * @see TS 11.14, clause 6.5.1
    */
@@ -262,39 +274,43 @@ dictionary MozStkCommand
    * Qualifiers specific to the command.
    */
   unsigned short commandQualifier;
 
   /**
    * options varies accrording to the typeOfCommand in MozStkCommand.
    *
    * When typeOfCommand is
-   * - STK_DISPLAY_TEXT
-   * - STK_SET_UP_IDLE_MODE_TEXT
-   * - STK_REFRESH
-   * - STK_SEND_{SS|USSD|SMS|DTMF},
+   * - STK_CMD_DISPLAY_TEXT
+   * - STK_CMD_SET_UP_IDLE_MODE_TEXT
+   * - STK_CMD_REFRESH
+   * - STK_CMD_SEND_{SS|USSD|SMS|DTMF},
    * options is MozStkTextMessage.
    *
    * When typeOfCommand is
-   * - STK_SELECT_ITEM
-   * - STK_SET_UP_MENU
+   * - STK_CMD_SELECT_ITEM
+   * - STK_CMD_SET_UP_MENU
    * options is MozStkMenu.
    *
    * When typeOfCommand is
-   * - STK_GET_INKEY
-   * - STK_GET_INPUT,
+   * - STK_CMD_GET_INKEY
+   * - STK_CMD_GET_INPUT,
    * options is MozStkInput.
    *
    * When typeOfCommand is
-   * - STK_LAUNCH_BROWSER
+   * - STK_CMD_LAUNCH_BROWSER
    * options is MozStkBrowserSetting.
    *
    * When typeOfCommand is
-   * - STK_SET_UP_CALL
+   * - STK_CMD_SET_UP_CALL
    * options is MozStkSetUpCall.
+   *
+   * When typeOfCommand is
+   * - STK_CMD_SET_UP_EVENT_LIST
+   * options is MozStkSetUpEventList.
    */
   jsval options;
 };
 
 [scriptable, builtinclass, uuid(06bbc6fa-9b59-4db6-b66b-3b26f9c379df)]
 interface nsIDOMMozStkCommandEvent : nsIDOMEvent
 {
   /**
@@ -319,37 +335,23 @@ dictionary MozStkResponse
   unsigned short itemIdentifier;
 
   /**
    * User input.
    */
   DOMString input;
 
   /**
-   * Alphabet encoding.
-   *
-   * @see MozStkInput.isUCS2
-   */
-  boolean isUCS2;
-
-  /**
    * YES/NO response.
    *
    * @see MozStkInput.isYesNoRequested
    */
   boolean isYesNo;
 
   /**
-   * Packed or unpacked format.
-   *
-   * @see MozStkInput.isPacked
-   */
-  boolean isPacked;
-
-  /**
    * User has confirmed or rejected the call during STK_CMD_CALL_SET_UP.
    *
    * @see RIL_REQUEST_STK_HANDLE_CALL_SETUP_REQUESTED_FROM_SIM
    *
    * true: Confirmed by User.
    * false: Rejected by User.
    */
   boolean hasConfirmed;
--- a/dom/icc/interfaces/nsIDOMIccManager.idl
+++ b/dom/icc/interfaces/nsIDOMIccManager.idl
@@ -2,17 +2,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsIDOMEventTarget.idl"
 #include "SimToolKit.idl"
 
 interface nsIDOMEventListener;
 
-[scriptable, builtinclass, uuid(cf58adc2-2db6-4130-86d2-2044788889cb)]
+[scriptable, builtinclass, uuid(2eace3f9-6aa4-491b-820e-7d69ce7b3f02)]
 interface nsIDOMMozIccManager : nsIDOMEventTarget
 {
   /**
    * STK Menu Presentation types.
    */
   const unsigned short STK_MENU_TYPE_NOT_SPECIFIED      = 0x00;
   const unsigned short STK_MENU_TYPE_DATA_VALUES        = 0x01;
   const unsigned short STK_MENU_TYPE_NAVIGATION_OPTIONS = 0x03;
@@ -25,16 +25,17 @@ interface nsIDOMMozIccManager : nsIDOMEv
   const unsigned short STK_BROWSER_MODE_USING_NEW_BROWSER              = 0x03;
 
   /**
    * STK Proactive commands.
    *
    * @see TS 11.14, clause 13.4
    */
   const unsigned short STK_CMD_REFRESH               = 0x01;
+  const unsigned short STK_CMD_SET_UP_EVENT_LIST     = 0x05;
   const unsigned short STK_CMD_SET_UP_CALL           = 0x10;
   const unsigned short STK_CMD_SEND_SS               = 0x11;
   const unsigned short STK_CMD_SEND_USSD             = 0x12;
   const unsigned short STK_CMD_SEND_SMS              = 0x13;
   const unsigned short STK_CMD_SEND_DTMF             = 0x14;
   const unsigned short STK_CMD_LAUNCH_BROWSER        = 0x15;
   const unsigned short STK_CMD_DISPLAY_TEXT          = 0x21;
   const unsigned short STK_CMD_GET_INKEY             = 0x22;
@@ -136,16 +137,37 @@ interface nsIDOMMozIccManager : nsIDOMEv
    * USIM, permanent problem
    */
   const unsigned short STK_RESULT_USIM_CALL_CONTROL_PERMANENT       = 0x39;
 
   /** Bearer Independent Protocol error */
   const unsigned short STK_RESULT_BIP_ERROR                         = 0x3a;
 
   /**
+   * STK Event List
+   */
+   const unsigned short STK_EVENT_TYPE_MT_CALL                          = 0x00;
+   const unsigned short STK_EVENT_TYPE_CALL_CONNECTED                   = 0x01;
+   const unsigned short STK_EVENT_TYPE_CALL_DISCONNECTED                = 0x02;
+   const unsigned short STK_EVENT_TYPE_LOCATION_STATUS                  = 0x03;
+   const unsigned short STK_EVENT_TYPE_USER_ACTIVITY                    = 0x04;
+   const unsigned short STK_EVENT_TYPE_IDLE_SCREEN_AVAILABLE            = 0x05;
+   const unsigned short STK_EVENT_TYPE_CARD_READER_STATUS               = 0x06;
+   const unsigned short STK_EVENT_TYPE_LANGUAGE_SELECTION               = 0x07;
+   const unsigned short STK_EVENT_TYPE_BROWSER_TERMINATION              = 0x08;
+   const unsigned short STK_EVENT_TYPE_DATA_AVAILABLE                   = 0x09;
+   const unsigned short STK_EVENT_TYPE_CHANNEL_STATUS                   = 0x0a;
+   const unsigned short STK_EVENT_TYPE_SINGLE_ACCESS_TECHNOLOGY_CHANGED = 0x0b;
+   const unsigned short STK_EVENT_TYPE_DISPLAY_PARAMETER_CHANGED        = 0x0c;
+   const unsigned short STK_EVENT_TYPE_LOCAL_CONNECTION                 = 0x0d;
+   const unsigned short STK_EVENT_TYPE_NETWORK_SEARCH_MODE_CHANGED      = 0x0e;
+   const unsigned short STK_EVENT_TYPE_BROWSING_STATUS                  = 0x0f;
+   const unsigned short STK_EVENT_TYPE_FRAMES_INFORMATION_CHANGED       = 0x10;
+
+  /**
    * Send the response back to ICC after an attempt to execute STK Proactive
    * Command.
    *
    * @param command
    *        Command received from ICC. See MozStkCommand.
    * @param response
    *        The response that will be sent to ICC.
    * @see MozStkResponse for the detail of response.
--- a/dom/interfaces/apps/nsIDOMApplicationRegistry.idl
+++ b/dom/interfaces/apps/nsIDOMApplicationRegistry.idl
@@ -68,17 +68,17 @@ interface mozIDOMApplicationMgmt : nsISu
   /**
    * event listener to get notified of application uninstalls. Only settable by
    * privileged callers.
    * the event will be a mozIDOMApplicationEvent
    */
   attribute nsIDOMEventListener onuninstall;
 };
 
-[scriptable, uuid(dd9a044c-1073-4d2b-a17d-c9b5834b3420)]
+[scriptable, uuid(7ca34d3e-d855-4d0a-a3b3-58c0acad9ec3)]
 interface mozIDOMApplicationRegistry : nsISupports
 {
   /**
    * Install a web app.
    *
    * @param manifestUrl : the URL of the webapps manifest.
    * @param parameters  : A structure with optional information.
    *                      {
@@ -90,14 +90,19 @@ interface mozIDOMApplicationRegistry : n
   nsIDOMDOMRequest install(in DOMString manifestUrl, [optional] in jsval parameters);
 
   /**
    * the request will return the application currently installed, or null.
    */
   nsIDOMDOMRequest getSelf();
 
   /**
+   * the request will return true if the app from that origin is installed
+   */
+  nsIDOMDOMRequest isInstalled(in DOMString manifestUrl);
+
+  /**
    * the request will return the applications installed from this origin, or null.
    */
   nsIDOMDOMRequest getInstalled();
 
   readonly attribute mozIDOMApplicationMgmt mgmt;
 };
--- a/dom/interfaces/canvas/nsIDOMWebGLRenderingContext.idl
+++ b/dom/interfaces/canvas/nsIDOMWebGLRenderingContext.idl
@@ -150,16 +150,35 @@ interface nsIWebGLExtensionCompressedTex
 {
     /* Compressed Texture Formats */
     const WebGLenum COMPRESSED_RGB_S3TC_DXT1_EXT        = 0x83F0;
     const WebGLenum COMPRESSED_RGBA_S3TC_DXT1_EXT       = 0x83F1;
     const WebGLenum COMPRESSED_RGBA_S3TC_DXT3_EXT       = 0x83F2;
     const WebGLenum COMPRESSED_RGBA_S3TC_DXT5_EXT       = 0x83F3;
 };
 
+[scriptable, builtinclass, uuid(9592637f-ee3b-4c42-8329-5c9ad47411c1)]
+interface nsIWebGLExtensionCompressedTextureATC : nsIWebGLExtension
+{
+    /* Compressed Texture Formats */
+    const WebGLenum COMPRESSED_RGB_ATC_WEBGL                     = 0x8C92;
+    const WebGLenum COMPRESSED_RGBA_ATC_EXPLICIT_ALPHA_WEBGL     = 0x8C93;
+    const WebGLenum COMPRESSED_RGBA_ATC_INTERPOLATED_ALPHA_WEBGL = 0x87EE;
+};
+
+[scriptable, builtinclass, uuid(c33aa5a1-035c-4dfa-b240-df71395ad0f8)]
+interface nsIWebGLExtensionCompressedTexturePVRTC : nsIWebGLExtension
+{
+    /* Compressed Texture Formats */
+    const WebGLenum COMPRESSED_RGB_PVRTC_4BPPV1  = 0x8C00;
+    const WebGLenum COMPRESSED_RGB_PVRTC_2BPPV1  = 0x8C01;
+    const WebGLenum COMPRESSED_RGBA_PVRTC_4BPPV1 = 0x8C02;
+    const WebGLenum COMPRESSED_RGBA_PVRTC_2BPPV1 = 0x8C03;
+};
+
 [scriptable, builtinclass, uuid(ef36f000-c1b2-11e1-afa7-0800200c9a66)]
 interface nsIWebGLExtensionDepthTexture : nsIWebGLExtension
 {
   const WebGLenum UNSIGNED_INT_24_8_WEBGL = 0x84FA;
 };
 
 [builtinclass, uuid(a1fdfb76-6a08-4a1a-b0c9-d92ef3357cb9)]
 interface nsIDOMWebGLRenderingContext : nsISupports
--- a/dom/plugins/base/nsPluginNativeWindowGtk2.cpp
+++ b/dom/plugins/base/nsPluginNativeWindowGtk2.cpp
@@ -12,17 +12,16 @@
 #include "nsDebug.h"
 #include "nsPluginNativeWindow.h"
 #include "nsNPAPIPlugin.h"
 #include "npapi.h"
 #include <gtk/gtk.h>
 #include <gdk/gdkx.h>
 #include <gdk/gdk.h>
 
-#include "gtk2compat.h"
 #include "gtk2xtbin.h"
 #include "mozilla/X11Util.h"
 
 class nsPluginNativeWindowGtk2 : public nsPluginNativeWindow {
 public: 
   nsPluginNativeWindowGtk2();
   virtual ~nsPluginNativeWindowGtk2();
 
--- a/dom/plugins/ipc/PluginModuleChild.cpp
+++ b/dom/plugins/ipc/PluginModuleChild.cpp
@@ -18,17 +18,16 @@
 
 #include "mozilla/ipc/SyncChannel.h"
 
 #ifdef MOZ_WIDGET_GTK
 #include <gtk/gtk.h>
 #if (MOZ_WIDGET_GTK == 3)
 #include <gtk/gtkx.h>
 #endif
-#include "gtk2compat.h"
 #endif
 
 #include "nsIFile.h"
 
 #include "pratom.h"
 #include "nsDebug.h"
 #include "nsCOMPtr.h"
 #include "nsPluginsDir.h"
--- a/dom/plugins/test/mochitest/test_busy_hang.xul
+++ b/dom/plugins/test/mochitest/test_busy_hang.xul
@@ -12,23 +12,16 @@
           src="http://mochi.test:8888/chrome/dom/plugins/test/hang_test.js" />
   <body xmlns="http://www.w3.org/1999/xhtml" onload="runTests()">
     <embed id="plugin1" type="application/x-test" width="200" height="200"></embed>
   </body>
   <script class="testbody" type="application/javascript">
     <![CDATA[
 SimpleTest.waitForExplicitFinish();
 
-const isOSXLion = navigator.userAgent.indexOf("Mac OS X 10.7") != -1;
-const isOSXMtnLion = navigator.userAgent.indexOf("Mac OS X 10.8") != -1;
-if (isOSXLion || isOSXMtnLion) {
-  todo(false, "Can't test plugin crash notification on OS X 10.7 or 10.8, see bug 705047");
-  SimpleTest.finish();
-}
-
 function runTests() {
   if (!SimpleTest.testPluginIsOOP()) {
     ok(true, "Skipping this test when test plugin is not OOP.");
     SimpleTest.finish();
     return;
   }
   
   // Default plugin hang timeout is too high for mochitests
--- a/dom/plugins/test/mochitest/test_crash_notify.xul
+++ b/dom/plugins/test/mochitest/test_crash_notify.xul
@@ -10,23 +10,16 @@
           src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
 <body xmlns="http://www.w3.org/1999/xhtml" onload="runTests()">
 <embed id="plugin1" type="application/x-test" width="200" height="200"></embed>
 </body>
 <script class="testbody" type="application/javascript">
 <![CDATA[
 SimpleTest.waitForExplicitFinish();
 
-const isOSXLion = navigator.userAgent.indexOf("Mac OS X 10.7") != -1;
-const isOSXMtnLion = navigator.userAgent.indexOf("Mac OS X 10.8") != -1;
-if (isOSXLion || isOSXMtnLion) {
-  todo(false, "Can't test plugin crash notification on OS X 10.7 or 10.8, see bug 705047");
-  SimpleTest.finish();
-}
-
 var success = false;
 
 var observerFired = false;
 
 var testObserver = {
   observe: function(subject, topic, data) {
     observerFired = true;
     ok(true, "Observer fired");
--- a/dom/plugins/test/mochitest/test_crash_notify_no_report.xul
+++ b/dom/plugins/test/mochitest/test_crash_notify_no_report.xul
@@ -10,23 +10,16 @@
           src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
 <body xmlns="http://www.w3.org/1999/xhtml" onload="runTests()">
 <embed id="plugin1" type="application/x-test" width="200" height="200"></embed>
 </body>
 <script class="testbody" type="application/javascript">
 <![CDATA[
 SimpleTest.waitForExplicitFinish();
 
-const isOSXLion = navigator.userAgent.indexOf("Mac OS X 10.7") != -1;
-const isOSXMtnLion = navigator.userAgent.indexOf("Mac OS X 10.8") != -1;
-if (isOSXLion || isOSXMtnLion) {
-  todo(false, "Can't test plugin crash notification on OS X 10.7 or 10.8, see bug 705047");
-  SimpleTest.finish();
-}
-
 var success = false;
 
 var observerFired = false;
 
 var testObserver = {
   observe: function(subject, topic, data) {
     observerFired = true;
     ok(true, "Observer fired");
--- a/dom/plugins/test/mochitest/test_crash_submit.xul
+++ b/dom/plugins/test/mochitest/test_crash_submit.xul
@@ -13,23 +13,16 @@
 <body xmlns="http://www.w3.org/1999/xhtml" onload="runTests()">
 <embed id="plugin1" type="application/x-test" width="200" height="200"></embed>
 </body>
 <script class="testbody" type="application/javascript">
 <![CDATA[
 SimpleTest.waitForExplicitFinish();
 SimpleTest.ignoreAllUncaughtExceptions();
 
-const isOSXLion = navigator.userAgent.indexOf("Mac OS X 10.7") != -1;
-const isOSXMtnLion = navigator.userAgent.indexOf("Mac OS X 10.8") != -1;
-if (isOSXLion || isOSXMtnLion) {
-  todo(false, "Can't test plugin crash notification on OS X 10.7 or 10.8, see bug 705047");
-  SimpleTest.finish();
-}
-
 Components.utils.import("resource://gre/modules/NetUtil.jsm");
 Components.utils.import("resource://gre/modules/Services.jsm");
 
 var crashReporter =
   Components.classes["@mozilla.org/toolkit/crash-reporter;1"]
     .getService(Components.interfaces.nsICrashReporter);
 var oldServerURL = crashReporter.serverURL;
 
--- a/dom/plugins/test/mochitest/test_crashing.html
+++ b/dom/plugins/test/mochitest/test_crashing.html
@@ -2,25 +2,17 @@
   <title>Plugin crashing</title>
   <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
 
 <body>
   <script class="testbody" type="application/javascript">
   SimpleTest.waitForExplicitFinish();
 
   window.frameLoaded = function frameLoaded_toCrash() {
-    const isOSXLion = navigator.userAgent.indexOf("Mac OS X 10.7") != -1;
-    const isOSXMtnLion = navigator.userAgent.indexOf("Mac OS X 10.8") != -1;
-    if (isOSXLion || isOSXMtnLion) {
-      todo(false, "Can't test plugin crash notification on OS X 10.7 or 10.8, see bug 705047");
-      SimpleTest.finish();
-      return;
-    }
-
-    if (!SimpleTest.testPluginIsOOP()) {
+   if (!SimpleTest.testPluginIsOOP()) {
       ok(true, "Skipping this test when test plugin is not OOP.");
       SimpleTest.finish();
       return;
     }
 
     SimpleTest.expectChildProcessCrash();
 
     var iframe = document.getElementById('iframe1');
--- a/dom/plugins/test/mochitest/test_hanging.html
+++ b/dom/plugins/test/mochitest/test_hanging.html
@@ -1,23 +1,16 @@
 <head>
   <title>Plugin hanging</title>
   <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
 
 <body>
   <script class="testbody" type="application/javascript">
   SimpleTest.waitForExplicitFinish();
 
-  const isOSXLion = navigator.userAgent.indexOf("Mac OS X 10.7") != -1;
-  const isOSXMtnLion = navigator.userAgent.indexOf("Mac OS X 10.8") != -1;
-  if (isOSXLion || isOSXMtnLion) {
-    todo(false, "Can't test plugin crash notification on OS X 10.7 or 10.8, see bug 705047");
-    SimpleTest.finish();
-  }
-
   window.frameLoaded = function frameLoaded_toCrash() {
     if (!SimpleTest.testPluginIsOOP()) {
       ok(true, "Skipping this test when test plugin is not OOP.");
       SimpleTest.finish();
       return;
     }
 
     SimpleTest.expectChildProcessCrash();
--- a/dom/plugins/test/mochitest/test_idle_hang.xul
+++ b/dom/plugins/test/mochitest/test_idle_hang.xul
@@ -12,23 +12,16 @@
           src="http://mochi.test:8888/chrome/dom/plugins/test/hang_test.js" />
 <body xmlns="http://www.w3.org/1999/xhtml" onload="runTests()">
 <embed id="plugin1" type="application/x-test" width="200" height="200"></embed>
 </body>
 <script class="testbody" type="application/javascript">
 <![CDATA[
 SimpleTest.waitForExplicitFinish();
 
-const isOSXLion = navigator.userAgent.indexOf("Mac OS X 10.7") != -1;
-const isOSXMtnLion = navigator.userAgent.indexOf("Mac OS X 10.8") != -1;
-if (isOSXLion || isOSXMtnLion) {
-  todo(false, "Can't test plugin crash notification on OS X 10.7 or 10.8, see bug 705047");
-  SimpleTest.finish();
-}
-
 function runTests() {
   if (!SimpleTest.testPluginIsOOP()) {
     ok(true, "Skipping this test when test plugin is not OOP.");
     SimpleTest.finish();
     return;
   }
   
   // Default plugin hang timeout is too high for mochitests
--- a/dom/sms/src/SmsManager.cpp
+++ b/dom/sms/src/SmsManager.cpp
@@ -55,36 +55,50 @@ NS_INTERFACE_MAP_END_INHERITING(nsDOMEve
 NS_IMPL_ADDREF_INHERITED(SmsManager, nsDOMEventTargetHelper)
 NS_IMPL_RELEASE_INHERITED(SmsManager, nsDOMEventTargetHelper)
 
 NS_IMPL_EVENT_HANDLER(SmsManager, received)
 NS_IMPL_EVENT_HANDLER(SmsManager, sent)
 NS_IMPL_EVENT_HANDLER(SmsManager, delivered)
 
 /* static */already_AddRefed<SmsManager>
-SmsManager::CheckPermissionAndCreateInstance(nsPIDOMWindow* aWindow)
+SmsManager::CreateInstanceIfAllowed(nsPIDOMWindow* aWindow)
 {
   NS_ASSERTION(aWindow, "Null pointer!");
 
+#ifndef MOZ_WEBSMS_BACKEND
+  return nullptr;
+#endif
+
   // First of all, the general pref has to be turned on.
   bool enabled = false;
   Preferences::GetBool("dom.sms.enabled", &enabled);
   NS_ENSURE_TRUE(enabled, nullptr);
 
   nsCOMPtr<nsIPermissionManager> permMgr =
     do_GetService(NS_PERMISSIONMANAGER_CONTRACTID);
   NS_ENSURE_TRUE(permMgr, nullptr);
 
   uint32_t permission = nsIPermissionManager::DENY_ACTION;
   permMgr->TestPermissionFromWindow(aWindow, "sms", &permission);
 
   if (permission != nsIPermissionManager::ALLOW_ACTION) {
     return nullptr;
   }
 
+  // Check the Sms Service:
+  nsCOMPtr<nsISmsService> smsService = do_GetService(SMS_SERVICE_CONTRACTID);
+  NS_ENSURE_TRUE(smsService, nullptr);
+
+  bool result = false;
+  smsService->HasSupport(&result);
+  if (!result) {
+    return nullptr;
+  }
+
   nsRefPtr<SmsManager> smsMgr = new SmsManager();
   smsMgr->Init(aWindow);
 
   return smsMgr.forget();
 }
 
 void
 SmsManager::Init(nsPIDOMWindow *aWindow)
--- a/dom/sms/src/SmsManager.h
+++ b/dom/sms/src/SmsManager.h
@@ -26,17 +26,17 @@ public:
   NS_DECL_NSIDOMMOZSMSMANAGER
 
   NS_FORWARD_NSIDOMEVENTTARGET(nsDOMEventTargetHelper::)
 
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(SmsManager,
                                            nsDOMEventTargetHelper)
 
   static already_AddRefed<SmsManager>
-  CheckPermissionAndCreateInstance(nsPIDOMWindow *aWindow);
+  CreateInstanceIfAllowed(nsPIDOMWindow *aWindow);
 
   void Init(nsPIDOMWindow *aWindow);
   void Shutdown();
 
 private:
   /**
    * Internal Send() method used to send one message.
    */
--- a/dom/system/gonk/AudioManager.cpp
+++ b/dom/system/gonk/AudioManager.cpp
@@ -28,16 +28,19 @@ using namespace mozilla;
 
 #define LOG(args...)  __android_log_print(ANDROID_LOG_INFO, "AudioManager" , ## args) 
 
 #define HEADPHONES_STATUS_CHANGED "headphones-status-changed"
 #define HEADPHONES_STATUS_ON      NS_LITERAL_STRING("on").get()
 #define HEADPHONES_STATUS_OFF     NS_LITERAL_STRING("off").get()
 #define HEADPHONES_STATUS_UNKNOWN NS_LITERAL_STRING("unknown").get()
 
+// A bitwise variable for recording what kind of headset is attached.
+static int sHeadsetState;
+
 static bool
 IsFmRadioAudioOn()
 {
   if (static_cast<
       audio_policy_dev_state_t (*) (audio_devices_t, const char *)
       >(AudioSystem::getDeviceConnectionState)) {
     return AudioSystem::getDeviceConnectionState(AUDIO_DEVICE_OUT_FM, "") == 
            AUDIO_POLICY_DEVICE_STATE_AVAILABLE ? true : false;
@@ -59,22 +62,68 @@ GetRoutingMode(int aType) {
   } else if (aType == nsIAudioManager::FORCE_BT_A2DP) {
     return AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP;
   } else {
     return AudioSystem::DEVICE_IN_DEFAULT;
   }
 }
 
 static void
+InternalSetAudioRoutesICS(SwitchState aState)
+{
+  if (aState == SWITCH_STATE_HEADSET) {
+    AudioSystem::setDeviceConnectionState(AUDIO_DEVICE_OUT_WIRED_HEADSET,
+                                          AUDIO_POLICY_DEVICE_STATE_AVAILABLE, "");
+    sHeadsetState |= AUDIO_DEVICE_OUT_WIRED_HEADSET;
+  } else if (aState == SWITCH_STATE_HEADPHONE) {
+    AudioSystem::setDeviceConnectionState(AUDIO_DEVICE_OUT_WIRED_HEADPHONE,
+                                          AUDIO_POLICY_DEVICE_STATE_AVAILABLE, "");
+    sHeadsetState |= AUDIO_DEVICE_OUT_WIRED_HEADPHONE;
+  } else if (aState == SWITCH_STATE_OFF) {
+    AudioSystem::setDeviceConnectionState(static_cast<audio_devices_t>(sHeadsetState),
+                                          AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE, "");
+    sHeadsetState = 0;
+  }
+
+  // The audio volume is not consistent when we plug and unplug the headset.
+  // Set the fm volume again here.
+  if (IsFmRadioAudioOn()) {
+    float masterVolume;
+    AudioSystem::getMasterVolume(&masterVolume);
+    AudioSystem::setFmVolume(masterVolume);
+  }
+}
+
+static void
+InternalSetAudioRoutesGB(SwitchState aState)
+{
+  audio_io_handle_t handle = 
+    AudioSystem::getOutput((AudioSystem::stream_type)AudioSystem::SYSTEM);
+  String8 cmd;
+
+  if (aState == SWITCH_STATE_HEADSET || aState == SWITCH_STATE_HEADPHONE) {
+    cmd.appendFormat("routing=%d", GetRoutingMode(nsIAudioManager::FORCE_HEADPHONES));
+  } else if (aState == SWITCH_STATE_OFF) {
+    cmd.appendFormat("routing=%d", GetRoutingMode(nsIAudioManager::FORCE_SPEAKER));
+  }
+
+  AudioSystem::setParameters(handle, cmd);
+}
+
+static void
 InternalSetAudioRoutes(SwitchState aState)
 {
-  if (aState == SWITCH_STATE_ON) {
-    AudioManager::SetAudioRoute(nsIAudioManager::FORCE_HEADPHONES);
-  } else if (aState == SWITCH_STATE_OFF) {
-    AudioManager::SetAudioRoute(nsIAudioManager::FORCE_SPEAKER);
+  if (static_cast<
+    status_t (*)(audio_devices_t, audio_policy_dev_state_t, const char*)
+    >(AudioSystem::setDeviceConnectionState)) {
+    InternalSetAudioRoutesICS(aState);
+  } else if (static_cast<
+    audio_io_handle_t (*)(AudioSystem::stream_type, uint32_t, uint32_t, uint32_t, AudioSystem::output_flags)
+    >(AudioSystem::getOutput)) {
+    InternalSetAudioRoutesGB(aState);
   }
 }
 
 static void
 NotifyHeadphonesStatus(SwitchState aState)
 {
   nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
   if (obs) {
@@ -96,17 +145,17 @@ public:
     NotifyHeadphonesStatus(aEvent.status());
   }
 };
 
 AudioManager::AudioManager() : mPhoneState(PHONE_STATE_CURRENT),
                  mObserver(new HeadphoneSwitchObserver())
 {
   RegisterSwitchObserver(SWITCH_HEADPHONES, mObserver);
-  
+
   InternalSetAudioRoutes(GetCurrentSwitchState(SWITCH_HEADPHONES));
 }
 
 AudioManager::~AudioManager() {
   UnregisterSwitchObserver(SWITCH_HEADPHONES, mObserver);
 }
 
 NS_IMETHODIMP
@@ -230,44 +279,16 @@ AudioManager::GetForceForUse(int32_t aUs
              audio_policy_forced_cfg_t (*)(audio_policy_force_use_t)
              >(AudioSystem::getForceUse)) {
     // Dynamically resolved the ICS signature.
     *aForce = AudioSystem::getForceUse((audio_policy_force_use_t)aUsage);
   }
   return NS_OK;
 }
 
-void
-AudioManager::SetAudioRoute(int aRoutes) {
-  if (static_cast<
-      audio_io_handle_t (*)(AudioSystem::stream_type, uint32_t, uint32_t, uint32_t, AudioSystem::output_flags)
-      >(AudioSystem::getOutput)) {
-    audio_io_handle_t handle = 0;
-    handle = AudioSystem::getOutput((AudioSystem::stream_type)AudioSystem::SYSTEM);
-    String8 cmd;
-    cmd.appendFormat("routing=%d", GetRoutingMode(aRoutes));
-    AudioSystem::setParameters(handle, cmd);
-  } else if (static_cast<
-             status_t (*)(audio_devices_t, audio_policy_dev_state_t, const char*)
-             >(AudioSystem::setDeviceConnectionState)) {
-    AudioSystem::setDeviceConnectionState(AUDIO_DEVICE_OUT_WIRED_HEADSET, 
-        GetRoutingMode(aRoutes) == AudioSystem::DEVICE_OUT_WIRED_HEADSET ? 
-        AUDIO_POLICY_DEVICE_STATE_AVAILABLE : AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
-        "");
-
-    // The audio volume is not consistent when we plug and unplug the headset.
-    // Set the fm volume again here.
-    if (IsFmRadioAudioOn()) {
-      float masterVolume;
-      AudioSystem::getMasterVolume(&masterVolume);
-      AudioSystem::setFmVolume(masterVolume);
-    }
-  }
-}
-
 NS_IMETHODIMP
 AudioManager::GetFmRadioAudioEnabled(bool *aFmRadioAudioEnabled)
 {
   *aFmRadioAudioEnabled = IsFmRadioAudioOn();
   return NS_OK;
 }
 
 NS_IMETHODIMP
--- a/dom/system/gonk/AudioManager.h
+++ b/dom/system/gonk/AudioManager.h
@@ -39,18 +39,16 @@ class AudioManager : public nsIAudioMana
 {
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIAUDIOMANAGER
 
   AudioManager();
   ~AudioManager();
 
-  static void SetAudioRoute(int aRoutes);
-
 protected:
   int32_t mPhoneState;
 
 private:
   nsAutoPtr<mozilla::hal::SwitchObserver> mObserver;
 };
 
 } /* namespace gonk */
--- a/dom/system/gonk/NetworkManager.js
+++ b/dom/system/gonk/NetworkManager.js
@@ -17,22 +17,16 @@ const NETWORKINTERFACE_CID =
   Components.ID("{266c3edd-78f0-4512-8178-2d6fee2d35ee}");
 
 const DEFAULT_PREFERRED_NETWORK_TYPE = Ci.nsINetworkInterface.NETWORK_TYPE_WIFI;
 
 XPCOMUtils.defineLazyServiceGetter(this, "gSettingsService",
                                    "@mozilla.org/settingsService;1",
                                    "nsISettingsService");
 
-XPCOMUtils.defineLazyGetter(this, "gWifi", function () {
-  return Cc["@mozilla.org/telephony/system-worker-manager;1"]
-           .getService(Ci.nsIInterfaceRequestor)
-           .getInterface(Ci.nsIWifi);
-});
-
 const TOPIC_INTERFACE_STATE_CHANGED  = "network-interface-state-changed";
 const TOPIC_INTERFACE_REGISTERED     = "network-interface-registered";
 const TOPIC_INTERFACE_UNREGISTERED   = "network-interface-unregistered";
 const TOPIC_DEFAULT_ROUTE_CHANGED    = "network-default-route-changed";
 const TOPIC_MOZSETTINGS_CHANGED      = "mozsettings-changed";
 const TOPIC_XPCOM_SHUTDOWN           = "xpcom-shutdown";
 
 // TODO, get USB RNDIS interface name automatically.(see Bug 776212)
@@ -290,17 +284,16 @@ NetworkManager.prototype = {
   },
 
   handleWorkerMessage: function handleWorkerMessage(e) {
     let response = e.data;
     let id = response.id;
     let callback = this.controlCallbacks[id];
     if (callback) {
       callback.call(this, response);
-      delete this.controlCallbacks[id];
     }
     debug("NetworkManager received message from worker: " + JSON.stringify(e));
   },
 
   /**
    * Determine the active interface and configure it.
    */
   setAndConfigureActive: function setAndConfigureActive() {
@@ -435,19 +428,20 @@ NetworkManager.prototype = {
 
   tetheringSettings: {},
 
   handle: function handle(aName, aResult) {
     switch(aName) {
       case SETTINGS_USB_ENABLED:
         this.handleUSBTetheringToggle(aResult);
         break;
-      case SETTINGS_WIFI_ENABLED:
-        this.handleWifiTetheringToggle(aResult);
-        break;
+      // SETTINGS_WIFI_ENABLED is handled in WifiManager.js to deal with
+      // the interaction between wifi and wifi tethering settings. Also, we
+      // update tetheringSettings[SETTINGS_WIFI_ENABLED] in setWifiTethering
+      // function.
       case SETTINGS_WIFI_SSID:
       case SETTINGS_WIFI_SECURITY_TYPE:
       case SETTINGS_WIFI_SECURITY_PASSWORD:
       case SETTINGS_WIFI_IP:
       case SETTINGS_WIFI_PREFIX:
       case SETTINGS_WIFI_DHCPSERVER_STARTIP:
       case SETTINGS_WIFI_DHCPSERVER_ENDIP:
       case SETTINGS_USB_IP:
@@ -481,17 +475,17 @@ NetworkManager.prototype = {
 
   handleUSBTetheringToggle: function handleUSBTetheringToggle(enable) {
     if (this.tetheringSettings[SETTINGS_USB_ENABLED] == enable) {
       return;
     }
 
     if (!enable) {
       this.tetheringSettings[SETTINGS_USB_ENABLED] = false;
-      this.disableTethering(TETHERING_TYPE_USB);
+      this.setUSBFunction(false, USB_FUNCTION_ADB, this.setUSBFunctionResult);
       return;
     }
 
     if (this.active) {
       this._tetheringInterface[TETHERING_TYPE_USB].externalInterface = this.active.name
     } else {
       let mobile = this.getNetworkInterface(Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE);
       if (!mobile) {
@@ -502,77 +496,17 @@ NetworkManager.prototype = {
         };
         this.usbTetheringResultReport(params);
         debug("Can't enable usb tethering - no active network interface.");
         return;
       }
       this._tetheringInterface[TETHERING_TYPE_USB].externalInterface = mobile.name;
     }
     this.tetheringSettings[SETTINGS_USB_ENABLED] = true;
-    this.enableTethering(TETHERING_TYPE_USB);
-  },
-
-  handleWifiTetheringToggle: function handleWifiTetheringToggle(enable) {
-    if (this.tetheringSettings[SETTINGS_WIFI_ENABLED] == enable) {
-      return;
-    }
-
-    let mobile = this.getNetworkInterface(Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE);
-    if (!mobile) {
-      let params = {
-        enable: enable,
-        unload: false,
-        resultCode: NETD_COMMAND_ERROR,
-        resultReason: "Mobile interface is not registered"
-      };
-      this.wifiTetheringResultReport(params);
-      debug("Can't enable wifi tethering, MOBILE interface is not registered.");
-      return;
-    }
-    this._tetheringInterface[TETHERING_TYPE_WIFI].externalInterface = mobile.name;
-
-    if (enable) {
-      this.tetheringSettings[SETTINGS_WIFI_ENABLED] = true;
-      this.enableTethering(TETHERING_TYPE_WIFI);
-    } else {
-      this.tetheringSettings[SETTINGS_WIFI_ENABLED] = false;
-      this.disableTethering(TETHERING_TYPE_WIFI);
-    }
-  },
-
-  // Callback to enable Wifi tethering.
-  setWifiTetheringEnabledResult: function setWifiTetheringEnabledResult(result, network) {
-    if (!network || result < 0) {
-      let params = {
-        enable: true,
-        unload: false,
-        resultCode: NETD_COMMAND_ERROR,
-        resultReason: "Can't enable wifi tethering"
-      };
-      debug("WifiWorker reports enable tethering result ..." + params.resultReason);
-      this.wifiTetheringResultReport(params);
-      return;
-    }
-    this._tetheringInterface[TETHERING_TYPE_WIFI].internalInterface = network.name;
-    this.setWifiTethering(true, this._tetheringInterface[TETHERING_TYPE_WIFI]);
-  },
-
-  // Callback to involve after wifi manager unloads wifi driver.
-  setWifiTetheringDisabledResult: function setWifiTetheringDisabledResult(result, network) {
-    if (result < 0) {
-      let params = {
-        enable: false,
-        unload: false,
-        resultCode: NETD_COMMAND_ERROR,
-        resultReason: "Can't enable wifi tethering"
-      };
-      debug("WifiWorker reports disable tethering result ..." + params.resultReason);
-      this.wifiTetheringResultReport(params);
-      return;
-    }
+    this.setUSBFunction(true, USB_FUNCTION_RNDIS, this.setUSBFunctionResult);
   },
 
   getWifiTetheringParameters: function getWifiTetheringParameters(enable, tetheringinterface) {
     let ssid;
     let securityType;
     let securityId;
     let interfaceIp;
     let prefix;
@@ -662,34 +596,79 @@ NetworkManager.prototype = {
       dns2: "",
       internalIfname: internalInterface,
       externalIfname: externalInterface,
       enable: enable,
       link: enable ? NETWORK_INTERFACE_UP : NETWORK_INTERFACE_DOWN
     };
   },
 
-  // Enable/disable WiFi tethering by sending commands to netd.
-  setWifiTethering: function setWifiTethering(enable, tetheringInterface) {
-    let params = this.getWifiTetheringParameters(enable, tetheringInterface);
+  get wifiTetheringEnabled() {
+    return this.tetheringSettings[SETTINGS_WIFI_ENABLED];
+  },
+
+  notifyError: function notifyError(resetSettings, callback, msg) {
+    if (resetSettings) {
+      let settingsLock = gSettingsService.createLock();
+      this.tetheringSettings[SETTINGS_WIFI_ENABLED] = false;
+      settingsLock.set("tethering.wifi.enabled", false, null);
+    }
 
-    if (params === null) {
-      params = {
-        enable: enable,
-        resultCode: NETD_COMMAND_ERROR,
-        resultReason: "Invalid parameters"
-      };
-      (enable) ? (params.unload = true) : (params.unload = false);
-      this.wifiTetheringResultReport(params);
+    debug("setWifiTethering: " + (msg ? msg : "success"));
+
+    if (callback) {
+      callback.wifiTetheringEnabledChange(msg);
+    }
+  },
+
+  // Enable/disable WiFi tethering by sending commands to netd.
+  setWifiTethering: function setWifiTethering(enable, network, callback) {
+    if (this.tetheringSettings[SETTINGS_WIFI_ENABLED] == enable) {
+      this.notifyError(false, callback, "no change");
       return;
     }
+
+    if (!network) {
+      this.notifyError(true, callback, "invalid network information");
+      return;
+    }
+    this._tetheringInterface[TETHERING_TYPE_WIFI].internalInterface = network.name;
+
+    let mobile = this.getNetworkInterface(Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE);
+    if (!mobile) {
+      this.notifyError(true, callback, "mobile interface is not registered");
+      return;
+    }
+    this._tetheringInterface[TETHERING_TYPE_WIFI].externalInterface = mobile.name;
+
+    let params = this.getWifiTetheringParameters(enable, this._tetheringInterface[TETHERING_TYPE_WIFI]);
+    if (!params) {
+      this.notifyError(true, callback, "invalid parameters");
+      return;
+    }
+
     params.cmd = "setWifiTethering";
     // The callback function in controlMessage may not be fired immediately.
     params.isAsync = true;
-    this.controlMessage(params, this.wifiTetheringResultReport);
+    this.controlMessage(params, function setWifiTetheringResult(data) {
+      let code = data.resultCode;
+      let reason = data.resultReason;
+      let enable = data.enable;
+      let enableString = enable ? "Enable" : "Disable";
+
+      debug(enableString + " Wifi tethering result: Code " + code + " reason " + reason);
+      // Update settings status.
+      this.tetheringSettings[SETTINGS_WIFI_ENABLED] = enable;
+
+      if (isError(code)) {
+        this.notifyError(true, callback, "netd command error");
+      } else {
+        this.notifyError(false, callback, null);
+      }
+    }.bind(this));
   },
 
   // Enable/disable USB tethering by sending commands to netd.
   setUSBTethering: function setUSBTethering(enable, tetheringInterface) {
     let params = this.getUSBTetheringParameters(enable, tetheringInterface);
 
     if (params === null) {
       params = {
@@ -703,39 +682,16 @@ NetworkManager.prototype = {
     }
 
     params.cmd = "setUSBTethering";
     // The callback function in controlMessage may not be fired immediately.
     params.isAsync = true;
     this.controlMessage(params, this.usbTetheringResultReport);
   },
 
-  // Send enable tehtering request to peripheral(WiFi/USB/Bluetooth) Manager module.
-  enableTethering: function enableTethering(type) {
-    if (type == TETHERING_TYPE_WIFI) {
-      debug("Notify WifiWorker to help !!!");
-      gWifi.setWifiTethering(true, this.setWifiTetheringEnabledResult.bind(this));
-    } else if (type == TETHERING_TYPE_USB) {
-      debug("Notify USB device manager to help !!!");
-      this.setUSBFunction(true, USB_FUNCTION_RNDIS, this.setUSBFunctionResult);
-    } else {
-      debug("Fatal error !!! Unsupported type.");
-    }
-  },
-
-  disableTethering: function disableTethering(type) {
-    if (type == TETHERING_TYPE_WIFI) {
-      this.setWifiTethering(false, this._tetheringInterface[TETHERING_TYPE_WIFI]);
-    } else if (type == TETHERING_TYPE_USB) {
-      this.setUSBFunction(false, USB_FUNCTION_ADB, this.setUSBFunctionResult);
-    } else {
-      debug("Fatal error !!! Unsupported type.");
-    }
-  },
-
   setUSBFunctionResult: function setUSBFunctionResult(data) {
     let result = data.result;
     let enable = data.enable;
     if (result) {
       this.setUSBTethering(enable, this._tetheringInterface[TETHERING_TYPE_USB]);
     } else {
       let params = {
         enable: false,
@@ -762,39 +718,16 @@ NetworkManager.prototype = {
       params.report = false;
     }
 
     // The callback function in controlMessage may not be fired immediately.
     params.isAsync = true;
     this.controlMessage(params, callback);
   },
 
-  wifiTetheringResultReport: function wifiTetheringResultReport(data) {
-    let code = data.resultCode;
-    let reason = data.resultReason;
-    let enable = data.enable;
-    let enableString = enable ? "Enable" : "Disable";
-    let unload = data.unload;
-    let settingsLock = gSettingsService.createLock();
-
-    debug(enableString + " Wifi tethering result: Code " + code + " reason " + reason);
-    // Unload wifi driver when
-    // 1. We have sent disable tethering commands to netd and switch wifi to station mode.
-    // 2. We fail to enable wifi tethering.
-    if (unload) {
-      gWifi.setWifiTethering(false, this.setWifiTetheringDisabledResult.bind(this));
-    }
-
-    // Disable tethering settings when fail to enable it.
-    if (isError(code)) {
-      this.tetheringSettings[SETTINGS_WIFI_ENABLED] = false;
-      settingsLock.set("tethering.wifi.enabled", false, null);
-    }
-  },
-
   usbTetheringResultReport: function usbTetheringResultReport(data) {
     let code = data.resultCode;
     let reason = data.resultReason;
     let enable = data.enable;
     let enableString = enable ? "Enable" : "Disable";
     let settingsLock = gSettingsService.createLock();
 
     debug(enableString + " USB tethering result: Code " + code + " reason " + reason);
--- a/dom/system/gonk/RadioInterfaceLayer.js
+++ b/dom/system/gonk/RadioInterfaceLayer.js
@@ -443,17 +443,19 @@ RadioInterfaceLayer.prototype = {
         break;
       case "icccontacts":
         if (!this._contactsCallbacks) {
           return;
         }
         let callback = this._contactsCallbacks[message.requestId];
         if (callback) {
           delete this._contactsCallbacks[message.requestId];
-          callback.receiveContactsList(message.contactType, message.contacts);
+          callback.receiveContactsList(message.errorMsg,
+                                       message.contactType,
+                                       message.contacts);
         }
         break;
       case "iccmbdn":
         ppmm.broadcastAsyncMessage("RIL:VoicemailNumberChanged", message);
         break;
       case "ussdreceived":
         debug("ussdreceived " + JSON.stringify(message));
         this.handleUSSDReceived(message);
@@ -997,16 +999,24 @@ RadioInterfaceLayer.prototype = {
     let sms = gSmsService.createSmsMessage(id,
                                            DOM_SMS_DELIVERY_RECEIVED,
                                            message.sender || null,
                                            message.receiver || null,
                                            message.fullBody || null,
                                            message.timestamp,
                                            false);
 
+    gSystemMessenger.broadcastMessage("sms-received",
+                                      {id: id,
+                                       delivery: DOM_SMS_DELIVERY_RECEIVED,
+                                       sender: message.sender || null,
+                                       receiver: message.receiver || null,
+                                       body: message.fullBody || null,
+                                       timestamp: message.timestamp,
+                                       read: false});
     Services.obs.notifyObservers(sms, kSmsReceivedObserverTopic, null);
   },
 
   /**
    * Local storage for sent SMS messages.
    */
   _sentSmsEnvelopes: null,
   createSmsEnvelope: function createSmsEnvelope(options) {
@@ -1851,17 +1861,17 @@ RadioInterfaceLayer.prototype = {
     message.rilMessageType = "iccSetCardLock";
     this.worker.postMessage(message);
   },
 
   _contactsCallbacks: null,
   getICCContacts: function getICCContacts(contactType, callback) {
     if (!this._contactsCallbacks) {
       this._contactsCallbacks = {};
-    } 
+    }
     let requestId = Math.floor(Math.random() * 1000);
     this._contactsCallbacks[requestId] = callback;
     this.worker.postMessage({rilMessageType: "getICCContacts",
                              contactType: contactType,
                              requestId: requestId});
   }
 };
 
--- a/dom/system/gonk/net_worker.js
+++ b/dom/system/gonk/net_worker.js
@@ -54,43 +54,28 @@ function isComplete(code) {
   return (type != NETD_COMMAND_PROCEEDING);
 }
 
 let gWifiFailChain = [stopSoftAP,
                       setIpForwardingEnabled,
                       stopTethering];
 
 function wifiTetheringFail(params) {
-  let unload = false;
-
-  // Unload wifi driver when failing to enable tethering.
-  if (params.enable) {
-    unload = true;
-  }
-  params.unload = unload;
   // Notify the main thread.
   postMessage(params);
 
   // If one of the stages fails, we try roll back to ensure
   // we don't leave the network systems in limbo.
 
   // This parameter is used to disable ipforwarding.
   params.enable = false;
   chain(params, gWifiFailChain, null);
 }
 
 function wifiTetheringSuccess(params) {
-  let unload = false;
-
-  // Unload wifi driver after switch wifi to station mode.
-  if (!params.enable) {
-    unload = true;
-  }
-
-  params.unload = unload;
   // Notify the main thread.
   postMessage(params);
   return true;
 }
 
 let gUSBFailChain = [stopSoftAP,
                      setIpForwardingEnabled,
                      stopTethering];
--- a/dom/system/gonk/nsINetworkManager.idl
+++ b/dom/system/gonk/nsINetworkManager.idl
@@ -81,20 +81,33 @@ interface nsINetworkInterface : nsISuppo
 
   /*
    * The port number of the http proxy server. 
    */
   readonly attribute long httpProxyPort;
 
 };
 
+[scriptable, function, uuid(91824160-fb25-11e1-a21f-0800200c9a66)]
+interface nsIWifiTetheringCallback : nsISupports
+{
+  /**
+   * Callback function used to report status to WifiManager.
+   *
+   * @param error
+   *        An error message if the operation wasn't successful,
+   *        or `null` if it was.
+   */
+  void wifiTetheringEnabledChange(in jsval error);
+};
+
 /**
  * Manage network interfaces.
  */
-[scriptable, uuid(3bc29392-2fba-11e1-80fd-0010183a41af)]
+[scriptable, uuid(a02de6b0-fb25-11e1-a21f-0800200c9a66)]
 interface nsINetworkManager : nsISupports
 {
   /**
    * Register the given network interface with the network manager.
    *
    * Consumers will be notified with the 'network-interface-registered'
    * observer notification.
    *
@@ -152,9 +165,27 @@ interface nsINetworkManager : nsISupport
    * the 'network-active-changed' observer notification.
    *
    * @param network
    *        Network to route all network traffic to. If this is null,
    *        a previous override is canceled.
    */
   long overrideActive(in nsINetworkInterface network);
 
+  /**
+   * Returns whether or not wifi tethering is currently enabled.
+   */
+  readonly attribute boolean wifiTetheringEnabled;
+
+  /**
+   * Enable or disable Wifi Tethering
+   *
+   * @param enabled
+   *        Boolean that indicates whether tethering should be enabled (true) or disabled (false).
+   * @param network
+   *        The Wifi network interface with at least name of network interface.
+   * @param callback
+   *        Callback function used to report status to WifiManager.
+   */
+  void setWifiTethering(in boolean enabled,
+                        in nsINetworkInterface networkInterface,
+                        in nsIWifiTetheringCallback callback);
 };
--- a/dom/system/gonk/nsIRadioInterfaceLayer.idl
+++ b/dom/system/gonk/nsIRadioInterfaceLayer.idl
@@ -112,28 +112,32 @@ interface nsIRILDataCallback : nsISuppor
    *        Array of nsIRILDataCallInfo objects.
    * @param length
    *        Lenght of the aforementioned array.
    */
   void receiveDataCallList([array,size_is(length)] in nsIRILDataCallInfo dataCalls,
                            in unsigned long length);
 };
 
-[scriptable, function, uuid(cfff68a2-7799-4c37-acca-bf58c19b2236)]
+[scriptable, function, uuid(a94282b6-da60-4daf-95c1-82ee6889d0df)]
 interface nsIRILContactCallback : nsISupports
 {
   /**
    * Called when nsIRadioInterfaceLayer is asked to provide ICC contacts.
    *
+   * @param errorMsg
+   *        error message from RIL.
    * @param contactType
    *        Type of the dialling number, i.e. ADN, FDN.
    * @param contacts
    *        Array of the ICC contacts of the specified type.
    */
-  void receiveContactsList(in DOMString contactType, in jsval contacts);
+  void receiveContactsList(in DOMString errorMsg,
+                           in DOMString contactType,
+                           in jsval contacts);
 };
 
 /**
  * Helper that runs in the content process and exposes information
  * to the DOM.
  */
 [scriptable, uuid(31ea634b-e710-49ce-bb7d-bfcbaa40fb00)]
 interface nsIRILContentHelper : nsIMobileConnectionProvider
--- a/dom/system/gonk/ril_consts.js
+++ b/dom/system/gonk/ril_consts.js
@@ -530,31 +530,33 @@ const COMPREHENSIONTLV_TAG_DURATION = 0x
 const COMPREHENSIONTLV_TAG_ALPHA_ID = 0x05;
 const COMPREHENSIONTLV_TAG_ADDRESS = 0x06;
 const COMPREHENSIONTLV_TAG_TEXT_STRING = 0x0d;
 const COMPREHENSIONTLV_TAG_ITEM = 0x0f;
 const COMPREHENSIONTLV_TAG_ITEM_ID = 0x10;
 const COMPREHENSIONTLV_TAG_RESPONSE_LENGTH = 0x11;
 const COMPREHENSIONTLV_TAG_HELP_REQUEST = 0x15;
 const COMPREHENSIONTLV_TAG_DEFAULT_TEXT = 0x17;
+const COMPREHENSIONTLV_TAG_EVENT_LIST = 0x19;
 const COMPREHENSIONTLV_TAG_ICON_ID = 0x1e;
 const COMPREHENSIONTLV_TAG_ICON_ID_LIST = 0x1f;
 const COMPREHENSIONTLV_TAG_IMMEDIATE_RESPONSE = 0x2b;
 const COMPREHENSIONTLV_TAG_URL = 0x31;
 
 // Device identifiers, see TS 11.14, clause 12.7
 const STK_DEVICE_ID_KEYPAD = 0x01;
 const STK_DEVICE_ID_DISPLAY = 0x02;
 const STK_DEVICE_ID_EARPIECE = 0x03;
 const STK_DEVICE_ID_SIM = 0x81;
 const STK_DEVICE_ID_ME = 0x82;
 const STK_DEVICE_ID_NETWORK = 0x83;
 
 // STK Proactive commands.
 const STK_CMD_REFRESH = 0x01;
+const STK_CMD_SET_UP_EVENT_LIST = 0x05;
 const STK_CMD_SET_UP_CALL = 0x10;
 const STK_CMD_SEND_SS = 0x11;
 const STK_CMD_SEND_USSD = 0x12;
 const STK_CMD_SEND_SMS = 0x13;
 const STK_CMD_SEND_DTMF = 0x14;
 const STK_CMD_LAUNCH_BROWSER = 0x15;
 const STK_CMD_DISPLAY_TEXT = 0x21;
 const STK_CMD_GET_INKEY = 0x22;
@@ -693,16 +695,34 @@ const STK_PRESENTATION_TYPE_NOT_SPECIFIE
 const STK_PRESENTATION_TYPE_DATA_VALUES = 0x01; // Bit 1 is 1, bit 2 is 0.
 const STK_PRESENTATION_TYPE_NAVIGATION_OPTIONS = 0x03; // Bit 1 is 1, bit 2 is 1.
 
 // STK Coding Scheme.
 const STK_TEXT_CODING_GSM_7BIT_PACKED = 0x00;
 const STK_TEXT_CODING_GSM_8BIT = 0x04;
 const STK_TEXT_CODING_UCS2 = 0x08;
 
+// STK Event List.
+const STK_EVENT_TYPE_MT_CALL = 0x00;
+const STK_EVENT_TYPE_CALL_CONNECTED = 0x01;
+const STK_EVENT_TYPE_CALL_DISCONNECTED = 0x02;
+const STK_EVENT_TYPE_LOCATION_STATUS = 0x03;
+const STK_EVENT_TYPE_USER_ACTIVITY = 0x04;
+const STK_EVENT_TYPE_IDLE_SCREEN_AVAILABLE = 0x05;
+const STK_EVENT_TYPE_CARD_READER_STATUS = 0x06;
+const STK_EVENT_TYPE_LANGUAGE_SELECTION = 0x07;
+const STK_EVENT_TYPE_BROWSER_TERMINATION = 0x08;
+const STK_EVENT_TYPE_DATA_AVAILABLE = 0x09;
+const STK_EVENT_TYPE_CHANNEL_STATUS = 0x0a;
+const STK_EVENT_TYPE_SINGLE_ACCESS_TECHNOLOGY_CHANGED = 0x0b;
+const STK_EVENT_TYPE_DISPLAY_PARAMETER_CHANGED = 0x0c;
+const STK_EVENT_TYPE_LOCAL_CONNECTION = 0x0d;
+const STK_EVENT_TYPE_NETWORK_SEARCH_MODE_CHANGED = 0x0e;
+const STK_EVENT_TYPE_BROWSING_STATUS = 0x0f;
+
 /**
  * (U)SIM Services.
  *
  * @see 3GPP TS 51.011 10.3.7 (SIM) and 3GPP TS 31.102 4.2.8 (USIM).
  */
 const GECKO_ICC_SERVICES = {
   sim: {
     ADN: 2,
--- a/dom/system/gonk/ril_worker.js
+++ b/dom/system/gonk/ril_worker.js
@@ -1456,21 +1456,20 @@ let RIL = {
         options.rilMessageType = "icccontacts";
         options.contacts = this.iccInfo.adn;
         this.sendDOMMessage(options);
       };
       this.parseDiallingNumber(options, add, finish);
     }
 
     function error(options) {
-      // TODO: Error handling should be addressed in Bug 787477
       delete options.callback;
       delete options.onerror;
       options.rilMessageType = "icccontacts";
-      options.contacts = [];
+      options.errorMsg = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError];
       this.sendDOMMessage(options);
     }
 
     this.iccInfo.adn = [];
     this.iccIO({
       command:   ICC_COMMAND_GET_RESPONSE,
       fileId:    options.fileId,
       pathId:    this._getPathIdForICCRecord(options.fileId),
@@ -1549,19 +1548,18 @@ let RIL = {
   /**
    * Get UICC Phonebook.
    *
    * @params contactType
    *         "ADN" or "FDN".
    */
   getICCContacts: function getICCContacts(options) {
     if (!this.appType) {
-      // TODO: Error handling should be addressed in Bug 787477
       options.rilMessageType = "icccontacts";
-      options.contacts = [];
+      options.errorMsg = GECKO_ERROR_REQUEST_NOT_SUPPORTED;
       this.sendDOMMessage(options);
     }
 
     let type = options.contactType;
     switch (type) {
       case "ADN":
         switch (this.appType) {
           case CARD_APPTYPE_SIM:
@@ -1597,21 +1595,20 @@ let RIL = {
       let adnEfid = (adn.value[0] << 8) | adn.value[1];
       this.getADN({fileId: adnEfid,
                    requestId: options.requestId});
 
       Buf.readStringDelimiter(bufLen);
     }
 
     function error(options) {
-      // TODO: Error handling should be addressed in Bug 787477
       delete options.callback;
       delete options.onerror;
       options.rilMessageType = "icccontacts";
-      options.contacts = [];
+      options.errorMsg = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError];
       this.sendDOMMessage(options);
     }
 
     this.iccIO({
       command:   ICC_COMMAND_GET_RESPONSE,
       fileId:    ICC_EF_PBR,
       pathId:    this._getPathIdForICCRecord(ICC_EF_PBR),
       p1:        0, // For GET_RESPONSE, p1 = 0
@@ -2142,35 +2139,34 @@ let RIL = {
   /**
    * Send STK terminal response.
    *
    * @param command
    * @param resultCode
    * @param [optional] itemIdentifier
    * @param [optional] input
    * @param [optional] isYesNo
-   * @param [optional] isUCS2
-   * @param [optional] isPacked
    * @param [optional] hasConfirmed
    */
   sendStkTerminalResponse: function sendStkTerminalResponse(response) {
     if (response.hasConfirmed !== undefined) {
       this.stkHandleCallSetup(response);
       return;
     }
 
     let token = Buf.newParcel(REQUEST_STK_SEND_TERMINAL_RESPONSE);
     let textLen = 0;
+    let command = response.command;
     if (response.resultCode != STK_RESULT_HELP_INFO_REQUIRED) {
       if (response.isYesNo) {
         textLen = 1;
       } else if (response.input) {
-        if (response.isUCS2) {
+        if (command.options.isUCS2) {
           textLen = response.input.length * 2;
-        } else if (response.isPacked) {
+        } else if (command.options.isPacked) {
           let bits = response.input.length * 7;
           textLen = bits * 7 / 8 + (bits % 8 ? 1 : 0);
         } else {
           textLen = response.input.length;
         }
       }
     }
 
@@ -2182,19 +2178,19 @@ let RIL = {
                 (textLen ? textLen + 3 : 0)) * 2;
     Buf.writeUint32(size);
 
     // Command Details
     GsmPDUHelper.writeHexOctet(COMPREHENSIONTLV_TAG_COMMAND_DETAILS |
                                COMPREHENSIONTLV_FLAG_CR);
     GsmPDUHelper.writeHexOctet(3);
     if (response.command) {
-      GsmPDUHelper.writeHexOctet(response.command.commandNumber);
-      GsmPDUHelper.writeHexOctet(response.command.typeOfCommand);
-      GsmPDUHelper.writeHexOctet(response.command.commandQualifier);
+      GsmPDUHelper.writeHexOctet(command.commandNumber);
+      GsmPDUHelper.writeHexOctet(command.typeOfCommand);
+      GsmPDUHelper.writeHexOctet(command.commandQualifier);
     } else {
       GsmPDUHelper.writeHexOctet(0x00);
       GsmPDUHelper.writeHexOctet(0x00);
       GsmPDUHelper.writeHexOctet(0x00);
     }
 
     // Device Identifier
     // According to TS102.223/TS31.111 section 6.8 Structure of
@@ -2235,18 +2231,20 @@ let RIL = {
       } else {
         text = response.input;
       }
 
       if (text) {
         GsmPDUHelper.writeHexOctet(COMPREHENSIONTLV_TAG_TEXT_STRING |
                                    COMPREHENSIONTLV_FLAG_CR);
         GsmPDUHelper.writeHexOctet(textLen + 1); // +1 for coding
-        let coding = response.isUCS2 ? STK_TEXT_CODING_UCS2 :
-                       (response.isPacked ? STK_TEXT_CODING_GSM_7BIT_PACKED :
+        let coding = command.options.isUCS2 ?
+                       STK_TEXT_CODING_UCS2 :
+                       (command.options.isPacked ?
+                          STK_TEXT_CODING_GSM_7BIT_PACKED :
                           STK_TEXT_CODING_GSM_8BIT);
         GsmPDUHelper.writeHexOctet(coding);
 
         // Write Text String.
         switch (coding) {
           case STK_TEXT_CODING_UCS2:
             GsmPDUHelper.writeUCS2String(text);
             break;
@@ -5615,16 +5613,19 @@ let GsmPDUHelper = {
     Buf.writeUint16(0);
   },
 };
 
 let StkCommandParamsFactory = {
   createParam: function createParam(cmdDetails, ctlvs) {
     let param;
     switch (cmdDetails.typeOfCommand) {
+      case STK_CMD_SET_UP_EVENT_LIST:
+        param = this.processSetUpEventList(cmdDetails, ctlvs);
+        break;
       case STK_CMD_SET_UP_MENU:
       case STK_CMD_SELECT_ITEM:
         param = this.processSelectItem(cmdDetails, ctlvs);
         break;
       case STK_CMD_DISPLAY_TEXT:
         param = this.processDisplayText(cmdDetails, ctlvs);
         break;
       case STK_CMD_SET_UP_IDLE_MODE_TEXT:
@@ -5651,16 +5652,37 @@ let StkCommandParamsFactory = {
       default:
         debug("unknown proactive command");
         break;
     }
     return param;
   },
 
   /**
+   * Construct a param for Set Up Event list.
+   *
+   * @param cmdDetails
+   *        The value object of CommandDetails TLV.
+   * @param ctlvs
+   *        The all TLVs in this proactive command.
+   */
+  processSetUpEventList: function processSetUpEventList(cmdDetails, ctlvs) {
+    let ctlv = StkProactiveCmdHelper.searchForTag(
+        COMPREHENSIONTLV_TAG_EVENT_LIST, ctlvs);
+    if (!ctlv) {
+      RIL.sendStkTerminalResponse({
+        command: cmdDetails,
+        resultCode: STK_RESULT_REQUIRED_VALUES_MISSING});
+      throw new Error("Stk Event List: Required value missing : Event List");
+    }
+
+    return ctlv.value || {eventList: null};
+  },
+
+  /**
    * Construct a param for Select Item.
    *
    * @param cmdDetails
    *        The value object of CommandDetails TLV.
    * @param ctlvs
    *        The all TLVs in this proactive command.
    */
   processSelectItem: function processSelectItem(cmdDetails, ctlvs) {
@@ -5918,16 +5940,18 @@ let StkProactiveCmdHelper = {
       case COMPREHENSIONTLV_TAG_ITEM:
         return this.retrieveItem(length);
       case COMPREHENSIONTLV_TAG_ITEM_ID:
         return this.retrieveItemId(length);
       case COMPREHENSIONTLV_TAG_RESPONSE_LENGTH:
         return this.retrieveResponseLength(length);
       case COMPREHENSIONTLV_TAG_DEFAULT_TEXT:
         return this.retrieveDefaultText(length);
+      case COMPREHENSIONTLV_TAG_EVENT_LIST:
+        return this.retrieveEventList(length);
       case COMPREHENSIONTLV_TAG_IMMEDIATE_RESPONSE:
         return this.retrieveImmediaResponse(length);
       case COMPREHENSIONTLV_TAG_URL:
         return this.retrieveUrl(length);
       default:
         debug("StkProactiveCmdHelper: unknown tag " + tag.toString(16));
         Buf.seekIncoming(length * PDU_HEX_OCTET_SIZE);
         return null;
@@ -6093,16 +6117,31 @@ let StkProactiveCmdHelper = {
    *
    * Same as Text String.
    */
   retrieveDefaultText: function retrieveDefaultText(length) {
     return this.retrieveTextString(length);
   },
 
   /**
+   * Event List.
+   */
+  retrieveEventList: function retrieveEventList(length) {
+    if (!length) {
+      // null means an indication to ME to remove the existing list of events
+      // in ME.
+      return null;
+    }
+
+    return {
+      eventList: GsmPDUHelper.readHexOctetArray(length)
+    };
+  },
+
+  /**
    * Immediate Response.
    *
    * | Byte  | Description            | Length |
    * |  1    | Immediate Response Tag |   1    |
    * |  2    | Length = 00            |   1    |
    */
   retrieveImmediaResponse: function retrieveImmediaResponse(length) {
     return {};
--- a/dom/tests/mochitest/general/test_interfaces.html
+++ b/dom/tests/mochitest/general/test_interfaces.html
@@ -285,16 +285,18 @@ var interfaceNamesInGlobalScope =
     "KeyEvent",
     "HTMLAreaElement",
     "XULLabelElement",
     "FormData",
     "IDBDatabase",
     "CSSPrimitiveValue",
     "SVGStopElement",
     "WebGLExtensionCompressedTextureS3TC",
+    "WebGLExtensionCompressedTextureATC",
+    "WebGLExtensionCompressedTexturePVRTC",
     "XULCommandEvent",
     "HTMLMediaElement",
     "SVGPathSegLinetoHorizontalAbs",
     "SVGAnimatedRect",
     "SVGTextContentElement",
     "WebGLRenderbuffer",
     "TreeColumn",
     "WebGLExtensionStandardDerivatives",
--- a/dom/tests/mochitest/webapps/Makefile.in
+++ b/dom/tests/mochitest/webapps/Makefile.in
@@ -24,9 +24,15 @@ MOCHITEST_CHROME_FILES = \
     test_list_api.xul \
     test_install_errors.xul \
     test_install_utf8.xul \
     test_install_receipts.xul \
     test_getNotInstalled.xul \
     test_launch_paths.xul \
     $(NULL)
 
+MOCHITEST_FILES = \
+    test_bug_779982.html \
+    file_bug_779982.js \
+    file_bug_779982.html \
+    $(NULL)
+
 include $(topsrcdir)/config/rules.mk
--- a/dom/tests/mochitest/webapps/cross_origin.html
+++ b/dom/tests/mochitest/webapps/cross_origin.html
@@ -21,20 +21,17 @@ var parent = SpecialPowers.wrap(window).
 
 confirmNextInstall();
 navigator.mozApps.install(parent.url2, null).onsuccess = function onInstall() {
   // Give the test page a reference to the installed app, so it can uninstall it
   // after it finishes the tests.
   parent.app2 = this.result;
 
   navigator.mozApps.getSelf().onsuccess = function onGetSelf() {
-    parent.ok(this.result instanceof SpecialPowers.Ci.mozIDOMApplication,
-              "getSelf() from app's origin returns mozIDOMApplication");
-    parent.is(this.result.manifestURL, parent.url2,
-              "getSelf() from app's origin returns origin's app");
+    parent.ok(this.result == null, "getSelf() from app's origin returns null if called from a browser");
 
     // Tell the test page to continue the tests.
     parent.postMessage("next", "*");
   }
 }
 
 </script>
 </body>
new file mode 100644
--- /dev/null
+++ b/dom/tests/mochitest/webapps/file_bug_779982.html
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<html>
+  <body>
+    foobar!
+  </body>
+  <script>
+    var finished = false;
+    var data = window.location.search.substring(1).split('&');
+
+    function finish(value) {
+      value ? alert('success') : alert('failure');
+      finished = true;
+    }
+
+    switch (data[0]) {
+      case "getSelf":
+        navigator.mozApps.getSelf().onsuccess = function onGetSelf() {
+          if (data[1] == 'true') {
+            finish(this.result == null);
+          } else {
+            finish(this.result != null);
+          }
+        }
+        break;
+
+      case "isInstalled":
+        navigator.mozApps.isInstalled('http://example.org/manifest.webapp').onsuccess = function onIsInstalled() {
+          if (data[1] == 'true') {
+            finish(this.result == false);
+          } else {
+            finish(this.result == true);
+          }
+        }
+        break;
+
+      case "isInstalledWrong":
+        try {
+          navigator.mozApps.isInstalled('http://something.org/manifest.webapp');
+          finish(false);
+        } catch (e) {
+          finish(true);
+        }
+        break;
+
+      default:
+        finish(false);
+        break;
+    }
+  </script>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/tests/mochitest/webapps/file_bug_779982.js
@@ -0,0 +1,125 @@
+function makeAllAppsLaunchable() {
+  var Webapps = {};
+  SpecialPowers.wrap(Components).utils.import("resource://gre/modules/Webapps.jsm", Webapps);
+  var appRegistry = SpecialPowers.wrap(Webapps.DOMApplicationRegistry);
+
+  var originalValue = appRegistry.allAppsLaunchable;
+  appRegistry.allAppsLaunchable = true;
+
+  // Clean up after ourselves once tests are done so the test page is unloaded.
+  window.addEventListener("unload", function restoreAllAppsLaunchable(event) {
+    if (event.target == window.document) {
+      window.removeEventListener("unload", restoreAllAppsLaunchable, false);
+      appRegistry.allAppsLaunchable = originalValue;
+    }
+  }, false);
+}
+
+SimpleTest.waitForExplicitFinish();
+makeAllAppsLaunchable();
+
+var fileTestOnCurrentOrigin = 'http://example.org/tests/dom/tests/mochitest/webapps/file_bug_779982.html';
+
+var previousPrefs = {
+  mozBrowserFramesEnabled: undefined,
+  oop_by_default: undefined,
+};
+
+try {
+  previousPrefs.mozBrowserFramesEnabled = SpecialPowers.getBoolPref('dom.mozBrowserFramesEnabled');
+} catch(e)
+{
+}
+
+SpecialPowers.setBoolPref('dom.mozBrowserFramesEnabled', true);
+
+SpecialPowers.addPermission("browser", true, window.document);
+
+var gData = [
+  // APP 1
+  {
+    app: 'http://example.org/manifest.webapp',
+    action: 'getSelf',
+    isnull: false,
+    src: fileTestOnCurrentOrigin,
+    message: 'getSelf() for app should return something'
+  },
+  {
+    app: 'http://example.org/manifest.webapp',
+    action: 'isInstalled',
+    isnull: false,
+    src: fileTestOnCurrentOrigin,
+    message: 'isInstalled() for app should return true'
+  },
+  {
+    app: 'http://example.org/manifest.webapp',
+    action: 'isInstalledWrong',
+    isnull: true,
+    src: fileTestOnCurrentOrigin,
+    message: 'isInstalled() for browser should return true'
+  },
+  // Browser
+  {
+    browser: true,
+    action: 'getSelf',
+    isnull: true,
+    src: fileTestOnCurrentOrigin,
+    message: 'getSelf() for browser should return null'
+  },
+  {
+    browser: true,
+    action: 'isInstalled',
+    isnull: false,
+    src: fileTestOnCurrentOrigin,
+    message: 'isInstalled() for browser should return true'
+  },
+  {
+    browser: true,
+    action: 'isInstalledWrong',
+    isnull: true,
+    src: fileTestOnCurrentOrigin,
+    message: 'isInstalled() for browser should return true'
+  },
+];
+
+function runTest() {
+  for (var i in gData) {
+    var iframe = document.createElement('iframe');
+    var data = gData[i];
+
+    if (data.app) {
+      iframe.setAttribute('mozbrowser', '');
+      iframe.setAttribute('mozapp', data.app);
+    } else if (data.browser) {
+      iframe.setAttribute('mozbrowser', '');
+    }
+
+    if (data.app || data.browser) {
+      iframe.addEventListener('mozbrowsershowmodalprompt', function(e) {
+        is(e.detail.message, 'success', data.message);
+
+        i++;
+        if (i >= gData.length) {
+          if (previousPrefs.mozBrowserFramesEnabled !== undefined) {
+            SpecialPowers.setBoolPref('dom.mozBrowserFramesEnabled', previousPrefs.mozBrowserFramesEnabled);
+          }
+
+          SpecialPowers.removePermission("browser", window.document);
+
+          SimpleTest.finish();
+        } else {
+          gTestRunner.next();
+        }
+      });
+    }
+
+    iframe.src = data.src + '?' + data.action + '&' + data.isnull;
+    document.getElementById('content').appendChild(iframe);
+
+    yield;
+  }
+}
+
+var gTestRunner = runTest();
+
+gTestRunner.next();
new file mode 100644
--- /dev/null
+++ b/dom/tests/mochitest/webapps/test_bug_779982.html
@@ -0,0 +1,21 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=779982
+-->
+<head>
+  <title>Test for getSelf()/isInstalled() in browser and in apps</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=779982">Mozilla Bug 779982</a>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script type="application/javascript;version=1.7" src="file_bug_779982.js">
+</script>
+</pre>
+</body>
+</html>
--- a/dom/tests/mochitest/webapps/test_install_errors.xul
+++ b/dom/tests/mochitest/webapps/test_install_errors.xul
@@ -23,16 +23,17 @@ var steps = [
   parseError,
   invalidManifest,
   permissionDenied,
   invalidContent,
   installPackageNotImplemented,
   invalidLaunchPath,
   invalidEntryPoint,
   invalidLocaleEntryPoint,
+  fileURL,
 ];
 
 runAll(steps);
 
 function noArgs(next) {
   try { 
     navigator.mozApps.install();
   } catch (e) {
@@ -131,10 +132,31 @@ function invalidLocaleEntryPoint(next) {
 }
 
 function installPackageNotImplemented(next) {
   ok(!("installPackage" in navigator.mozApps),
      "installPackage not in navigator.mozApps");
   next();
 }
 
+function fileURL(next) {
+  try {
+    navigator.mozApps.install("file:///nonexistent");
+    ok(false,
+       "attempt to install nonexistent file: URL doesn't throw exception");
+  } catch(ex) {
+    is(ex.message, "INVALID_URL_SCHEME: 'file'; must be 'http' or 'https'",
+       "attempt to install nonexistent file: URL throws exception");
+  }
+
+  try {
+    navigator.mozApps.install("file:///");
+    ok(false, "attempt to install existent file: URL doesn't throw exception");
+  } catch(ex) {
+    is(ex.message, "INVALID_URL_SCHEME: 'file'; must be 'http' or 'https'",
+       "attempt to install existent file: URL throws exception");
+  }
+
+  next();
+}
+
 </script>
 </window>
--- a/dom/tests/mochitest/webapps/test_list_api.xul
+++ b/dom/tests/mochitest/webapps/test_list_api.xul
@@ -15,16 +15,17 @@
   <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=741549"
      target="_blank">Mozilla Bug 741549</a>
   </body>
 
 <script>
 
 var props = {
   QueryInterface: "function",
+  isInstalled: "function",
   getInstalled: "function",
   getSelf: "function",
   install: "function",
   mgmt: "object",
 };
 
 isDeeply([p for (p in navigator.mozApps)].sort(), Object.keys(props).sort(),
          "navigator.mozApps has only the expected properties");
--- a/dom/wifi/DOMWifiManager.js
+++ b/dom/wifi/DOMWifiManager.js
@@ -73,16 +73,17 @@ DOMWifiManager.prototype = {
     this._connectionStatus = "disconnected";
     this._enabled = false;
     this._lastConnectionInfo = null;
 
     const messages = ["WifiManager:getNetworks:Return:OK", "WifiManager:getNetworks:Return:NO",
                       "WifiManager:associate:Return:OK", "WifiManager:associate:Return:NO",
                       "WifiManager:forget:Return:OK", "WifiManager:forget:Return:NO",
                       "WifiManager:wps:Return:OK", "WifiManager:wps:Return:NO",
+                      "WifiManager:setPowerSavingMode:Return:OK", "WifiManager:setPowerSavingMode:Return:NO",
                       "WifiManager:wifiDown", "WifiManager:wifiUp",
                       "WifiManager:onconnecting", "WifiManager:onassociate",
                       "WifiManager:onconnect", "WifiManager:ondisconnect",
                       "WifiManager:onwpstimeout", "WifiManager:onwpsfail",
                       "WifiManager:onwpsoverlap", "WifiManager:connectionInfoUpdate",
                       "WifiManager:onconnectingfailed"];
     this.initHelper(aWindow, messages);
     this._mm = Cc["@mozilla.org/childprocessmessagemanager;1"].getService(Ci.nsISyncMessageSender);
@@ -159,16 +160,26 @@ DOMWifiManager.prototype = {
         Services.DOMRequest.fireSuccess(request, exposeReadOnly(msg.data));
         break;
 
       case "WifiManager:wps:Return:NO":
         request = this.takeRequest(msg.rid);
         Services.DOMRequest.fireError(request, msg.data);
         break;
 
+      case "WifiManager:setPowerSavingMode:Return:OK":
+        request = this.takeRequest(msg.rid);
+        Services.DOMRequest.fireSuccess(request, exposeReadOnly(msg.data));
+        break;
+
+      case "WifiManager:setPowerSavingMode:Return:NO":
+        request = this.takeRequest(msg.rid);
+        Services.DOMRequest.fireError(request, msg.data);
+        break;
+
       case "WifiManager:wifiDown":
         this._enabled = false;
         this._currentNetwork = null;
         this._fireEnabledOrDisabled(false);
         break;
 
       case "WifiManager:wifiUp":
         this._enabled = true;
@@ -297,16 +308,24 @@ DOMWifiManager.prototype = {
   wps: function nsIDOMWifiManager_wps(detail) {
     if (!this._hasPrivileges)
       throw new Components.Exception("Denied", Cr.NS_ERROR_FAILURE);
     var request = this.createRequest();
     this._sendMessageForRequest("WifiManager:wps", detail, request);
     return request;
   },
 
+  setPowerSavingMode: function nsIDOMWifiManager_setPowerSavingMode(enabled) {
+    if (!this._hasPrivileges)
+      throw new Components.Exception("Denied", Cr.NS_ERROR_FAILURE);
+    var request = this.createRequest();
+    this._sendMessageForRequest("WifiManager:setPowerSavingMode", enabled, request);
+    return request;
+  },
+
   get enabled() {
     if (!this._hasPrivileges)
       throw new Components.Exception("Denied", Cr.NS_ERROR_FAILURE);
     return this._enabled;
   },
 
   get connection() {
     if (!this._hasPrivileges)
--- a/dom/wifi/WifiWorker.js
+++ b/dom/wifi/WifiWorker.js
@@ -399,17 +399,17 @@ var WifiManager = (function() {
     doStringCommand("DRIVER MACADDR", function(reply) {
       if (reply)
         reply = reply.split(" ")[2]; // Format: Macaddr = XX.XX.XX.XX.XX.XX
       callback(reply);
     });
   }
 
   function setPowerModeCommand(mode, callback) {
-    doBooleanCommand("DRIVER POWERMODE " + mode, "OK", callback);
+    doBooleanCommand("DRIVER POWERMODE " + (mode === "AUTO" ? 0 : 1), "OK", callback);
   }
 
   function getPowerModeCommand(callback) {
     doStringCommand("DRIVER GETPOWER", function(reply) {
       if (reply)
         reply = (reply.split()[2]|0); // Format: powermode = XX
       callback(reply);
     });
@@ -1002,38 +1002,48 @@ var WifiManager = (function() {
     }
   }
 
   // Get wifi interface and load wifi driver when enable Ap mode.
   manager.setWifiApEnabled = function(enabled, callback) {
     if (enabled) {
       getProperty("wifi.interface", "tiwlan0", function (ifname) {
         if (!ifname) {
-          callback(-1, null);
+          callback(enabled);
           return;
         }
         manager.ifname = ifname;
         loadDriver(function (status) {
           if (status < 0) {
-            callback(status, null);
+            callback(enabled);
             return;
           }
           WifiNetworkInterface.name = manager.ifname;
           manager.state = "WIFITETHERING";
-          callback(0, WifiNetworkInterface);
+          // Turning on wifi tethering.
+          gNetworkManager.setWifiTethering(enabled, WifiNetworkInterface, function(result) {
+            // Pop out current request.
+            callback(enabled);
+            // Should we fire a dom event if we fail to set wifi tethering  ?
+            debug("Enable Wifi tethering result: " + (result ? result : "successfully"));
+          });
         });
       });
     } else {
       manager.state = "UNINITIALIZED";
-      unloadDriver(function(status) {
-        if (status < 0) {
-          callback(status, null);
-          return;
-        }
-        callback(0, null);
+      gNetworkManager.setWifiTethering(enabled, WifiNetworkInterface, function(result) {
+        // Should we fire a dom event if we fail to set wifi tethering  ?
+        debug("Disable Wifi tethering result: " + (result ? result : "successfully"));
+        // Unload wifi driver even if we fail to control wifi tethering.
+        unloadDriver(function(status) {
+          if (status < 0) {
+            debug("Fail to unload wifi driver");
+          }
+          callback(enabled);
+        });
       });
     }
   }
 
   manager.disconnect = disconnectCommand;
   manager.reconnect = reconnectCommand;
   manager.reassociate = reassociateCommand;
 
@@ -1169,16 +1179,18 @@ var WifiManager = (function() {
   manager.getScanResults = scanResultsCommand;
   manager.setScanMode = function(mode, callback) {
     setScanModeCommand(mode === "active", callback);
   }
   manager.scan = scanCommand;
   manager.wpsPbc = wpsPbcCommand;
   manager.wpsPin = wpsPinCommand;
   manager.wpsCancel = wpsCancelCommand;
+  manager.setPowerMode = setPowerModeCommand;
+  manager.setSuspendOptimizations = setSuspendOptimizationsCommand;
   manager.getRssiApprox = getRssiApproxCommand;
   manager.getLinkSpeed = getLinkSpeedCommand;
   manager.getDhcpInfo = function() { return dhcpInfo; }
   manager.getConnectionInfo = (sdkVersion >= 15)
                               ? getConnectionInfoICS
                               : getConnectionInfoGB;
 
   manager.isHandShakeState = function(state) {
@@ -1365,16 +1377,17 @@ let netFromDOM;
 function WifiWorker() {
   var self = this;
 
   this._mm = Cc["@mozilla.org/parentprocessmessagemanager;1"]
                .getService(Ci.nsIMessageListenerManager);
   const messages = ["WifiManager:getNetworks",
                     "WifiManager:associate", "WifiManager:forget",
                     "WifiManager:wps", "WifiManager:getState",
+                    "WifiManager:setPowerSavingMode",
                     "WifiManager:managerFinished"];
 
   messages.forEach((function(msgName) {
     this._mm.addMessageListener(msgName, this);
   }).bind(this));
 
   Services.obs.addObserver(this, kMozSettingsChangedObserverTopic, false);
 
@@ -1977,16 +1990,19 @@ WifiWorker.prototype = {
         this.associate(msg);
         break;
       case "WifiManager:forget":
         this.forget(msg);
         break;
       case "WifiManager:wps":
         this.wps(msg);
         break;
+      case "WifiManager:setPowerSavingMode":
+        this.setPowerSavingMode(msg);
+        break;
       case "WifiManager:getState": {
         let net = this.currentNetwork ? netToDOM(this.currentNetwork) : null;
         let i;
         for (i = 0; i < this._domManagers.length; ++i) {
           let obj = this._domManagers[i];
           if (obj.manager === msg.manager) {
             obj.count++;
             break;
@@ -2072,17 +2088,17 @@ WifiWorker.prototype = {
     }
 
     // If there were requests queued after this one, run them.
     if (this._stateRequests.length > 0) {
       let timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
       let self = this;
       timer.initWithCallback(function(timer) {
         if ("callback" in self._stateRequests[0]) {
-          self._stateRequests[0].callback.call(self);
+          self._stateRequests[0].callback.call(self, self._stateRequests[0].enabled);
         } else {
           WifiManager.setWifiEnabled(self._stateRequests[0].enabled,
                                      self._setWifiEnabledCallback.bind(this));
         }
         timer = null;
       }, 1000, Ci.nsITimer.TYPE_ONE_SHOT);
     }
   },
@@ -2112,17 +2128,17 @@ WifiWorker.prototype = {
     //   - If we get multiple requests to turn on and off wifi before the
     //     current request has finished, then we need to queue up the requests
     //     and handle each on/off request in turn.
     //   - Because we can't pass a callback to WifiManager.start, we need to
     //     have a way to communicate with our onsupplicantconnection callback.
     this._stateRequests.push(msg);
     if (this._stateRequests.length === 1) {
       if ("callback" in this._stateRequests[0]) {
-        this._stateRequests[0].callback.call(this);
+        this._stateRequests[0].callback.call(this, msg.enabled);
       } else {
         WifiManager.setWifiEnabled(msg.enabled, this._setWifiEnabledCallback.bind(this));
       }
     }
   },
 
   setWifiEnabledInternal: function(enabled, callback) {
     this.setWifiEnabled({enabled: enabled, callback: callback});
@@ -2262,63 +2278,100 @@ WifiWorker.prototype = {
           self._sendMessage(message, false, "WPS Cancel failed", msg);
       });
     } else {
       self._sendMessage(message, false, "Invalid WPS method=" + detail.method,
                         msg);
     }
   },
 
+  setPowerSavingMode: function(msg) {
+    const message = "WifiManager:setPowerSavingMode:Return";
+    let self = this;
+    let enabled = msg.data;
+    let mode = enabled ? "AUTO" : "ACTIVE";
+
+    // Some wifi drivers may not implement this command. Set power mode
+    // even if suspend optimization command failed.
+    WifiManager.setSuspendOptimizations(enabled, function(ok) {
+      WifiManager.setPowerMode(mode, function(ok) {
+        if (ok) {
+          self._sendMessage(message, true, true, msg);
+        } else {
+          self._sendMessage(message, false, "Set power saving mode failed", msg);
+        }
+      });
+    });
+  },
+
   // This is a bit ugly, but works. In particular, this depends on the fact
   // that RadioManager never actually tries to get the worker from us.
   get worker() { throw "Not implemented"; },
 
   shutdown: function() {
     debug("shutting down ...");
     this.setWifiEnabled({enabled: false});
   },
 
-  setWifiTethering: function(enabled, callback) {
-    debug("Requesting Wifi Tethering from NetworkManager " + enabled);
-    // Wifi is disabled switch to Ap mode immediately.
-    if (!WifiManager.enabled) {
-      this.setWifiApEnabled(enabled, callback.wifiTetheringEnabledChange);
+  nextRequest: function nextRequest(state) {
+    if (this._stateRequests.length <= 0 ||
+        !("callback" in this._stateRequests[0])) {
+      return;
+    }
+
+    do {
+      this._stateRequests.shift();
+    } while (this._stateRequests.length &&
+             this._stateRequests[0].enabled === state);
+
+    // Serve the pending requests.
+    if (this._stateRequests.length > 0) {
+      if ("callback" in this._stateRequests[0]) {
+        this._stateRequests[0].callback.call(this,
+                                             this._stateRequests[0].enabled);
+      } else {
+        WifiManager.setWifiEnabled(this._stateRequests[0].enabled,
+                                   this._setWifiEnabledCallback.bind(this));
+      }
+    }
+  },
+
+  handleWifiEnabled: function(enabled) {
+    if (WifiManager.enabled === enabled) {
       return;
     }
-    // Wifi is enabled, disabled it before switch to Ap mode.
+    // Disable wifi tethering before enabling wifi.
+    if (gNetworkManager.wifiTetheringEnabled) {
+      this.setWifiEnabledInternal(false, function(data) {
+        this.setWifiApEnabled(data, this.nextRequest.bind(this));
+      }.bind(this));
+    }
+    this.setWifiEnabled({enabled: enabled});
+  },
+
+  handleWifiTetheringEnabled: function(enabled) {
+    if (gNetworkManager.wifiTetheringEnabled === enabled) {
+      return;
+    }
+
+    // Wifi is disabled
+    if (!WifiManager.enabled) {
+      this.setWifiEnabledInternal(enabled, function(data) {
+        this.setWifiApEnabled(data, this.nextRequest.bind(this));
+      }.bind(this));
+      return;
+    }
+
+    // Wifi is enabled, turn off it before switching to Ap mode.
     if (enabled) {
-      // Disabled the wifi before switch to AP mode.
-      this.setWifiEnabledInternal(false, (function () {
-        WifiManager.setWifiEnabled(false, (function (status) {
-          if (status === 0) {
-            this.setWifiApEnabled(true, (function (status, network) {
-              callback.wifiTetheringEnabledChange(status, network);
-              // We have finished everything we would like to do for tethering.
-              // Pop out this request.
-              if (this._stateRequests.length > 0 &&
-                  ("callback" in this._stateRequests[0])) {
-                // Pop out the request.
-                this._stateRequests.shift();
-                // Serve the pending requests.
-                if (this._stateRequests.length > 0) {
-                  WifiManager.setWifiEnabled(this._stateRequests[0].enabled,
-                                             this._setWifiEnabledCallback.bind(this));
-                }
-              }
-            }).bind(this));
-          } else {
-            if (callback) {
-              callback.wifiTetheringEnabledChange(status, null);
-            }
-          }
-        }).bind(this));
+      // Turn off wifi first.
+      this.setWifiEnabled({enabled: false});
+      this.setWifiEnabledInternal(enabled, (function (data) {
+        this.setWifiApEnabled(data, this.nextRequest.bind(this));
       }).bind(this));
-    } else {
-      // This should not be happened. Return error to NetworkManager.
-      callback.wifiTetheringEnabledChange(1, null);
     }
   },
 
   _updateWifiSetting: function(enabled) {
     // This is used to update the setting value, whenever the
     // WifiManager.enabled is re-assigned based on supplicant
     // connection/lost/failed.
     //
@@ -2330,26 +2383,39 @@ WifiWorker.prototype = {
   },
 
   // nsIObserver implementation
   observe: function observe(subject, topic, data) {
     // Note that this function gets called for any and all settings changes,
     // so we need to carefully check if we have the one we're interested in.
     // The string we're interested in will be a JSON string that looks like:
     // {"key":"wifi.enabled","value":"true"}.
-    if (topic !== kMozSettingsChangedObserverTopic)
+    if (topic !== kMozSettingsChangedObserverTopic) {
       return;
+    }
+
     let setting = JSON.parse(data);
-    if (setting.key !== "wifi.enabled")
+    if (setting.key !== "wifi.enabled" &&
+        setting.key !== "tethering.wifi.enabled") {
       return;
+    }
     // To avoid WifiWorker setting the wifi again, don't need to deal with
     // the "mozsettings-changed" event fired from internal setting.
-    if (setting.message && setting.message === "fromInternalSetting")
+    if (setting.message && setting.message === "fromInternalSetting") {
       return;
-    this.setWifiEnabled({enabled: setting.value});
+    }
+
+    switch (setting.key) {
+      case "wifi.enabled":
+        this.handleWifiEnabled(setting.value)
+        break;
+      case "tethering.wifi.enabled":
+        this.handleWifiTetheringEnabled(setting.value)
+        break;
+    }
   }
 };
 
 const NSGetFactory = XPCOMUtils.generateNSGetFactory([WifiWorker]);
 
 let debug;
 if (DEBUG) {
   debug = function (s) {
--- a/dom/wifi/nsIWifi.idl
+++ b/dom/wifi/nsIWifi.idl
@@ -1,47 +1,28 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsISupports.idl"
 #include "nsIDOMDOMRequest.idl"
 #include "nsIDOMEvent.idl"
-#include "nsINetworkManager.idl"
 
 interface nsIVariant;
 
-[scriptable, function, uuid(c675c7c3-5261-480a-98f3-69934c9ab7c6)]
-interface nsIWifiTetheringCallback : nsISupports
-{
-  /**
-   * Callback function used to report status to NetworkManager.
-   * result: 0: success, others: fail.
-   * networkInterface: report wifi network interface's name.
-   */
-  void wifiTetheringEnabledChange(in jsval result,
-                                  in nsINetworkInterface networkInterface);
-};
-
-[scriptable, uuid(65649c30-d312-11e1-9b23-0800200c9a66)]
+[scriptable, uuid(335ff8a0-fb18-11e1-a21f-0800200c9a66)]
 interface nsIWifi : nsISupports
 {
     /**
      * Shutdown the wifi system.
      */
     void shutdown();
-    /**
-     * Request to enable/disable Wifi Tethering.
-     * enabled: true or false.
-     * callback: report status to NetworkManager.
-     */
-    void setWifiTethering(in boolean enabled, in nsIWifiTetheringCallback callback);
 };
 
-[scriptable, uuid(540674a6-edbe-11e1-87c9-dbcd31c74284)]
+[scriptable, uuid(e3a967e0-015e-11e2-a21f-0800200c9a66)]
 interface nsIDOMWifiManager : nsISupports
 {
     /**
      * Returns the list of currently available networks as well as the list of
      * currently configured networks.
      * onsuccess: We have obtained the current list of networks. request.value
      *            is an object whose property names are SSIDs and values are
      *            network objects.
@@ -83,16 +64,24 @@ interface nsIDOMWifiManager : nsISupport
      *               If method field is 'pin', 'pin' field can exist and has
      *               a PIN number.
      * onsuccess: We have successfully started/canceled wps.
      * onerror: We have failed to start/cancel wps.
      */
     nsIDOMDOMRequest wps(in jsval detail);
 
     /**
+     * Turn on/off wifi power saving mode.
+     * @param enabled true or false.
+     * onsuccess: We have successfully turn on/off wifi power saving mode.
+     * onerror: We have failed to turn on/off wifi power saving mode.
+     */
+    nsIDOMDOMRequest setPowerSavingMode(in boolean enabled);
+
+    /**
      * Returns whether or not wifi is currently enabled.
      */
     readonly attribute boolean enabled;
 
     /**
      * An non-null object containing the following information:
      *  - status ("disconnected", "connecting", "associated", "connected")
      *  - network
--- a/gfx/gl/GLContext.cpp
+++ b/gfx/gl/GLContext.cpp
@@ -64,16 +64,18 @@ static const char *sExtensionNames[] = {
     "GL_ARB_texture_float",
     "GL_EXT_unpack_subimage",
     "GL_OES_standard_derivatives",
     "GL_EXT_texture_filter_anisotropic",
     "GL_EXT_texture_compression_s3tc",
     "GL_EXT_texture_compression_dxt1",
     "GL_ANGLE_texture_compression_dxt3",
     "GL_ANGLE_texture_compression_dxt5",
+    "GL_AMD_compressed_ATC_texture",
+    "GL_IMG_texture_compression_pvrtc",
     "GL_EXT_framebuffer_blit",
     "GL_ANGLE_framebuffer_blit",
     "GL_EXT_framebuffer_multisample",
     "GL_ANGLE_framebuffer_multisample",
     "GL_OES_rgb8_rgba8",
     "GL_ARB_robustness",
     "GL_EXT_robustness",
     "GL_ARB_sync",
--- a/gfx/gl/GLContext.h
+++ b/gfx/gl/GLContext.h
@@ -1653,16 +1653,18 @@ public:
         ARB_texture_float,
         EXT_unpack_subimage,
         OES_standard_derivatives,
         EXT_texture_filter_anisotropic,
         EXT_texture_compression_s3tc,
         EXT_texture_compression_dxt1,
         ANGLE_texture_compression_dxt3,
         ANGLE_texture_compression_dxt5,
+        AMD_compressed_ATC_texture,
+        IMG_texture_compression_pvrtc,
         EXT_framebuffer_blit,
         ANGLE_framebuffer_blit,
         EXT_framebuffer_multisample,
         ANGLE_framebuffer_multisample,
         OES_rgb8_rgba8,
         ARB_robustness,
         EXT_robustness,
         ARB_sync,
--- a/gfx/gl/GLDefs.h
+++ b/gfx/gl/GLDefs.h
@@ -3088,16 +3088,27 @@ typedef void* GLeglImage;
 #define LOCAL_GL_CONTEXT_CORE_PROFILE_BIT_ARB               0x00000001
 #define LOCAL_GL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB      0x00000002
 #define LOCAL_GL_CONTEXT_ROBUST_ACCESS_BIT_ARB              0x00000004
 
 #define LOCAL_WGL_CONTEXT_CORE_PROFILE_BIT_ARB              0x00000001
 #define LOCAL_WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB     0x00000002
 #define LOCAL_WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB             0x00000004
 
+// AMD_compressed_ATC_texture
+#define LOCAL_GL_ATC_RGB                                0x8C92
+#define LOCAL_GL_ATC_RGBA_EXPLICIT_ALPHA                0x8C93
+#define LOCAL_GL_ATC_RGBA_INTERPOLATED_ALPHA            0x87EE
+
+// IMG_texture_compression_pvrtc
+#define LOCAL_GL_COMPRESSED_RGB_PVRTC_4BPPV1            0x8C00
+#define LOCAL_GL_COMPRESSED_RGB_PVRTC_2BPPV1            0x8C01
+#define LOCAL_GL_COMPRESSED_RGBA_PVRTC_4BPPV1           0x8C02
+#define LOCAL_GL_COMPRESSED_RGBA_PVRTC_2BPPV1           0x8C03
+
 #define LOCAL_WGL_NUMBER_PIXEL_FORMATS_ARB 0x2000
 #define LOCAL_WGL_DRAW_TO_WINDOW_ARB 0x2001
 #define LOCAL_WGL_DRAW_TO_BITMAP_ARB 0x2002
 #define LOCAL_WGL_ACCELERATION_ARB 0x2003
 #define LOCAL_WGL_NEED_PALETTE_ARB 0x2004
 #define LOCAL_WGL_NEED_SYSTEM_PALETTE_ARB 0x2005
 #define LOCAL_WGL_SWAP_LAYER_BUFFERS_ARB 0x2006
 #define LOCAL_WGL_SWAP_METHOD_ARB 0x2007
--- a/gfx/layers/ThebesLayerBuffer.h
+++ b/gfx/layers/ThebesLayerBuffer.h
@@ -185,16 +185,20 @@ protected:
    * unset the provider when inactive, by calling
    * SetBufferProvider(nullptr).
    */
   void SetBufferProvider(AutoOpenSurface* aProvider)
   {
     mBufferProvider = aProvider;
     if (!mBufferProvider) {
       mBuffer = nullptr;
+    } else {
+      // Only this buffer provider can give us a buffer.  If we
+      // already have one, something has gone wrong.
+      MOZ_ASSERT(!mBuffer);
     }
   }
 
   /**
    * Get a context at the specified resolution for updating |aBounds|,
    * which must be contained within a single quadrant.
    */
   already_AddRefed<gfxContext>
--- a/gfx/layers/basic/BasicLayerManager.cpp
+++ b/gfx/layers/basic/BasicLayerManager.cpp
@@ -1,13 +1,14 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
+#include "mozilla/dom/TabChild.h"
 #include "mozilla/layers/PLayerChild.h"
 #include "mozilla/layers/PLayersChild.h"
 #include "mozilla/layers/PLayersParent.h"
 
 #include "gfxSharedImageSurface.h"
 #include "gfxImageSurface.h"
 #include "gfxUtils.h"
 #include "gfxPlatform.h"
@@ -20,16 +21,17 @@
 
 #include "BasicTiledThebesLayer.h"
 #include "BasicLayersImpl.h"
 #include "BasicThebesLayer.h"
 #include "BasicContainerLayer.h"
 #include "mozilla/Preferences.h"
 #include "nsIWidget.h"
 
+using namespace mozilla::dom;
 using namespace mozilla::gfx;
 
 namespace mozilla {
 namespace layers {
 
 /**
  * Clips to the smallest device-pixel-aligned rectangle containing aRect
  * in user space.
@@ -210,16 +212,17 @@ public:
 BasicLayerManager::BasicLayerManager(nsIWidget* aWidget) :
 #ifdef DEBUG
   mPhase(PHASE_NONE),
 #endif
   mWidget(aWidget)
   , mDoubleBuffering(BUFFER_NONE), mUsingDefaultTarget(false)
   , mCachedSurfaceInUse(false)
   , mTransactionIncomplete(false)
+  , mCompositorMightResample(false)
 {
   MOZ_COUNT_CTOR(BasicLayerManager);
   NS_ASSERTION(aWidget, "Must provide a widget");
 }
 
 BasicLayerManager::BasicLayerManager() :
 #ifdef DEBUG
   mPhase(PHASE_NONE),
@@ -1085,16 +1088,27 @@ BasicShadowLayerManager::BeginTransactio
   nsRefPtr<gfxContext> targetContext = aTarget;
 
   // If the last transaction was incomplete (a failed DoEmptyTransaction),
   // don't signal a new transaction to ShadowLayerForwarder. Carry on adding
   // to the previous transaction.
   if (HasShadowManager()) {
     ShadowLayerForwarder::BeginTransaction(mTargetBounds, mTargetRotation);
 
+    // If we're drawing on behalf of a context with async pan/zoom
+    // enabled, then the entire buffer of thebes layers might be
+    // composited (including resampling) asynchronously before we get
+    // a chance to repaint, so we have to ensure that it's all valid
+    // and not rotated.
+    if (mWidget) {
+      if (TabChild* window = mWidget->GetOwningTabChild()) {
+        mCompositorMightResample = window->IsAsyncPanZoomEnabled();
+      }
+    }
+
     // If we have a non-default target, we need to let our shadow manager draw
     // to it. This will happen at the end of the transaction.
     if (aTarget && (aTarget != mDefaultTarget) &&
         XRE_GetProcessType() == GeckoProcessType_Default) {
       mShadowTarget = aTarget;
 
       // Create a temporary target for ourselves, so that mShadowTarget is only
       // drawn to by our shadow manager.
--- a/gfx/layers/basic/BasicLayers.h
+++ b/gfx/layers/basic/BasicLayers.h
@@ -148,16 +148,17 @@ public:
                                                  const nsIntRegion& aRegion,
                                                  bool* aNeedsClipToVisibleRegion);
   already_AddRefed<gfxContext> PushGroupWithCachedSurface(gfxContext *aTarget,
                                                           gfxASurface::gfxContentType aContent);
   void PopGroupToSourceWithCachedSurface(gfxContext *aTarget, gfxContext *aPushed);
 
   virtual bool IsCompositingCheap() { return false; }
   virtual int32_t GetMaxTextureSize() const { return PR_INT32_MAX; }
+  bool CompositorMightResample() { return mCompositorMightResample; }
 
 protected:
   enum TransactionPhase {
     PHASE_NONE, PHASE_CONSTRUCTION, PHASE_DRAWING, PHASE_FORWARD
   };
   TransactionPhase mPhase;
 
   // This is the main body of the PaintLayer routine which will if it has
@@ -195,20 +196,21 @@ protected:
   // A context we want our shadow to draw into.
   nsRefPtr<gfxContext> mShadowTarget;
   // Image factory we use.
   nsRefPtr<ImageFactory> mFactory;
 
   // Cached surface for double buffering
   gfxCachedTempSurface mCachedSurface;
 
-  BufferMode   mDoubleBuffering;
+  BufferMode mDoubleBuffering;
   bool mUsingDefaultTarget;
   bool mCachedSurfaceInUse;
-  bool         mTransactionIncomplete;
+  bool mTransactionIncomplete;
+  bool mCompositorMightResample;
 };
  
 
 class BasicShadowLayerManager : public BasicLayerManager,
                                 public ShadowLayerForwarder
 {
   typedef nsTArray<nsRefPtr<Layer> > LayerRefArray;
 
--- a/gfx/layers/basic/BasicThebesLayer.cpp
+++ b/gfx/layers/basic/BasicThebesLayer.cpp
@@ -1,19 +1,18 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "BasicThebesLayer.h"
-
+#include "gfxUtils.h"
 #include "nsIWidget.h"
 #include "RenderTrace.h"
 #include "sampler.h"
-#include "gfxUtils.h"
 
 #include "prprf.h"
 
 using namespace mozilla::gfx;
 
 namespace mozilla {
 namespace layers {
 
@@ -151,22 +150,27 @@ BasicThebesLayer::PaintThebes(gfxContext
     }
 
     RenderTraceInvalidateEnd(this, "FFFF00");
     return;
   }
 
   {
     uint32_t flags = 0;
-#ifndef MOZ_GFX_OPTIMIZE_MOBILE
-    gfxMatrix transform;
-    if (!GetEffectiveTransform().CanDraw2D(&transform) ||
-        transform.HasNonIntegerTranslation()) {
+#ifndef MOZ_WIDGET_ANDROID
+    if (BasicManager()->CompositorMightResample()) {
       flags |= ThebesLayerBuffer::PAINT_WILL_RESAMPLE;
     }
+    if (!(flags & ThebesLayerBuffer::PAINT_WILL_RESAMPLE)) {
+      gfxMatrix transform;
+      if (!GetEffectiveTransform().CanDraw2D(&transform) ||
+          transform.HasNonIntegerTranslation()) {
+        flags |= ThebesLayerBuffer::PAINT_WILL_RESAMPLE;
+      }
+    }
 #endif
     if (mDrawAtomically) {
       flags |= ThebesLayerBuffer::PAINT_NO_ROTATION;
     }
     Buffer::PaintState state =
       mBuffer.BeginPaint(this, contentType, flags);
     mValidRegion.Sub(mValidRegion, state.mRegionToInvalidate);
 
@@ -254,25 +258,27 @@ struct NS_STACK_CLASS AutoBufferTracker 
 
   ~AutoBufferTracker() {
     mLayer->mBufferTracker = nullptr;
     mLayer->mBuffer.RevokeBuffer();
     // mInitialBuffer and mNewBuffer will clean up after themselves if
     // they were constructed.
   }
 
+  gfxASurface* GetInitialBuffer() { return mInitialBuffer.ref().Get(); }
+
   gfxASurface*
   CreatedBuffer(const SurfaceDescriptor& aDescriptor) {
     Maybe<AutoOpenSurface>* surface = mNewBuffers.AppendElement();
     surface->construct(OPEN_READ_WRITE, aDescriptor);
     return surface->ref().Get();
   }
 
   Maybe<AutoOpenSurface> mInitialBuffer;
-  nsAutoTArray<Maybe<AutoOpenSurface>, 2> mNewBuffers;
+  nsAutoTArray<Maybe<AutoOpenSurface>, 3> mNewBuffers;
   BasicShadowableThebesLayer* mLayer;
 
 private:
   AutoBufferTracker(const AutoBufferTracker&) MOZ_DELETE;
   AutoBufferTracker& operator=(const AutoBufferTracker&) MOZ_DELETE;
 };
 
 void
@@ -309,45 +315,42 @@ BasicShadowableThebesLayer::SetBackBuffe
     mBackBuffer = aBuffer.get_ThebesBuffer().buffer();
     mBackBufferRect = aBuffer.get_ThebesBuffer().rect();
     mBackBufferRectRotation = aBuffer.get_ThebesBuffer().rotation();
   }
   mFrontAndBackBufferDiffer = true;
   mROFrontBuffer = aReadOnlyFrontBuffer;
   mFrontUpdatedRegion = aFrontUpdatedRegion;
   mFrontValidRegion = aValidRegion;
-  if (OptionalThebesBuffer::Tnull_t == mROFrontBuffer.type()) {
-    // For null readonly front, we have single buffer mode
-    // so we can do sync right now, because it does not create new buffer and
-    // don't do any graphic operations
-    SyncFrontBufferToBackBuffer();
-  }
 }
 
 void
 BasicShadowableThebesLayer::SyncFrontBufferToBackBuffer()
 {
   if (!mFrontAndBackBufferDiffer) {
     return;
   }
 
-  gfxASurface* backBuffer = mBuffer.GetBuffer();
+  // We temporarily map our back buffer here in order to copy from the
+  // front buffer.  We need a live buffer tracker in order to unmap
+  // that buffer when appropriate.
+  MOZ_ASSERT(mBufferTracker);
+
+  nsRefPtr<gfxASurface> backBuffer = mBuffer.GetBuffer();
   if (!IsSurfaceDescriptorValid(mBackBuffer)) {
     MOZ_ASSERT(!backBuffer);
     MOZ_ASSERT(mROFrontBuffer.type() == OptionalThebesBuffer::TThebesBuffer);
     const ThebesBuffer roFront = mROFrontBuffer.get_ThebesBuffer();
     AutoOpenSurface roFrontBuffer(OPEN_READ_ONLY, roFront.buffer());
-    AllocBackBuffer(roFrontBuffer.ContentType(), roFrontBuffer.Size());
+    backBuffer = CreateBuffer(roFrontBuffer.ContentType(), roFrontBuffer.Size());
   }
   mFrontAndBackBufferDiffer = false;
 
-  Maybe<AutoOpenSurface> autoBackBuffer;
   if (!backBuffer) {
-    autoBackBuffer.construct(OPEN_READ_WRITE, mBackBuffer);
-    backBuffer = autoBackBuffer.ref().Get();
+    backBuffer = mBufferTracker->GetInitialBuffer();
   }
 
   if (OptionalThebesBuffer::Tnull_t == mROFrontBuffer.type()) {
     // We didn't get back a read-only ref to our old back buffer (the
     // parent's new front buffer).  If the parent is pushing updates
     // to a texture it owns, then we probably got back the same buffer
     // we pushed in the update and all is well.  If not, ...
     mValidRegion = mFrontValidRegion;
@@ -412,33 +415,16 @@ BasicShadowableThebesLayer::PaintBuffer(
                     "should have a back buffer by now");
   BasicManager()->PaintedThebesBuffer(BasicManager()->Hold(this),
                                       updatedRegion,
                                       mBuffer.BufferRect(),
                                       mBuffer.BufferRotation(),
                                       mBackBuffer);
 }
 
-void
-BasicShadowableThebesLayer::AllocBackBuffer(Buffer::ContentType aType,
-                                            const nsIntSize& aSize)
-{
-  // This function may *not* open the buffer it allocates.
-  if (!BasicManager()->AllocBuffer(gfxIntSize(aSize.width, aSize.height),
-                                   aType,
-                                   &mBackBuffer)) {
-    enum { buflen = 256 };
-    char buf[buflen];
-    PR_snprintf(buf, buflen,
-                "creating ThebesLayer 'back buffer' failed! width=%d, height=%d, type=%x",
-                aSize.width, aSize.height, int(aType));
-    NS_RUNTIMEABORT(buf);
-  }
-}
-
 already_AddRefed<gfxASurface>
 BasicShadowableThebesLayer::CreateBuffer(Buffer::ContentType aType,
                                          const nsIntSize& aSize)
 {
   if (!HasShadow()) {
     return BasicThebesLayer::CreateBuffer(aType, aSize);
   }
 
@@ -447,17 +433,26 @@ BasicShadowableThebesLayer::CreateBuffer
                   aSize.width, aSize.height));
 
   if (IsSurfaceDescriptorValid(mBackBuffer)) {
     BasicManager()->DestroyedThebesBuffer(BasicManager()->Hold(this),
                                           mBackBuffer);
     mBackBuffer = SurfaceDescriptor();
   }
 
-  AllocBackBuffer(aType, aSize);
+  if (!BasicManager()->AllocBuffer(gfxIntSize(aSize.width, aSize.height),
+                                   aType,
+                                   &mBackBuffer)) {
+    enum { buflen = 256 };
+    char buf[buflen];
+    PR_snprintf(buf, buflen,
+                "creating ThebesLayer 'back buffer' failed! width=%d, height=%d, type=%x",
+                aSize.width, aSize.height, int(aType));
+    NS_RUNTIMEABORT(buf);
+  }
 
   NS_ABORT_IF_FALSE(!mIsNewBuffer,
                     "Bad! Did we create a buffer twice without painting?");
 
   mIsNewBuffer = true;
 
   nsRefPtr<gfxASurface> buffer = mBufferTracker->CreatedBuffer(mBackBuffer);
   return buffer.forget();
--- a/gfx/layers/basic/BasicThebesLayer.h
+++ b/gfx/layers/basic/BasicThebesLayer.h
@@ -162,20 +162,16 @@ private:
   PaintBuffer(gfxContext* aContext,
               const nsIntRegion& aRegionToDraw,
               const nsIntRegion& aExtendedRegionToDraw,
               const nsIntRegion& aRegionToInvalidate,
               bool aDidSelfCopy,
               LayerManager::DrawThebesLayerCallback aCallback,
               void* aCallbackData) MOZ_OVERRIDE;
 
-  // This function may *not* open the buffer it allocates.
-  void
-  AllocBackBuffer(Buffer::ContentType aType, const nsIntSize& aSize);
-
   virtual already_AddRefed<gfxASurface>
   CreateBuffer(Buffer::ContentType aType, const nsIntSize& aSize) MOZ_OVERRIDE;
 
   void DestroyBackBuffer()
   {
     if (IsSurfaceDescriptorValid(mBackBuffer)) {
       BasicManager()->ShadowLayerForwarder::DestroySharedSurface(&mBackBuffer);
     }
--- a/gfx/layers/ipc/ShadowLayerUtilsX11.cpp
+++ b/gfx/layers/ipc/ShadowLayerUtilsX11.cpp
@@ -89,16 +89,19 @@ SurfaceDescriptorX11::OpenForeign() cons
 }
 
 bool
 ShadowLayerForwarder::PlatformAllocBuffer(const gfxIntSize& aSize,
                                           gfxASurface::gfxContentType aContent,
                                           uint32_t aCaps,
                                           SurfaceDescriptor* aBuffer)
 {
+  if (!PR_GetEnv("MOZ_LAYERS_ENABLE_XLIB_SURFACES")) {
+      return false;
+  }
   if (!UsingXCompositing()) {
     // If we're not using X compositing, we're probably compositing on
     // the client side, in which case X surfaces would just slow
     // things down.  Use Shmem instead.
     return false;
   }
   if (MAP_AS_IMAGE_SURFACE & aCaps) {
     // We can't efficiently map pixmaps as gfxImageSurface, in
--- a/gfx/thebes/gfxPlatformGtk.cpp
+++ b/gfx/thebes/gfxPlatformGtk.cpp
@@ -23,19 +23,16 @@
 #include FT_FREETYPE_H
 #include "gfxFT2Fonts.h"
 #endif
 
 #include "mozilla/gfx/2D.h"
 
 #include "cairo.h"
 #include <gtk/gtk.h>
-#if (MOZ_WIDGET_GTK == 2)
-#include "gtk2compat.h"
-#endif
 
 #include "gfxImageSurface.h"
 #ifdef MOZ_X11
 #include <gdk/gdkx.h>
 #include "gfxXlibSurface.h"
 #include "cairo-xlib.h"
 #include "mozilla/Preferences.h"
 
--- a/hal/HalTypes.h
+++ b/hal/HalTypes.h
@@ -47,16 +47,18 @@ enum SwitchDevice {
   SWITCH_USB,
   NUM_SWITCH_DEVICE
 };
 
 enum SwitchState {
   SWITCH_STATE_UNKNOWN = -1,
   SWITCH_STATE_ON,
   SWITCH_STATE_OFF,
+  SWITCH_STATE_HEADSET,          // Headphone with microphone
+  SWITCH_STATE_HEADPHONE,        // without microphone
   NUM_SWITCH_STATE
 };
 
 typedef Observer<SwitchEvent> SwitchObserver;
 
 enum ProcessPriority {
   PROCESS_PRIORITY_BACKGROUND,
   PROCESS_PRIORITY_FOREGROUND,
--- a/hal/cocoa/CocoaBattery.cpp
+++ b/hal/cocoa/CocoaBattery.cpp
@@ -230,26 +230,16 @@ MacPowerInformationService::HandleChange
   // Usually there's only 1 available, depending on current power source.
   for (CFIndex i = 0; i < ::CFArrayGetCount(list); ++i) {
     CFTypeRef source = ::CFArrayGetValueAtIndex(list, i);
     CFDictionaryRef currPowerSourceDesc = ::IOPSGetPowerSourceDescription(data, source);
     if (!currPowerSourceDesc) {
       continue;
     }
 
-    if (sIOPSGetTimeRemainingEstimate) {
-      // See if we can get a time estimate.
-      CFTimeInterval estimate = sIOPSGetTimeRemainingEstimate();
-      if (estimate == kIOPSTimeRemainingUnlimited || estimate == kIOPSTimeRemainingUnknown) {
-        remainingTime = kUnknownRemainingTime;
-      } else {
-        remainingTime = estimate;
-      }
-    }
-
     // Get a battery level estimate. This key is required.
     int currentCapacity = 0;
     const void* cfRef = ::CFDictionaryGetValue(currPowerSourceDesc, CFSTR(kIOPSCurrentCapacityKey));
     ::CFNumberGetValue((CFNumberRef)cfRef, kCFNumberSInt32Type, &currentCapacity);
 
     // This key is also required.
     int maxCapacity = 0;
     cfRef = ::CFDictionaryGetValue(currPowerSourceDesc, CFSTR(kIOPSMaxCapacityKey));
@@ -259,16 +249,41 @@ MacPowerInformationService::HandleChange
       level = static_cast<double>(currentCapacity)/static_cast<double>(maxCapacity);
     }
 
     // Find out if we're charging.
     // This key is optional, we fallback to kDefaultCharging if the current power
     // source doesn't have that info.
     if(::CFDictionaryGetValueIfPresent(currPowerSourceDesc, CFSTR(kIOPSIsChargingKey), &cfRef)) {
       charging = ::CFBooleanGetValue((CFBooleanRef)cfRef);
+
+      // Get an estimate of how long it's going to take until we're fully charged.
+      // This key is optional.
+      if (charging) {
+        // Default value that will be changed if we happen to find the actual
+        // remaining time.
+        remainingTime = level == 1.0 ? kDefaultRemainingTime : kUnknownRemainingTime;
+
+        if (::CFDictionaryGetValueIfPresent(currPowerSourceDesc,
+                CFSTR(kIOPSTimeToFullChargeKey), &cfRef)) {
+          int timeToCharge;
+          ::CFNumberGetValue((CFNumberRef)cfRef, kCFNumberIntType, &timeToCharge);
+          if (timeToCharge != kIOPSTimeRemainingUnknown) {
+            remainingTime = timeToCharge*60;
+          }
+        }
+      } else if (sIOPSGetTimeRemainingEstimate) { // not charging
+        // See if we can get a time estimate.
+        CFTimeInterval estimate = sIOPSGetTimeRemainingEstimate();
+        if (estimate == kIOPSTimeRemainingUnlimited || estimate == kIOPSTimeRemainingUnknown) {
+          remainingTime = kUnknownRemainingTime;
+        } else {
+          remainingTime = estimate;
+        }
+      }
     }
 
     break;
   }
 
   bool isNewData = level != power->mLevel || charging != power->mCharging ||
                    remainingTime != power->mRemainingTime;
 
--- a/hal/gonk/GonkSwitch.cpp
+++ b/hal/gonk/GonkSwitch.cpp
@@ -33,43 +33,26 @@ using namespace mozilla::hal;
 
 #define SWITCH_HEADSET_DEVPATH "/devices/virtual/switch/h2w"
 #define SWITCH_USB_DEVPATH_GB  "/devices/virtual/switch/usb_configuration"
 #define SWITCH_USB_DEVPATH_ICS "/devices/virtual/android_usb/android0"
 
 namespace mozilla {
 namespace hal_impl {
 /**
- * The uevent for a headset on SGS2 insertion looks like:
- * 
- * change@/devices/virtual/switch/h2w
- *   ACTION=change
- *   DEVPATH=/devices/virtual/switch/h2w
- *   SUBSYSTEM=switch
- *   SWITCH_NAME=h2w
- *   SWITCH_STATE=2
- *   SEQNUM=2581
- * On Otoro, SWITCH_NAME could be Headset/No Device when plug/unplug.
- * change@/devices/virtual/switch/h2w
- *   ACTION=change
- *   DEVPATH=/devices/virtual/switch/h2w
- *   SUBSYSTEM=switch
- *   SWITCH_NAME=Headset
- *   SWITCH_STATE=1
- *   SEQNUM=1602
- * 
- * The uevent for usb on GB,
+ * The uevent for a usb on GB insertion looks like:
+ *
  *  change@/devices/virtual/switch/usb_configuration
  *    ACTION=change
  *    DEVPATH=/devices/virtual/switch/usb_configuration
  *    SUBSYSTEM=switch
  *    SWITCH_NAME=usb_configuration
  *    SWITCH_STATE=0
  *    SEQNUM=5038
- */ 
+ */
 class SwitchHandler : public RefCounted<SwitchHandler>
 {
 public:
   SwitchHandler(const char* aDevPath, SwitchDevice aDevice)
     : mDevPath(aDevPath),
       mState(SWITCH_STATE_UNKNOWN),
       mDevice(aDevice)
   {
@@ -179,16 +162,57 @@ protected:
 
   SwitchState ConvertState(const char* aState)
   {
     MOZ_ASSERT(aState);
     return strcmp(aState, "CONFIGURED") == 0 ? SWITCH_STATE_ON : SWITCH_STATE_OFF;
   }
 };
 
+/**
+ * The uevent delivered for the headset under ICS looks like,
+ *
+ * change@/devices/virtual/switch/h2w
+ *   ACTION=change
+ *   DEVPATH=/devices/virtual/switch/h2w
+ *   SUBSYSTEM=switch
+ *   SWITCH_NAME=h2w
+ *   SWITCH_STATE=2 // Headset with no mic
+ *   SEQNUM=2581
+ * On Otoro, SWITCH_NAME could be Headset/No Device when plug/unplug.
+ * change@/devices/virtual/switch/h2w
+ *   ACTION=change
+ *   DEVPATH=/devices/virtual/switch/h2w
+ *   SUBSYSTEM=switch
+ *   SWITCH_NAME=Headset
+ *   SWITCH_STATE=1 // Headset with mic
+ *   SEQNUM=1602
+ */
+class SwitchHandlerHeadphone: public SwitchHandler
+{
+public:
+  SwitchHandlerHeadphone(const char* aDevPath) :
+    SwitchHandler(aDevPath, SWITCH_HEADPHONES)
+  {
+    SwitchHandler::GetInitialState();
+  }
+
+  virtual ~SwitchHandlerHeadphone() { }
+
+protected:
+  SwitchState ConvertState(const char* aState)
+  {
+    MOZ_ASSERT(aState);
+
+    return aState[0] == '0' ? SWITCH_STATE_OFF :
+      (aState[0] == '1' ? SWITCH_STATE_HEADSET : SWITCH_STATE_HEADPHONE);
+  }
+};
+
+
 typedef nsTArray<RefPtr<SwitchHandler> > SwitchHandlerArray;
 
 class SwitchEventRunnable : public nsRunnable
 {
 public:
   SwitchEventRunnable(SwitchEvent& aEvent) : mEvent(aEvent)
   {
   }
@@ -280,20 +304,20 @@ private:
   };
 
   EventInfo mEventInfo[NUM_SWITCH_DEVICE];
   size_t mEnableCount;
   SwitchHandlerArray mHandler;
 
   void Init()
   {
-    mHandler.AppendElement(new SwitchHandler(SWITCH_HEADSET_DEVPATH, SWITCH_HEADPHONES));
+    mHandler.AppendElement(new SwitchHandlerHeadphone(SWITCH_HEADSET_DEVPATH));
     mHandler.AppendElement(new SwitchHandler(SWITCH_USB_DEVPATH_GB, SWITCH_USB));
     mHandler.AppendElement(new SwitchHandlerUsbIcs(SWITCH_USB_DEVPATH_ICS));
-    
+
     SwitchHandlerArray::index_type handlerIndex;
     SwitchHandlerArray::size_type numHandlers = mHandler.Length();
 
     for (handlerIndex = 0; handlerIndex < numHandlers; handlerIndex++) {
       SwitchState state = mHandler[handlerIndex]->GetState();
       if (state == SWITCH_STATE_UNKNOWN) {
         continue;
       }
--- a/ipc/glue/IPCMessageUtils.h
+++ b/ipc/glue/IPCMessageUtils.h
@@ -7,18 +7,18 @@
 #ifndef __IPC_GLUE_IPCMESSAGEUTILS_H__
 #define __IPC_GLUE_IPCMESSAGEUTILS_H__
 
 #include "chrome/common/ipc_message_utils.h"
 
 #include "mozilla/TimeStamp.h"
 #include "mozilla/Util.h"
 #include "mozilla/gfx/2D.h"
+#include "mozilla/StandardInteger.h"
 
-#include "prtypes.h"
 #include "nsID.h"
 #include "nsMemory.h"
 #include "nsStringGlue.h"
 #include "nsTArray.h"
 #include "gfx3DMatrix.h"
 #include "gfxColor.h"
 #include "gfxMatrix.h"
 #include "gfxPattern.h"
--- a/js/src/config/config.mk
+++ b/js/src/config/config.mk
@@ -22,16 +22,30 @@ EXIT_ON_ERROR = set -e; # Shell loops co
 ifndef topsrcdir
 topsrcdir	= $(DEPTH)
 endif
 
 ifndef INCLUDED_AUTOCONF_MK
 include $(DEPTH)/config/autoconf.mk
 endif
 
+space = $(NULL) $(NULL)
+
+# Include defs.mk files that can be found in $(srcdir)/$(DEPTH),
+# $(srcdir)/$(DEPTH-1), $(srcdir)/$(DEPTH-2), etc., and $(srcdir)
+# where $(DEPTH-1) is one level less of depth, $(DEPTH-2), two, etc.
+# i.e. for DEPTH=../../.., DEPTH-1 is ../.. and DEPTH-2 is ..
+# These defs.mk files are used to define variables in a directory
+# and all its subdirectories, recursively.
+__depth := $(subst /, ,$(DEPTH))
+ifeq (.,$(__depth))
+__depth :=
+endif
+$(foreach __d,$(__depth) .,$(eval __depth = $(wordlist 2,$(words $(__depth)),$(__depth))$(eval -include $(subst $(space),/,$(strip $(srcdir) $(__depth) defs.mk)))))
+
 COMMA = ,
 
 # Sanity check some variables
 CHECK_VARS := \
  XPI_NAME \
  LIBRARY_NAME \
  MODULE \
  DEPTH \
@@ -46,19 +60,16 @@ CHECK_VARS := \
 # named by $x
 check-variable = $(if $(filter-out 0 1,$(words $($(x))z)),$(error Spaces are not allowed in $(x)))
 
 $(foreach x,$(CHECK_VARS),$(check-variable))
 
 core_abspath = $(if $(findstring :,$(1)),$(1),$(if $(filter /%,$(1)),$(1),$(CURDIR)/$(1)))
 core_realpath = $(if $(realpath $(1)),$(realpath $(1)),$(call core_abspath,$(1)))
 
-nullstr :=
-space :=$(nullstr) # EOL
-
 core_winabspath = $(firstword $(subst /, ,$(call core_abspath,$(1)))):$(subst $(space),,$(patsubst %,\\%,$(wordlist 2,$(words $(subst /, ,$(call core_abspath,$(1)))), $(strip $(subst /, ,$(call core_abspath,$(1)))))))
 
 RM = rm -f
 
 # LIBXUL_DIST is not defined under js/src, thus we make it mean DIST there.
 LIBXUL_DIST ?= $(DIST)
 
 # FINAL_TARGET specifies the location into which we copy end-user-shipped
@@ -809,8 +820,12 @@ EXPAND_LIBNAME_PATH = $(foreach lib,$(1)
 EXPAND_MOZLIBNAME = $(foreach lib,$(1),$(DIST)/lib/$(LIB_PREFIX)$(lib).$(LIB_SUFFIX))
 
 # Include internal ply only if needed
 ifndef MOZ_SYSTEM_PLY
 PLY_INCLUDE = -I$(topsrcdir)/other-licenses/ply
 endif
 
 export CL_INCLUDES_PREFIX
+
+ifeq ($(MOZ_WIDGET_GTK),2)
+MOZ_GTK2_CFLAGS := -I$(topsrcdir)/widget/gtk2/compat $(MOZ_GTK2_CFLAGS)
+endif
--- a/js/src/config/rules.mk
+++ b/js/src/config/rules.mk
@@ -938,17 +938,17 @@ endif # Sun Studio on Solaris
 
 $(HOST_CMMOBJS): host_%.$(OBJ_SUFFIX): %.mm
 	$(REPORT_BUILD)
 	$(ELOG) $(HOST_CXX) $(HOST_OUTOPTION)$@ -c $(HOST_CXXFLAGS) $(HOST_CMMFLAGS) $(INCLUDES) $(NSPR_CFLAGS) $(_VPATH_SRCS)
 
 $(COBJS): %.$(OBJ_SUFFIX): %.c $(call mkdir_deps,$(MDDEPDIR))
 	$(REPORT_BUILD)
 	@$(MAKE_DEPS_AUTO_CC)
-	$(ELOG) $(CC) $(OUTOPTION)$@ -c $(COMPILE_CFLAGS) $(_VPATH_SRCS)
+	$(ELOG) $(CC) $(OUTOPTION)$@ -c $(COMPILE_CFLAGS) $(TARGET_LOCAL_INCLUDES) $(_VPATH_SRCS)
 
 # DEFINES and ACDEFINES are needed here to enable conditional compilation of Q_OBJECTs:
 # 'moc' only knows about #defines it gets on the command line (-D...), not in
 # included headers like mozilla-config.h
 moc_%.cpp: %.h
 	$(ELOG) $(MOC) $(DEFINES) $(ACDEFINES) $< $(OUTOPTION)$@
 
 moc_%.cc: %.cc
@@ -960,61 +960,61 @@ qrc_%.cpp: %.qrc
 ifdef ASFILES
 # The AS_DASH_C_FLAG is needed cause not all assemblers (Solaris) accept
 # a '-c' flag.
 $(ASOBJS): %.$(OBJ_SUFFIX): %.$(ASM_SUFFIX)
 	$(AS) $(ASOUTOPTION)$@ $(ASFLAGS) $(AS_DASH_C_FLAG) $(_VPATH_SRCS)
 endif
 
 $(SOBJS): %.$(OBJ_SUFFIX): %.S
-	$(AS) -o $@ $(ASFLAGS) -c $<
+	$(AS) -o $@ $(ASFLAGS) $(LOCAL_INCLUDES) $(TARGET_LOCAL_INCLUDES) -c $<
 
 #
 # Please keep the next two rules in sync.
 #
 $(CCOBJS): %.$(OBJ_SUFFIX): %.cc $(call mkdir_deps,$(MDDEPDIR))
 	$(REPORT_BUILD)
 	@$(MAKE_DEPS_AUTO_CXX)
-	$(ELOG) $(CCC) $(OUTOPTION)$@ -c $(COMPILE_CXXFLAGS) $(_VPATH_SRCS)
+	$(ELOG) $(CCC) $(OUTOPTION)$@ -c $(COMPILE_CXXFLAGS) $(TARGET_LOCAL_INCLUDES) $(_VPATH_SRCS)
 
 $(CPPOBJS): %.$(OBJ_SUFFIX): %.cpp $(call mkdir_deps,$(MDDEPDIR))
 	$(REPORT_BUILD)
 	@$(MAKE_DEPS_AUTO_CXX)
-	$(ELOG) $(CCC) $(OUTOPTION)$@ -c $(COMPILE_CXXFLAGS) $(_VPATH_SRCS)
+	$(ELOG) $(CCC) $(OUTOPTION)$@ -c $(COMPILE_CXXFLAGS) $(TARGET_LOCAL_INCLUDES) $(_VPATH_SRCS)
 
 $(CMMOBJS): $(OBJ_PREFIX)%.$(OBJ_SUFFIX): %.mm $(call mkdir_deps,$(MDDEPDIR))
 	$(REPORT_BUILD)
 	@$(MAKE_DEPS_AUTO_CXX)
-	$(ELOG) $(CCC) -o $@ -c $(COMPILE_CXXFLAGS) $(COMPILE_CMMFLAGS) $(_VPATH_SRCS)
+	$(ELOG) $(CCC) -o $@ -c $(COMPILE_CXXFLAGS) $(COMPILE_CMMFLAGS) $(TARGET_LOCAL_INCLUDES) $(_VPATH_SRCS)
 
 $(CMOBJS): $(OBJ_PREFIX)%.$(OBJ_SUFFIX): %.m $(call mkdir_deps,$(MDDEPDIR))
 	$(REPORT_BUILD)
 	@$(MAKE_DEPS_AUTO_CC)
-	$(ELOG) $(CC) -o $@ -c $(COMPILE_CFLAGS) $(COMPILE_CMFLAGS) $(_VPATH_SRCS)
+	$(ELOG) $(CC) -o $@ -c $(COMPILE_CFLAGS) $(COMPILE_CMFLAGS) $(TARGET_LOCAL_INCLUDES) $(_VPATH_SRCS)
 
 %.s: %.cpp $(call mkdir_deps,$(MDDEPDIR))
-	$(CCC) -S $(COMPILE_CXXFLAGS) $(_VPATH_SRCS)
+	$(CCC) -S $(COMPILE_CXXFLAGS) $(TARGET_LOCAL_INCLUDES) $(_VPATH_SRCS)
 
 %.s: %.cc $(call mkdir_deps,$(MDDEPDIR))
-	$(CCC) -S $(COMPILE_CXXFLAGS) $(_VPATH_SRCS)
+	$(CCC) -S $(COMPILE_CXXFLAGS) $(TARGET_LOCAL_INCLUDES) $(_VPATH_SRCS)
 
 %.s: %.c $(call mkdir_deps,$(MDDEPDIR))
-	$(CC) -S $(COMPILE_CFLAGS) $(_VPATH_SRCS)
+	$(CC) -S $(COMPILE_CFLAGS) $(TARGET_LOCAL_INCLUDES) $(_VPATH_SRCS)
 
 %.i: %.cpp $(call mkdir_deps,$(MDDEPDIR))
-	$(CCC) -C -E $(COMPILE_CXXFLAGS) $(_VPATH_SRCS) > $*.i
+	$(CCC) -C -E $(COMPILE_CXXFLAGS) $(TARGET_LOCAL_INCLUDES) $(_VPATH_SRCS) > $*.i
 
 %.i: %.cc $(call mkdir_deps,$(MDDEPDIR))
-	$(CCC) -C -E $(COMPILE_CXXFLAGS) $(_VPATH_SRCS) > $*.i
+	$(CCC) -C -E $(COMPILE_CXXFLAGS) $(TARGET_LOCAL_INCLUDES) $(_VPATH_SRCS) > $*.i
 
 %.i: %.c $(call mkdir_deps,$(MDDEPDIR))
-	$(CC) -C -E $(COMPILE_CFLAGS) $(_VPATH_SRCS) > $*.i
+	$(CC) -C -E $(COMPILE_CFLAGS) $(TARGET_LOCAL_INCLUDES) $(_VPATH_SRCS) > $*.i
 
 %.i: %.mm $(call mkdir_deps,$(MDDEPDIR))
-	$(CCC) -C -E $(COMPILE_CXXFLAGS) $(COMPILE_CMMFLAGS) $(_VPATH_SRCS) > $*.i
+	$(CCC) -C -E $(COMPILE_CXXFLAGS) $(COMPILE_CMMFLAGS) $(TARGET_LOCAL_INCLUDES) $(_VPATH_SRCS) > $*.i
 
 %.res: %.rc
 	@echo Creating Resource file: $@
 ifeq ($(OS_ARCH),OS2)
 	$(RC) $(RCFLAGS:-D%=-d %) -i $(subst /,\,$(srcdir)) -r $< $@
 else
 ifdef GNU_CC
 	$(RC) $(RCFLAGS) $(filter-out -U%,$(DEFINES)) $(INCLUDES:-I%=--include-dir %) $(OUTOPTION)$@ $(_VPATH_SRCS)
--- a/js/src/ctypes/CTypes.h
+++ b/js/src/ctypes/CTypes.h
@@ -245,17 +245,17 @@ struct FunctionInfo
 {
   // Initialized in NewFunctionInfo when !mIsVariadic, but only later, in
   // FunctionType::Call, when mIsVariadic. Not always consistent with
   // mFFITypes, due to lazy initialization when mIsVariadic.
   ffi_cif mCIF;
 
   // Calling convention of the function. Convert to ffi_abi using GetABI
   // and OBJECT_TO_JSVAL. Stored as a JSObject* for ease of tracing.
-  JSObject* mABI;                
+  JSObject* mABI;
 
   // The CType of the value returned by the function.
   JSObject* mReturnType;
 
   // A fixed array of known parameter types, excluding any variadic
   // parameters (if mIsVariadic).
   Array<JSObject*> mArgTypes; 
 
--- a/js/src/ion/CodeGenerator.cpp
+++ b/js/src/ion/CodeGenerator.cpp
@@ -2640,17 +2640,17 @@ LoadNativeIterator(MacroAssembler &masm,
 
 bool
 CodeGenerator::visitIteratorNext(LIteratorNext *lir)
 {
     const Register obj = ToRegister(lir->object());
     const Register temp = ToRegister(lir->temp());
     const ValueOperand output = ToOutValue(lir);
 
-    typedef bool (*pf)(JSContext *, JSObject *, MutableHandleValue);
+    typedef bool (*pf)(JSContext *, HandleObject, MutableHandleValue);
     static const VMFunction Info = FunctionInfo<pf>(js_IteratorNext);
 
     OutOfLineCode *ool = oolCallVM(Info, lir, (ArgList(), obj), StoreValueTo(output));
     if (!ool)
         return false;
 
     LoadNativeIterator(masm, obj, temp, ool->entry());
 
@@ -2698,17 +2698,17 @@ CodeGenerator::visitIteratorMore(LIterat
 
 bool
 CodeGenerator::visitIteratorEnd(LIteratorEnd *lir)
 {
     const Register obj = ToRegister(lir->object());
     const Register temp1 = ToRegister(lir->temp1());
     const Register temp2 = ToRegister(lir->temp2());
 
-    typedef bool (*pf)(JSContext *, JSObject *);
+    typedef bool (*pf)(JSContext *, HandleObject);
     static const VMFunction Info = FunctionInfo<pf>(CloseIterator);
 
     OutOfLineCode *ool = oolCallVM(Info, lir, (ArgList(), obj), StoreNothing());
     if (!ool)
         return false;
 
     LoadNativeIterator(masm, obj, temp1, ool->entry());
 
--- a/js/src/ion/IonBuilder.cpp
+++ b/js/src/ion/IonBuilder.cpp
@@ -3448,17 +3448,17 @@ IonBuilder::createCallObject(MDefinition
     current->add(MStoreFixedSlot::New(callObj, CallObject::calleeSlot(), callee));
     current->add(MStoreFixedSlot::New(callObj, CallObject::enclosingScopeSlot(), scope));
 
     // Initialize argument slots.
     for (AliasedFormalIter i(script); i; i++) {
         unsigned slot = i.scopeSlot();
         unsigned formal = i.frameIndex();
         MDefinition *param = current->getSlot(info().argSlot(formal));
-        if (slots->type() == MIRType_Slots)
+        if (slot >= templateObj->numFixedSlots())
             current->add(MStoreSlot::New(slots, slot - templateObj->numFixedSlots(), param));
         else
             current->add(MStoreFixedSlot::New(callObj, slot, param));
     }
 
     return callObj;
 }
 
--- a/js/src/ion/IonCaches.cpp
+++ b/js/src/ion/IonCaches.cpp
@@ -273,16 +273,28 @@ TryAttachNativeStub(JSContext *cx, IonCa
     RootedShape shape(cx);
     RootedObject holder(cx);
     if (!JSObject::lookupProperty(cx, obj, name, &holder, &shape))
         return false;
 
     if (!IsCacheableGetProp(obj, holder, shape))
         return true;
 
+    // TI infers the possible types of native object properties. There's one
+    // edge case though: for singleton objects it does not add the initial
+    // "undefined" type, see the propertySet comment in jsinfer.h. We can't
+    // monitor the return type inside an idempotent cache though, so we don't
+    // handle this case.
+    if (cache.idempotent() &&
+        holder->hasSingletonType() &&
+        holder->getSlot(shape->slot()).isUndefined())
+    {
+        return true;
+    }
+
     *isCacheableNative = true;
 
     if (cache.stubCount() < MAX_STUBS) {
         cache.incrementStubCount();
 
         if (!cache.attachNative(cx, obj, holder, shape))
             return false;
     }
--- a/js/src/ion/IonFrames.cpp
+++ b/js/src/ion/IonFrames.cpp
@@ -247,17 +247,17 @@ CloseLiveIterator(JSContext *cx, const I
     // Skip stack slots until we reach the iterator object.
     uint32 base = CountArgSlots(frame.maybeCallee()) + frame.script()->nfixed;
     uint32 skipSlots = base + localSlot - 1;
 
     for (unsigned i = 0; i < skipSlots; i++)
         si.skip();
 
     Value v = si.read();
-    JSObject *obj = &v.toObject();
+    RootedObject obj(cx, &v.toObject());
 
     if (cx->isExceptionPending())
         UnwindIteratorForException(cx, obj);
     else
         UnwindIteratorForUncatchableException(cx, obj);
 }
 
 static void
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/bug793385.js
@@ -0,0 +1,9 @@
+// |jit-test| error: out of memory
+gcparam("maxBytes", gcparam("gcBytes") + 4*1024);
+function f() {
+    var inner4 = f("get"),
+	x1,x2,x3,x4,x5,x11,x12,x13,x14,x15,x16,x17,x18,
+        otherGlobalSameCompartment = newGlobal("same-compartment");
+    eval('');
+}
+assertEq("aaa".replace(/a/g, f()), "poniesponiesponies");
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/ion/bug792944.js
@@ -0,0 +1,13 @@
+function whoo() {
+    (new Object()).foo()
+}
+Object.prototype.foo = function() { return undefined };
+whoo();
+Object.prototype.foo = undefined;
+gc();
+try {
+    whoo();
+    assertEq(0, 1);
+} catch(e) {
+    assertEq(e instanceof TypeError, true);
+}
--- a/js/src/jsinfer.cpp
+++ b/js/src/jsinfer.cpp
@@ -3885,23 +3885,26 @@ ScriptAnalysis::analyzeTypesBytecode(JSC
         break;
 
       case JSOP_REST: {
         StackTypeSet *types = script->analysis()->bytecodeTypes(pc);
         if (script->compileAndGo) {
             TypeObject *rest = TypeScript::InitObject(cx, script, pc, JSProto_Array);
             if (!rest)
                 return false;
-            types->addType(cx, Type::ObjectType(rest));
 
             // Simulate setting a element.
-            HeapTypeSet *propTypes = rest->getProperty(cx, JSID_VOID, true);
-            if (!propTypes)
-                return false;
-            propTypes->addType(cx, Type::UnknownType());
+            if (!rest->unknownProperties()) {
+                HeapTypeSet *propTypes = rest->getProperty(cx, JSID_VOID, true);
+                if (!propTypes)
+                    return false;
+                propTypes->addType(cx, Type::UnknownType());
+            }
+
+            types->addType(cx, Type::ObjectType(rest));
         } else {
             types->addType(cx, Type::UnknownType());
         }
         types->addSubset(cx, &pushed[0]);
         break;
       }
 
 
--- a/js/src/jsinterp.cpp
+++ b/js/src/jsinterp.cpp
@@ -1024,17 +1024,17 @@ IteratorMore(JSContext *cx, JSObject *it
     Rooted<JSObject*> iobj(cx, iterobj);
     if (!js_IteratorMore(cx, iobj, rval))
         return false;
     *cond = rval.isTrue();
     return true;
 }
 
 static inline bool
-IteratorNext(JSContext *cx, JSObject *iterobj, MutableHandleValue rval)
+IteratorNext(JSContext *cx, HandleObject iterobj, MutableHandleValue rval)
 {
     if (iterobj->isPropertyIterator()) {
         NativeIterator *ni = iterobj->asPropertyIterator().getNativeIterator();
         if (ni->isKeyIter()) {
             JS_ASSERT(ni->props_cursor < ni->props_end);
             rval.setString(*ni->current());
             ni->incCursor();
             return true;
@@ -1773,25 +1773,29 @@ BEGIN_CASE(JSOP_MOREITER)
 }
 END_CASE(JSOP_MOREITER)
 
 BEGIN_CASE(JSOP_ITERNEXT)
 {
     JS_ASSERT(regs.sp[-1].isObject());
     PUSH_NULL();
     MutableHandleValue res = MutableHandleValue::fromMarkedLocation(&regs.sp[-1]);
-    if (!IteratorNext(cx, &regs.sp[-2].toObject(), res))
+    RootedObject &obj = rootObject0;
+    obj = &regs.sp[-2].toObject();
+    if (!IteratorNext(cx, obj, res))
         goto error;
 }
 END_CASE(JSOP_ITERNEXT)
 
 BEGIN_CASE(JSOP_ENDITER)
 {
     JS_ASSERT(regs.stackDepth() >= 1);
-    bool ok = CloseIterator(cx, &regs.sp[-1].toObject());
+    RootedObject &obj = rootObject0;
+    obj = &regs.sp[-1].toObject();
+    bool ok = CloseIterator(cx, obj);
     regs.sp--;
     if (!ok)
         goto error;
 }
 END_CASE(JSOP_ENDITER)
 
 BEGIN_CASE(JSOP_DUP)
 {
@@ -3911,17 +3915,19 @@ END_CASE(JSOP_ARRAYPUSH)
                 PUSH_COPY(cx->getPendingException());
                 cx->clearPendingException();
                 len = 0;
                 DO_NEXT_OP(len);
 
               case JSTRY_ITER: {
                 /* This is similar to JSOP_ENDITER in the interpreter loop. */
                 JS_ASSERT(JSOp(*regs.pc) == JSOP_ENDITER);
-                bool ok = UnwindIteratorForException(cx, &regs.sp[-1].toObject());
+                RootedObject &obj = rootObject0;
+                obj = &regs.sp[-1].toObject();
+                bool ok = UnwindIteratorForException(cx, obj);
                 regs.sp -= 1;
                 if (!ok)
                     goto error;
               }
            }
         }
 
         /*
--- a/js/src/jsiter.cpp
+++ b/js/src/jsiter.cpp
@@ -78,29 +78,27 @@ struct IdHashPolicy {
 typedef HashSet<jsid, IdHashPolicy> IdSet;
 
 static inline bool
 NewKeyValuePair(JSContext *cx, jsid id, const Value &val, MutableHandleValue rval)
 {
     Value vec[2] = { IdToValue(id), val };
     AutoArrayRooter tvr(cx, ArrayLength(vec), vec);
 
-    JSObject *aobj = NewDenseCopiedArray(cx, 2, vec);
+    RawObject aobj = NewDenseCopiedArray(cx, 2, vec);
     if (!aobj)
         return false;
     rval.setObject(*aobj);
     return true;
 }
 
 static inline bool
-Enumerate(JSContext *cx, JSObject *obj, JSObject *pobj, jsid id,
+Enumerate(JSContext *cx, HandleObject pobj, jsid id,
           bool enumerable, unsigned flags, IdSet& ht, AutoIdVector *props)
 {
-    JS_ASSERT_IF(flags & JSITER_OWNONLY, obj == pobj);
-
     /*
      * We implement __proto__ using a property on |Object.prototype|, but
      * because __proto__ is highly deserving of removal, we don't want it to
      * show up in property enumeration, even if only for |Object.prototype|
      * (think introspection by Prototype-like frameworks that add methods to
      * the built-in prototypes).  So exclude __proto__ if the object where the
      * property was found has no [[Prototype]] and might be |Object.prototype|.
      */
@@ -124,54 +122,52 @@ Enumerate(JSContext *cx, JSObject *obj, 
 
     if (enumerable || (flags & JSITER_HIDDEN))
         return props->append(id);
 
     return true;
 }
 
 static bool
-EnumerateNativeProperties(JSContext *cx, JSObject *obj_, JSObject *pobj_, unsigned flags, IdSet &ht,
+EnumerateNativeProperties(JSContext *cx, HandleObject pobj, unsigned flags, IdSet &ht,
                           AutoIdVector *props)
 {
-    RootedObject obj(cx, obj_), pobj(cx, pobj_);
-
     size_t initialLength = props->length();
 
     /* Collect all unique properties from this object's scope. */
     Shape::Range r = pobj->lastProperty()->all();
     Shape::Range::AutoRooter root(cx, &r);
     for (; !r.empty(); r.popFront()) {
         Shape &shape = r.front();
 
         if (!JSID_IS_DEFAULT_XML_NAMESPACE(shape.propid()) &&
-            !Enumerate(cx, obj, pobj, shape.propid(), shape.enumerable(), flags, ht, props))
+            !Enumerate(cx, pobj, shape.propid(), shape.enumerable(), flags, ht, props))
         {
             return false;
         }
     }
 
     ::Reverse(props->begin() + initialLength, props->end());
     return true;
 }
 
 static bool
-EnumerateDenseArrayProperties(JSContext *cx, JSObject *obj, JSObject *pobj, unsigned flags,
+EnumerateDenseArrayProperties(JSContext *cx, HandleObject pobj, unsigned flags,
                               IdSet &ht, AutoIdVector *props)
 {
-    if (!Enumerate(cx, obj, pobj, NameToId(cx->names().length), false, flags, ht, props))
+    if (!Enumerate(cx, pobj, NameToId(cx->names().length), false, flags, ht, props))
         return false;
 
     if (pobj->getArrayLength() > 0) {
         size_t initlen = pobj->getDenseArrayInitializedLength();
         const Value *vp = pobj->getDenseArrayElements();
         for (size_t i = 0; i < initlen; ++i, ++vp) {
             if (!vp->isMagic(JS_ARRAY_HOLE)) {
                 /* Dense arrays never get so large that i would not fit into an integer id. */
-                if (!Enumerate(cx, obj, pobj, INT_TO_JSID(i), true, flags, ht, props))
+                if (!Enumerate(cx, pobj, INT_TO_JSID(i), true, flags, ht, props))
                     return false;
             }
         }
     }
 
     return true;
 }
 
@@ -201,36 +197,35 @@ struct SortComparatorIds
         *lessOrEqualp = (result <= 0);
         return true;
     }
 };
 
 #endif /* JS_MORE_DETERMINISTIC */
 
 static bool
-Snapshot(JSContext *cx, RawObject obj_, unsigned flags, AutoIdVector *props)
+Snapshot(JSContext *cx, RawObject pobj_, unsigned flags, AutoIdVector *props)
 {
     IdSet ht(cx);
     if (!ht.init(32))
         return false;
 
-    RootedObject obj(cx, obj_), pobj(cx);
-    pobj = obj;
+    RootedObject pobj(cx, pobj_);
 
     do {
         Class *clasp = pobj->getClass();
         if (pobj->isNative() &&
             !pobj->getOps()->enumerate &&
             !(clasp->flags & JSCLASS_NEW_ENUMERATE)) {
             if (!clasp->enumerate(cx, pobj))
                 return false;
-            if (!EnumerateNativeProperties(cx, obj, pobj, flags, ht, props))
+            if (!EnumerateNativeProperties(cx, pobj, flags, ht, props))
                 return false;
         } else if (pobj->isDenseArray()) {
-            if (!EnumerateDenseArrayProperties(cx, obj, pobj, flags, ht, props))
+            if (!EnumerateDenseArrayProperties(cx, pobj, flags, ht, props))
                 return false;
         } else if (ParallelArrayObject::is(pobj)) {
             if (!ParallelArrayObject::enumerate(cx, pobj, flags, props))
                 return false;
             /*
              * ParallelArray objects enumerate the prototype on their own, so
              * we are done here.
              */
@@ -246,38 +241,38 @@ Snapshot(JSContext *cx, RawObject obj_, 
                         if (!Proxy::keys(cx, pobj, proxyProps))
                             return false;
                     }
                 } else {
                     if (!Proxy::enumerate(cx, pobj, proxyProps))
                         return false;
                 }
                 for (size_t n = 0, len = proxyProps.length(); n < len; n++) {
-                    if (!Enumerate(cx, obj, pobj, proxyProps[n], true, flags, ht, props))
+                    if (!Enumerate(cx, pobj, proxyProps[n], true, flags, ht, props))
                         return false;
                 }
                 /* Proxy objects enumerate the prototype on their own, so we are done here. */
                 break;
             }
             RootedValue state(cx);
             RootedId id(cx);
             JSIterateOp op = (flags & JSITER_HIDDEN) ? JSENUMERATE_INIT_ALL : JSENUMERATE_INIT;
             if (!JSObject::enumerate(cx, pobj, op, &state, &id))
                 return false;
             if (state.isMagic(JS_NATIVE_ENUMERATE)) {
-                if (!EnumerateNativeProperties(cx, obj, pobj, flags, ht, props))
+                if (!EnumerateNativeProperties(cx, pobj, flags, ht, props))
                     return false;
             } else {
                 while (true) {
                     RootedId id(cx);
                     if (!JSObject::enumerate(cx, pobj, JSENUMERATE_NEXT, &state, &id))
                         return false;
                     if (state.isNull())
                         break;
-                    if (!Enumerate(cx, obj, pobj, id, true, flags, ht, props))
+                    if (!Enumerate(cx, pobj, id, true, flags, ht, props))
                         return false;
                 }
             }
         }
 
         if (flags & JSITER_OWNONLY)
             break;
 
@@ -413,17 +408,17 @@ NewPropertyIteratorObject(JSContext *cx,
         if (!type)
             return NULL;
 
         RootedShape shape(cx, EmptyShape::getInitialShape(cx, &PropertyIteratorObject::class_,
                                                           NULL, NULL, ITERATOR_FINALIZE_KIND));
         if (!shape)
             return NULL;
 
-        JSObject *obj = JSObject::create(cx, ITERATOR_FINALIZE_KIND, shape, type, NULL);
+        RawObject obj = JSObject::create(cx, ITERATOR_FINALIZE_KIND, shape, type, NULL);
         if (!obj)
             return NULL;
 
         JS_ASSERT(obj->numFixedSlots() == JSObject::ITER_CLASS_NFIXED_SLOTS);
         return &obj->asPropertyIterator();
     }
 
     return &NewBuiltinClassInstance(cx, &PropertyIteratorObject::class_)->asPropertyIterator();
@@ -449,17 +444,17 @@ NativeIterator::allocateIterator(JSConte
                 return NULL;
             ni->props_array[i].init(str);
         }
     }
     return ni;
 }
 
 inline void
-NativeIterator::init(JSObject *obj, unsigned flags, uint32_t slength, uint32_t key)
+NativeIterator::init(RawObject obj, unsigned flags, uint32_t slength, uint32_t key)
 {
     this->obj.init(obj);
     this->flags = flags;
     this->shapes_array = (Shape **) this->props_end;
     this->shapes_length = slength;
     this->shapes_key = key;
 }
 
@@ -500,17 +495,17 @@ VectorToKeyIterator(JSContext *cx, Handl
     if (slength) {
         /*
          * Fill in the shape array from scratch.  We can't use the array that was
          * computed for the cache lookup earlier, as constructing iterobj could
          * have triggered a shape-regenerating GC.  Don't bother with regenerating
          * the shape key; if such a GC *does* occur, we can only get hits through
          * the one-slot lastNativeIterator cache.
          */
-        JSObject *pobj = obj;
+        RawObject pobj = obj;
         size_t ind = 0;
         do {
             ni->shapes_array[ind++] = pobj->lastProperty();
             pobj = pobj->getProto();
         } while (pobj);
         JS_ASSERT(ind == slength);
     }
 
@@ -564,17 +559,17 @@ EnumeratedIdVectorToIterator(JSContext *
 {
     if (!(flags & JSITER_FOREACH))
         return VectorToKeyIterator(cx, obj, flags, props, vp);
 
     return VectorToValueIterator(cx, obj, flags, props, vp);
 }
 
 static inline void
-UpdateNativeIterator(NativeIterator *ni, JSObject *obj)
+UpdateNativeIterator(NativeIterator *ni, RawObject obj)
 {
     // Update the object for which the native iterator is associated, so
     // SuppressDeletedPropertyHelper will recognize the iterator as a match.
     ni->obj = obj;
 }
 
 bool
 GetIterator(JSContext *cx, HandleObject obj, unsigned flags, MutableHandleValue vp)
@@ -596,48 +591,48 @@ GetIterator(JSContext *cx, HandleObject 
             JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_NOT_ITERABLE, bytes);
             js_free(bytes);
             return false;
         }
 
         if (!Invoke(cx, ObjectOrNullValue(obj), method, 0, NULL, vp.address()))
             return false;
 
-        JSObject *obj = ToObject(cx, vp);
+        RawObject obj = ToObject(cx, vp);
         if (!obj)
             return false;
         vp.setObject(*obj);
         return true;
     }
 
     Vector<Shape *, 8> shapes(cx);
     uint32_t key = 0;
 
     bool keysOnly = (flags == JSITER_ENUMERATE);
 
     if (obj) {
         if (JSIteratorOp op = obj->getClass()->ext.iteratorObject) {
-            JSObject *iterobj = op(cx, obj, !(flags & JSITER_FOREACH));
+            RawObject iterobj = op(cx, obj, !(flags & JSITER_FOREACH));
             if (!iterobj)
                 return false;
             vp.setObject(*iterobj);
             types::MarkIteratorUnknown(cx);
             return true;
         }
 
         if (keysOnly) {
             /*
              * Check to see if this is the same as the most recent object which
              * was iterated over.  We don't explicitly check for shapeless
              * objects here, as they are not inserted into the cache and
              * will result in a miss.
              */
             PropertyIteratorObject *last = cx->runtime->nativeIterCache.last;
-            JSObject *proto = obj->getProto();
             if (last) {
+                RawObject proto = obj->getProto();
                 NativeIterator *lastni = last->getNativeIterator();
                 if (!(lastni->flags & (JSITER_ACTIVE|JSITER_UNREUSABLE)) &&
                     obj->isNative() &&
                     obj->lastProperty() == lastni->shapes_array[0] &&
                     proto && proto->isNative() &&
                     proto->lastProperty() == lastni->shapes_array[1] &&
                     !proto->getProto()) {
                     vp.setObject(*last);
@@ -648,31 +643,33 @@ GetIterator(JSContext *cx, HandleObject 
             }
 
             /*
              * The iterator object for JSITER_ENUMERATE never escapes, so we
              * don't care for the proper parent/proto to be set. This also
              * allows us to re-use a previous iterator object that is not
              * currently active.
              */
-            JSObject *pobj = obj;
-            do {
-                if (!pobj->isNative() ||
-                    pobj->hasUncacheableProto() ||
-                    obj->getOps()->enumerate ||
-                    pobj->getClass()->enumerate != JS_EnumerateStub) {
-                    shapes.clear();
-                    goto miss;
-                }
-                Shape *shape = pobj->lastProperty();
-                key = (key + (key << 16)) ^ (uintptr_t(shape) >> 3);
-                if (!shapes.append((Shape *) shape))
-                    return false;
-                pobj = pobj->getProto();
-            } while (pobj);
+            {
+                RawObject pobj = obj;
+                do {
+                    if (!pobj->isNative() ||
+                        pobj->hasUncacheableProto() ||
+                        obj->getOps()->enumerate ||
+                        pobj->getClass()->enumerate != JS_EnumerateStub) {
+                        shapes.clear();
+                        goto miss;
+                    }
+                    Shape *shape = pobj->lastProperty();
+                    key = (key + (key << 16)) ^ (uintptr_t(shape) >> 3);
+                    if (!shapes.append((Shape *) shape))
+                        return false;
+                    pobj = pobj->getProto();
+                } while (pobj);
+            }
 
             PropertyIteratorObject *iterobj = cx->runtime->nativeIterCache.get(key);
             if (iterobj) {
                 NativeIterator *ni = iterobj->getNativeIterator();
                 if (!(ni->flags & (JSITER_ACTIVE|JSITER_UNREUSABLE)) &&
                     ni->shapes_key == key &&
                     ni->shapes_length == shapes.length() &&
                     Compare(ni->shapes_array, shapes.begin(), ni->shapes_length)) {
@@ -776,17 +773,17 @@ IsIterator(const Value &v)
     return v.isObject() && v.toObject().hasClass(&PropertyIteratorObject::class_);
 }
 
 JS_ALWAYS_INLINE bool
 iterator_next_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(IsIterator(args.thisv()));
 
-    Rooted<JSObject*> thisObj(cx, &args.thisv().toObject());
+    RootedObject thisObj(cx, &args.thisv().toObject());
 
     if (!js_IteratorMore(cx, thisObj, args.rval()))
         return false;
 
     if (!args.rval().toBoolean()) {
         js_ThrowStopIteration(cx);
         return false;
     }
@@ -817,24 +814,24 @@ static JSFunctionSpec iterator_methods[]
 
 static JSObject *
 iterator_iteratorObject(JSContext *cx, HandleObject obj, JSBool keysonly)
 {
     return obj;
 }
 
 void
-PropertyIteratorObject::trace(JSTracer *trc, JSObject *obj)
+PropertyIteratorObject::trace(JSTracer *trc, RawObject obj)
 {
     if (NativeIterator *ni = obj->asPropertyIterator().getNativeIterator())
         ni->mark(trc);
 }
 
 void
-PropertyIteratorObject::finalize(FreeOp *fop, JSObject *obj)
+PropertyIteratorObject::finalize(FreeOp *fop, RawObject obj)
 {
     if (NativeIterator *ni = obj->asPropertyIterator().getNativeIterator()) {
         obj->asPropertyIterator().setNativeIterator(NULL);
         fop->free_(ni);
     }
 }
 
 Class PropertyIteratorObject::class_ = {
@@ -864,20 +861,20 @@ Class PropertyIteratorObject::class_ = {
     }
 };
 
 const uint32_t CLOSED_INDEX = UINT32_MAX;
 
 JSObject *
 ElementIteratorObject::create(JSContext *cx, Handle<Value> target)
 {
-    Rooted<JSObject*> proto(cx, cx->global()->getOrCreateElementIteratorPrototype(cx));
+    RootedObject proto(cx, cx->global()->getOrCreateElementIteratorPrototype(cx));
     if (!proto)
         return NULL;
-    JSObject *iterobj = NewObjectWithGivenProto(cx, &ElementIteratorClass, proto, cx->global());
+    RootedObject iterobj(cx, NewObjectWithGivenProto(cx, &ElementIteratorClass, proto, cx->global()));
     if (iterobj) {
         iterobj->setReservedSlot(TargetSlot, target);
         iterobj->setReservedSlot(IndexSlot, Int32Value(0));
     }
     return iterobj;
 }
 
 static bool
@@ -894,17 +891,17 @@ ElementIteratorObject::next(JSContext *c
 }
 
 bool
 ElementIteratorObject::next_impl(JSContext *cx, CallArgs args)
 {
     RootedObject iterobj(cx, &args.thisv().toObject());
     uint32_t i, length;
     RootedValue target(cx, iterobj->getReservedSlot(TargetSlot));
-    Rooted<JSObject*> obj(cx);
+    RootedObject obj(cx);
 
     // Get target.length.
     if (target.isString()) {
         length = uint32_t(target.toString()->length());
     } else {
         obj = ToObjectFromStack(cx, target);
         if (!obj)
             goto close;
@@ -959,17 +956,17 @@ Class js::ElementIteratorClass = {
 
 JSFunctionSpec ElementIteratorObject::methods[] = {
     JS_FN("next", next, 0, 0),
     JS_FS_END
 };
 
 #if JS_HAS_GENERATORS
 static JSBool
-CloseGenerator(JSContext *cx, JSObject *genobj);
+CloseGenerator(JSContext *cx, HandleObject genobj);
 #endif
 
 bool
 js::ValueToIterator(JSContext *cx, unsigned flags, MutableHandleValue vp)
 {
     /* JSITER_KEYVALUE must always come with JSITER_FOREACH */
     JS_ASSERT_IF(flags & JSITER_KEYVALUE, flags & JSITER_FOREACH);
 
@@ -1002,17 +999,17 @@ js::ValueToIterator(JSContext *cx, unsig
                 return false;
         }
     }
 
     return GetIterator(cx, obj, flags, vp);
 }
 
 bool
-js::CloseIterator(JSContext *cx, JSObject *obj)
+js::CloseIterator(JSContext *cx, HandleObject obj)
 {
     cx->iterValue.setMagic(JS_NO_ITER_VALUE);
 
     if (obj->isPropertyIterator()) {
         /* Remove enumerators from the active list, which is a stack. */
         NativeIterator *ni = obj->asPropertyIterator().getNativeIterator();
 
         if (ni->flags & JSITER_ENUMERATE) {
@@ -1033,28 +1030,28 @@ js::CloseIterator(JSContext *cx, JSObjec
     else if (obj->isGenerator()) {
         return CloseGenerator(cx, obj);
     }
 #endif
     return JS_TRUE;
 }
 
 bool
-js::UnwindIteratorForException(JSContext *cx, JSObject *obj)
+js::UnwindIteratorForException(JSContext *cx, HandleObject obj)
 {
     RootedValue v(cx, cx->getPendingException());
     cx->clearPendingException();
     if (!CloseIterator(cx, obj))
         return false;
     cx->setPendingException(v);
     return true;
 }
 
 void
-js::UnwindIteratorForUncatchableException(JSContext *cx, JSObject *obj)
+js::UnwindIteratorForUncatchableException(JSContext *cx, RawObject obj)
 {
     if (obj->isPropertyIterator()) {
         NativeIterator *ni = obj->asPropertyIterator().getNativeIterator();
         if (ni->flags & JSITER_ENUMERATE) {
             JS_ASSERT(cx->enumerators == obj);
             cx->enumerators = ni->next;
         }
     }
@@ -1258,17 +1255,17 @@ js_IteratorMore(JSContext *cx, HandleObj
     /* Cache the value returned by iterobj.next() so js_IteratorNext() can find it. */
     JS_ASSERT(!rval.isMagic(JS_NO_ITER_VALUE));
     cx->iterValue = rval;
     rval.setBoolean(true);
     return true;
 }
 
 bool
-js_IteratorNext(JSContext *cx, JSObject *iterobj, MutableHandleValue rval)
+js_IteratorNext(JSContext *cx, HandleObject iterobj, MutableHandleValue rval)
 {
     /* Fast path for native iterators */
     if (iterobj->isPropertyIterator()) {
         /*
          * Implement next directly as all the methods of the native iterator are
          * read-only and permanent.
          */
         NativeIterator *ni = iterobj->asPropertyIterator().getNativeIterator();
@@ -1312,17 +1309,17 @@ Class js::StopIterationClass = {
     NULL                     /* construct   */
 };
 
 /*** Generators **********************************************************************************/
 
 #if JS_HAS_GENERATORS
 
 static void
-generator_finalize(FreeOp *fop, JSObject *obj)
+generator_finalize(FreeOp *fop, RawObject obj)
 {
     JSGenerator *gen = (JSGenerator *) obj->getPrivate();
     if (!gen)
         return;
 
     /*
      * gen is open when a script has not called its close method while
      * explicitly manipulating it.
@@ -1377,17 +1374,17 @@ SetGeneratorClosed(JSContext *cx, JSGene
 {
     JS_ASSERT(gen->state != JSGEN_CLOSED);
     if (GeneratorHasMarkableFrame(gen))
         GeneratorWriteBarrierPre(cx, gen);
     gen->state = JSGEN_CLOSED;
 }
 
 static void
-generator_trace(JSTracer *trc, JSObject *obj)
+generator_trace(JSTracer *trc, RawObject obj)
 {
     JSGenerator *gen = (JSGenerator *) obj->getPrivate();
     if (!gen)
         return;
 
     if (GeneratorHasMarkableFrame(gen))
         MarkGeneratorFrame(trc, gen);
 }
@@ -1428,20 +1425,23 @@ Class js::GeneratorClass = {
 JSObject *
 js_NewGenerator(JSContext *cx)
 {
     FrameRegs &stackRegs = cx->regs();
     JS_ASSERT(stackRegs.stackDepth() == 0);
     StackFrame *stackfp = stackRegs.fp();
 
     Rooted<GlobalObject*> global(cx, &stackfp->global());
-    JSObject *proto = global->getOrCreateGeneratorPrototype(cx);
-    if (!proto)
-        return NULL;
-    JSObject *obj = NewObjectWithGivenProto(cx, &GeneratorClass, proto, global);
+    RootedObject obj(cx);
+    {
+        RawObject proto = global->getOrCreateGeneratorPrototype(cx);
+        if (!proto)
+            return NULL;
+        obj = NewObjectWithGivenProto(cx, &GeneratorClass, proto, global);
+    }
     if (!obj)
         return NULL;
 
     /* Load and compute stack slot counts. */
     Value *stackvp = stackfp->generatorArgsSnapshotBegin();
     unsigned vplen = stackfp->generatorArgsSnapshotEnd() - stackvp;
 
     /* Compute JSGenerator size. */
@@ -1489,17 +1489,17 @@ typedef enum JSGeneratorOp {
     JSGENOP_CLOSE
 } JSGeneratorOp;
 
 /*
  * Start newborn or restart yielding generator and perform the requested
  * operation inside its frame.
  */
 static JSBool
-SendToGenerator(JSContext *cx, JSGeneratorOp op, JSObject *obj,
+SendToGenerator(JSContext *cx, JSGeneratorOp op, HandleObject obj,
                 JSGenerator *gen, const Value &arg)
 {
     if (gen->state == JSGEN_RUNNING || gen->state == JSGEN_CLOSING) {
         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_NESTING_GENERATOR);
         return JS_FALSE;
     }
 
     /*
@@ -1586,17 +1586,17 @@ SendToGenerator(JSContext *cx, JSGenerat
     /*
      * An error, silent termination by operation callback or an exception.
      * Propagate the condition to the caller.
      */
     return JS_FALSE;
 }
 
 static JSBool
-CloseGenerator(JSContext *cx, JSObject *obj)
+CloseGenerator(JSContext *cx, HandleObject obj)
 {
     JS_ASSERT(obj->isGenerator());
 
     JSGenerator *gen = (JSGenerator *) obj->getPrivate();
     if (!gen) {
         /* Generator prototype object. */
         return JS_TRUE;
     }
@@ -1613,17 +1613,17 @@ IsGenerator(const Value &v)
     return v.isObject() && v.toObject().hasClass(&GeneratorClass);
 }
 
 JS_ALWAYS_INLINE bool
 generator_send_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(IsGenerator(args.thisv()));
 
-    Rooted<JSObject*> thisObj(cx, &args.thisv().toObject());
+    RootedObject thisObj(cx, &args.thisv().toObject());
 
     JSGenerator *gen = (JSGenerator *) thisObj->getPrivate();
     if (!gen || gen->state == JSGEN_CLOSED) {
         /* This happens when obj is the generator prototype. See bug 352885. */
         return js_ThrowStopIteration(cx);
     }
 
     if (gen->state == JSGEN_NEWBORN && args.hasDefined(0)) {
@@ -1650,17 +1650,17 @@ generator_send(JSContext *cx, unsigned a
     return CallNonGenericMethod<IsGenerator, generator_send_impl>(cx, args);
 }
 
 JS_ALWAYS_INLINE bool
 generator_next_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(IsGenerator(args.thisv()));
 
-    Rooted<JSObject*> thisObj(cx, &args.thisv().toObject());
+    RootedObject thisObj(cx, &args.thisv().toObject());
 
     JSGenerator *gen = (JSGenerator *) thisObj->getPrivate();
     if (!gen || gen->state == JSGEN_CLOSED) {
         /* This happens when obj is the generator prototype. See bug 352885. */
         return js_ThrowStopIteration(cx);
     }
 
     if (!SendToGenerator(cx, JSGENOP_NEXT, thisObj, gen, UndefinedValue()))
@@ -1677,17 +1677,17 @@ generator_next(JSContext *cx, unsigned a
     return CallNonGenericMethod<IsGenerator, generator_next_impl>(cx, args);
 }
 
 JS_ALWAYS_INLINE bool
 generator_throw_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(IsGenerator(args.thisv()));
 
-    Rooted<JSObject*> thisObj(cx, &args.thisv().toObject());
+    RootedObject thisObj(cx, &args.thisv().toObject());
 
     JSGenerator *gen = (JSGenerator *) thisObj->getPrivate();
     if (!gen || gen->state == JSGEN_CLOSED) {
         /* This happens when obj is the generator prototype. See bug 352885. */
         cx->setPendingException(args.length() >= 1 ? args[0] : UndefinedValue());
         return false;
     }
 
@@ -1708,17 +1708,17 @@ generator_throw(JSContext *cx, unsigned 
     return CallNonGenericMethod<IsGenerator, generator_throw_impl>(cx, args);
 }
 
 JS_ALWAYS_INLINE bool
 generator_close_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(IsGenerator(args.thisv()));
 
-    Rooted<JSObject*> thisObj(cx, &args.thisv().toObject());
+    RootedObject thisObj(cx, &args.thisv().toObject());
 
     JSGenerator *gen = (JSGenerator *) thisObj->getPrivate();
     if (!gen || gen->state == JSGEN_CLOSED) {
         /* This happens when obj is the generator prototype. See bug 352885. */
         args.rval().setUndefined();
         return true;
     }
 
@@ -1753,17 +1753,17 @@ static JSFunctionSpec generator_methods[
     JS_FS_END
 };
 
 #endif /* JS_HAS_GENERATORS */
 
 /* static */ bool
 GlobalObject::initIteratorClasses(JSContext *cx, Handle<GlobalObject *> global)
 {
-    Rooted<JSObject*> iteratorProto(cx);
+    RootedObject iteratorProto(cx);
     Value iteratorProtoVal = global->getPrototype(JSProto_Iterator);
     if (iteratorProtoVal.isObject()) {
         iteratorProto = &iteratorProtoVal.toObject();
     } else {
         iteratorProto = global->createBlankPrototype(cx, &PropertyIteratorObject::class_);
         if (!iteratorProto)
             return false;
 
@@ -1782,17 +1782,17 @@ GlobalObject::initIteratorClasses(JSCont
         if (!LinkConstructorAndPrototype(cx, ctor, iteratorProto))
             return false;
         if (!DefinePropertiesAndBrand(cx, iteratorProto, NULL, iterator_methods))
             return false;
         if (!DefineConstructorAndPrototype(cx, global, JSProto_Iterator, ctor, iteratorProto))
             return false;
     }
 
-    Rooted<JSObject*> proto(cx);
+    RootedObject proto(cx);
     if (global->getSlot(ELEMENT_ITERATOR_PROTO).isUndefined()) {
         Class *cls = &ElementIteratorClass;
         proto = global->createBlankPrototypeInheriting(cx, cls, *iteratorProto);
         if (!proto || !DefinePropertiesAndBrand(cx, proto, NULL, ElementIteratorObject::methods))
             return false;
         global->setReservedSlot(ELEMENT_ITERATOR_PROTO, ObjectValue(*proto));
     }
 
--- a/js/src/jsiter.h
+++ b/js/src/jsiter.h
@@ -60,32 +60,32 @@ struct NativeIterator
     }
 
     void incCursor() {
         props_cursor = props_cursor + 1;
     }
 
     static NativeIterator *allocateIterator(JSContext *cx, uint32_t slength,
                                             const js::AutoIdVector &props);
-    void init(JSObject *obj, unsigned flags, uint32_t slength, uint32_t key);
+    void init(RawObject obj, unsigned flags, uint32_t slength, uint32_t key);
 
     void mark(JSTracer *trc);
 };
 
 class PropertyIteratorObject : public JSObject
 {
   public:
     static Class class_;
 
     inline NativeIterator *getNativeIterator() const;
     inline void setNativeIterator(js::NativeIterator *ni);
 
   private:
-    static void trace(JSTracer *trc, JSObject *obj);
-    static void finalize(FreeOp *fop, JSObject *obj);
+    static void trace(JSTracer *trc, RawObject obj);
+    static void finalize(FreeOp *fop, RawObject obj);
 };
 
 /*
  * Array iterators are roughly like this:
  *
  *   Array.prototype.iterator = function iterator() {
  *       for (var i = 0; i < (this.length >>> 0); i++)
  *           yield this[i];
@@ -140,23 +140,23 @@ EnumeratedIdVectorToIterator(JSContext *
  * contain JSITER_ENUMERATE if js::ValueToIterator is called when enumerating
  * for-in semantics are required, and when the caller can guarantee that the
  * iterator will never be exposed to scripts.
  */
 bool
 ValueToIterator(JSContext *cx, unsigned flags, MutableHandleValue vp);
 
 bool
-CloseIterator(JSContext *cx, JSObject *iterObj);
+CloseIterator(JSContext *cx, HandleObject iterObj);
 
 bool
-UnwindIteratorForException(JSContext *cx, JSObject *obj);
+UnwindIteratorForException(JSContext *cx, js::HandleObject obj);
 
 void
-UnwindIteratorForUncatchableException(JSContext *cx, JSObject *obj);
+UnwindIteratorForUncatchableException(JSContext *cx, RawObject obj);
 
 JSBool
 IteratorConstructor(JSContext *cx, unsigned argc, Value *vp);
 
 }
 
 extern bool
 js_SuppressDeletedProperty(JSContext *cx, js::HandleObject obj, jsid id);
@@ -171,17 +171,17 @@ js_SuppressDeletedElements(JSContext *cx
  * IteratorMore() indicates whether another value is available. It might
  * internally call iterobj.next() and then cache the value until its
  * picked up by IteratorNext(). The value is cached in the current context.
  */
 extern bool
 js_IteratorMore(JSContext *cx, js::HandleObject iterobj, js::MutableHandleValue rval);
 
 extern bool
-js_IteratorNext(JSContext *cx, JSObject *iterobj, js::MutableHandleValue rval);
+js_IteratorNext(JSContext *cx, js::HandleObject iterobj, js::MutableHandleValue rval);
 
 extern JSBool
 js_ThrowStopIteration(JSContext *cx);
 
 namespace js {
 
 /*
  * Get the next value from an iterator object.
--- a/js/src/jswrapper.cpp
+++ b/js/src/jswrapper.cpp
@@ -626,31 +626,31 @@ CanReify(Value *vp)
     JSObject *obj;
     return vp->isObject() &&
            (obj = &vp->toObject())->isPropertyIterator() &&
            (obj->asPropertyIterator().getNativeIterator()->flags & JSITER_ENUMERATE);
 }
 
 struct AutoCloseIterator
 {
-    AutoCloseIterator(JSContext *cx, JSObject *obj) : cx(cx), obj(obj) {}
+    AutoCloseIterator(JSContext *cx, JSObject *obj) : cx(cx), obj(cx, obj) {}
 
     ~AutoCloseIterator() { if (obj) CloseIterator(cx, obj); }
 
     void clear() { obj = NULL; }
 
   private:
     JSContext *cx;
-    JSObject *obj;
+    RootedObject obj;
 };
 
 static bool
 Reify(JSContext *cx, JSCompartment *origin, Value *vp)
 {
-    PropertyIteratorObject *iterObj = &vp->toObject().asPropertyIterator();
+    Rooted<PropertyIteratorObject*> iterObj(cx, &vp->toObject().asPropertyIterator());
     NativeIterator *ni = iterObj->getNativeIterator();
 
     AutoCloseIterator close(cx, iterObj);
 
     /* Wrap the iteratee. */
     RootedObject obj(cx, ni->obj);
     if (!origin->wrap(cx, obj.address()))
         return false;
--- a/js/src/methodjit/InvokeHelpers.cpp
+++ b/js/src/methodjit/InvokeHelpers.cpp
@@ -102,17 +102,18 @@ FindExceptionHandler(JSContext *cx)
                   /*
                    * This is similar to JSOP_ENDITER in the interpreter loop,
                    * except the code now uses the stack slot normally used by
                    * JSOP_NEXTITER, namely regs.sp[-1] before the regs.sp -= 2
                    * adjustment and regs.sp[1] after, to save and restore the
                    * pending exception.
                    */
                   JS_ASSERT(JSOp(*pc) == JSOP_ENDITER);
-                  bool ok = UnwindIteratorForException(cx, &cx->regs().sp[-1].toObject());
+                  RootedObject obj(cx, &cx->regs().sp[-1].toObject());
+                  bool ok = UnwindIteratorForException(cx, obj);
                   cx->regs().sp -= 1;
                   if (!ok)
                       goto error;
                 }
             }
         }
     } else {
         UnwindForUncatchableException(cx, cx->regs());
--- a/js/src/methodjit/StubCalls.cpp
+++ b/js/src/methodjit/StubCalls.cpp
@@ -1096,17 +1096,17 @@ stubs::InitProp(VMFrame &f, PropertyName
 }
 
 void JS_FASTCALL
 stubs::IterNext(VMFrame &f)
 {
     JS_ASSERT(f.regs.stackDepth() >= 1);
     JS_ASSERT(f.regs.sp[-1].isObject());
 
-    JSObject *iterobj = &f.regs.sp[-1].toObject();
+    RootedObject iterobj(f.cx, &f.regs.sp[-1].toObject());
     f.regs.sp[0].setNull();
     f.regs.sp++;
     if (!js_IteratorNext(f.cx, iterobj, MutableHandleValue::fromMarkedLocation(&f.regs.sp[-1])))
         THROW();
 }
 
 JSBool JS_FASTCALL
 stubs::IterMore(VMFrame &f)
@@ -1121,17 +1121,18 @@ stubs::IterMore(VMFrame &f)
 
     return v.toBoolean();
 }
 
 void JS_FASTCALL
 stubs::EndIter(VMFrame &f)
 {
     JS_ASSERT(f.regs.stackDepth() >= 1);
-    if (!CloseIterator(f.cx, &f.regs.sp[-1].toObject()))
+    RootedObject obj(f.cx, &f.regs.sp[-1].toObject());
+    if (!CloseIterator(f.cx, obj))
         THROW();
 }
 
 JSString * JS_FASTCALL
 stubs::TypeOf(VMFrame &f)
 {
     const Value &ref = f.regs.sp[-1];
     JSType type = JS_TypeOfValue(f.cx, ref);
--- a/js/src/vm/ScopeObject.cpp
+++ b/js/src/vm/ScopeObject.cpp
@@ -165,17 +165,17 @@ CallObject::createTemplateObject(JSConte
         return NULL;
 
     HeapSlot *slots;
     if (!PreallocateObjectDynamicSlots(cx, shape, &slots))
         return NULL;
 
     CallObject *callobj = CallObject::create(cx, shape, type, slots);
     if (!callobj) {
-        js_delete(slots);
+        js_free(slots);
         return NULL;
     }
 
     return callobj;
 }
 
 /*
  * Construct a call object for the given bindings.  If this is a call object
--- a/js/xpconnect/loader/XPCOMUtils.jsm
+++ b/js/xpconnect/loader/XPCOMUtils.jsm
@@ -166,19 +166,23 @@ var XPCOMUtils = {
    * @param aName
    *        The name of the getter to define on aObject.
    * @param aLambda
    *        A function that returns what the getter should return.  This will
    *        only ever be called once.
    */
   defineLazyGetter: function XPCU_defineLazyGetter(aObject, aName, aLambda)
   {
-    aObject.__defineGetter__(aName, function() {
-      delete aObject[aName];
-      return aObject[aName] = aLambda.apply(aObject);
+    Object.defineProperty(aObject, aName, {
+      get: function () {
+        delete aObject[aName];
+        return aObject[aName] = aLambda.apply(aObject);
+      },
+      configurable: true,
+      enumerable: true
     });
   },
 
   /**
    * Defines a getter on a specified object for a service.  The service will not
    * be obtained until first use.
    *
    * @param aObject
--- a/js/xpconnect/src/dom_quickstubs.qsconf
+++ b/js/xpconnect/src/dom_quickstubs.qsconf
@@ -471,16 +471,18 @@ irregularFilenames = {
     'nsIWebGLShaderPrecisionFormat' : 'nsIDOMWebGLRenderingContext',
     'nsIWebGLActiveInfo': 'nsIDOMWebGLRenderingContext',
     'nsIWebGLUniformLocation': 'nsIDOMWebGLRenderingContext',
     'nsIWebGLExtension': 'nsIDOMWebGLRenderingContext',
     'nsIWebGLExtensionStandardDerivatives' : 'nsIDOMWebGLRenderingContext',
     'nsIWebGLExtensionTextureFilterAnisotropic' : 'nsIDOMWebGLRenderingContext',
     'nsIWebGLExtensionLoseContext' : 'nsIDOMWebGLRenderingContext',
     'nsIWebGLExtensionCompressedTextureS3TC' : 'nsIDOMWebGLRenderingContext',
+    'nsIWebGLExtensionCompressedTextureATC' : 'nsIDOMWebGLRenderingContext',
+    'nsIWebGLExtensionCompressedTexturePVRTC' : 'nsIDOMWebGLRenderingContext',
     'nsIWebGLExtensionDepthTexture' : 'nsIDOMWebGLRenderingContext',
 
     'nsIIndexedDatabaseUsageCallback': 'nsIIndexedDatabaseManager',
 
     'nsIDOMTouch': 'nsIDOMTouchEvent',
     'nsIDOMTouchList': 'nsIDOMTouchEvent',
 
     'nsIDOMMutationRecord': 'nsIDOMMutationObserver',
--- a/layout/generic/nsSimplePageSequence.cpp
+++ b/layout/generic/nsSimplePageSequence.cpp
@@ -810,67 +810,43 @@ nsSimplePageSequenceFrame::DoPageEnd()
 
   if (mCurrentPageFrame) {
     mCurrentPageFrame = mCurrentPageFrame->GetNextSibling();
   }
   
   return rv;
 }
 
-static void PaintPageSequence(nsIFrame* aFrame, nsRenderingContext* aCtx,
-                             const nsRect& aDirtyRect, nsPoint aPt)
+static gfx3DMatrix
+ComputePageSequenceTransform(nsIFrame* aFrame, float aAppUnitsPerPixel)
 {
-  static_cast<nsSimplePageSequenceFrame*>(aFrame)->PaintPageSequence(*aCtx, aDirtyRect, aPt);
-}
-
-//------------------------------------------------------------------------------
-void
-nsSimplePageSequenceFrame::PaintPageSequence(nsRenderingContext& aRenderingContext,
-                                             const nsRect&        aDirtyRect,
-                                             nsPoint              aPt) {
-  nsRect rect = aDirtyRect;
-  float scale = PresContext()->GetPrintPreviewScale();
-  aRenderingContext.PushState();
-  nsPoint framePos = aPt;
-  aRenderingContext.Translate(framePos);
-  rect -= framePos;
-  aRenderingContext.Scale(scale, scale);
-  rect.ScaleRoundOut(1.0f / scale);
-
-  // Now the rect and the rendering coordinates are are relative to this frame.
-  // Loop over the pages and paint them.
-  nsIFrame* child = GetFirstPrincipalChild();
-  while (child) {
-    nsPoint pt = child->GetPosition();
-    // The rendering context has to be translated before each call to PaintFrame
-    aRenderingContext.PushState();
-    aRenderingContext.Translate(pt);
-    nsLayoutUtils::PaintFrame(&aRenderingContext, child,
-                              nsRegion(rect - pt), NS_RGBA(0,0,0,0),
-                              nsLayoutUtils::PAINT_SYNC_DECODE_IMAGES);
-    aRenderingContext.PopState();
-    child = child->GetNextSibling();
-  }
-
-  aRenderingContext.PopState();
+  float scale = aFrame->PresContext()->GetPrintPreviewScale();
+  return gfx3DMatrix::ScalingMatrix(scale, scale, 1);
 }
 
 NS_IMETHODIMP
 nsSimplePageSequenceFrame::BuildDisplayList(nsDisplayListBuilder*   aBuilder,
                                             const nsRect&           aDirtyRect,
                                             const nsDisplayListSet& aLists)
 {
   nsresult rv = DisplayBorderBackgroundOutline(aBuilder, aLists);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  rv = aLists.Content()->AppendNewToTop(new (aBuilder)
-        nsDisplayGeneric(aBuilder, this, ::PaintPageSequence, "PageSequence",
-                         nsDisplayItem::TYPE_PAGE_SEQUENCE));
+  nsDisplayList content;
+  nsIFrame* child = GetFirstPrincipalChild();
+  while (child) {
+    rv = child->BuildDisplayListForStackingContext(aBuilder, aDirtyRect - child->GetOffsetTo(this), &content);
+    NS_ENSURE_SUCCESS(rv, rv);
+    child = child->GetNextSibling();
+  }
+
+  rv = content.AppendNewToTop(new (aBuilder) nsDisplayTransform(aBuilder, this, &content, ::ComputePageSequenceTransform));
   NS_ENSURE_SUCCESS(rv, rv);
 
+  aLists.Content()->AppendToTop(&content);
   return NS_OK;
 }
 
 nsIAtom*
 nsSimplePageSequenceFrame::GetType() const
 {
   return nsGkAtoms::sequenceFrame; 
 }
--- a/layout/generic/nsSimplePageSequence.h
+++ b/layout/generic/nsSimplePageSequence.h
@@ -101,20 +101,16 @@ public:
   virtual void InvalidateInternal(const nsRect& aDamageRect,
                                   nscoord aX, nscoord aY,
                                   nsIFrame* aForChild,
                                   uint32_t aFlags);
 #ifdef DEBUG
   NS_IMETHOD  GetFrameName(nsAString& aResult) const;
 #endif
 
-  void PaintPageSequence(nsRenderingContext& aRenderingContext,
-                         const nsRect&        aDirtyRect,
-                         nsPoint              aPt);
-
 protected:
   nsSimplePageSequenceFrame(nsStyleContext* aContext);
   virtual ~nsSimplePageSequenceFrame();
 
   void SetPageNumberFormat(const char* aPropName, const char* aDefPropVal, bool aPageNumOnly);
 
   // SharedPageData Helper methods
   void SetDateTimeStr(PRUnichar * aDateTimeStr);
--- a/layout/reftests/printing/745025-1-ref.html
+++ b/layout/reftests/printing/745025-1-ref.html
@@ -1,9 +1,9 @@
 <!DOCTYPE html>
 <html class="reftest-print">
 <head>
 
 </head>
 <body>
-<!-- A 10x10 red image --><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAFElEQVQYlWP4z8DwnxjMMKqQvgoBksPHOVp9kXEAAAAASUVORK5CYII=">
+<!-- A 10x10 red image --><img style="-moz-transform: perspective(1px)" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAFElEQVQYlWP4z8DwnxjMMKqQvgoBksPHOVp9kXEAAAAASUVORK5CYII=">
 </body>
 </html>
--- a/layout/reftests/text-shadow/reftest.list
+++ b/layout/reftests/text-shadow/reftest.list
@@ -18,19 +18,19 @@ HTTP(..) == blur-opacity.html blur-opaci
 == padding-decoration.html padding-decoration-ref.html
 == textindent.html textindent-ref.html
 == lineoverflow.html lineoverflow-ref.html
 
 == overflow-not-scrollable-1.html overflow-not-scrollable-1-ref.html
 == overflow-not-scrollable-1.html overflow-not-scrollable-1-ref2.html
 == overflow-not-scrollable-2.html overflow-not-scrollable-2-ref.html
 
-!= text-shadow-selected-1.html text-shadow-selected-1-notref.html
-== text-shadow-selected-1.html text-shadow-selected-1-ref.html
-!= text-shadow-selected-2.html text-shadow-selected-2-notref.html
-== text-shadow-selected-2.html text-shadow-selected-2-ref.html
+needs-focus != text-shadow-selected-1.html text-shadow-selected-1-notref.html
+needs-focus == text-shadow-selected-1.html text-shadow-selected-1-ref.html
+needs-focus != text-shadow-selected-2.html text-shadow-selected-2-notref.html
+needs-focus == text-shadow-selected-2.html text-shadow-selected-2-ref.html
 
 # bug 692744
 == text-shadow-on-space-1.html text-shadow-on-space-1-ref.html
 
 # bug 721750
 needs-focus == text-shadow-on-selection-1.html text-shadow-on-selection-1-ref.html
 needs-focus == text-shadow-on-selection-2.html text-shadow-on-selection-2-ref.html
--- a/layout/reftests/text-shadow/text-shadow-selected-1-notref.html
+++ b/layout/reftests/text-shadow/text-shadow-selected-1-notref.html
@@ -1,13 +1,14 @@
 <!DOCTYPE html>
 <html>
 <head>
 <script type="text/javascript">
 function onload() {
+  window.focus();
   var range = document.createRange();
   range.selectNodeContents(document.getElementById("selectMe"));
   var sel = window.getSelection();
   sel.removeAllRanges();
   sel.addRange(range);
 }
 </script>
 <style type="text/css">
--- a/layout/reftests/text-shadow/text-shadow-selected-1-ref.html
+++ b/layout/reftests/text-shadow/text-shadow-selected-1-ref.html
@@ -1,13 +1,14 @@
 <!DOCTYPE html>
 <html>
 <head>
 <script type="text/javascript">
 function onload() {
+  window.focus();
   var range = document.createRange();
   range.selectNodeContents(document.getElementById("selectMe"));
   var sel = window.getSelection();
   sel.removeAllRanges();
   sel.addRange(range);
 }
 </script>
 <style type="text/css">
--- a/layout/reftests/text-shadow/text-shadow-selected-1.html
+++ b/layout/reftests/text-shadow/text-shadow-selected-1.html
@@ -1,13 +1,14 @@
 <!DOCTYPE html>
 <html>
 <head>
 <script type="text/javascript">
 function onload() {
+  window.focus();
   var range = document.createRange();
   range.selectNodeContents(document.getElementById("selectMe"));
   var sel = window.getSelection();
   sel.removeAllRanges();
   sel.addRange(range);
 }
 </script>
 <style type="text/css">
--- a/layout/reftests/text-shadow/text-shadow-selected-2-notref.html
+++ b/layout/reftests/text-shadow/text-shadow-selected-2-notref.html
@@ -1,13 +1,14 @@
 <!DOCTYPE html>
 <html>
 <head>
 <script type="text/javascript">
 function onload() {
+  window.focus();
   var range = document.createRange();
   range.selectNodeContents(document.getElementById("selectMe"));
   var sel = window.getSelection();
   sel.removeAllRanges();
   sel.addRange(range);
 }
 </script>
 <style type="text/css">
--- a/layout/reftests/text-shadow/text-shadow-selected-2-ref.html
+++ b/layout/reftests/text-shadow/text-shadow-selected-2-ref.html
@@ -1,13 +1,14 @@
 <!DOCTYPE html>
 <html>
 <head>
 <script type="text/javascript">
 function onload() {
+  window.focus();
   var range = document.createRange();
   range.selectNodeContents(document.getElementById("selectMe"));
   var sel = window.getSelection();
   sel.removeAllRanges();
   sel.addRange(range);
 }
 </script>
 <style type="text/css">
--- a/layout/reftests/text-shadow/text-shadow-selected-2.html
+++ b/layout/reftests/text-shadow/text-shadow-selected-2.html
@@ -1,13 +1,14 @@
 <!DOCTYPE html>
 <html>
 <head>
 <script type="text/javascript">
 function onload() {
+  window.focus();
   var range = document.createRange();
   range.selectNodeContents(document.getElementById("selectMe"));
   var sel = window.getSelection();
   sel.removeAllRanges();
   sel.addRange(range);
 }
 </script>
 <style type="text/css">
--- a/mobile/android/app/mobile.js
+++ b/mobile/android/app/mobile.js
@@ -529,61 +529,50 @@ pref("widget.ime.android.fullscreen_thre
 pref("image.mem.decodeondraw", true);
 pref("content.image.allow_locking", false);
 pref("image.mem.min_discard_timeout_ms", 10000);
 
 // enable touch events interfaces
 pref("dom.w3c_touch_events.enabled", true);
 
 #ifdef MOZ_SAFE_BROWSING
-// Safe browsing does nothing unless this pref is set
-pref("browser.safebrowsing.enabled", true);
-
-// Prevent loading of pages identified as malware
-pref("browser.safebrowsing.malware.enabled", true);
-
-// Non-enhanced mode (local url lists) URL list to check for updates
-pref("browser.safebrowsing.provider.0.updateURL", "http://safebrowsing.clients.google.com/safebrowsing/downloads?client={moz:client}&appver={moz:version}&pver=2.2");
-
-pref("browser.safebrowsing.dataProvider", 0);
+pref("browser.safebrowsing.enabled", false);
+pref("browser.safebrowsing.malware.enabled", false);
+pref("browser.safebrowsing.debug", false);
 
-// Does the provider name need to be localizable?
-pref("browser.safebrowsing.provider.0.name", "Google");
-pref("browser.safebrowsing.provider.0.keyURL", "https://sb-ssl.google.com/safebrowsing/newkey?client={moz:client}&appver={moz:version}&pver=2.2");
-pref("browser.safebrowsing.provider.0.reportURL", "http://safebrowsing.clients.google.com/safebrowsing/report?");
-pref("browser.safebrowsing.provider.0.gethashURL", "http://safebrowsing.clients.google.com/safebrowsing/gethash?client={moz:client}&appver={moz:version}&pver=2.2");
+pref("browser.safebrowsing.updateURL", "http://safebrowsing.clients.google.com/safebrowsing/downloads?client=SAFEBROWSING_ID&appver=%VERSION%&pver=2.2");
+pref("browser.safebrowsing.keyURL", "https://sb-ssl.google.com/safebrowsing/newkey?client=SAFEBROWSING_ID&appver=%VERSION%&pver=2.2");
+pref("browser.safebrowsing.gethashURL", "http://safebrowsing.clients.google.com/safebrowsing/gethash?client=SAFEBROWSING_ID&appver=%VERSION%&pver=2.2");
+pref("browser.safebrowsing.reportURL", "http://safebrowsing.clients.google.com/safebrowsing/report?");
+pref("browser.safebrowsing.reportGenericURL", "http://%LOCALE%.phish-generic.mozilla.com/?hl=%LOCALE%");
+pref("browser.safebrowsing.reportErrorURL", "http://%LOCALE%.phish-error.mozilla.com/?hl=%LOCALE%");
+pref("browser.safebrowsing.reportPhishURL", "http://%LOCALE%.phish-report.mozilla.com/?hl=%LOCALE%");
+pref("browser.safebrowsing.reportMalwareURL", "http://%LOCALE%.malware-report.mozilla.com/?hl=%LOCALE%");
+pref("browser.safebrowsing.reportMalwareErrorURL", "http://%LOCALE%.malware-error.mozilla.com/?hl=%LOCALE%");
 
-// HTML report pages
-pref("browser.safebrowsing.provider.0.reportGenericURL", "http://{moz:locale}.phish-generic.mozilla.com/?hl={moz:locale}");
-pref("browser.safebrowsing.provider.0.reportErrorURL", "http://{moz:locale}.phish-error.mozilla.com/?hl={moz:locale}");
-pref("browser.safebrowsing.provider.0.reportPhishURL", "http://{moz:locale}.phish-report.mozilla.com/?hl={moz:locale}");
-pref("browser.safebrowsing.provider.0.reportMalwareURL", "http://{moz:locale}.malware-report.mozilla.com/?hl={moz:locale}");
-pref("browser.safebrowsing.provider.0.reportMalwareErrorURL", "http://{moz:locale}.malware-error.mozilla.com/?hl={moz:locale}");
-
-// FAQ URLs
-pref("browser.safebrowsing.warning.infoURL", "http://www.mozilla.com/%LOCALE%/%APP%/phishing-protection/");
-pref("browser.geolocation.warning.infoURL", "http://www.mozilla.com/%LOCALE%/%APP%/geolocation/");
+pref("browser.safebrowsing.warning.infoURL", "http://www.mozilla.com/%LOCALE%/firefox/phishing-protection/");
+pref("browser.safebrowsing.malware.reportURL", "http://safebrowsing.clients.google.com/safebrowsing/diagnostic?client=%NAME%&hl=%LOCALE%&site=");
 
 // Name of the about: page contributed by safebrowsing to handle display of error
 // pages on phishing/malware hits.  (bug 399233)
 pref("urlclassifier.alternate_error_page", "blocked");
 
 // The number of random entries to send with a gethash request.
 pref("urlclassifier.gethashnoise", 4);
 
+// Randomize all UrlClassifier data with a per-client key.
+pref("urlclassifier.randomizeclient", true);
+
 // The list of tables that use the gethash request to confirm partial results.
 pref("urlclassifier.gethashtables", "goog-phish-shavar,goog-malware-shavar");
 
 // If an urlclassifier table has not been updated in this number of seconds,
 // a gethash request will be forced to check that the result is still in
 // the database.
 pref("urlclassifier.confirm-age", 2700);
-
-// URL for checking the reason for a malware warning.
-pref("browser.safebrowsing.malware.reportURL", "http://safebrowsing.clients.google.com/safebrowsing/diagnostic?client=%NAME%&hl=%LOCALE%&site=");
 #endif
 
 // True if this is the first time we are showing about:firstrun
 pref("browser.firstrun.show.uidiscovery", true);
 pref("browser.firstrun.show.localepicker", false);
 
 // True if you always want dump() to work
 //
--- a/mobile/android/base/BrowserApp.java
+++ b/mobile/android/base/BrowserApp.java
@@ -46,16 +46,17 @@ import java.util.regex.Pattern;
 
 abstract public class BrowserApp extends GeckoApp
                                  implements TabsPanel.TabsLayoutChangeListener,
                                             PropertyAnimator.PropertyAnimationListener {
     private static final String LOGTAG = "GeckoBrowserApp";
 
     public static BrowserToolbar mBrowserToolbar;
     private AboutHomeContent mAboutHomeContent;
+    private boolean mAboutHomeShowing;
 
     static Vector<MenuItem> sAddonMenuItems = new Vector<MenuItem>();
 
     private PropertyAnimator mMainLayoutAnimator;
 
     private FindInPageBar mFindInPageBar;
 
     // We'll ask for feedback after the user launches the app this many times.
@@ -579,27 +580,35 @@ abstract public class BrowserApp extends
     /* About:home UI */
     void updateAboutHomeTopSites() {
         if (mAboutHomeContent == null)
             return;
 
         mAboutHomeContent.update(EnumSet.of(AboutHomeContent.UpdateFlags.TOP_SITES));
     }
 
-    public void showAboutHome() {
+    private void showAboutHome() {
+        if (mAboutHomeShowing)
+            return;
+
+        mAboutHomeShowing = true;
         Runnable r = new AboutHomeRunnable(true);
         mMainHandler.postAtFrontOfQueue(r);
     }
 
-    public void hideAboutHome() {
+    private void hideAboutHome() {
+        if (!mAboutHomeShowing)
+            return;
+
+        mAboutHomeShowing = false;
         Runnable r = new AboutHomeRunnable(false);
         mMainHandler.postAtFrontOfQueue(r);
     }
 
-    public class AboutHomeRunnable implements Runnable {
+    private class AboutHomeRunnable implements Runnable {
         boolean mShow;
         AboutHomeRunnable(boolean show) {
             mShow = show;
         }
 
         public void run() {
             mFormAssistPopup.hide();
             if (mShow) {
--- a/mobile/android/base/DoorHanger.java
+++ b/mobile/android/base/DoorHanger.java
@@ -81,16 +81,21 @@ public class DoorHanger extends LinearLa
                 String label = buttonObject.getString("label");
                 int callBackId = buttonObject.getInt("callback");
                 addButton(label, callBackId);
             } catch (JSONException e) {
                 Log.e(LOGTAG, "Error creating doorhanger button", e);
             }
          }
 
+        // Enable the button layout if we have buttons.
+        if (buttons.length() > 0) {
+            mChoicesLayout.setVisibility(LinearLayout.VISIBLE);
+        }
+
         setOptions(options);
     }
 
     private void addButton(String aText, int aCallback) {
         if (mLayoutParams == null)
             mLayoutParams = new LayoutParams(LayoutParams.FILL_PARENT,
                                              LayoutParams.FILL_PARENT,
                                              1.0f);
--- a/mobile/android/base/GeckoApp.java
+++ b/mobile/android/base/GeckoApp.java
@@ -1674,16 +1674,17 @@ abstract public class GeckoApp
 
         if (SmsManager.getInstance() != null) {
           SmsManager.getInstance().start();
         }
 
         mPromptService = new PromptService();
 
         mTextSelection = new TextSelection((TextSelectionHandle) findViewById(R.id.start_handle),
+                                           (TextSelectionHandle) findViewById(R.id.middle_handle),
                                            (TextSelectionHandle) findViewById(R.id.end_handle),
                                            GeckoAppShell.getEventDispatcher());
 
         UpdateServiceHelper.registerForUpdates(this);
 
         final GeckoApp self = this;
 
         GeckoAppShell.getHandler().postDelayed(new Runnable() {
--- a/mobile/android/base/Makefile.in
+++ b/mobile/android/base/Makefile.in
@@ -500,16 +500,17 @@ RES_DRAWABLE_BASE = \
   res/drawable/reader.png \
   res/drawable/reading_list.png \
   res/drawable/validation_arrow.png \
   res/drawable/validation_arrow_inverted.png \
   res/drawable/validation_bg.9.png \
   res/drawable/bookmarkdefaults_favicon_support.png \
   res/drawable/bookmarkdefaults_favicon_addons.png \
   res/drawable/handle_end.png \
+  res/drawable/handle_middle.png \
   res/drawable/handle_start.png \
   $(addprefix res/drawable-mdpi/,$(notdir $(SYNC_RES_DRAWABLE_MDPI))) \
   $(NULL)
 
 RES_DRAWABLE_LDPI = \
   $(addprefix res/drawable-ldpi/,$(notdir $(SYNC_RES_DRAWABLE_LDPI))) \
   $(NULL)
 
@@ -566,16 +567,17 @@ RES_DRAWABLE_HDPI = \
   res/drawable-hdpi/site_security_verified.png \
   res/drawable-hdpi/urlbar_stop.png \
   res/drawable-hdpi/reader.png \
   res/drawable-hdpi/reading_list.png \
   res/drawable-hdpi/validation_arrow.png \
   res/drawable-hdpi/validation_arrow_inverted.png \
   res/drawable-hdpi/validation_bg.9.png \
   res/drawable-hdpi/handle_end.png \
+  res/drawable-hdpi/handle_middle.png \
   res/drawable-hdpi/handle_start.png \
   $(addprefix res/drawable-hdpi/,$(notdir $(SYNC_RES_DRAWABLE_HDPI))) \
   $(NULL)
 
 RES_DRAWABLE_XHDPI = \
   res/drawable-xhdpi/favicon.png \
   res/drawable-xhdpi/folder.png \
   res/drawable-xhdpi/abouthome_icon.png \
@@ -626,16 +628,17 @@ RES_DRAWABLE_XHDPI = \
   res/drawable-xhdpi/remote_tabs_off.png \
   res/drawable-xhdpi/remote_tabs_on.png \
   res/drawable-xhdpi/site_security_identified.png \
   res/drawable-xhdpi/site_security_verified.png \
   res/drawable-xhdpi/validation_arrow.png \
   res/drawable-xhdpi/validation_arrow_inverted.png \
   res/drawable-xhdpi/validation_bg.9.png \
   res/drawable-xhdpi/handle_end.png \
+  res/drawable-xhdpi/handle_middle.png \
   res/drawable-xhdpi/handle_start.png \
   $(NULL)
 
 RES_DRAWABLE_MDPI_V11 = \
   res/drawable-mdpi-v11/alert_addon.png \
   res/drawable-mdpi-v11/alert_app.png \
   res/drawable-mdpi-v11/alert_download.png \
   res/drawable-mdpi-v11/ic_menu_back.png \
--- a/mobile/android/base/Tab.java
+++ b/mobile/android/base/Tab.java
@@ -258,17 +258,17 @@ public final class Tab {
         mDocumentURI = documentURI;
     }
 
     public String getDocumentURI() {
         return mDocumentURI;
     }
 
     public void setContentType(String contentType) {
-        mContentType = contentType;
+        mContentType = (contentType == null) ? "" : contentType;
     }
 
     public String getContentType() {
         return mContentType;
     }
 
     public synchronized void updateTitle(String title) {
         // Keep the title unchanged while entering reader mode
--- a/mobile/android/base/TextSelection.java
+++ b/mobile/android/base/TextSelection.java
@@ -6,40 +6,45 @@ package org.mozilla.gecko;
 
 import org.mozilla.gecko.gfx.Layer;
 import org.mozilla.gecko.gfx.Layer.RenderContext;
 import org.mozilla.gecko.gfx.LayerView;
 import org.mozilla.gecko.util.EventDispatcher;
 import org.mozilla.gecko.util.FloatUtils;
 import org.mozilla.gecko.util.GeckoEventListener;
 
+import org.json.JSONArray;
 import org.json.JSONObject;
 
 import android.util.Log;
 import android.view.View;
 
 class TextSelection extends Layer implements GeckoEventListener {
     private static final String LOGTAG = "GeckoTextSelection";
 
     private final TextSelectionHandle mStartHandle;
+    private final TextSelectionHandle mMiddleHandle;
     private final TextSelectionHandle mEndHandle;
     private final EventDispatcher mEventDispatcher;
 
     private float mViewLeft;
     private float mViewTop;
     private float mViewZoom;
 
-    TextSelection(TextSelectionHandle startHandle, TextSelectionHandle endHandle,
+    TextSelection(TextSelectionHandle startHandle,
+                  TextSelectionHandle middleHandle,
+                  TextSelectionHandle endHandle,
                   EventDispatcher eventDispatcher) {
         mStartHandle = startHandle;
+        mMiddleHandle = middleHandle;
         mEndHandle = endHandle;
         mEventDispatcher = eventDispatcher;
 
-        // Only register listeners if we have valid start/end handles
-        if (mStartHandle == null || mEndHandle == null) {
+        // Only register listeners if we have valid start/middle/end handles
+        if (mStartHandle == null || mMiddleHandle == null || mEndHandle == null) {
             Log.e(LOGTAG, "Failed to initialize text selection because at least one handle is null");
         } else {
             registerEventListener("TextSelection:ShowHandles");
             registerEventListener("TextSelection:HideHandles");
             registerEventListener("TextSelection:PositionHandles");
         }
     }
 
@@ -47,52 +52,83 @@ class TextSelection extends Layer implem
         unregisterEventListener("TextSelection:ShowHandles");
         unregisterEventListener("TextSelection:HideHandles");
         unregisterEventListener("TextSelection:PositionHandles");
     }
 
     public void handleMessage(String event, JSONObject message) {
         try {
             if (event.equals("TextSelection:ShowHandles")) {
+                final JSONArray handles = message.getJSONArray("handles");
                 GeckoApp.mAppContext.mMainHandler.post(new Runnable() {
                     public void run() {
-                        mStartHandle.setVisibility(View.VISIBLE);
-                        mEndHandle.setVisibility(View.VISIBLE);
+                        try {
+                            for (int i=0; i < handles.length(); i++) {
+                                String handle = handles.getString(i);
 
-                        mViewLeft = 0.0f;
-                        mViewTop = 0.0f;
-                        mViewZoom = 0.0f;
-                        LayerView layerView = GeckoApp.mAppContext.getLayerView();
-                        if (layerView != null) {
-                            layerView.addLayer(TextSelection.this);
-                        }
+                                if (handle.equals("START"))
+                                    mStartHandle.setVisibility(View.VISIBLE);
+                                else if (handle.equals("MIDDLE"))
+                                    mMiddleHandle.setVisibility(View.VISIBLE);
+                                else
+                                    mEndHandle.setVisibility(View.VISIBLE);
+                            }
+
+                            mViewLeft = 0.0f;
+                            mViewTop = 0.0f;
+                            mViewZoom = 0.0f;
+                            LayerView layerView = GeckoApp.mAppContext.getLayerView();
+                            if (layerView != null) {
+                                layerView.addLayer(TextSelection.this);
+                            }
+                        } catch(Exception e) {}
                     }
                 });
             } else if (event.equals("TextSelection:HideHandles")) {
+                final JSONArray handles = message.getJSONArray("handles");
                 GeckoApp.mAppContext.mMainHandler.post(new Runnable() {
                     public void run() {
-                        LayerView layerView = GeckoApp.mAppContext.getLayerView();
-                        if (layerView != null) {
-                            layerView.removeLayer(TextSelection.this);
-                        }
+                        try {
+                            LayerView layerView = GeckoApp.mAppContext.getLayerView();
+                            if (layerView != null) {
+                                layerView.removeLayer(TextSelection.this);
+                            }
 
-                        mStartHandle.setVisibility(View.GONE);
-                        mEndHandle.setVisibility(View.GONE);
+                            for (int i=0; i < handles.length(); i++) {
+                                String handle = handles.getString(i);
+                                if (handle.equals("START"))
+                                    mStartHandle.setVisibility(View.GONE);
+                                else if (handle.equals("MIDDLE"))
+                                    mMiddleHandle.setVisibility(View.GONE);
+                                else
+                                    mEndHandle.setVisibility(View.GONE);
+                            }
+
+                        } catch(Exception e) {}
                     }
                 });
             } else if (event.equals("TextSelection:PositionHandles")) {
-                final int startLeft = message.getInt("startLeft");
-                final int startTop = message.getInt("startTop");
-                final int endLeft = message.getInt("endLeft");
-                final int endTop = message.getInt("endTop");
-
+                final JSONArray positions = message.getJSONArray("positions");
                 GeckoApp.mAppContext.mMainHandler.post(new Runnable() {
                     public void run() {
-                        mStartHandle.positionFromGecko(startLeft, startTop);
-                        mEndHandle.positionFromGecko(endLeft, endTop);
+                        try {
+                            for (int i=0; i < positions.length(); i++) {
+                                JSONObject position = positions.getJSONObject(i);
+                                String handle = position.getString("handle");
+                                int left = position.getInt("left");
+                                int top = position.getInt("top");
+
+                                if (handle.equals("START"))
+                                    mStartHandle.positionFromGecko(left, top);
+                                else if (handle.equals("MIDDLE"))
+                                    mMiddleHandle.positionFromGecko(left, top);
+                                else
+                                    mEndHandle.positionFromGecko(left, top);
+                             }
+                        } catch (Exception e) { }
                     }
                 });
             }
         } catch (Exception e) {
             Log.e(LOGTAG, "Exception handling message \"" + event + "\":", e);
         }
     }
 
@@ -108,16 +144,17 @@ class TextSelection extends Layer implem
         }
         mViewLeft = context.viewport.left;
         mViewTop = context.viewport.top;
         mViewZoom = context.zoomFactor;
 
         GeckoApp.mAppContext.mMainHandler.post(new Runnable() {
             public void run() {
                 mStartHandle.repositionWithViewport(context.viewport.left, context.viewport.top, context.zoomFactor);
+                mMiddleHandle.repositionWithViewport(context.viewport.left, context.viewport.top, context.zoomFactor);
                 mEndHandle.repositionWithViewport(context.viewport.left, context.viewport.top, context.zoomFactor);
             }
         });
     }
 
     private void registerEventListener(String event) {
         mEventDispatcher.registerEventListener(event, this);
     }
--- a/mobile/android/base/TextSelectionHandle.java
+++ b/mobile/android/base/TextSelectionHandle.java
@@ -17,17 +17,17 @@ import android.util.Log;
 import android.view.MotionEvent;
 import android.view.View;
 import android.widget.ImageView;
 import android.widget.RelativeLayout;
 
 class TextSelectionHandle extends ImageView implements View.OnTouchListener {
     private static final String LOGTAG = "GeckoTextSelectionHandle";
 
-    private enum HandleType { START, END }; 
+    private enum HandleType { START, MIDDLE, END }; 
 
     private final HandleType mHandleType;
     private final int mWidth;
     private final int mHeight;
     private final int mShadow;
 
     private int mLeft;
     private int mTop;
@@ -37,18 +37,26 @@ class TextSelectionHandle extends ImageV
 
     private RelativeLayout.LayoutParams mLayoutParams;
 
     TextSelectionHandle(Context context, AttributeSet attrs) {
         super(context, attrs);
         setOnTouchListener(this);
 
         TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.TextSelectionHandle);
-        String handleType = a.getString(R.styleable.TextSelectionHandle_handleType);
-        mHandleType = handleType.equals("START") ? HandleType.START : HandleType.END;
+        int handleType = a.getInt(R.styleable.TextSelectionHandle_handleType, 0x01);
+
+        if (handleType == 0x01)
+            mHandleType = HandleType.START;
+        else if (handleType == 0x02)
+            mHandleType = HandleType.MIDDLE;
+        else
+            mHandleType = HandleType.END;
+
+        mGeckoPoint = new PointF(0.0f, 0.0f);
 
         mWidth = getResources().getDimensionPixelSize(R.dimen.text_selection_handle_width);
         mHeight = getResources().getDimensionPixelSize(R.dimen.text_selection_handle_height);
         mShadow = getResources().getDimensionPixelSize(R.dimen.text_selection_handle_shadow);
     }
 
     public boolean onTouch(View v, MotionEvent event) {
         switch (event.getActionMasked()) {
@@ -84,17 +92,24 @@ class TextSelectionHandle extends ImageV
         mTop = mTop + newY - mTouchStartY;
 
         LayerView layerView = GeckoApp.mAppContext.getLayerView();
         if (layerView == null) {
             Log.e(LOGTAG, "Can't move selection because layerView is null");
             return;
         }
         // Send x coordinate on the right side of the start handle, left side of the end handle.
-        float left = (float) mLeft + (mHandleType.equals(HandleType.START) ? mWidth - mShadow : mShadow);
+        float left = (float) mLeft;
+        if (mHandleType.equals(HandleType.START))
+            left +=  mWidth - mShadow;
+        else if (mHandleType.equals(HandleType.MIDDLE))
+            left +=  (float) ((mWidth - mShadow) / 2);
+        else
+            left += mShadow;
+
         PointF geckoPoint = new PointF(left, (float) mTop);
         geckoPoint = layerView.convertViewPointToLayerPoint(geckoPoint);
 
         JSONObject args = new JSONObject();
         try {
             args.put("handleType", mHandleType.toString());
             args.put("x", Math.round(geckoPoint.x));
             args.put("y", Math.round(geckoPoint.y));
@@ -117,17 +132,24 @@ class TextSelectionHandle extends ImageV
         ImmutableViewportMetrics metrics = layerView.getViewportMetrics();
         repositionWithViewport(metrics.viewportRectLeft, metrics.viewportRectTop, metrics.zoomFactor);
     }
 
     void repositionWithViewport(float x, float y, float zoom) {
         PointF viewPoint = new PointF((mGeckoPoint.x * zoom) - x,
                                       (mGeckoPoint.y * zoom) - y);
 
-        mLeft = Math.round(viewPoint.x) - (mHandleType.equals(HandleType.START) ? mWidth - mShadow : mShadow);
+        mLeft = Math.round(viewPoint.x);
+        if (mHandleType.equals(HandleType.START))
+            mLeft -=  mWidth - mShadow;
+        else if (mHandleType.equals(HandleType.MIDDLE))
+            mLeft -=  (float) ((mWidth - mShadow) / 2);
+        else
+            mLeft -= mShadow;
+
         mTop = Math.round(viewPoint.y);
 
         setLayoutPosition();
     }
 
     private void setLayoutPosition() {
         if (mLayoutParams == null) {
             mLayoutParams = (RelativeLayout.LayoutParams) getLayoutParams();
--- a/mobile/android/base/WebAppManifestFragment.xml.frag
+++ b/mobile/android/base/WebAppManifestFragment.xml.frag
@@ -1,16 +1,16 @@
         <activity android:name=".WebApps$WebApp@APPNUM@"
                   android:label="@string/webapp_generic_name"
                   android:configChanges="keyboard|keyboardHidden|mcc|mnc|orientation|screenSize"
                   android:windowSoftInputMode="stateUnspecified|adjustResize"
                   android:launchMode="singleInstance"
                   android:taskAffinity="org.mozilla.gecko.WEBAPP@APPNUM@"
                   android:process=":@ANDROID_PACKAGE_NAME@.WebApp@APPNUM@"
-                  android:theme="@style/Gecko.Translucent.NoActionBar">
+                  android:theme="@style/Gecko.App">
             <intent-filter>
                 <action android:name="org.mozilla.gecko.WEBAPP@APPNUM@" />
             </intent-filter>
             <intent-filter>
                 <action android:name="org.mozilla.gecko.ACTION_ALERT_CALLBACK" />
             </intent-filter>
         </activity>
 
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..5dcee14f7a70c720d23716cef4cae3c399c7f96b
GIT binary patch
literal 2517
zc$}S9c~n#95>EhwvZ^eC2!_y#_(;M{LP!EAAtCG%b_7{Ma!Eo~lduaUC?dAv27-~N
zK$SkN6%`Z}EutWc7C}K&q%2CQLPZe>Ak_w+_<DMJ{NsJ+-aFsSH@}(rW;y5P(>HtS
z>#Wv+Kp^_wUeq8pMXF!-r7-pP*5z0eH8GcYM96|g39=N11cZ=TqIeMQEnu+0AdtaI
z+tv!YKp>hNZb*bI!rza?6bVp_1sznXKnz(}E}K%t3?>hh!Q(+TSLliuud7GExhz*i
zxTC*=znB7YxL)ZJFgSg42s53>B(e~jHo{#}NooTEP{x3#3iv`PDb*G6(Jo27Ul5}a
z@Q*4oo-5+NK}Gn};S`Ysggc_JNTve-!0~t#fOEv-0ed*c0l=Ug)DIpB;7E>m62=Ms
zX(80!B&-Bd5S8}Hmzr}$aAYzu35`xkNkOGxQ6dQ&4G@XM1sfO)QmuiMrU_+?RHRU9
zvuJ?|N|_R_SjH6z;R`$?UX&zrMIaWhAQ1cee>N<XeoB-&W$09f7!9Bt&;kK^QClht
z0u#QhEe%N%gXkboDoT<t)%8fQ`HQPBLl+d)(U1ZpTy;?xe5#0<BmjjnZ>lRoeS%_f
zStJ_4i3R{pI0q+;1D*f?1P20^=8hqfi4+eE1`90O_$MqG4`3bfWU4!jhywr*fJh<Y
z2~-+^K*l<G5NMc1thZ1qV+fhxB9{9<Eai(>5=8<sWFkq3NW@?406Iq`6G=HDF`N>N
zhp+c%FuB47f!#uZKE(=3xXB=kCJ_nXA2Uqi{zC)+6_3Z0u^s^JFE_{2a0CGBL?dEw
zh)-D7|C2SeIvDid+GSCs?!kra=jK;4pT`Fjs%J)`9*z^0sk#sdOw*f64oQ77rp(|Q
zd#q_@C##aj&)4>hZoAIoabE-)=mhb~E-B-T$|GXm1kQN6!{_oUs7A5Nne(^8{k~PY
z4XriPKj2CKK(<+_N89ZK`EEC?(=Ej6_ia7to?Ml1JUOM*uKKCu<giah?>naLEGQi5
z%=$H>{>W_KU3Z6u8WuFA53ija&MtYPTGgd!T?g~qhLInS?M-$bk1J1u1Q(SAK}1=n
z{uuPEV`opdj{e(1x9Iqu#?3X9OcSiBcscv^?^Ct1B=kyr_q!qSuK(0tr2f#|r=78H
z-lE6#a@DtQC*+kr7>gbhCxewg*=e6$e``m(^{Oh(?31d3mb(L2uII&P$Hh4bZ3CQf
zu(LPJYlUD<+SJ62_Qwk7_qt6hw3dE&gA>19uEm}?+#NC-@M=@~AWrDaeeF$V#;stt
zcdI;BA5Sey>?w_F8-W3Or76$?xwE;M&RpGB-lVxd&NrrQ9aHMf=u?<+Q1&m{&g_RS
z)fLH}IGow^%@P9z{<I-<RkVG$<>_myF0_wlk${d(L3;9da~v#rVBb##xuNgFAL3qZ
zrDI+0G*2=HcvTIJp#=LgzYXm?;-~;656_R+2De&o%{@2lW3boO=*2UUaPpgR7t6jZ
zY4p`AIiua?`z>qNLPr>@^R3AI%Xa5#QrtdFbUpTE6*krcxl{OxtLN79vxM&tKioAY
z$eMPs$_-+%Etk@1F`ZjhoH9(FPYZi2MQ!x!T4(dncZsFUnfU5faa4blacfejB$K3#
zF<RpYW8e3hNWUqyX^1kMKR6dJUhn%98Lh*)kmk@E6E#n3UUS`c{iL;lUVq1!?V->(
zY|F@07qZmi*xRXnZ?5}<Nloi2&KW`9&vZAT?YRk7hD2tI0#)AHWVitqzCU0BfAOxa
z_NM;q_r38w;!9p}GYz{u_91ym*UYB3cBB<5jm1_j+NGsB^BYfrgVz#;D#b69CV6!e
zr2ZYBch6PO?!;@-8k+i0sYNg>gIws--f&`?!(2bxZJ60yrQIH5IP>H8k%#;H2h-|f
zeB7W@0d}uVmhMdPhvvAQl-b5K-`g%FBuiXgpD**&DAVWtT3a<XDd66K?l=0{M}rSj
z5v&`xwcYorAAi(v{2BYUM!o5z7i9AJp5Nvj`xL()Xxk16dD&=vjdyhmOr%Pw>l+%R
zG#h1JF0s!$@}}&1v1Zxhy`xq-nNN(pd~%`tO$Mx1-RTK=S7%(*uNsYQCC@Rx&OmZ5
z^v<TgI$agrA6#t{>1a0LzA_*}o6lDnz->C4>MTYz`dS$Y_wwt}l|Kt_mdHJig(tm?
z8p+KYJpmx_yc>>gT09;7+_0p?C_7sm;Yv>bH~fnwi3cB@F$gs9V<T34*Vs6j7$~f;
zYA{n20UEmu<RfCo9maHne6hILvcyS2xqSlT`L8>`vci49(_3_<Jrd>mgJ!e>r1++`
z?4iwijp^%i4x8#cDT8%=wZVcTpgR>NcYp!II+>Ba@toS2jUB~Hp4;J=VaoEv>PQ`m
z?(nm_kuTe_ZkCiQmX&sbV-G09nm^tNH`QUDtb1v1sKg(U_=cZ1d9{1^*g)ZNW#pw7
zk2>%*`T|Pt-^gJ%o5bORbfClB<arH-7#9TORTTX6dhL=-oI!z#4e6@fBAocJta-)V
z;D~0EEZw683V{JEq$ZEtn9DQ2oi6H3f;`v&$zu-S2JI$IB{O7$>6Y$d!zkn>7++DQ
z+clSappGgex!9bNQxW<tQ3TCL?;B_vV;k2UEn0WX{s9g3)H>h4d<O=`>ArR+&~%4q
z<@Oe_p=QaNh(m8<HIx;@&n*TN7n>7qzgvq54J*HQ8Y*<-)zHiL>eEf0-^)cxxrgo-
zbI!`=EeI`VaOVC>yjINte$J&fS3Qoz*V!)(Q^PO3Poq!<aiOJ0VJG#&f2I%KpG>22
zpFQo_K0XAQ9o49A3$u$RG+zkmC^cVgEVodh`OtGk9k9y@O1UzS4O2XOB-^=$`MAVw
iScY{-^n4#HheC#OfJ%p^7^8(BEpLy_)U)n!Ie!9ej}L4B
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..2a1774ff98a51d11cef6932d315261eec239ed3c
GIT binary patch
literal 3034
zc$}S92~bnX77c`5b`WIK7(i4Y$xA{=LL!ooC`%9tYFK0vLVze)2w_tP2p|I}D1!(h
zD5!wwh-^btL>3276hu(*%RY(=vIr>XWJZ6OFV@trsi|MT>%G_Ax6e6!`}Vz6FT>kw
zo0f*D1_%Vwa@+3eBku|Fm!YO2|5lzlu|?jQh$##)T@WgcWr;W-mk>cP2ja$Kg>ig1
ztdRJ~yBs+K9M1J+h#53bJX^qnv6eBgIGzx++z8HbLKb^JM+^z(gmL*q=xk#%6v7Q5
zLiae(5Hul~6VBa!K*XUR@bYCJ*w4m=K%KWh2yuA10FNVPLE?B3{3v`J5&EYtUOrwn
z!=aErA>#c+=zpAI(7YjJfrtZffT8T!2mpX!Ffah^fWZKE5F`RX!V&TZV-KM54j4Sr
z5%RS`<-3VOLh(MX)USKVXGCbYSS-ZD;jyu?uvipKAPR#6I2>+S1BtYkBkZH%`C?X_
zJwM8FMZuL5#TIdeVy=J>S)Q|k1<_(66uNQ*o{&cSCd`le8Yp?l;BhP=9DpI<JRW=n
z9VPbRg#I%+$~Ruff%|Zx1kob4{60c0|FYFTQ<s5qZ}2-rT=}K2B3uRRXdZ_zc5@{{
z<twldZU~-=b)*7-BO2j|L}0K0fJI<YR1y;Bf+JIqNEEQ5@poJo41h&Dpb#V~4h;Yl
z07u4Qu&z`r)&=EA!BUYcTsMA{n8jyvR=C`6TqN}$xp=aO!x9Tbz5+qSN(Oj`3&et`
zaDfm)reh!*X)HFEziimFd_iA*<%qa3oDix=z=Ql5VLbP5JOErV7>o;w0#N^QatsxX
z1yGJu91;!v$_@E{q6U{c1OKmdSux3TaC!JG`Q?*u<-_62Yepn5j*jH1+aQpdnwzVO
zZ``w~qWB2IUFMym=1vFij~JJE_&wv79_|yJ)lk5>r@N!K8=}<!l?S?H?~Kef!O#t#
zUDSY$>X{{a$>Y`Pb6a&01xagW?%k;=D;qx3I5<6Xf1zpm{(OvoNw0nJl?9KWQ2eV|
zRP(6QtvZ3b#Odh?AEWoF7KA*Z?F@a8y!1xwq_y_k-RgBWk#BNn`(OU_dP?DaJrMhB
ze5vnLTJ*T;?=yY1I~OVrHp5I?Xq$8x0Ws?|*M5;w(WNp9GTvF-Jp!gy$J8^wOKi9n
z@=&w0A*m@dw)S!Fn`%$3kHkH;$9#(^+VdA(QPHD8a->l`!Y%>o{jM+Yfs`^swb?P8
zY8Rn!b1g`EZ;LIwGkURt?Rd51x#y|mnbl0C{iIb1pO3oS8aUH698}alG)mf)VW|6~
z%uiQ&1DFy&yy)ju@yCnS=MDqCq3jKPvQn@m!_b*oOnmstZ>}iuZS~O0LuOg5{(v2t
zJPa}-@#=X}g`)*N=2C+S?lO5v&~3_8x=dard&*inIBBgMkoJm__N-uYjtb8ryA0&o
ztEbdGxp1fo2S^4J=SdgUah{gzp84t=WzIPilU4pjJ9}$q?e(E`X46bTI{N7FoVn%|
zuwFPuRGv)OLm{82Bt(_1&n!y2bL`qaiJqOZ&?y8ZJljlfh`ivuc#&>wXc9L&^-Hh$
z>cfPq(igHJddm8m`S}kol|+Q>LwdfdcC81n7Bs<L)M6d*X->n~*f7#!`qIv=O6J2F
z_C_hTh+g9OFYWKnOnRT7_H-V1KDRGv;?A#<_J*IIKk?eA|LUODuH(w%vL5}R<hO4&
z*86`f8Yhc7%&}{q4I5@h`NS$Wt{R%Y^+W1#?SY}LjFd`B5ZPfSY&<2%U?5i2%y8Ss
z!45&7U&F}0mqN?eCubfXBzx$`^k1sESDs&YFY4pIoD{9<#_Wd|Wql|h9JN3>pEhwI
z5$pZo2!upHWQg0PM=Q|kjS20q57$xOjx5bN98W3b-yTWJ23zKXVor17;v=gf2P9_A
z&n0eqsB9DE4XlAC-2B}2=UQhq>mMm<KMB=5=_vr)DCQ628|p761}~M4o!u+x*@(DN
zpembxSUdk_VZ)r+?~DHa@X)oG39HE`N6nRB`5Y0mq@sNObvJz}xn~U`6P8vs5)_C}
zXhjd^f6DeR)*B&J6FY2irj+0mMZT1G1Kt@w{)+uLe^#YfZ|ubV0Pn!xNQW0rlfsHy
z)%HUk->#NgW|e56Cq6v2Ez*`{G-hP+!3M~y?<Q<y-|u;GNm|%KOIKZ`)6Yon7~W9W
z^XAo0WAO{?wtcy^>+sn7JEP$pNpz$j^p@Zg>bleM^61mK$l39>au+j`o`F%^DlK{f
zF#+a#)zC~w)9&8QOt&o$x(<Vzw-sUr+?DBt4UV2hW(0k+6cudPfV4L+>@(NXz)VL;
z4$a^M$tJBO(`C0#lI#{X>Z&&Jrh~zo>_(Wd_Xk5&-ljI?S6R1H6^~@eRH!y%OZ7da
z%GwFTm&wP=vrdkWuhkk%^4Hw6i7?af?!ZCj@v!+%mutQs*x&Xv_9sfaOrhh`lxgp=
z0RaOz)UTEpL2A5zMB(RCb{M;xmEXCwI8ENE>}dKx1By;v(@WW_;MGMqeTv=8a1i}b
z(ALmdWOp+D%GN6<Q$zi0+PZAvJtjA1h26($Fs(^3lo{oszWVRJ$G&7+Exf#*TZmD7
z#CNNa)Yo?h!`AGbyf^qEK<I2_<{nN}IMRJ{?n>({&DN1H>(J2b)opY;_;yPJt7az>
zdrUfm3yjs}X&XdrB6{j2qO3>8`Yx2OJ`K5pyp1=P1x=~Lauf?Yw%eL+J_KTuh*x3Y
z!Un0PEZgKqfuz4Q*KA|uofh-gPUX1;B}2iv<K<=G-}DhSz{3#t+=uOY154|fM7;?s
zTMyTQ97|0D-4^WqeLnXg6h>92daZW9RrQ+H65XDe-e47InNybVQl3$pqHbZGQyYnK
zqSHjv?}xk=x9}Ph%C#+xlJ><UK*^X=E;g<2JqjJ#%85-qO>ferA!{>pc8e_1N`FtS
zl|IyneF3GL>VkDalt=DIAaYuEU{~qHmo_w0ivfO;<nTXr*8*Cqb&^_T3VegDgq(Kg
z{NPdGc2g2vXF{wN7?BOu2<3*<%!ZN2e8M7%sc~;{)e8|8>5d&B>kvJM#nrMyFeUwf
z2PqcC7Ac7)`8MarD;swEYIsNHHMXW3|BzhaG0aRlb60z;AgQ)aJ8<-n=@h|l)o0S_
zN$=J#o~7#bJ1n#B8uV>vs%}2q*SC+EMC$}uZa)h;-{I-?i?S|n_15!BjALCK?kUC4
z3<F^+ZT06sYb(Jv<C2|vWvb^xnNyBux{@VkRw^#R?lhRSgu@_EbQ14MoQ3J`9|$Ua
zVI!BcjNB8X?pr#o(oz-i>IxY)7gF=qr9-Y<jxK@fx8yi&wZZxQs&o^8S*%fzI_v0O
zFsM^tEH+W9>hyEXC$#mlJ$7WIw%bH1Rh!cNt!nAnB8I}y`nGfR^s0(;Vg->#RiPwr
zSM9FNksJ#ZS9E`2{2SL|#obr3jQs5HlAetFy4#lC&E=l+@QIQtW!%`jEx@YZ#CYO`
zM{RGWHSX>1thV%{Xy5nEl?ertAr~tH_t?H3ZpqUCe)e*CYW(QxVh0&~a@tuz1+@Ot
VnLvWU!kXp3Z8wUSYZZx^{BQTt{73)*
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..751eb898b136ab9814248a83df833d43f0e778dc
GIT binary patch
literal 1850
zc$}S8X;c$e6pn%lh@iB9sMRsJp=6mXlLcZ7SukiKhNvhO7?KH@Viq$a38;Xm6bmZW
z9npddl&XkYL_uT~mzsK9QE|iCQbh$7*F&Wf3)a))@kig8nfLB}-*@kQ_uYGDRk$*A
zklQdf5{WcOK2@S3=8?o3=+d9~TGCydiOCO_M&c1B9d3m!2uY+h#UX&)0LLRL1lA@k
zJc9(2NKSfG9f?OOrt>u>0~K~)s5XO{<QTz1n;F(5AUF_*#G^(5xxKQQ44_&8c@A4a
zSD3|!9-W$OK_ZfsYE5#2hNmS9Cj-GYK4HLs;4ok_EHGkxn}Gb@E}vLC)HE{i9)c$b
z$o~WtsR#$eCJO?vsZ5H74uSv#Q9%|Pg1|t4K?fN$I`Kdhki}<1d<F;T8DzqnMXTeh
zB(fe~gd`yAaoo(O(X3W0)ykxrEb%mu$KyF{Fc=g9LBW!YIBcUBG5=l*5(Lv&P&1C2
zjDSOi<4lWi0h!!;1cO<j_+Z$G^(2Z&8O;WpX&{wOGZ<*SXbe{&y3eCAb&?sOsSwPx
z$f6<cL+AgItIty%Kq4Cc3=2wJ3cNsK(kwC{MqDltkcl0t7S-})T#gI`IV?JdL5H{?
z$fa|cvJeJO#1l&y3?|rX<5OG_1Txu>h!-N`u|QA?^29udE0J-zA|^-5l`(p`awCSr
zMh()-MgQe;Kg;EdEeMR8ENYW!L2m_w>rJ=`)0@nII06DDC}0h0bSMHG7t|9gVnGuT
zt;}LF0Pi!*M?Vn(D1jhI#FT=vk4_HBSX_|Fk?|NTat~Mgf3ij+f}#DVTzXYR4LX(|
zik}cZv=3q=dd5OD2agesIC@Sl5vgrA9&K)(_T|i>HPu_IDy>c7QO$|Se)jcQGr{`o
z5TDVVqJq=v&VnWSNd>BqOe!ue9pju;qpHs@dbd3PRCIFj0N09QL))#{3vb=Rat|+-
zWl-#MLt}1uPS*X(yYnWcHE8qJ_R^d@t&95S*z9ErFE`)Zu&|ZL!MbsMkp2~(?6RxJ
zqJ`B-_k#n*JH?+2Sxoi0GV*zip(w?D)*lBFCs)kBxy3!t+o|fp6JGN1`OW30==MJ^
zjNh<pTkUOzeS77Jx?u-9>}iyS2OBq~Uwm7iF+TBm_Vm?-^m6HxGXg_~Utvi|Q|jaF
z$}sn?m{|XVPq*V=>GwgNLFW#KvE3T-@zlNn*z$E8wcjW!tHLed=27p`H4#X{c4m25
z<Fh(+>!reFqnK%4o&)q|QfuLPbX(OXIBv$<3-5N;ezSA@agVm^H_i=dEs<vVr0f(H
zEFAq}UWb2t<IdtLDz>5Xx22hVCY{z-4cPA!Q?+P<aMBh{Y}W|Zp_a?w;C_Pm*0b)q
z^(j|=ue^j_er8WYv`fEx6@`DTcv;Z5O|?TL%WqLUR>y@tl2`Awzl5#P6`S@#GppOu
z&lJ+z?N^JRyqSMK_=xvfIkYNrgx4$h?jyNyE#>~PRO6k9s7*>~m(lsimd=UN)S|`t
zr+p@JemN=rqUGevsmPtN)&r{AvtDcc>QjNEvc%n$yUXkR45wpHts6nBpFOtj;g;ge
zjY&a`Yj&J?Q8Mset2wu8%<Gl$Z*w0vO>^HnNY*_@*3vJsUx3zUxVOvM?72lFp`gN`
z4B@K|ie*??9oW6c&NbHQ5fA?yRblB&@BXLiLWa+=O-YJWTJz@FfgH;DIQNTL3z9q%
zu9dYrC1o9AJ!D<e)jpki={07*n8|MTXaq~g4cV9W*f+xx*}~Jo@he)^b}0Ll=V5zl
z0?clCeT!<k{fD}i#5LzQH*|G-cL`jc*V5^#`c=Yvuc8L)R=!x0oHamLGwq4zt?zez
z%L-`yLAx);cQp6)kZ9LNFQ@gsow~lav0-=H8@vwf%A=b3$~#RpyF0`=DD^^c_Bwsx
z88)`#lB@Es4ZcpH69T8K_HC-1H!c8v$eh9(0yl{GxiRUxqkhU<)jb#qboC$CRvp$P
sI*Te-g#OsrG*okrBY8kdl%x!#liu0<J<_IMx$XFy$)!q3Nl0w^-v-y!SpWb4
--- a/mobile/android/base/resources/layout/doorhanger.xml
+++ b/mobile/android/base/resources/layout/doorhanger.xml
@@ -19,11 +19,12 @@
               android:layout_height="wrap_content"
               android:checked="true"
               android:visibility="gone"/>
 
     <LinearLayout android:id="@+id/doorhanger_choices"
                   style="@android:style/ButtonBar"
                   android:layout_width="fill_parent"
                   android:layout_height="wrap_content"
-                  android:orientation="horizontal"/>
+                  android:orientation="horizontal"
+                  android:visibility="gone"/>
 
 </merge>
--- a/mobile/android/base/resources/layout/text_selection_handles.xml.in
+++ b/mobile/android/base/resources/layout/text_selection_handles.xml.in
@@ -7,17 +7,24 @@
 <merge xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:gecko="http://schemas.android.com/apk/res/@ANDROID_PACKAGE_NAME@">
 
    <org.mozilla.gecko.TextSelectionHandle android:id="@+id/start_handle"
                                           android:layout_width="@dimen/text_selection_handle_width"
                                           android:layout_height="@dimen/text_selection_handle_height"
                                           android:src="@drawable/handle_start"
                                           android:visibility="gone"
-                                          gecko:handleType="START"/>
+                                          gecko:handleType="start"/>
+
+   <org.mozilla.gecko.TextSelectionHandle android:id="@+id/middle_handle"
+                                          android:layout_width="@dimen/text_selection_handle_width"
+                                          android:layout_height="@dimen/text_selection_handle_height"
+                                          android:src="@drawable/handle_middle"
+                                          android:visibility="gone"
+                                          gecko:handleType="middle"/>
 
    <org.mozilla.gecko.TextSelectionHandle android:id="@+id/end_handle"
                                           android:layout_width="@dimen/text_selection_handle_width"
                                           android:layout_height="@dimen/text_selection_handle_height"
                                           android:src="@drawable/handle_end"
                                           android:visibility="gone"
-                                          gecko:handleType="END"/>
+                                          gecko:handleType="end"/>
 </merge>
--- a/mobile/android/base/resources/values-v11/themes.xml
+++ b/mobile/android/base/resources/values-v11/themes.xml
@@ -38,21 +38,16 @@
         <item name="android:windowNoTitle">true</item>
     </style>
     
     <style name="Gecko.Translucent" parent="@android:style/Theme.Translucent">
         <item name="android:windowActionBar">true</item>
         <item name="android:windowNoTitle">false</item>
     </style>
 
-    <style name="Gecko.Translucent.NoActionBar">
-        <item name="android:windowActionBar">false</item>
-        <item name="android:windowNoTitle">true</item>
-    </style>
-
     <style name="Gecko.App">
         <item name="android:windowBackground">@drawable/abouthome_bg_repeat</item>
         <item name="android:panelBackground">@drawable/menu_panel_bg</item>
         <item name="android:listViewStyle">@style/GeckoList</item>
     </style>
 
     <style name="Gecko.Light.AwesomeBar">
         <item name="android:actionBarStyle">@style/ActionBar.AwesomeBar</item>
--- a/mobile/android/base/resources/values/attrs.xml
+++ b/mobile/android/base/resources/values/attrs.xml
@@ -45,13 +45,17 @@
         <attr name="cropped" format="boolean"/>
     </declare-styleable>
 
     <declare-styleable name="TabsPanel">
         <attr name="sidebar" format="boolean"/>
     </declare-styleable>
 
     <declare-styleable name="TextSelectionHandle">
-        <attr name="handleType" format="string"/>
+        <attr name="handleType">
+            <flag name="start" value="0x01" />
+            <flag name="middle" value="0x02" />
+            <flag name="end" value="0x03" />
+        </attr>
     </declare-styleable>
 
 </resources>
 
--- a/mobile/android/base/resources/values/themes.xml
+++ b/mobile/android/base/resources/values/themes.xml
@@ -31,21 +31,19 @@
     </style>
 
     <style name="Gecko.Light.NoActionBar" parent="Gecko.Light"/>
     
     <style name="Gecko.Translucent" parent="@android:style/Theme.Translucent">
         <item name="android:windowNoTitle">true</item>
     </style>
 
-    <style name="Gecko.Translucent.NoActionBar"  parent="Gecko.Translucent"/>
-
     <style name="Gecko.App">
         <item name="android:windowBackground">@drawable/abouthome_bg_repeat</item>
     </style>
-    
+
     <style name="Gecko.Light.AwesomeBar"/>
     
     <style name="Gecko.TitleBar.Preferences"/>
     
     <style name="Gecko.Translucent.TabsTray"/>
 
 </resources>
--- a/mobile/android/chrome/content/blockedSite.xhtml
+++ b/mobile/android/chrome/content/blockedSite.xhtml
@@ -114,32 +114,29 @@
         el.parentNode.removeChild(el);
 
         el = document.getElementById("errorShortDescText_malware");
         el.parentNode.removeChild(el);
 
         el = document.getElementById("errorLongDescText_malware");
         el.parentNode.removeChild(el);
 
-        // Set sitename
-        document.getElementById("phishing_sitename").textContent = getHostString();
         document.title = document.getElementById("errorTitleText_phishing")
                                  .innerHTML;
       }
     ]]></script>
     <style type="text/css">
       /* Style warning button to look like a small text link in the
          bottom right. This is preferable to just using a text link
          since there is already a mechanism in browser.js for trapping
          oncommand events from unprivileged chrome pages (BrowserOnCommand).*/
       #ignoreWarningButton {
         -moz-appearance: none;
         background: transparent;
         border: none;
-        color: white;  /* Hard coded because netError.css forces this page's background to dark red */
         text-decoration: underline;
         margin: 0;
         padding: 0;
         position: relative;
         top: 23px;
         left: 20px;
         font-size: smaller;
       }
@@ -176,16 +173,19 @@
         
         <!-- Action buttons -->
         <div id="buttons">
           <!-- Commands handled in browser.js -->
           <button id="getMeOutButton">&safeb.palm.accept.label;</button>
           <button id="reportButton">&safeb.palm.reportPage.label;</button>
         </div>
       </div>
+      <div id="ignoreWarning">
+        <button id="ignoreWarningButton">&safeb.palm.decline.label;</button>
+      </div>
     </div>
     <!--
     - Note: It is important to run the script this way, instead of using
     - an onload handler. This is because error pages are loaded as
     - LOAD_BACKGROUND, which means that onload handlers will not be executed.
     -->
     <script type="application/javascript">initPage();</script>
   </body>
--- a/mobile/android/chrome/content/browser.js
+++ b/mobile/android/chrome/content/browser.js
@@ -27,16 +27,24 @@ XPCOMUtils.defineLazyGetter(this, "Debug
   return DebuggerServer;
 });
 
 XPCOMUtils.defineLazyGetter(this, "NetUtil", function() {
   Cu.import("resource://gre/modules/NetUtil.jsm");
   return NetUtil;
 });
 
+#ifdef MOZ_SAFE_BROWSING
+XPCOMUtils.defineLazyGetter(this, "SafeBrowsing", function() {
+  let tmp = {};
+ Cu.import("resource://gre/modules/SafeBrowsing.jsm", tmp);
+  return tmp.SafeBrowsing;
+});
+#endif
+
 // Lazily-loaded browser scripts:
 [
   ["HelperApps", "chrome://browser/content/HelperApps.js"],
   ["SelectHelper", "chrome://browser/content/SelectHelper.js"],
   ["InputWidgetHelper", "chrome://browser/content/InputWidgetHelper.js"],
   ["AboutReader", "chrome://browser/content/aboutReader.js"],
   ["WebAppRT", "chrome://browser/content/WebAppRT.js"],
 ].forEach(function (aScript) {
@@ -339,16 +347,21 @@ var BrowserApp = {
 
     // after gecko has loaded, set the checkerboarding pref once at startup (for testing only)
     sendMessageToJava({
       gecko: {
         "type": "Checkerboard:Toggle",
         "value": Services.prefs.getBoolPref("gfx.show_checkerboard_pattern")
       }
     });
+
+#ifdef MOZ_SAFE_BROWSING
+    // Bug 778855 - Perf regression if we do this here. To be addressed in bug 779008.
+    setTimeout(function() { SafeBrowsing.init(); }, 2000);
+#endif
   },
 
   isAppUpdated: function() {
     let savedmstone = null;
     try {
       savedmstone = Services.prefs.getCharPref("browser.startup.homepage_override.mstone");
     } catch (e) {
     }
@@ -1624,22 +1637,27 @@ var NativeWindow = {
     _stripScheme: function(aString) {
       return aString.slice(aString.indexOf(":") + 1);
     }
   }
 };
 
 var SelectionHandler = {
   HANDLE_TYPE_START: "START",
+  HANDLE_TYPE_MIDDLE: "MIDDLE",
   HANDLE_TYPE_END: "END",
 
+  TYPE_NONE: 0,
+  TYPE_CURSOR: 1,
+  TYPE_SELECTION: 2,
+
   // Keeps track of data about the dimensions of the selection. Coordinates
   // stored here are relative to the _view window.
   cache: null,
-  _active: false,
+  _activeType: this.TYPE_NONE,
 
   // The window that holds the selection (can be a sub-frame)
   get _view() {
     if (this._viewRef)
       return this._viewRef.get();
     return null;
   },
 
@@ -1679,72 +1697,88 @@ var SelectionHandler = {
     Services.obs.removeObserver(this, "Window:Resize");
     Services.obs.removeObserver(this, "Tab:Selected");
     Services.obs.removeObserver(this, "after-viewport-change");
     Services.obs.removeObserver(this, "TextSelection:Move");
     Services.obs.removeObserver(this, "TextSelection:Position");
   },
 
   observe: function sh_observe(aSubject, aTopic, aData) {
-    if (!this._active)
-      return;
-
     switch (aTopic) {
       case "Gesture:SingleTap": {
-        let data = JSON.parse(aData);
-        this.endSelection(data.x, data.y);
+        if (this._activeType == this.TYPE_SELECTION) {
+          let data = JSON.parse(aData);
+          this.endSelection(data.x, data.y);
+        }
         break;
       }
       case "Tab:Selected":
       case "Window:Resize": {
-        // Knowing when the page is done drawing is hard, so let's just cancel
-        // the selection when the window changes. We should fix this later.
-        this.endSelection();
+        if (this._activeType == this.TYPE_SELECTION) {
+          // Knowing when the page is done drawing is hard, so let's just cancel
+          // the selection when the window changes. We should fix this later.
+          this.endSelection();
+        }
         break;
       }
       case "after-viewport-change": {
-        // Update the cache after the viewport changes (e.g. panning, zooming).
-        this.updateCacheForSelection();
+        if (this._activeType == this.TYPE_SELECTION) {
+          // Update the cache after the viewport changes (e.g. panning, zooming).
+          this.updateCacheForSelection();
+        }
         break;
       }
       case "TextSelection:Move": {
         let data = JSON.parse(aData);
-        this.moveSelection(data.handleType == this.HANDLE_TYPE_START, data.x, data.y);
+        if (this._activeType == this.TYPE_SELECTION)
+          this.moveSelection(data.handleType == this.HANDLE_TYPE_START, data.x, data.y);
+        else if (this._activeType == this.TYPE_CURSOR)
+          this._sendMouseEvents(data.x, data.y);
         break;
       }
       case "TextSelection:Position": {
-        let data = JSON.parse(aData);
-
-        // Reverse the handles if necessary.
-        let selectionReversed = this.updateCacheForSelection(data.handleType == this.HANDLE_TYPE_START);
-        if (selectionReversed) {
-          // Re-send mouse events to update the selection corresponding to the new handles.
-          if (this._isRTL) {
-            this._sendMouseEvents(this.cache.end.x, this.cache.end.y, false);
-            this._sendMouseEvents(this.cache.start.x, this.cache.start.y, true);
-          } else {
-            this._sendMouseEvents(this.cache.start.x, this.cache.start.y, false);
-            this._sendMouseEvents(this.cache.end.x, this.cache.end.y, true);
+        if (this._activeType == this.TYPE_SELECTION) {
+          let data = JSON.parse(aData);
+
+          // Reverse the handles if necessary.
+          let selectionReversed = this.updateCacheForSelection(data.handleType == this.HANDLE_TYPE_START);
+          if (selectionReversed) {
+            // Re-send mouse events to update the selection corresponding to the new handles.
+            if (this._isRTL) {
+              this._sendMouseEvents(this.cache.end.x, this.cache.end.y, false);
+              this._sendMouseEvents(this.cache.start.x, this.cache.start.y, true);
+            } else {
+              this._sendMouseEvents(this.cache.start.x, this.cache.start.y, false);
+              this._sendMouseEvents(this.cache.end.x, this.cache.end.y, true);
+            }
           }
+
+          // Position the handles to align with the edges of the selection.
+          this.positionHandles();
+        } else if (this._activeType == this.TYPE_CURSOR) {
+          this.positionHandles();
         }
-
-        // Position the handles to align with the edges of the selection.
-        this.positionHandles();
         break;
       }
     }
   },
 
   handleEvent: function sh_handleEvent(aEvent) {
-    if (!this._active)
-      return;
-
     switch (aEvent.type) {
       case "pagehide":
-        this.endSelection();
+        if (this._activeType == this.TYPE_SELECTION)
+          this.endSelection();
+        else
+          this.hideThumb();
+        break;
+
+      case "keydown":
+      case "blur":
+        if (this._activeType == this.TYPE_CURSOR)
+          this.hideThumb();
         break;
     }
   },
 
   _ignoreCollapsedSelection: false,
 
   notifySelectionChanged: function sh_notifySelectionChanged(aDoc, aSel, aReason) {
     if (aSel.isCollapsed) {
@@ -1772,18 +1806,22 @@ var SelectionHandler = {
              aElement instanceof Ci.nsIDOMHTMLEmbedElement ||
              aElement instanceof Ci.nsIDOMHTMLImageElement ||
              aElement instanceof Ci.nsIDOMHTMLMediaElement);
   },
 
   // aX/aY are in top-level window browser coordinates
   startSelection: function sh_startSelection(aElement, aX, aY) {
     // Clear out any existing selection
-    if (this._active)
+    if (this._activeType == this.TYPE_SELECTION) {
       this.endSelection();
+    } else if (this._activeType == this.TYPE_CURSOR) {
+      // Hide the cursor handles.
+      this.hideThumb();
+    }
 
     // Get the element's view
     this._view = aElement.ownerDocument.defaultView;
 
     if (aElement instanceof Ci.nsIDOMNSEditableElement)
       this._target = aElement;
     else
       this._target = this._view;
@@ -1822,18 +1860,25 @@ var SelectionHandler = {
 
     // Add a listener to end the selection if it's removed programatically
     selection.QueryInterface(Ci.nsISelectionPrivate).addSelectionListener(this);
 
     // Initialize the cache
     this.cache = { start: {}, end: {}};
     this.updateCacheForSelection();
 
-    this.showHandles();
-    this._active = true;
+    this._activeType = this.TYPE_SELECTION;
+    this.positionHandles();
+
+    sendMessageToJava({
+      gecko: {
+        type: "TextSelection:ShowHandles",
+        handles: [this.HANDLE_TYPE_START, this.HANDLE_TYPE_END]
+      }
+    });
 
     if (aElement instanceof Ci.nsIDOMNSEditableElement)
       aElement.focus();
   },
 
   getSelection: function sh_getSelection() {
     if (this._target instanceof Ci.nsIDOMNSEditableElement)
       return this._target.QueryInterface(Ci.nsIDOMNSEditableElement).editor.selection;
@@ -1849,21 +1894,21 @@ var SelectionHandler = {
                           getInterface(Ci.nsIWebNavigation).
                           QueryInterface(Ci.nsIInterfaceRequestor).
                           getInterface(Ci.nsISelectionDisplay).
                           QueryInterface(Ci.nsISelectionController);
   },
 
   // Used by the contextmenu "matches" functions in ClipboardHelper
   shouldShowContextMenu: function sh_shouldShowContextMenu(aX, aY) {
-    return this._active && this._pointInSelection(aX, aY);
+    return (this._activeType == this.TYPE_SELECTION) && this._pointInSelection(aX, aY);
   },
 
   selectAll: function sh_selectAll(aElement, aX, aY) {
-    if (!this._active)
+    if (this._activeType != this.TYPE_SELECTION)
       this.startSelection(aElement, aX, aY);
 
     let selectionController = this.getSelectionController();
     selectionController.selectAll();
     this.updateCacheForSelection();
     this.positionHandles();
   },
 
@@ -1901,21 +1946,27 @@ var SelectionHandler = {
   _sendMouseEvents: function sh_sendMouseEvents(aX, aY, useShift) {
     // Send mouse event 1px too high to prevent selection from entering the line below where it should be
     this._cwu.sendMouseEventToWindow("mousedown", aX, aY - 1, 0, 0, useShift ? Ci.nsIDOMNSEvent.SHIFT_MASK : 0, true);
     this._cwu.sendMouseEventToWindow("mouseup", aX, aY - 1, 0, 0, useShift ? Ci.nsIDOMNSEvent.SHIFT_MASK : 0, true);
   },
 
   // aX/aY are in top-level window browser coordinates
   endSelection: function sh_endSelection(aX, aY) {
-    if (!this._active)
+    if (this._activeType != this.TYPE_SELECTION)
       return "";
-
-    this._active = false;
-    this.hideHandles();
+ 
+    this._activeType = this.TYPE_NONE;
+    sendMessageToJava({
+      gecko: {
+        type: "TextSelection:HideHandles",
+        handles: [this.HANDLE_TYPE_START, this.HANDLE_TYPE_END]
+      }
+    });
+
 
     let selectedText = "";
     let pointInSelection = false;
     if (this._view) {
       let selection = this.getSelection();
       if (selection) {
         // Get the text before we clear the selection!
         selectedText = selection.toString().trim();
@@ -1942,16 +1993,19 @@ var SelectionHandler = {
 
     this._cleanUp();
 
     return selectedText;
   },
 
   _cleanUp: function sh_cleanUp() {
     this._view.removeEventListener("pagehide", this, false);
+    this._view.removeEventListener("keydown", this, false);
+    this._view.removeEventListener("blur", this, true);
+    this._activeType = this.TYPE_NONE;
     this._view = null;
     this._target = null;
     this._isRTL = false;
     this.cache = null;
   },
 
   _getViewOffset: function sh_getViewOffset() {
     let offset = { x: 0, y: 0 };
@@ -1995,54 +2049,82 @@ var SelectionHandler = {
     }
 
     this.cache.start = start;
     this.cache.end = end;
 
     return selectionReversed;
   },
 
+  showThumb: function sh_showThumb(aElement) {
+    if (!aElement)
+      return;
+
+    // Get the element's view
+    this._view = aElement.ownerDocument.defaultView;
+    this._target = aElement;
+
+    this._view.addEventListener("pagehide", this, false);
+    this._view.addEventListener("keydown", this, false);
+    this._view.addEventListener("blur", this, true);
+
+    this._activeType = this.TYPE_CURSOR;
+    this.positionHandles();
+
+    sendMessageToJava({
+      gecko: {
+        type: "TextSelection:ShowHandles",
+        handles: [this.HANDLE_TYPE_MIDDLE]
+      }
+    });
+  },
+
+  hideThumb: function sh_hideThumb() {
+    this._activeType = this.TYPE_NONE;
+    this._cleanUp();
+
+    sendMessageToJava({
+      gecko: {
+        type: "TextSelection:HideHandles",
+        handles: [this.HANDLE_TYPE_MIDDLE]
+      }
+    });
+  },
+
   positionHandles: function sh_positionHandles() {
     // Translate coordinates to account for selections in sub-frames. We can't cache
     // this because the top-level page may have scrolled since selection started.
     let offset = this._getViewOffset();
     let scrollX = {}, scrollY = {};
     this._view.top.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils).getScrollXY(false, scrollX, scrollY);
 
+    let positions = null;
+    if (this._activeType == this.TYPE_CURSOR) {
+      let cursor = this._cwu.sendQueryContentEvent(this._cwu.QUERY_CARET_RECT, this._target.selectionEnd, 0, 0, 0);
+      positions = [ { handle: this.HANDLE_TYPE_MIDDLE,
+                     left: cursor.left + offset.x + scrollX.value,
+                     top: cursor.top + cursor.height + offset.y + scrollY.value } ];
+    } else {
+      positions = [ { handle: this.HANDLE_TYPE_START,
+                     left: this.cache.start.x + offset.x + scrollX.value,
+                     top: this.cache.start.y + offset.y + scrollY.value },
+                   { handle: this.HANDLE_TYPE_END,
+                     left: this.cache.end.x + offset.x + scrollX.value,
+                     top: this.cache.end.y + offset.y + scrollY.value } ];
+    }
+
     sendMessageToJava({
       gecko: {
         type: "TextSelection:PositionHandles",
-        startLeft: this.cache.start.x + offset.x + scrollX.value,
-        startTop: this.cache.start.y + offset.y + scrollY.value,
-        endLeft: this.cache.end.x + offset.x + scrollX.value,
-        endTop: this.cache.end.y + offset.y + scrollY.value
-      }
-    });
-  },
-
-  showHandles: function sh_showHandles() {
-    this.positionHandles();
-
-    sendMessageToJava({
-      gecko: {
-        type: "TextSelection:ShowHandles"
-      }
-    });
-  },
-
-  hideHandles: function sh_hideHandles() {
-    sendMessageToJava({
-      gecko: {
-        type: "TextSelection:HideHandles"
+        positions: positions
       }
     });
   }
 };
 
-
 var UserAgent = {
   DESKTOP_UA: null,
 
   init: function ua_init() {
     Services.obs.addObserver(this, "DesktopMode:Change", false);
     Services.obs.addObserver(this, "http-on-modify-request", false);
 
     // See https://developer.mozilla.org/en/Gecko_user_agent_string_reference
@@ -3144,17 +3226,17 @@ Tab.prototype = {
     }
 
     let message = {
       gecko: {
         type: "Content:LocationChange",
         tabID: this.id,
         uri: fixedURI.spec,
         documentURI: documentURI,
-        contentType: contentType,
+        contentType: (contentType ? contentType : ""),
         sameDocument: sameDocument
       }
     };
 
     sendMessageToJava(message);
 
     if (!sameDocument) {
       // XXX This code assumes that this is the earliest hook we have at which
@@ -3602,16 +3684,20 @@ var BrowserEventHandler = {
             [data.x, data.y] = this._moveClickPoint(element, data.x, data.y);
             element = ElementTouchHelper.anyElementFromPoint(data.x, data.y);
             isClickable = ElementTouchHelper.isElementClickable(element);
           }
 
           this._sendMouseEvent("mousemove", element, data.x, data.y);
           this._sendMouseEvent("mousedown", element, data.x, data.y);
           this._sendMouseEvent("mouseup",   element, data.x, data.y);
+
+          // See if its a input element
+          if ((element instanceof HTMLInputElement && element.mozIsTextField(false)) || (element instanceof HTMLTextAreaElement))
+             SelectionHandler.showThumb(element);
   
           if (isClickable)
             Haptic.performSimpleAction(Haptic.LongPress);
         } catch(e) {
           Cu.reportError(e);
         }
       }
       this._cancelTapHighlight();
@@ -4135,20 +4221,69 @@ var ErrorPageEventHandler = {
                 sslExceptions.addTemporaryException(uri);
             } catch (e) {
               dump("Failed to set cert exception: " + e + "\n");
             }
             errorDoc.location.reload();
           } else if (target == errorDoc.getElementById("getMeOutOfHereButton")) {
             errorDoc.location = "about:home";
           }
-        } else if (/^about:neterror\?e=netOffline/.test(ownerDoc.documentURI)) {
-          let tryAgain = errorDoc.getElementById("errorTryAgain");
-          if (target == tryAgain)
-            Services.io.offline = false;
+        } else if (/^about:blocked/.test(errorDoc.documentURI)) {
+          let secHistogram = Cc["@mozilla.org/base/telemetry;1"].getService(Ci.nsITelemetry).getHistogramById("SECURITY_UI");
+
+          // The event came from a button on a malware/phishing block page
+          // First check whether it's malware or phishing, so that we can
+          // use the right strings/links
+          let isMalware = /e=malwareBlocked/.test(errorDoc.documentURI);
+          let bucketName = isMalware ? "WARNING_MALWARE_PAGE_" : "WARNING_PHISHING_PAGE_";
+          let nsISecTel = Ci.nsISecurityUITelemetry;
+
+          let formatter = Cc["@mozilla.org/toolkit/URLFormatterService;1"].getService(Ci.nsIURLFormatter);
+
+          if (target == errorDoc.getElementById("getMeOutButton")) {
+            secHistogram.add(nsISecTel[bucketName + "GET_ME_OUT_OF_HERE"]);
+            errorDoc.location = "about:home";
+          } else if (target == errorDoc.getElementById("reportButton")) {
+            // We log even if malware/phishing info URL couldn't be found:
+            // the measurement is for how many users clicked the WHY BLOCKED button
+            secHistogram.add(nsISecTel[bucketName + "WHY_BLOCKED"]);
+
+            // This is the "Why is this site blocked" button.  For malware,
+            // we can fetch a site-specific report, for phishing, we redirect
+            // to the generic page describing phishing protection.
+            if (isMalware) {
+              // Get the stop badware "why is this blocked" report url, append the current url, and go there.
+              try {
+                let reportURL = formatter.formatURLPref("browser.safebrowsing.malware.reportURL");
+                reportURL += errorDoc.location.href;
+                BrowserApp.selectedBrowser.loadURI(reportURL);
+              } catch (e) {
+                Cu.reportError("Couldn't get malware report URL: " + e);
+              }
+            } else {
+              // It's a phishing site, not malware. (There's no report URL)
+              try {
+                let reportURL = formatter.formatURLPref("browser.safebrowsing.warning.infoURL");
+                BrowserApp.selectedBrowser.loadURI(reportURL);
+              } catch (e) {
+                Cu.reportError("Couldn't get phishing info URL: " + e);
+              }
+            }
+          } else if (target == errorDoc.getElementById("ignoreWarningButton")) {
+            secHistogram.add(nsISecTel[bucketName + "IGNORE_WARNING"]);
+
+            // Allow users to override and continue through to the site,
+            let webNav = BrowserApp.selectedBrowser.docShell.QueryInterface(Ci.nsIWebNavigation);
+            let location = BrowserApp.selectedBrowser.contentWindow.location;
+            webNav.loadURI(location, Ci.nsIWebNavigation.LOAD_FLAGS_BYPASS_CLASSIFIER, null, null, null);
+
+            // ....but add a notify bar as a reminder, so that they don't lose
+            // track after, e.g., tab switching.
+            NativeWindow.doorhanger.show(Strings.browser.GetStringFromName("safeBrowsingDoorhanger"), "safebrowsing-warning", [], BrowserApp.selectedTab.id);
+          }
         }
         break;
       }
     }
   }
 };
 
 var FindHelper = {
--- a/mobile/android/components/Makefile.in
+++ b/mobile/android/components/Makefile.in
@@ -35,12 +35,18 @@ EXTRA_COMPONENTS = \
         ContentDispatchChooser.js \
         AddonUpdateService.js \
         FormAutoComplete.js \
         LoginManagerPrompter.js \
         BlocklistPrompt.js \
         $(NULL)
 
 ifdef MOZ_SAFE_BROWSING
-EXTRA_COMPONENTS += SafeBrowsing.js
+DEFINES += \
+        -DMOZ_APP_UA_NAME=$(MOZ_APP_UA_NAME) \
+        $(NULL)
+
+EXTRA_PP_JS_MODULES = \
+        SafeBrowsing.jsm \
+        $(NULL)
 endif
 
 include $(topsrcdir)/config/rules.mk
--- a/mobile/android/components/MobileComponents.manifest
+++ b/mobile/android/components/MobileComponents.manifest
@@ -84,15 +84,8 @@ contract @mozilla.org/satchel/form-autoc
 # LoginManagerPrompter.js
 component {97d12931-abe2-11df-94e2-0800200c9a66} LoginManagerPrompter.js
 contract @mozilla.org/login-manager/prompter;1 {97d12931-abe2-11df-94e2-0800200c9a66}
 
 # BlocklistPrompt.js
 component {4e6ea350-b09a-11df-94e2-0800200c9a66} BlocklistPrompt.js
 contract @mozilla.org/addons/blocklist-prompt;1 {4e6ea350-b09a-11df-94e2-0800200c9a66}
 
-#ifdef MOZ_SAFE_BROWSING
-# SafeBrowsing.js
-component {aadaed90-6c03-42d0-924a-fc61198ff283} SafeBrowsing.js
-contract @mozilla.org/safebrowsing/application;1 {aadaed90-6c03-42d0-924a-fc61198ff283}
-category app-startup SafeBrowsing service,@mozilla.org/safebrowsing/application;1
-#endif
-
deleted file mode 100644
--- a/mobile/android/components/SafeBrowsing.js
+++ /dev/null
@@ -1,168 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-const Cc = Components.classes;
-const Ci = Components.interfaces;
-const Cu = Components.utils;
-const Cr = Components.results;
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource://gre/modules/Services.jsm");
-
-const kPhishWardenEnabledPref = "browser.safebrowsing.enabled";
-const kMalwareWardenEnabledPref = "browser.safebrowsing.malware.enabled";
-
-// This XPCOM object doesn't have a public interface. It just works quietly in the background
-function SafeBrowsing() {
-  this.listManager = null;
-
-  // Once we register tables, their respective names will be listed here.
-  this.phishing = {
-    pref: kPhishWardenEnabledPref,
-    blackTables: [],
-    whiteTables: []
-  };
-  this.malware = {
-    pref: kMalwareWardenEnabledPref,
-    blackTables: [],
-    whiteTables: []
-  };
-
-  // Get notifications when the phishing or malware warden enabled pref changes
-  Services.prefs.addObserver(kPhishWardenEnabledPref, this, true);
-  Services.prefs.addObserver(kMalwareWardenEnabledPref, this, true);
-}
-
-SafeBrowsing.prototype = {
-  classID: Components.ID("{aadaed90-6c03-42d0-924a-fc61198ff283}"),
-
-  QueryInterface: XPCOMUtils.generateQI([Ci.nsISessionStore,
-                                         Ci.nsIDOMEventListener,
-                                         Ci.nsIObserver,
-                                         Ci.nsISupportsWeakReference]),
-
-  observe: function sb_observe(aSubject, aTopic, aData) {
-    switch (aTopic) {
-      case "app-startup":
-        Services.obs.addObserver(this, "final-ui-startup", true);
-        Services.obs.addObserver(this, "xpcom-shutdown", true);
-        break;
-      case "final-ui-startup":
-        Services.obs.removeObserver(this, "final-ui-startup");
-        this._startup();
-        break;
-      case "xpcom-shutdown":
-        Services.obs.removeObserver(this, "xpcom-shutdown");
-        this._shutdown();
-        break;
-      case "nsPref:changed":
-        if (aData == kPhishWardenEnabledPref)
-          this.maybeToggleUpdateChecking(this.phishing);
-        else if (aData == kMalwareWardenEnabledPref)
-          this.maybeToggleUpdateChecking(this.malware);
-        break;
-    }
-  },
-
-  _startup: function sb_startup() {
-    this.listManager = Cc["@mozilla.org/url-classifier/listmanager;1"].getService(Ci.nsIUrlListManager);
-
-    // Add a test chunk to the database
-    let testData = "mozilla.org/firefox/its-an-attack.html";
-    let testUpdate =
-      "n:1000\ni:test-malware-simple\nad:1\n" +
-      "a:1:32:" + testData.length + "\n" +
-      testData;
-
-    testData = "mozilla.org/firefox/its-a-trap.html";
-    testUpdate +=
-      "n:1000\ni:test-phish-simple\nad:1\n" +
-      "a:1:32:" + testData.length + "\n" +
-      testData;
-
-    let dbService = Cc["@mozilla.org/url-classifier/dbservice;1"].getService(Ci.nsIUrlClassifierDBService);
-
-    let listener = {
-      QueryInterface: function(aIID) {
-        if (aIID.equals(Ci.nsISupports) || aIID.equals(Ci.nsIUrlClassifierUpdateObserver))
-          return this;
-        throw Cr.NS_ERROR_NO_INTERFACE;
-      },
-
-      updateUrlRequested: function(aURL) { },
-      streamFinished: function(aStatus) { },
-      updateError: function(aErrorCode) { },
-      updateSuccess: function(aRequestedTimeout) { }
-    };
-
-    try {
-      dbService.beginUpdate(listener, "test-malware-simple,test-phish-simple", "");
-      dbService.beginStream("", "");
-      dbService.updateStream(testUpdate);
-      dbService.finishStream();
-      dbService.finishUpdate();
-    } catch(ex) {}
-
-    this.registerBlackTable("goog-malware-shavar", this.malware);
-    this.maybeToggleUpdateChecking(this.malware);
-
-    this.registerBlackTable("goog-phish-shavar", this.phishing);
-    this.maybeToggleUpdateChecking(this.phishing);
-  },
-
-  _shutdown: function sb_shutdown() {
-    Services.prefs.removeObserver(kPhishWardenEnabledPref, this);
-    Services.prefs.removeObserver(kMalwareWardenEnabledPref, this);
-
-    this.listManager = null;
-  },
-
-  enableBlacklistTableUpdates: function sb_enableBlacklistTableUpdates(aWarden) {
-    for (let i = 0; i < aWarden.blackTables.length; ++i) {
-      this.listManager.enableUpdate(aWarden.blackTables[i]);
-    }
-  },
-
-  disableBlacklistTableUpdates: function sb_disableBlacklistTableUpdates(aWarden) {
-    for (let i = 0; i < aWarden.blackTables.length; ++i) {
-      this.listManager.disableUpdate(aWarden.blackTables[i]);
-    }
-  },
-
-  enableWhitelistTableUpdates: function sb_enableWhitelistTableUpdates(aWarden) {
-    for (let i = 0; i < this.whiteTables.length; ++i) {
-      this.listManager.enableUpdate(this.whiteTables[i]);
-    }
-  },
-
-  disableWhitelistTableUpdates: function sb_disableWhitelistTableUpdates(aWarden) {
-    for (let i = 0; i < aWarden.whiteTables.length; ++i) {
-      this.listManager.disableUpdate(aWarden.whiteTables[i]);
-    }
-  },
-
-  registerBlackTable: function sb_registerBlackTable(aTableName, aWarden) {
-    let result = this.listManager.registerTable(aTableName, false);
-    if (result)
-      aWarden.blackTables.push(aTableName);
-    return result;
-  },
-
-  registerWhiteTable: function sb_registerWhiteTable(aTableName, aWarden) {
-    let result = this.listManager.registerTable(aTableName, false);
-    if (result)
-      aWarden.whiteTables.push(aTableName);
-    return result;
-  },
-
-  maybeToggleUpdateChecking: function sb_maybeToggleUpdateChecking(aWarden) {
-    let enabled = Services.prefs.getBoolPref(aWarden.pref);
-    if (enabled)
-      this.enableBlacklistTableUpdates(aWarden);
-    else
-      this.disableBlacklistTableUpdates(aWarden);
-  }
-}
-
-const NSGetFactory = XPCOMUtils.generateNSGetFactory([SafeBrowsing]);
new file mode 100644
--- /dev/null
+++ b/mobile/android/components/SafeBrowsing.jsm
@@ -0,0 +1,182 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+var EXPORTED_SYMBOLS = ["SafeBrowsing"];
+
+const Cc = Components.classes;
+const Ci = Components.interfaces;
+const Cu = Components.utils;
+
+Cu.import("resource://gre/modules/Services.jsm");
+
+const phishingList = "goog-phish-shavar";
+const malwareList  = "goog-malware-shavar";
+
+var debug = false;
+
+function log(...stuff) {
+  if (!debug)
+    return;
+
+  let msg = "SafeBrowsing: " + stuff.join(" ");
+  Services.console.logStringMessage(msg);
+  dump(msg + "\n");
+}
+
+var SafeBrowsing = {
+
+  init: function() {
+    if (this.initialized) {
+      log("Already initialized");
+      return;
+    }
+
+    Services.prefs.addObserver("browser.safebrowsing", this.readPrefs, false);
+    this.readPrefs();
+
+    // Register our two types of tables, and add custom Mozilla entries
+    let listManager = Cc["@mozilla.org/url-classifier/listmanager;1"].
+                      getService(Ci.nsIUrlListManager);
+    listManager.registerTable(phishingList, false);
+    listManager.registerTable(malwareList, false);
+    this.addMozEntries();
+
+    this.controlUpdateChecking();
+    this.initialized = true;
+
+    log("init() finished");
+  },
+
+
+  initialized:     false,
+  phishingEnabled: false,
+  malwareEnabled:  false,
+
+  updateURL:             null,
+  keyURL:                null,
+  gethashURL:            null,
+
+  reportURL:             null,
+  reportGenericURL:      null,
+  reportErrorURL:        null,
+  reportPhishURL:        null,
+  reportMalwareURL:      null,
+  reportMalwareErrorURL: null,
+
+
+  getReportURL: function(kind) {
+    return this["report"  + kind + "URL"];
+  },
+
+
+  readPrefs: function() {
+    log("reading prefs");
+
+    debug = Services.prefs.getBoolPref("browser.safebrowsing.debug");
+    this.phishingEnabled = Services.prefs.getBoolPref("browser.safebrowsing.enabled");
+    this.malwareEnabled  = Services.prefs.getBoolPref("browser.safebrowsing.malware.enabled");
+    this.updateProviderURLs();
+
+    // XXX The listManager backend gets confused if this is called before the
+    // lists are registered. So only call it here when a pref changes, and not
+    // when doing initialization. I expect to refactor this later, so pardon the hack.
+    if (this.initialized)
+      this.controlUpdateChecking();
+  },
+
+
+  updateProviderURLs: function() {
+#ifdef USE_HISTORIC_SAFEBROWSING_ID
+    let clientID = "navclient-auto-ffox";
+#else
+#expand    let clientID = __MOZ_APP_UA_NAME__;
+#endif
+
+    log("initializing safe browsing URLs");
+    let basePref = "browser.safebrowsing.";
+
+    // Urls to HTML report pages
+    this.reportURL             = Services.urlFormatter.formatURLPref(basePref + "reportURL");
+    this.reportGenericURL      = Services.urlFormatter.formatURLPref(basePref + "reportGenericURL");
+    this.reportErrorURL        = Services.urlFormatter.formatURLPref(basePref + "reportErrorURL");
+    this.reportPhishURL        = Services.urlFormatter.formatURLPref(basePref + "reportPhishURL");
+    this.reportMalwareURL      = Services.urlFormatter.formatURLPref(basePref + "reportMalwareURL");
+    this.reportMalwareErrorURL = Services.urlFormatter.formatURLPref(basePref + "reportMalwareErrorURL");
+
+    // Urls used to update DB
+    this.updateURL  = Services.urlFormatter.formatURLPref(basePref + "updateURL");
+    this.keyURL     = Services.urlFormatter.formatURLPref(basePref + "keyURL");
+    this.gethashURL = Services.urlFormatter.formatURLPref(basePref + "gethashURL");
+
+    this.updateURL  = this.updateURL.replace("SAFEBROWSING_ID", clientID);
+    this.keyURL     = this.keyURL.replace("SAFEBROWSING_ID", clientID);
+    this.gethashURL = this.gethashURL.replace("SAFEBROWSING_ID", clientID);
+
+    let listManager = Cc["@mozilla.org/url-classifier/listmanager;1"].
+                      getService(Ci.nsIUrlListManager);
+
+    listManager.setUpdateUrl(this.updateURL);
+    // XXX Bug 779317 - setKeyUrl has the side effect of fetching a key from the server.
+    // This shouldn't happen if anti-phishing/anti-malware is disabled.
+    if (this.phishingEnabled || this.malwareEnabled)
+      listManager.setKeyUrl(this.keyURL);
+    listManager.setGethashUrl(this.gethashURL);
+  },
+
+
+  controlUpdateChecking: function() {
+    log("phishingEnabled:", this.phishingEnabled, "malwareEnabled:", this.malwareEnabled);
+
+    let listManager = Cc["@mozilla.org/url-classifier/listmanager;1"].
+                      getService(Ci.nsIUrlListManager);
+
+    if (this.phishingEnabled)
+      listManager.enableUpdate(phishingList);
+    else
+      listManager.disableUpdate(phishingList);
+
+    if (this.malwareEnabled)
+      listManager.enableUpdate(malwareList);
+    else
+      listManager.disableUpdate(malwareList);
+  },
+
+
+  addMozEntries: function() {
+    // Add test entries to the DB.
+    // XXX bug 779008 - this could be done by DB itself?
+    const phishURL   = "mozilla.org/firefox/its-a-trap.html";
+    const malwareURL = "mozilla.org/firefox/its-an-attack.html";
+
+    let update = "n:1000\ni:test-malware-simple\nad:1\n" +
+                 "a:1:32:" + malwareURL.length + "\n" +
+                 malwareURL;
+    update += "n:1000\ni:test-phish-simple\nad:1\n" +
+              "a:1:32:" + phishURL.length + "\n" +
+              phishURL;
+    log("addMozEntries:", update);
+
+    let db = Cc["@mozilla.org/url-classifier/dbservice;1"].
+             getService(Ci.nsIUrlClassifierDBService);
+
+    // nsIUrlClassifierUpdateObserver
+    let dummyListener = {
+      updateUrlRequested: function() { },
+      streamFinished:     function() { },
+      updateError:        function() { },
+      updateSuccess:      function() { }
+    };
+
+    try {
+      db.beginUpdate(dummyListener, "test-malware-simple,test-phish-simple", "");
+      db.beginStream("", "");
+      db.updateStream(update);
+      db.finishStream();
+      db.finishUpdate();
+    } catch(ex) {
+      // beginUpdate will throw harmlessly if there's an existing update in progress, ignore failures.
+      log("addMozEntries failed!", ex);
+    }
+  },
+};
--- a/mobile/android/confvars.sh
+++ b/mobile/android/confvars.sh
@@ -7,17 +7,17 @@ MOZ_APP_VENDOR=Mozilla
 
 MOZ_APP_VERSION=18.0a1
 MOZ_APP_UA_NAME=Firefox
 
 MOZ_BRANDING_DIRECTORY=mobile/android/branding/unofficial
 MOZ_OFFICIAL_BRANDING_DIRECTORY=mobile/android/branding/official
 # MOZ_APP_DISPLAYNAME is set by branding/configure.sh
 
-MOZ_SAFE_BROWSING=
+MOZ_SAFE_BROWSING=1
 
 MOZ_DISABLE_DOMCRYPTO=1
 
 # Enable getUserMedia
 MOZ_MEDIA_NAVIGATOR=1
 
 if test "$LIBXUL_SDK"; then
 MOZ_XULRUNNER=1