merge mozilla-inbound to mozilla-central a=merge
authorCarsten "Tomcat" Book <cbook@mozilla.com>
Wed, 16 Mar 2016 10:56:14 +0100
changeset 288922 341344bdec8f10bf50646cd6ef2355361435cbf6
parent 288819 d49937a2e5fe27e469781ea09c42aa2a142cf77d (current diff)
parent 288921 1d96035b9f320d0139a6d214affaaeb174d90f5d (diff)
child 288923 6449a9493de02ed7b9615d690abda0863ef380bf
child 288962 6b3f223a96189c9130f079d455e9dac18118eaae
child 288985 4b3a31a77586e3a756f276cd5258807a253bd887
push id30091
push usercbook@mozilla.com
push dateWed, 16 Mar 2016 09:56:40 +0000
treeherdermozilla-central@341344bdec8f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone48.0a1
first release with
nightly linux32
341344bdec8f / 48.0a1 / 20160316030233 / files
nightly linux64
341344bdec8f / 48.0a1 / 20160316030233 / files
nightly mac
341344bdec8f / 48.0a1 / 20160316030233 / files
nightly win32
341344bdec8f / 48.0a1 / 20160316030233 / files
nightly win64
341344bdec8f / 48.0a1 / 20160316030233 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
merge mozilla-inbound to mozilla-central a=merge
dom/media/gmp-plugin-openh264/Makefile.in
dom/media/gmp-plugin/Makefile.in
editor/libeditor/tests/test_bug527935.html
editor/libeditor/tests/test_bug629172.html
gfx/angle/src/libANGLE/RefCountObject.cpp
gfx/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table.cpp
gfx/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_util.cpp
layout/style/test/Makefile.in
media/gmp-clearkey/0.1/Makefile.in
security/manager/ssl/tests/unit/pkcs11testmodule/Makefile.in
testing/web-platform/meta/mixed-content/blockable/http-csp/cross-origin-http/picture-tag/top-level/no-redirect/opt-in-blocks.https.html.ini
testing/web-platform/meta/mixed-content/optionally-blockable/http-csp/cross-origin-http/audio-tag/top-level/keep-scheme-redirect/opt-in-blocks.https.html.ini
testing/web-platform/meta/mixed-content/optionally-blockable/http-csp/cross-origin-http/audio-tag/top-level/no-redirect/opt-in-blocks.https.html.ini
testing/web-platform/meta/mixed-content/optionally-blockable/http-csp/cross-origin-http/audio-tag/top-level/swap-scheme-redirect/opt-in-blocks.https.html.ini
testing/web-platform/meta/mixed-content/optionally-blockable/http-csp/cross-origin-http/img-tag/top-level/keep-scheme-redirect/opt-in-blocks.https.html.ini
testing/web-platform/meta/mixed-content/optionally-blockable/http-csp/cross-origin-http/img-tag/top-level/no-redirect/opt-in-blocks.https.html.ini
testing/web-platform/meta/mixed-content/optionally-blockable/http-csp/cross-origin-http/img-tag/top-level/swap-scheme-redirect/opt-in-blocks.https.html.ini
testing/web-platform/meta/mixed-content/optionally-blockable/http-csp/cross-origin-http/video-tag/top-level/keep-scheme-redirect/opt-in-blocks.https.html.ini
testing/web-platform/meta/mixed-content/optionally-blockable/http-csp/cross-origin-http/video-tag/top-level/no-redirect/opt-in-blocks.https.html.ini
testing/web-platform/meta/mixed-content/optionally-blockable/http-csp/cross-origin-http/video-tag/top-level/swap-scheme-redirect/opt-in-blocks.https.html.ini
testing/web-platform/meta/mixed-content/optionally-blockable/http-csp/same-host-http/audio-tag/top-level/keep-scheme-redirect/opt-in-blocks.https.html.ini
testing/web-platform/meta/mixed-content/optionally-blockable/http-csp/same-host-http/audio-tag/top-level/no-redirect/opt-in-blocks.https.html.ini
testing/web-platform/meta/mixed-content/optionally-blockable/http-csp/same-host-http/audio-tag/top-level/swap-scheme-redirect/opt-in-blocks.https.html.ini
testing/web-platform/meta/mixed-content/optionally-blockable/http-csp/same-host-http/img-tag/top-level/keep-scheme-redirect/opt-in-blocks.https.html.ini
testing/web-platform/meta/mixed-content/optionally-blockable/http-csp/same-host-http/img-tag/top-level/no-redirect/opt-in-blocks.https.html.ini
testing/web-platform/meta/mixed-content/optionally-blockable/http-csp/same-host-http/img-tag/top-level/swap-scheme-redirect/opt-in-blocks.https.html.ini
testing/web-platform/meta/mixed-content/optionally-blockable/http-csp/same-host-http/video-tag/top-level/keep-scheme-redirect/opt-in-blocks.https.html.ini
testing/web-platform/meta/mixed-content/optionally-blockable/http-csp/same-host-http/video-tag/top-level/no-redirect/opt-in-blocks.https.html.ini
testing/web-platform/meta/mixed-content/optionally-blockable/http-csp/same-host-http/video-tag/top-level/swap-scheme-redirect/opt-in-blocks.https.html.ini
--- a/accessible/base/ARIAMap.cpp
+++ b/accessible/base/ARIAMap.cpp
@@ -30,17 +30,17 @@ static const uint32_t kGenericAccType = 
  *  Using RDF will also allow for role extensibility. See bug 280138.
  *
  *  Definition of nsRoleMapEntry contains comments explaining this table.
  *
  *  When no Role enum mapping exists for an ARIA role, the role will be exposed
  *  via the object attribute "xml-roles".
  */
 
-static nsRoleMapEntry sWAIRoleMaps[] =
+static const nsRoleMapEntry sWAIRoleMaps[] =
 {
   { // alert
     &nsGkAtoms::alert,
     roles::ALERT,
     kUseMapRole,
     eNoValue,
     eNoAction,
     eNoLiveAttr,
@@ -755,17 +755,17 @@ static nsRoleMapEntry sWAIRoleMaps[] =
     eNoLiveAttr,
     kGenericAccType,
     kNoReqStates,
     eARIASelectable,
     eARIACheckedMixed
   }
 };
 
-static nsRoleMapEntry sLandmarkRoleMap = {
+static const nsRoleMapEntry sLandmarkRoleMap = {
   &nsGkAtoms::_empty,
   roles::NOTHING,
   kUseNativeRole,
   eNoValue,
   eNoAction,
   eNoLiveAttr,
   kGenericAccType,
   kNoReqStates
@@ -856,17 +856,17 @@ struct RoleComparator
   explicit RoleComparator(const nsDependentSubstring& aRole) : mRole(aRole) {}
   int operator()(const nsRoleMapEntry& aEntry) const {
     return Compare(mRole, aEntry.ARIARoleString());
   }
 };
 
 }
 
-nsRoleMapEntry*
+const nsRoleMapEntry*
 aria::GetRoleMap(dom::Element* aEl)
 {
   nsAutoString roles;
   if (!aEl || !aEl->GetAttr(kNameSpaceID_None, nsGkAtoms::role, roles) ||
       roles.IsEmpty()) {
     // We treat role="" as if the role attribute is absent (per aria spec:8.1.1)
     return nullptr;
   }
--- a/accessible/base/ARIAMap.h
+++ b/accessible/base/ARIAMap.h
@@ -205,17 +205,17 @@ extern nsRoleMapEntry gEmptyRoleMap;
 /**
  * Get the role map entry for a given DOM node. This will use the first
  * ARIA role if the role attribute provides a space delimited list of roles.
  *
  * @param aNode  [in] the DOM node to get the role map entry for
  * @return        a pointer to the role map entry for the ARIA role, or nullptr
  *                if none
  */
-nsRoleMapEntry* GetRoleMap(dom::Element* aEl);
+const nsRoleMapEntry* GetRoleMap(dom::Element* aEl);
 
 /**
  * Return accessible state from ARIA universal states applied to the given
  * element.
  */
 uint64_t UniversalStatesFor(mozilla::dom::Element* aElement);
 
 /**
--- a/accessible/base/nsAccUtils.cpp
+++ b/accessible/base/nsAccUtils.cpp
@@ -141,17 +141,17 @@ nsAccUtils::SetLiveContainerAttributes(n
     // container-relevant attribute
     if (relevant.IsEmpty() &&
         HasDefinedARIAToken(ancestor, nsGkAtoms::aria_relevant) &&
         ancestor->GetAttr(kNameSpaceID_None, nsGkAtoms::aria_relevant, relevant))
       SetAccAttr(aAttributes, nsGkAtoms::containerRelevant, relevant);
 
     // container-live, and container-live-role attributes
     if (live.IsEmpty()) {
-      nsRoleMapEntry* role = nullptr;
+      const nsRoleMapEntry* role = nullptr;
       if (ancestor->IsElement()) {
         role = aria::GetRoleMap(ancestor->AsElement());
       }
       if (HasDefinedARIAToken(ancestor, nsGkAtoms::aria_live)) {
         ancestor->GetAttr(kNameSpaceID_None, nsGkAtoms::aria_live, live);
       } else if (role) {
         GetLiveAttrValue(role->liveAttRule, live);
       }
--- a/accessible/base/nsAccessibilityService.cpp
+++ b/accessible/base/nsAccessibilityService.cpp
@@ -137,17 +137,17 @@ MustBeAccessible(nsIContent* aContent, D
 ////////////////////////////////////////////////////////////////////////////////
 // Accessible constructors
 
 static Accessible*
 New_HTMLLink(nsIContent* aContent, Accessible* aContext)
 {
   // Only some roles truly enjoy life as HTMLLinkAccessibles, for details
   // see closed bug 494807.
-  nsRoleMapEntry* roleMapEntry = aria::GetRoleMap(aContent->AsElement());
+  const nsRoleMapEntry* roleMapEntry = aria::GetRoleMap(aContent->AsElement());
   if (roleMapEntry && roleMapEntry->role != roles::NOTHING &&
       roleMapEntry->role != roles::LINK) {
     return new HyperTextAccessibleWrap(aContent, aContext->Document());
   }
 
   return new HTMLLinkAccessible(aContent, aContext->Document());
 }
 
@@ -1127,17 +1127,17 @@ nsAccessibilityService::GetOrCreateAcces
       return nullptr;
     }
 
     newAcc = new HyperTextAccessibleWrap(content, document);
     document->BindToDocument(newAcc, aria::GetRoleMap(content->AsElement()));
     return newAcc;
   }
 
-  nsRoleMapEntry* roleMapEntry = aria::GetRoleMap(content->AsElement());
+  const nsRoleMapEntry* roleMapEntry = aria::GetRoleMap(content->AsElement());
 
   // If the element is focusable or global ARIA attribute is applied to it or
   // it is referenced by ARIA relationship then treat role="presentation" on
   // the element as the role is not there.
   if (roleMapEntry &&
       (roleMapEntry->Is(nsGkAtoms::presentation) ||
        roleMapEntry->Is(nsGkAtoms::none))) {
     if (!MustBeAccessible(content, document))
@@ -1179,29 +1179,29 @@ nsAccessibilityService::GetOrCreateAcces
         newAcc = new ARIAGridAccessibleWrap(content, document);
       }
     }
 
     // If table has strong ARIA role then all table descendants shouldn't
     // expose their native roles.
     if (!roleMapEntry && newAcc && aContext->HasStrongARIARole()) {
       if (frame->AccessibleType() == eHTMLTableRowType) {
-        nsRoleMapEntry* contextRoleMap = aContext->ARIARoleMap();
+        const nsRoleMapEntry* contextRoleMap = aContext->ARIARoleMap();
         if (!contextRoleMap->IsOfType(eTable))
           roleMapEntry = &aria::gEmptyRoleMap;
 
       } else if (frame->AccessibleType() == eHTMLTableCellType &&
                  aContext->ARIARoleMap() == &aria::gEmptyRoleMap) {
         roleMapEntry = &aria::gEmptyRoleMap;
 
       } else if (content->IsAnyOfHTMLElements(nsGkAtoms::dt,
                                               nsGkAtoms::li,
                                               nsGkAtoms::dd) ||
                  frame->AccessibleType() == eHTMLLiType) {
-        nsRoleMapEntry* contextRoleMap = aContext->ARIARoleMap();
+        const nsRoleMapEntry* contextRoleMap = aContext->ARIARoleMap();
         if (!contextRoleMap->IsOfType(eList))
           roleMapEntry = &aria::gEmptyRoleMap;
       }
     }
   }
 
   // Accessible XBL types and deck stuff are used in XUL only currently.
   if (!newAcc && content->IsXULElement()) {
--- a/accessible/generic/Accessible.h
+++ b/accessible/generic/Accessible.h
@@ -221,17 +221,17 @@ public:
    */
   bool HasARIARole() const { return mRoleMapEntry; }
   bool IsARIARole(nsIAtom* aARIARole) const;
   bool HasStrongARIARole() const;
 
   /**
    * Retrun ARIA role map if any.
    */
-  nsRoleMapEntry* ARIARoleMap() const { return mRoleMapEntry; }
+  const nsRoleMapEntry* ARIARoleMap() const { return mRoleMapEntry; }
 
   /**
    * Return accessible role specified by ARIA (see constants in
    * roles).
    */
   mozilla::a11y::role ARIARole();
 
   /**
@@ -367,17 +367,17 @@ public:
   /**
    * Shutdown this accessible object.
    */
   virtual void Shutdown();
 
   /**
    * Set the ARIA role map entry for a new accessible.
    */
-  void SetRoleMapEntry(nsRoleMapEntry* aRoleMapEntry)
+  void SetRoleMapEntry(const nsRoleMapEntry* aRoleMapEntry)
     { mRoleMapEntry = aRoleMapEntry; }
 
   /**
    * Cache children if necessary.
    */
   void EnsureChildren();
 
   /**
@@ -1183,17 +1183,17 @@ protected:
     AccGroupInfo* groupInfo;
     ProxyAccessible* proxy;
   } mBits;
   friend class AccGroupInfo;
 
   /**
    * Non-null indicates author-supplied role; possibly state & value as well
    */
-  nsRoleMapEntry* mRoleMapEntry;
+  const nsRoleMapEntry* mRoleMapEntry;
 
 private:
   Accessible() = delete;
   Accessible(const Accessible&) = delete;
   Accessible& operator =(const Accessible&) = delete;
 
 };
 
--- a/accessible/generic/DocAccessible.cpp
+++ b/accessible/generic/DocAccessible.cpp
@@ -1277,17 +1277,17 @@ DocAccessible::GetAccessibleOrDescendant
     }
   }
 
   return nullptr;
 }
 
 void
 DocAccessible::BindToDocument(Accessible* aAccessible,
-                              nsRoleMapEntry* aRoleMapEntry)
+                              const nsRoleMapEntry* aRoleMapEntry)
 {
   // Put into DOM node cache.
   if (aAccessible->IsNodeMapEntry())
     mNodeToAccessibleMap.Put(aAccessible->GetNode(), aAccessible);
 
   // Put into unique ID cache.
   mAccessibleCache.Put(aAccessible->UniqueID(), aAccessible);
 
--- a/accessible/generic/DocAccessible.h
+++ b/accessible/generic/DocAccessible.h
@@ -309,17 +309,18 @@ public:
 
   /**
    * Initialize the newly created accessible and put it into document caches.
    *
    * @param  aAccessible    [in] created accessible
    * @param  aRoleMapEntry  [in] the role map entry role the ARIA role or nullptr
    *                          if none
    */
-  void BindToDocument(Accessible* aAccessible, nsRoleMapEntry* aRoleMapEntry);
+  void BindToDocument(Accessible* aAccessible,
+                      const nsRoleMapEntry* aRoleMapEntry);
 
   /**
    * Remove from document and shutdown the given accessible.
    */
   void UnbindFromDocument(Accessible* aAccessible);
 
   /**
    * Notify the document accessible that content was inserted.
--- a/accessible/ipc/DocAccessibleChild.cpp
+++ b/accessible/ipc/DocAccessibleChild.cpp
@@ -348,17 +348,17 @@ DocAccessibleChild::RecvLandmarkRole(con
 bool
 DocAccessibleChild::RecvARIARoleAtom(const uint64_t& aID, nsString* aRole)
 {
   Accessible* acc = IdToAccessible(aID);
   if (!acc) {
     return true;
   }
 
-  if (nsRoleMapEntry* roleMap = acc->ARIARoleMap()) {
+  if (const nsRoleMapEntry* roleMap = acc->ARIARoleMap()) {
     if (nsIAtom* roleAtom = *(roleMap->roleAtom)) {
       roleAtom->ToString(*aRole);
     }
   }
 
   return true;
 }
 
--- a/accessible/mac/mozAccessible.mm
+++ b/accessible/mac/mozAccessible.mm
@@ -806,17 +806,17 @@ ConvertToNSArray(nsTArray<ProxyAccessibl
       return @"AXLandmarkSearch";
     if (landmark == nsGkAtoms::searchbox)
       return @"AXSearchField";
   }
 
   // Now, deal with widget roles
   nsIAtom* roleAtom = nullptr;
   if (accWrap && accWrap->HasARIARole()) {
-    nsRoleMapEntry* roleMap = accWrap->ARIARoleMap();
+    const nsRoleMapEntry* roleMap = accWrap->ARIARoleMap();
     roleAtom = *roleMap->roleAtom;
   }
   if (proxy)
     roleAtom = proxy->ARIARoleAtom();
 
   if (roleAtom) {
     if (roleAtom == nsGkAtoms::alert)
       return @"AXApplicationAlert";
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -6133,17 +6133,17 @@ var IndexedDBPromptHelper = {
     timeoutId = setTimeout(timeoutNotification, firstTimeoutDuration);
   }
 };
 
 function CanCloseWindow()
 {
   // Avoid redundant calls to canClose from showing multiple
   // PermitUnload dialogs.
-  if (window.skipNextCanClose) {
+  if (Services.startup.shuttingDown || window.skipNextCanClose) {
     return true;
   }
 
   for (let browser of gBrowser.browsers) {
     let {permitUnload, timedOut} = browser.permitUnload();
     if (timedOut) {
       return true;
     }
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -1555,17 +1555,23 @@
             let wasActive = document.activeElement == aBrowser;
 
             // Unmap the old outerWindowID.
             this._outerWindowIDBrowserMap.delete(aBrowser.outerWindowID);
 
             // Unhook our progress listener.
             let tab = this.getTabForBrowser(aBrowser);
             let filter = this._tabFilters.get(tab);
+            let listener = this._tabListeners.get(tab);
             aBrowser.webProgress.removeProgressListener(filter);
+            filter.removeProgressListener(listener);
+
+            // We'll be creating a new listener, so destroy the old one.
+            listener.destroy();
+
             // Make sure the browser is destroyed so it unregisters from observer notifications
             aBrowser.destroy();
 
             // Make sure to restore the original droppedLinkHandler.
             let droppedLinkHandler = aBrowser.droppedLinkHandler;
 
             // Change the "remote" attribute.
             let parent = aBrowser.parentNode;
@@ -1577,16 +1583,23 @@
 
             // Switching a browser's remoteness will create a new frameLoader.
             // As frameLoaders start out with an active docShell we have to
             // deactivate it if this is not the selected tab's browser or the
             // browser window is minimized.
             aBrowser.docShellIsActive = (aBrowser == this.selectedBrowser &&
                                          window.windowState != window.STATE_MINIMIZED);
 
+            // Create a new tab progress listener for the new browser we just injected,
+            // since tab progress listeners have logic for handling the initial about:blank
+            // load
+            listener = this.mTabProgressListener(tab, aBrowser, false, false);
+            this._tabListeners.set(tab, listener);
+            filter.addProgressListener(listener, Ci.nsIWebProgress.NOTIFY_ALL);
+
             // Restore the progress listener.
             aBrowser.webProgress.addProgressListener(filter, Ci.nsIWebProgress.NOTIFY_ALL);
 
             // Restore the securityUI state.
             let securityUI = aBrowser.securityUI;
             let state = securityUI ? securityUI.state
                                    : Ci.nsIWebProgressListener.STATE_IS_INSECURE;
             // Include the true final argument to indicate that this event is
--- a/browser/base/content/test/general/browser.ini
+++ b/browser/base/content/test/general/browser.ini
@@ -115,16 +115,18 @@ support-files =
   test_mcb_redirect.html
   test_mcb_redirect_image.html
   test_mcb_double_redirect_image.html
   test_mcb_redirect.js
   test_mcb_redirect.sjs
   xul_tooltiptext.xhtml
   file_bug1045809_1.html
   file_bug1045809_2.html
+  file_csp_block_all_mixedcontent.html
+  file_csp_block_all_mixedcontent.js
 
 [browser_URLBarSetURI.js]
 skip-if = (os == "linux" || os == "mac") && debug # bug 970052, bug 970053
 [browser_aboutAccounts.js]
 skip-if = os == "linux" # Bug 958026
 support-files =
   content_aboutAccounts.js
 [browser_aboutCertError.js]
@@ -549,8 +551,10 @@ tags = fullscreen
 [browser_aboutTabCrashed.js]
 skip-if = !e10s || !crashreporter
 [browser_aboutTabCrashed_clearEmail.js]
 skip-if = !e10s || !crashreporter
 [browser_aboutTabCrashed_showForm.js]
 skip-if = !e10s || !crashreporter
 [browser_aboutTabCrashed_withoutDump.js]
 skip-if = !e10s
+[browser_csp_block_all_mixedcontent.js]
+tags = mcb
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/general/browser_csp_block_all_mixedcontent.js
@@ -0,0 +1,55 @@
+/*
+ * Description of the Test:
+ * We load an https page which uses a CSP including block-all-mixed-content.
+ * The page tries to load a script over http. We make sure the UI is not
+ * influenced when blocking the mixed content. In particular the page
+ * should still appear fully encrypted with a green lock.
+ */
+
+const PRE_PATH = "https://example.com/browser/browser/base/content/test/general/";
+var gTestBrowser = null;
+
+//------------------------------------------------------
+function cleanUpAfterTests() {
+  gBrowser.removeCurrentTab();
+  window.focus();
+  finish();
+}
+
+//------------------------------------------------------
+function verifyUInotDegraded() {
+  // make sure that not mixed content is loaded and also not blocked
+  assertMixedContentBlockingState(
+    gTestBrowser,
+    { activeLoaded: false,
+      activeBlocked: false,
+      passiveLoaded: false
+    }
+  );
+  // clean up and finish test
+  cleanUpAfterTests();
+}
+
+//------------------------------------------------------
+function runTests() {
+  var newTab = gBrowser.addTab();
+  gBrowser.selectedTab = newTab;
+  gTestBrowser = gBrowser.selectedBrowser;
+  newTab.linkedBrowser.stop();
+
+  // Starting the test
+  BrowserTestUtils.browserLoaded(gTestBrowser).then(verifyUInotDegraded);
+  var url = PRE_PATH + "file_csp_block_all_mixedcontent.html";
+  gTestBrowser.loadURI(url);
+}
+
+//------------------------------------------------------
+function test() {
+  // Performing async calls, e.g. 'onload', we have to wait till all of them finished
+  waitForExplicitFinish();
+
+  SpecialPowers.pushPrefEnv(
+    { 'set': [["security.mixed_content.block_active_content", true]] },
+    function() { runTests(); }
+  );
+}
--- a/browser/base/content/test/general/browser_ctrlTab.js
+++ b/browser/base/content/test/general/browser_ctrlTab.js
@@ -1,154 +1,178 @@
-function test() {
+add_task(function* () {
   gPrefService.setBoolPref("browser.ctrlTab.previews", true);
 
   gBrowser.addTab();
   gBrowser.addTab();
   gBrowser.addTab();
 
   checkTabs(4);
 
-  ctrlTabTest([2]      , 1, 0);
-  ctrlTabTest([2, 3, 1], 2, 2);
-  ctrlTabTest([]       , 4, 2);
+  yield ctrlTabTest([2]      , 1, 0);
+  yield ctrlTabTest([2, 3, 1], 2, 2);
+  yield ctrlTabTest([]       , 4, 2);
 
   {
     let selectedIndex = gBrowser.tabContainer.selectedIndex;
-    pressCtrlTab();
-    pressCtrlTab(true);
-    releaseCtrl();
+    yield pressCtrlTab();
+    yield pressCtrlTab(true);
+    yield releaseCtrl();
     is(gBrowser.tabContainer.selectedIndex, selectedIndex,
        "Ctrl+Tab -> Ctrl+Shift+Tab keeps the selected tab");
   }
 
   { // test for bug 445369
     let tabs = gBrowser.tabs.length;
-    pressCtrlTab();
-    EventUtils.synthesizeKey("w", { ctrlKey: true });
+    yield pressCtrlTab();
+    yield synthesizeCtrlW();
     is(gBrowser.tabs.length, tabs - 1, "Ctrl+Tab -> Ctrl+W removes one tab");
-    releaseCtrl();
+    yield releaseCtrl();
   }
 
   { // test for bug 667314
     let tabs = gBrowser.tabs.length;
-    pressCtrlTab();
-    pressCtrlTab(true);
-    EventUtils.synthesizeKey("w", { ctrlKey: true });
+    yield pressCtrlTab();
+    yield pressCtrlTab(true);
+    yield synthesizeCtrlW();
     is(gBrowser.tabs.length, tabs - 1, "Ctrl+Tab -> Ctrl+W removes the selected tab");
-    releaseCtrl();
+    yield releaseCtrl();
   }
 
   gBrowser.addTab();
   checkTabs(3);
-  ctrlTabTest([2, 1, 0], 7, 1);
+  yield ctrlTabTest([2, 1, 0], 7, 1);
 
   gBrowser.addTab();
   checkTabs(4);
 
   { // test for bug 445369
     selectTabs([1, 2, 0]);
 
     let selectedTab = gBrowser.selectedTab;
     let tabToRemove = gBrowser.tabs[1];
 
-    pressCtrlTab();
-    pressCtrlTab();
-    EventUtils.synthesizeKey("w", { ctrlKey: true });
+    yield pressCtrlTab();
+    yield pressCtrlTab();
+    yield synthesizeCtrlW();
     ok(!tabToRemove.parentNode,
        "Ctrl+Tab*2 -> Ctrl+W removes the second most recently selected tab");
 
-    pressCtrlTab(true);
-    pressCtrlTab(true);
-    releaseCtrl();
+    yield pressCtrlTab(true);
+    yield pressCtrlTab(true);
+    yield releaseCtrl();
     ok(selectedTab.selected,
        "Ctrl+Tab*2 -> Ctrl+W -> Ctrl+Shift+Tab*2 keeps the selected tab");
   }
   gBrowser.removeTab(gBrowser.tabContainer.lastChild);
   checkTabs(2);
 
-  ctrlTabTest([1], 1, 0);
+  yield ctrlTabTest([1], 1, 0);
 
   gBrowser.removeTab(gBrowser.tabContainer.lastChild);
   checkTabs(1);
 
   { // test for bug 445768
     let focusedWindow = document.commandDispatcher.focusedWindow;
     let eventConsumed = true;
     let detectKeyEvent = function (event) {
       eventConsumed = event.defaultPrevented;
     };
     document.addEventListener("keypress", detectKeyEvent, false);
-    pressCtrlTab();
+    yield pressCtrlTab();
     document.removeEventListener("keypress", detectKeyEvent, false);
     ok(eventConsumed, "Ctrl+Tab consumed by the tabbed browser if one tab is open");
     is(focusedWindow, document.commandDispatcher.focusedWindow,
        "Ctrl+Tab doesn't change focus if one tab is open");
   }
 
   // cleanup
   if (gPrefService.prefHasUserValue("browser.ctrlTab.previews"))
     gPrefService.clearUserPref("browser.ctrlTab.previews");
 
   /* private utility functions */
 
-  function pressCtrlTab(aShiftKey) {
+  function* pressCtrlTab(aShiftKey) {
+    let promise;
+    if (!isOpen() && canOpen()) {
+      promise = BrowserTestUtils.waitForEvent(ctrlTab.panel, "popupshown");
+    } else {
+      promise = BrowserTestUtils.waitForEvent(document, "keyup");
+    }
     EventUtils.synthesizeKey("VK_TAB", { ctrlKey: true, shiftKey: !!aShiftKey });
+    return promise;
   }
 
-  function releaseCtrl() {
+  function* releaseCtrl() {
+    let promise;
+    if (isOpen()) {
+      promise = BrowserTestUtils.waitForEvent(ctrlTab.panel, "popuphidden");
+    } else {
+      promise = BrowserTestUtils.waitForEvent(document, "keyup");
+    }
     EventUtils.synthesizeKey("VK_CONTROL", { type: "keyup" });
+    return promise;
+  }
+
+  function* synthesizeCtrlW() {
+    let promise = BrowserTestUtils.waitForEvent(gBrowser.tabContainer, "TabClose");
+    EventUtils.synthesizeKey("w", { ctrlKey: true });
+    return promise;
   }
 
   function isOpen() {
     return ctrlTab.isOpen;
   }
 
+  function canOpen() {
+    return gPrefService.getBoolPref("browser.ctrlTab.previews") && gBrowser.tabs.length > 2;
+  }
+
   function checkTabs(aTabs) {
     var tabs = gBrowser.tabs.length;
     if (tabs != aTabs) {
       while (gBrowser.tabs.length > 1)
         gBrowser.removeCurrentTab();
       throw "expected " + aTabs + " open tabs, got " + tabs;
     }
   }
 
   function selectTabs(tabs) {
     tabs.forEach(function (index) {
       gBrowser.selectedTab = gBrowser.tabs[index];
     });
   }
 
-  function ctrlTabTest(tabsToSelect, tabTimes, expectedIndex) {
+  function* ctrlTabTest(tabsToSelect, tabTimes, expectedIndex) {
     selectTabs(tabsToSelect);
 
     var indexStart = gBrowser.tabContainer.selectedIndex;
     var tabCount = gBrowser.tabs.length;
     var normalized = tabTimes % tabCount;
     var where = normalized == 1 ? "back to the previously selected tab" :
                 normalized + " tabs back in most-recently-selected order";
 
     for (let i = 0; i < tabTimes; i++) {
-      pressCtrlTab();
+      yield pressCtrlTab();
 
       if (tabCount > 2)
        is(gBrowser.tabContainer.selectedIndex, indexStart,
          "Selected tab doesn't change while tabbing");
     }
 
     if (tabCount > 2) {
       ok(isOpen(),
          "With " + tabCount + " tabs open, Ctrl+Tab opens the preview panel");
 
-      releaseCtrl();
+      yield releaseCtrl();
 
       ok(!isOpen(),
          "Releasing Ctrl closes the preview panel");
     } else {
       ok(!isOpen(),
          "With " + tabCount + " tabs open, Ctrl+Tab doesn't open the preview panel");
     }
 
     is(gBrowser.tabContainer.selectedIndex, expectedIndex,
        "With "+ tabCount +" tabs open and tab " + indexStart
        + " selected, Ctrl+Tab*" + tabTimes + " goes " + where);
   }
-}
+});
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/general/file_csp_block_all_mixedcontent.html
@@ -0,0 +1,9 @@
+<!DOCTYPE HTML>
+<html><head><meta charset="utf-8">
+<title>Bug 1122236 - CSP: Implement block-all-mixed-content</title>
+</head>
+<meta http-equiv="Content-Security-Policy" content="block-all-mixed-content">
+<body>
+<script src="http://example.com/browser/browser/base/content/test/general/file_csp_block_all_mixedcontent.js"/>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/general/file_csp_block_all_mixedcontent.js
@@ -0,0 +1,3 @@
+// empty script file just used for testing Bug 1122236.
+// Making sure the UI is not degraded when blocking
+// mixed content using the CSP directive: block-all-mixed-content.
--- a/browser/components/extensions/ext-utils.js
+++ b/browser/components/extensions/ext-utils.js
@@ -4,16 +4,17 @@
 
 XPCOMUtils.defineLazyModuleGetter(this, "CustomizableUI",
                                   "resource:///modules/CustomizableUI.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils",
                                   "resource://gre/modules/PrivateBrowsingUtils.jsm");
 
 Cu.import("resource://gre/modules/ExtensionUtils.jsm");
 Cu.import("resource://gre/modules/AddonManager.jsm");
+Cu.import("resource://gre/modules/AppConstants.jsm");
 
 const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
 
 const INTEGER = /^[1-9]\d*$/;
 
 var {
   EventManager,
   instanceOf,
@@ -133,16 +134,35 @@ function promisePopupShown(popup) {
       popup.addEventListener("popupshown", function onPopupShown(event) {
         popup.removeEventListener("popupshown", onPopupShown);
         resolve();
       });
     }
   });
 }
 
+XPCOMUtils.defineLazyGetter(global, "stylesheets", () => {
+  let styleSheetService = Cc["@mozilla.org/content/style-sheet-service;1"]
+      .getService(Components.interfaces.nsIStyleSheetService);
+  let styleSheetURI = Services.io.newURI("chrome://browser/content/extension.css",
+                                         null, null);
+  let styleSheet = styleSheetService.preloadSheet(styleSheetURI,
+                                                  styleSheetService.AGENT_SHEET);
+  let stylesheets = [styleSheet];
+
+  if (AppConstants.platform === "macosx") {
+    styleSheetURI = Services.io.newURI("chrome://browser/content/extension-mac.css",
+                                       null, null);
+    let macStyleSheet = styleSheetService.preloadSheet(styleSheetURI,
+                                                       styleSheetService.AGENT_SHEET);
+    stylesheets.push(macStyleSheet);
+  }
+  return stylesheets;
+});
+
 class BasePopup {
   constructor(extension, viewNode, popupURL) {
     let popupURI = Services.io.newURI(popupURL, null, extension.baseURI);
 
     Services.scriptSecurityManager.checkLoadURIWithPrincipal(
       extension.principal, popupURI,
       Services.scriptSecurityManager.DISALLOW_SCRIPT);
 
@@ -158,16 +178,17 @@ class BasePopup {
     this.viewNode.addEventListener(this.DESTROY_EVENT, this);
 
     this.browser = null;
     this.browserReady = this.createBrowser(viewNode, popupURI);
   }
 
   destroy() {
     this.browserReady.then(() => {
+      this.browser.removeEventListener("DOMWindowCreated", this, true);
       this.browser.removeEventListener("load", this, true);
       this.browser.removeEventListener("DOMTitleChanged", this, true);
       this.browser.removeEventListener("DOMWindowClose", this, true);
 
       this.viewNode.removeEventListener(this.DESTROY_EVENT, this);
 
       this.context.unload();
       this.browser.remove();
@@ -185,16 +206,23 @@ class BasePopup {
   }
 
   handleEvent(event) {
     switch (event.type) {
       case this.DESTROY_EVENT:
         this.destroy();
         break;
 
+      case "DOMWindowCreated":
+        let winUtils = this.browser.contentWindow
+            .QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
+        for (let stylesheet of global.stylesheets) {
+          winUtils.addSheet(stylesheet, winUtils.AGENT_SHEET);
+        }
+        break;
       case "DOMWindowClose":
         if (event.target === this.browser.contentWindow) {
           event.preventDefault();
           this.closePopup();
         }
         break;
 
       case "DOMTitleChanged":
@@ -212,17 +240,16 @@ class BasePopup {
         // dynamically, probably in response to MozScrolledAreaChanged events.
         this.window.setTimeout(() => this.resizeBrowser(), 0);
         break;
     }
   }
 
   createBrowser(viewNode, popupURI) {
     let document = viewNode.ownerDocument;
-
     this.browser = document.createElementNS(XUL_NS, "browser");
     this.browser.setAttribute("type", "content");
     this.browser.setAttribute("disableglobalhistory", "true");
 
     // Note: When using noautohide panels, the popup manager will add width and
     // height attributes to the panel, breaking our resize code, if the browser
     // starts out smaller than 30px by 10px. This isn't an issue now, but it
     // will be if and when we popup debugging.
@@ -254,16 +281,17 @@ class BasePopup {
         contentWindow,
         uri: popupURI,
         docShell: this.browser.docShell,
       });
 
       GlobalManager.injectInDocShell(this.browser.docShell, this.extension, this.context);
       this.browser.setAttribute("src", this.context.uri.spec);
 
+      this.browser.addEventListener("DOMWindowCreated", this, true);
       this.browser.addEventListener("load", this, true);
       this.browser.addEventListener("DOMTitleChanged", this, true);
       this.browser.addEventListener("DOMWindowClose", this, true);
     });
   }
 
   // Resizes the browser to match the preferred size of the content.
   resizeBrowser() {
new file mode 100644
--- /dev/null
+++ b/browser/components/extensions/extension-mac.css
@@ -0,0 +1,11 @@
+button,
+select,
+input[type="checkbox"] + label::before {
+  border-radius: 4px;
+}
+
+.panel-section-footer {
+  border-bottom-left-radius: 4px;
+  border-bottom-right-radius: 4px;
+  overflow: hidden;
+}
new file mode 100644
--- /dev/null
+++ b/browser/components/extensions/extension.css
@@ -0,0 +1,572 @@
+/* stylelint-disable property-no-vendor-prefix */
+/* stylelint-disable property-no-vendor-prefix */
+/* Base */
+button,
+select,
+option,
+input {
+  -moz-appearance: none;
+}
+
+/* Variables */
+html,
+body {
+  background-color: #fcfcfc;
+  box-sizing: border-box;
+  color: #222426;
+  cursor: default;
+  display: flex;
+  flex-direction: column;
+  font: caption;
+  margin: 0;
+  padding: 0;
+  -moz-user-select: none;
+}
+
+body * {
+  box-sizing: border-box;
+  text-align: start;
+}
+
+/* stylelint-disable property-no-vendor-prefix */
+/* Buttons */
+button,
+select {
+  background-color: #fbfbfb;
+  border: 1px solid #b1b1b1;
+  box-shadow: 0 0 0 0 transparent;
+  font: caption;
+  height: 24px;
+  outline: 0 !important;
+  padding: 0 8px 0;
+  transition-duration: 250ms;
+  transition-property: box-shadow, border;
+}
+
+select {
+  background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiIgdmlld0JveD0iMCAwIDE2IDE2Ij4KICA8cGF0aCBkPSJNOCwxMkwzLDcsNCw2bDQsNCw0LTQsMSwxWiIgZmlsbD0iIzZBNkE2QSIgLz4KPC9zdmc+Cg==);
+  background-position: calc(100% - 4px) center;
+  background-repeat: no-repeat;
+  -moz-padding-end: 24px;
+  text-overflow: ellipsis;
+}
+
+label {
+  font: caption;
+}
+
+button::-moz-focus-inner {
+  border: 0;
+  outline: 0;
+}
+
+/* Dropdowns */
+select {
+  background-color: #fbfbfb;
+  border: 1px solid #b1b1b1;
+  box-shadow: 0 0 0 0 transparent;
+  font: caption;
+  height: 24px;
+  outline: 0 !important;
+  padding: 0 8px 0;
+  transition-duration: 250ms;
+  transition-property: box-shadow, border;
+}
+
+select {
+  background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiIgdmlld0JveD0iMCAwIDE2IDE2Ij4KICA8cGF0aCBkPSJNOCwxMkwzLDcsNCw2bDQsNCw0LTQsMSwxWiIgZmlsbD0iIzZBNkE2QSIgLz4KPC9zdmc+Cg==);
+  background-position: calc(100% - 4px) center;
+  background-repeat: no-repeat;
+  -moz-padding-end: 24px;
+  text-overflow: ellipsis;
+}
+
+select:-moz-focusring {
+  color: transparent;
+  text-shadow: 0 0 0 #000;
+}
+
+select:-moz-focusring * {
+  color: #000;
+  text-shadow: none;
+}
+
+button.hover,
+select.hover {
+  background-color: #ebebeb;
+  border: 1px solid #b1b1b1;
+}
+
+button.pressed,
+select.pressed {
+  background-color: #d4d4d4;
+  border: 1px solid #858585;
+}
+
+button.disabled,
+select.disabled {
+  color: #999;
+  opacity: .5;
+}
+
+button.focused,
+select.focused {
+  border-color: #fff;
+  box-shadow: 0 0 0 2px rgba(97, 181, 255, 0.75);
+}
+
+button.default {
+  background-color: #0996f8;
+  border-color: #0670cc;
+  color: #fff;
+}
+
+button.default.hover {
+  background-color: #0670cc;
+  border-color: #005bab;
+}
+
+button.default.pressed {
+  background-color: #005bab;
+  border-color: #004480;
+}
+
+button.default.focused {
+  border-color: #fff;
+}
+
+/* Radio Buttons */
+.radioItem {
+  margin-bottom: 6px;
+  text-align: left;
+}
+
+input[type="radio"] {
+  display: none;
+}
+
+input[type="radio"] + label {
+  -moz-user-select: none;
+}
+
+input[type="radio"] + label::before {
+  background-color: #fff;
+  background-position: center;
+  border: 1px solid #b1b1b1;
+  border-radius: 50%;
+  content: "";
+  display: inline-block;
+  height: 16px;
+  margin-right: 6px;
+  vertical-align: text-top;
+  width: 16px;
+}
+
+input[type="radio"]:hover + label::before,
+.radioItem.hover input[type="radio"]:not(active) + label::before {
+  background-color: #fbfbfb;
+  border-color: #b1b1b1;
+}
+
+input[type="radio"]:hover:active + label::before,
+.radioItem.pressed input[type="radio"]:not(active) + label::before {
+  background-color: #ebebeb;
+  border-color: #858585;
+}
+
+input[type="radio"]:checked + label::before {
+  background-color: #0996f8;
+  background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiIgdmlld0JveD0iMCAwIDE2IDE2Ij4KICA8Y2lyY2xlIGN4PSI4IiBjeT0iOCIgcj0iNCIgZmlsbD0iI2ZmZiIgLz4KPC9zdmc+Cg==);
+  border-color: #0670cc;
+}
+
+input[type="radio"]:checked:hover + label::before,
+.radioItem.hover input[type="radio"]:checked:not(active) + label::before {
+  background-color: #0670cc;
+  border-color: #005bab;
+}
+
+input[type="radio"]:checked:hover:active + label::before,
+.radioItem.pressed input[type="radio"]:checked:not(active) + label::before {
+  background-color: #005bab;
+  border-color: #004480;
+}
+
+.radioItem.disabled input[type="radio"] + label,
+.radioItem.disabled input[type="radio"]:hover + label,
+.radioItem.disabled input[type="radio"]:hover:active + label {
+  color: #999;
+  opacity: .5;
+}
+
+.radioItem.focused input[type="radio"] + label::before {
+  border-color: #0996f8;
+  box-shadow: 0 0 0 2px rgba(97, 181, 255, 0.75);
+}
+
+.radioItem.focused input[type="radio"]:checked + label::before {
+  border-color: #fff;
+}
+
+/* Checkboxes */
+.checkboxItem {
+  margin-bottom: 6px;
+  text-align: left;
+}
+
+input[type="checkbox"] {
+  display: none;
+}
+
+input[type="checkbox"] + label {
+  -moz-user-select: none;
+}
+
+input[type="checkbox"] + label::before {
+  background-color: #fff;
+  background-position: center;
+  border: 1px solid #b1b1b1;
+  content: "";
+  display: inline-block;
+  height: 16px;
+  margin-right: 6px;
+  vertical-align: text-top;
+  width: 16px;
+}
+
+input[type="checkbox"]:hover + label::before,
+.checkboxItem.hover input[type="checkbox"]:not(active) + label::before {
+  background-color: #fbfbfb;
+  border-color: #b1b1b1;
+}
+
+input[type="checkbox"]:hover:active + label::before,
+.checkboxItem.pressed input[type="checkbox"]:not(active) + label::before {
+  background-color: #ebebeb;
+  border-color: #858585;
+}
+
+input[type="checkbox"]:checked + label::before {
+  background-color: #0996f8;
+  background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiIgdmlld0JveD0iMCAwIDE2IDE2Ij4KICA8cGF0aCBkPSJNNy43LDEyLjkgQzcuNCwxMy4zIDYuOCwxMy40IDYuNCwxMyBMMy4yLDkuOCBDMi44LDkuNCAyLjgsOC42IDMuMiw4LjIgQzMuNiw3LjggNC40LDcuOCA0LjgsOC4yIEw2LjksMTAuMyBMMTEuMSw0LjQgQzExLjUsMy45IDEyLjIsMy44IDEyLjcsNC4xIEMxMy4yLDQuNSAxMy4zLDUuMiAxMyw1LjcgTDcuNywxMi45IEw3LjcsMTIuOSBaIiBmaWxsPSIjZmZmIiAvPgo8L3N2Zz4K);
+  border-color: #0670cc;
+}
+
+input[type="checkbox"]:checked:hover + label::before,
+.checkboxItem.hover input[type="checkbox"]:checked:not(active) + label::before {
+  background-color: #0670cc;
+  border-color: #005bab;
+}
+
+input[type="checkbox"]:checked:hover:active + label::before,
+.checkboxItem.pressed input[type="checkbox"]:checked:not(active) + label::before {
+  background-color: #005bab;
+  border-color: #004480;
+}
+
+.checkboxItem.disabled input[type="checkbox"] + label,
+.checkboxItem.disabled input[type="checkbox"]:hover + label,
+.checkboxItem.disabled input[type="checkbox"]:hover:active + label {
+  color: #999;
+  opacity: .5;
+}
+
+.checkboxItem.focused input[type="checkbox"] + label::before {
+  border-color: #0996f8;
+  box-shadow: 0 0 0 2px rgba(97, 181, 255, 0.75);
+}
+
+.checkboxItem.focused input[type="checkbox"]:checked + label::before {
+  border-color: #fff;
+}
+
+/* Expander Button */
+button.expander {
+  background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiIgdmlld0JveD0iMCAwIDE2IDE2Ij4KICA8cGF0aCBkPSJNOCwxMkwzLDcsNCw2bDQsNCw0LTQsMSwxWiIgZmlsbD0iIzZBNkE2QSIgLz4KPC9zdmc+Cg==);
+  background-position: center;
+  background-repeat: no-repeat;
+  height: 24px;
+  padding: 0;
+  width: 24px;
+}
+
+/* Interactive States */
+button:hover:not(.pressed):not(.disabled):not(.focused),
+select:hover:not(.pressed):not(.disabled):not(.focused) {
+  background-color: #ebebeb;
+  border: 1px solid #b1b1b1;
+}
+
+button:hover:active:not(.hover):not(.disabled):not(.focused),
+select:hover:active:not(.hover):not(.disabled):not(.focused) {
+  background-color: #d4d4d4;
+  border: 1px solid #858585;
+}
+
+button.default:hover:not(.pressed):not(.disabled):not(.focused) {
+  background-color: #0670cc;
+  border-color: #005bab;
+}
+
+button.default:hover:active:not(.hover):not(.disabled):not(.focused) {
+  background-color: #005bab;
+  border-color: #004480;
+}
+
+button:focus:not(.disabled) {
+  border-color: #fff !important;
+  box-shadow: 0 0 0 2px rgba(97, 181, 255, 0.75);
+}
+
+/* Fields */
+input[type="text"],
+textarea {
+  background-color: #fff;
+  border: 1px solid #b1b1b1;
+  box-shadow: 0 0 0 0 rgba(97, 181, 255, 0);
+  font: caption;
+  padding: 0 6px 0;
+  transition-duration: 250ms;
+  transition-property: box-shadow;
+}
+
+input[type="text"] {
+  height: 24px;
+}
+
+input[type="text"].hover,
+textarea.hover {
+  border: 1px solid #858585;
+}
+
+input[type="text"].disabled,
+textarea.disabled {
+  color: #999;
+  opacity: .5;
+}
+
+input[type="text"].focused,
+textarea.focused {
+  border-color: #0996f8;
+  box-shadow: 0 0 0 2px rgba(97, 181, 255, 0.75);
+}
+
+/* Interactive States */
+input[type="text"]:not(disabled):hover,
+textarea:not(disabled):hover {
+  border: 1px solid #858585;
+}
+
+input[type="text"]:focus,
+input[type="text"]:focus:hover,
+textarea:focus,
+textarea:focus:hover {
+  border-color: #0996f8;
+  box-shadow: 0 0 0 2px rgba(97, 181, 255, 0.75);
+}
+
+/* stylelint-disable property-no-vendor-prefix */
+.panel-section {
+  display: flex;
+  flex-direction: row;
+}
+
+.panel-section-separator {
+  background-color: rgba(0, 0, 0, 0.15);
+  min-height: 1px;
+}
+
+/* Panel Section - Header */
+.panel-section-header {
+  border-bottom: 1px solid rgba(0, 0, 0, 0.15);
+  padding: 16px;
+}
+
+.panel-section-header > .icon-section-header {
+  background-position: center center;
+  background-repeat: no-repeat;
+  height: 32px;
+  margin-right: 16px;
+  position: relative;
+  width: 32px;
+}
+
+.panel-section-header > .text-section-header {
+  align-self: center;
+  font-size: 1.385em;
+  font-weight: lighter;
+}
+
+/* Panel Section - List */
+.panel-section-list {
+  flex-direction: column;
+  padding: 4px 0;
+}
+
+.panel-list-item {
+  align-items: center;
+  display: flex;
+  flex-direction: row;
+  height: 24px;
+  padding: 0 16px;
+}
+
+.panel-list-item:not(.disabled):hover {
+  background-color: rgba(0, 0, 0, 0.06);
+  border-bottom: 1px solid rgba(0, 0, 0, 0.1);
+  border-top: 1px solid rgba(0, 0, 0, 0.1);
+}
+
+.panel-list-item:not(.disabled):hover:active {
+  background-color: rgba(0, 0, 0, 0.1);
+}
+
+.panel-list-item.disabled {
+  color: #999;
+}
+
+.panel-list-item > .icon {
+  flex-grow: 0;
+  flex-shrink: 0;
+}
+
+.panel-list-item > .text {
+  flex-grow: 10;
+}
+
+.panel-list-item > .text-shortcut {
+  color: #808080;
+  font-family: "Lucida Grande", caption;
+  font-size: .847em;
+  justify-content: flex-end;
+}
+
+.panel-section-list .panel-section-separator {
+  margin: 4px 0;
+}
+
+/* Panel Section - Form Elements */
+.panel-section-formElements {
+  display: flex;
+  flex-direction: column;
+  padding: 16px;
+}
+
+.panel-formElements-item {
+  align-items: center;
+  display: flex;
+  flex-direction: row;
+  margin-bottom: 12px;
+}
+
+.panel-formElements-item:last-child {
+  margin-bottom: 0;
+}
+
+.panel-formElements-item label {
+  flex-shrink: 0;
+  margin-right: 6px;
+  text-align: right;
+}
+
+.panel-formElements-item input[type="text"],
+.panel-formElements-item select {
+  flex-grow: 1;
+}
+
+/* Panel Section - Footer */
+.panel-section-footer {
+  background-color: rgba(0, 0, 0, 0.06);
+  border-top: 1px solid rgba(0, 0, 0, 0.15);
+  color: #1a1a1a;
+  display: flex;
+  flex-direction: row;
+  height: 41px;
+  margin-top: -1px;
+  padding: 0;
+}
+
+.panel-section-footer-button {
+  flex: 1 1 auto;
+  height: 100%;
+  margin: 0 -1px;
+  padding: 12px;
+  text-align: center;
+}
+
+.panel-section-footer-button > .text-shortcut {
+  color: #808080;
+  font-family: "Lucida Grande", caption;
+  font-size: .847em;
+}
+
+.panel-section-footer-button:hover {
+  background-color: rgba(0, 0, 0, 0.06);
+}
+
+.panel-section-footer-button:hover:active {
+  background-color: rgba(0, 0, 0, 0.1);
+}
+
+.panel-section-footer-button.default {
+  background-color: #0996f8;
+  box-shadow: 0 1px 0 #0670cc inset;
+  color: #fff;
+}
+
+.panel-section-footer-button.default:hover {
+  background-color: #0670cc;
+  box-shadow: 0 1px 0 #005bab inset;
+}
+
+.panel-section-footer-button.default:hover:active {
+  background-color: #005bab;
+  box-shadow: 0 1px 0 #004480 inset;
+}
+
+.panel-section-footer-separator {
+  background-color: rgba(0, 0, 0, 0.1);
+  width: 1px;
+  z-index: 99;
+}
+
+/* Panel Section - Tabs */
+.panel-section-tabs {
+  color: #1a1a1a;
+  display: flex;
+  flex-direction: row;
+  height: 41px;
+  margin-bottom: -1px;
+  padding: 0;
+}
+
+.panel-section-tabs-button {
+  flex: 1 1 auto;
+  height: 100%;
+  margin: 0 -1px;
+  padding: 12px;
+  text-align: center;
+}
+
+.panel-section-tabs-button:hover {
+  background-color: rgba(0, 0, 0, 0.06);
+}
+
+.panel-section-tabs-button:hover:active {
+  background-color: rgba(0, 0, 0, 0.1);
+}
+
+.panel-section-tabs-button.selected {
+  box-shadow: 0 -1px 0 #0670cc inset, 0 -4px 0 #0996f8 inset;
+  color: #0996f8;
+}
+
+.panel-section-tabs-button.selected:hover {
+  color: #0670cc;
+}
+
+.panel-section-tabs-separator {
+  background-color: rgba(0, 0, 0, 0.1);
+  width: 1px;
+  z-index: 99;
+}
--- a/browser/components/extensions/jar.mn
+++ b/browser/components/extensions/jar.mn
@@ -1,13 +1,15 @@
 # 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/.
 
 browser.jar:
+    content/browser/extension.css
+    content/browser/extension-mac.css
     content/browser/extension.svg
     content/browser/ext-utils.js
     content/browser/ext-commands.js
     content/browser/ext-contextMenus.js
     content/browser/ext-browserAction.js
     content/browser/ext-pageAction.js
     content/browser/ext-desktop-runtime.js
     content/browser/ext-tabs.js
--- a/browser/components/extensions/test/browser/browser_ext_browserAction_popup.js
+++ b/browser/components/extensions/test/browser/browser_ext_browserAction_popup.js
@@ -1,29 +1,35 @@
 /* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
 /* vim: set sts=2 sw=2 et tw=80: */
 "use strict";
 
 function* testInArea(area) {
-  let scriptPage = url => `<html><head><meta charset="utf-8"><script src="${url}"></script></head></html>`;
+  let scriptPage = url => `<html><head><meta charset="utf-8"><script src="${url}"></script></head><body>${url}</body></html>`;
 
   let extension = ExtensionTestUtils.loadExtension({
     manifest: {
       "background": {
         "page": "data/background.html",
       },
       "browser_action": {
         "default_popup": "popup-a.html",
       },
     },
 
     files: {
       "popup-a.html": scriptPage("popup-a.js"),
       "popup-a.js": function() {
-        browser.runtime.sendMessage("from-popup-a");
+        window.onload = () => {
+          if (window.getComputedStyle(document.body).backgroundColor == "rgb(252, 252, 252)") {
+            browser.runtime.sendMessage("from-popup-a");
+          } else {
+            browser.runtime.sendMessage("popup-a-failed-style-check");
+          }
+        };
         browser.runtime.onMessage.addListener(msg => {
           if (msg == "close-popup") {
             window.close();
           }
         });
       },
 
       "data/popup-b.html": scriptPage("popup-b.js"),
@@ -69,16 +75,18 @@ function* testInArea(area) {
         sendClick = ({expectEvent, expectPopup, runNextTest}) => {
           expect = {event: expectEvent, popup: expectPopup, runNextTest};
           browser.test.sendMessage("send-click");
         };
 
         browser.runtime.onMessage.addListener(msg => {
           if (msg == "close-popup") {
             return;
+          } else if (msg == "popup-a-failed-style-check") {
+            browser.test.fail("popup failed style check");
           } else if (expect.popup) {
             browser.test.assertEq(msg, `from-popup-${expect.popup}`,
                                   "expected popup opened");
           } else {
             browser.test.fail(`unexpected popup: ${msg}`);
           }
 
           expect.popup = null;
--- a/browser/themes/shared/customizableui/panelUIOverlay.inc.css
+++ b/browser/themes/shared/customizableui/panelUIOverlay.inc.css
@@ -250,16 +250,24 @@ panelmultiview[nosubviews=true] > .panel
   max-width: @standaloneSubviewWidth@;
 }
 
 /* Give WebExtension stand-alone panels extra width for Chrome compatibility */
 .cui-widget-panel[viewId^=PanelUI-webext-] .panel-mainview {
   max-width: 800px;
 }
 
+.cui-widget-panel[viewId^=PanelUI-webext-] > .panel-arrowcontainer > .panel-arrowcontent {
+  padding: 0;
+}
+
+.cui-widget-panelview[id^=PanelUI-webext-] {
+  border-radius: 3.5px;
+}
+
 panelview:not([mainview]) .toolbarbutton-text,
 .cui-widget-panel toolbarbutton > .toolbarbutton-text {
   text-align: start;
   display: -moz-box;
 }
 
 .cui-widget-panel > .panel-arrowcontainer > .panel-arrowcontent {
   padding: 4px 0;
--- a/build/moz.configure/checks.configure
+++ b/build/moz.configure/checks.configure
@@ -44,17 +44,17 @@ def checking(what):
 
 # Template to check for programs in $PATH.
 #   check('PROG', ('a', 'b'))
 # will look for 'a' or 'b' in $PATH, and set_config PROG to the one
 # it can find. If PROG is already set from the environment or command line,
 # use that value instead.
 @template
 def check_prog(var, progs, allow_missing=False):
-    option(env=var, nargs=1, help=var)
+    option(env=var, nargs=1, help='Path to the %s program' % var.lower())
 
     not_found = 'not found'
     progs = list(progs)
 
     @depends(var)
     @checking('for %s' % var.lower())
     def check(value):
         if value:
--- a/build/moz.configure/init.configure
+++ b/build/moz.configure/init.configure
@@ -255,16 +255,17 @@ def wanted_mozconfig_variables(help):
          'DSYMUTIL',
          'EXTERNAL_SOURCE_DIR',
          'GENISOIMAGE',
          'MOZILLABUILD',
          'MOZ_ARTIFACT_BUILDS',
          'MOZ_BUILD_APP',
          'PERL',
          'RPMBUILD',
+         'TAR',
          'UNZIP',
          'XARGS',
          'ZIP',
      ])
 
 
 @depends(mozconfig, wanted_mozconfig_variables)
 def mozconfig_options(mozconfig, wanted_mozconfig_variables):
@@ -399,16 +400,17 @@ def split_triplet(triplet):
         canonical_cpu = cpu
 
     return namespace(
         alias=triplet,
         cpu=canonical_cpu,
         kernel=canonical_kernel,
         os=canonical_os,
         raw_cpu=cpu,
+        raw_os=os,
     )
 
 
 @depends('--host', shell)
 @advanced
 def host(value, shell):
     if not value:
         import subprocess
@@ -461,16 +463,19 @@ def target_variables(target):
     set_config('OS_TEST', os_test)
 
     add_old_configure_assignment('CPU_ARCH', target.cpu)
     set_config('CPU_ARCH', target.cpu)
 
     if target.cpu in ('x86', 'x86_64'):
         set_config('INTEL_ARCHITECTURE', '1')
 
+    set_config('TARGET_CPU', target.raw_cpu)
+    set_config('TARGET_OS', target.raw_os)
+
 @depends(host)
 def host_variables(host):
     if host.kernel == 'kFreeBSD':
         os_arch = 'GNU_kFreeBSD'
     else:
         os_arch = host.kernel
     add_old_configure_assignment('HOST_OS_ARCH', os_arch)
     set_config('HOST_OS_ARCH', os_arch)
--- a/build/moz.configure/old.configure
+++ b/build/moz.configure/old.configure
@@ -76,33 +76,38 @@ def check_mozconfig_variables():
                 error(
                     'You need to add `%s` to the `wanted_mozconfig_variables` '
                     'list in build/moz.configure/init.configure.' % option.env)
 
 check_mozconfig_variables()
 
 
 @depends('OLD_CONFIGURE', mozconfig, autoconf, check_build_environment, shell,
-         old_configure_assignments)
+         old_configure_assignments, build_project)
 @advanced
 def prepare_configure(old_configure, mozconfig, autoconf, build_env, shell,
-                      old_configure_assignments):
+                      old_configure_assignments, build_project):
     import glob
     import itertools
     import subprocess
     # Import getmtime without overwriting the sandbox os.path.
     from os.path import getmtime
 
     from mozbuild.shellutil import quote
 
     # os.path.abspath in the sandbox will ensure forward slashes on Windows,
     # which is actually necessary because this path actually ends up literally
     # as $0, and backslashes there breaks autoconf's detection of the source
     # directory.
     old_configure = os.path.abspath(old_configure[0])
+    if build_project == 'js':
+        old_configure_dir = os.path.dirname(old_configure)
+        if not old_configure_dir.endswith('/js/src'):
+            old_configure = os.path.join(old_configure_dir, 'js', 'src',
+                                         os.path.basename(old_configure))
 
     refresh = True
     if os.path.exists(old_configure):
         mtime = getmtime(old_configure)
         aclocal = os.path.join(build_env['TOPSRCDIR'], 'build', 'autoconf',
                                '*.m4')
         for input in itertools.chain(
             (old_configure + '.in',
@@ -132,16 +137,20 @@ def prepare_configure(old_configure, moz
             for key, value in mozconfig['vars']['added'].items():
                 print("%s=%s" % (key, quote(value)), file=out)
             for key, (old, value) in mozconfig['vars']['modified'].items():
                 print("%s=%s" % (key, quote(value)), file=out)
             for t in ('env', 'vars'):
                 for key in mozconfig[t]['removed'].keys():
                     print("unset %s" % key, file=out)
 
+        # Autoconf is special, because it might be passed from
+        # mozconfig['make_extra'], which we don't pass automatically above.
+        print('export AUTOCONF=%s' % quote(autoconf), file=out)
+
         for assignment in old_configure_assignments:
             print(assignment, file=out)
 
     return cmd
 
 
 @template
 def old_configure_options(*options):
--- a/configure.py
+++ b/configure.py
@@ -19,16 +19,20 @@ from mozbuild.configure import Configure
 def main(argv):
     config = {}
     sandbox = ConfigureSandbox(config, os.environ, argv)
     sandbox.run(os.path.join(os.path.dirname(__file__), 'moz.configure'))
 
     if sandbox._help:
         return 0
 
+    return config_status(config)
+
+
+def config_status(config):
     # Sanitize config data to feed config.status
     sanitized_config = {}
     sanitized_config['substs'] = {
         k: v for k, v in config.iteritems()
         if k not in ('DEFINES', 'non_global_defines', 'TOPSRCDIR', 'TOPOBJDIR')
     }
     sanitized_config['defines'] = config['DEFINES']
     sanitized_config['non_global_defines'] = config['non_global_defines']
@@ -38,16 +42,20 @@ def main(argv):
     # Create config.status. Eventually, we'll want to just do the work it does
     # here, when we're able to skip configure tests/use cached results/not rely
     # on autoconf.
     print("Creating config.status", file=sys.stderr)
     encoding = 'mbcs' if sys.platform == 'win32' else 'utf-8'
     with codecs.open('config.status', 'w', encoding) as fh:
         fh.write('#!%s\n' % config['PYTHON'])
         fh.write('# coding=%s\n' % encoding)
+        # Because we're serializing as JSON but reading as python, the values
+        # for True, False and None are true, false and null, which don't exist.
+        # Define them.
+        fh.write('true, false, null = True, False, None\n')
         for k, v in sanitized_config.iteritems():
             fh.write('%s = ' % k)
             json.dump(v, fh, sort_keys=True, indent=4, ensure_ascii=False)
             fh.write('\n')
         fh.write("__all__ = ['topobjdir', 'topsrcdir', 'defines', "
                  "'non_global_defines', 'substs']")
 
         if not config.get('BUILDING_JS') or config.get('JS_STANDALONE'):
@@ -64,10 +72,11 @@ if __name__ == '__main__':
     if not config.get('BUILDING_JS') or config.get('JS_STANDALONE'):
         if not config.get('JS_STANDALONE'):
             os.environ['WRITE_MOZINFO'] = '1'
         # Until we have access to the virtualenv from this script, execute
         # config.status externally, with the virtualenv python.
         return subprocess.call([config['PYTHON'], 'config.status'])
     return 0
 
+
 if __name__ == '__main__':
     sys.exit(main(sys.argv))
index db37cbd9ca1a6e1264267a456372b7f12e863434..238c9756257ea0d9d8dc5f7e639d7ab6716b6d95
GIT binary patch
literal 5046
zc$|$`1yB@B-#=19Qjl(t?rx;vB&8)h`hWu@B#st=qoo@J1S#QAX^uR)50pL{5qOZ2
zhELy_?|a_QdES|KcXns~JG;N#f9!u}fBHZyYzhDXfCu1=@X*|nm~8|Q0RUE{0Ko52
z9W|rJ{93x|f)I~Du$vo5z{?x7lo=p3y-(XeY8#*5m(yhy2fxOBrJRxM-{T4;1Jf>0
zh}!bOZ2dXXts3?!;I%ZZtZ(>%Kb7sZ42r9F^tWrqptn+?`MZ{1FAmObmWF*5$4?gv
zuUaq&qKV=SWJZ|X@+o@(W2K(dm=wgpLU@rNTx!sXvjpBbvphrRH3~mX3$z2^I)MOi
z3{&tiUUfdF9#{+&9VU8yvx;N8Oi18<lYwoE|C*&UV~d*I)6+(Xg|uAr7F$x1{=3v5
z>eU8}?SZChyc~0@hl9H2t;39hLxjjFyL90C8H4^7HWh35w+IoxqZ5{ud?9M35Jf<Q
z)ZSr_)|cJZR6a(|Xm1~Ovi6O|4yRPMfR^WJfY(eMA`$-VZHV%t6pjG@w;flZNnbB{
z3G}?~Mf#fy4~4Pf#&y{W$Hq254L7Oqv7ZWAc7`7yMRNmXn#mUNRr9vrh04p5bbc13
zCao^lTvioHR8lo3%L@|TgMR(FZ}NN|O>oXjkO*M<+DDJcj$lXu4$LKOY=*r6(6{0J
zwd^h>GWc{ivjl^p?py5{Npblr{mwlf=v{Uvg;0!pkcEl@x??rv>NwTuR26&EvVh5s
z8uYMkRCQ!o3gAt)7x(bJ+<}6GnRN<VcA<#NU>aDYvw<u^?g206k$ewIpT9>tF;g<c
zQB8(ixM_x_ZZ}SXa0)fdZe?HELL7_!#H@;IY#mF_cV-}paC$IQn<9I!&%%#nOV-$`
zqL4@w)9FYvDm`Js>a^D{m*6W$-K=n1S~iK$sf$pv--od=ANWBarTlbz%Q>n>2LA?a
zw#x)7NW?7BVjX{FpR5N-I_2=EPE7JPPF$6*k0>dt@P2DyQML(OHgfYHoyJ;wM%O%c
zzDt!t$h75^y0oIFH)Wzo!;v2^T)Gae>RfsSI1N>ppqE@xgIP+fK7)!mEFUxGN_#_;
zb04t?%>4+7Nm;9uk)}H}L09IeXprcLD}5m<gc@+fEN`6Q&?>JrVY17CcN=K;;{s|N
z>gIH3CfY7{{EkEN1V%2}0;5NB0=?gzAEWyH0>D3%Eo{3_Y9txR&gOj>t!jg){NL8y
zKeex#L>cfMSRCd(Aso4>$a$J-*|Y_WIOAob-0DNF@NX7z$m;rEU9Vb{bKBTVXuIu0
z<nO{K!NEa1HrmBUC`)(dB~3^-O@+M8YOQycNAqZ7hSfd(i{ihktW9rpN}Rft&lE4!
z_!F0@DGk%ysUoJC&qbiP)GsVJNy_iQa|BUg-;_dk^#^WynzFq#zV(V8sFl$6@A`RW
zZDdZ}e4e_V;C`VR6zf6x(6ko*^I7OD?58KuEqbKcs8V})?IqNr*w<ksnUImQO43|K
zJ?o%HRN$S2j`)qjU)HQcd1FT!vC_y;@vQp@$E5+Y0*LHSvoVDt11p|)`}1=KIh=!6
zL41*7jBG}gx6=Yb5;{lkhSfPf8g?4zOJu#)c#~_8@t7!dbgC5YvWRD7tLpIsZZuW>
z!^#;lezNQCS{vzAll0v?VF<~v_VPHC*zg$=q?V8>r!egX=fAh$w#1gdn{wMtLu0v3
zKX?cuQSd15x=_$!Yj#beIKsV0U&p30?d+c3?38J;Ne9x>a9LTyK{Vh{M2NK+AtQv(
zyBp>V8a~a-Z9W>4RM+i4Z6A%6e`vis15;b)wY{$!3OP-HFtI2ziOa?(+&59$)%n;*
zt{wQWJ(hd=6b}4}475)?lPHtj*D<Sq+uj;j<rqoW)@e1=QUCH~_L^z5r|!lyqE^}k
zj!HMk3S8%XO0W8%^VMT3i2?h1X`1}<{N3KVJ|r$gI$wVXUiT=M@iOLf%Sg5MWl>1M
z&B2QHW*Thg4co3ya_OT2FssT3Jh3ld1jrc8BU|liV6ts#4$k5#3clrnE>ggj)(M8f
z&!AN3iZD-zQjzxbWT0FqIWn}bY25ka$M<UQBpk)Di#i)H2z<6=hgj%+R%~qWhZ*~^
z?y9J%aIrh=^7>O%Sr5XW{iMoUU(`bXh+A5(iH%@2d8`E@=^(f=+$lV|a~!$mjF9x>
zPBdX5X|pAF)m-i07Ra)Z{YEMH+3U(G4w%z5mi{5I;AfQcw(mQ+uGPVuq3+}Iqj6fv
z^Re;*9<aI}32gZ}P10p`szS#rpn)E?Xmo`ptwbiO!UJ{nd?>GUqIFs#Wme(@$2M{k
zl!&a1nUH>YmB)g9_9pulmp4N1Jb@2|y<kXpERd|d{J!LRo=wr(V+5Dd<_)*G(A_9U
zVoW1}Pt63x%rl(J!C%odCcSo3yDg|M3=KIW8szgcCihj*<;iPY(MQj3XTub~GIdDp
zoE*JPGwE^f=$bt+wU?XEg!@=I&rmxBr%7#4r!NtZ?;atHMmostdq}_EA$#XFN+q2o
z%tESbTiE7W7Py--gd~pCzPX5c#f*#5gShEi%&UZz3iNEM{q!%G>3V!=68kQJ!qow+
zy<Tx?yo%A##QRYJCo)KyG8x%{Hllb?E8nG??b{!{N05vdSjn?-%m>QTd4$?-Lrg&~
zLQVV~4)%eQn#e}AeYZ~R+vf}L-1qF#h7(8>vG&=Fe6{ZErlM`sE++{Qyx8Z1qBIV-
zXj*)U!}3Xh-LlMg{>P3?{!1aoH!}%%qO_1tEVY*}t_(b|9}GybZvlzt`-fW|v(^^g
z;MZ3vGK2dtIIMi0N!xx~CPv=crCL9XF24IdW%>^E{x2DqClrY=vM<nuN<qS?PCjEV
zt|B%7P9%=mPsVr5nA#*tN=3DR1%xg7Dnj{eo*MVZo+~VP6jP{c#hE&$pa28&;)_d!
zn?55Km2_t~ub+(M%d&0;^_!>q=9#8a^mt`|Eg*}!vXwk7NKMslip85(C@1w=+Ex;?
zNGSzVHHQg^5zy1ncx(bZY_4wV@hF<GZV4YH{rBuiO}yEAFN~~j(X9rINvZwNmcan2
z<~t%cbf3+n=hKyeb8_{;18t~LJ92uTN<F&9M&Tj+KF=m7={AtDW0E)MvD%1RAYO4T
z3^=2NI8Mqz6$`xTIC=?=VyyjU+9X&P+si1wb8nJgz=U6jj*Bh>lE3za6}B7O<ci2C
z+|qYIZ5&K+Z$r$}2BVI|W3AU0Y4`OtICCunm3SkTd3IuNsT<ZGPB8OxeFD2L?y(hJ
z=3yxxrHbiFQno3|*|piGvV<z2ohtWGJ2@p}V3pBD)u-m@uVAEf9lh9cq}LffntIa^
z4}~w8x-S&oYLJ)ql%aI9j1l?i#Z>g<{lSd$BiP~<`5V~<K6<my=u;jd`Y((&VCC_y
zlya8hNszfQsOIvs!>nxEL=Bx&ULIlJ$h+k+DtITN&P!}r+sb<;ohHsgZjAg0BhAK&
zh)1VFx>T4WEU(brKh%@^EXm~R!*2RWzS|=Ci@_l(-?99yeG%Rg?}RqKajjE3^VP+?
z6swW4M;m3PmaWVfHk)cQEUAjmmWJDT**u#iiAZxM1oI|Fcn~zf?lbn4qxw}P#tkyE
zdQusaTU|XRR;kFL-FS1ma8SP}Gogk=LwU~*bUNrmS)4eOX?>bLv_<$*U_I=~N;!@>
z@NJ99Re#lfO$c^KF|zMtGSxCB4Xe_u>ZtH+Fc(#WVqJ^YPssNitoN}m_4q}Wo2HLg
z-LO@{ui=e@SqC+8N}dOI!$KGEl$*s>k$ntAA&fc8##9Dyfl^Ka-7O%nVs1Vu3q$w(
zy%xJ%*H_XI;hAl&4*J0}Q?W_&XmzSI%re>SE$2F#uhuH}H81KdF)We`_-B@~BC9Ap
z$7yDewzM(}EuYo?YLndbC*9cy@>(t6^*#eL#5k^g4B?hl?C`^ev=2mAG0?%?5x`yU
z#L6{U$5c@!I2TrZ!ZJToVB*lb<5kvlOX=6O0S(D%4^oRaA%at2VKcGteO<x3WPhua
zlEMCT=nOtSj5P2{+6Ppckp}Bus??}%>JzLNXQg7@Ql3_ezDQ|IuF(I20!z4Z|7;@!
z$C&ed_226qUBX9DV(v7}t>Ef~Eq)%L$1NZZEaq)ewkZiFr-!89d?}akaT6EYa?_LM
zwCB`S(E&E$G9GXSAaJmT9}*{Oouo95#z?wav5Rl*Z;0TK)QQV(@tLzHW+PryY}xr8
zPC3zNcV>+9gnXZwJhM^QwIf})Q%_GVLzs^)&^+h|qbe@7r^I&RoFxtTH}#QE-U8Yr
z4!qF4&-s^_Qn=@A87Yk7FWt)<Ni;HWs`A3yqy{l)-Uk@KKi9d9%3T}e@&&?5zKhzj
z5DDr$(Ts0nh?r2W`q(mYKAx!FC~$e%zY{X5E1xojyKiBWo7j{uTxWaE0)~rp1XQEG
zfUQ@19)3O|ba!ePFK|4{$qCUc>;thKiX38CDWcVzd7J_SFT0iO)w?8ohhs-?<sS|y
zS0Ps0hBt;kIF!>Kkq!e(8ZYkY|KE@4V}PA{sbN9U#xE%x0|2-Wpa$4_c=&kxc!4|x
zT)d5qZ~#~-U8hFA{)7Mw>~B~Az`wfSBpqO{5NXuG4dsEs@YDb!l^lLV9U)=hp_GoH
zY>K0{$lPW4-I5QEd~@bS&{i-FYONO~0DZl+z<*R9<-LP;jMc5saHU19fj8ncxCa9l
zVaH9GVsFR1c5K>fFfkeAr^~rjqP)G6Nr=Ne`GTJ>6d?<0lIA=-zt`=%%gEhlHp@nb
zdL%;m(#X_SrCiq#@BPfo`UyO(9dL<_*Ubs|)HG{*#nng*<13HHvUd7gQ%`Iw%PQQ<
zo)v<l$ZP6VJx8=zETs+SnFEH%YY#6@HKv27L~L05igh#mF}M$HN<99y60@y`=2ti|
zfD{t|;Kl|32!B}#?C$LYa&r^#vUmKKk%Gj(nfzfSho@E^xk41d+op??jbL2mVsTac
zrB8fQr6yGwE>i`pSed<avjYe*t@4|*W>QV(g3j#%Z^gvgZNKRHFsEsCu4YdS>lMr)
zBL`)7Dt8^}+!jB$XlOsR+<s*E=Stt$A8HPGyzhW@Srw`1Eb?T`c^1;|Q(;57J+A`E
z)VfyTx&&`z0G%t=rCdZIVNN8<f<IQC5z`wQGeBq7<@cH~D)2-=nsKF%MxF~gJK=YK
zf_WLt@^u&yac35huXTs8V{*=t8H=I?7cL8?o}nF2A@XRfKHL86JF^d+iGriu^6;~(
z_C_Yj4Fd|b5YkJ~fKP^~cUmvWlN`FnnUOmB0Rh6-kA)85L6pl)@O@u|YO0ID8($j#
zVwd_Y7in3TqcZK9T9>wfT4EIKn{<%$1M@tlw7GbRuD+Oh0V(dAo#OdL5A*glpWH+H
zsmK;PrgFR2FJ^ml&<e?1YF}Kfk)^I~cuwz~X6n~=3Pm@4URreT7FS31Su)UOUKLw<
zyiqVsU&7Q4R#b77sV=-0EJHn~-)Q6`!Ww(T#3>z@0+@3i>6h#N_EIkYnoeq>0>~0t
z@Q6vxdcsqnjwO>x<~kTChh>#}Yg}0K>Z`XE_1kpza~@HDr8S^#&<bpWqc8v08~5CX
zsk)Wdy<RfDpwP;vb2VY&e&pPO;}v@)#waQPUw~}eWvbbuP;2k{->%(nq9T+_YPkEC
zM1k=qQ2}xXJ34s#2tXVYMun3igsA%t+Y5`KY~2h6%H8^I@smo$i}1!UOEPCLTId8-
z*!OM4XCYPYZX@&1z?zmYu3p%rQn)XCn=S45EeuZ2{{wOMB>3@@hO_veH6r98_vqH+
zYdqoQ7%d6N^`sZmo7}k_(<l3PPj;O(UXS!VO(}w2R0d@-#(AC!W7TGCf~*Tvw&_7R
zkd$(PG)%%M*V>PFTY5B{zC})430d@S7hFV?&=)5k8`&l&a8BW~vDYr~jGDYtI=<_7
zfd8-a{fEIUF2AIJU+uv^ku%<ogkw*}fqdNj+A~Bzex9+B@sEZ=)1oU!zQQxUgHQDM
z1tw2*MuwkYiBwbY0QuU3u33TJtj9}i?d^noRRoqj!w^VwggiZwa5|MSb#to|jp+r{
z=_1Eb-N^YKb!&?~`=gvkoC{trFn%2k1Cs*lKQl-FTf#5^|A9yPjlhWYpEK$2@_X^8
zaFJiQ|4m-~cf^0nI)5XY5d;349Q3D>e@5NkN>-5ma}558@TU*|M#v}oM~~_Qad3Z6
P!1-03e{Cy8{#*JV%yuOR
index f40f9d041ad6f81f5298789c046e94df2276e8cd..2f86c4d4d5f68a212acf5e59cdb9d5f7a5cb60a5
GIT binary patch
literal 5046
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
L?`Ory{&@cbqVGj;
index 6f8183822b0ef4f1c12efe13e438dc62bd1cbcb6..6da2fcbad77aeb90b39898a5cb005d6f2f8d6f93
GIT binary patch
literal 5044
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%0DTLwkK?{IgJ{HbtT$S
zY{&X%#8P%yQoIhhdX@_^D)**L{8Gu3k%Q3djVcTrNE)5C!!M6^WfR)i9%`7QUiXPU
zX)O6g<-C1$|HY`~%~~LTCiW^gt4fGSG~F*_jSGTloyX63jF*S<61jNdoUM~8dn=(X
z74<cH*~CJQN80WDD#Z(@N#v$f${4qNvx!fZQ{_MpdJxoMka7N<;-~66@oHpwD^kkP
z(_qfpiAGYoc`K-$F6Ta8b$vftMHl$7@R;0$d0;%Ba8W98>f)Z(zv&b$yPRRIzdaDf
z-*pO0M?0tu+>HkYjp>(p{f3XG>(Ez9VJ~OIf>3y=mA$>v9)&gS5j{Lp!{7BaCn@0a
z@yq64RkOfB#(*%s?Xh6<@l2pFZMa>9Vi8ELyFy?oY$EuzCcDl}0&5dv=Fuhw4Nn#K
zm!r^J?=oaycxlY=h5rhgrH}bmOo544nY`PUBe0Y@AbGbr1$Vl*Tp&c~F8^w`bpmi0
zx9~0xcR!Sv=fLUK5N|}=_qg_T0j`Sn)2DY4n>jdgWi3PK&ye(^?F@S5#e>X@3$}j`
zIVn?R!~VDD{d-dUlQaW|5)P;hs&a8~L&k|!xgQVo4OVOOjR`Itx$}>^|5VfD<{3U!
z@9R|q3Y38`DQ<wo-18$3s)^h4{4z^JWYypJ17Wbn5XlF`{K<uO2412{IC@_B;wfRt
z>l;tKeU)g!utZbWji+2)FaTPr7?>d7f7Xru*Mcwr|3O9igTMg%&qVsi{#>pJ<|hXH
zSG4;75&wyF{z5b$0sJ=<^!FhD-gJKjSw#BJE%<kYzt`|Dgmkihtf-bMHqM^|*uRJE
L?`K8G|9JlcICvw3
index 1479fbc59fd523a9f25efa4911995a0f026a12d5..546deacaf81c59cf28a7bbfdfbffd6b7838cd024
GIT binary patch
literal 5046
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
NyIKA|mKXPr_dme&Fn9m}
index 2c8ae834e1eedaf5f99f94a83419d3b887fe2ac8..e2335e3a0462f1344d412552263b43345bda9d4b
GIT binary patch
literal 5046
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
Lzn&Gp|J(Z)^;-|~
index 27a115f1f2296dc820bdd3d7761311e80a360517..75fe209eac3f6c16523e57976464e1db50d9b521
GIT binary patch
literal 5046
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
NVgLJCF!>+ezW}-oD?b1L
index ab0ec357a48b74926ff1b56ce8c416a2ab5f69bb..58749f72421d1fc04c91a08672c8d907eb314d48
GIT binary patch
literal 5043
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
NJsf^ND@p&S_dhqREVuvw
index 66f293e7fd9a48835721fa203adcec377dbfcce4..60cffd46eb560f796e2c83165a62e44057105c15
GIT binary patch
literal 5045
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
Nhtuz8MM?j7{{xqHAZ-8u
index f099114215f0849da4998f8806c3eda10d2fe600..c54cae3aa703eaff030fdedced22c6cd0f30a16b
GIT binary patch
literal 5045
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
IgnxSf1G2F)y#N3J
index 75b86a6bd093814fffa6f3b6c35e655a44b3236a..9a650a888211adf65c511e1fee30d072e857b882
GIT binary patch
literal 5048
zc$|$`2T&8twoV9Lr6V9sib5!%DIEa?1cFGfLPP=@DFFh~OHe?1?@fB|9i&RH0s*A=
z(4~X)r+4PP|J{H7J9BqucjoNuemke^nLVEx6og9!000O9s$NLNh=wq8;2i+KhztPu
zv-(0_OO{tjRe{e6>4LDdG=bQmOlD)9MWfuOyVeruOyk2J_lgq=Je=U~Zi2#lAT!U(
z&FH3s-08E}_1WsoLc5DC^~>9Nv)EZ@Vle#bED?KZyY3UN&7NO9rMgfIL!J|-;<3w@
zS0VFfVxg3orBkf550;OXh2wxO@0fhX0GXwmvOs_zE*-gj9EhKjlo40%+8*bCGuI>R
z>BKFK*V@kfoB$tIz~T2(zdjjkb0c8ISWRW<l${?c>J5622w4U>pWsmv_>l`>zV-DH
z6}>n*eQ+*;=R)RgGjjjKe839XMPEJw?k#-Gk-{dnEAeGOYQ{~{ZRR@`at$YaOT$1C
zHAm`Y%W!-(O+>%<jc9AzzJFszEd6DRz%KJ-2>I2ljguO7mx2xm8TMk%!zq=U2lSKP
zFz?^<loz9Hlm%LwCrNS!Mt<w*>0MqO+E(&`vC}?lwe{YX4tSn$-r(fy<oZkW%<pn{
z6opQ@@J{(S`C0LR$o^nY*3h{YcTw-8c;}+%{-b7^JzXjgftDd92T6d3G<%Mh1;2pT
zeJFqk$TY{!mm`zj+{yPG1Xf#w?J|G)*utrHw|ma>AtxTOjB?J>PkkfvO6w5UDV6t0
zb9FBaHQ5MJhE~iU^pF;;g)rr<+c;9v`<^P1-N~3r(X-FEbk<C;bcILl_AYNmbfpiF
z`mf5=Q9k*>k0hOoNsDYE-<MxK+bT-Vyy~U5RFipdvM~^$2p3|ZI&>*T7xy@=mmQ3@
zGiArF>p^&s_*f<T;=5}doOS8z6s|pbQ=QaJ4_<DO&Whoc(S*(ilkYZs7(Z&~2eE--
zA-ymBI}8H+tvHu3=4%^{#@+CA|K&~t&NLvrcK@@3maWHLPqFW9<o%|xy$G&*cT*{e
zk@})PI^(byl-H9Avs%)#*Ew7CtZ#90T|Z=p@;{^1D6*}(4KqIK<BT3>=KPuKmQfvd
zeOA$q$761W+E1eOubflTP8HNL&{!*k7e_VFoOD8Btw!B{g<V}44PY3@_sD%0(}g;4
z?!GmGp$x2x>)9~ghJ~C~Q9)z|F(2vS9v%Dfqjlb_;&-~q{qiFw;JPQ8M|3hAqd`C7
zt`y9tO)FI}Q|{8o$t<D3Y>N27488e>Lc8jbPINi`(JaR13SSXN4k>Y*>QIdD&e;P~
zoAA^NlS(ti&rIq%YdcZ{-fWSFRYYRe{k6WDn^NE|2V)42=-igETZ##Xlg9I-v|kzd
zQ<N`nHE_6!GccV_DVDaV6JYEToyV8ZO&R2>Ukxk9)o200>*2K0D?bx@n12d2ice%=
zYOgvaZBy1XJFES;FIN$p1dW6HN3!lXhH9Ok$J!I>CbnY}cp(ZK*vW$?tD)O(gy3fN
zwb50t1u|a!texe0&$pSHy-vi=K@AaMP9Nj5rQ?#h*WdiK0cBaA@0{_=s6A$YtL->E
zJcX$Kdwwn*`RRHKC*<C7q%@uOdj?)n=J7^3)d-%G2Ssc1g!*Z2b3VkgWuza1U=o=3
zu}0id^CrX&TSm$3c?TlJd+FG>;U04}@x;NCFEwxWG*Zh8e$q0qOpkF5k7j9E5I(<*
zAGqko<BwKiZinaj8&G84jRL8vHh@nv^VqGSs)AGm5tXXdWg8iIVmipmOk|%Moo$fD
z!d*tsu%-YG+UE7NqJnhmBr}X#fhBl}5jd=+%=~rg4%o1(Vh%o>XF=t85WxgCe#~8F
zS8W89{#dad<HW$m=uvDHzINK>oBi=10Doz`O}*F06vV!=%+Pj`tO&C+i5&@NhnF}M
zLQ62!)*kua6D{(q4@0!rC$!R>pP@bP9aul)Mf3-5LcTt(Ycy*N7^)*|CYq?MU#RWW
zVmV^T&r>}z@fu#FL3yM5s>x@|XX1Un(mCUU1pBMDecRH&OTzL=Pl(-SuOs$nQ^AyL
zY$}{gF_a4%1+hHWdSzt$IyB8PPN?axJ+(mPTTk*;k_f<`dBbp0FVJ?h+_>jk+_F2i
zl1uXewz6S21f6x4{_QPNHm07fb&(?b5+183P6hYbxH&$?PJS!tZ)(2@y)2;<x?ygW
zAb@xMJS-dH|NVL-w_m9|Zf>UxgY1Ks-D3?yu4}r{1h3qSdWz|PNnB=l3Xjc8A+@mY
zX6_w9rgQTt58-m6z+-WQ(bjkaQdLA-Fs)k@PvGOA!ROw)jC8uotmsMb&VvBURt{0)
zG;v~H9Ut7ma#5-f+y};ex5jSTZ`MoG%t$<uAEp^!z8Ui-7O&l%Qg$;0s?mY9<sVD0
z#$cB%sTYlNMwJ~tE~1pa3FeIqB*mLFZ!n)s>EBPFE(u7Z3{iT8h0u65RX-7Nu+4B?
z%It&teNxyO47>idp$MLDG85|tV4VUAn9d1RilRD*V>VCH4A?7~O0$~D>aE^9yX$gS
zikVI7`fHhVAJ!kLQqlFRzzUtK+7$jQJ64PbkIz!Lpo!4U(PAGcyT~T&BNPN=qv4Wm
z#tyM)ykdbhdraPp^@+~Eg&^=Ji*dmQa=mE&#a8g<EM*^EF1MyKjDW4Ui>o0<cXE90
zVkSS8<!bCZW=M@C7dk26)*GLryTf(fDe$H;l@SO_U$Ss$YuaXskma+0f1)d*zUd~^
zF})u%9_ASR_4S;P0>vG;^L{p;vf0DM0R3m*^tO^ae?ECYK|uMMA+g-(GYi3w%78h#
zH_q)M{8S#MAzm?s-C@mwb{F&=CRs)zsoKK!4hR});)zL_&|5+a8n_M!DHlD?+a`Hx
zia;t^;`;>YCrl5d36e-Y0b3wWuVH1|?yZZiRzZNeldAP51+)qw{%xEu85w@9O*Qv!
zfTA=>Li|ZB`jUo8;<{_WoQ>UlCEs|R=z_qrHGwUr2Q6_)?*{7$0)^45LQh&Fs#co=
z38TcJX2L67?Nstte&I4efZE;Gb=n-#cK2bN1sj24wx4Kplk&*OO$~ika&l(!Rb$9m
zz0(cIa=r`J@y@lqU;--YW&?+ffC4vyh`wbAN6tQt86JDZ)6=k)+$>3Xq(vr>$cWy^
zlQ1hdXe52%QlMUcdv=vct@(?Q2)kxmLoY{;y&!G2roQvnnQi$2&g!@4U-0)ohlJIf
z_c!Q|FB4!$Pc6pm9C?+gTS%*jU~ewO$4k6>1c~Y<)POGw?<pGlUtp={xO(_X5!N$G
zSg9xd#BBJ1bn}9%e00e|*YHGc_og68qr=H!r48jl#Wh)GP0R0zNxe_ySUM*^X&kM8
z7k$7Uv+*gmM~4BaPC?(1n_4?_ttGtncz;>1SWnkwN6XfKy$Wf_sUx;JT7P{0sp@C<
zhkir3aUK;>G02U_t59Q9@XYSaUI|fiU2RNgBJ}&5_7}40{z5DNNsFK28p}$7Q@KAv
zW%Nzi)Z8nSUO6Ph?#^0n5u{|j*<$iT|8iMb1`)`Qmakk@4o=yU#*N9$l=vuBMB`^X
zDYH^FrMabCLNlM=umbKa?G3hG>@%pTH+se1L4U$SKovLAAd!^<bAEibo!?_$f>!V(
ztu9*#dCirv(@2tqmgZg+p*`$kTdG8vXm#)zR>W?ka7AWV``brgeqdlX`)1qjkOr;x
zw_M{IU$VN=T&qerek_-UcEq;+AfiAPlhKNdW%_cWQN4HMA61(oCM|FmJib}2T5NQV
z#dv(y6(#O>K}HJ98#=edy}jZ6wz3<&y+#td24FgmC-l8=$O4^t7_8gy-28Bq2~X7#
zwGL$ruHJdtSLl)e-P`<G=<&g+?6NJ<GYBGzM?5^9%S7$gUG|`JX=V9xvB^AxYy%yq
z`Bbg-uBmH0XvJMZHL(!eh-qVNOLr?!m>VfRp4G6kztzk}!D>&_g#8fT)aTmbjj_XO
zY$7KziUiyoswTI(OdfS@X*zs&Cf}3NRPt^-%$^i807Nr}jn{gOFoMll2Z>@X5Q*Bu
z8i8kQBC0E0NzeCI-*Wfr6vi#pP+hfw5{($1$i~uEXxDEB2QN~y#%8^vVsg8*l=|8v
zK)9S62FqJIu6mKC4ff87LJy?aZ>4oqaLJo$Y|v?&4PMLXb=eS#Js3TC*lJm_TOmdK
ztK>=0l7^Bg>SyvO1iI4UfnW~f<|dx@P%fgC^2Teg5_r#=B&?7E4rLx{V9xR5G*qg3
z_@Xl^p~)(c+i*h!lbbx;t-2Z}Ag)|CJ~c~Nvy)Z4>zxm&4gFXm6a1+_a0M@Po8jRA
zcLYaz(pt@C_wsg~q$44odcwfahH-lrj&B^Me{m!@)?XsUE5Ego3LGy~n(&dQQ+JGk
zkC^M{C*EP~lLd6md1cf<h^fv`9h|!Ebb{XWYB)p2<t$13hTg{@iw+b)mk0(b>1f^w
z4LG{}Yh}kcx%KT<J)ETT+#ULrE<V>ll(xI~%f_(>_mVwHeT~(b#kF{)!4<}Ql_a{{
zdDt)Wad=E!>nH58deji}b;V6!U`sPV?f*)q3TIP=OpTN;E59W)5CFIhpar}^BJEN3
zb|yBE_b6>GJOC)7^;pZn=@tNpyAA>X{x!LWzJRv#llksmQSYkvjdU~7ND_IM-n!+o
zFZx15BEno*aPk~|Gi#40RTq2ahIOYKU1}eNxcXqHc@N5cQ5*B-0jhb=E$)pjAy$H(
zgL_<N{10nmAEgc2ZNM6faBvu<Fgf67z9>`}DGAz!$Nly6myVR8&`G4tX6cT#xa95o
zdhzp~$PibaD02BlQH!OfTt_{<E@B&FGkg;5Wqo2EdBu|U$MU2aLHUP+aT{F?kw<Ux
zv-7O84O0=m6h-B7HvP&huf#N_?mPEVl<c1!KgYO_2*Ox9(^X@ffZ%;t2J$Z}3BE=u
zVksVdB*Os!z_<Xwt>0EcSflJsEG;2+aPxl|X<lGm=Wj+b(=<XR@>995>COz-An<Y2
z>C-=18{9=`6lg;qBVLB1p-Xox;jjew==H@bLUu&Tp44g5g{`Ie=|%o08jJ#`nB#Nf
z1)N@$)u+~2>t}e0wWt0<u3fZ}NFQ|cdwbtK{Z&F}7I$eJVgwdP9)>f;O19bS#Wl5{
zenoE9vzVs@4HpBnEXcw+?|698kUr(xTd)8!2x>FqkBx%1Yk_%$b|#8}l`Q=x9PccM
z+U$LZ)u*_mwLx^TUo@85JlJtKeo%~Q&X?3*r;O0g>l|B2&x1NCy5ikoJgvoi12a<P
zjt$8*fd&VhA*RxVSNw2szBn<(CD(@o!PAIrJ)`bHdLLQ-lQI|Txmy2ZhiaKfgnFa{
zom2k3a_oCCsetUK_m<3hxFGUqUxV;ylgHG~8r#wO&$nJ%$&E!NMO{0MTVWjwWo^F>
zz}=>^&uzL#(>mELQ9HJZnabhE2@^yc_=asn_w<4bolh?0#5z@<JGpa0)5_E?##ht8
z6ZDxc9jsu$9Fr8Ng^T5nOFr|+`@{hfF+RYz%hR^4OOIrP1Dx7TgLcz<e$D%U8tW+z
zx@-^CxAAz_Za1tPxQ90He&+bXJldR4f!cE^5n`*1z=gp{LKWRw{b5e5&OS=W@fvD5
zV?e=m!1N}s>B8DuN*gD(M>K7hJEhOa$Gov;M}&jqYwt(nk)Dz5XQXQX##G$+Ja_%}
zTcQH~ovARfM*J@A>>*a>!2>Ul-ZE4^i&vKclaxdm$8798fYC78cX@X<?eNL){YqSs
zkM}1E5Zj$E967|02kqsfT@;9jXs`O+R}f3TGP&xkJ_kSc;IcH)@~UE{cw|1)qcPrk
zN#mh2;RC#e(4O7hgHz6U4|W<kO^?+PG1FXt+mLDKL5V@-doT&Y<BFu>O8MF?zcTH$
zqf-IjoTje(OU3&H4XvJs2%e&+x8L^41nc&Z9+I#7kecI5SbR~SO0>$2pltbW5KXLe
zmfQ^dcco>c((T^=mYjbN%73C~Q0BJ=RfeEEU|!|1J5XM(!TzBN4StN!!hwUpm_v`s
zOJ2zE@r(XG6_8*d)j@9o7wGZ@kCYUT=D<t=h5Mc03N8jKt2%EfhC2e$7tRDRzKL@6
z7g1&j>l}XZIr3*wnX6`5SsXFbcDBF&U{D|q73e>6NB`TrfPnwNB>h2P0{!Py`ltOl
zT!|L?jr-pu*8h+APif~bM12y#f0Km%uH@gt?k^?t$^JPA|Bmo?AO3}qO8$=?RfFQ;
S|Ji`|yTAK=tvJOW>3;z3x-w1x
index d1472e322d2d2d4fc37023e0d987d8c8a059325a..d13dd78de9cc8087db058c850f5c814b988515c4
GIT binary patch
literal 5048
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
OevkLRpA{zj<NXh^`YYW4
index 5fa042a512baae76a210637f698cf3a73522b68a..92d5cc39427c419b6b2e824e73d49a761b881e0b
GIT binary patch
literal 5044
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
NY5)7#C!~L@{{iP7H^%?~
index f1fec6fc7bed209db842d25b93af4e9ebf03090d..7a2a432ff4459e665d0b1cdf7887c81f56bd9fbe
GIT binary patch
literal 5052
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
Vsw;so{~Q4Q9=5-q6(juP{SQ{nFoOU9
index 0fd70ca9f13a12362ab54df2691c8aeee8b6d0ab..d389321956e2b75e0a20e2fcb24ff0ebf71491d3
GIT binary patch
literal 5055
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
Ws;7yE|N8*mukrlXvta7q-v0p4(=QDG
index 434ed5e0db8eda2e865237330d91b3648cda3049..48e271d54a2e8c5d0b32b4dcdec9b6f0ca880953
GIT binary patch
literal 5051
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
S{5gRAdp!O9tSrSJ?|%S@ZxR9k
index aea5862b0a016a5874ba3af1235b146417a75416..4c8bb2f10010dfe9ce2b994af313e46a7a6ebce2
GIT binary patch
literal 5051
zc$|$`1xy^wwqD#FTHK|$I}|8|Qrx9j7x!J9MT@&T6t|)ai#x^Lr9g2CMM`0DioEtF
z@BQ!o`EPR1WF|S2nQwA(zH^fK)RmBsi2(orI^Z}Eq)?U;%<zZ}0KCTs0RHT%$Z5-P
zzEzdyb_99bIyeBiTwH-`=@5~W2lAo)%!#h(V{wBp>tpeeXUj0Xq&0K~Y*@%y76$<*
zy-zP~`zz?%MEuYsK_%@b2RiX^F_8QE`Oxi=(SF-xz|?hX`cd;*-mf+pi3d@}P*Rz^
zT2-V38Q0SbdD`4ZMq<FUHZ2Mvohnu^jDePRft!UEP3-}*pTQ)^OJ4^U8&kSKp+~~Y
zuN=Af_5ekl3R$knR}HZ~gdsCOZO=wE;Xz%UkCzM>%$u8w+rd)X^-|vyEdYCwf)k|>
zw_01dH^3mCBJ(us&Me1SH5|8Nk5m{G(@X(vjRpY*M^Iu>OK_3iD-Zelixu4aixhmM
zWTg6-Q@8G)WFiH7Yv#8$4a>inV$uX~yz-aQye+7G>Ax*?AJA|ANb)V@60z05b{d|K
z{SKFtrIL}|Z%>--p84~zjR61fjro~&X%|;6DR)eB@Xv1nYm!*QzAuI|Y+`CfKmlkm
z!cdYyCVUl7u)~HL3grG5;$sxObx^KI+%u$jzYRwIJbV1bDU(6!hHJdq>prh7399?L
zuB`4Kxc#!X0o{lIgutx=w}jxQ6m<#W5938aC&L~d(0Tdmv~mN?n$dve^3>D%milG!
ziV%&G4n1fY#C4p@6X<7w#j0iDaQ7JKY<Ch%kIFyzUMoo@L7*RM%mIg4QDwt>CuL)o
zvUL-Gj=r_bt1@l8rAx6eL`1{psyH&xsw485L%T-Kb=wSEe8%yn7zZhCriMeV+QF^F
z&v#G4mlI6<g2CcDX`HyD|5ZiPC@s2f?|R)kE72E<nlavSi8zX$Inxk2vm~Mn^>#dn
z1QB0XeL2BP%`r1<s*AM3vudw1Sc&hYL8s4Bq0ftDlY|-}zhD#K*ADjSPsal@$#tU@
zRLK?-XLfnAAkIYCww2L`EgjQhiSq5nr3xPdS{oew&T^iuSt8X|i<J)s?SpH1;YP)+
zZ$v3<>iO#0;S)l!14(gc+^&2TLm66Yg5InOs^BD9F!15<$YOb0MP#sn{32rZ(E=w`
z1B4r;Xxm0ZFc;R#t2Z%m&}bzf4L6*e<orqR0og__?-QUHO7m8X6*6YPOufC@TUo^N
zY#8u{zSeM=w`0tG*d+97@a|p_UM|{7i!GYgcKc}MV*B0St}xQB$k(gXAm%w!fH5<p
z<-)6xM5)}`Vw*t*-Yn}OFFPe^N44YOdOCmP(I9Hf*WyQEPRD)4Lh#{^MK&QQo7g_M
znz@kDt0F?wX+H_IS*|y;=r*4RfOuc601U^I1?r0ISNj=n#sCwZkgd_imUsI2Xq4xT
zlSSBb*0bu|K5~BG+}6G!^5_(35*47=9REde^fC`yFh|W;xuQ;odt@?q+AKmxgds;a
zUSD#-V8!YM2ilk|K6{0%M=P6m1R3rNEf{%>?XvHLHn8C(Nr45sqPay)L$Ef^T+PSj
z0v|gYUykJU1vI|XkDppDEy^1qK?QHejpUkar8tFUvjo4+WZI<fv&ikK0$aXpb^-;!
zebBBSLh__F?;={3YWTDDQdmZF=j+#=ZeEsI4sfWAFc3;vXPGP4(8s?Ym1PdiW?WII
z<6cq=32q-BS_nT~6hpz&8t2$6AUoNj{MG7>1ywS!Cb__i?2y!P<Z-{RTxXymCkjeX
znzNc6FX2xuFDG`T-d%Cs{1KO<JHyqiAWCst#(*pI`VKZr`0iH&`rJrHSCm?+IT@85
zAG7{UDgIhP26;AiwRP$3E~+L-x;;M7yXT51ULt-<(B90`CLssul1?Wjl$FU^UaBp`
zf@v>L)2Qpt+LXH}z-YsHaQ>N-VExIWsL<59#>i*%sCGi3taGv!0`gmHp#w|S7gSRd
zE%LKwxB9s+ql%elH6#Q^GF*jc3kwQGzf@^tDc1UQXs6?TviG4YY$S0!4du<cIn$;S
z980-SEK}8c=ExnWTv3$!c}B&Z-OUQ?5OX_mm6rPDZSWqCH~Pi3-YdTk@Y*M~5r}jR
z4WsqhfY}4ym)N`5@3<ykej=xdOV<Q7#C*K)L{y?tTn-q0%2qwkLtmd~<-dtYK0_)2
z9B^f8JvQ9xcyt>Uj<K3%t?^xY*0>4PHY6q)Em=ml+zlPtQ+tt;nDQ{AsFqNq3P*My
z?!=c-cRi}G+uIFo)f`g2Ad!*zl3$Kl*cOW}t=AS2^^?G`4srGLS{Z3x?VLmRriJR@
z7=DLHMCclHnciwrOZLvnrLk0swJm}(PvaYoozgw|uU%?&54l3$mHU)c6%b1$&$XT7
zYy*X|5XBO^pX?#;c}~LlokOk<|ChO2_TG-Oq(a^*CVI)r4dypROL^T=2YhgC?c|1Q
z`GDc$s1UW)Aj)DbBi?15bUpl1)#Cb~HLzh7K6(v;!^k80x?ml~=26@YF{|Lb)-~V6
zUaHcr`S^4Xm!}tz^@heADYH_pln_m2=Vjh#mSe4+{wpT_@Pz0wl<1`DJ3frv^wA~X
z=rby>H>U?4t+oj#cHF$r)08QCHw48Vq(O9{VoutSO7>%qlqmbRt&R(Qf=T{S^JxVK
zOtPUpR;gG8MXJZuhf7{sOmzh5lPhD-D(>_Ta@hUl<!Z7Qm)`VMlKkpL*R`eftryyV
z*AoL7qg5TwJNYrx1YW>9b1t*DM|&&hKDC<Steo<}SsU(@>-8ZI=k2HOIBQswlfnh%
z$yXg_C9H5~KNNAVc4(|v>jmFu_VZt`2k;N~bvl0+H@^5uqi8NnOxbsAyITlM_;|yC
z^Jwu&(HL<6AfOg+mYS_Cm|NsNKPHiOtl*j0{5&mFk`W~aExrZMmut<P!qEDj%m>*Y
znddBUkg~21UF3`re5Fc)_dVm;G#4O#9D#wKA)}JQ%JE+5r59SHPO1eum?($wWPVRx
zejV?Lh5-Q&kdK|TjVMDy>tKTbZsCc}Z}0Aoho#JS>lLLW2d5-M%ZlTpmo|E?Iv-N6
zgu`&Kr;03tYZ{C}wWMkgkk`1?u4ta+YZNTw*{<+8dEqHJl)yP6KOSS8a5uq8?$1k7
z_Jq&#e^up>2YmeG&tN=U*UMVw%ZFZStXrz@a_49%RbhD_!K|yEJ*BkMH;>#&UyZt|
zRL!=yXAtRgTBLRZ<#WL4(k4;kZ@sT=BF<G`&%8*j-62yX+}U0i5O%`cR6i~W2L^}4
z)+@JS{$hzucdRdwh(a1<Uz%KGAF{j>q&gFlL-8Ny7?a(L6wloJ*)1X#(oHE>zHbXt
z*=z~OK>%G4wol)@V|FEN7s%lJ>RV|i(5?Q$**ZJRM0G&9On$@v@-|ieY-+dxgEWAU
z?wX)L?%KJ;2$kKJ{jnq3ek7sw`&VsNL6`Kf$G5NUD%zX+r!SX@<~5Y0osFr~otsTw
zJAMpywF_z(ewhbaGg~4vlwFYVdHvlg>z;{osJ<$vjGgWzl1>x5pZ3r)Y{Gf|SaSQv
zebr&*^Uz^EeaO?U@-Hi$gaFeZhGKD|UFroto{B_656%(i0gH|W>2pi0iW3upDICnz
zaJ5wNq0!wXR+sQzbQTzJPLX1jh&N)14PnawQANZZHFoPN_A~c#3?a~d?uF8cl;LqM
zw4o6h_@#qWsI72)M+9~&-D}e+2E(7^xMr@ZArMUOvcr?8;8cIxVQB<}V2FMg?5n~H
zBRdZ+M~gXr46tREDubDt8^uw1UFgx1-d&gD?%rF<<R3f=!9O5&SAj1O#3iW3Ya+R|
z4<}9}?WYW`;pRXcl?TJ4pq&EzSB^s%&|%u1yRo=$U&SLGJOn)ldE`px%(h6_QulT(
zC8;lvXEZ0S7<io~Jk#piuQaut7=rgFCd?xaQH9U_nCK=D@bgqr3hiV*og{PUj_`De
z_svZ)(X{*9b>l~W|1zASP)-oxuV6j4<p|y7pUnaF;X<{EMu~YT#Vb_Mvenlw$G5vo
zjC}{zVIVodx+95BRdLu)-)LL!#nw*6h=LqW;HLrsvv9Pxe69FUp^+x;sf%HQ;KS6b
zp4b_>PX4=6Ry9#9gOn!7GYP1vg;Y^(9SiM!s!_5rkKUR>iezAF1XFuAHGcI<ig#on
z>@9uiJpxxEy~;*jpOl+>n@(>bQ^HF+J(gn94WYF@deweEbYkL$9KAATgUWu>hjEJR
z&#$+JRF9rdTlSXQ5!ektQhF=1&JrIvgFpB8qX{t&1c~x{{9rh)^W14n{~F7+h6c8b
z4Ccm81dbWS(6|$tb!Toga;XzmC8@Ot(QGIkO<p<G1np<|rA^Hb&YN9e77A~-&b5kS
zn+Rbvub=B)x+tT`jXpxk@V(kMyH=4<Ozcgx+0_g+KRazVlo$^hRJkoBoe(mgt`9oM
z@xefl#O#<8FJIRt*Jtg`h_Lzt-KxsAt{d>!8Ueu%XTC!eD~QqaW~dSNa-*^_56&60
z1pR?*rtAP%o+))`+-X<}p#FdVr5zwh!K@7uOo9ji@F4>LSO8Lht&^)8(7}Pr#llKQ
z8wG%bA^2U_-3tqVfczZ^0QlEpsbvhx<{|dm*ZVrtY>SGxOkNn`^zON>W~Gk3j;&f^
zpwbSGgM}%)&i2WV3z;yD#dk__-=8vjV4{l+7`=kdlz!5WWh9+hZZw=;va0^s>O^Im
zW1R<8jRLr-At)w$Q{@tpI!mHIE^weWj;?^<h>z}WDNW)ChWbatc2B2^ONJ={@4+m5
zDX1Ht7lWs<ByQdT!j%`oWiG*J;!e_RK}Mvr^p5DRUockmgLsS!UZpgR;w?xIGJQ&E
zsileR!4P_V`SrT8rn~GS8dQ1Ll=l<CJaUJlYon&8hI?XG66V>S(;WQ{&KPGdh5o=}
zA;z5{s<7?DJdwI;yQd#(u^-z@n{lV#i3$DMKiSqImu#z%>`vxYK@Quq6P1eEdquu&
zIl{&z7Z~;~F%>BI9HM!gYVhXhy~=7MfsU4o=G~4#U+4w_+RWLj<m+Uig>cziTtQ}F
zwtc)Ty-rlsT8FBF@E1bW=^i_aiF#9(QC<(R-XlW;jM&hXW_di7R)3j0?WHR^F!>%?
z`<!_nJb)(~MMK@Fo&#GX+dtzOhbodqa>N^n!5gtGm8Uq$?+d93Q$rIhb<Z0<@;i)w
z`$ZkFN}wh!RT{u+y}$X*#9H2l38QP6@+9$wljSA+H5@Z}y$TeM4?&QS>@yD-a|})s
zP=MFdi5S^UC}clL!PVb1=0n6JLtXn@zj$t~J~25zBK*awdWgAvv1V@m?r$#;0RX`M
z%_=hx$j#Nw1qkM{bNv^sl0IK*|BY6D@hVFFJosThA4q;`jLi;HKbOD=s>Q<cJ`+*V
z6i>2J<XgTAd|Gouk!(%B_1*I$o7?W6<MIjJTjhkq!dwqFtfExQ-`JDSZQJg~ykQ;j
z{u+7Sk}gm%>2hG&S&fKDB{^TlDjVkNnt+EJ2<Gs6znVXgTOGd)0w31?a1xWirq$2f
z2mr<TaHJ5(ZHd@#cYX5I*B`<Jn^>aa>g*U`a>yw_`vv9jG-E2xCo>L)+LJHLDoV?p
zN)7XD!w9QkufgMrbVj0@E3}YNLg?A;<(qlGSw2(x!9vwEF9g;z(;|@iziAa`j9wlC
zzdd4vziSmhCtE8^S2r$4tJn!i`#v7x&@JQcSM9Zt<n6@4Xe@!qniNLQpIay2lQ1Q5
zn65Pmba!EtQ1Q8ogH60#fD6+;*oV{|Sq`rtEwsh>rD~sG)S-)XZb-|Y&eANsKT2=S
z+=T39XXv)aBp;#sKZabbZFR0Ya^I6>Yo5G$Cba^c5@2eEL+z-?H{HmZ`zq0{;JO1E
zyxdu%l!X_1>2o2}GA*aOPZQ~_@2Na#^n*Wga~L-BzxSAermYz6o%Xl;HKq-a^^ggT
zE@=6D>qhwZutTK;^lg88kl&N&pClSrE38T7DJ2e8PQ?WrB~G@<@u_-Eo_YRFxI6EH
z`-rj{C)doS%J`Tv5?>Xu@~mvVs}=)?%R>-R=Q-h=CXVqM)~KUnYmg)*PTdPA8z$$}
z6(%oOrDA%LYt-Ex16`>Gn}dH$vFY13;_qgNfJlt=pXH<fwGRk@{~#v)L7+zZ&kgmD
z{khx_$b$p;Z`$ks2mGg6`U@}&5Aa`A*58BtJMaDqvI_s7S@?H^zo+mogd&1}OsKjN
T3hJK&D8Glz?`I_m|9Jlc+r%1J
--- a/devtools/shared/gcli/commands/security.js
+++ b/devtools/shared/gcli/commands/security.js
@@ -22,16 +22,17 @@ const MOD_IMG_SRC = "chrome://browser/co
 const BAD_IMG_SRC = "chrome://browser/content/gcli_sec_bad.svg";
 
 
 // special handling within policy
 const POLICY_REPORT_ONLY = "report-only"
 
 // special handling of directives
 const DIR_UPGRADE_INSECURE = "upgrade-insecure-requests";
+const DIR_BLOCK_ALL_MIXED_CONTENT = "block-all-mixed-content";
 
 // special handling of sources
 const SRC_UNSAFE_INLINE = "'unsafe-inline'";
 const SRC_UNSAFE_EVAL = "'unsafe-eval'";
 
 const WILDCARD_MSG = l10n.lookup("securityCSPRemWildCard");
 const XSS_WARNING_MSG = l10n.lookup("securityCSPPotentialXSS");
 const NO_CSP_ON_PAGE_MSG = l10n.lookup("securityCSPNoCSPOnPage");
@@ -84,23 +85,25 @@ exports.items = [
                           CONTENT_SECURITY_POLICY_REPORT_ONLY_MSG :
                           CONTENT_SECURITY_POLICY_MSG;
             continue;
           }
 
           // loop over all the directive-sources within that directive
           var outSrcs = [];
 
-          // special case handling for upgrade-insecure-requests
-          // which does not have any srcs
-          if (dir === DIR_UPGRADE_INSECURE) {
+          // special case handling for the directives
+          // upgrade-insecure-requests and block-all-mixed-content
+          // which do not include any srcs
+          if (dir === DIR_UPGRADE_INSECURE ||
+              dir === DIR_BLOCK_ALL_MIXED_CONTENT) {
             outSrcs.push({
               icon: GOOD_IMG_SRC,
-              src: "", // no src for upgrade-insecure-requests
-              desc: "" // no description for upgrade-insecure-requests
+              src: "", // no src
+              desc: "" // no description
             });
           }
 
           for (var src in curDir) {
             var curSrc = curDir[src];
 
             // the default icon and descritpion of the directive-src
             var outIcon = GOOD_IMG_SRC;
--- a/dom/base/ScriptSettings.cpp
+++ b/dom/base/ScriptSettings.cpp
@@ -329,17 +329,19 @@ AutoJSAPI::~AutoJSAPI()
   }
 }
 
 void
 AutoJSAPI::InitInternal(JSObject* aGlobal, JSContext* aCx, bool aIsMainThread)
 {
   MOZ_ASSERT(aCx);
   MOZ_ASSERT(aIsMainThread == NS_IsMainThread());
-  MOZ_ASSERT(!JS_IsExceptionPending(aCx));
+#ifdef DEBUG
+  bool haveException = JS_IsExceptionPending(aCx);
+#endif // DEBUG
 
   mCx = aCx;
   mIsMainThread = aIsMainThread;
   if (aIsMainThread) {
     // This Rooted<> is necessary only as long as AutoCxPusher::AutoCxPusher
     // can GC, which is only possible because XPCJSContextStack::Push calls
     // nsIPrincipal.Equals. Once that is removed, the Rooted<> will no longer
     // be necessary.
@@ -351,16 +353,82 @@ AutoJSAPI::InitInternal(JSObject* aGloba
   }
 
   JSRuntime* rt = JS_GetRuntime(aCx);
   mOldErrorReporter.emplace(JS_GetErrorReporter(rt));
 
   if (aIsMainThread) {
     JS_SetErrorReporter(rt, xpc::SystemErrorReporter);
   }
+
+#ifdef DEBUG
+  if (haveException) {
+    JS::Rooted<JS::Value> exn(aCx);
+    JS_GetPendingException(aCx, &exn);
+
+    JS_ClearPendingException(aCx);
+    if (exn.isObject()) {
+      JS::Rooted<JSObject*> exnObj(aCx, &exn.toObject());
+
+      nsAutoJSString stack, filename, name, message;
+      int32_t line;
+
+      JS::Rooted<JS::Value> tmp(aCx);
+      if (!JS_GetProperty(aCx, exnObj, "filename", &tmp)) {
+        JS_ClearPendingException(aCx);
+      }
+      if (tmp.isUndefined()) {
+        if (!JS_GetProperty(aCx, exnObj, "fileName", &tmp)) {
+          JS_ClearPendingException(aCx);
+        }
+      }
+
+      if (!filename.init(aCx, tmp)) {
+        JS_ClearPendingException(aCx);
+      }
+
+      if (!JS_GetProperty(aCx, exnObj, "stack", &tmp) ||
+          !stack.init(aCx, tmp)) {
+        JS_ClearPendingException(aCx);
+      }
+
+      if (!JS_GetProperty(aCx, exnObj, "name", &tmp) ||
+          !name.init(aCx, tmp)) {
+        JS_ClearPendingException(aCx);
+      }
+
+      if (!JS_GetProperty(aCx, exnObj, "message", &tmp) ||
+          !message.init(aCx, tmp)) {
+        JS_ClearPendingException(aCx);
+      }
+
+      if (!JS_GetProperty(aCx, exnObj, "lineNumber", &tmp) ||
+          !JS::ToInt32(aCx, tmp, &line)) {
+        JS_ClearPendingException(aCx);
+        line = 0;
+      }
+
+      printf_stderr("PREEXISTING EXCEPTION OBJECT: '%s: %s'\n%s:%d\n%s\n",
+                    NS_ConvertUTF16toUTF8(name).get(),
+                    NS_ConvertUTF16toUTF8(message).get(),
+                    NS_ConvertUTF16toUTF8(filename).get(), line,
+                    NS_ConvertUTF16toUTF8(stack).get());
+    } else {
+      // It's a primitive... not much we can do other than stringify it.
+      nsAutoJSString exnStr;
+      if (!exnStr.init(aCx, exn)) {
+        JS_ClearPendingException(aCx);
+      }
+
+      printf_stderr("PREEXISTING EXCEPTION PRIMITIVE: %s\n",
+                    NS_ConvertUTF16toUTF8(exnStr).get());
+    }
+    MOZ_ASSERT(false, "We had an exception; we should not have");
+  }
+#endif // DEBUG
 }
 
 AutoJSAPI::AutoJSAPI(nsIGlobalObject* aGlobalObject,
                      bool aIsMainThread,
                      JSContext* aCx)
   : mOwnErrorReporting(false)
   , mOldAutoJSAPIOwnsErrorReporting(false)
   , mIsMainThread(aIsMainThread)
--- a/dom/base/TextInputProcessor.cpp
+++ b/dom/base/TextInputProcessor.cpp
@@ -192,17 +192,18 @@ TextInputProcessor::BeginInputTransactio
     if (NS_WARN_IF(mDispatcher)) {
       // Forcibly initialize the members if we failed to end the input
       // transaction.
       UnlinkFromTextEventDispatcher();
     }
   }
 
   if (aForTests) {
-    rv = dispatcher->BeginInputTransactionForTests(this);
+    bool isAPZAware = gfxPrefs::TestEventsAsyncEnabled();
+    rv = dispatcher->BeginTestInputTransaction(this, isAPZAware);
   } else {
     rv = dispatcher->BeginInputTransaction(this);
   }
 
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
@@ -626,18 +627,21 @@ TextInputProcessor::CancelCompositionInt
   return NS_OK;
 }
 
 NS_IMETHODIMP
 TextInputProcessor::NotifyIME(TextEventDispatcher* aTextEventDispatcher,
                               const IMENotification& aNotification)
 {
   // If This is called while this is being initialized, ignore the call.
+  // In such case, this method should return NS_ERROR_NOT_IMPLEMENTED because
+  // we can say, TextInputProcessor doesn't implement any handlers of the
+  // requests and notifications.
   if (!mDispatcher) {
-    return NS_ERROR_NOT_AVAILABLE;
+    return NS_ERROR_NOT_IMPLEMENTED;
   }
   MOZ_ASSERT(aTextEventDispatcher == mDispatcher,
              "Wrong TextEventDispatcher notifies this");
   NS_ASSERTION(mForTests || mCallback,
                "mCallback can be null only when IME is initialized for tests");
   if (mCallback) {
     RefPtr<TextInputProcessorNotification> notification;
     switch (aNotification.mMessage) {
@@ -696,16 +700,26 @@ TextInputProcessor::OnRemovedFrom(TextEv
   if (!mDispatcher) {
     return;
   }
   MOZ_ASSERT(aTextEventDispatcher == mDispatcher,
              "Wrong TextEventDispatcher notifies this");
   UnlinkFromTextEventDispatcher();
 }
 
+NS_IMETHODIMP_(void)
+TextInputProcessor::WillDispatchKeyboardEvent(
+                      TextEventDispatcher* aTextEventDispatcher,
+                      WidgetKeyboardEvent& aKeyboardEvent,
+                      uint32_t aIndexOfKeypress,
+                      void* aData)
+{
+  // TextInputProcessor doesn't set alternative char code.
+}
+
 nsresult
 TextInputProcessor::PrepareKeyboardEventToDispatch(
                       WidgetKeyboardEvent& aKeyboardEvent,
                       uint32_t aKeyFlags)
 {
   if (NS_WARN_IF(aKeyboardEvent.mCodeNameIndex == CODE_NAME_INDEX_USE_STRING)) {
     return NS_ERROR_INVALID_ARG;
   }
@@ -771,33 +785,16 @@ TextInputProcessor::Keydown(nsIDOMKeyEve
   WidgetKeyboardEvent* originalKeyEvent =
     aDOMKeyEvent->AsEvent()->WidgetEventPtr()->AsKeyboardEvent();
   if (NS_WARN_IF(!originalKeyEvent)) {
     return NS_ERROR_INVALID_ARG;
   }
   return KeydownInternal(*originalKeyEvent, aKeyFlags, true, *aConsumedFlags);
 }
 
-TextEventDispatcher::DispatchTo
-TextInputProcessor::GetDispatchTo() const
-{
-  // Support asynchronous tests.
-  if (mForTests) {
-    return gfxPrefs::TestEventsAsyncEnabled() ?
-             TextEventDispatcher::eDispatchToParentProcess :
-             TextEventDispatcher::eDispatchToCurrentProcess;
-  }
-
-  // Otherwise, TextInputProcessor supports only keyboard apps on B2G.
-  // Keyboard apps on B2G doesn't want to dispatch keyboard events to
-  // chrome process. Therefore, this should dispatch key events only in
-  // the current process.
-  return TextEventDispatcher::eDispatchToCurrentProcess;
-}
-
 nsresult
 TextInputProcessor::KeydownInternal(const WidgetKeyboardEvent& aKeyboardEvent,
                                     uint32_t aKeyFlags,
                                     bool aAllowToDispatchKeypress,
                                     uint32_t& aConsumedFlags)
 {
   aConsumedFlags = KEYEVENT_NOT_CONSUMED;
 
@@ -833,30 +830,28 @@ TextInputProcessor::KeydownInternal(cons
   RefPtr<TextEventDispatcher> kungfuDeathGrip(mDispatcher);
   rv = IsValidStateForComposition();
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   nsEventStatus status = aConsumedFlags ? nsEventStatus_eConsumeNoDefault :
                                           nsEventStatus_eIgnore;
-  if (!mDispatcher->DispatchKeyboardEvent(eKeyDown, keyEvent, status,
-                                          GetDispatchTo())) {
+  if (!mDispatcher->DispatchKeyboardEvent(eKeyDown, keyEvent, status)) {
     // If keydown event isn't dispatched, we don't need to dispatch keypress
     // events.
     return NS_OK;
   }
 
   aConsumedFlags |=
     (status == nsEventStatus_eConsumeNoDefault) ? KEYDOWN_IS_CONSUMED :
                                                   KEYEVENT_NOT_CONSUMED;
 
   if (aAllowToDispatchKeypress &&
-      mDispatcher->MaybeDispatchKeypressEvents(keyEvent, status, 
-                                               GetDispatchTo())) {
+      mDispatcher->MaybeDispatchKeypressEvents(keyEvent, status)) {
     aConsumedFlags |=
       (status == nsEventStatus_eConsumeNoDefault) ? KEYPRESS_IS_CONSUMED :
                                                     KEYEVENT_NOT_CONSUMED;
   }
 
   return NS_OK;
 }
 
@@ -915,17 +910,17 @@ TextInputProcessor::KeyupInternal(const 
   RefPtr<TextEventDispatcher> kungfuDeathGrip(mDispatcher);
   rv = IsValidStateForComposition();
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   nsEventStatus status = aDoDefault ? nsEventStatus_eIgnore :
                                       nsEventStatus_eConsumeNoDefault;
-  mDispatcher->DispatchKeyboardEvent(eKeyUp, keyEvent, status, GetDispatchTo());
+  mDispatcher->DispatchKeyboardEvent(eKeyUp, keyEvent, status);
   aDoDefault = (status != nsEventStatus_eConsumeNoDefault);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 TextInputProcessor::GetModifierState(const nsAString& aModifierKeyName,
                                      bool* aActive)
 {
--- a/dom/base/TextInputProcessor.h
+++ b/dom/base/TextInputProcessor.h
@@ -31,16 +31,22 @@ public:
   NS_DECL_NSITEXTINPUTPROCESSOR
 
   // TextEventDispatcherListener
   NS_IMETHOD NotifyIME(TextEventDispatcher* aTextEventDispatcher,
                        const IMENotification& aNotification) override;
   NS_IMETHOD_(void)
     OnRemovedFrom(TextEventDispatcher* aTextEventDispatcher) override;
 
+  NS_IMETHOD_(void) WillDispatchKeyboardEvent(
+                      TextEventDispatcher* aTextEventDispatcher,
+                      WidgetKeyboardEvent& aKeyboardEvent,
+                      uint32_t aIndexOfKeypress,
+                      void* aData) override;
+
 protected:
   virtual ~TextInputProcessor();
 
 private:
   bool IsComposing() const;
   nsresult BeginInputTransactionInternal(
              mozIDOMWindow* aWindow,
              nsITextInputProcessorCallback* aCallback,
@@ -56,17 +62,16 @@ private:
              uint32_t aKeyFlags = 0);
   nsresult KeydownInternal(const WidgetKeyboardEvent& aKeyboardEvent,
                            uint32_t aKeyFlags,
                            bool aAllowToDispatchKeypress,
                            uint32_t& aConsumedFlags);
   nsresult KeyupInternal(const WidgetKeyboardEvent& aKeyboardEvent,
                          uint32_t aKeyFlags,
                          bool& aDoDefault);
-  TextEventDispatcher::DispatchTo GetDispatchTo() const;
   nsresult IsValidStateForComposition();
   void UnlinkFromTextEventDispatcher();
   nsresult PrepareKeyboardEventToDispatch(WidgetKeyboardEvent& aKeyboardEvent,
                                           uint32_t aKeyFlags);
   bool IsValidEventTypeForComposition(
          const WidgetKeyboardEvent& aKeyboardEvent) const;
   nsresult PrepareKeyboardEventForComposition(
              nsIDOMKeyEvent* aDOMKeyEvent,
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -1424,16 +1424,18 @@ static already_AddRefed<mozilla::dom::No
 
 // ==================================================================
 // =
 // ==================================================================
 nsIDocument::nsIDocument()
   : nsINode(nullNodeInfo),
     mReferrerPolicySet(false),
     mReferrerPolicy(mozilla::net::RP_Default),
+    mBlockAllMixedContent(false),
+    mBlockAllMixedContentPreloads(false),
     mUpgradeInsecureRequests(false),
     mUpgradeInsecurePreloads(false),
     mCharacterSet(NS_LITERAL_CSTRING("ISO-8859-1")),
     mNodeInfoManager(nullptr),
     mCompatMode(eCompatibility_FullStandards),
     mVisibilityState(dom::VisibilityState::Hidden),
     mIsInitialDocumentInWindow(false),
     mMayStartLayout(true),
@@ -2587,23 +2589,28 @@ nsDocument::StartDocumentLoad(const char
   // The CSP directive upgrade-insecure-requests not only applies to the
   // toplevel document, but also to nested documents. Let's propagate that
   // flag from the parent to the nested document.
   nsCOMPtr<nsIDocShellTreeItem> treeItem = this->GetDocShell();
   if (treeItem) {
     nsCOMPtr<nsIDocShellTreeItem> sameTypeParent;
     treeItem->GetSameTypeParent(getter_AddRefs(sameTypeParent));
     if (sameTypeParent) {
-      mUpgradeInsecureRequests =
-        sameTypeParent->GetDocument()->GetUpgradeInsecureRequests(false);
+      nsIDocument* doc = sameTypeParent->GetDocument();
+      mBlockAllMixedContent = doc->GetBlockAllMixedContent(false);
+      // if the parent document makes use of block-all-mixed-content
+      // then subdocument preloads should always be blocked.
+      mBlockAllMixedContentPreloads =
+        mBlockAllMixedContent || doc->GetBlockAllMixedContent(true);
+
+      mUpgradeInsecureRequests = doc->GetUpgradeInsecureRequests(false);
       // if the parent document makes use of upgrade-insecure-requests
       // then subdocument preloads should always be upgraded.
       mUpgradeInsecurePreloads =
-        mUpgradeInsecureRequests ||
-        sameTypeParent->GetDocument()->GetUpgradeInsecureRequests(true);
+        mUpgradeInsecureRequests || doc->GetUpgradeInsecureRequests(true);
     }
   }
 
   // If this is not a data document, set CSP.
   if (!mLoadedAsData) {
     nsresult rv = InitCSP(aChannel);
     NS_ENSURE_SUCCESS(rv, rv);
   }
@@ -2692,37 +2699,52 @@ nsDocument::ApplySettingsFromCSP(bool aS
       bool hasReferrerPolicy = false;
       uint32_t referrerPolicy = mozilla::net::RP_Default;
       rv = csp->GetReferrerPolicy(&referrerPolicy, &hasReferrerPolicy);
       NS_ENSURE_SUCCESS_VOID(rv);
       if (hasReferrerPolicy) {
         mReferrerPolicy = static_cast<ReferrerPolicy>(referrerPolicy);
         mReferrerPolicySet = true;
       }
+ 
+      // Set up 'block-all-mixed-content' if not already inherited
+      // from the parent context or set by any other CSP.
+      if (!mBlockAllMixedContent) {
+        rv = csp->GetBlockAllMixedContent(&mBlockAllMixedContent);
+        NS_ENSURE_SUCCESS_VOID(rv);
+      }
+      if (!mBlockAllMixedContentPreloads) {
+        mBlockAllMixedContentPreloads = mBlockAllMixedContent;
+     }
 
       // Set up 'upgrade-insecure-requests' if not already inherited
       // from the parent context or set by any other CSP.
       if (!mUpgradeInsecureRequests) {
         rv = csp->GetUpgradeInsecureRequests(&mUpgradeInsecureRequests);
         NS_ENSURE_SUCCESS_VOID(rv);
       }
       if (!mUpgradeInsecurePreloads) {
         mUpgradeInsecurePreloads = mUpgradeInsecureRequests;
       }
     }
     return;
   }
 
   // 2) apply settings from speculative csp
-  if (!mUpgradeInsecurePreloads) {
-    nsCOMPtr<nsIContentSecurityPolicy> preloadCsp;
-    rv = NodePrincipal()->GetPreloadCsp(getter_AddRefs(preloadCsp));
-    NS_ENSURE_SUCCESS_VOID(rv);
-    if (preloadCsp) {
-      preloadCsp->GetUpgradeInsecureRequests(&mUpgradeInsecurePreloads);
+  nsCOMPtr<nsIContentSecurityPolicy> preloadCsp;
+  rv = NodePrincipal()->GetPreloadCsp(getter_AddRefs(preloadCsp));
+  NS_ENSURE_SUCCESS_VOID(rv);
+  if (preloadCsp) {
+    if (!mBlockAllMixedContentPreloads) {
+      rv = preloadCsp->GetBlockAllMixedContent(&mBlockAllMixedContentPreloads);
+      NS_ENSURE_SUCCESS_VOID(rv);
+    }
+    if (!mUpgradeInsecurePreloads) {
+      rv = preloadCsp->GetUpgradeInsecureRequests(&mUpgradeInsecurePreloads);
+      NS_ENSURE_SUCCESS_VOID(rv);
     }
   }
 }
 
 nsresult
 nsDocument::InitCSP(nsIChannel* aChannel)
 {
   nsCOMPtr<nsIContentSecurityPolicy> csp;
--- a/dom/base/nsHTMLContentSerializer.cpp
+++ b/dom/base/nsHTMLContentSerializer.cpp
@@ -396,68 +396,84 @@ nsHTMLContentSerializer::AppendElementEn
   if (name == nsGkAtoms::body && ns == kNameSpaceID_XHTML) {
     --mInBody;
   }
 
   return NS_OK;
 }
 
 static const uint16_t kValNBSP = 160;
-static const char* kEntities[] = {
-  nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
-  nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
-  nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
-  nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, "&amp;", nullptr,
-  nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
-  nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
-  "&lt;", nullptr, "&gt;", nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
-  nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
-  nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
-  nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
-  nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
-  nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
-  nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
-  nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
-  nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
-  nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
-  "&nbsp;"
+
+#define _ 0
+
+// This table indexes into kEntityStrings[].
+static const uint8_t kEntities[] = {
+  _, _, _, _, _, _, _, _, _, _,
+  _, _, _, _, _, _, _, _, _, _,
+  _, _, _, _, _, _, _, _, _, _,
+  _, _, _, _, _, _, _, _, 2, _,
+  _, _, _, _, _, _, _, _, _, _,
+  _, _, _, _, _, _, _, _, _, _,
+  3, _, 4, _, _, _, _, _, _, _,
+  _, _, _, _, _, _, _, _, _, _,
+  _, _, _, _, _, _, _, _, _, _,
+  _, _, _, _, _, _, _, _, _, _,
+  _, _, _, _, _, _, _, _, _, _,
+  _, _, _, _, _, _, _, _, _, _,
+  _, _, _, _, _, _, _, _, _, _,
+  _, _, _, _, _, _, _, _, _, _,
+  _, _, _, _, _, _, _, _, _, _,
+  _, _, _, _, _, _, _, _, _, _,
+  5
 };
 
-static const char* kAttrEntities[] = {
-  nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
-  nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
-  nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
-  nullptr, nullptr, nullptr, nullptr, "&quot;", nullptr, nullptr, nullptr, "&amp;", nullptr,
-  nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
-  nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
-  "&lt;", nullptr, "&gt;", nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
-  nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
-  nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
-  nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
-  nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
-  nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
-  nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
-  nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
-  nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
-  nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
-  "&nbsp;"
+// This table indexes into kEntityStrings[].
+static const uint8_t kAttrEntities[] = {
+  _, _, _, _, _, _, _, _, _, _,
+  _, _, _, _, _, _, _, _, _, _,
+  _, _, _, _, _, _, _, _, _, _,
+  _, _, _, _, 1, _, _, _, 2, _,
+  _, _, _, _, _, _, _, _, _, _,
+  _, _, _, _, _, _, _, _, _, _,
+  3, _, 4, _, _, _, _, _, _, _,
+  _, _, _, _, _, _, _, _, _, _,
+  _, _, _, _, _, _, _, _, _, _,
+  _, _, _, _, _, _, _, _, _, _,
+  _, _, _, _, _, _, _, _, _, _,
+  _, _, _, _, _, _, _, _, _, _,
+  _, _, _, _, _, _, _, _, _, _,
+  _, _, _, _, _, _, _, _, _, _,
+  _, _, _, _, _, _, _, _, _, _,
+  _, _, _, _, _, _, _, _, _, _,
+  5
+};
+
+#undef _
+
+static const char* const kEntityStrings[] = {
+  /* 0 */ nullptr,
+  /* 1 */ "&quot;",
+  /* 2 */ "&amp;",
+  /* 3 */ "&lt;",
+  /* 4 */ "&gt;",
+  /* 5 */ "&nbsp;"
 };
 
 uint32_t FindNextBasicEntity(const nsAString& aStr,
                              const uint32_t aLen,
                              uint32_t aIndex,
-                             const char** aEntityTable,
+                             const uint8_t* aEntityTable,
                              const char** aEntity)
 {
   for (; aIndex < aLen; ++aIndex) {
     // for each character in this chunk, check if it
     // needs to be replaced
     char16_t val = aStr[aIndex];
     if (val <= kValNBSP && aEntityTable[val]) {
-      *aEntity = aEntityTable[val];
+      *aEntity = kEntityStrings[aEntityTable[val]];
       return aIndex;
     }
   }
   return aIndex;
 }
 
 bool
 nsHTMLContentSerializer::AppendAndTranslateEntities(const nsAString& aStr,
@@ -473,17 +489,17 @@ nsHTMLContentSerializer::AppendAndTransl
 
   bool nonBasicEntities =
     !!(mFlags & (nsIDocumentEncoder::OutputEncodeLatin1Entities |
                  nsIDocumentEncoder::OutputEncodeHTMLEntities   |
                  nsIDocumentEncoder::OutputEncodeW3CEntities));
 
   if (!nonBasicEntities &&
       (mFlags & (nsIDocumentEncoder::OutputEncodeBasicEntities))) {
-    const char **entityTable = mInAttribute ? kAttrEntities : kEntities;
+    const uint8_t* entityTable = mInAttribute ? kAttrEntities : kEntities;
     uint32_t start = 0;
     const uint32_t len = aStr.Length();
     for (uint32_t i = 0; i < len; ++i) {
       const char* entity = nullptr;
       i = FindNextBasicEntity(aStr, len, i, entityTable, &entity);
       uint32_t normalTextLen = i - start; 
       if (normalTextLen) {
         NS_ENSURE_TRUE(aOutputStr.Append(Substring(aStr, start, normalTextLen),
@@ -505,17 +521,17 @@ nsHTMLContentSerializer::AppendAndTransl
 
     nsReadingIterator<char16_t> done_reading;
     aStr.EndReading(done_reading);
 
     // for each chunk of |aString|...
     uint32_t advanceLength = 0;
     nsReadingIterator<char16_t> iter;
 
-    const char **entityTable = mInAttribute ? kAttrEntities : kEntities;
+    const uint8_t* entityTable = mInAttribute ? kAttrEntities : kEntities;
     nsAutoCString entityReplacement;
 
     for (aStr.BeginReading(iter);
          iter != done_reading;
          iter.advance(int32_t(advanceLength))) {
       uint32_t fragmentLength = iter.size_forward();
       uint32_t lengthReplaced = 0; // the number of UTF-16 codepoints
                                     //  replaced by a particular entity
@@ -527,17 +543,17 @@ nsHTMLContentSerializer::AppendAndTransl
       char* fullEntityText = nullptr;
 
       advanceLength = 0;
       // for each character in this chunk, check if it
       // needs to be replaced
       for (; c < fragmentEnd; c++, advanceLength++) {
         char16_t val = *c;
         if (val <= kValNBSP && entityTable[val]) {
-          fullConstEntityText = entityTable[val];
+          fullConstEntityText = kEntityStrings[entityTable[val]];
           break;
         } else if (val > 127 &&
                   ((val < 256 &&
                     mFlags & nsIDocumentEncoder::OutputEncodeLatin1Entities) ||
                     mFlags & nsIDocumentEncoder::OutputEncodeHTMLEntities)) {
           entityReplacement.Truncate();
           parserService->HTMLConvertUnicodeToEntity(val, entityReplacement);
 
--- a/dom/base/nsIDocument.h
+++ b/dom/base/nsIDocument.h
@@ -312,16 +312,29 @@ public:
    * GetReferrerPolicy() for Document.webidl.
    */
   uint32_t ReferrerPolicy() const
   {
     return GetReferrerPolicy();
   }
 
   /**
+   * If true, this flag indicates that all mixed content subresource
+   * loads for this document (and also embeded browsing contexts) will
+   * be blocked.
+   */
+  bool GetBlockAllMixedContent(bool aPreload) const
+  {
+    if (aPreload) {
+      return mBlockAllMixedContentPreloads;
+    }
+    return mBlockAllMixedContent;
+  }
+
+  /**
    * If true, this flag indicates that all subresource loads for this
    * document need to be upgraded from http to https.
    * This flag becomes true if the CSP of the document itself, or any
    * of the document's ancestors up to the toplevel document makes use
    * of the CSP directive 'upgrade-insecure-requests'.
    */
   bool GetUpgradeInsecureRequests(bool aPreload) const
   {
@@ -2761,16 +2774,18 @@ protected:
   nsCOMPtr<nsIURI> mDocumentBaseURI;
   nsCOMPtr<nsIURI> mChromeXHRDocBaseURI;
 
   nsWeakPtr mDocumentLoadGroup;
 
   bool mReferrerPolicySet;
   ReferrerPolicyEnum mReferrerPolicy;
 
+  bool mBlockAllMixedContent;
+  bool mBlockAllMixedContentPreloads;
   bool mUpgradeInsecureRequests;
   bool mUpgradeInsecurePreloads;
 
   mozilla::WeakPtr<nsDocShell> mDocumentContainer;
 
   nsCString mCharacterSet;
   int32_t mCharacterSetSource;
 
--- a/dom/base/nsXMLContentSerializer.cpp
+++ b/dom/base/nsXMLContentSerializer.cpp
@@ -1188,65 +1188,80 @@ nsXMLContentSerializer::AppendToString(c
     return true;
   }
   mColPos += aStr.Length();
   return aOutputStr.Append(aStr, mozilla::fallible);
 }
 
 
 static const uint16_t kGTVal = 62;
-static const char* kEntities[] = {
-  "", "", "", "", "", "", "", "", "", "",
-  "", "", "", "", "", "", "", "", "", "",
-  "", "", "", "", "", "", "", "", "", "",
-  "", "", "", "", "", "", "", "", "&amp;", "",
-  "", "", "", "", "", "", "", "", "", "",
-  "", "", "", "", "", "", "", "", "", "",
-  "&lt;", "", "&gt;"
+
+#define _ 0
+
+// This table indexes into kEntityStrings[].
+static const uint8_t kEntities[] = {
+  _, _, _, _, _, _, _, _, _, _,
+  _, _, _, _, _, _, _, _, _, _,
+  _, _, _, _, _, _, _, _, _, _,
+  _, _, _, _, _, _, _, _, 2, _,
+  _, _, _, _, _, _, _, _, _, _,
+  _, _, _, _, _, _, _, _, _, _,
+  3, _, 4
 };
 
-static const char* kAttrEntities[] = {
-  "", "", "", "", "", "", "", "", "", "",
-  "", "", "", "", "", "", "", "", "", "",
-  "", "", "", "", "", "", "", "", "", "",
-  "", "", "", "", "&quot;", "", "", "", "&amp;", "",
-  "", "", "", "", "", "", "", "", "", "",
-  "", "", "", "", "", "", "", "", "", "",
-  "&lt;", "", "&gt;"
+// This table indexes into kEntityStrings[].
+static const uint8_t kAttrEntities[] = {
+  _, _, _, _, _, _, _, _, _, _,
+  _, _, _, _, _, _, _, _, _, _,
+  _, _, _, _, _, _, _, _, _, _,
+  _, _, _, _, 1, _, _, _, 2, _,
+  _, _, _, _, _, _, _, _, _, _,
+  _, _, _, _, _, _, _, _, _, _,
+  3, _, 4
+};
+
+#undef _
+
+static const char* const kEntityStrings[] = {
+  /* 0 */ nullptr,
+  /* 1 */ "&quot;",
+  /* 2 */ "&amp;",
+  /* 3 */ "&lt;",
+  /* 4 */ "&gt;",
 };
 
 bool
 nsXMLContentSerializer::AppendAndTranslateEntities(const nsAString& aStr,
                                                    nsAString& aOutputStr)
 {
   nsReadingIterator<char16_t> done_reading;
   aStr.EndReading(done_reading);
 
   // for each chunk of |aString|...
   uint32_t advanceLength = 0;
   nsReadingIterator<char16_t> iter;
 
-  const char **entityTable = mInAttribute ? kAttrEntities : kEntities;
+  const uint8_t* entityTable = mInAttribute ? kAttrEntities : kEntities;
 
   for (aStr.BeginReading(iter);
        iter != done_reading;
        iter.advance(int32_t(advanceLength))) {
     uint32_t fragmentLength = iter.size_forward();
     const char16_t* c = iter.get();
     const char16_t* fragmentStart = c;
     const char16_t* fragmentEnd = c + fragmentLength;
     const char* entityText = nullptr;
 
     advanceLength = 0;
     // for each character in this chunk, check if it
     // needs to be replaced
     for (; c < fragmentEnd; c++, advanceLength++) {
       char16_t val = *c;
-      if ((val <= kGTVal) && (entityTable[val][0] != 0)) {
-        entityText = entityTable[val];
+      if ((val <= kGTVal) && entityTable[val]) {
+        entityText = kEntityStrings[entityTable[val]];
         break;
       }
     }
 
     NS_ENSURE_TRUE(aOutputStr.Append(fragmentStart, advanceLength, mozilla::fallible), false);
     if (entityText) {
       NS_ENSURE_TRUE(AppendASCIItoUTF16(entityText, aOutputStr, mozilla::fallible), false);
       advanceLength++;
--- a/dom/bindings/BindingUtils.cpp
+++ b/dom/bindings/BindingUtils.cpp
@@ -50,17 +50,17 @@
 #include "mozilla/jsipc/CrossProcessObjectWrappers.h"
 #include "nsDOMClassInfo.h"
 #include "ipc/ErrorIPCUtils.h"
 #include "mozilla/UseCounter.h"
 
 namespace mozilla {
 namespace dom {
 
-JSErrorFormatString ErrorFormatString[] = {
+const JSErrorFormatString ErrorFormatString[] = {
 #define MSG_DEF(_name, _argc, _exn, _str) \
   { #_name, _str, _argc, _exn },
 #include "mozilla/dom/Errors.msg"
 #undef MSG_DEF
 };
 
 #define MSG_DEF(_name, _argc, _exn, _str) \
   static_assert(_argc < JS::MaxNumErrorArguments, \
--- a/dom/canvas/WebGLExtensionDisjointTimerQuery.cpp
+++ b/dom/canvas/WebGLExtensionDisjointTimerQuery.cpp
@@ -7,16 +7,17 @@
 #include "WebGLExtensions.h"
 
 #include "mozilla/dom/ToJSValue.h"
 #include "mozilla/dom/WebGLRenderingContextBinding.h"
 #include "mozilla/dom/BindingUtils.h"
 #include "GLContext.h"
 #include "WebGLContext.h"
 #include "WebGLTimerQuery.h"
+#include "gfxPrefs.h"
 
 namespace mozilla {
 
 WebGLExtensionDisjointTimerQuery::WebGLExtensionDisjointTimerQuery(WebGLContext* webgl)
   : WebGLExtensionBase(webgl)
   , mActiveQuery(nullptr)
 {
   MOZ_ASSERT(IsSupported(webgl), "Don't construct extension if unsupported.");
@@ -112,16 +113,17 @@ WebGLExtensionDisjointTimerQuery::EndQue
 
   if (!mActiveQuery) {
     mContext->ErrorInvalidOperation("endQueryEXT: A query is not active.");
     return;
   }
 
   mContext->MakeContextCurrent();
   mContext->GL()->fEndQuery(target);
+  mActiveQuery->QueueAvailablity();
   mActiveQuery = nullptr;
 }
 
 void
 WebGLExtensionDisjointTimerQuery::QueryCounterEXT(WebGLTimerQuery* query,
                                                   GLenum target)
 {
   if (mIsLost)
@@ -134,16 +136,17 @@ WebGLExtensionDisjointTimerQuery::QueryC
     mContext->ErrorInvalidEnumInfo("queryCounterEXT: requires"
                                    " TIMESTAMP_EXT.", target);
     return;
   }
 
   mContext->MakeContextCurrent();
   mContext->GL()->fQueryCounter(query->mGLName, target);
   query->mTarget = LOCAL_GL_TIMESTAMP_EXT;
+  query->QueueAvailablity();
 }
 
 void
 WebGLExtensionDisjointTimerQuery::GetQueryEXT(JSContext* cx, GLenum target,
                                               GLenum pname,
                                               JS::MutableHandle<JS::Value> retval)
 {
   if (mIsLost)
@@ -216,17 +219,18 @@ WebGLExtensionDisjointTimerQuery::GetQue
     retval.set(JS::NumberValue(result));
     break;
   }
   case LOCAL_GL_QUERY_RESULT_AVAILABLE_EXT: {
     GLuint avail = 0;
     mContext->GL()->fGetQueryObjectuiv(query->mGLName,
                                        LOCAL_GL_QUERY_RESULT_AVAILABLE_EXT,
                                        &avail);
-    retval.set(JS::BooleanValue(bool(avail)));
+    bool canBeAvailable = query->CanBeAvailable() || gfxPrefs::WebGLImmediateQueries();
+    retval.set(JS::BooleanValue(bool(avail) && canBeAvailable));
     break;
   }
   default:
     mContext->ErrorInvalidEnumInfo("getQueryObjectEXT: Invalid query"
                                    " property.", pname);
     break;
   }
 }
--- a/dom/canvas/WebGLShaderValidator.cpp
+++ b/dom/canvas/WebGLShaderValidator.cpp
@@ -113,28 +113,28 @@ ShaderOutput(gl::GLContext* gl)
         case 430: return SH_GLSL_430_CORE_OUTPUT;
         case 440: return SH_GLSL_440_CORE_OUTPUT;
         case 450: return SH_GLSL_450_CORE_OUTPUT;
         default:
             MOZ_CRASH("Unexpected GLSL version.");
         }
     }
 
-    return SH_GLSL_OUTPUT;
+    return SH_GLSL_COMPATIBILITY_OUTPUT;
 }
 
 webgl::ShaderValidator*
 WebGLContext::CreateShaderValidator(GLenum shaderType) const
 {
     if (mBypassShaderValidation)
         return nullptr;
 
     ShShaderSpec spec = IsWebGL2() ? SH_WEBGL2_SPEC : SH_WEBGL_SPEC;
     ShShaderOutput outputLanguage = gl->IsGLES() ? SH_ESSL_OUTPUT
-                                                 : SH_GLSL_OUTPUT;
+                                                 : SH_GLSL_COMPATIBILITY_OUTPUT;
 
     // If we're using WebGL2 we want a more specific version of GLSL
     if (IsWebGL2())
         outputLanguage = ShaderOutput(gl);
 
     ShBuiltInResources resources;
     memset(&resources, 0, sizeof(resources));
     ShInitBuiltInResources(&resources);
--- a/dom/canvas/WebGLTimerQuery.cpp
+++ b/dom/canvas/WebGLTimerQuery.cpp
@@ -5,29 +5,31 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "WebGLTimerQuery.h"
 
 #include "GLContext.h"
 #include "mozilla/dom/WebGLRenderingContextBinding.h"
 #include "nsContentUtils.h"
 #include "WebGLContext.h"
+#include "nsThreadUtils.h"
 
 namespace mozilla {
 
 JSObject*
 WebGLTimerQuery::WrapObject(JSContext* cx, JS::Handle<JSObject*> givenProto)
 {
   return dom::WebGLTimerQueryEXTBinding::Wrap(cx, this, givenProto);
 }
 
 WebGLTimerQuery::WebGLTimerQuery(WebGLContext* webgl, GLuint name)
   : WebGLContextBoundObject(webgl)
   , mGLName(name)
   , mTarget(LOCAL_GL_NONE)
+  , mCanBeAvailable(false)
 {
 }
 
 WebGLTimerQuery::~WebGLTimerQuery()
 {
   DeleteOnce();
 }
 
@@ -48,15 +50,21 @@ WebGLTimerQuery::Delete()
 }
 
 WebGLContext*
 WebGLTimerQuery::GetParentObject() const
 {
   return mContext;
 }
 
+void
+WebGLTimerQuery::QueueAvailablity()
+{
+  RefPtr<WebGLTimerQuery> self = this;
+  NS_DispatchToCurrentThread(NS_NewRunnableFunction([self] { self->mCanBeAvailable = true; }));
+}
 
 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(WebGLTimerQuery)
 
 NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(WebGLTimerQuery, AddRef)
 NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(WebGLTimerQuery, Release)
 
 } // namespace mozilla
--- a/dom/canvas/WebGLTimerQuery.h
+++ b/dom/canvas/WebGLTimerQuery.h
@@ -19,16 +19,18 @@ class WebGLTimerQuery final
   , public WebGLContextBoundObject
 {
 public:
   static WebGLTimerQuery* Create(WebGLContext* webgl);
 
   void Delete();
 
   bool HasEverBeenBound() const { return mTarget != LOCAL_GL_NONE; }
+  bool CanBeAvailable() const { return mCanBeAvailable; }
+  void QueueAvailablity();
   GLenum Target() const { return mTarget; }
 
   WebGLContext* GetParentObject() const;
 
   // NS
   virtual JSObject* WrapObject(JSContext* cx, JS::Handle<JSObject*> givenProto) override;
 
   const GLenum mGLName;
@@ -36,15 +38,16 @@ public:
   NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLTimerQuery)
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(WebGLTimerQuery)
 
 private:
   explicit WebGLTimerQuery(WebGLContext* webgl, GLuint name);
   ~WebGLTimerQuery();
 
   GLenum mTarget;
+  bool mCanBeAvailable;
 
   friend class WebGLExtensionDisjointTimerQuery;
 };
 
 } // namespace mozilla
 
 #endif // WEBGL_TIMER_QUERY_H_
--- a/dom/canvas/test/webgl-mochitest.ini
+++ b/dom/canvas/test/webgl-mochitest.ini
@@ -10,17 +10,17 @@ support-files =
 
 [webgl-mochitest/ensure-exts/test_ANGLE_instanced_arrays.html]
 fail-if = (os == 'android') || (os == 'mac' && os_version == '10.6')
 [webgl-mochitest/ensure-exts/test_EXT_blend_minmax.html]
 fail-if = (os == 'android')
 [webgl-mochitest/ensure-exts/test_EXT_color_buffer_half_float.html]
 fail-if = (os == 'android')
 [webgl-mochitest/ensure-exts/test_EXT_disjoint_timer_query.html]
-fail-if = (os == 'android') || (os == 'mac') || (os == 'win')
+fail-if = (os == 'android') || (os == 'mac') || (os == 'win' && (os_version == '5.1' || os_version == '6.1'))
 [webgl-mochitest/ensure-exts/test_EXT_frag_depth.html]
 fail-if = (os == 'android')
 [webgl-mochitest/ensure-exts/test_EXT_sRGB.html]
 fail-if = (os == 'android') || (os == 'mac' && os_version == '10.6') || (os == 'win')
 [webgl-mochitest/ensure-exts/test_EXT_shader_texture_lod.html]
 fail-if = (os == 'android') || (os == 'linux') || (os == 'mac')
 [webgl-mochitest/ensure-exts/test_EXT_texture_filter_anisotropic.html]
 fail-if = (os == 'android') || (os == 'linux')
--- a/dom/encoding/EncodingUtils.cpp
+++ b/dom/encoding/EncodingUtils.cpp
@@ -10,21 +10,21 @@
 #include "nsUConvPropertySearch.h"
 #include "nsIUnicodeDecoder.h"
 #include "nsIUnicodeEncoder.h"
 #include "nsComponentManagerUtils.h"
 
 namespace mozilla {
 namespace dom {
 
-static const char* labelsEncodings[][3] = {
+static const char* const labelsEncodings[][3] = {
 #include "labelsencodings.properties.h"
 };
 
-static const char* encodingsGroups[][3] = {
+static const char* const encodingsGroups[][3] = {
 #include "encodingsgroups.properties.h"
 };
 
 bool
 EncodingUtils::FindEncodingForLabel(const nsACString& aLabel,
                                     nsACString& aOutEncoding)
 {
   // Save aLabel first because it may refer the same string as aOutEncoding.
--- a/dom/encoding/FallbackEncoding.cpp
+++ b/dom/encoding/FallbackEncoding.cpp
@@ -10,25 +10,25 @@
 #include "nsUConvPropertySearch.h"
 #include "nsIChromeRegistry.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/Services.h"
 
 namespace mozilla {
 namespace dom {
 
-static const char* localesFallbacks[][3] = {
+static const char* const localesFallbacks[][3] = {
 #include "localesfallbacks.properties.h"
 };
 
-static const char* domainsFallbacks[][3] = {
+static const char* const domainsFallbacks[][3] = {
 #include "domainsfallbacks.properties.h"
 };
 
-static const char* nonParticipatingDomains[][3] = {
+static const char* const nonParticipatingDomains[][3] = {
 #include "nonparticipatingdomains.properties.h"
 };
 
 FallbackEncoding* FallbackEncoding::sInstance = nullptr;
 bool FallbackEncoding::sGuessFallbackFromTopLevelDomain = true;
 
 FallbackEncoding::FallbackEncoding()
 {
--- a/dom/events/EventDispatcher.cpp
+++ b/dom/events/EventDispatcher.cpp
@@ -80,19 +80,56 @@ public:
     return !mNonMainThread;
   }
 
 private:
   bool mNonMainThread;
   uint32_t mInitialCount;
 };
 
+static bool IsEventTargetChrome(EventTarget* aEventTarget,
+                                nsIDocument** aDocument = nullptr)
+{
+  if (aDocument) {
+    *aDocument = nullptr;
+  }
+
+  if (NS_WARN_IF(!aEventTarget)) {
+    return false;
+  }
+
+  nsCOMPtr<nsIDocument> doc = do_QueryInterface(aEventTarget);
+  if (!doc) {
+    nsCOMPtr<nsINode> node = do_QueryInterface(aEventTarget);
+    if (node) {
+      doc = node->OwnerDoc();
+    } else {
+      nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(aEventTarget);
+      if (!window) {
+        return false;
+      }
+      doc = window->GetExtantDoc();
+    }
+    if (!doc) {
+      return false;
+    }
+  }
+  bool isChrome = nsContentUtils::IsChromeDoc(doc);
+  if (aDocument) {
+    doc.swap(*aDocument);
+  }
+  return isChrome;
+}
+
+
 #define NS_TARGET_CHAIN_FORCE_CONTENT_DISPATCH  (1 << 0)
 #define NS_TARGET_CHAIN_WANTS_WILL_HANDLE_EVENT (1 << 1)
 #define NS_TARGET_CHAIN_MAY_HAVE_MANAGER        (1 << 2)
+#define NS_TARGET_CHAIN_CHECKED_IF_CHROME       (1 << 3)
+#define NS_TARGET_CHAIN_IS_CHROME_CONTENT       (1 << 4)
 
 // EventTargetChainItem represents a single item in the event target chain.
 class EventTargetChainItem
 {
 private:
   explicit EventTargetChainItem(EventTarget* aTarget);
 public:
   EventTargetChainItem()
@@ -205,16 +242,21 @@ public:
                    ELMCreationDetector& aCd)
   {
     if (WantsWillHandleEvent()) {
       mTarget->WillHandleEvent(aVisitor);
     }
     if (aVisitor.mEvent->mFlags.mPropagationStopped) {
       return;
     }
+    if (aVisitor.mEvent->mFlags.mOnlySystemGroupDispatchInContent &&
+        !aVisitor.mEvent->mFlags.mInSystemGroup &&
+        !IsCurrentTargetChrome()) {
+      return;
+    }
     if (!mManager) {
       if (!MayHaveListenerManager() && !aCd.MayHaveNewListenerManager()) {
         return;
       }
       mManager = mTarget->GetExistingListenerManager();
     }
     if (mManager) {
       NS_ASSERTION(aVisitor.mEvent->currentTarget == nullptr,
@@ -228,24 +270,36 @@ public:
     }
   }
 
   /**
    * Copies mItemFlags and mItemData to aVisitor and calls PostHandleEvent.
    */
   void PostHandleEvent(EventChainPostVisitor& aVisitor);
 
+private:
   nsCOMPtr<EventTarget>             mTarget;
   uint16_t                          mFlags;
   uint16_t                          mItemFlags;
   nsCOMPtr<nsISupports>             mItemData;
   // Event retargeting must happen whenever mNewTarget is non-null.
   nsCOMPtr<EventTarget>             mNewTarget;
   // Cache mTarget's event listener manager.
   RefPtr<EventListenerManager>    mManager;
+
+  bool IsCurrentTargetChrome()
+  {
+    if (!(mFlags & NS_TARGET_CHAIN_CHECKED_IF_CHROME)) {
+      mFlags |= NS_TARGET_CHAIN_CHECKED_IF_CHROME;
+      if (IsEventTargetChrome(mTarget)) {
+        mFlags |= NS_TARGET_CHAIN_IS_CHROME_CONTENT;
+      }
+    }
+    return !!(mFlags & NS_TARGET_CHAIN_IS_CHROME_CONTENT);
+  }
 };
 
 EventTargetChainItem::EventTargetChainItem(EventTarget* aTarget)
   : mTarget(aTarget)
   , mFlags(0)
   , mItemFlags(0)
 {
   MOZ_ASSERT(!aTarget || mTarget == aTarget->GetTargetForEventTargetChain());
@@ -463,38 +517,31 @@ EventDispatcher::Dispatch(nsISupports* a
 
       aEvent->originalTarget = target;
       target = newTarget;
       retargeted = true;
     }
   }
 
   if (aEvent->mFlags.mOnlyChromeDispatch) {
-    nsCOMPtr<nsINode> node = do_QueryInterface(aTarget);
-    if (!node) {
-      nsCOMPtr<nsPIDOMWindowInner> win = do_QueryInterface(aTarget);
-      if (win) {
-        node = win->GetExtantDoc();
-      }
-    }
-
-    NS_ENSURE_STATE(node);
-    nsIDocument* doc = node->OwnerDoc();
-    if (!nsContentUtils::IsChromeDoc(doc)) {
-      nsPIDOMWindowInner* win = doc ? doc->GetInnerWindow() : nullptr;
+    nsCOMPtr<nsIDocument> doc;
+    if (!IsEventTargetChrome(target, getter_AddRefs(doc)) && doc) {
+      nsPIDOMWindowInner* win = doc->GetInnerWindow();
       // If we can't dispatch the event to chrome, do nothing.
       EventTarget* piTarget = win ? win->GetParentTarget() : nullptr;
       if (!piTarget) {
         return NS_OK;
       }
 
       // Set the target to be the original dispatch target,
       aEvent->target = target;
       // but use chrome event handler or TabChildGlobal for event target chain.
       target = piTarget;
+    } else if (NS_WARN_IF(!doc)) {
+      return NS_ERROR_UNEXPECTED;
     }
   }
 
 #ifdef DEBUG
   if (aEvent->mMessage != eVoidEvent &&
       !nsContentUtils::IsSafeToRunScript()) {
     nsresult rv = NS_ERROR_FAILURE;
     if (target->GetContextForEventHandlers(&rv) ||
--- a/dom/interfaces/security/nsIContentSecurityPolicy.idl
+++ b/dom/interfaces/security/nsIContentSecurityPolicy.idl
@@ -47,16 +47,17 @@ interface nsIContentSecurityPolicy : nsI
   const unsigned short FRAME_ANCESTORS_DIRECTIVE      = 11;
   const unsigned short REFLECTED_XSS_DIRECTIVE        = 12;
   const unsigned short BASE_URI_DIRECTIVE             = 13;
   const unsigned short FORM_ACTION_DIRECTIVE          = 14;
   const unsigned short REFERRER_DIRECTIVE             = 15;
   const unsigned short WEB_MANIFEST_SRC_DIRECTIVE     = 16;
   const unsigned short UPGRADE_IF_INSECURE_DIRECTIVE  = 17;
   const unsigned short CHILD_SRC_DIRECTIVE            = 18;
+  const unsigned short BLOCK_ALL_MIXED_CONTENT        = 19;
 
   /**
    * Accessor method for a read-only string version of the policy at a given
    * index.
    */
   AString getPolicy(in unsigned long index);
 
   /**
@@ -68,16 +69,25 @@ interface nsIContentSecurityPolicy : nsI
   /**
    * Returns whether this policy uses the directive upgrade-insecure-requests.
    * Please note that upgrade-insecure-reqeusts also applies if the parent or
    * including document (context) makes use of the directive.
    */
   readonly attribute bool upgradeInsecureRequests;
 
   /**
+   * Returns whether this policy uses the directive block-all-mixed-content.
+   * Please note that block-all-mixed-content takes presedence in case the
+   * directive upgrade-insecure-requests is defined in the same policy and
+   * will therefore block all mixed content without even trying to perform
+   * an upgrade.
+   */
+  readonly attribute bool blockAllMixedContent;
+
+  /**
    * Obtains the referrer policy (as integer) for this browsing context as
    * specified in CSP.  If there are multiple policies and...
    *  - only one sets a referrer policy: that policy is returned
    *  - more than one sets different referrer policies: no-referrer is returned
    *  - more than one set equivalent policies: that policy is returned
    * For the enumeration of policies see ReferrerPolicy.h and nsIHttpChannel.
    *
    * @param aPolicy
--- a/dom/locales/en-US/chrome/security/csp.properties
+++ b/dom/locales/en-US/chrome/security/csp.properties
@@ -63,16 +63,19 @@ upgradeInsecureRequest = Upgrading insec
 # LOCALIZATION NOTE (ignoreSrcForDirective):
 ignoreSrcForDirective = Ignoring srcs for directive '%1$S'
 # LOCALIZATION NOTE (hostNameMightBeKeyword):
 # %1$S is the hostname in question and %2$S is the keyword
 hostNameMightBeKeyword = Interpreting %1$S as a hostname, not a keyword. If you intended this to be a keyword, use '%2$S' (wrapped in single quotes).
 # LOCALIZATION NOTE (notSupportingDirective):
 # directive is not supported (e.g. 'reflected-xss')
 notSupportingDirective = Not supporting directive '%1$S'. Directive and values will be ignored.
+# LOCALIZATION NOTE (blockAllMixedContent):
+# %1$S is the URL of the blocked resource load.
+blockAllMixedContent = Blocking insecure request '%1$S'.
 
 # CSP Errors:
 # LOCALIZATION NOTE (couldntParseInvalidSource):
 # %1$S is the source that could not be parsed
 couldntParseInvalidSource = Couldn't parse invalid source %1$S
 # LOCALIZATION NOTE (couldntParseInvalidHost):
 # %1$S is the host that's invalid
 couldntParseInvalidHost = Couldn't parse invalid host %1$S
deleted file mode 100644
--- a/dom/media/gmp-plugin-openh264/Makefile.in
+++ /dev/null
@@ -1,12 +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/.
-
-INSTALL_TARGETS += FAKE_GMP_OPENH264_PLUGIN
-FAKE_GMP_OPENH264_PLUGIN_DEST = $(DEPTH)/dist/bin/gmp-fakeopenh264/1.0
-FAKE_GMP_OPENH264_PLUGIN_FILES = \
-  $(srcdir)/fakeopenh264.info \
-  $(srcdir)/fakeopenh264.voucher \
-  $(NULL)
-
--- a/dom/media/gmp-plugin-openh264/moz.build
+++ b/dom/media/gmp-plugin-openh264/moz.build
@@ -2,16 +2,22 @@
 # vim: set filetype=python:
 # 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/.
 
 # largely a copy of dom/media/gmp-fake/moz.build
 
 FINAL_TARGET = 'dist/bin/gmp-fakeopenh264/1.0'
+
+FINAL_TARGET_FILES += [
+    'fakeopenh264.info',
+    'fakeopenh264.voucher',
+]
+
 SOURCES += [
     'gmp-fake-openh264.cpp',
 ]
 
 SharedLibrary("fakeopenh264")
 
 if CONFIG['OS_ARCH'] == 'WINNT':
     OS_LIBS += [
deleted file mode 100644
--- a/dom/media/gmp-plugin/Makefile.in
+++ /dev/null
@@ -1,13 +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/.
-
-INSTALL_TARGETS += FAKE_GMP_PLUGIN
-FAKE_GMP_PLUGIN_DEST = $(DEPTH)/dist/bin/gmp-fake/1.0
-FAKE_GMP_PLUGIN_FILES = \
-  $(SHARED_LIBRARY) \
-  $(srcdir)/fake.info \
-  $(srcdir)/fake.voucher
-
-include $(topsrcdir)/config/rules.mk
--- a/dom/media/gmp-plugin/moz.build
+++ b/dom/media/gmp-plugin/moz.build
@@ -1,15 +1,21 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
-DIST_INSTALL = False
+FINAL_TARGET = 'dist/bin/gmp-fake/1.0'
+
+FINAL_TARGET_FILES += [
+    'fake.info',
+    'fake.voucher',
+]
+
 SOURCES += [
         'gmp-fake.cpp',
         'gmp-test-decryptor.cpp',
         'gmp-test-storage.cpp',
 ]
 
 DEFINES['GMP_FAKE_SUPPORT_DECRYPT'] = True
 
--- a/dom/plugins/ipc/PluginModuleParent.cpp
+++ b/dom/plugins/ipc/PluginModuleParent.cpp
@@ -119,16 +119,21 @@ mozilla::plugins::SetupBridge(uint32_t a
     PluginModuleChromeParent::ClearInstantiationFlag();
     RefPtr<nsPluginHost> host = nsPluginHost::GetInst();
     RefPtr<nsNPAPIPlugin> plugin;
     *rv = host->GetPluginForContentProcess(aPluginId, getter_AddRefs(plugin));
     if (NS_FAILED(*rv)) {
         return true;
     }
     PluginModuleChromeParent* chromeParent = static_cast<PluginModuleChromeParent*>(plugin->GetLibrary());
+    /*
+     *  We can't accumulate BLOCKED_ON_PLUGIN_MODULE_INIT_MS until here because
+     *  its histogram key is not available until *after* NP_Initialize.
+     */
+    chromeParent->AccumulateModuleInitBlockedTime();
     *rv = chromeParent->GetRunID(runID);
     if (NS_FAILED(*rv)) {
         return true;
     }
     if (chromeParent->IsStartingAsync()) {
         chromeParent->SetContentParent(aContentParent);
     }
     if (!aForceBridgeNow && chromeParent->IsStartingAsync() &&
@@ -396,23 +401,26 @@ PluginModuleContentParent::LoadModule(ui
      * message. Before it sends its response, it sends a message to create
      * PluginModuleParent instance. That message is handled by
      * PluginModuleContentParent::Initialize, which saves the instance in
      * its module mapping. We fetch it from there after LoadPlugin finishes.
      */
     dom::ContentChild* cp = dom::ContentChild::GetSingleton();
     nsresult rv;
     uint32_t runID;
+    TimeStamp sendLoadPluginStart = TimeStamp::Now();
     if (!cp->SendLoadPlugin(aPluginId, &rv, &runID) ||
         NS_FAILED(rv)) {
         return nullptr;
     }
+    TimeStamp sendLoadPluginEnd = TimeStamp::Now();
 
     PluginModuleContentParent* parent = mapping->GetModule();
     MOZ_ASSERT(parent);
+    parent->mTimeBlocked += (sendLoadPluginEnd - sendLoadPluginStart);
 
     if (!mapping->IsChannelOpened()) {
         // mapping is linked into PluginModuleMapping::sModuleListHead and is
         // needed later, so since this function is returning successfully we
         // forget it here.
         mapping.forget();
     }
 
@@ -2621,36 +2629,45 @@ class nsCaseInsensitiveUTF8StringArrayCo
 {
 public:
   template<class A, class B>
   bool Equals(const A& a, const B& b) const {
     return a.Equals(b.get(), nsCaseInsensitiveUTF8StringComparator());
   }
 };
 
+void
+PluginModuleParent::AccumulateModuleInitBlockedTime()
+{
+    if (mPluginName.IsEmpty()) {
+        GetPluginDetails();
+    }
+    Telemetry::Accumulate(Telemetry::BLOCKED_ON_PLUGIN_MODULE_INIT_MS,
+                          GetHistogramKey(),
+                          static_cast<uint32_t>(mTimeBlocked.ToMilliseconds()));
+    mTimeBlocked = TimeDuration();
+}
+
 nsresult
 PluginModuleParent::NPP_NewInternal(NPMIMEType pluginType, NPP instance,
                                     uint16_t mode,
                                     InfallibleTArray<nsCString>& names,
                                     InfallibleTArray<nsCString>& values,
                                     NPSavedData* saved, NPError* error)
 {
     if (mPluginName.IsEmpty()) {
         GetPluginDetails();
         InitQuirksModes(nsDependentCString(pluginType));
         /** mTimeBlocked measures the time that the main thread has been blocked
          *  on plugin module initialization. As implemented, this is the sum of
          *  plugin-container launch + toolhelp32 snapshot + NP_Initialize.
          *  We don't accumulate its value until here because the plugin info
-         *  is not available until *after* NP_Initialize.
+         *  for its histogram key is not available until *after* NP_Initialize.
          */
-        Telemetry::Accumulate(Telemetry::BLOCKED_ON_PLUGIN_MODULE_INIT_MS,
-                              GetHistogramKey(),
-                              static_cast<uint32_t>(mTimeBlocked.ToMilliseconds()));
-        mTimeBlocked = TimeDuration();
+        AccumulateModuleInitBlockedTime();
     }
 
     nsCaseInsensitiveUTF8StringArrayComparator comparator;
     NS_NAMED_LITERAL_CSTRING(srcAttributeName, "src");
     auto srcAttributeIndex = names.IndexOf(srcAttributeName, 0, comparator);
     nsAutoCString srcAttribute;
     if (srcAttributeIndex != names.NoIndex) {
         srcAttribute = values[srcAttributeIndex];
--- a/dom/plugins/ipc/PluginModuleParent.h
+++ b/dom/plugins/ipc/PluginModuleParent.h
@@ -131,16 +131,18 @@ public:
     void ProcessRemoteNativeEventsInInterruptCall() override;
 
     virtual bool WaitForIPCConnection() { return true; }
 
     nsCString GetHistogramKey() const {
         return mPluginName + mPluginVersion;
     }
 
+    void AccumulateModuleInitBlockedTime();
+
     virtual nsresult GetRunID(uint32_t* aRunID) override;
     virtual void SetHasLocalInstance() override {
         mHadLocalInstance = true;
     }
 
     int GetQuirks() { return mQuirks; }
 
 protected:
--- a/dom/security/nsCSPContext.cpp
+++ b/dom/security/nsCSPContext.cpp
@@ -304,16 +304,29 @@ nsCSPContext::GetUpgradeInsecureRequests
       *outUpgradeRequest = true;
       return NS_OK;
     }
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP
+nsCSPContext::GetBlockAllMixedContent(bool *outBlockAllMixedContent)
+{
+  *outBlockAllMixedContent = false;
+  for (uint32_t i = 0; i < mPolicies.Length(); i++) {
+    if (mPolicies[i]->hasDirective(nsIContentSecurityPolicy::BLOCK_ALL_MIXED_CONTENT)) {
+      *outBlockAllMixedContent = true;
+      return NS_OK;
+    }
+  }
+  return NS_OK;
+}
+
+NS_IMETHODIMP
 nsCSPContext::GetReferrerPolicy(uint32_t* outPolicy, bool* outIsSet)
 {
   *outIsSet = false;
   *outPolicy = mozilla::net::RP_Default;
   nsAutoString refpol;
   mozilla::net::ReferrerPolicy previousPolicy = mozilla::net::RP_Default;
   for (uint32_t i = 0; i < mPolicies.Length(); i++) {
     mPolicies[i]->getReferrerPolicy(refpol);
--- a/dom/security/nsCSPParser.cpp
+++ b/dom/security/nsCSPParser.cpp
@@ -1003,16 +1003,21 @@ nsCSPParser::directiveName()
     // log to the console to indicate that meta CSP is ignoring the directive
     const char16_t* params[] = { mCurToken.get() };
     logWarningErrorToConsole(nsIScriptError::warningFlag,
                              "ignoringSrcFromMetaCSP",
                              params, ArrayLength(params));
     return nullptr;
   }
 
+  // special case handling for block-all-mixed-content
+  if (CSP_IsDirective(mCurToken, nsIContentSecurityPolicy::BLOCK_ALL_MIXED_CONTENT)) {
+    return new nsBlockAllMixedContentDirective(CSP_StringToCSPDirective(mCurToken));
+  }
+
   // special case handling for upgrade-insecure-requests
   if (CSP_IsDirective(mCurToken, nsIContentSecurityPolicy::UPGRADE_IF_INSECURE_DIRECTIVE)) {
     return new nsUpgradeInsecureDirective(CSP_StringToCSPDirective(mCurToken));
   }
 
   // child-src has it's own class to handle frame-src if necessary
   if (CSP_IsDirective(mCurToken, nsIContentSecurityPolicy::CHILD_SRC_DIRECTIVE)) {
     mChildSrc = new nsCSPChildSrcDirective(CSP_StringToCSPDirective(mCurToken));
@@ -1054,16 +1059,30 @@ nsCSPParser::directive()
 
   // Try to create a new CSPDirective
   nsCSPDirective* cspDir = directiveName();
   if (!cspDir) {
     // if we can not create a CSPDirective, we can skip parsing the srcs for that array
     return;
   }
 
+  // special case handling for block-all-mixed-content, which is only specified
+  // by a directive name but does not include any srcs.
+  if (cspDir->equals(nsIContentSecurityPolicy::BLOCK_ALL_MIXED_CONTENT)) {
+    if (mCurDir.Length() > 1) {
+      const char16_t* params[] = { MOZ_UTF16("block-all-mixed-content") };
+      logWarningErrorToConsole(nsIScriptError::warningFlag,
+                               "ignoreSrcForDirective",
+                               params, ArrayLength(params));
+    }
+    // add the directive and return
+    mPolicy->addDirective(cspDir);
+    return;
+  }
+
   // special case handling for upgrade-insecure-requests, which is only specified
   // by a directive name but does not include any srcs.
   if (cspDir->equals(nsIContentSecurityPolicy::UPGRADE_IF_INSECURE_DIRECTIVE)) {
     if (mCurDir.Length() > 1) {
       const char16_t* params[] = { MOZ_UTF16("upgrade-insecure-requests") };
       logWarningErrorToConsole(nsIScriptError::warningFlag,
                                "ignoreSrcForDirective",
                                params, ArrayLength(params));
--- a/dom/security/nsCSPUtils.cpp
+++ b/dom/security/nsCSPUtils.cpp
@@ -897,16 +897,21 @@ nsCSPDirective::toDomCSPStruct(mozilla::
       outCSP.mBase_uri.Value() = mozilla::Move(srcs);
       return;
 
     case nsIContentSecurityPolicy::FORM_ACTION_DIRECTIVE:
       outCSP.mForm_action.Construct();
       outCSP.mForm_action.Value() = mozilla::Move(srcs);
       return;
 
+    case nsIContentSecurityPolicy::BLOCK_ALL_MIXED_CONTENT:
+      outCSP.mBlock_all_mixed_content.Construct();
+      // does not have any srcs
+      return;
+
     case nsIContentSecurityPolicy::UPGRADE_IF_INSECURE_DIRECTIVE:
       outCSP.mUpgrade_insecure_requests.Construct();
       // does not have any srcs
       return;
 
     case nsIContentSecurityPolicy::CHILD_SRC_DIRECTIVE:
       outCSP.mChild_src.Construct();
       outCSP.mChild_src.Value() = mozilla::Move(srcs);
@@ -982,16 +987,34 @@ bool nsCSPChildSrcDirective::equals(CSPD
 {
   if (aDirective == nsIContentSecurityPolicy::FRAME_SRC_DIRECTIVE) {
     return mHandleFrameSrc;
   }
 
   return (aDirective == nsIContentSecurityPolicy::CHILD_SRC_DIRECTIVE);
 }
 
+/* =============== nsBlockAllMixedContentDirective ============= */
+
+nsBlockAllMixedContentDirective::nsBlockAllMixedContentDirective(CSPDirective aDirective)
+: nsCSPDirective(aDirective)
+{
+}
+
+nsBlockAllMixedContentDirective::~nsBlockAllMixedContentDirective()
+{
+}
+
+void
+nsBlockAllMixedContentDirective::toString(nsAString& outStr) const
+{
+  outStr.AppendASCII(CSP_CSPDirectiveToString(
+    nsIContentSecurityPolicy::BLOCK_ALL_MIXED_CONTENT));
+}
+
 /* =============== nsUpgradeInsecureDirective ============= */
 
 nsUpgradeInsecureDirective::nsUpgradeInsecureDirective(CSPDirective aDirective)
 : nsCSPDirective(aDirective)
 {
 }
 
 nsUpgradeInsecureDirective::~nsUpgradeInsecureDirective()
--- a/dom/security/nsCSPUtils.h
+++ b/dom/security/nsCSPUtils.h
@@ -83,17 +83,18 @@ static const char* CSPStrDirectives[] = 
   "report-uri",                // REPORT_URI_DIRECTIVE
   "frame-ancestors",           // FRAME_ANCESTORS_DIRECTIVE
   "reflected-xss",             // REFLECTED_XSS_DIRECTIVE
   "base-uri",                  // BASE_URI_DIRECTIVE
   "form-action",               // FORM_ACTION_DIRECTIVE
   "referrer",                  // REFERRER_DIRECTIVE
   "manifest-src",              // MANIFEST_SRC_DIRECTIVE
   "upgrade-insecure-requests", // UPGRADE_IF_INSECURE_DIRECTIVE
-  "child-src"                  // CHILD_SRC_DIRECTIVE
+  "child-src",                 // CHILD_SRC_DIRECTIVE
+  "block-all-mixed-content"    // BLOCK_ALL_MIXED_CONTENT
 };
 
 inline const char* CSP_CSPDirectiveToString(CSPDirective aDir)
 {
   return CSPStrDirectives[static_cast<uint32_t>(aDir)];
 }
 
 inline CSPDirective CSP_StringToCSPDirective(const nsAString& aDir)
@@ -338,16 +339,39 @@ class nsCSPChildSrcDirective : public ns
     virtual bool restrictsContentType(nsContentPolicyType aContentType) const;
 
     virtual bool equals(CSPDirective aDirective) const;
 
   private:
     bool mHandleFrameSrc;
 };
 
+/* =============== nsBlockAllMixedContentDirective === */
+
+class nsBlockAllMixedContentDirective : public nsCSPDirective {
+  public:
+    explicit nsBlockAllMixedContentDirective(CSPDirective aDirective);
+    ~nsBlockAllMixedContentDirective();
+
+    bool permits(nsIURI* aUri, const nsAString& aNonce, bool aWasRedirected,
+                 bool aReportOnly, bool aUpgradeInsecure) const
+      { return false; }
+
+    bool permits(nsIURI* aUri) const
+      { return false; }
+
+    bool allows(enum CSPKeyword aKeyword, const nsAString& aHashOrNonce) const
+      { return false; }
+
+    void toString(nsAString& outStr) const;
+
+    void addSrcs(const nsTArray<nsCSPBaseSrc*>& aSrcs)
+      {  MOZ_ASSERT(false, "block-all-mixed-content does not hold any srcs"); }
+};
+
 /* =============== nsUpgradeInsecureDirective === */
 
 /*
  * Upgrading insecure requests includes the following actors:
  * (1) CSP:
  *     The CSP implementation whitelists the http-request
  *     in case the policy is executed in enforcement mode.
  *     The CSP implementation however does not allow http
--- a/dom/security/nsMixedContentBlocker.cpp
+++ b/dom/security/nsMixedContentBlocker.cpp
@@ -627,16 +627,45 @@ nsMixedContentBlocker::ShouldLoad(bool a
     *aDecision = REJECT_REQUEST;
     return NS_OK;
   }
   if (!parentIsHttps) {
     *aDecision = ACCEPT;
     return NS_OK;
   }
 
+  nsCOMPtr<nsIDocShell> docShell = NS_CP_GetDocShellFromContext(aRequestingContext);
+  NS_ENSURE_TRUE(docShell, NS_OK);
+
+  // The page might have set the CSP directive 'block-all-mixed-content' which
+  // should block not only active mixed content loads but in fact all mixed content
+  // loads, see https://www.w3.org/TR/mixed-content/#strict-checking
+  // Block all non secure loads in case the CSP directive is present. Please note
+  // that at this point we already know, based on |schemeSecure| that the load is
+  // not secure, so we can bail out early at this point.
+  if (docShell->GetDocument()->GetBlockAllMixedContent(isPreload)) {
+    // log a message to the console before returning.
+    nsAutoCString spec;
+    rv = aContentLocation->GetSpec(spec);
+    NS_ENSURE_SUCCESS(rv, rv);
+    NS_ConvertUTF8toUTF16 reportSpec(spec);
+
+    const char16_t* params[] = { reportSpec.get()};
+    CSP_LogLocalizedStr(MOZ_UTF16("blockAllMixedContent"),
+                        params, ArrayLength(params),
+                        EmptyString(), // aSourceFile
+                        EmptyString(), // aScriptSample
+                        0, // aLineNumber
+                        0, // aColumnNumber
+                        nsIScriptError::errorFlag, "CSP",
+                        docShell->GetDocument()->InnerWindowID());
+    *aDecision = REJECT_REQUEST;
+    return NS_OK;
+  }
+
   // Disallow mixed content loads for workers, shared workers and service
   // workers.
   if (isWorkerType) {
     // For workers, we can assume that we're mixed content at this point, since
     // the parent is https, and the protocol associated with aContentLocation
     // doesn't map to the secure URI flags checked above.  Assert this for
     // sanity's sake
 #ifdef DEBUG
@@ -644,20 +673,16 @@ nsMixedContentBlocker::ShouldLoad(bool a
     rv = aContentLocation->SchemeIs("https", &isHttpsScheme);
     NS_ENSURE_SUCCESS(rv, rv);
     MOZ_ASSERT(!isHttpsScheme);
 #endif
     *aDecision = REJECT_REQUEST;
     return NS_OK;
   }
 
-  // Determine if the rootDoc is https and if the user decided to allow Mixed Content
-  nsCOMPtr<nsIDocShell> docShell = NS_CP_GetDocShellFromContext(aRequestingContext);
-  NS_ENSURE_TRUE(docShell, NS_OK);
-
   // The page might have set the CSP directive 'upgrade-insecure-requests'. In such
   // a case allow the http: load to succeed with the promise that the channel will
   // get upgraded to https before fetching any data from the netwerk.
   // Please see: nsHttpChannel::Connect()
   //
   // Please note that the CSP directive 'upgrade-insecure-requests' only applies to
   // http: and ws: (for websockets). Websockets are not subject to mixed content
   // blocking since insecure websockets are not allowed within secure pages. Hence,
@@ -667,16 +692,17 @@ nsMixedContentBlocker::ShouldLoad(bool a
   bool isHttpScheme = false;
   rv = aContentLocation->SchemeIs("http", &isHttpScheme);
   NS_ENSURE_SUCCESS(rv, rv);
   if (isHttpScheme && docShell->GetDocument()->GetUpgradeInsecureRequests(isPreload)) {
     *aDecision = ACCEPT;
     return NS_OK;
   }
 
+  // Determine if the rootDoc is https and if the user decided to allow Mixed Content
   bool rootHasSecureConnection = false;
   bool allowMixedContent = false;
   bool isRootDocShell = false;
   rv = docShell->GetAllowMixedContentAndConnectionData(&rootHasSecureConnection, &allowMixedContent, &isRootDocShell);
   if (NS_FAILED(rv)) {
     *aDecision = REJECT_REQUEST;
     return rv;
   }
new file mode 100644
--- /dev/null
+++ b/dom/security/test/csp/file_block_all_mcb.sjs
@@ -0,0 +1,53 @@
+// custom *.sjs for Bug 1122236
+// CSP: 'block-all-mixed-content'
+
+const HEAD =
+  "<!DOCTYPE HTML>" +
+  "<html><head><meta charset=\"utf-8\">" +
+  "<title>Bug 1122236 - CSP: Implement block-all-mixed-content</title>" +
+  "</head>";
+
+const CSP_ALLOW =
+  "<meta http-equiv=\"Content-Security-Policy\" content=\"img-src *\">";
+
+const CSP_BLOCK =
+  "<meta http-equiv=\"Content-Security-Policy\" content=\"block-all-mixed-content\">";
+
+const BODY =
+  "<body>" +
+  "<img id=\"testimage\" src=\"http://mochi.test:8888/tests/image/test/mochitest/blue.png\"></img>" +
+  "<script type=\"application/javascript\">" +
+  "  var myImg = document.getElementById(\"testimage\");" +
+  "  myImg.onload = function(e) {" +
+  "    window.parent.postMessage({result: \"img-loaded\"}, \"*\");" +
+  "  };" +
+  "  myImg.onerror = function(e) {" +
+  "    window.parent.postMessage({result: \"img-blocked\"}, \"*\");" +
+  "  };" +
+  "</script>" +
+  "</body>" +
+  "</html>";
+
+function handleRequest(request, response)
+{
+  // avoid confusing cache behaviors
+  response.setHeader("Cache-Control", "no-cache", false);
+ 
+  var queryString = request.queryString;
+
+  if (queryString === "csp-block") {
+    response.write(HEAD + CSP_BLOCK + BODY);
+    return;
+  }
+  if (queryString === "csp-allow") {
+    response.write(HEAD + CSP_ALLOW + BODY);
+    return;
+  }
+  if (queryString === "no-csp") {
+    response.write(HEAD + BODY);
+    return;
+  }
+  // we should never get here but just in case return something unexpected
+  response.write("do'h");
+
+}
new file mode 100644
--- /dev/null
+++ b/dom/security/test/csp/file_block_all_mixed_content_frame_navigation1.html
@@ -0,0 +1,19 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <meta charset="utf-8">
+  <meta http-equiv="Content-Security-Policy" content="block-all-mixed-content">
+  <title>Bug 1122236 - CSP: Implement block-all-mixed-content</title>
+</head>
+<body>
+<b>user clicks and navigates from https://b.com to http://c.com</b>
+
+<a id="navlink" href="http://example.com/tests/dom/security/test/csp/file_block_all_mixed_content_frame_navigation2.html">foo</a>
+
+<script class="testbody" type="text/javascript">
+  // click the link to start the frame navigation
+  document.getElementById("navlink").click();
+</script>
+
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/security/test/csp/file_block_all_mixed_content_frame_navigation2.html
@@ -0,0 +1,15 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <meta charset="utf-8">
+  <title>Bug 1122236 - CSP: Implement block-all-mixed-content</title>
+</head>
+<body>
+<b>http://c.com loaded, let's tell the parent</b>
+
+<script class="testbody" type="text/javascript">
+  window.parent.postMessage({result: "frame-navigated"}, "*");
+</script>
+
+</body>
+</html>
--- a/dom/security/test/csp/mochitest.ini
+++ b/dom/security/test/csp/mochitest.ini
@@ -151,16 +151,19 @@ support-files =
   file_meta_header_dual.sjs
   file_docwrite_meta.html
   file_doccomment_meta.html
   file_docwrite_meta.css
   file_docwrite_meta.js
   file_multipart_testserver.sjs
   file_fontloader.sjs
   file_fontloader.woff
+  file_block_all_mcb.sjs
+  file_block_all_mixed_content_frame_navigation1.html
+  file_block_all_mixed_content_frame_navigation2.html
 
 [test_base-uri.html]
 [test_blob_data_schemes.html]
 [test_connect-src.html]
 [test_CSP.html]
 [test_allow_https_schemes.html]
 skip-if = buildapp == 'b2g' #no ssl support
 [test_bug663567.html]
@@ -231,8 +234,12 @@ skip-if = toolkit == 'android' #investig
 [test_child-src_worker_data.html]
 [test_child-src_worker-redirect.html]
 [test_child-src_iframe.html]
 [test_meta_element.html]
 [test_meta_header_dual.html]
 [test_docwrite_meta.html]
 [test_multipartchannel.html]
 [test_fontloader.html]
+[test_block_all_mixed_content.html]
+tags = mcb
+[test_block_all_mixed_content_frame_navigation.html]
+tags = mcb
new file mode 100644
--- /dev/null
+++ b/dom/security/test/csp/test_block_all_mixed_content.html
@@ -0,0 +1,94 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <meta charset="utf-8">
+  <title>Bug 1122236 - CSP: Implement block-all-mixed-content</title>
+  <!-- Including SimpleTest.js so we can use waitForExplicitFinish !-->
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<iframe style="width:100%;" id="testframe"></iframe>
+
+<script class="testbody" type="text/javascript">
+
+/* Description of the tests:
+ * Test 1:
+ * We load mixed display content in a frame using the CSP
+ * directive 'block-all-mixed-content' and observe that the image is blocked.
+ *
+ * Test 2:
+ * We load mixed display content in a frame using a CSP that allows the load
+ * and observe that the image is loaded.
+ *
+ * Test 3:
+ * We load mixed display content in a frame not using a CSP at all
+ * and observe that the image is loaded.
+ *
+ * Test 4:
+ * We load mixed display content in a frame using the CSP
+ * directive 'block-all-mixed-content' and observe that the image is blocked.
+ * Please note that Test 3 loads the image we are about to load in Test 4 into
+ * the img cache. Let's make sure the cached (mixed display content) image is
+ * not allowed to be loaded.
+ */
+
+const BASE_URI = "https://example.com/tests/dom/security/test/csp/";
+
+const tests = [
+  { // Test 1
+    query: "csp-block",
+    expected: "img-blocked",
+    description: "(csp-block) block-all-mixed content should block mixed display content"
+  },
+  { // Test 2
+    query: "csp-allow",
+    expected: "img-loaded",
+    description: "(csp-allow) mixed display content should be loaded"
+  },
+  { // Test 3
+    query: "no-csp",
+    expected: "img-loaded",
+    description: "(no-csp) mixed display content should be loaded"
+  },
+  { // Test 4
+    query: "csp-block",
+    expected: "img-blocked",
+    description: "(csp-block) block-all-mixed content should block insecure cache loads"
+  },
+];
+
+var curTest;
+var counter = -1;
+
+function checkResults(result) {
+  is(result, curTest.expected, curTest.description);
+  loadNextTest();
+}
+
+window.addEventListener("message", receiveMessage, false);
+function receiveMessage(event) {
+  checkResults(event.data.result);
+}
+
+function loadNextTest() {
+  counter++;
+  if (counter == tests.length) {
+    window.removeEventListener("message", receiveMessage, false);
+    SimpleTest.finish();
+    return;
+  }
+  curTest = tests[counter];
+  testframe.src =   BASE_URI + "file_block_all_mcb.sjs?" + curTest.query;
+}
+
+SimpleTest.waitForExplicitFinish();
+
+SpecialPowers.pushPrefEnv(
+  { 'set': [["security.mixed_content.block_display_content", false]] },
+  function() { loadNextTest(); }
+);
+
+</script>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/security/test/csp/test_block_all_mixed_content_frame_navigation.html
@@ -0,0 +1,46 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <meta charset="utf-8">
+  <title>Bug 1122236 - CSP: Implement block-all-mixed-content</title>
+  <!-- Including SimpleTest.js so we can use waitForExplicitFinish !-->
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<iframe style="width:100%;" id="testframe"></iframe>
+
+<script class="testbody" type="text/javascript">
+
+/* Description of the test:
+ *
+ * http://a.com embeds https://b.com.
+ * https://b.com has a CSP using 'block-all-mixed-content'.
+ *   | site | http://a.com
+ *   | embeds | https://b.com (uses block-all-mixed-content)
+ *
+ * The user navigates the embedded frame from
+ * https://b.com -> http://c.com.
+ * The test makes sure that such a navigation is not blocked
+ * by block-all-mixed-content.
+ */
+
+function checkResults(result) {
+  is(result, "frame-navigated", "frame should be allowed to be navigated");
+  window.removeEventListener("message", receiveMessage, false);
+  SimpleTest.finish();
+}
+
+window.addEventListener("message", receiveMessage, false);
+function receiveMessage(event) {
+  checkResults(event.data.result);
+}
+
+SimpleTest.waitForExplicitFinish();
+// http://a.com loads https://b.com
+document.getElementById("testframe").src =
+  "https://example.com/tests/dom/security/test/csp/file_block_all_mixed_content_frame_navigation1.html";
+
+</script>
+</body>
+</html>
--- a/dom/webidl/CSPDictionaries.webidl
+++ b/dom/webidl/CSPDictionaries.webidl
@@ -22,13 +22,14 @@ dictionary CSP {
   sequence<DOMString> frame-ancestors;
   // sequence<DOMString> reflected-xss; // not suppored in Firefox
   sequence<DOMString> base-uri;
   sequence<DOMString> form-action;
   sequence<DOMString> referrer;
   sequence<DOMString> manifest-src;
   sequence<DOMString> upgrade-insecure-requests;
   sequence<DOMString> child-src;
+  sequence<DOMString> block-all-mixed-content;
 };
 
 dictionary CSPPolicies {
   sequence<CSP> csp-policies;
 };
--- a/dom/xbl/nsXBLService.cpp
+++ b/dom/xbl/nsXBLService.cpp
@@ -551,32 +551,17 @@ nsXBLService::AttachGlobalKeyHandler(Eve
     return NS_OK;
 
   nsCOMPtr<nsIDOMElement> elt(do_QueryInterface(contentNode));
 
   // Create the key handler
   RefPtr<nsXBLWindowKeyHandler> handler =
     NS_NewXBLWindowKeyHandler(elt, piTarget);
 
-  // listen to these events
-  manager->AddEventListenerByType(handler, NS_LITERAL_STRING("keydown"),
-                                  TrustedEventsAtSystemGroupBubble());
-  manager->AddEventListenerByType(handler, NS_LITERAL_STRING("keyup"),
-                                  TrustedEventsAtSystemGroupBubble());
-  manager->AddEventListenerByType(handler, NS_LITERAL_STRING("keypress"),
-                                  TrustedEventsAtSystemGroupBubble());
-
-  // The capturing listener is only used for XUL keysets to properly handle
-  // shortcut keys in a multi-process environment.
-  manager->AddEventListenerByType(handler, NS_LITERAL_STRING("keydown"),
-                                  TrustedEventsAtSystemGroupCapture());
-  manager->AddEventListenerByType(handler, NS_LITERAL_STRING("keyup"),
-                                  TrustedEventsAtSystemGroupCapture());
-  manager->AddEventListenerByType(handler, NS_LITERAL_STRING("keypress"),
-                                  TrustedEventsAtSystemGroupCapture());
+  handler->InstallKeyboardEventListenersTo(manager);
 
   if (contentNode)
     return contentNode->SetProperty(nsGkAtoms::listener,
                                     handler.forget().take(),
                                     nsPropertyTable::SupportsDtorFunc, true);
 
   // The reference to the handler will be maintained by the event target,
   // and, if there is a content node, the property.
@@ -606,29 +591,18 @@ nsXBLService::DetachGlobalKeyHandler(Eve
   if (!piTarget || !manager)
     return NS_ERROR_FAILURE;
 
   nsIDOMEventListener* handler =
     static_cast<nsIDOMEventListener*>(contentNode->GetProperty(nsGkAtoms::listener));
   if (!handler)
     return NS_ERROR_FAILURE;
 
-  manager->RemoveEventListenerByType(handler, NS_LITERAL_STRING("keydown"),
-                                     TrustedEventsAtSystemGroupBubble());
-  manager->RemoveEventListenerByType(handler, NS_LITERAL_STRING("keyup"),
-                                     TrustedEventsAtSystemGroupBubble());
-  manager->RemoveEventListenerByType(handler, NS_LITERAL_STRING("keypress"),
-                                     TrustedEventsAtSystemGroupBubble());
-
-  manager->RemoveEventListenerByType(handler, NS_LITERAL_STRING("keydown"),
-                                     TrustedEventsAtSystemGroupCapture());
-  manager->RemoveEventListenerByType(handler, NS_LITERAL_STRING("keyup"),
-                                     TrustedEventsAtSystemGroupCapture());
-  manager->RemoveEventListenerByType(handler, NS_LITERAL_STRING("keypress"),
-                                     TrustedEventsAtSystemGroupCapture());
+  static_cast<nsXBLWindowKeyHandler*>(handler)->
+    RemoveKeyboardEventListenersFrom(manager);
 
   contentNode->DeleteProperty(nsGkAtoms::listener);
 
   return NS_OK;
 }
 
 // Internal helper methods ////////////////////////////////////////////////////////////////
 
--- a/dom/xbl/nsXBLWindowKeyHandler.cpp
+++ b/dom/xbl/nsXBLWindowKeyHandler.cpp
@@ -18,16 +18,17 @@
 #include "nsFocusManager.h"
 #include "nsIURI.h"
 #include "nsNetUtil.h"
 #include "nsContentUtils.h"
 #include "nsXBLPrototypeBinding.h"
 #include "nsPIDOMWindow.h"
 #include "nsIDocShell.h"
 #include "nsIPresShell.h"
+#include "mozilla/EventListenerManager.h"
 #include "mozilla/EventStateManager.h"
 #include "nsISelectionController.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/TextEvents.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/Event.h"
 #include "nsIEditor.h"
 #include "nsIHTMLEditor.h"
@@ -292,74 +293,175 @@ nsXBLWindowKeyHandler::WalkHandlers(nsID
     return NS_OK;
   }
 
   WalkHandlersInternal(aKeyEvent, aEventType, mHandler, true);
 
   return NS_OK;
 }
 
+void
+nsXBLWindowKeyHandler::InstallKeyboardEventListenersTo(
+                         EventListenerManager* aEventListenerManager)
+{
+  // For marking each keyboard event as if it's reserved by chrome,
+  // nsXBLWindowKeyHandlers need to listen each keyboard events before
+  // web contents.
+  aEventListenerManager->AddEventListenerByType(
+                           this, NS_LITERAL_STRING("keydown"),
+                           TrustedEventsAtCapture());
+  aEventListenerManager->AddEventListenerByType(
+                           this, NS_LITERAL_STRING("keyup"),
+                           TrustedEventsAtCapture());
+  aEventListenerManager->AddEventListenerByType(
+                           this, NS_LITERAL_STRING("keypress"),
+                           TrustedEventsAtCapture());
+
+  // For reducing the IPC cost, preventing to dispatch reserved keyboard
+  // events into the content process.
+  aEventListenerManager->AddEventListenerByType(
+                           this, NS_LITERAL_STRING("keydown"),
+                           TrustedEventsAtSystemGroupCapture());
+  aEventListenerManager->AddEventListenerByType(
+                           this, NS_LITERAL_STRING("keyup"),
+                           TrustedEventsAtSystemGroupCapture());
+  aEventListenerManager->AddEventListenerByType(
+                           this, NS_LITERAL_STRING("keypress"),
+                           TrustedEventsAtSystemGroupCapture());
+
+  // Handle keyboard events in bubbling phase of the system event group.
+  aEventListenerManager->AddEventListenerByType(
+                           this, NS_LITERAL_STRING("keydown"),
+                           TrustedEventsAtSystemGroupBubble());
+  aEventListenerManager->AddEventListenerByType(
+                           this, NS_LITERAL_STRING("keyup"),
+                           TrustedEventsAtSystemGroupBubble());
+  aEventListenerManager->AddEventListenerByType(
+                           this, NS_LITERAL_STRING("keypress"),
+                           TrustedEventsAtSystemGroupBubble());
+}
+
+void
+nsXBLWindowKeyHandler::RemoveKeyboardEventListenersFrom(
+                         EventListenerManager* aEventListenerManager)
+{
+  aEventListenerManager->RemoveEventListenerByType(
+                           this, NS_LITERAL_STRING("keydown"),
+                           TrustedEventsAtCapture());
+  aEventListenerManager->RemoveEventListenerByType(
+                           this, NS_LITERAL_STRING("keyup"),
+                           TrustedEventsAtCapture());
+  aEventListenerManager->RemoveEventListenerByType(
+                           this, NS_LITERAL_STRING("keypress"),
+                           TrustedEventsAtCapture());
+
+  aEventListenerManager->RemoveEventListenerByType(
+                           this, NS_LITERAL_STRING("keydown"),
+                           TrustedEventsAtSystemGroupCapture());
+  aEventListenerManager->RemoveEventListenerByType(
+                           this, NS_LITERAL_STRING("keyup"),
+                           TrustedEventsAtSystemGroupCapture());
+  aEventListenerManager->RemoveEventListenerByType(
+                           this, NS_LITERAL_STRING("keypress"),
+                           TrustedEventsAtSystemGroupCapture());
+
+  aEventListenerManager->RemoveEventListenerByType(
+                           this, NS_LITERAL_STRING("keydown"),
+                           TrustedEventsAtSystemGroupBubble());
+  aEventListenerManager->RemoveEventListenerByType(
+                           this, NS_LITERAL_STRING("keyup"),
+                           TrustedEventsAtSystemGroupBubble());
+  aEventListenerManager->RemoveEventListenerByType(
+                           this, NS_LITERAL_STRING("keypress"),
+                           TrustedEventsAtSystemGroupBubble());
+}
+
 NS_IMETHODIMP
 nsXBLWindowKeyHandler::HandleEvent(nsIDOMEvent* aEvent)
 {
   nsCOMPtr<nsIDOMKeyEvent> keyEvent(do_QueryInterface(aEvent));
   NS_ENSURE_TRUE(keyEvent, NS_ERROR_INVALID_ARG);
 
   uint16_t eventPhase;
   aEvent->GetEventPhase(&eventPhase);
   if (eventPhase == nsIDOMEvent::CAPTURING_PHASE) {
-    HandleEventOnCapture(keyEvent);
+    if (aEvent->WidgetEventPtr()->mFlags.mInSystemGroup) {
+      HandleEventOnCaptureInSystemEventGroup(keyEvent);
+    } else {
+      HandleEventOnCaptureInDefaultEventGroup(keyEvent);
+    }
     return NS_OK;
   }
 
   nsAutoString eventType;
   aEvent->GetType(eventType);
   nsCOMPtr<nsIAtom> eventTypeAtom = do_GetAtom(eventType);
   NS_ENSURE_TRUE(eventTypeAtom, NS_ERROR_OUT_OF_MEMORY);
 
   return WalkHandlers(keyEvent, eventTypeAtom);
 }
 
 void
-nsXBLWindowKeyHandler::HandleEventOnCapture(nsIDOMKeyEvent* aEvent)
+nsXBLWindowKeyHandler::HandleEventOnCaptureInDefaultEventGroup(
+                         nsIDOMKeyEvent* aEvent)
+{
+  WidgetKeyboardEvent* widgetKeyboardEvent =
+    aEvent->AsEvent()->WidgetEventPtr()->AsKeyboardEvent();
+
+  if (widgetKeyboardEvent->mFlags.mOnlySystemGroupDispatchInContent) {
+    MOZ_RELEASE_ASSERT(
+      widgetKeyboardEvent->mFlags.mNoCrossProcessBoundaryForwarding);
+    return;
+  }
+
+  bool isReserved = false;
+  if (HasHandlerForEvent(aEvent, &isReserved) && isReserved) {
+    // For reserved commands (such as Open New Tab), we don't to wait for
+    // the content to answer (so mWantReplyFromContentProcess remains false),
+    // neither to give a chance for content to override its behavior.
+    widgetKeyboardEvent->mFlags.mNoCrossProcessBoundaryForwarding = true;
+    // If the key combination is reserved by chrome, we shouldn't expose the
+    // keyboard event to web contents because such keyboard events shouldn't be
+    // cancelable.  So, it's not good behavior to fire keyboard events but
+    // to ignore the defaultPrevented attribute value in chrome.
+    widgetKeyboardEvent->mFlags.mOnlySystemGroupDispatchInContent = true;
+  }
+}
+
+void
+nsXBLWindowKeyHandler::HandleEventOnCaptureInSystemEventGroup(
+                         nsIDOMKeyEvent* aEvent)
 {
   WidgetKeyboardEvent* widgetEvent =
     aEvent->AsEvent()->WidgetEventPtr()->AsKeyboardEvent();
 
-  if (widgetEvent->mFlags.mNoCrossProcessBoundaryForwarding) {
+  if (widgetEvent->mFlags.mNoCrossProcessBoundaryForwarding ||
+      widgetEvent->mFlags.mOnlySystemGroupDispatchInContent) {
     return;
   }
 
   nsCOMPtr<mozilla::dom::Element> originalTarget =
     do_QueryInterface(aEvent->AsEvent()->WidgetEventPtr()->originalTarget);
   if (!EventStateManager::IsRemoteTarget(originalTarget)) {
     return;
   }
 
-  bool aReservedForChrome = false;
-  if (!HasHandlerForEvent(aEvent, &aReservedForChrome)) {
+  if (!HasHandlerForEvent(aEvent)) {
     return;
   }
 
-  if (aReservedForChrome) {
-    // For reserved commands (such as Open New Tab), we don't to wait for
-    // the content to answer (so mWantReplyFromContentProcess remains false),
-    // neither to give a chance for content to override its behavior.
-    widgetEvent->mFlags.mNoCrossProcessBoundaryForwarding = true;
-  } else {
-    // Inform the child process that this is a event that we want a reply
-    // from.
-    widgetEvent->mFlags.mWantReplyFromContentProcess = true;
-
-    // If this event hadn't been marked as mNoCrossProcessBoundaryForwarding
-    // yet, it means it wasn't processed by content. We'll not call any
-    // of the handlers at this moment, and will wait for the event to be
-    // redispatched with mNoCrossProcessBoundaryForwarding = 1 to process it.
-    aEvent->AsEvent()->StopPropagation();
-  }
+  // Inform the child process that this is a event that we want a reply
+  // from.
+  widgetEvent->mFlags.mWantReplyFromContentProcess = true;
+  // If this event hadn't been marked as mNoCrossProcessBoundaryForwarding
+  // yet, it means it wasn't processed by content. We'll not call any
+  // of the handlers at this moment, and will wait for the event to be
+  // redispatched with mNoCrossProcessBoundaryForwarding = 1 to process it.
+  // XXX Why not StopImmediatePropagation()?
+  aEvent->AsEvent()->StopPropagation();
 }
 
 //
 // EventMatched
 //
 // See if the given handler cares about this particular key event
 //
 bool
--- a/dom/xbl/nsXBLWindowKeyHandler.h
+++ b/dom/xbl/nsXBLWindowKeyHandler.h
@@ -12,30 +12,37 @@
 
 class nsIAtom;
 class nsIDOMElement;
 class nsIDOMKeyEvent;
 class nsXBLSpecialDocInfo;
 class nsXBLPrototypeHandler;
 
 namespace mozilla {
+class EventListenerManager;
 namespace dom {
 class Element;
 class EventTarget;
 struct IgnoreModifierState;
 } // namespace dom
 } // namespace mozilla
 
 class nsXBLWindowKeyHandler : public nsIDOMEventListener
 {
   typedef mozilla::dom::IgnoreModifierState IgnoreModifierState;
+  typedef mozilla::EventListenerManager EventListenerManager;
 
 public:
   nsXBLWindowKeyHandler(nsIDOMElement* aElement, mozilla::dom::EventTarget* aTarget);
 
+  void InstallKeyboardEventListenersTo(
+         EventListenerManager* aEventListenerManager);
+  void RemoveKeyboardEventListenersFrom(
+         EventListenerManager* aEventListenerManager);
+
   NS_DECL_ISUPPORTS
   NS_DECL_NSIDOMEVENTLISTENER
 
 protected:
   virtual ~nsXBLWindowKeyHandler();
 
   nsresult WalkHandlers(nsIDOMKeyEvent* aKeyEvent, nsIAtom* aEventType);
 
@@ -50,18 +57,20 @@ protected:
   // it if aExecute = true.
   bool WalkHandlersAndExecute(nsIDOMKeyEvent* aKeyEvent, nsIAtom* aEventType,
                               nsXBLPrototypeHandler* aHandler,
                               uint32_t aCharCode,
                               const IgnoreModifierState& aIgnoreModifierState,
                               bool aExecute,
                               bool* aOutReservedForChrome = nullptr);
 
-  // HandleEvent function for the capturing phase.
-  void HandleEventOnCapture(nsIDOMKeyEvent* aEvent);
+  // HandleEvent function for the capturing phase in the default event group.
+  void HandleEventOnCaptureInDefaultEventGroup(nsIDOMKeyEvent* aEvent);
+  // HandleEvent function for the capturing phase in the system event group.
+  void HandleEventOnCaptureInSystemEventGroup(nsIDOMKeyEvent* aEvent);
 
   // Check if any handler would handle the given event. Optionally returns
   // whether the command handler for the event is marked with the "reserved"
   // attribute.
   bool HasHandlerForEvent(nsIDOMKeyEvent* aEvent,
                           bool* aOutReservedForChrome = nullptr);
 
   // lazily load the handlers. Overridden to handle being attached
--- a/editor/libeditor/moz.build
+++ b/editor/libeditor/moz.build
@@ -6,16 +6,18 @@
 
 MOCHITEST_MANIFESTS += [
     'tests/browserscope/mochitest.ini',
     'tests/mochitest.ini',
 ]
 
 MOCHITEST_CHROME_MANIFESTS += ['tests/chrome.ini']
 
+BROWSER_CHROME_MANIFESTS += ['tests/browser.ini']
+
 UNIFIED_SOURCES += [
     'ChangeAttributeTxn.cpp',
     'ChangeStyleTxn.cpp',
     'CreateElementTxn.cpp',
     'DeleteNodeTxn.cpp',
     'DeleteRangeTxn.cpp',
     'DeleteTextTxn.cpp',
     'EditAggregateTxn.cpp',
new file mode 100644
--- /dev/null
+++ b/editor/libeditor/tests/browser.ini
@@ -0,0 +1,6 @@
+[browser_bug527935.js]
+skip-if = toolkit == 'android'
+support-files = bug527935.html
+[browser_bug629172.js]
+skip-if = toolkit == 'android'
+support-files = bug629172.html
new file mode 100644
--- /dev/null
+++ b/editor/libeditor/tests/browser_bug527935.js
@@ -0,0 +1,63 @@
+add_task(function*() {
+  yield new Promise(resolve => waitForFocus(resolve, window));
+
+  const kPageURL = "http://example.org/browser/editor/libeditor/tests/bug527935.html";
+  yield BrowserTestUtils.withNewTab({
+    gBrowser,
+    url: kPageURL
+  }, function*(aBrowser) {
+    var popupShown = false;
+    function listener() {
+      popupShown = true;
+    }
+    SpecialPowers.addAutoCompletePopupEventListener(window, "popupshowing", listener);
+
+    yield ContentTask.spawn(aBrowser, {}, function*() {
+      var window = content.window.wrappedJSObject;
+      var document = window.document;
+      var formTarget = document.getElementById("formTarget");
+      var initValue = document.getElementById("initValue");
+
+      window.loadPromise = new Promise(resolve => {
+        formTarget.onload = resolve;
+      });
+
+      initValue.focus();
+      initValue.value = "foo";
+    });
+
+    EventUtils.synthesizeKey("VK_RETURN", {});
+
+    yield ContentTask.spawn(aBrowser, {}, function*() {
+      var window = content.window.wrappedJSObject;
+      var document = window.document;
+
+      yield window.loadPromise;
+
+      var newInput = document.createElement("input");
+      newInput.setAttribute("name", "test");
+      document.body.appendChild(newInput);
+
+      var event = document.createEvent("KeyboardEvent");
+
+      event.initKeyEvent("keypress", true, true, null, false, false,
+                         false, false, 0, "f".charCodeAt(0));
+      newInput.value = "";
+      newInput.focus();
+      newInput.dispatchEvent(event);
+    });
+
+    yield new Promise(resolve => hitEventLoop(resolve, 100));
+
+    ok(!popupShown, "Popup must not be opened");
+    SpecialPowers.removeAutoCompletePopupEventListener(window, "popupshowing", listener);
+  });
+});
+
+function hitEventLoop(func, times) {
+  if (times > 0) {
+    setTimeout(hitEventLoop, 0, func, times - 1);
+  } else {
+    setTimeout(func, 0);
+  }
+}
new file mode 100644
--- /dev/null
+++ b/editor/libeditor/tests/browser_bug629172.js
@@ -0,0 +1,106 @@
+add_task(function*() {
+  yield new Promise(resolve => waitForFocus(resolve, window));
+
+  const kPageURL = "http://example.org/browser/editor/libeditor/tests/bug629172.html";
+  yield BrowserTestUtils.withNewTab({
+    gBrowser,
+    url: kPageURL
+  }, function*(aBrowser) {
+    yield ContentTask.spawn(aBrowser, {}, function*() {
+      var window = content.window.wrappedJSObject;
+      var document = window.document;
+
+      // Note: Using the with keyword, we would have been able to write this as:
+      //
+      // with (window) {
+      //   Screenshots = {};
+      //   // so on
+      // }
+      //
+      // However, browser-chrome tests are somehow forced to run in strict mode,
+      // which doesn't permit the usage of the with keyword, turning the following
+      // into the ugliest test you've ever seen.  :(
+      var LTRRef = document.getElementById("ltr-ref");
+      var RTLRef = document.getElementById("rtl-ref");
+      window.Screenshots = {};
+
+      // generate the reference screenshots
+      LTRRef.style.display = "";
+      document.body.clientWidth;
+      window.Screenshots.ltr = window.snapshotWindow(window);
+      LTRRef.parentNode.removeChild(LTRRef);
+      RTLRef.style.display = "";
+      document.body.clientWidth;
+      window.Screenshots.rtl = window.snapshotWindow(window);
+      RTLRef.parentNode.removeChild(RTLRef);
+      window.Screenshots.get = function(dir, flip) {
+        if (flip) {
+          return this[dir == "rtl" ? "ltr" : "rtl"];
+        } else {
+          return this[dir];
+        }
+      };
+    });
+
+    function simulateCtrlShiftX(aBrowser) {
+      // In e10s, the keypress event will be dispatched to the content process,
+      // but in non-e10s it is handled by the browser UI code and hence won't
+      // reach the web page.  As a result, we need to observe the event in
+      // the content process only in e10s mode.
+      var waitForKeypressContent = BrowserTestUtils.waitForContentEvent(aBrowser, "keypress");
+      EventUtils.synthesizeKey("x", {accelKey: true, shiftKey: true});
+      if (gMultiProcessBrowser) {
+        return waitForKeypressContent;
+      }
+      return Promise.resolve();
+    }
+
+    function* testDirection(initialDir, aBrowser) {
+      yield ContentTask.spawn(aBrowser, {initialDir}, function({initialDir}) {
+        var window = content.window.wrappedJSObject;
+        var document = window.document;
+
+        var t = window.t = document.createElement("textarea");
+        t.setAttribute("dir", initialDir);
+        t.value = "test.";
+        window.inputEventCount = 0;
+        t.oninput = function() { window.inputEventCount++; };
+        document.getElementById("content").appendChild(t);
+        document.body.clientWidth;
+        var s1 = window.snapshotWindow(window);
+        ok(window.compareSnapshots(s1, window.Screenshots.get(initialDir, false), true)[0],
+           "Textarea should appear correctly before switching the direction (" + initialDir + ")");
+        t.focus();
+        is(window.inputEventCount, 0, "input event count must be 0 before");
+      });
+      yield simulateCtrlShiftX(aBrowser);
+      yield ContentTask.spawn(aBrowser, {initialDir}, function({initialDir}) {
+        var window = content.window.wrappedJSObject;
+
+        is(window.t.getAttribute("dir"), initialDir == "ltr" ? "rtl" : "ltr", "The dir attribute must be correctly updated");
+        is(window.inputEventCount, 1, "input event count must be 1 after");
+        window.t.blur();
+        var s2 = window.snapshotWindow(window);
+        ok(window.compareSnapshots(s2, window.Screenshots.get(initialDir, true), true)[0],
+           "Textarea should appear correctly after switching the direction (" + initialDir + ")");
+        window.t.focus();
+        is(window.inputEventCount, 1, "input event count must be 1 before");
+      });
+      yield simulateCtrlShiftX(aBrowser);
+      yield ContentTask.spawn(aBrowser, {initialDir}, function({initialDir}) {
+        var window = content.window.wrappedJSObject;
+
+        is(window.inputEventCount, 2, "input event count must be 2 after");
+        is(window.t.getAttribute("dir"), initialDir == "ltr" ? "ltr" : "rtl", "The dir attribute must be correctly updated");
+        window.t.blur();
+        var s3 = window.snapshotWindow(window);
+        ok(window.compareSnapshots(s3, window.Screenshots.get(initialDir, false), true)[0],
+           "Textarea should appear correctly after switching back the direction (" + initialDir + ")");
+        window.t.parentNode.removeChild(window.t);
+      });
+    }
+
+    yield testDirection("ltr", aBrowser);
+    yield testDirection("rtl", aBrowser);
+  });
+});
new file mode 100644
--- /dev/null
+++ b/editor/libeditor/tests/bug527935.html
@@ -0,0 +1,11 @@
+<!DOCTYPE HTML>
+<html>
+<body>
+<div id="content">
+  <iframe id="formTarget" name="formTarget"></iframe>
+  <form action="data:text/html," target="formTarget">
+    <input name="test" id="initValue"><input type="submit">
+  </form>
+</div>
+</body>
+</html
new file mode 100644
--- /dev/null
+++ b/editor/libeditor/tests/bug629172.html
@@ -0,0 +1,15 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<script type="text/javascript" src="/tests/SimpleTest/WindowSnapshot.js"></script>
+<style>
+textarea { resize: none }
+</style>
+</head>
+<body>
+<div id="content">
+<textarea id="ltr-ref" style="display: none">test.</textarea>
+<textarea id="rtl-ref" style="display: none; direction: rtl">test.</textarea>
+</div
+</body>
+</html>
--- a/editor/libeditor/tests/mochitest.ini
+++ b/editor/libeditor/tests/mochitest.ini
@@ -53,18 +53,16 @@ skip-if = toolkit == 'android'
 skip-if = toolkit == 'android'
 [test_bug487524.html]
 [test_bug502673.html]
 [test_bug514156.html]
 [test_bug520189.html]
 skip-if = toolkit == 'android'
 [test_bug525389.html]
 skip-if = toolkit == 'android'
-[test_bug527935.html]
-skip-if = toolkit == 'android' || e10s
 [test_bug537046.html]
 [test_bug549262.html]
 skip-if = toolkit == 'android'
 [test_bug550434.html]
 skip-if = android_version == '18' # bug 1147989
 [test_bug551704.html]
 [test_bug552782.html]
 [test_bug567213.html]
@@ -97,18 +95,16 @@ skip-if = toolkit == 'android'
 skip-if = toolkit == 'android'
 [test_bug612128.html]
 [test_bug612447.html]
 [test_bug620906.html]
 skip-if = toolkit == 'android' #TIMED_OUT
 [test_bug622371.html]
 skip-if = toolkit == 'android' #bug 957797
 [test_bug625452.html]
-[test_bug629172.html]
-skip-if = toolkit == 'android' || e10s
 [test_bug629845.html]
 [test_bug638596.html]
 [test_bug640321.html]
 skip-if = android_version == '18' # bug 1147989
 [test_bug641466.html]
 [test_bug645914.html]
 [test_bug668599.html]
 [test_bug674770-1.html]
deleted file mode 100644
--- a/editor/libeditor/tests/test_bug527935.html
+++ /dev/null
@@ -1,74 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=527935
--->
-<head>
-  <title>Test for Bug 527935</title>
-  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
-  <script type="text/javascript" src="/tests/SimpleTest/EventUtils.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=527935">Mozilla Bug 527935</a>
-<p id="display"></p>
-<div id="content">
-  <iframe id="formTarget" name="formTarget"></iframe>
-  <form action="data:text/html," target="formTarget">
-    <input name="test" id="initValue"><input type="submit">
-  </form>
-</div>
-<pre id="test">
-<script type="application/javascript">
-
-/** Test for Bug 527935 **/
-SimpleTest.waitForExplicitFinish();
-SimpleTest.waitForFocus(function() {
-  var formTarget = document.getElementById("formTarget");
-  var initValue = document.getElementById("initValue");
-
-  formTarget.addEventListener("load", function() {
-    var newInput = document.createElement("input");
-    newInput.setAttribute("name", "test");
-    document.body.appendChild(newInput);
-
-    setTimeout(function() {
-      var popupShown = false;
-      function listener() {
-        popupShown = true;
-      }
-      SpecialPowers.addAutoCompletePopupEventListener(window, "popupshowing", listener);
-
-      var event = document.createEvent("KeyboardEvent");
-
-      event.initKeyEvent("keypress", true, true, null, false, false,
-                         false, false, 0, "f".charCodeAt(0));
-      newInput.value = "";
-      newInput.focus();
-      newInput.dispatchEvent(event);
-
-      hitEventLoop(function() {
-        ok(!popupShown, "Popup must not be opened");
-        SpecialPowers.removeAutoCompletePopupEventListener(window, "popupshowing", listener);
-        SimpleTest.finish();
-      }, 100);
-    }, 0);
-  }, false);
-
-  initValue.focus();
-  initValue.value = "foo";
-  synthesizeKey("VK_RETURN", {});
-});
-
-function hitEventLoop(func, times) {
-  if (times > 0) {
-    setTimeout(hitEventLoop, 0, func, times - 1);
-  } else {
-    setTimeout(func, 0);
-  }
-}
-
-</script>
-</pre>
-</body>
-</html>
deleted file mode 100644
--- a/editor/libeditor/tests/test_bug629172.html
+++ /dev/null
@@ -1,88 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=629172
--->
-<head>
-  <title>Test for Bug 629172</title>
-  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
-  <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
-  <script type="text/javascript" src="/tests/SimpleTest/WindowSnapshot.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=629172">Mozilla Bug 629172</a>
-<p id="display"></p>
-<div id="content">
-<textarea id="ltr-ref" style="display: none">test.</textarea>
-<textarea id="rtl-ref" style="display: none; direction: rtl">test.</textarea>
-</div>
-<pre id="test">
-<script type="application/javascript">
-
-/** Test for Bug 629172 **/
-SimpleTest.waitForExplicitFinish();
-SimpleTest.waitForFocus(function() {
-  var LTRRef = document.getElementById("ltr-ref");
-  var RTLRef = document.getElementById("rtl-ref");
-  var Screenshots = {};
-
-  // generate the reference screenshots
-  LTRRef.style.display = "";
-  document.body.clientWidth;
-  Screenshots.ltr = snapshotWindow(window);
-  LTRRef.parentNode.removeChild(LTRRef);
-  RTLRef.style.display = "";
-  document.body.clientWidth;
-  Screenshots.rtl = snapshotWindow(window);
-  RTLRef.parentNode.removeChild(RTLRef);
-  Screenshots.get = function(dir, flip) {
-    if (flip) {
-      return this[dir == "rtl" ? "ltr" : "rtl"];
-    } else {
-      return this[dir];
-    }
-  };
-
-  function testDirection(initialDir) {
-    var t = document.createElement("textarea");
-    t.setAttribute("dir", initialDir);
-    t.value = "test.";
-    var inputEventCount = 0;
-    t.oninput = function() { inputEventCount++; };
-    document.getElementById("content").appendChild(t);
-    document.body.clientWidth;
-    var s1 = snapshotWindow(window);
-    ok(compareSnapshots(s1, Screenshots.get(initialDir, false), true)[0],
-       "Textarea should appear correctly before switching the direction (" + initialDir + ")");
-    t.focus();
-    is(inputEventCount, 0, "input event count must be 0 before");
-    synthesizeKey("x", {accelKey: true, shiftKey: true});
-    is(t.getAttribute("dir"), initialDir == "ltr" ? "rtl" : "ltr", "The dir attribute must be correctly updated");
-    is(inputEventCount, 1, "input event count must be 1 after");
-    t.blur();
-    var s2 = snapshotWindow(window);
-    ok(compareSnapshots(s2, Screenshots.get(initialDir, true), true)[0],
-       "Textarea should appear correctly after switching the direction (" + initialDir + ")");
-    t.focus();
-    is(inputEventCount, 1, "input event count must be 1 before");
-    synthesizeKey("x", {accelKey: true, shiftKey: true});
-    is(inputEventCount, 2, "input event count must be 2 after");
-    is(t.getAttribute("dir"), initialDir == "ltr" ? "ltr" : "rtl", "The dir attribute must be correctly updated");
-    t.blur();
-    var s3 = snapshotWindow(window);
-    ok(compareSnapshots(s3, Screenshots.get(initialDir, false), true)[0],
-       "Textarea should appear correctly after switching back the direction (" + initialDir + ")");
-    t.parentNode.removeChild(t);
-  }
-
-  testDirection("ltr");
-  testDirection("rtl");
-
-  SimpleTest.finish();
-});
-
-</script>
-</pre>
-</body>
-</html>
--- a/gfx/angle/BUILD.gn
+++ b/gfx/angle/BUILD.gn
@@ -10,64 +10,59 @@ angle_git_is_present = exec_script("src/
                                    [
                                      "check",
                                      rebase_path(".", root_build_dir),
                                    ],
                                    "value")
 
 angle_use_commit_id = angle_git_is_present == 1
 
-gles_gypi = exec_script(
-  "//build/gypi_to_gn.py",
-  [ rebase_path("src/libGLESv2.gypi") ],
-  "scope",
-  [ "src/libGLESv2.gypi" ])
+gles_gypi = exec_script("//build/gypi_to_gn.py",
+                        [ rebase_path("src/libGLESv2.gypi") ],
+                        "scope",
+                        [ "src/libGLESv2.gypi" ])
 
-compiler_gypi = exec_script(
-  "//build/gypi_to_gn.py",
-  [ rebase_path("src/compiler.gypi") ],
-  "scope",
-  [ "src/compiler.gypi" ])
+compiler_gypi = exec_script("//build/gypi_to_gn.py",
+                            [ rebase_path("src/compiler.gypi") ],
+                            "scope",
+                            [ "src/compiler.gypi" ])
 
 # This config is exported to dependent targets (and also applied to internal
 # ones).
 config("external_config") {
-  include_dirs = [
-    "include",
-  ]
+  include_dirs = [ "include" ]
 }
 
 # This config is applied to internal Angle targets (not pushed to dependents).
 config("internal_config") {
   include_dirs = [
     "include",
     "src",
   ]
 }
 
 if (is_win) {
   copy("copy_compiler_dll") {
-    sources = [ "$windows_sdk_path/Redist/D3D/$target_cpu/d3dcompiler_47.dll" ]
-    outputs = [ "$root_build_dir/d3dcompiler_47.dll" ]
+    sources = [
+      "$windows_sdk_path/Redist/D3D/$target_cpu/d3dcompiler_47.dll",
+    ]
+    outputs = [
+      "$root_out_dir/d3dcompiler_47.dll",
+    ]
   }
 }
 
 component("translator") {
   sources = [
     "src/compiler/translator/ShaderLang.cpp",
     "src/compiler/translator/ShaderVars.cpp",
   ]
 
   defines = [ "ANGLE_TRANSLATOR_IMPLEMENTATION" ]
 
-  if (angle_enable_hlsl) {
-    sources += rebase_path(compiler_gypi.angle_translator_lib_hlsl_sources, ".", "src")
-    defines += [ "ANGLE_ENABLE_HLSL" ]
-  }
-
   configs -= [ "//build/config/compiler:chromium_code" ]
   configs += [
     ":internal_config",
     "//build/config/compiler:no_chromium_code",
   ]
 
   public_deps = [
     ":translator_lib",
@@ -79,19 +74,19 @@ source_set("includes") {
   sources = [
     "include/EGL/egl.h",
     "include/EGL/eglext.h",
     "include/EGL/eglplatform.h",
     "include/GLES2/gl2.h",
     "include/GLES2/gl2ext.h",
     "include/GLES2/gl2platform.h",
     "include/GLES3/gl3.h",
-    "include/GLES3/gl3platform.h",
     "include/GLES3/gl31.h",
     "include/GLES3/gl32.h",
+    "include/GLES3/gl3platform.h",
     "include/GLSLANG/ShaderLang.h",
     "include/KHR/khrplatform.h",
   ]
 }
 
 static_library("preprocessor") {
   sources = rebase_path(compiler_gypi.angle_preprocessor_sources, ".", "src")
 
@@ -101,42 +96,53 @@ static_library("preprocessor") {
     "//build/config/compiler:no_chromium_code",
   ]
 }
 
 config("translator_static_config") {
   defines = [ "ANGLE_TRANSLATOR_STATIC" ]
 }
 
-
 config("debug_annotations_config") {
   if (is_debug) {
-    defines = [
-      "ANGLE_ENABLE_DEBUG_ANNOTATIONS",
-    ]
+    defines = [ "ANGLE_ENABLE_DEBUG_ANNOTATIONS" ]
   }
 }
 
 static_library("angle_common") {
   sources = rebase_path(gles_gypi.libangle_common_sources, ".", "src")
 
   configs -= [ "//build/config/compiler:chromium_code" ]
   configs += [
     ":internal_config",
     ":debug_annotations_config",
     "//build/config/compiler:no_chromium_code",
   ]
 }
 
 static_library("translator_lib") {
   sources = rebase_path(compiler_gypi.angle_translator_lib_sources, ".", "src")
+  defines = []
+
+  if (angle_enable_essl) {
+    sources +=
+        rebase_path(compiler_gypi.angle_translator_lib_essl_sources, ".", "src")
+    defines += [ "ANGLE_ENABLE_ESSL" ]
+  }
+
+  if (angle_enable_glsl) {
+    sources +=
+        rebase_path(compiler_gypi.angle_translator_lib_glsl_sources, ".", "src")
+    defines += [ "ANGLE_ENABLE_GLSL" ]
+  }
 
   if (angle_enable_hlsl) {
-    sources += rebase_path(compiler_gypi.angle_translator_lib_hlsl_sources, ".", "src")
-    defines = [ "ANGLE_ENABLE_HLSL" ]
+    sources +=
+        rebase_path(compiler_gypi.angle_translator_lib_hlsl_sources, ".", "src")
+    defines += [ "ANGLE_ENABLE_HLSL" ]
   }
   configs -= [ "//build/config/compiler:chromium_code" ]
   configs += [
     ":internal_config",
     ":translator_static_config",
     "//build/config/compiler:no_chromium_code",
   ]
   public_configs = [ ":external_config" ]
@@ -241,28 +247,23 @@ config("libANGLE_config") {
   }
 }
 
 static_library("libANGLE") {
   sources = rebase_path(gles_gypi.libangle_sources, ".", "src")
 
   include_dirs = []
   libs = []
-  defines = [
-    "LIBANGLE_IMPLEMENTATION",
-  ]
+  defines = [ "LIBANGLE_IMPLEMENTATION" ]
 
   # Shared D3D sources.
   if (angle_enable_d3d9 || angle_enable_d3d11) {
     sources += rebase_path(gles_gypi.libangle_d3d_shared_sources, ".", "src")
 
-    defines += [
-      "ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES={ " +
-        "\"d3dcompiler_47.dll\", \"d3dcompiler_46.dll\", \"d3dcompiler_43.dll\" }",
-    ]
+    defines += [ "ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES={ " + "\"d3dcompiler_47.dll\", \"d3dcompiler_46.dll\", \"d3dcompiler_43.dll\" }" ]
   }
 
   if (angle_enable_d3d9) {
     sources += rebase_path(gles_gypi.libangle_d3d9_sources, ".", "src")
     libs += [ "d3d9.lib" ]
   }
 
   if (angle_enable_d3d11) {
@@ -280,101 +281,100 @@ static_library("libANGLE") {
     }
     if (use_x11) {
       sources += rebase_path(gles_gypi.libangle_gl_glx_sources, ".", "src")
       libs += [ "X11" ]
     }
   }
 
   if (is_debug) {
-    defines += [
-      "ANGLE_GENERATE_SHADER_DEBUG_INFO",
-    ]
+    defines += [ "ANGLE_GENERATE_SHADER_DEBUG_INFO" ]
   }
 
   configs -= [ "//build/config/compiler:chromium_code" ]
   configs += [
     ":commit_id_config",
     ":debug_annotations_config",
     ":libANGLE_config",
     ":internal_config",
     "//build/config/compiler:no_chromium_code",
   ]
 
   deps = [
+    ":angle_common",
     ":commit_id",
     ":includes",
     ":translator_static",
-    ":angle_common",
   ]
 
   if (is_win) {
     deps += [ ":copy_compiler_dll" ]
   }
 }
 
 shared_library("libGLESv2") {
   sources = rebase_path(gles_gypi.libglesv2_sources, ".", "src")
 
   if (is_win) {
-    ldflags = [ "/DEF:" +
-                rebase_path("src/libGLESv2/libGLESv2.def", root_build_dir) ]
+    ldflags =
+        [ "/DEF:" + rebase_path("src/libGLESv2/libGLESv2.def", root_build_dir) ]
   }
 
   configs -= [ "//build/config/compiler:chromium_code" ]
   configs += [
     ":internal_config",
     ":commit_id_config",
     ":debug_annotations_config",
     ":libANGLE_config",
     "//build/config/compiler:no_chromium_code",
   ]
 
-  defines = [
-    "LIBGLESV2_IMPLEMENTATION",
-  ]
+  defines = [ "LIBGLESV2_IMPLEMENTATION" ]
 
   deps = [
     ":includes",
     ":libANGLE",
   ]
 }
 
 shared_library("libEGL") {
   sources = rebase_path(gles_gypi.libegl_sources, ".", "src")
 
   if (is_win) {
-    ldflags = [ "/DEF:" +
-                rebase_path("src/libEGL/libEGL.def", root_build_dir) ]
+    ldflags = [ "/DEF:" + rebase_path("src/libEGL/libEGL.def", root_build_dir) ]
   }
 
   configs -= [ "//build/config/compiler:chromium_code" ]
   configs += [
     ":internal_config",
     ":commit_id_config",
     ":debug_annotations_config",
     ":libANGLE_config",
     "//build/config/compiler:no_chromium_code",
   ]
 
-  defines = [
-    "LIBEGL_IMPLEMENTATION",
-  ]
+  defines = [ "LIBEGL_IMPLEMENTATION" ]
 
   deps = [
     ":includes",
     ":libGLESv2",
   ]
 }
 
-util_gypi = exec_script(
-  "//build/gypi_to_gn.py",
-  [ rebase_path("util/util.gyp") ],
-  "scope",
-  [ "util/util.gyp" ])
+util_gypi = exec_script("//build/gypi_to_gn.py",
+                        [ rebase_path("util/util.gyp") ],
+                        "scope",
+                        [ "util/util.gyp" ])
+
+config("angle_util_config") {
+  include_dirs = [ "util" ]
+  if (is_linux) {
+    libs = [ "X11" ]
+  }
+}
 
 static_library("angle_util") {
   sources = rebase_path(util_gypi.util_sources, ".", "util")
 
   if (is_win) {
     sources += rebase_path(util_gypi.util_win32_sources, ".", "util")
   }
 
@@ -391,22 +391,21 @@ static_library("angle_util") {
     sources += rebase_path(util_gypi.util_x11_sources, ".", "util")
   }
 
   defines = [
     "GL_GLEXT_PROTOTYPES",
     "EGL_EGLEXT_PROTOTYPES",
   ]
 
-  configs += [
+  configs += [ ":debug_annotations_config" ]
+
+  public_configs = [
+    ":angle_util_config",
     ":internal_config",
-    ":debug_annotations_config",
-  ]
-
-  include_dirs = [
-    "util",
   ]
 
   deps = [
+    ":angle_common",
     ":libEGL",
     ":libGLESv2",
   ]
 }
--- a/gfx/angle/DEPS
+++ b/gfx/angle/DEPS
@@ -61,14 +61,48 @@ hooks = [
     'action': [ 'download_from_google_storage',
                 '--no_resume',
                 '--platform=linux*',
                 '--no_auth',
                 '--bucket', 'chromium-clang-format',
                 '-s', 'buildtools/linux64/clang-format.sha1',
     ],
   },
+  # Pull GN binaries using checked-in hashes.
+  {
+    'name': 'gn_win',
+    'pattern': '.',
+    'action': [ 'download_from_google_storage',
+                '--no_resume',
+                '--platform=win32',
+                '--no_auth',
+                '--bucket', 'chromium-gn',
+                '-s', 'buildtools/win/gn.exe.sha1',
+    ],
+  },
+  {
+    'name': 'gn_mac',
+    'pattern': '.',
+    'action': [ 'download_from_google_storage',
+                '--no_resume',
+                '--platform=darwin',
+                '--no_auth',
+                '--bucket', 'chromium-gn',
+                '-s', 'buildtools/mac/gn.sha1',
+    ],
+  },
+  {
+    'name': 'gn_linux64',
+    'pattern': '.',
+    'action': [ 'download_from_google_storage',
+                '--no_resume',
+                '--platform=linux*',
+                '--no_auth',
+                '--bucket', 'chromium-gn',
+                '-s', 'buildtools/linux64/gn.sha1',
+    ],
+  },
   {
     # A change to a .gyp, .gypi, or to GYP itself should run the generator.
     "pattern": ".",
     "action": ["python", "build/gyp_angle"],
   },
 ]
--- a/gfx/angle/README.md
+++ b/gfx/angle/README.md
@@ -34,10 +34,11 @@ View the [Dev setup instructions](doc/De
 * Become a [code contributor](doc/ContributingCode.md).
 * Refer to ANGLE's [coding standard](doc/CodingStandard.md).
 * Learn how to [build ANGLE for Chromium development](doc/BuildingAngleForChromiumDevelopment.md).
 * [Choose an ANGLE branch](doc/ChoosingANGLEBranch.md) to track in your own project.
 * File bugs in the [issue tracker](http://code.google.com/p/angleproject/issues/list) (preferably with an isolated test-case).
 * Read about WebGL on the [Khronos WebGL Wiki](http://khronos.org/webgl/wiki/Main_Page).
 * Learn about implementation details in the [OpenGL Insights chapter on ANGLE](http://www.seas.upenn.edu/~pcozzi/OpenGLInsights/OpenGLInsights-ANGLE.pdf) and this [ANGLE presentation](https://drive.google.com/file/d/0Bw29oYeC09QbbHoxNE5EUFh0RGs/view?usp=sharing).
 * Learn about the past, present, and future of the ANGLE implementation in [this recent presentation](https://docs.google.com/presentation/d/1CucIsdGVDmdTWRUbg68IxLE5jXwCb2y1E9YVhQo0thg/pub?start=false&loop=false).
+* Notes on [debugging ANGLE](doc/DebuggingTips.md).
 * If you use ANGLE in your own project, we'd love to hear about it!
 
--- a/gfx/angle/include/EGL/eglext.h
+++ b/gfx/angle/include/EGL/eglext.h
@@ -463,16 +463,21 @@ EGLAPI EGLBoolean EGLAPIENTRY eglQuerySu
 #define EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE ((EGLNativeDisplayType)-2)
 #define EGL_D3D11_ONLY_DISPLAY_ANGLE ((EGLNativeDisplayType)-3)
 #endif /* EGL_ANGLE_direct3d_display */
 
 #ifndef EGL_ANGLE_surface_d3d_texture_2d_share_handle
 #define EGL_ANGLE_surface_d3d_texture_2d_share_handle 1
 #endif /* EGL_ANGLE_surface_d3d_texture_2d_share_handle */
 
+#ifndef EGL_ANGLE_direct_composition
+#define EGL_ANGLE_direct_composition 1
+#define EGL_DIRECT_COMPOSITION_ANGLE 0x33A5
+#endif /* EGL_ANGLE_direct_composition */
+
 #ifndef EGL_ANGLE_platform_angle
 #define EGL_ANGLE_platform_angle 1
 #define EGL_PLATFORM_ANGLE_ANGLE          0x3202
 #define EGL_PLATFORM_ANGLE_TYPE_ANGLE     0x3203
 #define EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE 0x3204
 #define EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE 0x3205
 #define EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE 0x3206
 #endif /* EGL_ANGLE_platform_angle */
@@ -499,16 +504,36 @@ EGLAPI EGLBoolean EGLAPIENTRY eglQuerySu
 #define EGL_FIXED_SIZE_ANGLE              0x3201
 #endif /* EGL_ANGLE_window_fixed_size */
 
 #ifndef EGL_ANGLE_x11_visual
 #define EGL_ANGLE_x11_visual
 #define EGL_X11_VISUAL_ID_ANGLE 0x33A3
 #endif /* EGL_ANGLE_x11_visual */
 
+#ifndef EGL_ANGLE_flexible_surface_compatibility
+#define EGL_ANGLE_flexible_surface_compatibility 1
+#define EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE 0x33A6
+#endif /* EGL_ANGLE_flexible_surface_compatibility */
+
+#ifndef EGL_ANGLE_surface_orientation
+#define EGL_ANGLE_surface_orientation
+#define EGL_OPTIMAL_SURFACE_ORIENTATION_ANGLE 0x33A7
+#define EGL_SURFACE_ORIENTATION_ANGLE 0x33A8
+#define EGL_SURFACE_ORIENTATION_INVERT_X_ANGLE 0x0001
+#define EGL_SURFACE_ORIENTATION_INVERT_Y_ANGLE 0x0002
+#endif /* EGL_ANGLE_surface_orientation */
+
+#ifndef EGL_ANGLE_experimental_present_path
+#define EGL_ANGLE_experimental_present_path
+#define EGL_EXPERIMENTAL_PRESENT_PATH_ANGLE 0x33A4
+#define EGL_EXPERIMENTAL_PRESENT_PATH_FAST_ANGLE 0x33A9
+#define EGL_EXPERIMENTAL_PRESENT_PATH_COPY_ANGLE 0x33AA
+#endif /* EGL_ANGLE_experimental_present_path */
+
 #ifndef EGL_ARM_pixmap_multisample_discard
 #define EGL_ARM_pixmap_multisample_discard 1
 #define EGL_DISCARD_SAMPLES_ARM           0x3286
 #endif /* EGL_ARM_pixmap_multisample_discard */
 
 #ifndef EGL_EXT_buffer_age
 #define EGL_EXT_buffer_age 1
 #define EGL_BUFFER_AGE_EXT                0x313D
--- a/gfx/angle/include/GLES2/gl2ext.h
+++ b/gfx/angle/include/GLES2/gl2ext.h
@@ -2915,13 +2915,28 @@ GL_APICALL void GL_APIENTRY glEndTilingQ
 #define GL_WRITEONLY_RENDERING_QCOM       0x8823
 #endif /* GL_QCOM_writeonly_rendering */
 
 #ifndef GL_VIV_shader_binary
 #define GL_VIV_shader_binary 1
 #define GL_SHADER_BINARY_VIV              0x8FC4
 #endif /* GL_VIV_shader_binary */
 
+#ifndef GL_ANGLE_lossy_etc_decode
+#define GL_ANGLE_lossy_etc_decode 1
+#define GL_ETC1_RGB8_LOSSY_DECODE_ANGLE                                  0x9690
+#define GL_COMPRESSED_R11_LOSSY_DECODE_EAC_ANGLE                         0x9691
+#define GL_COMPRESSED_SIGNED_R11_LOSSY_DECODE_EAC_ANGLE                  0x9692
+#define GL_COMPRESSED_RG11_LOSSY_DECODE_EAC_ANGLE                        0x9693
+#define GL_COMPRESSED_SIGNED_RG11_LOSSY_DECODE_EAC_ANGLE                 0x9694
+#define GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE                       0x9695
+#define GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE                      0x9696
+#define GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE   0x9697
+#define GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE  0x9698
+#define GL_COMPRESSED_RGBA8_LOSSY_DECODE_ETC2_EAC_ANGLE                  0x9699
+#define GL_COMPRESSED_SRGB8_ALPHA8_LOSSY_DECODE_ETC2_EAC_ANGLE           0x969A
+#endif /* GL_ANGLE_lossy_etc_decode */
+
 #ifdef __cplusplus
 }
 #endif
 
 #endif
--- a/gfx/angle/include/GLSLANG/ShaderLang.h
+++ b/gfx/angle/include/GLSLANG/ShaderLang.h
@@ -43,17 +43,17 @@ typedef unsigned int GLenum;
 }
 
 // Must be included after GLenum proxy typedef
 // Note: make sure to increment ANGLE_SH_VERSION when changing ShaderVars.h
 #include "ShaderVars.h"
 
 // Version number for shader translation API.
 // It is incremented every time the API changes.
-#define ANGLE_SH_VERSION 140
+#define ANGLE_SH_VERSION 143
 
 typedef enum {
   SH_GLES2_SPEC = 0x8B40,
   SH_WEBGL_SPEC = 0x8B41,
 
   SH_GLES3_SPEC = 0x8B86,
   SH_WEBGL2_SPEC = 0x8B87,
 
@@ -75,40 +75,45 @@ typedef enum {
   // This new main function will call the css_main function.
   // It may also perform additional operations like varying assignment, texture
   // access, and gl_FragColor assignment in order to implement the CSS Shaders
   // blend modes.
   //
   SH_CSS_SHADERS_SPEC = 0x8B42
 } ShShaderSpec;
 
-typedef enum {
-  SH_ESSL_OUTPUT               = 0x8B45,
-  // SH_GLSL_OUTPUT is deprecated. This is to not break the build.
-  SH_GLSL_OUTPUT               = 0x8B46,
-  SH_GLSL_COMPATIBILITY_OUTPUT = 0x8B46,
-  // SH_GLSL_CORE_OUTPUT is deprecated.
-  SH_GLSL_CORE_OUTPUT          = 0x8B47,
-  //Note: GL introduced core profiles in 1.5. However, for compatiblity with Chromium, we treat SH_GLSL_CORE_OUTPUT as GLSL_130_OUTPUT.
-  //TODO: Remove SH_GLSL_CORE_OUTPUT
-  SH_GLSL_130_OUTPUT           = 0x8B47,
-  SH_GLSL_140_OUTPUT           = 0x8B80,
-  SH_GLSL_150_CORE_OUTPUT      = 0x8B81,
-  SH_GLSL_330_CORE_OUTPUT      = 0x8B82,
-  SH_GLSL_400_CORE_OUTPUT      = 0x8B83,
-  SH_GLSL_410_CORE_OUTPUT      = 0x8B84,
-  SH_GLSL_420_CORE_OUTPUT      = 0x8B85,
-  SH_GLSL_430_CORE_OUTPUT      = 0x8B86,
-  SH_GLSL_440_CORE_OUTPUT      = 0x8B87,
-  SH_GLSL_450_CORE_OUTPUT      = 0x8B88,
+typedef enum
+{
+    // ESSL output only supported in some configurations.
+    SH_ESSL_OUTPUT = 0x8B45,
 
-  // HLSL output only supported in some configurations.
-  SH_HLSL_OUTPUT   = 0x8B48,
-  SH_HLSL9_OUTPUT  = 0x8B48,
-  SH_HLSL11_OUTPUT = 0x8B49
+    // GLSL output only supported in some configurations.
+    SH_GLSL_COMPATIBILITY_OUTPUT = 0x8B46,
+    // Note: GL introduced core profiles in 1.5.
+    SH_GLSL_130_OUTPUT      = 0x8B47,
+    SH_GLSL_140_OUTPUT      = 0x8B80,
+    SH_GLSL_150_CORE_OUTPUT = 0x8B81,
+    SH_GLSL_330_CORE_OUTPUT = 0x8B82,
+    SH_GLSL_400_CORE_OUTPUT = 0x8B83,
+    SH_GLSL_410_CORE_OUTPUT = 0x8B84,
+    SH_GLSL_420_CORE_OUTPUT = 0x8B85,
+    SH_GLSL_430_CORE_OUTPUT = 0x8B86,
+    SH_GLSL_440_CORE_OUTPUT = 0x8B87,
+    SH_GLSL_450_CORE_OUTPUT = 0x8B88,
+
+    // HLSL output only supported in some configurations.
+    // Deprecated:
+    SH_HLSL_OUTPUT   = 0x8B48,
+    SH_HLSL9_OUTPUT  = 0x8B48,
+    SH_HLSL11_OUTPUT = 0x8B49,
+
+    // Prefer using these to specify HLSL output type:
+    SH_HLSL_3_0_OUTPUT       = 0x8B48,  // D3D 9
+    SH_HLSL_4_1_OUTPUT       = 0x8B49,  // D3D 11
+    SH_HLSL_4_0_FL9_3_OUTPUT = 0x8B4A   // D3D 11 feature level 9_3
 } ShShaderOutput;
 
 // Compile options.
 typedef enum {
   SH_VALIDATE                = 0,
   SH_VALIDATE_LOOP_INDEXING  = 0x0001,
   SH_INTERMEDIATE_TREE       = 0x0002,
   SH_OBJECT_CODE             = 0x0004,
@@ -329,19 +334,19 @@ COMPILER_EXPORT const std::string &ShGet
 // Driver calls these to create and destroy compiler objects.
 //
 // Returns the handle of constructed compiler, null if the requested compiler is
 // not supported.
 // Parameters:
 // type: Specifies the type of shader - GL_FRAGMENT_SHADER or GL_VERTEX_SHADER.
 // spec: Specifies the language spec the compiler must conform to -
 //       SH_GLES2_SPEC or SH_WEBGL_SPEC.
-// output: Specifies the output code type - SH_ESSL_OUTPUT, SH_GLSL_OUTPUT,
-//         SH_HLSL9_OUTPUT or SH_HLSL11_OUTPUT. Note: HLSL output is only
-//         supported in some configurations.
+// output: Specifies the output code type - for example SH_ESSL_OUTPUT, SH_GLSL_OUTPUT,
+//         SH_HLSL_3_0_OUTPUT or SH_HLSL_4_1_OUTPUT. Note: Each output type may only
+//         be supported in some configurations.
 // resources: Specifies the built-in resources.
 COMPILER_EXPORT ShHandle ShConstructCompiler(
     sh::GLenum type,
     ShShaderSpec spec,
     ShShaderOutput output,
     const ShBuiltInResources *resources);
 COMPILER_EXPORT void ShDestruct(ShHandle handle);
 
--- a/gfx/angle/include/GLSLANG/ShaderVars.h
+++ b/gfx/angle/include/GLSLANG/ShaderVars.h
@@ -195,21 +195,24 @@ struct COMPILER_EXPORT Varying : public 
 
 struct COMPILER_EXPORT InterfaceBlock
 {
     InterfaceBlock();
     ~InterfaceBlock();
     InterfaceBlock(const InterfaceBlock &other);
     InterfaceBlock &operator=(const InterfaceBlock &other);
 
+    // Fields from blocks with non-empty instance names are prefixed with the block name.
+    std::string fieldPrefix() const;
+
     std::string name;
     std::string mappedName;
     std::string instanceName;
     unsigned int arraySize;
     BlockLayoutType layout;
     bool isRowMajorLayout;
     bool staticUse;
     std::vector<InterfaceBlockField> fields;
 };
 
-}
+}  // namespace sh
 
 #endif // GLSLANG_SHADERVARS_H_
--- a/gfx/angle/moz.build
+++ b/gfx/angle/moz.build
@@ -103,34 +103,35 @@ UNIFIED_SOURCES += [
     'src/compiler/translator/VersionGLSL.cpp',
     'src/third_party/compiler/ArrayBoundsClamper.cpp',
 ]
 SOURCES += [
     'src/compiler/translator/glslang_lex.cpp',
     'src/compiler/translator/glslang_tab.cpp',
 ]
 
-if CONFIG['GNU_CXX'] or CONFIG['CLANG_CL']:
+
+if CONFIG['GNU_CXX']:
     CXXFLAGS += [
         '-Wno-attributes',
         '-Wno-shadow',
         '-Wno-sign-compare',
         '-Wno-unknown-pragmas',
         '-Wno-unreachable-code',
     ]
-if CONFIG['GNU_CXX'] and not CONFIG['CLANG_CXX'] and not CONFIG['CLANG_CL']:
-    CXXFLAGS += [
-        '-Wno-shadow-compatible-local',
-        '-Wno-shadow-local',
-    ]
-if CONFIG['CLANG_CXX'] or CONFIG['CLANG_CL']:
-    CXXFLAGS += [
-        '-Wno-inconsistent-missing-override',
-        '-Wno-unused-private-field',
-    ]
+    if CONFIG['CLANG_CXX']:
+        CXXFLAGS += [
+            '-Wno-inconsistent-missing-override',
+            '-Wno-unused-private-field',
+        ]
+    else:
+        CXXFLAGS += [
+            '-Wno-shadow-compatible-local',
+            '-Wno-shadow-local',
+        ]
 
 if CONFIG['MOZ_DIRECTX_SDK_PATH'] and not CONFIG['MOZ_HAS_WINSDK_WITH_D3D']:
     LOCAL_INCLUDES += ['%' + '%s/include/' % CONFIG['MOZ_DIRECTX_SDK_PATH']]
 
 DEFINES['_CRT_SECURE_NO_DEPRECATE'] = True
 DEFINES['_HAS_EXCEPTIONS'] = 0
 
 if not CONFIG['MOZ_DEBUG']:
@@ -149,16 +150,18 @@ DEFINES['GL_GLEXT_PROTOTYPES'] = ""
 DEFINES['EGLAPI'] = ""
 
 
 # Only build libEGL/libGLESv2 on Windows
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
     DIRS += [ 'src/libANGLE', 'src/libGLESv2', 'src/libEGL' ]
 
 DEFINES['ANGLE_ENABLE_HLSL'] = "1"
+DEFINES['ANGLE_ENABLE_GLSL'] = "1"
+DEFINES['ANGLE_ENABLE_ESSL'] = "1"
 DEFINES['ANGLE_ENABLE_KEYEDMUTEX'] = "1"
 
 EXPORTS.angle += [ 'include/GLSLANG/ShaderLang.h', 'include/GLSLANG/ShaderVars.h' ]
 EXPORTS.angle.KHR += [ 'include/KHR/khrplatform.h' ]
 
 LOCAL_INCLUDES += [ 'include', 'src' ]
 
 # We allow warnings for third-party code that can be updated from upstream.
--- a/gfx/angle/src/angle.gyp
+++ b/gfx/angle/src/angle.gyp
@@ -11,16 +11,18 @@
         'angle_id_script_base': 'commit_id.py',
         'angle_id_script': '<(angle_gen_path)/<(angle_id_script_base)',
         'angle_id_header_base': 'commit.h',
         'angle_id_header': '<(angle_gen_path)/id/<(angle_id_header_base)',
         'angle_use_commit_id%': '<!(python <(angle_id_script_base) check ..)',
         'angle_enable_d3d9%': 0,
         'angle_enable_d3d11%': 0,
         'angle_enable_gl%': 0,
+        'angle_enable_essl%': 1, # Enable this for all configs by default
+        'angle_enable_glsl%': 1, # Enable this for all configs by default
         'angle_enable_hlsl%': 0,
         'angle_link_glx%': 0,
         'angle_gl_library_type%': 'shared_library',
         'conditions':
         [
             ['OS=="win"',
             {
                 'angle_enable_gl%': 1,
--- a/gfx/angle/src/commit.h
+++ b/gfx/angle/src/commit.h
@@ -1,3 +1,3 @@
-#define ANGLE_COMMIT_HASH "d00f803db3a2"
+#define ANGLE_COMMIT_HASH "f1101625dbbe"
 #define ANGLE_COMMIT_HASH_SIZE 12
-#define ANGLE_COMMIT_DATE "2015-12-15 23:09:49 -0500"
+#define ANGLE_COMMIT_DATE "2016-02-24 21:04:03 -0500"
--- a/gfx/angle/src/common/BitSetIterator_unittest.cpp
+++ b/gfx/angle/src/common/BitSetIterator_unittest.cpp
@@ -50,17 +50,17 @@ TEST_F(BitSetIteratorTest, Iterator)
 TEST_F(BitSetIteratorTest, EmptySet)
 {
     // We don't use the FAIL gtest macro here since it returns immediately,
     // causing an unreachable code warning in MSVS
     bool sawBit = false;
     for (unsigned long bit : IterateBitSet(mStateBits))
     {
         sawBit = true;
-        UNUSED_TRACE_VARIABLE(bit);
+        UNUSED_VARIABLE(bit);
     }
     EXPECT_FALSE(sawBit);
 }
 
 // Test iterating a result of combining two bitsets.
 TEST_F(BitSetIteratorTest, NonLValueBitset)
 {
     std::bitset<40> otherBits;
--- a/gfx/angle/src/common/Optional.h
+++ b/gfx/angle/src/common/Optional.h
@@ -37,16 +37,23 @@ struct Optional
 
     Optional &operator=(const T &value)
     {
         mValue = value;
         mValid = true;
         return *this;
     }
 
+    Optional &operator=(T &&value)
+    {
+        mValue = std::move(value);
+        mValid = true;
+        return *this;
+    }
+
     void reset()
     {
         mValid = false;
     }
 
     static Optional Invalid() { return Optional(); }
 
     bool valid() const { return mValid; }
--- a/gfx/angle/src/common/angleutils.cpp
+++ b/gfx/angle/src/common/angleutils.cpp
@@ -3,18 +3,25 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 //
 
 #include "common/angleutils.h"
 #include "common/debug.h"
 
 #include <stdio.h>
+
+#include <limits>
 #include <vector>
 
+namespace angle
+{
+const uintptr_t DirtyPointer = std::numeric_limits<uintptr_t>::max();
+}
+
 size_t FormatStringIntoVector(const char *fmt, va_list vararg, std::vector<char>& outBuffer)
 {
     // Attempt to just print to the current buffer
     int len = vsnprintf(&(outBuffer.front()), outBuffer.size(), fmt, vararg);
     if (len < 0 || static_cast<size_t>(len) >= outBuffer.size())
     {
         // Buffer was not large enough, calculate the required size and resize the buffer
         len = vsnprintf(NULL, 0, fmt, vararg);
--- a/gfx/angle/src/common/angleutils.h
+++ b/gfx/angle/src/common/angleutils.h
@@ -28,16 +28,17 @@ class NonCopyable
   public:
     NonCopyable() = default;
     ~NonCopyable() = default;
   protected:
     NonCopyable(const NonCopyable&) = delete;
     void operator=(const NonCopyable&) = delete;
 };
 
+extern const uintptr_t DirtyPointer;
 }
 
 template <typename T, size_t N>
 inline size_t ArraySize(T(&)[N])
 {
     return N;
 }
 
--- a/gfx/angle/src/common/debug.cpp
+++ b/gfx/angle/src/common/debug.cpp
@@ -48,17 +48,17 @@ void output(bool traceInDebugOnly, Messa
             break;
           case DebugTraceOutputTypeSetMarker:
             g_debugAnnotator->setMarker(formattedWideMessage.c_str());
             break;
         }
     }
 
     std::string formattedMessage;
-    UNUSED_TRACE_VARIABLE(formattedMessage);
+    UNUSED_VARIABLE(formattedMessage);
 
 #if !defined(NDEBUG) && defined(_MSC_VER)
     if (messageType == MESSAGE_ERR)
     {
         if (formattedMessage.empty())
         {
             formattedMessage = FormatString(format, vararg);
         }
--- a/gfx/angle/src/common/debug.h
+++ b/gfx/angle/src/common/debug.h
@@ -11,17 +11,17 @@
 
 #include <assert.h>
 #include <stdio.h>
 #include <string>
 
 #include "common/angleutils.h"
 
 #if !defined(TRACE_OUTPUT_FILE)
-#define TRACE_OUTPUT_FILE "debug.txt"
+#define TRACE_OUTPUT_FILE "angle_debug.txt"
 #endif
 
 namespace gl
 {
 
 enum MessageType
 {
     MESSAGE_TRACE,
@@ -86,17 +86,17 @@ bool DebugAnnotationsActive();
 #define ERR(message, ...) (void(0))
 #endif
 
 // A macro to log a performance event around a scope.
 #if defined(ANGLE_TRACE_ENABLED)
 #if defined(_MSC_VER)
 #define EVENT(message, ...) gl::ScopedPerfEventHelper scopedPerfEventHelper ## __LINE__("%s" message "\n", __FUNCTION__, __VA_ARGS__);
 #else
-#define EVENT(message, ...) gl::ScopedPerfEventHelper scopedPerfEventHelper(message "\n", ##__VA_ARGS__);
+#define EVENT(message, ...) gl::ScopedPerfEventHelper scopedPerfEventHelper("%s" message "\n", __FUNCTION__, ##__VA_ARGS__);
 #endif // _MSC_VER
 #else
 #define EVENT(message, ...) (void(0))
 #endif
 
 #if defined(ANGLE_TRACE_ENABLED)
 #undef ANGLE_TRACE_ENABLED
 #endif
@@ -109,21 +109,17 @@ bool DebugAnnotationsActive();
         assert(expression); \
     } ANGLE_EMPTY_STATEMENT
 #define UNUSED_ASSERTION_VARIABLE(variable)
 #else
 #define ASSERT(expression) (void(0))
 #define UNUSED_ASSERTION_VARIABLE(variable) ((void)variable)
 #endif
 
-#ifndef ANGLE_ENABLE_DEBUG_TRACE
-#define UNUSED_TRACE_VARIABLE(variable) ((void)variable)
-#else
-#define UNUSED_TRACE_VARIABLE(variable)
-#endif
+#define UNUSED_VARIABLE(variable) ((void)variable)
 
 // A macro to indicate unimplemented functionality
 
 #if defined (ANGLE_TEST_CONFIG)
 #define NOASSERT_UNIMPLEMENTED 1
 #endif
 
 // Define NOASSERT_UNIMPLEMENTED to non zero to skip the assert fail in the unimplemented checks
--- a/gfx/angle/src/common/mathutil.h
+++ b/gfx/angle/src/common/mathutil.h
@@ -488,19 +488,20 @@ inline signed short average(signed short
     return ((int)a + (int)b) / 2;
 }
 
 inline unsigned int average(unsigned int a, unsigned int b)
 {
     return ((a ^ b) >> 1) + (a & b);
 }
 
-inline signed int average(signed int a, signed int b)
+inline int average(int a, int b)
 {
-    return ((long long)a + (long long)b) / 2;
+    long long average = (static_cast<long long>(a) + static_cast<long long>(b)) / 2ll;
+    return static_cast<int>(average);
 }
 
 inline float average(float a, float b)
 {
     return (a + b) * 0.5f;
 }
 
 inline unsigned short averageHalfFloat(unsigned short a, unsigned short b)
@@ -579,19 +580,20 @@ struct IndexRange
 // First, both normalized floating-point values are converted into 16-bit integer values.
 // Then, the results are packed into the returned 32-bit unsigned integer.
 // The first float value will be written to the least significant bits of the output;
 // the last float value will be written to the most significant bits.
 // The conversion of each value to fixed point is done as follows :
 // packSnorm2x16 : round(clamp(c, -1, +1) * 32767.0)
 inline uint32_t packSnorm2x16(float f1, float f2)
 {
-    uint16_t leastSignificantBits = static_cast<uint16_t>(roundf(clamp(f1, -1.0f, 1.0f) * 32767.0f));
-    uint16_t mostSignificantBits = static_cast<uint16_t>(roundf(clamp(f2, -1.0f, 1.0f) * 32767.0f));
-    return static_cast<uint32_t>(mostSignificantBits) << 16 | static_cast<uint32_t>(leastSignificantBits);
+    int16_t leastSignificantBits = static_cast<int16_t>(roundf(clamp(f1, -1.0f, 1.0f) * 32767.0f));
+    int16_t mostSignificantBits = static_cast<int16_t>(roundf(clamp(f2, -1.0f, 1.0f) * 32767.0f));
+    return static_cast<uint32_t>(mostSignificantBits) << 16 |
+           (static_cast<uint32_t>(leastSignificantBits) & 0xFFFF);
 }
 
 // First, unpacks a single 32-bit unsigned integer u into a pair of 16-bit unsigned integers. Then, each
 // component is converted to a normalized floating-point value to generate the returned two float values.
 // The first float value will be extracted from the least significant bits of the input;
 // the last float value will be extracted from the most-significant bits.
 // The conversion for unpacked fixed-point value to floating point is done as follows:
 // unpackSnorm2x16 : clamp(f / 32767.0, -1, +1)
--- a/gfx/angle/src/compiler.gypi
+++ b/gfx/angle/src/compiler.gypi
@@ -20,36 +20,32 @@
             '../include/GLES3/gl32.h',
             '../include/GLSLANG/ShaderLang.h',
             '../include/GLSLANG/ShaderVars.h',
             '../include/KHR/khrplatform.h',
             '../include/angle_gl.h',
             'compiler/translator/BaseTypes.h',
             'compiler/translator/BuiltInFunctionEmulator.cpp',
             'compiler/translator/BuiltInFunctionEmulator.h',
-            'compiler/translator/BuiltInFunctionEmulatorGLSL.cpp',
-            'compiler/translator/BuiltInFunctionEmulatorGLSL.h',
             'compiler/translator/Cache.cpp',
             'compiler/translator/Cache.h',
             'compiler/translator/CallDAG.cpp',
             'compiler/translator/CallDAG.h',
             'compiler/translator/CodeGen.cpp',
             'compiler/translator/Common.h',
             'compiler/translator/Compiler.cpp',
             'compiler/translator/Compiler.h',
             'compiler/translator/ConstantUnion.h',
             'compiler/translator/Diagnostics.cpp',
             'compiler/translator/Diagnostics.h',
             'compiler/translator/DirectiveHandler.cpp',
             'compiler/translator/DirectiveHandler.h',
             'compiler/translator/EmulatePrecision.cpp',
             'compiler/translator/EmulatePrecision.h',
             'compiler/translator/ExtensionBehavior.h',
-            'compiler/translator/ExtensionGLSL.cpp',
-            'compiler/translator/ExtensionGLSL.h',
             'compiler/translator/FlagStd140Structs.cpp',
             'compiler/translator/FlagStd140Structs.h',
             'compiler/translator/ForLoopUnroll.cpp',
             'compiler/translator/ForLoopUnroll.h',
             'compiler/translator/HashNames.h',
             'compiler/translator/InfoSink.cpp',
             'compiler/translator/InfoSink.h',
             'compiler/translator/Initialize.cpp',
@@ -67,22 +63,16 @@
             'compiler/translator/Intermediate.h',
             'compiler/translator/Intermediate.cpp',
             'compiler/translator/LoopInfo.cpp',
             'compiler/translator/LoopInfo.h',
             'compiler/translator/MMap.h',
             'compiler/translator/NodeSearch.h',
             'compiler/translator/Operator.cpp',
             'compiler/translator/Operator.h',
-            'compiler/translator/OutputESSL.cpp',
-            'compiler/translator/OutputESSL.h',
-            'compiler/translator/OutputGLSL.cpp',
-            'compiler/translator/OutputGLSL.h',
-            'compiler/translator/OutputGLSLBase.cpp',
-            'compiler/translator/OutputGLSLBase.h',
             'compiler/translator/ParseContext.cpp',
             'compiler/translator/ParseContext.h',
             'compiler/translator/PoolAlloc.cpp',
             'compiler/translator/PoolAlloc.h',
             'compiler/translator/Pragma.h',
             'compiler/translator/PruneEmptyDeclarations.cpp',
             'compiler/translator/PruneEmptyDeclarations.h',
             'compiler/translator/RecordConstantPrecision.cpp',
@@ -95,38 +85,32 @@
             'compiler/translator/RewriteDoWhile.h',
             'compiler/translator/RenameFunction.h',
             'compiler/translator/ScalarizeVecAndMatConstructorArgs.cpp',
             'compiler/translator/ScalarizeVecAndMatConstructorArgs.h',
             'compiler/translator/SearchSymbol.cpp',
             'compiler/translator/SearchSymbol.h',
             'compiler/translator/SymbolTable.cpp',
             'compiler/translator/SymbolTable.h',
-            'compiler/translator/TranslatorESSL.cpp',
-            'compiler/translator/TranslatorESSL.h',
-            'compiler/translator/TranslatorGLSL.cpp',
-            'compiler/translator/TranslatorGLSL.h',
             'compiler/translator/Types.cpp',
             'compiler/translator/Types.h',
             'compiler/translator/UnfoldShortCircuitAST.cpp',
             'compiler/translator/UnfoldShortCircuitAST.h',
             'compiler/translator/ValidateGlobalInitializer.cpp',
             'compiler/translator/ValidateGlobalInitializer.h',
             'compiler/translator/ValidateLimitations.cpp',
             'compiler/translator/ValidateLimitations.h',
             'compiler/translator/ValidateOutputs.cpp',
             'compiler/translator/ValidateOutputs.h',
             'compiler/translator/ValidateSwitch.cpp',
             'compiler/translator/ValidateSwitch.h',
             'compiler/translator/VariableInfo.cpp',
             'compiler/translator/VariableInfo.h',
             'compiler/translator/VariablePacker.cpp',
             'compiler/translator/VariablePacker.h',
-            'compiler/translator/VersionGLSL.cpp',
-            'compiler/translator/VersionGLSL.h',
             'compiler/translator/blocklayout.cpp',
             'compiler/translator/blocklayout.h',
             'compiler/translator/depgraph/DependencyGraph.cpp',
             'compiler/translator/depgraph/DependencyGraph.h',
             'compiler/translator/depgraph/DependencyGraphBuilder.cpp',
             'compiler/translator/depgraph/DependencyGraphBuilder.h',
             'compiler/translator/depgraph/DependencyGraphOutput.cpp',
             'compiler/translator/depgraph/DependencyGraphOutput.h',
@@ -143,16 +127,38 @@
             'compiler/translator/timing/RestrictFragmentShaderTiming.h',
             'compiler/translator/timing/RestrictVertexShaderTiming.cpp',
             'compiler/translator/timing/RestrictVertexShaderTiming.h',
             'compiler/translator/util.cpp',
             'compiler/translator/util.h',
             'third_party/compiler/ArrayBoundsClamper.cpp',
             'third_party/compiler/ArrayBoundsClamper.h',
         ],
+        'angle_translator_lib_essl_sources':
+        [
+            'compiler/translator/OutputESSL.cpp',
+            'compiler/translator/OutputESSL.h',
+            'compiler/translator/TranslatorESSL.cpp',
+            'compiler/translator/TranslatorESSL.h',
+        ],
+        'angle_translator_lib_glsl_sources':
+        [
+            'compiler/translator/BuiltInFunctionEmulatorGLSL.cpp',
+            'compiler/translator/BuiltInFunctionEmulatorGLSL.h',
+            'compiler/translator/ExtensionGLSL.cpp',
+            'compiler/translator/ExtensionGLSL.h',
+            'compiler/translator/OutputGLSL.cpp',
+            'compiler/translator/OutputGLSL.h',
+            'compiler/translator/OutputGLSLBase.cpp',
+            'compiler/translator/OutputGLSLBase.h',
+            'compiler/translator/TranslatorGLSL.cpp',
+            'compiler/translator/TranslatorGLSL.h',
+            'compiler/translator/VersionGLSL.cpp',
+            'compiler/translator/VersionGLSL.h',
+        ],
         'angle_translator_lib_hlsl_sources':
         [
             'compiler/translator/ArrayReturnValueToOutParameter.cpp',
             'compiler/translator/ArrayReturnValueToOutParameter.h',
             'compiler/translator/ASTMetadataHLSL.cpp',
             'compiler/translator/ASTMetadataHLSL.h',
             'compiler/translator/blocklayoutHLSL.cpp',
             'compiler/translator/blocklayoutHLSL.h',
@@ -248,16 +254,52 @@
             {
               'VCLibrarianTool':
               {
                 'AdditionalOptions': ['/ignore:4221']
               },
             },
             'conditions':
             [
+                ['angle_enable_essl==1',
+                {
+                    'defines':
+                    [
+                        'ANGLE_ENABLE_ESSL',
+                    ],
+                    'direct_dependent_settings':
+                    {
+                        'defines':
+                        [
+                            'ANGLE_ENABLE_ESSL',
+                        ],
+                    },
+                    'sources':
+                    [
+                        '<@(angle_translator_lib_essl_sources)',
+                    ],
+                }],
+                ['angle_enable_glsl==1',
+                {
+                    'defines':
+                    [
+                        'ANGLE_ENABLE_GLSL',
+                    ],
+                    'direct_dependent_settings':
+                    {
+                        'defines':
+                        [
+                            'ANGLE_ENABLE_GLSL',
+                        ],
+                    },
+                    'sources':
+                    [
+                        '<@(angle_translator_lib_glsl_sources)',
+                    ],
+                }],
                 ['angle_enable_hlsl==1',
                 {
                     'defines':
                     [
                         'ANGLE_ENABLE_HLSL',
                     ],
                     'direct_dependent_settings':
                     {
--- a/gfx/angle/src/compiler/translator/CallDAG.cpp
+++ b/gfx/angle/src/compiler/translator/CallDAG.cpp
@@ -30,16 +30,17 @@ class CallDAG::CallDAGCreator : public T
         for (auto &it : mFunctions)
         {
             // Skip unimplemented functions
             if (it.second.node)
             {
                 InitResult result = assignIndicesInternal(&it.second);
                 if (result != INITDAG_SUCCESS)
                 {
+                    *mCreationInfo << "\n";
                     return result;
                 }
             }
             else
             {
                 skipped++;
             }
         }
@@ -102,17 +103,18 @@ class CallDAG::CallDAGCreator : public T
     bool visitAggregate(Visit visit, TIntermAggregate *node) override
     {
         switch (node->getOp())
         {
           case EOpPrototype:
             if (visit == PreVisit)
             {
                 // Function declaration, create an empty record.
-                mFunctions[node->getName()];
+                auto& record = mFunctions[node->getName()];
+                record.name = node->getName();
             }
             break;
           case EOpFunction:
             {
                 // Function definition, create the record if need be and remember the node.
                 if (visit == PreVisit)
                 {
                     auto it = mFunctions.find(node->getName());
@@ -164,51 +166,48 @@ class CallDAG::CallDAGCreator : public T
 
     // Recursively assigns indices to a sub DAG
     InitResult assignIndicesInternal(CreatorFunctionData *function)
     {
         ASSERT(function);
 
         if (!function->node)
         {
-            *mCreationInfo << "Undefined function: " << function->name;
+            *mCreationInfo << "Undefined function '" << function->name
+                           << ")' used in the following call chain:";
             return INITDAG_UNDEFINED;
         }
 
         if (function->indexAssigned)
         {
             return INITDAG_SUCCESS;
         }
 
         if (function->visiting)
         {
             if (mCreationInfo)
             {
-                *mCreationInfo << "Recursive function call in the following call chain: " << function->name;
+                *mCreationInfo << "Recursive function call in the following call chain:" << function->name;
             }
             return INITDAG_RECURSION;
         }
         function->visiting = true;
 
         for (auto &callee : function->callees)
         {
             InitResult result = assignIndicesInternal(callee);
-            if (result == INITDAG_RECURSION)
+            if (result != INITDAG_SUCCESS)
             {
-                // We know that there is a recursive function call chain in the AST,
+                // We know that there is an issue with the call chain in the AST,
                 // print the link of the chain we were processing.
                 if (mCreationInfo)
                 {
-                    *mCreationInfo << " <- " << function->name;
+                    *mCreationInfo << " <- " << function->name << ")";
                 }
-                return INITDAG_RECURSION;
-            }
-            else if (result == INITDAG_UNDEFINED)
-            {
-                return INITDAG_UNDEFINED;
+                return result;
             }
         }
 
         function->index = mCurrentIndex++;
         function->indexAssigned = true;
 
         function->visiting = false;
         return INITDAG_SUCCESS;
--- a/gfx/angle/src/compiler/translator/CodeGen.cpp
+++ b/gfx/angle/src/compiler/translator/CodeGen.cpp
@@ -1,55 +1,74 @@
 //
 // Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 //
 
+#ifdef ANGLE_ENABLE_ESSL
 #include "compiler/translator/TranslatorESSL.h"
+#endif
+
+#ifdef ANGLE_ENABLE_GLSL
 #include "compiler/translator/TranslatorGLSL.h"
+#endif
+
 #ifdef ANGLE_ENABLE_HLSL
 #include "compiler/translator/TranslatorHLSL.h"
 #endif // ANGLE_ENABLE_HLSL
 
 //
 // This function must be provided to create the actual
 // compile object used by higher level code.  It returns
 // a subclass of TCompiler.
 //
 TCompiler* ConstructCompiler(
     sh::GLenum type, ShShaderSpec spec, ShShaderOutput output)
 {
     switch (output) {
       case SH_ESSL_OUTPUT:
+#ifdef ANGLE_ENABLE_ESSL
         return new TranslatorESSL(type, spec);
+#else
+        // This compiler is not supported in this
+        // configuration. Return NULL per the ShConstructCompiler API.
+        return nullptr;
+#endif // ANGLE_ENABLE_ESSL
       case SH_GLSL_130_OUTPUT:
       case SH_GLSL_140_OUTPUT:
       case SH_GLSL_150_CORE_OUTPUT:
       case SH_GLSL_330_CORE_OUTPUT:
       case SH_GLSL_400_CORE_OUTPUT:
       case SH_GLSL_410_CORE_OUTPUT:
       case SH_GLSL_420_CORE_OUTPUT:
       case SH_GLSL_430_CORE_OUTPUT:
       case SH_GLSL_440_CORE_OUTPUT:
       case SH_GLSL_450_CORE_OUTPUT:
       case SH_GLSL_COMPATIBILITY_OUTPUT:
+#ifdef ANGLE_ENABLE_GLSL
         return new TranslatorGLSL(type, spec, output);
-      case SH_HLSL9_OUTPUT:
-      case SH_HLSL11_OUTPUT:
+#else
+        // This compiler is not supported in this
+        // configuration. Return NULL per the ShConstructCompiler API.
+        return nullptr;
+#endif // ANGLE_ENABLE_GLSL
+      case SH_HLSL_3_0_OUTPUT:
+      case SH_HLSL_4_1_OUTPUT:
+      case SH_HLSL_4_0_FL9_3_OUTPUT:
 #ifdef ANGLE_ENABLE_HLSL
         return new TranslatorHLSL(type, spec, output);
 #else
         // This compiler is not supported in this
         // configuration. Return NULL per the ShConstructCompiler API.
-        return NULL;
+        return nullptr;
 #endif // ANGLE_ENABLE_HLSL
       default:
         // Unknown format. Return NULL per the ShConstructCompiler API.
-        return NULL;
+        return nullptr;
     }
 }
 
 //
 // Delete the compiler made by ConstructCompiler
 //
 void DeleteCompiler(TCompiler* compiler)
 {
--- a/gfx/angle/src/compiler/translator/Common.h
+++ b/gfx/angle/src/compiler/translator/Common.h
@@ -55,28 +55,31 @@ inline TString* NewPoolTString(const cha
 // across compiles.
 //
 #define TPersistString std::string
 #define TPersistStringStream std::ostringstream
 
 //
 // Pool allocator versions of vectors, lists, and maps
 //
-template <class T> class TVector : public std::vector<T, pool_allocator<T> > {
-public:
-    typedef typename std::vector<T, pool_allocator<T> >::size_type size_type;
-    TVector() : std::vector<T, pool_allocator<T> >() {}
-    TVector(const pool_allocator<T>& a) : std::vector<T, pool_allocator<T> >(a) {}
-    TVector(size_type i): std::vector<T, pool_allocator<T> >(i) {}
+template <class T>
+class TVector : public std::vector<T, pool_allocator<T>>
+{
+  public:
+    typedef typename std::vector<T, pool_allocator<T>>::size_type size_type;
+    TVector() : std::vector<T, pool_allocator<T>>() {}
+    TVector(const pool_allocator<T> &a) : std::vector<T, pool_allocator<T>>(a) {}
+    TVector(size_type i) : std::vector<T, pool_allocator<T>>(i) {}
 };
 
-template <class K, class D, class CMP = std::less<K> > 
-class TMap : public std::map<K, D, CMP, pool_allocator<std::pair<const K, D> > > {
-public:
-    typedef pool_allocator<std::pair<const K, D> > tAllocator;
+template <class K, class D, class CMP = std::less<K>>
+class TMap : public std::map<K, D, CMP, pool_allocator<std::pair<const K, D>>>
+{
+  public:
+    typedef pool_allocator<std::pair<const K, D>> tAllocator;
 
     TMap() : std::map<K, D, CMP, tAllocator>() {}
     // use correct two-stage name lookup supported in gcc 3.4 and above
     TMap(const tAllocator& a) : std::map<K, D, CMP, tAllocator>(std::map<K, D, CMP, tAllocator>::key_compare(), a) {}
 };
 
 // Integer to TString conversion
 template <typename T>
--- a/gfx/angle/src/compiler/translator/Compiler.cpp
+++ b/gfx/angle/src/compiler/translator/Compiler.cpp
@@ -317,17 +317,20 @@ TIntermNode *TCompiler::compileTreeImpl(
             initBuiltInFunctionEmulator(&builtInFunctionEmulator, compileOptions);
             builtInFunctionEmulator.MarkBuiltInFunctionsForEmulation(root);
         }
 
         // Clamping uniform array bounds needs to happen after validateLimitations pass.
         if (success && (compileOptions & SH_CLAMP_INDIRECT_ARRAY_BOUNDS))
             arrayBoundsClamper.MarkIndirectArrayBoundsForClamping(root);
 
-        if (success && shaderType == GL_VERTEX_SHADER && (compileOptions & SH_INIT_GL_POSITION))
+        // gl_Position is always written in compatibility output mode
+        if (success && shaderType == GL_VERTEX_SHADER &&
+            ((compileOptions & SH_INIT_GL_POSITION) ||
+             (outputType == SH_GLSL_COMPATIBILITY_OUTPUT)))
             initializeGLPosition(root);
 
         // This pass might emit short circuits so keep it before the short circuit unfolding
         if (success && (compileOptions & SH_REWRITE_DO_WHILE_LOOPS))
             RewriteDoWhile(root, getTemporaryIndex());
 
         if (success && (compileOptions & SH_UNFOLD_SHORT_CIRCUIT))
         {
@@ -602,17 +605,17 @@ bool TCompiler::tagUsedFunctions()
         if (mCallDag.getRecordFromIndex(i).name == "main(")
         {
             internalTagUsedFunction(i);
             return true;
         }
     }
 
     infoSink.info.prefix(EPrefixError);
-    infoSink.info << "Missing main()";
+    infoSink.info << "Missing main()\n";
     return false;
 }
 
 void TCompiler::internalTagUsedFunction(size_t index)
 {
     if (functionMetadata[index].used)
     {
         return;
@@ -739,27 +742,16 @@ bool TCompiler::limitExpressionComplexit
     root->traverse(&traverser);
 
     if (traverser.getMaxDepth() > maxExpressionComplexity)
     {
         infoSink.info << "Expression too complex.";
         return false;
     }
 
-    TDependencyGraph graph(root);
-
-    for (TFunctionCallVector::const_iterator iter = graph.beginUserDefinedFunctionCalls();
-         iter != graph.endUserDefinedFunctionCalls();
-         ++iter)
-    {
-        TGraphFunctionCall* samplerSymbol = *iter;
-        TDependencyGraphTraverser graphTraverser;
-        samplerSymbol->traverse(&graphTraverser);
-    }
-
     return true;
 }
 
 bool TCompiler::enforceFragmentShaderTimingRestrictions(const TDependencyGraph& graph)
 {
     RestrictFragmentShaderTiming restrictor(infoSink.info);
     restrictor.enforceRestrictions(graph);
     return restrictor.numErrors() == 0;
--- a/gfx/angle/src/compiler/translator/DirectiveHandler.cpp
+++ b/gfx/angle/src/compiler/translator/DirectiveHandler.cpp
@@ -3,16 +3,17 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 //
 
 #include "compiler/translator/DirectiveHandler.h"
 
 #include <sstream>
 
+#include "angle_gl.h"
 #include "common/debug.h"
 #include "compiler/translator/Diagnostics.h"
 
 static TBehavior getBehavior(const std::string& str)
 {
     const char kRequire[] = "require";
     const char kEnable[] = "enable";
     const char kDisable[] = "disable";
@@ -20,23 +21,25 @@ static TBehavior getBehavior(const std::
 
     if (str == kRequire) return EBhRequire;
     else if (str == kEnable) return EBhEnable;
     else if (str == kDisable) return EBhDisable;
     else if (str == kWarn) return EBhWarn;
     return EBhUndefined;
 }
 
-TDirectiveHandler::TDirectiveHandler(TExtensionBehavior& extBehavior,
-                                     TDiagnostics& diagnostics,
-                                     int& shaderVersion,
+TDirectiveHandler::TDirectiveHandler(TExtensionBehavior &extBehavior,
+                                     TDiagnostics &diagnostics,
+                                     int &shaderVersion,
+                                     sh::GLenum shaderType,
                                      bool debugShaderPrecisionSupported)
     : mExtensionBehavior(extBehavior),
       mDiagnostics(diagnostics),
       mShaderVersion(shaderVersion),
+      mShaderType(shaderType),
       mDebugShaderPrecisionSupported(debugShaderPrecisionSupported)
 {
 }
 
 TDirectiveHandler::~TDirectiveHandler()
 {
 }
 
@@ -52,17 +55,26 @@ void TDirectiveHandler::handlePragma(con
                                      bool stdgl)
 {
     if (stdgl)
     {
         const char kInvariant[] = "invariant";
         const char kAll[] = "all";
 
         if (name == kInvariant && value == kAll)
+        {
+            if (mShaderVersion == 300 && mShaderType == GL_FRAGMENT_SHADER)
+            {
+                // ESSL 3.00.4 section 4.6.1
+                mDiagnostics.writeInfo(
+                    pp::Diagnostics::PP_ERROR, loc,
+                    "#pragma STDGL invariant(all) can not be used in fragment shader", name, value);
+            }
             mPragma.stdgl.invariantAll = true;
+        }
         // The STDGL pragma is used to reserve pragmas for use by future
         // revisions of GLSL.  Do not generate an error on unexpected
         // name and value.
         return;
     }
     else
     {
         const char kOptimize[] = "optimize";
--- a/gfx/angle/src/compiler/translator/DirectiveHandler.h
+++ b/gfx/angle/src/compiler/translator/DirectiveHandler.h
@@ -6,25 +6,27 @@
 
 #ifndef COMPILER_TRANSLATOR_DIRECTIVEHANDLER_H_
 #define COMPILER_TRANSLATOR_DIRECTIVEHANDLER_H_
 
 #include "common/angleutils.h"
 #include "compiler/translator/ExtensionBehavior.h"
 #include "compiler/translator/Pragma.h"
 #include "compiler/preprocessor/DirectiveHandlerBase.h"
+#include "GLSLANG/ShaderLang.h"
 
 class TDiagnostics;
 
 class TDirectiveHandler : public pp::DirectiveHandler, angle::NonCopyable
 {
   public:
-    TDirectiveHandler(TExtensionBehavior& extBehavior,
-                      TDiagnostics& diagnostics,
-                      int& shaderVersion,
+    TDirectiveHandler(TExtensionBehavior &extBehavior,
+                      TDiagnostics &diagnostics,
+                      int &shaderVersion,
+                      sh::GLenum shaderType,
                       bool debugShaderPrecisionSupported);
     ~TDirectiveHandler() override;
 
     const TPragma& pragma() const { return mPragma; }
     const TExtensionBehavior& extensionBehavior() const { return mExtensionBehavior; }
 
     void handleError(const pp::SourceLocation &loc, const std::string &msg) override;
 
@@ -39,12 +41,13 @@ class TDirectiveHandler : public pp::Dir
 
     void handleVersion(const pp::SourceLocation &loc, int version) override;
 
   private:
     TPragma mPragma;
     TExtensionBehavior& mExtensionBehavior;
     TDiagnostics& mDiagnostics;
     int& mShaderVersion;
+    sh::GLenum mShaderType;
     bool mDebugShaderPrecisionSupported;
 };
 
 #endif  // COMPILER_TRANSLATOR_DIRECTIVEHANDLER_H_
--- a/gfx/angle/src/compiler/translator/OutputHLSL.cpp
+++ b/gfx/angle/src/compiler/translator/OutputHLSL.cpp
@@ -78,29 +78,19 @@ const TConstantUnion *WriteConstantUnion
 
 namespace sh
 {
 
 TString OutputHLSL::TextureFunction::name() const
 {
     TString name = "gl_texture";
 
-    if (IsSampler2D(sampler))
-    {
-        name += "2D";
-    }
-    else if (IsSampler3D(sampler))
-    {
-        name += "3D";
-    }
-    else if (IsSamplerCube(sampler))
-    {
-        name += "Cube";
-    }
-    else UNREACHABLE();
+    // We need to include full the sampler type in the function name to make the signature unique
+    // on D3D11, where samplers are passed to texture functions as indices.
+    name += TextureTypeSuffix(this->sampler);
 
     if (proj)
     {
         name += "Proj";
     }
 
     if (offset)
     {
@@ -180,17 +170,17 @@ OutputHLSL::OutputHLSL(sh::GLenum shader
     mInsideDiscontinuousLoop = false;
     mNestedLoopDepth = 0;
 
     mExcessiveLoopIndex = NULL;
 
     mStructureHLSL = new StructureHLSL;
     mUniformHLSL = new UniformHLSL(mStructureHLSL, outputType, uniforms);
 
-    if (mOutputType == SH_HLSL9_OUTPUT)
+    if (mOutputType == SH_HLSL_3_0_OUTPUT)
     {
         // Fragment shaders need dx_DepthRange, dx_ViewCoords and dx_DepthFront.
         // Vertex shaders need a slightly different set: dx_DepthRange, dx_ViewCoords and dx_ViewAdjust.
         // In both cases total 3 uniform registers need to be reserved.
         mUniformHLSL->reserveUniformRegisters(3);
     }
 
     // Reserve registers for the default uniform block and driver constants
@@ -367,17 +357,17 @@ void OutputHLSL::header(TInfoSinkBase &o
         const TType &type = attribute->second->getType();
         const TString &name = attribute->second->getSymbol();
 
         attributes += "static " + TypeString(type) + " " + Decorate(name) + ArrayString(type) + " = " + initializer(type) + ";\n";
     }
 
     out << mStructureHLSL->structsHeader();
 
-    out << mUniformHLSL->uniformsHeader(mOutputType, mReferencedUniforms);
+    mUniformHLSL->uniformsHeader(out, mOutputType, mReferencedUniforms);
     out << mUniformHLSL->interfaceBlocksHeader(mReferencedInterfaceBlocks);
 
     if (!mEqualityFunctions.empty())
     {
         out << "\n// Equality functions\n\n";
         for (const auto &eqFunction : mEqualityFunctions)
         {
             out << eqFunction->functionDefinition << "\n";
@@ -490,17 +480,17 @@ void OutputHLSL::header(TInfoSinkBase &o
                    "{\n"
                    "    float near;\n"
                    "    float far;\n"
                    "    float diff;\n"
                    "};\n"
                    "\n";
         }
 
-        if (mOutputType == SH_HLSL11_OUTPUT)
+        if (mOutputType == SH_HLSL_4_1_OUTPUT || mOutputType == SH_HLSL_4_0_FL9_3_OUTPUT)
         {
             out << "cbuffer DriverConstants : register(b1)\n"
                    "{\n";
 
             if (mUsesDepthRange)
             {
                 out << "    float3 dx_DepthRange : packoffset(c0);\n";
             }
@@ -510,16 +500,23 @@ void OutputHLSL::header(TInfoSinkBase &o
                 out << "    float4 dx_ViewCoords : packoffset(c1);\n";
             }
 
             if (mUsesFragCoord || mUsesFrontFacing)
             {
                 out << "    float3 dx_DepthFront : packoffset(c2);\n";
             }
 
+            if (mUsesFragCoord)
+            {
+                // dx_ViewScale is only used in the fragment shader to correct
+                // the value for glFragCoord if necessary
+                out << "    float2 dx_ViewScale : packoffset(c3);\n";
+            }
+
             out << "};\n";
         }
         else
         {
             if (mUsesDepthRange)
             {
                 out << "uniform float3 dx_DepthRange : register(c0);";
             }
@@ -594,31 +591,33 @@ void OutputHLSL::header(TInfoSinkBase &o
                    "{\n"
                    "    float near;\n"
                    "    float far;\n"
                    "    float diff;\n"
                    "};\n"
                    "\n";
         }
 
-        if (mOutputType == SH_HLSL11_OUTPUT)
+        if (mOutputType == SH_HLSL_4_1_OUTPUT || mOutputType == SH_HLSL_4_0_FL9_3_OUTPUT)
         {
             out << "cbuffer DriverConstants : register(b1)\n"
                     "{\n";
 
             if (mUsesDepthRange)
             {
                 out << "    float3 dx_DepthRange : packoffset(c0);\n";
             }
 
-            // dx_ViewAdjust and dx_ViewCoords will only be used in Feature Level 9 shaders.
-            // However, we declare it for all shaders (including Feature Level 10+).
-            // The bytecode is the same whether we declare it or not, since D3DCompiler removes it if it's unused.
+            // dx_ViewAdjust and dx_ViewCoords will only be used in Feature Level 9
+            // shaders. However, we declare it for all shaders (including Feature Level 10+).
+            // The bytecode is the same whether we declare it or not, since D3DCompiler removes it
+            // if it's unused.
             out << "    float4 dx_ViewAdjust : packoffset(c1);\n";
             out << "    float2 dx_ViewCoords : packoffset(c2);\n";
+            out << "    float2 dx_ViewScale  : packoffset(c3);\n";
 
             out << "};\n"
                    "\n";
         }
         else
         {
             if (mUsesDepthRange)
             {
@@ -694,17 +693,17 @@ void OutputHLSL::header(TInfoSinkBase &o
         }
 
         // Function name
         out << textureFunction->name();
 
         // Argument list
         int hlslCoords = 4;
 
-        if (mOutputType == SH_HLSL9_OUTPUT)
+        if (mOutputType == SH_HLSL_3_0_OUTPUT)
         {
             switch(textureFunction->sampler)
             {
               case EbtSampler2D:   out << "sampler2D s";   hlslCoords = 2; break;
               case EbtSamplerCube: out << "samplerCUBE s"; hlslCoords = 3; break;
               default: UNREACHABLE();
             }
 
@@ -713,39 +712,30 @@ void OutputHLSL::header(TInfoSinkBase &o
               case TextureFunction::IMPLICIT:                 break;
               case TextureFunction::BIAS:     hlslCoords = 4; break;
               case TextureFunction::LOD:      hlslCoords = 4; break;
               case TextureFunction::LOD0:     hlslCoords = 4; break;
               case TextureFunction::LOD0BIAS: hlslCoords = 4; break;
               default: UNREACHABLE();
             }
         }
-        else if (mOutputType == SH_HLSL11_OUTPUT)
+        else
         {
-            switch(textureFunction->sampler)
+            hlslCoords = HLSLTextureCoordsCount(textureFunction->sampler);
+            if (mOutputType == SH_HLSL_4_0_FL9_3_OUTPUT)
             {
-              case EbtSampler2D:            out << "Texture2D x, SamplerState s";                hlslCoords = 2; break;
-              case EbtSampler3D:            out << "Texture3D x, SamplerState s";                hlslCoords = 3; break;
-              case EbtSamplerCube:          out << "TextureCube x, SamplerState s";              hlslCoords = 3; break;
-              case EbtSampler2DArray:       out << "Texture2DArray x, SamplerState s";           hlslCoords = 3; break;
-              case EbtISampler2D:           out << "Texture2D<int4> x, SamplerState s";          hlslCoords = 2; break;
-              case EbtISampler3D:           out << "Texture3D<int4> x, SamplerState s";          hlslCoords = 3; break;
-              case EbtISamplerCube:         out << "Texture2DArray<int4> x, SamplerState s";     hlslCoords = 3; break;
-              case EbtISampler2DArray:      out << "Texture2DArray<int4> x, SamplerState s";     hlslCoords = 3; break;
-              case EbtUSampler2D:           out << "Texture2D<uint4> x, SamplerState s";         hlslCoords = 2; break;
-              case EbtUSampler3D:           out << "Texture3D<uint4> x, SamplerState s";         hlslCoords = 3; break;
-              case EbtUSamplerCube:         out << "Texture2DArray<uint4> x, SamplerState s";    hlslCoords = 3; break;
-              case EbtUSampler2DArray:      out << "Texture2DArray<uint4> x, SamplerState s";    hlslCoords = 3; break;
-              case EbtSampler2DShadow:      out << "Texture2D x, SamplerComparisonState s";      hlslCoords = 2; break;
-              case EbtSamplerCubeShadow:    out << "TextureCube x, SamplerComparisonState s";    hlslCoords = 3; break;
-              case EbtSampler2DArrayShadow: out << "Texture2DArray x, SamplerComparisonState s"; hlslCoords = 3; break;
-              default: UNREACHABLE();
+                out << TextureString(textureFunction->sampler) << " x, "
+                    << SamplerString(textureFunction->sampler) << " s";
+            }
+            else
+            {
+                ASSERT(mOutputType == SH_HLSL_4_1_OUTPUT);
+                out << "const uint samplerIndex";
             }
         }
-        else UNREACHABLE();
 
         if (textureFunction->method == TextureFunction::FETCH)   // Integer coordinates
         {
             switch(textureFunction->coords)
             {
               case 2: out << ", int2 t"; break;
               case 3: out << ", int3 t"; break;
               default: UNREACHABLE();
@@ -826,35 +816,63 @@ void OutputHLSL::header(TInfoSinkBase &o
             textureFunction->method == TextureFunction::LOD0BIAS)
         {
             out << ", float bias";
         }
 
         out << ")\n"
                "{\n";
 
+        // In some cases we use a variable to store the texture/sampler objects, but to work around
+        // a D3D11 compiler bug related to discard inside a loop that is conditional on texture
+        // sampling we need to call the function directly on a reference to the array. The bug was
+        // found using dEQP-GLES3.functional.shaders.discard*loop_texture* tests.
+        TString textureReference("x");
+        TString samplerReference("s");
+        if (mOutputType == SH_HLSL_4_1_OUTPUT)
+        {
+            TString suffix = TextureGroupSuffix(textureFunction->sampler);
+            if (TextureGroup(textureFunction->sampler) == HLSL_TEXTURE_2D)
+            {
+                textureReference = TString("textures") + suffix + "[samplerIndex]";
+                samplerReference = TString("samplers") + suffix + "[samplerIndex]";
+            }
+            else
+            {
+                out << "    const uint textureIndex = samplerIndex - textureIndexOffset" << suffix
+                    << ";\n";
+                textureReference = TString("textures") + suffix + "[textureIndex]";
+                out << "    const uint samplerArrayIndex = samplerIndex - samplerIndexOffset"
+                    << suffix << ";\n";
+                samplerReference = TString("samplers") + suffix + "[samplerArrayIndex]";
+            }
+        }
+
         if (textureFunction->method == TextureFunction::SIZE)
         {
             if (IsSampler2D(textureFunction->sampler) || IsSamplerCube(textureFunction->sampler))
             {
                 if (IsSamplerArray(textureFunction->sampler))
                 {
                     out << "    uint width; uint height; uint layers; uint numberOfLevels;\n"
-                           "    x.GetDimensions(lod, width, height, layers, numberOfLevels);\n";
+                        << "    " << textureReference
+                        << ".GetDimensions(lod, width, height, layers, numberOfLevels);\n";
                 }
                 else
                 {
                     out << "    uint width; uint height; uint numberOfLevels;\n"
-                           "    x.GetDimensions(lod, width, height, numberOfLevels);\n";
+                        << "    " << textureReference
+                        << ".GetDimensions(lod, width, height, numberOfLevels);\n";
                 }
             }
             else if (IsSampler3D(textureFunction->sampler))
             {
                 out << "    uint width; uint height; uint depth; uint numberOfLevels;\n"
-                       "    x.GetDimensions(lod, width, height, depth, numberOfLevels);\n";
+                    << "    " << textureReference
+                    << ".GetDimensions(lod, width, height, depth, numberOfLevels);\n";
             }
             else UNREACHABLE();
 
             switch(textureFunction->sampler)
             {
               case EbtSampler2D:            out << "    return int2(width, height);";         break;
               case EbtSampler3D:            out << "    return int3(width, height, depth);";  break;
               case EbtSamplerCube:          out << "    return int2(width, height);";         break;
@@ -876,17 +894,18 @@ void OutputHLSL::header(TInfoSinkBase &o
         else
         {
             if (IsIntegerSampler(textureFunction->sampler) && IsSamplerCube(textureFunction->sampler))
             {
                 out << "    float width; float height; float layers; float levels;\n";
 
                 out << "    uint mip = 0;\n";
 
-                out << "    x.GetDimensions(mip, width, height, layers, levels);\n";
+                out << "    " << textureReference
+                    << ".GetDimensions(mip, width, height, layers, levels);\n";
 
                 out << "    bool xMajor = abs(t.x) > abs(t.y) && abs(t.x) > abs(t.z);\n";
                 out << "    bool yMajor = abs(t.y) > abs(t.z) && abs(t.y) > abs(t.x);\n";
                 out << "    bool zMajor = abs(t.z) > abs(t.x) && abs(t.z) > abs(t.y);\n";
                 out << "    bool negative = (xMajor && t.x < 0.0f) || (yMajor && t.y < 0.0f) || (zMajor && t.z < 0.0f);\n";
 
                 // FACE_POSITIVE_X = 000b
                 // FACE_NEGATIVE_X = 001b
@@ -906,17 +925,18 @@ void OutputHLSL::header(TInfoSinkBase &o
                 // Mip level computation.
                 if (textureFunction->method == TextureFunction::IMPLICIT)
                 {
                     out << "    float2 tSized = float2(t.x * width, t.y * height);\n"
                            "    float2 dx = ddx(tSized);\n"
                            "    float2 dy = ddy(tSized);\n"
                            "    float lod = 0.5f * log2(max(dot(dx, dx), dot(dy, dy)));\n"
                            "    mip = uint(min(max(round(lod), 0), levels - 1));\n"
-                           "    x.GetDimensions(mip, width, height, layers, levels);\n";
+                        << "    " << textureReference
+                        << ".GetDimensions(mip, width, height, layers, levels);\n";
                 }
             }
             else if (IsIntegerSampler(textureFunction->sampler) &&
                      textureFunction->method != TextureFunction::FETCH)
             {
                 if (IsSampler2D(textureFunction->sampler))
                 {
                     if (IsSamplerArray(textureFunction->sampler))
@@ -929,17 +949,18 @@ void OutputHLSL::header(TInfoSinkBase &o
                         }
                         else if (textureFunction->method == TextureFunction::LOD0BIAS)
                         {
                             out << "    uint mip = bias;\n";
                         }
                         else
                         {
 
-                            out << "    x.GetDimensions(0, width, height, layers, levels);\n";
+                            out << "    " << textureReference
+                                << ".GetDimensions(0, width, height, layers, levels);\n";
                             if (textureFunction->method == TextureFunction::IMPLICIT ||
                                 textureFunction->method == TextureFunction::BIAS)
                             {
                                 out << "    float2 tSized = float2(t.x * width, t.y * height);\n"
                                        "    float dx = length(ddx(tSized));\n"
                                        "    float dy = length(ddy(tSized));\n"
                                        "    float lod = log2(max(dx, dy));\n";
 
@@ -951,33 +972,35 @@ void OutputHLSL::header(TInfoSinkBase &o
                             else if (textureFunction->method == TextureFunction::GRAD)
                             {
                                 out << "    float lod = log2(max(length(ddx), length(ddy)));\n";
                             }
 
                             out << "    uint mip = uint(min(max(round(lod), 0), levels - 1));\n";
                         }
 
-                        out << "    x.GetDimensions(mip, width, height, layers, levels);\n";
+                        out << "    " << textureReference
+                            << ".GetDimensions(mip, width, height, layers, levels);\n";
                     }
                     else
                     {
                         out << "    float width; float height; float levels;\n";
 
                         if (textureFunction->method == TextureFunction::LOD0)
                         {
                             out << "    uint mip = 0;\n";
                         }
                         else if (textureFunction->method == TextureFunction::LOD0BIAS)
                         {
                             out << "    uint mip = bias;\n";
                         }
                         else
                         {
-                            out << "    x.GetDimensions(0, width, height, levels);\n";
+                            out << "    " << textureReference
+                                << ".GetDimensions(0, width, height, levels);\n";
 
                             if (textureFunction->method == TextureFunction::IMPLICIT ||
                                 textureFunction->method == TextureFunction::BIAS)
                             {
                                 out << "    float2 tSized = float2(t.x * width, t.y * height);\n"
                                        "    float dx = length(ddx(tSized));\n"
                                        "    float dy = length(ddy(tSized));\n"
                                        "    float lod = log2(max(dx, dy));\n";
@@ -990,34 +1013,36 @@ void OutputHLSL::header(TInfoSinkBase &o
                             else if (textureFunction->method == TextureFunction::GRAD)
                             {
                                 out << "    float lod = log2(max(length(ddx), length(ddy)));\n";
                             }
 
                             out << "    uint mip = uint(min(max(round(lod), 0), levels - 1));\n";
                         }
 
-                        out << "    x.GetDimensions(mip, width, height, levels);\n";
+                        out << "    " << textureReference
+                            << ".GetDimensions(mip, width, height, levels);\n";
                     }
                 }
                 else if (IsSampler3D(textureFunction->sampler))
                 {
                     out << "    float width; float height; float depth; float levels;\n";
 
                     if (textureFunction->method == TextureFunction::LOD0)
                     {
                         out << "    uint mip = 0;\n";
                     }
                     else if (textureFunction->method == TextureFunction::LOD0BIAS)
                     {
                         out << "    uint mip = bias;\n";
                     }
                     else
                     {
-                        out << "    x.GetDimensions(0, width, height, depth, levels);\n";
+                        out << "    " << textureReference
+                            << ".GetDimensions(0, width, height, depth, levels);\n";
 
                         if (textureFunction->method == TextureFunction::IMPLICIT ||
                             textureFunction->method == TextureFunction::BIAS)
                         {
                             out << "    float3 tSized = float3(t.x * width, t.y * height, t.z * "
                                    "depth);\n"
                                    "    float dx = length(ddx(tSized));\n"
                                    "    float dy = length(ddy(tSized));\n"
@@ -1031,86 +1056,127 @@ void OutputHLSL::header(TInfoSinkBase &o
                         else if (textureFunction->method == TextureFunction::GRAD)
                         {
                             out << "    float lod = log2(max(length(ddx), length(ddy)));\n";
                         }
 
                         out << "    uint mip = uint(min(max(round(lod), 0), levels - 1));\n";
                     }
 
-                    out << "    x.GetDimensions(mip, width, height, depth, levels);\n";
+                    out << "    " << textureReference
+                        << ".GetDimensions(mip, width, height, depth, levels);\n";
                 }
                 else UNREACHABLE();
             }
 
             out << "    return ";
 
             // HLSL intrinsic
-            if (mOutputType == SH_HLSL9_OUTPUT)
+            if (mOutputType == SH_HLSL_3_0_OUTPUT)
             {
                 switch(textureFunction->sampler)
                 {
                   case EbtSampler2D:   out << "tex2D";   break;
                   case EbtSamplerCube: out << "texCUBE"; break;
                   default: UNREACHABLE();
                 }
 
                 switch(textureFunction->method)
                 {
-                  case TextureFunction::IMPLICIT: out << "(s, ";     break;
-                  case TextureFunction::BIAS:     out << "bias(s, "; break;
-                  case TextureFunction::LOD:      out << "lod(s, ";  break;
-                  case TextureFunction::LOD0:     out << "lod(s, ";  break;
-                  case TextureFunction::LOD0BIAS: out << "lod(s, ";  break;
+                    case TextureFunction::IMPLICIT:
+                        out << "(" << samplerReference << ", ";
+                        break;
+                    case TextureFunction::BIAS:
+                        out << "bias(" << samplerReference << ", ";
+                        break;
+                    case TextureFunction::LOD:
+                        out << "lod(" << samplerReference << ", ";
+                        break;
+                    case TextureFunction::LOD0:
+                        out << "lod(" << samplerReference << ", ";
+                        break;
+                    case TextureFunction::LOD0BIAS:
+                        out << "lod(" << samplerReference << ", ";
+                        break;
                   default: UNREACHABLE();
                 }
             }
-            else if (mOutputType == SH_HLSL11_OUTPUT)
+            else if (mOutputType == SH_HLSL_4_1_OUTPUT || mOutputType == SH_HLSL_4_0_FL9_3_OUTPUT)
             {
                 if (textureFunction->method == TextureFunction::GRAD)
                 {
                     if (IsIntegerSampler(textureFunction->sampler))
                     {
-                        out << "x.Load(";
+                        out << "" << textureReference << ".Load(";
                     }
                     else if (IsShadowSampler(textureFunction->sampler))
                     {
-                        out << "x.SampleCmpLevelZero(s, ";
+                        out << "" << textureReference << ".SampleCmpLevelZero(" << samplerReference
+                            << ", ";
                     }
                     else
                     {
-                        out << "x.SampleGrad(s, ";
+                        out << "" << textureReference << ".SampleGrad(" << samplerReference << ", ";
                     }
                 }
                 else if (IsIntegerSampler(textureFunction->sampler) ||
                          textureFunction->method == TextureFunction::FETCH)
                 {
-                    out << "x.Load(";
+                    out << "" << textureReference << ".Load(";
                 }
                 else if (IsShadowSampler(textureFunction->sampler))
                 {
                     switch(textureFunction->method)
                     {
-                      case TextureFunction::IMPLICIT: out << "x.SampleCmp(s, ";          break;
-                      case TextureFunction::BIAS:     out << "x.SampleCmp(s, ";          break;
-                      case TextureFunction::LOD:      out << "x.SampleCmp(s, ";          break;
-                      case TextureFunction::LOD0:     out << "x.SampleCmpLevelZero(s, "; break;
-                      case TextureFunction::LOD0BIAS: out << "x.SampleCmpLevelZero(s, "; break;
+                        case TextureFunction::IMPLICIT:
+                            out << "" << textureReference << ".SampleCmp(" << samplerReference
+                                << ", ";
+                            break;
+                        case TextureFunction::BIAS:
+                            out << "" << textureReference << ".SampleCmp(" << samplerReference
+                                << ", ";
+                            break;
+                        case TextureFunction::LOD:
+                            out << "" << textureReference << ".SampleCmp(" << samplerReference
+                                << ", ";
+                            break;
+                        case TextureFunction::LOD0:
+                            out << "" << textureReference << ".SampleCmpLevelZero("
+                                << samplerReference << ", ";
+                            break;
+                        case TextureFunction::LOD0BIAS:
+                            out << "" << textureReference << ".SampleCmpLevelZero("
+                                << samplerReference << ", ";
+                            break;
                       default: UNREACHABLE();
                     }
                 }
                 else
                 {
                     switch(textureFunction->method)
                     {
-                      case TextureFunction::IMPLICIT: out << "x.Sample(s, ";      break;
-                      case TextureFunction::BIAS:     out << "x.SampleBias(s, ";  break;
-                      case TextureFunction::LOD:      out << "x.SampleLevel(s, "; break;
-                      case TextureFunction::LOD0:     out << "x.SampleLevel(s, "; break;
-                      case TextureFunction::LOD0BIAS: out << "x.SampleLevel(s, "; break;
+                        case TextureFunction::IMPLICIT:
+                            out << "" << textureReference << ".Sample(" << samplerReference << ", ";
+                            break;
+                        case TextureFunction::BIAS:
+                            out << "" << textureReference << ".SampleBias(" << samplerReference
+                                << ", ";
+                            break;
+                        case TextureFunction::LOD:
+                            out << "" << textureReference << ".SampleLevel(" << samplerReference
+                                << ", ";
+                            break;
+                        case TextureFunction::LOD0:
+                            out << "" << textureReference << ".SampleLevel(" << samplerReference
+                                << ", ";
+                            break;
+                        case TextureFunction::LOD0BIAS:
+                            out << "" << textureReference << ".SampleLevel(" << samplerReference
+                                << ", ";
+                            break;
                       default: UNREACHABLE();
                     }
                 }
             }
             else UNREACHABLE();
 
             // Integer sampling requires integer addresses
             TString addressx = "";
@@ -1170,17 +1236,17 @@ void OutputHLSL::header(TInfoSinkBase &o
                   case 3: proj = " / t.z"; break;
                   case 4: proj = " / t.w"; break;
                   default: UNREACHABLE();
                 }
             }
 
             out << addressx + ("t.x" + proj) + close + ", " + addressy + ("t.y" + proj) + close;
 
-            if (mOutputType == SH_HLSL9_OUTPUT)
+            if (mOutputType == SH_HLSL_3_0_OUTPUT)
             {
                 if (hlslCoords >= 3)
                 {
                     if (textureFunction->coords < 3)
                     {
                         out << ", 0";
                     }
                     else
@@ -1198,17 +1264,17 @@ void OutputHLSL::header(TInfoSinkBase &o
                       case TextureFunction::LOD0:     out << ", 0";    break;
                       case TextureFunction::LOD0BIAS: out << ", bias"; break;
                       default: UNREACHABLE();
                     }
                 }
 
                 out << "));\n";
             }
-            else if (mOutputType == SH_HLSL11_OUTPUT)
+            else if (mOutputType == SH_HLSL_4_1_OUTPUT || mOutputType == SH_HLSL_4_0_FL9_3_OUTPUT)
             {
                 if (hlslCoords >= 3)
                 {
                     if (IsIntegerSampler(textureFunction->sampler) && IsSamplerCube(textureFunction->sampler))
                     {
                         out << ", face";
                     }
                     else
@@ -2388,17 +2454,18 @@ bool OutputHLSL::visitAggregate(Visit vi
 
                 mUsesTexture.insert(textureFunction);
 
                 out << textureFunction.name();
             }
 
             for (TIntermSequence::iterator arg = arguments->begin(); arg != arguments->end(); arg++)
             {
-                if (mOutputType == SH_HLSL11_OUTPUT && IsSampler((*arg)->getAsTyped()->getBasicType()))
+                if (mOutputType == SH_HLSL_4_0_FL9_3_OUTPUT &&
+                    IsSampler((*arg)->getAsTyped()->getBasicType()))
                 {
                     out << "texture_";
                     (*arg)->traverse(this);
                     out << ", sampler_";
                 }
 
                 (*arg)->traverse(this);
 
@@ -2722,17 +2789,17 @@ bool OutputHLSL::visitLoop(Visit visit, 
     mNestedLoopDepth++;
 
     bool wasDiscontinuous = mInsideDiscontinuousLoop;
     mInsideDiscontinuousLoop = mInsideDiscontinuousLoop ||
     mCurrentFunctionMetadata->mDiscontinuousLoops.count(node) > 0;
 
     TInfoSinkBase &out = getInfoSink();
 
-    if (mOutputType == SH_HLSL9_OUTPUT)
+    if (mOutputType == SH_HLSL_3_0_OUTPUT)
     {
         if (handleExcessiveLoop(out, node))
         {
             mInsideDiscontinuousLoop = wasDiscontinuous;
             mNestedLoopDepth--;
 
             return false;
         }
@@ -3149,21 +3216,31 @@ TString OutputHLSL::argumentString(const
     {
         nameStr = "x" + str(mUniqueIndex++);
     }
     else
     {
         nameStr = DecorateIfNeeded(name);
     }
 
-    if (mOutputType == SH_HLSL11_OUTPUT && IsSampler(type.getBasicType()))
+    if (IsSampler(type.getBasicType()))
     {
-        return QualifierString(qualifier) + " " + TextureString(type) + " texture_" + nameStr +
-               ArrayString(type) + ", " + QualifierString(qualifier) + " " + SamplerString(type) +
-               " sampler_" + nameStr + ArrayString(type);
+        if (mOutputType == SH_HLSL_4_1_OUTPUT)
+        {
+            // Samplers are passed as indices to the sampler array.
+            ASSERT(qualifier != EvqOut && qualifier != EvqInOut);
+            return "const uint " + nameStr + ArrayString(type);
+        }
+        if (mOutputType == SH_HLSL_4_0_FL9_3_OUTPUT)
+        {
+            return QualifierString(qualifier) + " " + TextureString(type.getBasicType()) +
+                   " texture_" + nameStr + ArrayString(type) + ", " + QualifierString(qualifier) +
+                   " " + SamplerString(type.getBasicType()) + " sampler_" + nameStr +
+                   ArrayString(type);
+        }
     }
 
     return QualifierString(qualifier) + " " + TypeString(type) + " " + nameStr + ArrayString(type);
 }
 
 TString OutputHLSL::initializer(const TType &type)
 {
     TString string;
--- a/gfx/angle/src/compiler/translator/ParseContext.cpp
+++ b/gfx/angle/src/compiler/translator/ParseContext.cpp
@@ -1920,16 +1920,94 @@ void TParseContext::parseGlobalLayoutQua
     }
 
     if (layoutQualifier.blockStorage != EbsUnspecified)
     {
         mDefaultBlockStorage = layoutQualifier.blockStorage;
     }
 }
 
+TIntermAggregate *TParseContext::addFunctionPrototypeDeclaration(const TFunction &function,
+                                                                 const TSourceLoc &location)
+{
+    // Note: symbolTableFunction could be the same as function if this is the first declaration.
+    // Either way the instance in the symbol table is used to track whether the function is declared
+    // multiple times.
+    TFunction *symbolTableFunction =
+        static_cast<TFunction *>(symbolTable.find(function.getMangledName(), getShaderVersion()));
+    if (symbolTableFunction->hasPrototypeDeclaration() && mShaderVersion == 100)
+    {
+        // ESSL 1.00.17 section 4.2.7.
+        // Doesn't apply to ESSL 3.00.4: see section 4.2.3.
+        error(location, "duplicate function prototype declarations are not allowed", "function");
+        recover();
+    }
+    symbolTableFunction->setHasPrototypeDeclaration();
+
+    TIntermAggregate *prototype = new TIntermAggregate;
+    prototype->setType(function.getReturnType());
+    prototype->setName(function.getMangledName());
+    prototype->setFunctionId(function.getUniqueId());
+
+    for (size_t i = 0; i < function.getParamCount(); i++)
+    {
+        const TConstParameter &param = function.getParam(i);
+        if (param.name != 0)
+        {
+            TVariable variable(param.name, *param.type);
+
+            TIntermSymbol *paramSymbol = intermediate.addSymbol(
+                variable.getUniqueId(), variable.getName(), variable.getType(), location);
+            prototype = intermediate.growAggregate(prototype, paramSymbol, location);
+        }
+        else
+        {
+            TIntermSymbol *paramSymbol = intermediate.addSymbol(0, "", *param.type, location);
+            prototype                  = intermediate.growAggregate(prototype, paramSymbol, location);
+        }
+    }
+
+    prototype->setOp(EOpPrototype);
+
+    symbolTable.pop();
+
+    if (!symbolTable.atGlobalLevel())
+    {
+        // ESSL 3.00.4 section 4.2.4.
+        error(location, "local function prototype declarations are not allowed", "function");
+        recover();
+    }
+
+    return prototype;
+}
+
+TIntermAggregate *TParseContext::addFunctionDefinition(const TFunction &function,
+                                                       TIntermAggregate *functionPrototype,
+                                                       TIntermAggregate *functionBody,
+                                                       const TSourceLoc &location)
+{
+    //?? Check that all paths return a value if return type != void ?
+    //   May be best done as post process phase on intermediate code
+    if (mCurrentFunctionType->getBasicType() != EbtVoid && !mFunctionReturnsValue)
+    {
+        error(location, "function does not return a value:", "", function.getName().c_str());
+        recover();
+    }
+
+    TIntermAggregate *aggregate =
+        intermediate.growAggregate(functionPrototype, functionBody, location);
+    intermediate.setAggregateOperator(aggregate, EOpFunction, location);
+    aggregate->setName(function.getMangledName().c_str());
+    aggregate->setType(function.getReturnType());
+    aggregate->setFunctionId(function.getUniqueId());
+
+    symbolTable.pop();
+    return aggregate;
+}
+
 void TParseContext::parseFunctionPrototype(const TSourceLoc &location,
                                            TFunction *function,
                                            TIntermAggregate **aggregateOut)
 {
     const TSymbol *builtIn =
         symbolTable.findBuiltIn(function->getMangledName(), getShaderVersion());
 
     if (builtIn)
@@ -1973,18 +2051,18 @@ void TParseContext::parseFunctionPrototy
                   "main function cannot return a value");
             recover();
         }
     }
 
     //
     // Remember the return type for later checking for RETURN statements.
     //
-    setCurrentFunctionType(&(prevDec->getReturnType()));
-    setFunctionReturnsValue(false);
+    mCurrentFunctionType  = &(prevDec->getReturnType());
+    mFunctionReturnsValue = false;
 
     //
     // Insert parameters into the symbol table.
     // If the parameter has no name, it's not an error, just don't insert it
     // (could be used for unused args).
     //
     // Also, accumulate the list of parameters into the HIL, so lower level code
     // knows where to find parameters.
@@ -2025,22 +2103,22 @@ void TParseContext::parseFunctionPrototy
     intermediate.setAggregateOperator(paramNodes, EOpParameters, location);
     *aggregateOut = paramNodes;
     setLoopNestingLevel(0);
 }
 
 TFunction *TParseContext::parseFunctionDeclarator(const TSourceLoc &location, TFunction *function)
 {
     //
-    // Multiple declarations of the same function are allowed.
+    // We don't know at this point whether this is a function definition or a prototype.
+    // The definition production code will check for redefinitions.
+    // In the case of ESSL 1.00 the prototype production code will also check for redeclarations.
     //
-    // If this is a definition, the definition production code will check for redefinitions
-    // (we don't know at this point if it's a definition or not).
-    //
-    // Redeclarations are allowed.  But, return types and parameter qualifiers must match.
+    // Return types and parameter qualifiers must match in all redeclarations, so those are checked
+    // here.
     //
     TFunction *prevDec =
         static_cast<TFunction *>(symbolTable.find(function->getMangledName(), getShaderVersion()));
     if (prevDec)
     {
         if (prevDec->getReturnType() != function->getReturnType())
         {
             error(location, "overloaded functions must have the same return type",
--- a/gfx/angle/src/compiler/translator/ParseContext.h
+++ b/gfx/angle/src/compiler/translator/ParseContext.h
@@ -52,16 +52,17 @@ class TParseContext : angle::NonCopyable
           mChecksPrecisionErrors(checksPrecErrors),
           mFragmentPrecisionHighOnESSL1(false),
           mDefaultMatrixPacking(EmpColumnMajor),
           mDefaultBlockStorage(EbsShared),
           mDiagnostics(is),
           mDirectiveHandler(ext,
                             mDiagnostics,
                             mShaderVersion,
+                            mShaderType,
                             resources.WEBGL_debug_shader_precision == 1),
           mPreprocessor(&mDiagnostics, &mDirectiveHandler),
           mScanner(nullptr),
           mUsesFragData(false),
           mUsesFragColor(false),
           mUsesSecondaryOutputs(false),
           mMinProgramTexelOffset(resources.MinProgramTexelOffset),
           mMaxProgramTexelOffset(resources.MaxProgramTexelOffset)
@@ -97,33 +98,21 @@ class TParseContext : angle::NonCopyable
     {
         return mFragmentPrecisionHighOnESSL1 || mShaderVersion >= 300;
     }
     void setFragmentPrecisionHighOnESSL1(bool fragmentPrecisionHigh)
     {
         mFragmentPrecisionHighOnESSL1 = fragmentPrecisionHigh;
     }
 
-    bool getFunctionReturnsValue() const { return mFunctionReturnsValue; }
-    void setFunctionReturnsValue(bool functionReturnsValue)
-    {
-        mFunctionReturnsValue = functionReturnsValue;
-    }
-
     void setLoopNestingLevel(int loopNestintLevel)
     {
         mLoopNestingLevel = loopNestintLevel;
     }
 
-    const TType *getCurrentFunctionType() const { return mCurrentFunctionType; }
-    void setCurrentFunctionType(const TType *currentFunctionType)
-    {
-        mCurrentFunctionType = currentFunctionType;
-    }
-
     void incrLoopNestingLevel() { ++mLoopNestingLevel; }
     void decrLoopNestingLevel() { --mLoopNestingLevel; }
 
     void incrSwitchNestingLevel() { ++mSwitchNestingLevel; }
     void decrSwitchNestingLevel() { --mSwitchNestingLevel; }
 
     // This method is guaranteed to succeed, even if no variable with 'name' exists.
     const TVariable *getNamedVariable(const TSourceLoc &location, const TString *name, const TSymbol *symbol);
@@ -239,16 +228,22 @@ class TParseContext : angle::NonCopyable
                                                const TSourceLoc &identifierLocation,
                                                const TString &identifier,
                                                const TSourceLoc &indexLocation,
                                                TIntermTyped *indexExpression,
                                                const TSourceLoc &initLocation,
                                                TIntermTyped *initializer);
 
     void parseGlobalLayoutQualifier(const TPublicType &typeQualifier);
+    TIntermAggregate *addFunctionPrototypeDeclaration(const TFunction &function,
+                                                      const TSourceLoc &location);
+    TIntermAggregate *addFunctionDefinition(const TFunction &function,
+                                            TIntermAggregate *functionPrototype,
+                                            TIntermAggregate *functionBody,
+                                            const TSourceLoc &location);
     void parseFunctionPrototype(const TSourceLoc &location,
                                 TFunction *function,
                                 TIntermAggregate **aggregateOut);
     TFunction *parseFunctionDeclarator(const TSourceLoc &location,
                                        TFunction *function);
     TFunction *addConstructorFunc(const TPublicType &publicType);
     TIntermTyped *addConstructor(TIntermNode *arguments,
                                  TType *type,
--- a/gfx/angle/src/compiler/translator/ShaderLang.cpp
+++ b/gfx/angle/src/compiler/translator/ShaderLang.cpp
@@ -184,19 +184,26 @@ void ShInitBuiltInResources(ShBuiltInRes
 //
 // Driver calls these to create and destroy compiler objects.
 //
 ShHandle ShConstructCompiler(sh::GLenum type, ShShaderSpec spec,
                              ShShaderOutput output,
                              const ShBuiltInResources* resources)
 {
     TShHandleBase* base = static_cast<TShHandleBase*>(ConstructCompiler(type, spec, output));
+    if (base == nullptr)
+    {
+        return 0;
+    }
+
     TCompiler* compiler = base->getAsCompiler();
-    if (compiler == 0)
+    if (compiler == nullptr)
+    {
         return 0;
+    }
 
     // Generate built-in symbol table.
     if (!compiler->Init(*resources)) {
         ShDestruct(base);
         return 0;
     }
 
     return reinterpret_cast<void*>(base);
--- a/gfx/angle/src/compiler/translator/ShaderVars.cpp
+++ b/gfx/angle/src/compiler/translator/ShaderVars.cpp
@@ -388,9 +388,14 @@ InterfaceBlock &InterfaceBlock::operator
     arraySize = other.arraySize;
     layout = other.layout;
     isRowMajorLayout = other.isRowMajorLayout;
     staticUse = other.staticUse;
     fields = other.fields;
     return *this;
 }
 
+std::string InterfaceBlock::fieldPrefix() const
+{
+    return instanceName.empty() ? "" : name;
 }
+
+}  // namespace sh
--- a/gfx/angle/src/compiler/translator/SymbolTable.h
+++ b/gfx/angle/src/compiler/translator/SymbolTable.h
@@ -192,22 +192,26 @@ struct TParameter
     TString *name;
     TType *type;
 };
 
 // The function sub-class of a symbol.  
 class TFunction : public TSymbol
 {
   public:
-    TFunction(const TString *name, const TType *retType, TOperator tOp = EOpNull, const char *ext = "")
+    TFunction(const TString *name,
+              const TType *retType,
+              TOperator tOp   = EOpNull,
+              const char *ext = "")
         : TSymbol(name),
           returnType(retType),
           mangledName(nullptr),
           op(tOp),
-          defined(false)
+          defined(false),
+          mHasPrototypeDeclaration(false)
     {
         relateToExtension(ext);
     }
     ~TFunction() override;
     bool isFunction() const override { return true; }
 
     static TString mangleName(const TString &name)
     {
@@ -237,24 +241,20 @@ class TFunction : public TSymbol
         return *returnType;
     }
 
     TOperator getBuiltInOp() const
     {
         return op;
     }
 
-    void setDefined()
-    {
-        defined = true;
-    }
-    bool isDefined()
-    {
-        return defined;
-    }
+    void setDefined() { defined = true; }
+    bool isDefined() { return defined; }
+    void setHasPrototypeDeclaration() { mHasPrototypeDeclaration = true; }
+    bool hasPrototypeDeclaration() const { return mHasPrototypeDeclaration; }
 
     size_t getParamCount() const
     {
         return parameters.size();
     }
     const TConstParameter &getParam(size_t i) const
     {
         return parameters[i];
@@ -264,16 +264,17 @@ class TFunction : public TSymbol
     const TString *buildMangledName() const;
 
     typedef TVector<TConstParameter> TParamList;
     TParamList parameters;
     const TType *returnType;
     mutable const TString *mangledName;
     TOperator op;
     bool defined;
+    bool mHasPrototypeDeclaration;
 };
 
 // Interface block name sub-symbol
 class TInterfaceBlockName : public TSymbol
 {
   public:
     TInterfaceBlockName(const TString *name)
         : TSymbol(name)
--- a/gfx/angle/src/compiler/translator/TranslatorHLSL.cpp
+++ b/gfx/angle/src/compiler/translator/TranslatorHLSL.cpp
@@ -42,17 +42,17 @@ void TranslatorHLSL::translate(TIntermNo
     if (!shouldRunLoopAndIndexingValidation(compileOptions))
     {
         // HLSL doesn't support dynamic indexing of vectors and matrices.
         RemoveDynamicIndexing(root, getTemporaryIndex(), getSymbolTable(), getShaderVersion());
     }
 
     // Work around D3D9 bug that would manifest in vertex shaders with selection blocks which
     // use a vertex attribute as a condition, and some related computation in the else block.
-    if (getOutputType() == SH_HLSL9_OUTPUT && getShaderType() == GL_VERTEX_SHADER)
+    if (getOutputType() == SH_HLSL_3_0_OUTPUT && getShaderType() == GL_VERTEX_SHADER)
     {
         sh::RewriteElseBlocks(root, getTemporaryIndex());
     }
 
     sh::OutputHLSL outputHLSL(getShaderType(), getShaderVersion(), getExtensionBehavior(),
         getSourcePath(), getOutputType(), numRenderTargets, getUniforms(), compileOptions);
 
     outputHLSL.output(root, getInfoSink().obj);
--- a/gfx/angle/src/compiler/translator/UniformHLSL.cpp
+++ b/gfx/angle/src/compiler/translator/UniformHLSL.cpp
@@ -88,77 +88,167 @@ const Uniform *UniformHLSL::findUniformB
             return &mUniforms[uniformIndex];
         }
     }
 
     UNREACHABLE();
     return NULL;
 }
 
-unsigned int UniformHLSL::declareUniformAndAssignRegister(const TType &type, const TString &name)
+unsigned int UniformHLSL::declareUniformAndAssignRegister(const TType &type,
+                                                          const TString &name,
+                                                          unsigned int *registerCount)
 {
     unsigned int registerIndex = (IsSampler(type.getBasicType()) ? mSamplerRegister : mUniformRegister);
 
     const Uniform *uniform = findUniformByName(name);
     ASSERT(uniform);
 
     mUniformRegisterMap[uniform->name] = registerIndex;
 
-    unsigned int registerCount = HLSLVariableRegisterCount(*uniform, mOutputType);
+    ASSERT(registerCount);
+    *registerCount = HLSLVariableRegisterCount(*uniform, mOutputType);
 
     if (gl::IsSamplerType(uniform->type))
     {
-        mSamplerRegister += registerCount;
+        mSamplerRegister += *registerCount;
     }
     else
     {
-        mUniformRegister += registerCount;
+        mUniformRegister += *registerCount;
     }
 
     return registerIndex;
 }
 
-TString UniformHLSL::uniformsHeader(ShShaderOutput outputType, const ReferencedSymbols &referencedUniforms)
+unsigned int UniformHLSL::declareUniformAndAssignRegister(const TType &type, const TString &name)
 {
-    TString uniforms;
+    unsigned int registerCount;
+    return declareUniformAndAssignRegister(type, name, &registerCount);
+}
 
-    for (ReferencedSymbols::const_iterator uniformIt = referencedUniforms.begin();
-         uniformIt != referencedUniforms.end(); uniformIt++)
+void UniformHLSL::outputHLSLSamplerUniformGroup(TInfoSinkBase &out,
+                                                const HLSLTextureSamplerGroup textureGroup,
+                                                const TVector<const TIntermSymbol *> &group,
+                                                unsigned int *groupTextureRegisterIndex)
+{
+    if (group.empty())
+    {
+        return;
+    }
+    unsigned int groupRegisterCount = 0;
+    for (const TIntermSymbol *uniform : group)
     {
-        const TIntermSymbol &uniform = *uniformIt->second;
+        const TType &type   = uniform->getType();
+        const TString &name = uniform->getSymbol();
+        unsigned int registerCount;
+        unsigned int samplerArrayIndex =
+            declareUniformAndAssignRegister(type, name, &registerCount);
+        groupRegisterCount += registerCount;
+        if (type.isArray())
+        {
+            out << "static const uint " << DecorateIfNeeded(uniform->getName()) << ArrayString(type)
+                << " = {";
+            for (int i = 0; i < type.getArraySize(); ++i)
+            {
+                if (i > 0)
+                    out << ", ";
+                out << (samplerArrayIndex + i);
+            }
+            out << "};\n";
+        }
+        else
+        {
+            out << "static const uint " << DecorateIfNeeded(uniform->getName()) << " = "
+                << samplerArrayIndex << ";\n";
+        }
+    }
+    TString suffix = TextureGroupSuffix(textureGroup);
+    // Since HLSL_TEXTURE_2D is the first group, it has a fixed offset of zero.
+    if (textureGroup != HLSL_TEXTURE_2D)
+    {
+        out << "static const uint textureIndexOffset" << suffix << " = "
+            << (*groupTextureRegisterIndex) << ";\n";
+        out << "static const uint samplerIndexOffset" << suffix << " = "
+            << (*groupTextureRegisterIndex) << ";\n";
+    }
+    out << "uniform " << TextureString(textureGroup) << " textures" << suffix << "["
+        << groupRegisterCount << "]"
+        << " : register(t" << (*groupTextureRegisterIndex) << ");\n";
+    out << "uniform " << SamplerString(textureGroup) << " samplers" << suffix << "["
+        << groupRegisterCount << "]"
+        << " : register(s" << (*groupTextureRegisterIndex) << ");\n";
+    *groupTextureRegisterIndex += groupRegisterCount;
+}
+
+void UniformHLSL::uniformsHeader(TInfoSinkBase &out,
+                                 ShShaderOutput outputType,
+                                 const ReferencedSymbols &referencedUniforms)
+{
+    if (!referencedUniforms.empty())
+    {
+        out << "// Uniforms\n\n";
+    }
+    // In the case of HLSL 4, sampler uniforms need to be grouped by type before the code is
+    // written. They are grouped based on the combination of the HLSL texture type and
+    // HLSL sampler type, enumerated in HLSLTextureSamplerGroup.
+    TVector<TVector<const TIntermSymbol *>> groupedSamplerUniforms;
+    groupedSamplerUniforms.resize(HLSL_TEXTURE_MAX + 1);
+    for (auto &uniformIt : referencedUniforms)
+    {
+        // Output regular uniforms. Group sampler uniforms by type.
+        const TIntermSymbol &uniform = *uniformIt.second;
         const TType &type = uniform.getType();
         const TString &name = uniform.getSymbol();
 
-        unsigned int registerIndex = declareUniformAndAssignRegister(type, name);
-
-        if (outputType == SH_HLSL11_OUTPUT && IsSampler(type.getBasicType()))   // Also declare the texture
+        if (outputType == SH_HLSL_4_1_OUTPUT && IsSampler(type.getBasicType()))
+        {
+            HLSLTextureSamplerGroup group = TextureGroup(type.getBasicType());
+            groupedSamplerUniforms[group].push_back(&uniform);
+        }
+        else if (outputType == SH_HLSL_4_0_FL9_3_OUTPUT && IsSampler(type.getBasicType()))
         {
-            uniforms += "uniform " + SamplerString(type) + " sampler_" + DecorateUniform(name, type) + ArrayString(type) +
-                        " : register(s" + str(registerIndex) + ");\n";
-
-            uniforms += "uniform " + TextureString(type) + " texture_" + DecorateUniform(name, type) + ArrayString(type) +
-                        " : register(t" + str(registerIndex) + ");\n";
+            unsigned int registerIndex = declareUniformAndAssignRegister(type, name);
+            out << "uniform " << SamplerString(type.getBasicType()) << " sampler_"
+                << DecorateUniform(name, type) << ArrayString(type) << " : register(s"
+                << str(registerIndex) << ");\n";
+            out << "uniform " << TextureString(type.getBasicType()) << " texture_"
+                << DecorateUniform(name, type) << ArrayString(type) << " : register(t"
+                << str(registerIndex) << ");\n";
         }
         else
         {
+            unsigned int registerIndex  = declareUniformAndAssignRegister(type, name);
             const TStructure *structure = type.getStruct();
             // If this is a nameless struct, we need to use its full definition, rather than its (empty) name.
             // TypeString() will invoke defineNameless in this case; qualifier prefixes are unnecessary for 
             // nameless structs in ES, as nameless structs cannot be used anywhere that layout qualifiers are
             // permitted.
             const TString &typeName = ((structure && !structure->name().empty()) ?
                                         QualifiedStructNameString(*structure, false, false) : TypeString(type));
 
             const TString &registerString = TString("register(") + UniformRegisterPrefix(type) + str(registerIndex) + ")";
 
-            uniforms += "uniform " + typeName + " " + DecorateUniform(name, type) + ArrayString(type) + " : " + registerString + ";\n";
+            out << "uniform " << typeName << " " << DecorateUniform(name, type) << ArrayString(type)
+                << " : " << registerString << ";\n";
         }
     }
 
-    return (uniforms.empty() ? "" : ("// Uniforms\n\n" + uniforms));
+    if (outputType == SH_HLSL_4_1_OUTPUT)
+    {
+        unsigned int groupTextureRegisterIndex = 0;
+        // TEXTURE_2D is special, index offset is assumed to be 0 and omitted in that case.
+        ASSERT(HLSL_TEXTURE_MIN == HLSL_TEXTURE_2D);
+        for (int groupId = HLSL_TEXTURE_MIN; groupId < HLSL_TEXTURE_MAX; ++groupId)
+        {
+            outputHLSLSamplerUniformGroup(out, HLSLTextureSamplerGroup(groupId),
+                                          groupedSamplerUniforms[groupId],
+                                          &groupTextureRegisterIndex);
+        }
+    }
 }
 
 TString UniformHLSL::interfaceBlocksHeader(const ReferencedSymbols &referencedInterfaceBlocks)
 {
     TString interfaceBlocks;
 
     for (ReferencedSymbols::const_iterator interfaceBlockIt = referencedInterfaceBlocks.begin();
          interfaceBlockIt != referencedInterfaceBlocks.end(); interfaceBlockIt++)
--- a/gfx/angle/src/compiler/translator/UniformHLSL.h
+++ b/gfx/angle/src/compiler/translator/UniformHLSL.h
@@ -6,29 +6,36 @@
 // UniformHLSL.h:
 //   Methods for GLSL to HLSL translation for uniforms and interface blocks.
 //
 
 #ifndef COMPILER_TRANSLATOR_UNIFORMHLSL_H_
 #define COMPILER_TRANSLATOR_UNIFORMHLSL_H_
 
 #include "compiler/translator/OutputHLSL.h"
+#include "compiler/translator/UtilsHLSL.h"
 
 namespace sh
 {
 class StructureHLSL;
 
 class UniformHLSL : angle::NonCopyable
 {
   public:
     UniformHLSL(StructureHLSL *structureHLSL, ShShaderOutput outputType, const std::vector<Uniform> &uniforms);
 
     void reserveUniformRegisters(unsigned int registerCount);
     void reserveInterfaceBlockRegisters(unsigned int registerCount);
-    TString uniformsHeader(ShShaderOutput outputType, const ReferencedSymbols &referencedUniforms);
+    void outputHLSLSamplerUniformGroup(TInfoSinkBase &out,
+                                       const HLSLTextureSamplerGroup textureGroup,
+                                       const TVector<const TIntermSymbol *> &group,
+                                       unsigned int *groupTextureRegisterIndex);
+    void uniformsHeader(TInfoSinkBase &out,
+                        ShShaderOutput outputType,
+                        const ReferencedSymbols &referencedUniforms);
     TString interfaceBlocksHeader(const ReferencedSymbols &referencedInterfaceBlocks);
 
     // Used for direct index references
     static TString interfaceBlockInstanceString(const TInterfaceBlock& interfaceBlock, unsigned int arrayIndex);
 
     const std::map<std::string, unsigned int> &getInterfaceBlockRegisterMap() const
     {
         return mInterfaceBlockRegisterMap;
@@ -40,16 +47,19 @@ class UniformHLSL : angle::NonCopyable
 
   private:
     TString interfaceBlockString(const TInterfaceBlock &interfaceBlock, unsigned int registerIndex, unsigned int arrayIndex);
     TString interfaceBlockMembersString(const TInterfaceBlock &interfaceBlock, TLayoutBlockStorage blockStorage);
     TString interfaceBlockStructString(const TInterfaceBlock &interfaceBlock);
     const Uniform *findUniformByName(const TString &name) const;
 
     // Returns the uniform's register index
+    unsigned int declareUniformAndAssignRegister(const TType &type,
+                                                 const TString &name,
+                                                 unsigned int *registerCount);
     unsigned int declareUniformAndAssignRegister(const TType &type, const TString &name);
 
     unsigned int mUniformRegister;
     unsigned int mInterfaceBlockRegister;
     unsigned int mSamplerRegister;
     StructureHLSL *mStructureHLSL;
     ShShaderOutput mOutputType;
 
--- a/gfx/angle/src/compiler/translator/UtilsHLSL.cpp
+++ b/gfx/angle/src/compiler/translator/UtilsHLSL.cpp
@@ -10,54 +10,180 @@
 #include "compiler/translator/UtilsHLSL.h"
 #include "compiler/translator/IntermNode.h"
 #include "compiler/translator/StructureHLSL.h"
 #include "compiler/translator/SymbolTable.h"
 
 namespace sh
 {
 
-TString SamplerString(const TType &type)
+TString SamplerString(const TBasicType type)
 {
-    if (IsShadowSampler(type.getBasicType()))
+    if (IsShadowSampler(type))
+    {
+        return "SamplerComparisonState";
+    }
+    else
+    {
+        return "SamplerState";
+    }
+}
+
+TString SamplerString(HLSLTextureSamplerGroup type)
+{
+    if (type >= HLSL_COMPARISON_SAMPLER_GROUP_BEGIN && type <= HLSL_COMPARISON_SAMPLER_GROUP_END)
     {
         return "SamplerComparisonState";
     }
     else
     {
         return "SamplerState";
     }
 }
 
-TString TextureString(const TType &type)
+HLSLTextureSamplerGroup TextureGroup(const TBasicType type)
 {
-    switch (type.getBasicType())
+    switch (type)
     {
-      case EbtSampler2D:            return "Texture2D";
-      case EbtSamplerCube:          return "TextureCube";
-      case EbtSamplerExternalOES:   return "Texture2D";
-      case EbtSampler2DArray:       return "Texture2DArray";
-      case EbtSampler3D:            return "Texture3D";
-      case EbtISampler2D:           return "Texture2D<int4>";
-      case EbtISampler3D:           return "Texture3D<int4>";
-      case EbtISamplerCube:         return "Texture2DArray<int4>";
-      case EbtISampler2DArray:      return "Texture2DArray<int4>";
-      case EbtUSampler2D:           return "Texture2D<uint4>";
-      case EbtUSampler3D:           return "Texture3D<uint4>";
-      case EbtUSamplerCube:         return "Texture2DArray<uint4>";
-      case EbtUSampler2DArray:      return "Texture2DArray<uint4>";
-      case EbtSampler2DShadow:      return "Texture2D";
-      case EbtSamplerCubeShadow:    return "TextureCube";
-      case EbtSampler2DArrayShadow: return "Texture2DArray";
-      default: UNREACHABLE();
+        case EbtSampler2D:
+            return HLSL_TEXTURE_2D;
+        case EbtSamplerCube:
+            return HLSL_TEXTURE_CUBE;
+        case EbtSamplerExternalOES:
+            return HLSL_TEXTURE_2D;
+        case EbtSampler2DArray:
+            return HLSL_TEXTURE_2D_ARRAY;
+        case EbtSampler3D:
+            return HLSL_TEXTURE_3D;
+        case EbtISampler2D:
+            return HLSL_TEXTURE_2D_INT4;
+        case EbtISampler3D:
+            return HLSL_TEXTURE_3D_INT4;
+        case EbtISamplerCube:
+            return HLSL_TEXTURE_2D_ARRAY_INT4;
+        case EbtISampler2DArray:
+            return HLSL_TEXTURE_2D_ARRAY_INT4;
+        case EbtUSampler2D:
+            return HLSL_TEXTURE_2D_UINT4;
+        case EbtUSampler3D:
+            return HLSL_TEXTURE_3D_UINT4;
+        case EbtUSamplerCube:
+            return HLSL_TEXTURE_2D_ARRAY_UINT4;
+        case EbtUSampler2DArray:
+            return HLSL_TEXTURE_2D_ARRAY_UINT4;
+        case EbtSampler2DShadow:
+            return HLSL_TEXTURE_2D_COMPARISON;
+        case EbtSamplerCubeShadow:
+            return HLSL_TEXTURE_CUBE_COMPARISON;
+        case EbtSampler2DArrayShadow:
+            return HLSL_TEXTURE_2D_ARRAY_COMPARISON;
+        default:
+            UNREACHABLE();
+    }
+    return HLSL_TEXTURE_UNKNOWN;
+}
+
+TString TextureString(const HLSLTextureSamplerGroup type)
+{
+    switch (type)
+    {
+        case HLSL_TEXTURE_2D:
+            return "Texture2D";
+        case HLSL_TEXTURE_CUBE:
+            return "TextureCube";
+        case HLSL_TEXTURE_2D_ARRAY:
+            return "Texture2DArray";
+        case HLSL_TEXTURE_3D:
+            return "Texture3D";
+        case HLSL_TEXTURE_2D_INT4:
+            return "Texture2D<int4>";
+        case HLSL_TEXTURE_3D_INT4:
+            return "Texture3D<int4>";
+        case HLSL_TEXTURE_2D_ARRAY_INT4:
+            return "Texture2DArray<int4>";
+        case HLSL_TEXTURE_2D_UINT4:
+            return "Texture2D<uint4>";
+        case HLSL_TEXTURE_3D_UINT4:
+            return "Texture3D<uint4>";
+        case HLSL_TEXTURE_2D_ARRAY_UINT4:
+            return "Texture2DArray<uint4>";
+        case HLSL_TEXTURE_2D_COMPARISON:
+            return "Texture2D";
+        case HLSL_TEXTURE_CUBE_COMPARISON:
+            return "TextureCube";
+        case HLSL_TEXTURE_2D_ARRAY_COMPARISON:
+            return "Texture2DArray";
+        default:
+            UNREACHABLE();
     }
 
     return "<unknown texture type>";
 }
 
+TString TextureString(const TBasicType type)
+{
+    return TextureString(TextureGroup(type));
+}
+
+TString TextureGroupSuffix(const HLSLTextureSamplerGroup type)
+{
+    switch (type)
+    {
+        case HLSL_TEXTURE_2D:
+            return "2D";
+        case HLSL_TEXTURE_CUBE:
+            return "Cube";
+        case HLSL_TEXTURE_2D_ARRAY:
+            return "2DArray";
+        case HLSL_TEXTURE_3D:
+            return "3D";
+        case HLSL_TEXTURE_2D_INT4:
+            return "2D_int4_";
+        case HLSL_TEXTURE_3D_INT4:
+            return "3D_int4_";
+        case HLSL_TEXTURE_2D_ARRAY_INT4:
+            return "2DArray_int4_";
+        case HLSL_TEXTURE_2D_UINT4:
+            return "2D_uint4_";
+        case HLSL_TEXTURE_3D_UINT4:
+            return "3D_uint4_";
+        case HLSL_TEXTURE_2D_ARRAY_UINT4:
+            return "2DArray_uint4_";
+        case HLSL_TEXTURE_2D_COMPARISON:
+            return "2D_comparison";
+        case HLSL_TEXTURE_CUBE_COMPARISON:
+            return "Cube_comparison";
+        case HLSL_TEXTURE_2D_ARRAY_COMPARISON:
+            return "2DArray_comparison";
+        default:
+            UNREACHABLE();
+    }
+
+    return "<unknown texture type>";
+}
+
+TString TextureGroupSuffix(const TBasicType type)
+{
+    return TextureGroupSuffix(TextureGroup(type));
+}
+
+TString TextureTypeSuffix(const TBasicType type)
+{
+    switch (type)
+    {
+        case EbtISamplerCube:
+            return "Cube_int4_";
+        case EbtUSamplerCube:
+            return "Cube_uint4_";
+        default:
+            // All other types are identified by their group suffix
+            return TextureGroupSuffix(type);
+    }
+}
+
 TString DecorateUniform(const TString &string, const TType &type)
 {
     if (type.getBasicType() == EbtSamplerExternalOES)
     {
         return "ex_" + string;
     }
 
     return Decorate(string);
@@ -265,9 +391,48 @@ TString QualifierString(TQualifier quali
       case EvqInOut:         return "inout";
       case EvqConstReadOnly: return "const";
       default: UNREACHABLE();
     }
 
     return "";
 }
 
+int HLSLTextureCoordsCount(const TBasicType samplerType)
+{
+    switch (samplerType)
+    {
+        case EbtSampler2D:
+            return 2;
+        case EbtSampler3D:
+            return 3;
+        case EbtSamplerCube:
+            return 3;
+        case EbtSampler2DArray:
+            return 3;
+        case EbtISampler2D:
+            return 2;
+        case EbtISampler3D:
+            return 3;
+        case EbtISamplerCube:
+            return 3;
+        case EbtISampler2DArray:
+            return 3;
+        case EbtUSampler2D:
+            return 2;
+        case EbtUSampler3D:
+            return 3;
+        case EbtUSamplerCube:
+            return 3;
+        case EbtUSampler2DArray:
+            return 3;
+        case EbtSampler2DShadow:
+            return 2;
+        case EbtSamplerCubeShadow:
+            return 3;
+        case EbtSampler2DArrayShadow:
+            return 3;
+        default:
+            UNREACHABLE();
+    }
+    return 0;
 }
+}
--- a/gfx/angle/src/compiler/translator/UtilsHLSL.h
+++ b/gfx/angle/src/compiler/translator/UtilsHLSL.h
@@ -15,28 +15,64 @@
 
 #include "angle_gl.h"
 
 class TName;
 
 namespace sh
 {
 
-TString TextureString(const TType &type);
-TString SamplerString(const TType &type);
+// Unique combinations of HLSL Texture type and HLSL Sampler type.
+enum HLSLTextureSamplerGroup
+{
+    // Regular samplers
+    HLSL_TEXTURE_2D,
+    HLSL_TEXTURE_MIN = HLSL_TEXTURE_2D,
+
+    HLSL_TEXTURE_CUBE,
+    HLSL_TEXTURE_2D_ARRAY,
+    HLSL_TEXTURE_3D,
+    HLSL_TEXTURE_2D_INT4,
+    HLSL_TEXTURE_3D_INT4,
+    HLSL_TEXTURE_2D_ARRAY_INT4,
+    HLSL_TEXTURE_2D_UINT4,
+    HLSL_TEXTURE_3D_UINT4,
+    HLSL_TEXTURE_2D_ARRAY_UINT4,
+
+    // Comparison samplers
+
+    HLSL_TEXTURE_2D_COMPARISON,
+    HLSL_TEXTURE_CUBE_COMPARISON,
+    HLSL_TEXTURE_2D_ARRAY_COMPARISON,
+
+    HLSL_COMPARISON_SAMPLER_GROUP_BEGIN = HLSL_TEXTURE_2D_COMPARISON,
+    HLSL_COMPARISON_SAMPLER_GROUP_END   = HLSL_TEXTURE_2D_ARRAY_COMPARISON,
+
+    HLSL_TEXTURE_UNKNOWN,
+    HLSL_TEXTURE_MAX = HLSL_TEXTURE_UNKNOWN
+};
+
+HLSLTextureSamplerGroup TextureGroup(const TBasicType type);
+TString TextureString(const HLSLTextureSamplerGroup type);
+TString TextureString(const TBasicType type);
+TString TextureGroupSuffix(const HLSLTextureSamplerGroup type);
+TString TextureGroupSuffix(const TBasicType type);
+TString TextureTypeSuffix(const TBasicType type);
+TString SamplerString(const TBasicType type);
+TString SamplerString(HLSLTextureSamplerGroup type);
 // Prepends an underscore to avoid naming clashes
 TString Decorate(const TString &string);
 TString DecorateIfNeeded(const TName &name);
 // Decorates and also unmangles the function name
 TString DecorateFunctionIfNeeded(const TName &name);
 TString DecorateUniform(const TString &string, const TType &type);
 TString DecorateField(const TString &string, const TStructure &structure);
 TString DecoratePrivate(const TString &privateText);
 TString TypeString(const TType &type);
 TString StructNameString(const TStructure &structure);
 TString QualifiedStructNameString(const TStructure &structure, bool useHLSLRowMajorPacking,
                                   bool useStd140Packing);
 TString InterpolationString(TQualifier qualifier);
 TString QualifierString(TQualifier qualifier);
-
+int HLSLTextureCoordsCount(const TBasicType samplerType);
 }
 
 #endif // COMPILER_TRANSLATOR_UTILSHLSL_H_
--- a/gfx/angle/src/compiler/translator/VariableInfo.cpp
+++ b/gfx/angle/src/compiler/translator/VariableInfo.cpp
@@ -11,28 +11,16 @@
 #include "common/utilities.h"
 
 namespace sh
 {
 
 namespace
 {
 
-TString InterfaceBlockFieldName(const TInterfaceBlock &interfaceBlock, const TField &field)
-{
-    if (interfaceBlock.hasInstanceName())
-    {
-        return interfaceBlock.name() + "." + field.name();
-    }
-    else
-    {
-        return field.name();
-    }
-}
-
 BlockLayoutType GetBlockLayoutType(TLayoutBlockStorage blockStorage)
 {
     switch (blockStorage)
     {
       case EbsPacked:         return BLOCKLAYOUT_PACKED;
       case EbsShared:         return BLOCKLAYOUT_SHARED;
       case EbsStd140:         return BLOCKLAYOUT_STANDARD;
       default: UNREACHABLE(); return BLOCKLAYOUT_SHARED;
@@ -554,26 +542,22 @@ void CollectVariables::visitVariable(con
     interfaceBlock.mappedName =
         TIntermTraverser::hash(blockType->name().c_str(), mHashFunction).c_str();
     interfaceBlock.instanceName = (blockType->hasInstanceName() ? blockType->instanceName().c_str() : "");
     interfaceBlock.arraySize = variable->getArraySize();
     interfaceBlock.isRowMajorLayout = (blockType->matrixPacking() == EmpRowMajor);
     interfaceBlock.layout = GetBlockLayoutType(blockType->blockStorage());
 
     // Gather field information
-    const TFieldList &fieldList = blockType->fields();
-
-    for (size_t fieldIndex = 0; fieldIndex < fieldList.size(); ++fieldIndex)
+    for (const TField *field : blockType->fields())
     {
-        const TField &field = *fieldList[fieldIndex];
-        const TString &fullFieldName = InterfaceBlockFieldName(*blockType, field);
-        const TType &fieldType = *field.type();
+        const TType &fieldType = *field->type();
 
         NameHashingTraverser traverser(mHashFunction, mSymbolTable);
-        traverser.traverse(fieldType, fullFieldName, &interfaceBlock.fields);
+        traverser.traverse(fieldType, field->name(), &interfaceBlock.fields);
 
         interfaceBlock.fields.back().isRowMajorLayout = (fieldType.getLayoutQualifier().matrixPacking == EmpRowMajor);
     }
 
     infoList->push_back(interfaceBlock);
 }
 
 template <typename VarT>
--- a/gfx/angle/src/compiler/translator/blocklayout.h
+++ b/gfx/angle/src/compiler/translator/blocklayout.h
@@ -50,18 +50,16 @@ class COMPILER_EXPORT BlockLayoutEncoder
 {
   public:
     BlockLayoutEncoder();
     virtual ~BlockLayoutEncoder() {}
 
     BlockMemberInfo encodeType(GLenum type, unsigned int arraySize, bool isRowMajorMatrix);
 
     size_t getBlockSize() const { return mCurrentOffset * BytesPerComponent; }
-    size_t getCurrentRegister() const { return mCurrentOffset / ComponentsPerRegister; }
-    size_t getCurrentElement() const { return mCurrentOffset % ComponentsPerRegister; }
 
     virtual void enterAggregateType() = 0;
     virtual void exitAggregateType() = 0;
 
     static const size_t BytesPerComponent = 4u;
     static const unsigned int ComponentsPerRegister = 4u;
 
     static size_t getBlockRegister(const BlockMemberInfo &info);
--- a/gfx/angle/src/compiler/translator/blocklayoutHLSL.cpp
+++ b/gfx/angle/src/compiler/translator/blocklayoutHLSL.cpp
@@ -108,19 +108,24 @@ void HLSLBlockEncoder::skipRegisters(uns
 {
     mCurrentOffset += (numRegisters * ComponentsPerRegister);
 }
 
 HLSLBlockEncoder::HLSLBlockEncoderStrategy HLSLBlockEncoder::GetStrategyFor(ShShaderOutput outputType)
 {
     switch (outputType)
     {
-      case SH_HLSL9_OUTPUT: return ENCODE_LOOSE;
-      case SH_HLSL11_OUTPUT: return ENCODE_PACKED;
-      default: UNREACHABLE(); return ENCODE_PACKED;
+        case SH_HLSL_3_0_OUTPUT:
+            return ENCODE_LOOSE;
+        case SH_HLSL_4_1_OUTPUT:
+        case SH_HLSL_4_0_FL9_3_OUTPUT:
+            return ENCODE_PACKED;
+        default:
+            UNREACHABLE();
+            return ENCODE_PACKED;
     }
 }
 
 template <class ShaderVarType>
 void HLSLVariableRegisterCount(const ShaderVarType &variable, HLSLBlockEncoder *encoder)
 {
     if (variable.isStruct())
     {
--- a/gfx/angle/src/compiler/translator/depgraph/DependencyGraph.h
+++ b/gfx/angle/src/compiler/translator/depgraph/DependencyGraph.h
@@ -137,37 +137,21 @@ public:
 // This class (and nobody else) manages the memory of the created nodes.
 // Nodes may not be removed after being added, so all created nodes will exist while the
 // TDependencyGraph instance exists.
 //
 class TDependencyGraph {
 public:
     TDependencyGraph(TIntermNode* intermNode);
     ~TDependencyGraph();
-    TGraphNodeVector::const_iterator begin() const { return mAllNodes.begin(); }
-    TGraphNodeVector::const_iterator end() const { return mAllNodes.end(); }
-
-    TGraphSymbolVector::const_iterator beginSamplerSymbols() const
-    {
-        return mSamplerSymbols.begin();
-    }
-
-    TGraphSymbolVector::const_iterator endSamplerSymbols() const
+    const TGraphNodeVector &allNodes() const { return mAllNodes; }
+    const TGraphSymbolVector &samplerSymbols() const { return mSamplerSymbols; }
+    const TFunctionCallVector &userDefinedFunctionCalls() const
     {
-        return mSamplerSymbols.end();
-    }
-
-    TFunctionCallVector::const_iterator beginUserDefinedFunctionCalls() const
-    {
-        return mUserDefinedFunctionCalls.begin();
-    }
-
-    TFunctionCallVector::const_iterator endUserDefinedFunctionCalls() const
-    {
-        return mUserDefinedFunctionCalls.end();
+        return mUserDefinedFunctionCalls;
     }
 
     TGraphArgument* createArgument(TIntermAggregate* intermFunctionCall, int argumentNumber);
     TGraphFunctionCall* createFunctionCall(TIntermAggregate* intermFunctionCall);
     TGraphSymbol* getOrCreateSymbol(TIntermSymbol* intermSymbol);
     TGraphSelection* createSelection(TIntermSelection* intermSelection);
     TGraphLoop* createLoop(TIntermLoop* intermLoop);
     TGraphLogicalOp* createLogicalOp(TIntermBinary* intermLogicalOp);
--- a/gfx/angle/src/compiler/translator/depgraph/DependencyGraphOutput.cpp
+++ b/gfx/angle/src/compiler/translator/depgraph/DependencyGraphOutput.cpp
@@ -49,17 +49,16 @@ void TDependencyGraphOutput::visitLogica
     outputIndentation();
     mSink << "logical " << logicalOp->getOpString() << "\n";
 }
 
 void TDependencyGraphOutput::outputAllSpanningTrees(TDependencyGraph& graph)
 {
     mSink << "\n";
 
-    for (TGraphNodeVector::const_iterator iter = graph.begin(); iter != graph.end(); ++iter)
+    for (auto symbol : graph.allNodes())
     {
-        TGraphNode* symbol = *iter;
         mSink << "--- Dependency graph spanning tree ---\n";
         clearVisited();
         symbol->traverse(this);
         mSink << "\n";
     }
 }
--- a/gfx/angle/src/compiler/translator/generate_parser.sh
+++ b/gfx/angle/src/compiler/translator/generate_parser.sh
@@ -2,27 +2,28 @@
 # Copyright (c) 2010 The ANGLE Project Authors. All rights reserved.
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
 # Generates GLSL ES parser - glslang_lex.cpp, glslang_tab.h, and glslang_tab.cpp
 
 run_flex()
 {
-input_file=$script_dir/$1.l
-output_source=$script_dir/$1_lex.cpp
+input_file=./$1.l
+output_source=./$1_lex.cpp
 flex --noline --nounistd --outfile=$output_source $input_file
 }
 
 run_bison()
 {
-input_file=$script_dir/$1.y
-output_header=$script_dir/$1_tab.h
-output_source=$script_dir/$1_tab.cpp
+input_file=./$1.y
+output_header=./$1_tab.h
+output_source=./$1_tab.cpp
 bison --no-lines --skeleton=yacc.c --defines=$output_header --output=$output_source $input_file
 }
 
 script_dir=$(dirname $0)
 
 # Generate Parser
+cd $script_dir
 run_flex glslang
 run_bison glslang
 patch --silent --forward < 64bit-lexer-safety.patch
--- a/gfx/angle/src/compiler/translator/glslang.y
+++ b/gfx/angle/src/compiler/translator/glslang.y
@@ -173,20 +173,20 @@ extern void yyerror(YYLTYPE* yylloc, TPa
 %type <interm.intermTypedNode> relational_expression equality_expression
 %type <interm.intermTypedNode> conditional_expression constant_expression
 %type <interm.intermTypedNode> logical_or_expression logical_xor_expression logical_and_expression
 %type <interm.intermTypedNode> shift_expression and_expression exclusive_or_expression inclusive_or_expression
 %type <interm.intermTypedNode> function_call initializer condition conditionopt
 
 %type <interm.intermNode> translation_unit function_definition
 %type <interm.intermNode> statement simple_statement
-%type <interm.intermAggregate>  statement_list compound_statement
+%type <interm.intermAggregate>  statement_list compound_statement compound_statement_no_new_scope
 %type <interm.intermNode> declaration_statement selection_statement expression_statement
 %type <interm.intermNode> declaration external_declaration
-%type <interm.intermNode> for_init_statement compound_statement_no_new_scope
+%type <interm.intermNode> for_init_statement
 %type <interm.nodePair> selection_rest_statement for_rest_statement
 %type <interm.intermSwitch> switch_statement
 %type <interm.intermCase> case_label
 %type <interm.intermNode> iteration_statement jump_statement statement_no_new_scope statement_with_scope
 %type <interm> single_declaration init_declarator_list
 
 %type <interm> parameter_declaration parameter_declarator parameter_type_specifier
 %type <interm.qualifier> parameter_qualifier parameter_type_qualifier 
@@ -575,43 +575,18 @@ enter_struct
     : IDENTIFIER LEFT_BRACE {
         if (context->enterStructDeclaration(@1, *$1.string))
             context->recover();
         $$ = $1;
     }
     ;
 
 declaration
-    : function_prototype SEMICOLON   {
-        TFunction &function = *($1.function);
-        
-        TIntermAggregate *prototype = new TIntermAggregate;
-        prototype->setType(function.getReturnType());
-        prototype->setName(function.getMangledName());
-        prototype->setFunctionId(function.getUniqueId());
-        
-        for (size_t i = 0; i < function.getParamCount(); i++)
-        {
-            const TConstParameter &param = function.getParam(i);
-            if (param.name != 0)
-            {
-                TVariable variable(param.name, *param.type);
-                
-                prototype = context->intermediate.growAggregate(prototype, context->intermediate.addSymbol(variable.getUniqueId(), variable.getName(), variable.getType(), @1), @1);
-            }
-            else
-            {
-                prototype = context->intermediate.growAggregate(prototype, context->intermediate.addSymbol(0, "", *param.type, @1), @1);
-            }
-        }
-        
-        prototype->setOp(EOpPrototype);
-        $$ = prototype;
-
-        context->symbolTable.pop();
+    : function_prototype SEMICOLON {
+        $$ = context->addFunctionPrototypeDeclaration(*($1.function), @1);
     }
     | init_declarator_list SEMICOLON {
         TIntermAggregate *aggNode = $1.intermAggregate;
         if (aggNode && aggNode->getOp() == EOpNull)
             aggNode->setOp(EOpDeclaration);
         $$ = aggNode;
     }
     | PRECISION precision_qualifier type_specifier_no_prec SEMICOLON {
@@ -1594,30 +1569,17 @@ external_declaration
     }
     ;
 
 function_definition
     : function_prototype {
         context->parseFunctionPrototype(@1, $1.function, &$1.intermAggregate);
     }
     compound_statement_no_new_scope {
-        //?? Check that all paths return a value if return type != void ?
-        //   May be best done as post process phase on intermediate code
-        if (context->getCurrentFunctionType()->getBasicType() != EbtVoid && !context->getFunctionReturnsValue()) {
-            context->error(@1, "function does not return a value:", "", $1.function->getName().c_str());
-            context->recover();
-        }
-        
-        $$ = context->intermediate.growAggregate($1.intermAggregate, $3, @$);
-        context->intermediate.setAggregateOperator($$, EOpFunction, @1);
-        $$->getAsAggregate()->setName($1.function->getMangledName().c_str());
-        $$->getAsAggregate()->setType($1.function->getReturnType());
-        $$->getAsAggregate()->setFunctionId($1.function->getUniqueId());
-
-        context->symbolTable.pop();
+        $$ = context->addFunctionDefinition(*($1.function), $1.intermAggregate, $3, @1);
     }
     ;
 
 %%
 
 int glslang_parse(TParseContext* context) {
     return yyparse(context, context->getScanner());
 }
--- a/gfx/angle/src/compiler/translator/glslang_tab.cpp
+++ b/gfx/angle/src/compiler/translator/glslang_tab.cpp
@@ -697,36 +697,36 @@ static const yytype_uint16 yyrline[] =
        0,   212,   212,   213,   216,   226,   229,   234,   239,   244,
      249,   255,   258,   261,   264,   267,   270,   276,   284,   295,
      299,   307,   310,   316,   320,   327,   333,   342,   350,   356,
      363,   373,   376,   379,   382,   392,   393,   394,   395,   403,
      404,   407,   410,   417,   418,   421,   427,   428,   432,   439,
      440,   443,   446,   449,   455,   456,   459,   465,   466,   473,
      474,   481,   482,   489,   490,   496,   497,   503,   504,   510,
      511,   517,   518,   526,   527,   528,   529,   533,   534,   535,
-     539,   543,   547,   551,   558,   561,   567,   575,   583,   611,
-     617,   628,   632,   636,   640,   647,   653,   656,   663,   671,
-     692,   719,   729,   757,   762,   772,   777,   787,   790,   793,
-     796,   802,   809,   812,   816,   820,   825,   830,   837,   841,
-     845,   849,   854,   859,   863,   870,   880,   886,   889,   895,
-     901,   908,   917,   927,   935,   938,   945,   949,   953,   958,
-     966,   969,   973,   977,   986,   995,  1003,  1013,  1025,  1028,
-    1031,  1037,  1044,  1047,  1053,  1056,  1059,  1065,  1068,  1073,
-    1088,  1092,  1096,  1100,  1104,  1108,  1113,  1118,  1123,  1128,
-    1133,  1138,  1143,  1148,  1153,  1158,  1163,  1168,  1173,  1178,
-    1183,  1188,  1193,  1198,  1203,  1208,  1213,  1217,  1221,  1225,
-    1229,  1233,  1237,  1241,  1245,  1249,  1253,  1257,  1261,  1265,
-    1269,  1273,  1281,  1289,  1293,  1306,  1306,  1309,  1309,  1315,
-    1318,  1334,  1337,  1346,  1350,  1356,  1363,  1378,  1382,  1386,
-    1387,  1393,  1394,  1395,  1396,  1397,  1398,  1399,  1403,  1404,
-    1404,  1404,  1414,  1415,  1419,  1419,  1420,  1420,  1425,  1428,
-    1438,  1441,  1447,  1448,  1452,  1460,  1464,  1471,  1471,  1478,
-    1481,  1488,  1493,  1508,  1508,  1513,  1513,  1520,  1520,  1528,
-    1531,  1537,  1540,  1546,  1550,  1557,  1560,  1563,  1566,  1569,
-    1578,  1582,  1589,  1592,  1598,  1598
+     539,   543,   547,   551,   558,   561,   567,   575,   583,   586,
+     592,   603,   607,   611,   615,   622,   628,   631,   638,   646,
+     667,   694,   704,   732,   737,   747,   752,   762,   765,   768,
+     771,   777,   784,   787,   791,   795,   800,   805,   812,   816,
+     820,   824,   829,   834,   838,   845,   855,   861,   864,   870,
+     876,   883,   892,   902,   910,   913,   920,   924,   928,   933,
+     941,   944,   948,   952,   961,   970,   978,   988,  1000,  1003,
+    1006,  1012,  1019,  1022,  1028,  1031,  1034,  1040,  1043,  1048,
+    1063,  1067,  1071,  1075,  1079,  1083,  1088,  1093,  1098,  1103,
+    1108,  1113,  1118,  1123,  1128,  1133,  1138,  1143,  1148,  1153,
+    1158,  1163,  1168,  1173,  1178,  1183,  1188,  1192,  1196,  1200,
+    1204,  1208,  1212,  1216,  1220,  1224,  1228,  1232,  1236,  1240,
+    1244,  1248,  1256,  1264,  1268,  1281,  1281,  1284,  1284,  1290,
+    1293,  1309,  1312,  1321,  1325,  1331,  1338,  1353,  1357,  1361,
+    1362,  1368,  1369,  1370,  1371,  1372,  1373,  1374,  1378,  1379,
+    1379,  1379,  1389,  1390,  1394,  1394,  1395,  1395,  1400,  1403,
+    1413,  1416,  1422,  1423,  1427,  1435,  1439,  1446,  1446,  1453,
+    1456,  1463,  1468,  1483,  1483,  1488,  1488,  1495,  1495,  1503,
+    1506,  1512,  1515,  1521,  1525,  1532,  1535,  1538,  1541,  1544,
+    1553,  1557,  1564,  1567,  1573,  1573
 };
 #endif
 
 #if YYDEBUG || YYERROR_VERBOSE || 0
 /* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
    First, the terminals, then, starting at YYNTOKENS, nonterminals.  */
 static const char *const yytname[] =
 {
@@ -3043,42 +3043,17 @@ yyreduce:
         (yyval.lex) = (yyvsp[-1].lex);
     }
 
     break;
 
   case 88:
 
     {
-        TFunction &function = *((yyvsp[-1].interm).function);
-        
-        TIntermAggregate *prototype = new TIntermAggregate;
-        prototype->setType(function.getReturnType());
-        prototype->setName(function.getMangledName());
-        prototype->setFunctionId(function.getUniqueId());
-        
-        for (size_t i = 0; i < function.getParamCount(); i++)
-        {
-            const TConstParameter &param = function.getParam(i);
-            if (param.name != 0)
-            {
-                TVariable variable(param.name, *param.type);
-                
-                prototype = context->intermediate.growAggregate(prototype, context->intermediate.addSymbol(variable.getUniqueId(), variable.getName(), variable.getType(), (yylsp[-1])), (yylsp[-1]));
-            }
-            else
-            {
-                prototype = context->intermediate.growAggregate(prototype, context->intermediate.addSymbol(0, "", *param.type, (yylsp[-1])), (yylsp[-1]));
-            }
-        }
-        
-        prototype->setOp(EOpPrototype);
-        (yyval.interm.intermNode) = prototype;
-
-        context->symbolTable.pop();
+        (yyval.interm.intermNode) = context->addFunctionPrototypeDeclaration(*((yyvsp[-1].interm).function), (yylsp[-1]));
     }
 
     break;
 
   case 89:
 
     {
         TIntermAggregate *aggNode = (yyvsp[-1].interm).intermAggregate;
@@ -4483,17 +4458,17 @@ yyreduce:
         }
         (yyval.interm.intermAggregate) = (yyvsp[-2].interm.intermAggregate);
     }
 
     break;
 
   case 232:
 
-    { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); }
+    { (yyval.interm.intermNode) = (yyvsp[0].interm.intermAggregate); }
 
     break;
 
   case 233:
 
     { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); }
 
     break;
@@ -4501,17 +4476,17 @@ yyreduce:
   case 234:
 
     { context->symbolTable.push(); }
 
     break;
 
   case 235:
 
-    { context->symbolTable.pop(); (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); }
+    { context->symbolTable.pop(); (yyval.interm.intermNode) = (yyvsp[0].interm.intermAggregate); }
 
     break;
 
   case 236:
 
     { context->symbolTable.push(); }
 
     break;
@@ -4520,29 +4495,29 @@ yyreduce:
 
     { context->symbolTable.pop(); (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); }
 
     break;
 
   case 238:
 
     {
-        (yyval.interm.intermNode) = 0;
+        (yyval.interm.intermAggregate) = 0;
     }
 
     break;
 
   case 239:
 
     {
         if ((yyvsp[-1].interm.intermAggregate)) {
             (yyvsp[-1].interm.intermAggregate)->setOp(EOpSequence);
             (yyvsp[-1].interm.intermAggregate)->setLine((yyloc));
         }
-        (yyval.interm.intermNode) = (yyvsp[-1].interm.intermAggregate);
+        (yyval.interm.intermAggregate) = (yyvsp[-1].interm.intermAggregate);
     }
 
     break;
 
   case 240:
 
     {
         (yyval.interm.intermAggregate) = context->intermediate.makeAggregate((yyvsp[0].interm.intermNode), (yyloc));
@@ -4837,30 +4812,17 @@ yyreduce:
         context->parseFunctionPrototype((yylsp[0]), (yyvsp[0].interm).function, &(yyvsp[0].interm).intermAggregate);
     }
 
     break;
 
   case 275:
 
     {
-        //?? Check that all paths return a value if return type != void ?
-        //   May be best done as post process phase on intermediate code
-        if (context->getCurrentFunctionType()->getBasicType() != EbtVoid && !context->getFunctionReturnsValue()) {
-            context->error((yylsp[-2]), "function does not return a value:", "", (yyvsp[-2].interm).function->getName().c_str());
-            context->recover();
-        }
-        
-        (yyval.interm.intermNode) = context->intermediate.growAggregate((yyvsp[-2].interm).intermAggregate, (yyvsp[0].interm.intermNode), (yyloc));
-        context->intermediate.setAggregateOperator((yyval.interm.intermNode), EOpFunction, (yylsp[-2]));
-        (yyval.interm.intermNode)->getAsAggregate()->setName((yyvsp[-2].interm).function->getMangledName().c_str());
-        (yyval.interm.intermNode)->getAsAggregate()->setType((yyvsp[-2].interm).function->getReturnType());
-        (yyval.interm.intermNode)->getAsAggregate()->setFunctionId((yyvsp[-2].interm).function->getUniqueId());
-
-        context->symbolTable.pop();
+        (yyval.interm.intermNode) = context->addFunctionDefinition(*((yyvsp[-2].interm).function), (yyvsp[-2].interm).intermAggregate, (yyvsp[0].interm.intermAggregate), (yylsp[-2]));
     }
 
     break;
 
 
 
       default: break;
     }
--- a/gfx/angle/src/compiler/translator/timing/RestrictFragmentShaderTiming.cpp
+++ b/gfx/angle/src/compiler/translator/timing/RestrictFragmentShaderTiming.cpp
@@ -49,33 +49,27 @@ void RestrictFragmentShaderTiming::enfor
     mNumErrors = 0;
 
     // FIXME(mvujovic): The dependency graph does not support user defined function calls right now,
     // so we generate errors for them.
     validateUserDefinedFunctionCallUsage(graph);
 
     // Starting from each sampler, traverse the dependency graph and generate an error each time we
     // hit a node where sampler dependent values are not allowed.
-    for (TGraphSymbolVector::const_iterator iter = graph.beginSamplerSymbols();
-         iter != graph.endSamplerSymbols();
-         ++iter)
+    for (auto samplerSymbol : graph.samplerSymbols())
     {
-        TGraphSymbol* samplerSymbol = *iter;
         clearVisited();
         samplerSymbol->traverse(this);
     }
 }
 
 void RestrictFragmentShaderTiming::validateUserDefinedFunctionCallUsage(const TDependencyGraph& graph)
 {
-    for (TFunctionCallVector::const_iterator iter = graph.beginUserDefinedFunctionCalls();
-         iter != graph.endUserDefinedFunctionCalls();
-         ++iter)
+    for (const auto* functionCall : graph.userDefinedFunctionCalls())
     {
-        TGraphFunctionCall* functionCall = *iter;
         beginError(functionCall->getIntermFunctionCall());
         mSink << "A call to a user defined function is not permitted.\n";
     }
 }
 
 void RestrictFragmentShaderTiming::beginError(const TIntermNode* node)
 {
     ++mNumErrors;
--- a/gfx/angle/src/libANGLE/Buffer.cpp
+++ b/gfx/angle/src/libANGLE/Buffer.cpp
@@ -13,32 +13,43 @@
 #include "libANGLE/renderer/Renderer.h"
 
 namespace gl
 {
 
 Buffer::Buffer(rx::BufferImpl *impl, GLuint id)
     : RefCountObject(id),
       mBuffer(impl),
+      mLabel(),
       mUsage(GL_STATIC_DRAW),
       mSize(0),
       mAccessFlags(0),
       mAccess(GL_WRITE_ONLY_OES),
       mMapped(GL_FALSE),
       mMapPointer(NULL),
       mMapOffset(0),
       mMapLength(0)
 {
 }
 
 Buffer::~Buffer()
 {
     SafeDelete(mBuffer);
 }
 
+void Buffer::setLabel(const std::string &label)
+{
+    mLabel = label;
+}
+
+const std::string &Buffer::getLabel() const
+{
+    return mLabel;
+}
+
 Error Buffer::bufferData(const void *data, GLsizeiptr size, GLenum usage)
 {
     gl::Error error = mBuffer->setData(data, size, usage);
     if (error.isError())
     {
         return error;
     }
 
--- a/gfx/angle/src/libANGLE/Buffer.h
+++ b/gfx/angle/src/libANGLE/Buffer.h
@@ -7,34 +7,37 @@
 // Buffer.h: Defines the gl::Buffer class, representing storage of vertex and/or
 // index data. Implements GL buffer objects and related functionality.
 // [OpenGL ES 2.0.24] section 2.9 page 21.
 
 #ifndef LIBANGLE_BUFFER_H_
 #define LIBANGLE_BUFFER_H_
 
 #include "common/angleutils.h"
+#include "libANGLE/Debug.h"
 #include "libANGLE/Error.h"
 #include "libANGLE/IndexRangeCache.h"
 #include "libANGLE/RefCountObject.h"
 
 namespace rx
 {
 class BufferImpl;
 };
 
 namespace gl
 {
 
-class Buffer : public RefCountObject
+class Buffer final : public RefCountObject, public LabeledObject
 {
   public:
     Buffer(rx::BufferImpl *impl, GLuint id);
+    virtual ~Buffer();
 
-    virtual ~Buffer();
+    void setLabel(const std::string &label) override;
+    const std::string &getLabel() const override;
 
     Error bufferData(const void *data, GLsizeiptr size, GLenum usage);
     Error bufferSubData(const void *data, GLsizeiptr size, GLintptr offset);
     Error copyBufferSubData(Buffer* source, GLintptr sourceOffset, GLintptr destOffset, GLsizeiptr size);
     Error map(GLenum access);
     Error mapRange(GLintptr offset, GLsizeiptr length, GLbitfield access);
     Error unmap(GLboolean *result);
 
@@ -56,16 +59,18 @@ class Buffer : public RefCountObject
     GLint64 getMapLength() const { return mMapLength; }
     GLint64 getSize() const { return mSize; }
 
     rx::BufferImpl *getImplementation() const { return mBuffer; }
 
   private:
     rx::BufferImpl *mBuffer;
 
+    std::string mLabel;
+
     GLenum mUsage;
     GLint64 mSize;
     GLbitfield mAccessFlags;
     GLenum mAccess;
     GLboolean mMapped;
     GLvoid *mMapPointer;
     GLint64 mMapOffset;
     GLint64 mMapLength;
--- a/gfx/angle/src/libANGLE/Caps.cpp
+++ b/gfx/angle/src/libANGLE/Caps.cpp
@@ -97,16 +97,17 @@ Extensions::Extensions()
       packedDepthStencil(false),
       getProgramBinary(false),
       rgb8rgba8(false),
       textureFormatBGRA8888(false),
       readFormatBGRA(false),
       pixelBufferObject(false),
       mapBuffer(false),
       mapBufferRange(false),
+      colorBufferHalfFloat(false),
       textureHalfFloat(false),
       textureHalfFloatLinear(false),
       textureFloat(false),
       textureFloatLinear(false),
       textureRG(false),
       textureCompressionDXT1(false),
       textureCompressionDXT3(false),
       textureCompressionDXT5(false),
@@ -118,16 +119,19 @@ Extensions::Extensions()
       textureStorage(false),
       textureNPOT(false),
       drawBuffers(false),
       textureFilterAnisotropic(false),
       maxTextureAnisotropy(false),
       occlusionQueryBoolean(false),
       fence(false),
       timerQuery(false),
+      disjointTimerQuery(false),
+      queryCounterBitsTimeElapsed(0),
+      queryCounterBitsTimestamp(0),
       robustness(false),
       blendMinMax(false),
       framebufferBlit(false),
       framebufferMultisample(false),
       instancedArrays(false),
       packReverseRowOrder(false),
       standardDerivatives(false),
       shaderTextureLOD(false),
@@ -141,16 +145,23 @@ Extensions::Extensions()
       discardFramebuffer(false),
       debugMarker(false),
       eglImage(false),
       eglImageExternal(false),
       eglImageExternalEssl3(false),
       unpackSubimage(false),
       packSubimage(false),
       vertexArrayObject(false),
+      debug(false),
+      maxDebugMessageLength(0),
+      maxDebugLoggedMessages(0),
+      maxDebugGroupStackDepth(0),
+      maxLabelLength(0),
+      noError(false),
+      lossyETCDecode(false),
       colorBufferFloat(false)
 {
 }
 
 std::vector<std::string> Extensions::getStrings() const
 {
     std::vector<std::string> extensionStrings;
 
@@ -160,16 +171,17 @@ std::vector<std::string> Extensions::get
     InsertExtensionString("GL_OES_packed_depth_stencil",         packedDepthStencil,        &extensionStrings);
     InsertExtensionString("GL_OES_get_program_binary",           getProgramBinary,          &extensionStrings);
     InsertExtensionString("GL_OES_rgb8_rgba8",                   rgb8rgba8,                 &extensionStrings);
     InsertExtensionString("GL_EXT_texture_format_BGRA8888",      textureFormatBGRA8888,     &extensionStrings);
     InsertExtensionString("GL_EXT_read_format_bgra",             readFormatBGRA,            &extensionStrings);
     InsertExtensionString("GL_NV_pixel_buffer_object",           pixelBufferObject,         &extensionStrings);
     InsertExtensionString("GL_OES_mapbuffer",                    mapBuffer,                 &extensionStrings);
     InsertExtensionString("GL_EXT_map_buffer_range",             mapBufferRange,            &extensionStrings);
+    InsertExtensionString("GL_EXT_color_buffer_half_float",      colorBufferHalfFloat,      &extensionStrings);
     InsertExtensionString("GL_OES_texture_half_float",           textureHalfFloat,          &extensionStrings);
     InsertExtensionString("GL_OES_texture_half_float_linear",    textureHalfFloatLinear,    &extensionStrings);
     InsertExtensionString("GL_OES_texture_float",                textureFloat,              &extensionStrings);
     InsertExtensionString("GL_OES_texture_float_linear",         textureFloatLinear,        &extensionStrings);
     InsertExtensionString("GL_EXT_texture_rg",                   textureRG,                 &extensionStrings);
     InsertExtensionString("GL_EXT_texture_compression_dxt1",     textureCompressionDXT1,    &extensionStrings);
     InsertExtensionString("GL_ANGLE_texture_compression_dxt3",   textureCompressionDXT3,    &extensionStrings);
     InsertExtensionString("GL_ANGLE_texture_compression_dxt5",   textureCompressionDXT5,    &extensionStrings);
@@ -181,16 +193,17 @@ std::vector<std::string> Extensions::get
     InsertExtensionString("GL_OES_depth32",                      depth32,                   &extensionStrings);
     InsertExtensionString("GL_EXT_texture_storage",              textureStorage,            &extensionStrings);
     InsertExtensionString("GL_OES_texture_npot",                 textureNPOT,               &extensionStrings);
     InsertExtensionString("GL_EXT_draw_buffers",                 drawBuffers,               &extensionStrings);
     InsertExtensionString("GL_EXT_texture_filter_anisotropic",   textureFilterAnisotropic,  &extensionStrings);
     InsertExtensionString("GL_EXT_occlusion_query_boolean",      occlusionQueryBoolean,     &extensionStrings);
     InsertExtensionString("GL_NV_fence",                         fence,                     &extensionStrings);
     InsertExtensionString("GL_ANGLE_timer_query",                timerQuery,                &extensionStrings);
+    InsertExtensionString("GL_EXT_disjoint_timer_query",         disjointTimerQuery,        &extensionStrings);
     InsertExtensionString("GL_EXT_robustness",                   robustness,                &extensionStrings);
     InsertExtensionString("GL_EXT_blend_minmax",                 blendMinMax,               &extensionStrings);
     InsertExtensionString("GL_ANGLE_framebuffer_blit",           framebufferBlit,           &extensionStrings);
     InsertExtensionString("GL_ANGLE_framebuffer_multisample",    framebufferMultisample,    &extensionStrings);
     InsertExtensionString("GL_ANGLE_instanced_arrays",           instancedArrays,           &extensionStrings);
     InsertExtensionString("GL_ANGLE_pack_reverse_row_order",     packReverseRowOrder,       &extensionStrings);
     InsertExtensionString("GL_OES_standard_derivatives",         standardDerivatives,       &extensionStrings);
     InsertExtensionString("GL_EXT_shader_texture_lod",           shaderTextureLOD,          &extensionStrings);
@@ -205,16 +218,21 @@ std::vector<std::string> Extensions::get
     InsertExtensionString("GL_EXT_debug_marker",                 debugMarker,               &extensionStrings);
     InsertExtensionString("GL_OES_EGL_image",                    eglImage,                  &extensionStrings);
     InsertExtensionString("GL_OES_EGL_image_external",           eglImageExternal,          &extensionStrings);
     InsertExtensionString("GL_OES_EGL_image_external_essl3",     eglImageExternalEssl3,     &extensionStrings);
     InsertExtensionString("GL_EXT_unpack_subimage",              unpackSubimage,            &extensionStrings);
     InsertExtensionString("GL_NV_pack_subimage",                 packSubimage,              &extensionStrings);
     InsertExtensionString("GL_EXT_color_buffer_float",           colorBufferFloat,          &extensionStrings);
     InsertExtensionString("GL_OES_vertex_array_object",          vertexArrayObject,         &extensionStrings);
+    InsertExtensionString("GL_KHR_debug",                        debug,                     &extensionStrings);
+    // TODO(jmadill): Enable this when complete.
+    //InsertExtensionString("GL_KHR_no_error",                     noError,                   &extensionStrings);
+
+    InsertExtensionString("GL_ANGLE_lossy_etc_decode",           lossyETCDecode,            &extensionStrings);
     // clang-format on
 
     return extensionStrings;
 }
 
 Limitations::Limitations()
     : noFrontFacingSupport(false),
       noSampleAlphaToCoverageSupport(false),
@@ -274,16 +292,28 @@ static bool DetermineRGB8AndRGBA8Texture
 static bool DetermineBGRA8TextureSupport(const TextureCapsMap &textureCaps)
 {
     std::vector<GLenum> requiredFormats;
     requiredFormats.push_back(GL_BGRA8_EXT);
 
     return GetFormatSupport(textureCaps, requiredFormats, true, true, true);
 }
 
+// Checks for GL_OES_color_buffer_half_float support
+static bool DetermineColorBufferHalfFloatSupport(const TextureCapsMap &textureCaps)
+{
+    std::vector<GLenum> requiredFormats;
+    requiredFormats.push_back(GL_RGBA16F);
+    requiredFormats.push_back(GL_RGB16F);
+    requiredFormats.push_back(GL_RG16F);
+    requiredFormats.push_back(GL_R16F);
+
+    return GetFormatSupport(textureCaps, requiredFormats, true, false, true);
+}
+
 // Checks for GL_OES_texture_half_float support
 static bool DetermineHalfFloatTextureSupport(const TextureCapsMap &textureCaps)
 {
     std::vector<GLenum> requiredFormats;
     requiredFormats.push_back(GL_RGB16F);
     requiredFormats.push_back(GL_RGBA16F);
 
     return GetFormatSupport(textureCaps, requiredFormats, true, false, true);
@@ -291,17 +321,18 @@ static bool DetermineHalfFloatTextureSup
 
 // Checks for GL_OES_texture_half_float_linear support
 static bool DetermineHalfFloatTextureFilteringSupport(const TextureCapsMap &textureCaps)
 {
     std::vector<GLenum> requiredFormats;
     requiredFormats.push_back(GL_RGB16F);
     requiredFormats.push_back(GL_RGBA16F);
 
-    return GetFormatSupport(textureCaps, requiredFormats, true, true, false);
+    return DetermineHalfFloatTextureSupport(textureCaps) &&
+           GetFormatSupport(textureCaps, requiredFormats, true, true, false);
 }
 
 // Checks for GL_OES_texture_float support
 static bool DetermineFloatTextureSupport(const TextureCapsMap &textureCaps)
 {
     std::vector<GLenum> requiredFormats;
     requiredFormats.push_back(GL_RGB32F);
     requiredFormats.push_back(GL_RGBA32F);
@@ -311,17 +342,18 @@ static bool DetermineFloatTextureSupport
 
 // Checks for GL_OES_texture_float_linear support
 static bool DetermineFloatTextureFilteringSupport(const TextureCapsMap &textureCaps)
 {
     std::vector<GLenum> requiredFormats;
     requiredFormats.push_back(GL_RGB32F);
     requiredFormats.push_back(GL_RGBA32F);
 
-    return GetFormatSupport(textureCaps, requiredFormats, true, true, false);
+    return DetermineFloatTextureSupport(textureCaps) &&
+           GetFormatSupport(textureCaps, requiredFormats, true, true, false);
 }
 
 // Checks for GL_EXT_texture_rg support
 static bool DetermineRGTextureSupport(const TextureCapsMap &textureCaps, bool checkHalfFloatFormats, bool checkFloatFormats)
 {
     std::vector<GLenum> requiredFormats;
     requiredFormats.push_back(GL_R8);
     requiredFormats.push_back(GL_RG8);
@@ -461,16 +493,17 @@ static bool DetermineColorBufferFloatSup
     return GetFormatSupport(textureCaps, requiredFormats, true, false, true);
 }
 
 void Extensions::setTextureExtensionSupport(const TextureCapsMap &textureCaps)
 {
     packedDepthStencil = DeterminePackedDepthStencilSupport(textureCaps);
     rgb8rgba8 = DetermineRGB8AndRGBA8TextureSupport(textureCaps);
     textureFormatBGRA8888 = DetermineBGRA8TextureSupport(textureCaps);
+    colorBufferHalfFloat      = DetermineColorBufferHalfFloatSupport(textureCaps);
     textureHalfFloat = DetermineHalfFloatTextureSupport(textureCaps);
     textureHalfFloatLinear = DetermineHalfFloatTextureFilteringSupport(textureCaps);
     textureFloat = DetermineFloatTextureSupport(textureCaps);
     textureFloatLinear = DetermineFloatTextureFilteringSupport(textureCaps);
     textureRG = DetermineRGTextureSupport(textureCaps, textureHalfFloat, textureFloat);
     textureCompressionDXT1 = DetermineDXT1TextureSupport(textureCaps);
     textureCompressionDXT3 = DetermineDXT3TextureSupport(textureCaps);
     textureCompressionDXT5 = DetermineDXT5TextureSupport(textureCaps);
@@ -583,53 +616,62 @@ Caps::Caps()
 
 DisplayExtensions::DisplayExtensions()
     : createContextRobustness(false),
       d3dShareHandleClientBuffer(false),
       surfaceD3DTexture2DShareHandle(false),
       querySurfacePointer(false),
       windowFixedSize(false),
       keyedMutex(false),
+      surfaceOrientation(false),
       postSubBuffer(false),
       createContext(false),
       deviceQuery(false),
       image(false),
       imageBase(false),
       imagePixmap(false),
       glTexture2DImage(false),
       glTextureCubemapImage(false),
       glTexture3DImage(false),
       glRenderbufferImage(false),
-      getAllProcAddresses(false)
+      getAllProcAddresses(false),
+      flexibleSurfaceCompatibility(false),
+      directComposition(false),
+      createContextNoError(false)
 {
 }
 
 std::vector<std::string> DisplayExtensions::getStrings() const
 {
     std::vector<std::string> extensionStrings;
 
     // clang-format off
     //                   | Extension name                                 | Supported flag                | Output vector   |
     InsertExtensionString("EGL_EXT_create_context_robustness",             createContextRobustness,        &extensionStrings);
     InsertExtensionString("EGL_ANGLE_d3d_share_handle_client_buffer",      d3dShareHandleClientBuffer,     &extensionStrings);
     InsertExtensionString("EGL_ANGLE_surface_d3d_texture_2d_share_handle", surfaceD3DTexture2DShareHandle, &extensionStrings);
     InsertExtensionString("EGL_ANGLE_query_surface_pointer",               querySurfacePointer,            &extensionStrings);
     InsertExtensionString("EGL_ANGLE_window_fixed_size",                   windowFixedSize,                &extensionStrings);
     InsertExtensionString("EGL_ANGLE_keyed_mutex",                         keyedMutex,                     &extensionStrings);
+    InsertExtensionString("EGL_ANGLE_surface_orientation",                 surfaceOrientation,             &extensionStrings);
+    InsertExtensionString("EGL_ANGLE_direct_composition",                  directComposition,              &extensionStrings);
     InsertExtensionString("EGL_NV_post_sub_buffer",                        postSubBuffer,                  &extensionStrings);
     InsertExtensionString("EGL_KHR_create_context",                        createContext,                  &extensionStrings);
     InsertExtensionString("EGL_EXT_device_query",                          deviceQuery,                    &extensionStrings);
     InsertExtensionString("EGL_KHR_image",                                 image,                          &extensionStrings);
     InsertExtensionString("EGL_KHR_image_base",                            imageBase,                      &extensionStrings);
     InsertExtensionString("EGL_KHR_image_pixmap",                          imagePixmap,                    &extensionStrings);
     InsertExtensionString("EGL_KHR_gl_texture_2D_image",                   glTexture2DImage,               &extensionStrings);
     InsertExtensionString("EGL_KHR_gl_texture_cubemap_image",              glTextureCubemapImage,          &extensionStrings);
     InsertExtensionString("EGL_KHR_gl_texture_3D_image",                   glTexture3DImage,               &extensionStrings);
     InsertExtensionString("EGL_KHR_gl_renderbuffer_image",                 glRenderbufferImage,            &extensionStrings);
     InsertExtensionString("EGL_KHR_get_all_proc_addresses",                getAllProcAddresses,            &extensionStrings);
+    InsertExtensionString("EGL_ANGLE_flexible_surface_compatibility",      flexibleSurfaceCompatibility,   &extensionStrings);
+    // TODO(jmadill): Enable this when complete.
+    //InsertExtensionString("KHR_create_context_no_error",                   createContextNoError,           &extensionStrings);
     // clang-format on
 
     return extensionStrings;
 }
 
 DeviceExtensions::DeviceExtensions()
     : deviceD3D(false)
 {
@@ -650,16 +692,17 @@ ClientExtensions::ClientExtensions()
       platformBase(false),
       platformDevice(false),
       platformANGLE(false),
       platformANGLED3D(false),
       platformANGLEOpenGL(false),
       deviceCreation(false),
       deviceCreationD3D11(false),
       x11Visual(false),
+      experimentalPresentPath(false),
       clientGetAllProcAddresses(false)
 {
 }
 
 std::vector<std::string> ClientExtensions::getStrings() const
 {
     std::vector<std::string> extensionStrings;
 
@@ -669,15 +712,16 @@ std::vector<std::string> ClientExtension
     InsertExtensionString("EGL_EXT_platform_base",                 platformBase,              &extensionStrings);
     InsertExtensionString("EGL_EXT_platform_device",               platformDevice,            &extensionStrings);
     InsertExtensionString("EGL_ANGLE_platform_angle",              platformANGLE,             &extensionStrings);
     InsertExtensionString("EGL_ANGLE_platform_angle_d3d",          platformANGLED3D,          &extensionStrings);
     InsertExtensionString("EGL_ANGLE_platform_angle_opengl",       platformANGLEOpenGL,       &extensionStrings);
     InsertExtensionString("EGL_ANGLE_device_creation",             deviceCreation,            &extensionStrings);
     InsertExtensionString("EGL_ANGLE_device_creation_d3d11",       deviceCreationD3D11,       &extensionStrings);
     InsertExtensionString("EGL_ANGLE_x11_visual",                  x11Visual,                 &extensionStrings);
+    InsertExtensionString("EGL_ANGLE_experimental_present_path",   experimentalPresentPath,   &extensionStrings);
     InsertExtensionString("EGL_KHR_client_get_all_proc_addresses", clientGetAllProcAddresses, &extensionStrings);
     // clang-format on
 
     return extensionStrings;
 }
 
 }
--- a/gfx/angle/src/libANGLE/Caps.h
+++ b/gfx/angle/src/libANGLE/Caps.h
@@ -71,20 +71,22 @@ struct Extensions
     // Generate a vector of supported extension strings
     std::vector<std::string> getStrings() const;
 
     // Set all texture related extension support based on the supported textures.
     // Determines support for:
     // GL_OES_packed_depth_stencil
     // GL_OES_rgb8_rgba8
     // GL_EXT_texture_format_BGRA8888
+    // GL_EXT_color_buffer_half_float,
     // GL_OES_texture_half_float, GL_OES_texture_half_float_linear
     // GL_OES_texture_float, GL_OES_texture_float_linear
     // GL_EXT_texture_rg
-    // GL_EXT_texture_compression_dxt1, GL_ANGLE_texture_compression_dxt3, GL_ANGLE_texture_compression_dxt5
+    // GL_EXT_texture_compression_dxt1, GL_ANGLE_texture_compression_dxt3,
+    // GL_ANGLE_texture_compression_dxt5
     // GL_KHR_texture_compression_astc_hdr, GL_KHR_texture_compression_astc_ldr
     // GL_OES_compressed_ETC1_RGB8_texture
     // GL_EXT_sRGB
     // GL_ANGLE_depth_texture, GL_OES_depth32
     // GL_EXT_color_buffer_float
     void setTextureExtensionSupport(const TextureCapsMap &textureCaps);
 
     // ES2 Extension support
@@ -111,16 +113,21 @@ struct Extensions
 
     // GL_NV_pixel_buffer_object
     bool pixelBufferObject;
 
     // GL_OES_mapbuffer and GL_EXT_map_buffer_range
     bool mapBuffer;
     bool mapBufferRange;
 
+    // GL_EXT_color_buffer_half_float
+    // Together with GL_OES_texture_half_float in a GLES 2.0 context, implies that half-float
+    // textures are renderable.
+    bool colorBufferHalfFloat;
+
     // GL_OES_texture_half_float and GL_OES_texture_half_float_linear
     // Implies that TextureCaps for GL_RGB16F, GL_RGBA16F, GL_ALPHA32F_EXT, GL_LUMINANCE32F_EXT and
     // GL_LUMINANCE_ALPHA32F_EXT exist
     bool textureHalfFloat;
     bool textureHalfFloatLinear;
 
     // GL_OES_texture_float and GL_OES_texture_float_linear
     // Implies that TextureCaps for GL_RGB32F, GL_RGBA32F, GL_ALPHA16F_EXT, GL_LUMINANCE16F_EXT and
@@ -179,16 +186,21 @@ struct Extensions
     bool occlusionQueryBoolean;
 
     // GL_NV_fence
     bool fence;
 
     // GL_ANGLE_timer_query
     bool timerQuery;
 
+    // GL_EXT_disjoint_timer_query
+    bool disjointTimerQuery;
+    GLuint queryCounterBitsTimeElapsed;
+    GLuint queryCounterBitsTimestamp;
+
     // GL_EXT_robustness
     bool robustness;
 
     // GL_EXT_blend_minmax
     bool blendMinMax;
 
     // GL_ANGLE_framebuffer_blit
     bool framebufferBlit;
@@ -248,16 +260,29 @@ struct Extensions
     bool unpackSubimage;
 
     // NV_pack_subimage
     bool packSubimage;
 
     // GL_OES_vertex_array_object
     bool vertexArrayObject;
 
+    // GL_KHR_debug
+    bool debug;
+    GLuint maxDebugMessageLength;
+    GLuint maxDebugLoggedMessages;
+    GLuint maxDebugGroupStackDepth;
+    GLuint maxLabelLength;
+
+    // KHR_no_error
+    bool noError;
+
+    // GL_ANGLE_lossy_etc_decode
+    bool lossyETCDecode;
+
     // ES3 Extension support
 
     // GL_EXT_color_buffer_float
     bool colorBufferFloat;
 };
 
 struct Limitations
 {
@@ -408,16 +433,19 @@ struct DisplayExtensions
     bool querySurfacePointer;
 
     // EGL_ANGLE_window_fixed_size
     bool windowFixedSize;
 
     // EGL_ANGLE_keyed_mutex
     bool keyedMutex;
 
+    // EGL_ANGLE_surface_orientation
+    bool surfaceOrientation;
+
     // EGL_NV_post_sub_buffer
     bool postSubBuffer;
 
     // EGL_KHR_create_context
     bool createContext;
 
     // EGL_EXT_device_query
     bool deviceQuery;
@@ -440,16 +468,25 @@ struct DisplayExtensions
     // EGL_KHR_gl_texture_3D_image
     bool glTexture3DImage;
 
     // EGL_KHR_gl_renderbuffer_image
     bool glRenderbufferImage;
 
     // EGL_KHR_get_all_proc_addresses
     bool getAllProcAddresses;
+
+    // EGL_ANGLE_flexible_surface_compatibility
+    bool flexibleSurfaceCompatibility;
+
+    // EGL_ANGLE_direct_composition
+    bool directComposition;
+
+    // KHR_create_context_no_error
+    bool createContextNoError;
 };
 
 struct DeviceExtensions
 {
     DeviceExtensions();
 
     // Generate a vector of supported extension strings
     std::vector<std::string> getStrings() const;
@@ -487,15 +524,18 @@ struct ClientExtensions
     bool deviceCreation;
 
     // EGL_ANGLE_device_creation_d3d11
     bool deviceCreationD3D11;
 
     // EGL_ANGLE_x11_visual
     bool x11Visual;
 
+    // EGL_ANGLE_experimental_present_path
+    bool experimentalPresentPath;
+
     // EGL_KHR_client_get_all_proc_addresses
     bool clientGetAllProcAddresses;
 };
 
 }
 
 #endif // LIBANGLE_CAPS_H_
--- a/gfx/angle/src/libANGLE/Config.cpp
+++ b/gfx/angle/src/libANGLE/Config.cpp
@@ -52,17 +52,18 @@ Config::Config()
       renderableType(0),
       sampleBuffers(0),
       samples(0),
       stencilSize(0),
       surfaceType(0),
       transparentType(EGL_NONE),
       transparentRedValue(0),
       transparentGreenValue(0),
-      transparentBlueValue(0)
+      transparentBlueValue(0),
+      optimalOrientation(0)
 {
 }
 
 EGLint ConfigSet::add(const Config &config)
 {
     // Set the config's ID to a small number that starts at 1 ([EGL 1.5] section 3.4)
     EGLint id = static_cast<EGLint>(mConfigs.size()) + 1;
 
@@ -246,16 +247,19 @@ std::vector<const Config*> ConfigSet::fi
               case EGL_ALPHA_MASK_SIZE:           match = config.alphaMaskSize >= attributeValue;                     break;
               case EGL_COLOR_BUFFER_TYPE:         match = config.colorBufferType == (EGLenum)attributeValue;          break;
               case EGL_RENDERABLE_TYPE:           match = (config.renderableType & attributeValue) == attributeValue; break;
               case EGL_MATCH_NATIVE_PIXMAP:       match = false; UNIMPLEMENTED();                                     break;
               case EGL_CONFORMANT:                match = (config.conformant & attributeValue) == attributeValue;     break;
               case EGL_MAX_PBUFFER_WIDTH:         match = config.maxPBufferWidth >= attributeValue;                   break;
               case EGL_MAX_PBUFFER_HEIGHT:        match = config.maxPBufferHeight >= attributeValue;                  break;
               case EGL_MAX_PBUFFER_PIXELS:        match = config.maxPBufferPixels >= attributeValue;                  break;
+              case EGL_OPTIMAL_SURFACE_ORIENTATION_ANGLE:
+                  match = config.optimalOrientation == attributeValue;
+                  break;
               default: UNREACHABLE();
             }
 
             if (!match)
             {
                 break;
             }
         }
--- a/gfx/angle/src/libANGLE/Config.h
+++ b/gfx/angle/src/libANGLE/Config.h
@@ -59,16 +59,17 @@ struct Config
     EGLint sampleBuffers;           // Number of multisample buffers
     EGLint samples;                 // Number of samples per pixel
     EGLint stencilSize;             // Bits of Stencil in the stencil buffer
     EGLint surfaceType;             // Which types of EGL surfaces are supported.
     EGLenum transparentType;        // Type of transparency supported
     EGLint transparentRedValue;     // Transparent red value
     EGLint transparentGreenValue;   // Transparent green value
     EGLint transparentBlueValue;    // Transparent blue value
+    EGLint optimalOrientation;      // Optimal window surface orientation
 };
 
 class ConfigSet
 {
   public:
     EGLint add(const Config &config);
     const Config &get(EGLint id) const;
 
--- a/gfx/angle/src/libANGLE/Context.cpp
+++ b/gfx/angle/