merge m-c to fx-team
authorTim Taubert <ttaubert@mozilla.com>
Wed, 26 Sep 2012 10:59:07 +0200
changeset 111787 7505bbe999e4dc52b67c5c4df8585d8785a61ceb
parent 111786 37d3286e67bac1ba602d30a6f98758bf08e43c7a (current diff)
parent 111629 e64a78df7258a0650990fdabd9610881f7d11617 (diff)
child 111788 c7ea268e3322b52ff800744bc354563b895a8bad
push idunknown
push userunknown
push dateunknown
milestone18.0a1
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
--- a/mobile/android/installer/package-manifest.in
+++ b/mobile/android/installer/package-manifest.in
@@ -352,22 +352,24 @@
 @BINPATH@/components/AppsService.manifest
 
 @BINPATH@/components/TCPSocket.js
 @BINPATH@/components/TCPSocket.manifest
 
 ; Modules
 @BINPATH@/modules/*
 
+#ifdef MOZ_SAFE_BROWSING
 ; Safe Browsing
 @BINPATH@/components/nsURLClassifier.manifest
 @BINPATH@/components/nsUrlClassifierHashCompleter.js
 @BINPATH@/components/nsUrlClassifierListManager.js
 @BINPATH@/components/nsUrlClassifierLib.js
 @BINPATH@/components/url-classifier.xpt
+#endif
 
 ; GNOME hooks
 #ifdef MOZ_ENABLE_GNOME_COMPONENT
 @BINPATH@/components/@DLL_PREFIX@mozgnome@DLL_SUFFIX@
 #endif
 
 ; [Browser Chrome Files]
 @BINPATH@/chrome/browser@JAREXT@
@@ -517,17 +519,17 @@ bin/components/@DLL_PREFIX@nkgnomevfs@DL
 @BINPATH@/components/HelperAppDialog.js
 @BINPATH@/components/LoginManagerPrompter.js
 @BINPATH@/components/MobileComponents.manifest
 @BINPATH@/components/MobileComponents.xpt
 @BINPATH@/components/PromptService.js
 @BINPATH@/components/SessionStore.js
 @BINPATH@/components/Sidebar.js
 #ifdef MOZ_SAFE_BROWSING
-@BINPATH@/components/SafeBrowsing.js
+@BINPATH@/components/SafeBrowsing.jsm
 #endif
 @BINPATH@/components/XPIDialogService.js
 @BINPATH@/components/browsercomps.xpt
 @BINPATH@/extensions/feedback@mobile.mozilla.org.xpi
 
 #ifdef ENABLE_MARIONETTE
 @BINPATH@/chrome/marionette@JAREXT@ 
 @BINPATH@/chrome/marionette.manifest
--- a/mobile/android/locales/en-US/chrome/browser.properties
+++ b/mobile/android/locales/en-US/chrome/browser.properties
@@ -50,16 +50,19 @@ notificationRestart.button=Restart
 
 # Popup Blocker
 popupWarning=%S prevented this site from opening a pop-up window.
 popupWarningMultiple=%S prevented this site from opening %S pop-up windows.
 popupButtonAllowOnce=Show
 popupButtonAlwaysAllow2=Always Show
 popupButtonNeverWarn2=Never Show