merge mozilla-inbound to mozilla-central a=merge
authorCarsten "Tomcat" Book <cbook@mozilla.com>
Wed, 10 Feb 2016 11:47:34 +0100
changeset 283746 7042e8a19f94d6e075ec149567aea74dfd06c392
parent 283600 337331f990883ff125b1e764cb919d5029e9883b (current diff)
parent 283745 99bef2f7a333546e90de4a11094b1ab3f507dcfe (diff)
child 283747 31150215eedfe1406dbd92058635eb619e817939
child 283785 ac39fba33c6daf95b2cda71e588ca18e2eb752ab
child 283828 66b3222f623ffeb63aa20f30a89d25cc4bc8fbdb
push id17536
push usercbook@mozilla.com
push dateWed, 10 Feb 2016 13:30:18 +0000
treeherderfx-team@31150215eedf [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone47.0a1
merge mozilla-inbound to mozilla-central a=merge
build/msys-perl-wrapper
configure.in
gfx/skia/skia/include/core/SkDither.h
gfx/skia/skia/include/core/SkTDict.h
gfx/skia/skia/include/core/SkTSearch.h
gfx/skia/skia/include/effects/SkModeColorFilter.h
gfx/skia/skia/include/effects/SkRectShaderImageFilter.h
gfx/skia/skia/include/gpu/GrRect.h
gfx/skia/skia/include/pipe/SkGPipe.h
gfx/skia/skia/include/private/SkUtility.h
gfx/skia/skia/include/utils/SkCubicInterval.h
gfx/skia/skia/include/utils/SkCullPoints.h
gfx/skia/skia/include/utils/SkParsePaint.h
gfx/skia/skia/src/codec/SkCodec_libgif.cpp
gfx/skia/skia/src/codec/SkCodec_libgif.h
gfx/skia/skia/src/codec/SkCodec_libico.cpp
gfx/skia/skia/src/codec/SkCodec_libico.h
gfx/skia/skia/src/codec/SkCodec_wbmp.cpp
gfx/skia/skia/src/codec/SkCodec_wbmp.h
gfx/skia/skia/src/core/SkBitmapFilter.cpp
gfx/skia/skia/src/core/SkFilterShader.cpp
gfx/skia/skia/src/core/SkFilterShader.h
gfx/skia/skia/src/core/SkPx.h
gfx/skia/skia/src/effects/SkColorFilters.cpp
gfx/skia/skia/src/effects/SkRectShaderImageFilter.cpp
gfx/skia/skia/src/effects/gradients/SkRadialGradient_Table.h
gfx/skia/skia/src/gpu/GrAtlasTextBlob.cpp
gfx/skia/skia/src/gpu/GrAtlasTextBlob.h
gfx/skia/skia/src/gpu/GrAtlasTextContext.cpp
gfx/skia/skia/src/gpu/GrAtlasTextContext.h
gfx/skia/skia/src/gpu/GrBatchFontCache.cpp
gfx/skia/skia/src/gpu/GrBatchFontCache.h
gfx/skia/skia/src/gpu/GrFontScaler.cpp
gfx/skia/skia/src/gpu/GrFontScaler.h
gfx/skia/skia/src/gpu/GrStencilAndCoverTextContext.cpp
gfx/skia/skia/src/gpu/GrStencilAndCoverTextContext.h
gfx/skia/skia/src/gpu/GrTextBlobCache.cpp
gfx/skia/skia/src/gpu/GrTextBlobCache.h
gfx/skia/skia/src/gpu/GrTextContext.cpp
gfx/skia/skia/src/gpu/GrTextContext.h
gfx/skia/skia/src/gpu/gl/GrGLNameAllocator.cpp
gfx/skia/skia/src/gpu/gl/GrGLNameAllocator.h
gfx/skia/skia/src/opts/SkPx_neon.h
gfx/skia/skia/src/opts/SkPx_none.h
gfx/skia/skia/src/opts/SkPx_sse.h
gfx/skia/skia/src/pipe/SkGPipePriv.h
gfx/skia/skia/src/pipe/SkGPipeRead.cpp
gfx/skia/skia/src/pipe/SkGPipeWrite.cpp
gfx/skia/skia/src/pipe/utils/SamplePipeControllers.cpp
gfx/skia/skia/src/pipe/utils/SamplePipeControllers.h
gfx/skia/skia/src/ports/SkGlobalInitialization_chromium.cpp
gfx/skia/skia/src/utils/SkCubicInterval.cpp
gfx/skia/skia/src/utils/SkCullPoints.cpp
gfx/skia/skia/src/utils/android/SkAndroidSDKCanvas.cpp
gfx/skia/skia/src/utils/android/SkAndroidSDKCanvas.h
js/src/jit-test/tests/proxy/testDirectProxyEnumerate2.js
js/src/jit-test/tests/proxy/testDirectProxyEnumerate3.js
js/src/jit-test/tests/proxy/testDirectProxyEnumerate4.js
mobile/android/base/Makefile.in
mobile/android/tests/browser/robocop/robocop.ini
netwerk/protocol/http/HttpBaseChannel.cpp
netwerk/protocol/http/nsHttpChannel.cpp
testing/web-platform/meta/html/browsers/the-window-object/window-named-properties.html.ini
toolkit/components/satchel/test/browser/head.js
--- a/CLOBBER
+++ b/CLOBBER
@@ -17,10 +17,10 @@
 #
 # Modifying this file will now automatically clobber the buildbot machines \o/
 #
 
 # Are you updating CLOBBER because you think it's needed for your WebIDL
 # changes to stick? As of bug 928195, this shouldn't be necessary! Please
 # don't change CLOBBER for WebIDL changes any more.
 
-Bug 1237983 - Investigate and remove the Bagheera Client implementation.
+Bug 1246756 - Update Skia to m49 branch.
 
--- a/accessible/atk/moz.build
+++ b/accessible/atk/moz.build
@@ -47,11 +47,12 @@ if CONFIG['MOZ_ENABLE_GTK']:
     CFLAGS += CONFIG['TK_CFLAGS']
     CXXFLAGS += CONFIG['TK_CFLAGS']
 
 if CONFIG['MOZ_ENABLE_DBUS']:
     CXXFLAGS += CONFIG['MOZ_DBUS_CFLAGS']
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
-if CONFIG['CLANG_CXX']:
-    # Suppress clang warning about unused function from gobject's RTTI macros.
-    CXXFLAGS += ['-Wno-unused-function']
+if CONFIG['CLANG_CXX'] or CONFIG['GNU_CXX']:
+    # Used in G_DEFINE_TYPE_EXTENDED macro, probably fixed in newer glib /
+    # gobject headers. See bug 1243331 comment 3.
+    CXXFLAGS += ['-Wno-unused-local-typedefs']
--- a/addon-sdk/source/lib/sdk/preferences/service.js
+++ b/addon-sdk/source/lib/sdk/preferences/service.js
@@ -32,19 +32,16 @@ const Branch = function(branchName) {
     getOwnPropertyDescriptor(target, name, receiver) {
       return {
         configurable: true,
         enumerable: true,
         writable: false,
         value: this.get(target, name, receiver)
       };
     },
-    enumerate(target) {
-      return branchKeys(branchName)[Symbol.iterator]();
-    },
     ownKeys(target) {
       return branchKeys(branchName);
     },
     get(target, name, receiver) {
       return get(`${branchName}${name}`);
     },
     set(target, name, value, receiver) {
       set(`${branchName}${name}`, value);
--- a/browser/app/nsBrowserApp.cpp
+++ b/browser/app/nsBrowserApp.cpp
@@ -31,16 +31,17 @@
 
 #ifdef XP_WIN
 // we want a wmain entry point
 #ifdef MOZ_ASAN
 // ASAN requires firefox.exe to be built with -MD, and it's OK if we don't
 // support Windows XP SP2 in ASAN builds.
 #define XRE_DONT_SUPPORT_XPSP2
 #endif
+#define XRE_WANT_ENVIRON
 #include "nsWindowsWMain.cpp"
 #if defined(_MSC_VER) && (_MSC_VER < 1900)
 #define snprintf _snprintf
 #endif
 #define strcasecmp _stricmp
 #endif
 #include "BinaryPath.h"
 
@@ -118,29 +119,31 @@ static bool IsArg(const char* arg, const
 
 XRE_GetFileFromPathType XRE_GetFileFromPath;
 XRE_CreateAppDataType XRE_CreateAppData;
 XRE_FreeAppDataType XRE_FreeAppData;
 XRE_TelemetryAccumulateType XRE_TelemetryAccumulate;
 XRE_StartupTimelineRecordType XRE_StartupTimelineRecord;
 XRE_mainType XRE_main;
 XRE_StopLateWriteChecksType XRE_StopLateWriteChecks;
+XRE_XPCShellMainType XRE_XPCShellMain;
 
 static const nsDynamicFunctionLoad kXULFuncs[] = {
     { "XRE_GetFileFromPath", (NSFuncPtr*) &XRE_GetFileFromPath },
     { "XRE_CreateAppData", (NSFuncPtr*) &XRE_CreateAppData },
     { "XRE_FreeAppData", (NSFuncPtr*) &XRE_FreeAppData },
     { "XRE_TelemetryAccumulate", (NSFuncPtr*) &XRE_TelemetryAccumulate },
     { "XRE_StartupTimelineRecord", (NSFuncPtr*) &XRE_StartupTimelineRecord },
     { "XRE_main", (NSFuncPtr*) &XRE_main },
     { "XRE_StopLateWriteChecks", (NSFuncPtr*) &XRE_StopLateWriteChecks },
+    { "XRE_XPCShellMain", (NSFuncPtr*) &XRE_XPCShellMain },
     { nullptr, nullptr }
 };
 
-static int do_main(int argc, char* argv[], nsIFile *xreDirectory)
+static int do_main(int argc, char* argv[], char* envp[], nsIFile *xreDirectory)
 {
   nsCOMPtr<nsIFile> appini;
   nsresult rv;
   uint32_t mainFlags = 0;
 
   // Allow firefox.exe to launch XULRunner apps via -app <application.ini>
   // Note that -app must be the *first* argument.
   const char *appDataFile = getenv("XUL_APP_FILE");
@@ -167,16 +170,21 @@ static int do_main(int argc, char* argv[
     snprintf(appEnv, MAXPATHLEN, "XUL_APP_FILE=%s", argv[2]);
     if (putenv(appEnv)) {
       Output("Couldn't set %s.\n", appEnv);
       return 255;
     }
     argv[2] = argv[0];
     argv += 2;
     argc -= 2;
+  } else if (argc > 1 && IsArg(argv[1], "xpcshell")) {
+    for (int i = 1; i < argc; i++) {
+      argv[i] = argv[i + 1];
+    }
+    return XRE_XPCShellMain(--argc, argv, envp);
   }
 
   if (appini) {
     nsXREAppData *appData;
     rv = XRE_CreateAppData(appini, &appData);
     if (NS_FAILED(rv)) {
       Output("Couldn't read application.ini");
       return 255;
@@ -278,17 +286,17 @@ sizeof(XPCOM_DLL) - 1))
 #else
   rv = NS_NewNativeLocalFile(nsDependentCString(exePath), false,
                              xreDirectory);
 #endif
 
   return rv;
 }
 
-int main(int argc, char* argv[])
+int main(int argc, char* argv[], char* envp[])
 {
   mozilla::TimeStamp start = mozilla::TimeStamp::Now();
 
 #ifdef XP_MACOSX
   TriggerQuirks();
 #endif
 
   int gotCounters;
@@ -344,17 +352,17 @@ int main(int argc, char* argv[])
       XRE_TelemetryAccumulate(mozilla::Telemetry::GLUESTARTUP_HARD_FAULTS,
                               int(newRUsage.ru_majflt - initialRUsage.ru_majflt));
     }
 #else
   #error "Unknown platform"  // having this here keeps cppcheck happy
 #endif
   }
 
-  int result = do_main(argc, argv, xreDirectory);
+  int result = do_main(argc, argv, envp, xreDirectory);
 
   NS_LogTerm();
 
 #ifdef XP_MACOSX
   // Allow writes again. While we would like to catch writes from static
   // destructors to allow early exits to use _exit, we know that there is
   // at least one such write that we don't control (see bug 826029). For
   // now we enable writes again and early exits will have to use exit instead
--- a/browser/base/content/test/social/browser.ini
+++ b/browser/base/content/test/social/browser.ini
@@ -24,23 +24,20 @@ support-files =
   social_sidebar.html
   social_sidebar_empty.html
   social_window.html
   social_worker.js
   unchecked.jpg
 
 [browser_aboutHome_activation.js]
 [browser_addons.js]
-skip-if = e10s && debug # Leaking docshells (bug 1150147)
 [browser_blocklist.js]
-skip-if = e10s && debug # Leaking docshells (bug 1150147)
 [browser_share.js]
 skip-if = true # bug 1115131
 [browser_social_activation.js]
-skip-if = e10s && debug # e10s/Linux/Debug Leaking docshells (bug 1150147)
 [browser_social_chatwindow.js]
 skip-if = true # Bug 1245798 'document-element-inserted' is not fired for chat windows anymore, so no mozSocial
 [browser_social_chatwindow_resize.js]
 skip-if = true # Bug 1245798 'document-element-inserted' is not fired for chat windows anymore, so no mozSocial
 [browser_social_chatwindowfocus.js]
 skip-if = true # Bug 1245798 'document-element-inserted' is not fired for chat windows anymore, so no mozSocial
 [browser_social_contextmenu.js]
 skip-if = (os == 'linux' && e10s) # Bug 1072669 context menu relies on target element
--- a/browser/components/preferences/cookies.js
+++ b/browser/components/preferences/cookies.js
@@ -502,17 +502,17 @@ var gCookiesWindow = {
                                      date.getMinutes(),
                                      date.getSeconds());
     }
     return this._bundle.getString("expireAtEndOfSession");
   },
 
   _getUserContextString: function(aUserContextId) {
     if (parseInt(aUserContextId) == 0) {
-      return this._bundle.getString("noUserContextLabel");
+      return this._bundle.getString("defaultUserContextLabel");
     }
 
     return UserContextUI.getUserContextLabel(aUserContextId);
   },
 
   _updateCookieData: function (aItem) {
     var seln = this._view.selection;
     var ids = ["name", "value", "host", "path", "isSecure", "expires", "userContext"];
--- a/browser/locales/Makefile.in
+++ b/browser/locales/Makefile.in
@@ -199,11 +199,11 @@ endif
 l10n-check:: INNER_UNMAKE_PACKAGE=true
 l10n-check::
 	$(RM) -rf x-test
 	$(NSINSTALL) -D x-test/toolkit
 	echo '#define MOZ_LANG_TITLE Just testing' > x-test/toolkit/defines.inc
 	@# ZIP_IN='$(ZIP_IN)' will pass down the *current* value of ZIP_IN, based
 	@# on MOZ_SIMPLE_PACKAGE_NAME not being reset, overwriting the value it
 	@# would get with MOZ_SIMPLE_PACKAGE_NAME reset.
-	$(MAKE) installers-x-test L10NBASEDIR='$(PWD)' LOCALE_MERGEDIR='$(PWD)/mergedir' ZIP_IN='$(ZIP_IN)' MOZ_SIMPLE_PACKAGE_NAME=
-	$(PYTHON) $(topsrcdir)/toolkit/mozapps/installer/unpack.py $(DIST)/l10n-stage/$(STAGEPATH)$(MOZ_PKG_DIR)$(_BINPATH)
-	cd $(DIST)/l10n-stage && test $$(cat $(STAGEPATH)$(MOZ_PKG_DIR)$(_BINPATH)/update.locale) = x-test
+	$(MAKE) installers-x-test L10NBASEDIR='$(PWD)' LOCALE_MERGEDIR='$(PWD)/mergedir' ZIP_IN='$(ZIP_IN)' MOZ_SIMPLE_PACKAGE_NAME= UNIVERSAL_BINARY=
+	$(PYTHON) $(topsrcdir)/toolkit/mozapps/installer/unpack.py $(DIST)/l10n-stage/$(MOZ_PKG_DIR)$(_RESPATH)
+	cd $(DIST)/l10n-stage && test $$(cat $(MOZ_PKG_DIR)$(_RESPATH)/update.locale) = x-test
--- a/browser/locales/en-US/chrome/browser/preferences/preferences.properties
+++ b/browser/locales/en-US/chrome/browser/preferences/preferences.properties
@@ -124,17 +124,17 @@ cookiesFiltered=The following cookies ma
 # LOCALIZATION NOTE (removeSelectedCookies):
 # Semicolon-separated list of plural forms. See:
 # http://developer.mozilla.org/en/docs/Localization_and_Plurals
 # If you need to display the number of selected elements in your language,
 # you can use #1 in your localization as a placeholder for the number.
 # For example this is the English string with numbers:   
 # removeSelectedCookied=Remove #1 Selected;Remove #1 Selected
 removeSelectedCookies=Remove Selected;Remove Selected
-noUserContextLabel=None
+defaultUserContextLabel=None
 
 #### Offline apps
 offlineAppsList.height=7em
 offlineAppRemoveTitle=Remove offline website data
 offlineAppRemovePrompt=After removing this data, %S will not be available offline.  Are you sure you want to remove this offline website?
 offlineAppRemoveConfirm=Remove offline data
 
 # LOCALIZATION NOTE: The next string is for the disk usage of the
--- a/build/Makefile.in
+++ b/build/Makefile.in
@@ -4,20 +4,20 @@
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 USE_RCS_MK := 1
 include $(topsrcdir)/config/makefiles/makeutils.mk
 
 ifdef MOZ_APP_BASENAME
 APP_INI_DEPS = $(topsrcdir)/config/milestone.txt
 
-MOZ_APP_BUILDID := $(shell cat $(DEPTH)/config/buildid)
+MOZ_BUILDID := $(shell cat $(DEPTH)/config/buildid)
 APP_INI_DEPS += $(DEPTH)/config/buildid
 
-DEFINES += -DMOZ_APP_BUILDID=$(MOZ_APP_BUILDID)
+DEFINES += -DMOZ_BUILDID=$(MOZ_BUILDID)
 
 APP_INI_DEPS += $(DEPTH)/config/autoconf.mk
 
 MOZ_SOURCE_STAMP := $(firstword $(shell cd $(topsrcdir)/$(MOZ_BUILD_APP)/.. && hg parent --template='{node}\n' 2>/dev/null))
 ifdef MOZ_SOURCE_STAMP
 DEFINES += -DMOZ_SOURCE_STAMP='$(MOZ_SOURCE_STAMP)'
 endif
 
--- a/build/annotationProcessors/CodeGenerator.java
+++ b/build/annotationProcessors/CodeGenerator.java
@@ -22,49 +22,46 @@ public class CodeGenerator {
     // Buffers holding the strings to ultimately be written to the output files.
     private final StringBuilder cpp = new StringBuilder();
     private final StringBuilder header = new StringBuilder();
     private final StringBuilder natives = new StringBuilder();
     private final StringBuilder nativesInits = new StringBuilder();
 
     private final Class<?> cls;
     private final String clsName;
+    private boolean isMultithreaded;
 
     private final HashSet<String> takenMethodNames = new HashSet<String>();
 
     public CodeGenerator(ClassWithOptions annotatedClass) {
         this.cls = annotatedClass.wrappedClass;
         this.clsName = annotatedClass.generatedName;
 
         final String unqualifiedName = Utils.getUnqualifiedName(clsName);
         header.append(
-                "class " + clsName + " : public mozilla::jni::Class<" + unqualifiedName + ">\n" +
+                "class " + clsName + " : public mozilla::jni::ObjectBase<" +
+                        unqualifiedName + ", jobject>\n" +
                 "{\n" +
                 "public:\n" +
-                "    typedef mozilla::jni::Ref<" + unqualifiedName + "> Ref;\n" +
-                "    typedef mozilla::jni::LocalRef<" + unqualifiedName + "> LocalRef;\n" +
-                "    typedef mozilla::jni::GlobalRef<" + unqualifiedName + "> GlobalRef;\n" +
-                "    typedef const mozilla::jni::Param<" + unqualifiedName + ">& Param;\n" +
-                "\n" +
-                "    static constexpr char name[] =\n" +
-                "            \"" + cls.getName().replace('.', '/') + "\";\n" +
-                "\n" +
-                "protected:\n" +
-                "    " + unqualifiedName + "(jobject instance) : Class(instance) {}\n" +
+                "    explicit " + unqualifiedName + "(const Context& ctx) : ObjectBase<" +
+                        unqualifiedName + ", jobject>(ctx) {}\n" +
                 "\n");
 
         cpp.append(
-                "constexpr char " + clsName + "::name[];\n" +
+                "template<> const char mozilla::jni::Context<" +
+                        clsName + ", jobject>::name[] =\n" +
+                "        \"" + cls.getName().replace('.', '/') + "\";\n" +
                 "\n");
 
         natives.append(
                 "template<class Impl>\n" +
                 "class " + clsName + "::Natives : " +
                         "public mozilla::jni::NativeImpl<" + unqualifiedName + ", Impl>\n" +
-                "{\n");
+                "{\n" +
+                "public:\n");
     }
 
     private String getTraitsName(String uniqueName, boolean includeScope) {
         return (includeScope ? clsName + "::" : "") + uniqueName + "_t";
     }
 
     /**
      * Return the C++ type name for this class or any class within the chain
@@ -108,42 +105,42 @@ public class CodeGenerator {
         for (Class<?> argType : argTypes) {
             args.append("\n                " + getNativeParameterType(argType, info) + ",");
         }
         if (args.length() > 0) {
             args.setLength(args.length() - 1);
         }
 
         header.append(
-                "public:\n" +
                 "    struct " + getTraitsName(uniqueName, /* includeScope */ false) + " {\n" +
                 "        typedef " + Utils.getUnqualifiedName(clsName) + " Owner;\n" +
                 "        typedef " + getNativeReturnType(type, info) + " ReturnType;\n" +
                 "        typedef " + getNativeParameterType(type, info) + " SetterType;\n" +
                 "        typedef mozilla::jni::Args<" + args + "> Args;\n" +
                 "        static constexpr char name[] = \"" +
                         Utils.getMemberName(member) + "\";\n" +
                 "        static constexpr char signature[] =\n" +
                 "                \"" + Utils.getSignature(member) + "\";\n" +
                 "        static const bool isStatic = " + Utils.isStatic(member) + ";\n" +
-                "        static const bool isMultithreaded = " + info.isMultithreaded + ";\n" +
                 "        static const mozilla::jni::ExceptionMode exceptionMode =\n" +
                 "                " + (
                         info.catchException ? "mozilla::jni::ExceptionMode::NSRESULT" :
                         info.noThrow ?        "mozilla::jni::ExceptionMode::IGNORE" :
                                               "mozilla::jni::ExceptionMode::ABORT") + ";\n" +
                 "    };\n" +
                 "\n");
 
         cpp.append(
                 "constexpr char " + getTraitsName(uniqueName, /* includeScope */ true) +
                         "::name[];\n" +
                 "constexpr char " + getTraitsName(uniqueName, /* includeScope */ true) +
                         "::signature[];\n" +
                 "\n");
+
+        this.isMultithreaded |= info.isMultithreaded;
     }
 
     private String getUniqueMethodName(String basename) {
         String newName = basename;
         int index = 1;
 
         while (takenMethodNames.contains(newName)) {
             newName = basename + (++index);
@@ -256,17 +253,18 @@ public class CodeGenerator {
             def.append(
                     "    return ");
         }
 
 
         // Generate a call, e.g., Method<Traits>::Call(a0, a1, a2);
 
         def.append(accessorName).append("(")
-           .append(isStatic ? "nullptr" : "this");
+           .append(Utils.getUnqualifiedName(clsName) +
+                   (isStatic ? "::Context()" : "::mCtx"));
 
         if (info.catchException) {
             def.append(", &rv");
         } else {
             def.append(", nullptr");
         }
 
         // Generate the call argument list.
@@ -395,27 +393,25 @@ public class CodeGenerator {
                 field.setAccessible(true);
                 val = field.get(null);
             } catch (final IllegalAccessException e) {
             }
 
             if (val != null && type.isPrimitive()) {
                 // For static final primitive fields, we can use a "static const" declaration.
                 header.append(
-                    "public:\n" +
                     "    static const " + Utils.getNativeReturnType(type, info) +
                             ' ' + info.wrapperName + " = " + getLiteral(val, info) + ";\n" +
                     "\n");
                 return;
 
             } else if (val != null && type.equals(String.class)) {
                 final String nativeType = info.narrowChars ? "char" : "char16_t";
 
                 header.append(
-                    "public:\n" +
                     "    static const " + nativeType + ' ' + info.wrapperName + "[];\n" +
                     "\n");
 
                 cpp.append(
                     "const " + nativeType + ' ' + clsName + "::" + info.wrapperName +
                             "[] = " + getLiteral(val, info) + ";\n" +
                     "\n");
                 return;
@@ -514,18 +510,16 @@ public class CodeGenerator {
         }
     }
 
     public void generateClasses(final ClassWithOptions[] classes) {
         if (classes.length == 0) {
             return;
         }
 
-        header.append(
-                "public:\n");
         for (final ClassWithOptions cls : classes) {
             // Extract "Inner" from "Outer::Inner".
             header.append(
                     "    class " + Utils.getUnqualifiedName(cls.generatedName) + ";\n");
         }
         header.append('\n');
     }
 
@@ -539,19 +533,22 @@ public class CodeGenerator {
     }
 
     /**
      * Get the finalised bytes to go into the generated header file.
      *
      * @return The bytes to be written to the header file.
      */
     public String getHeaderFileContents() {
+        header.append(
+                "    static const bool isMultithreaded = " + this.isMultithreaded + ";\n" +
+                "\n");
+
         if (nativesInits.length() > 0) {
             header.append(
-                    "public:\n" +
                     "    template<class Impl> class Natives;\n");
         }
         header.append(
                 "};\n" +
                 "\n");
         return header.toString();
     }
 
@@ -560,17 +557,16 @@ public class CodeGenerator {
      *
      * @return The bytes to be written to the header file.
      */
     public String getNativesFileContents() {
         if (nativesInits.length() == 0) {
             return "";
         }
         natives.append(
-                "public:\n" +
                 "    static constexpr JNINativeMethod methods[] = {" + nativesInits + '\n' +
                 "    };\n" +
                 "};\n" +
                 "\n" +
                 "template<class Impl>\n" +
                 "constexpr JNINativeMethod " + clsName + "::Natives<Impl>::methods[];\n" +
                 "\n");
         return natives.toString();
--- a/build/annotationProcessors/utils/Utils.java
+++ b/build/annotationProcessors/utils/Utils.java
@@ -83,17 +83,17 @@ public class Utils {
 
         if (type.equals(String.class) || type.equals(CharSequence.class)) {
             return "mozilla::jni::String::Param";
         }
 
         if (type.equals(Class.class)) {
             // You're doing reflection on Java objects from inside C, returning Class objects
             // to C, generating the corresponding code using this Java program. Really?!
-            return "mozilla::jni::ClassObject::Param";
+            return "mozilla::jni::Class::Param";
         }
 
         if (type.equals(Throwable.class)) {
             return "mozilla::jni::Throwable::Param";
         }
 
         return "mozilla::jni::Object::Param";
     }
@@ -115,17 +115,17 @@ public class Utils {
 
         if (type.equals(String.class)) {
             return "mozilla::jni::String::LocalRef";
         }
 
         if (type.equals(Class.class)) {
             // You're doing reflection on Java objects from inside C, returning Class objects
             // to C, generating the corresponding code using this Java program. Really?!
-            return "mozilla::jni::ClassObject::LocalRef";
+            return "mozilla::jni::Class::LocalRef";
         }
 
         if (type.equals(Throwable.class)) {
             return "mozilla::jni::Throwable::LocalRef";
         }
 
         return "mozilla::jni::Object::LocalRef";
     }
--- a/build/application.ini
+++ b/build/application.ini
@@ -21,17 +21,17 @@ Name=@MOZ_APP_BASENAME@
 RemotingName=@MOZ_APP_REMOTINGNAME@
 #ifdef MOZ_APP_DISPLAYNAME
 CodeName=@MOZ_APP_DISPLAYNAME@
 #endif
 Version=@MOZ_APP_VERSION@
 #ifdef MOZ_APP_PROFILE
 Profile=@MOZ_APP_PROFILE@
 #endif
-BuildID=@MOZ_APP_BUILDID@
+BuildID=@MOZ_BUILDID@
 #ifdef MOZ_SOURCE_REPO
 SourceRepository=@MOZ_SOURCE_REPO@
 #endif
 #ifdef MOZ_SOURCE_STAMP
 SourceStamp=@MOZ_SOURCE_STAMP@
 #endif
 ID=@MOZ_APP_ID@
 
@@ -42,10 +42,10 @@ MaxVersion=@GRE_MILESTONE@
 [XRE]
 #ifdef MOZ_PROFILE_MIGRATOR
 EnableProfileMigrator=1
 #endif
 
 #if MOZ_CRASHREPORTER
 [Crash Reporter]
 Enabled=1
-ServerURL=https://crash-reports.mozilla.com/submit?id=@MOZ_APP_ID@&version=@MOZ_APP_VERSION@&buildid=@MOZ_APP_BUILDID@
+ServerURL=https://crash-reports.mozilla.com/submit?id=@MOZ_APP_ID@&version=@MOZ_APP_VERSION@&buildid=@MOZ_BUILDID@
 #endif
--- a/build/mach_bootstrap.py
+++ b/build/mach_bootstrap.py
@@ -34,16 +34,19 @@ mach has detected that you have never ru
 Running this command will ensure your Mercurial version control tool is up
 to date and optimally configured for a better, more productive experience
 when working on Mozilla projects.
 
 Please run `{mach} mercurial-setup` now.
 
 Note: `{mach} mercurial-setup` does not make any changes without prompting
 you first.
+
+You can disable this check by setting NO_MERCURIAL_SETUP_CHECK=1 in your
+environment.
 '''.strip()
 
 MERCURIAL_SETUP_FATAL_INTERVAL = 31 * 24 * 60 * 60
 
 
 # TODO Bug 794506 Integrate with the in-tree virtualenv configuration.
 SEARCH_PATHS = [
     'python/mach',
@@ -231,19 +234,21 @@ def bootstrap(topsrcdir, mozilla_dir=Non
         # The user is performing a maintenance command.
         if handler.name in ('bootstrap', 'doctor', 'mach-commands', 'mercurial-setup'):
             return
 
         # We are running in automation.
         if 'MOZ_AUTOMATION' in os.environ or 'TASK_ID' in os.environ:
             return
 
-        # We are a curmudgeon who has found this undocumented variable.
+        # User has disabled first run check.
         if 'I_PREFER_A_SUBOPTIMAL_MERCURIAL_EXPERIENCE' in os.environ:
             return
+        if 'NO_MERCURIAL_SETUP_CHECK' in os.environ:
+            return
 
         # The environment is likely a machine invocation.
         if sys.stdin.closed or not sys.stdin.isatty():
             return
 
         # Mercurial isn't managing this source checkout.
         if not os.path.exists(os.path.join(topsrcdir, '.hg')):
             return
--- a/build/macosx/local-mozconfig.common
+++ b/build/macosx/local-mozconfig.common
@@ -1,14 +1,12 @@
 # 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/.
 
-MOZ_AUTOMATION_L10N_CHECK=0
-
 if [ "x$IS_NIGHTLY" = "xyes" ]; then
   # Some nightlies (eg: Mulet) don't want these set.
   MOZ_AUTOMATION_UPLOAD_SYMBOLS=${MOZ_AUTOMATION_UPLOAD_SYMBOLS-1}
   MOZ_AUTOMATION_UPDATE_PACKAGING=${MOZ_AUTOMATION_UPDATE_PACKAGING-1}
   MOZ_AUTOMATION_SDK=${MOZ_AUTOMATION_SDK-1}
 fi
 . "$topsrcdir/build/mozconfig.common"
 
deleted file mode 100644
--- a/build/msys-perl-wrapper
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/bin/sh
-# 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/.
-
-
-args=""
-
-for i in "${@}"
-do
-    case "$i" in
-    -I?:/*)
-        i="$(echo "${i}" | sed -e 's|^-I\(.\):/|-I/\1/|')"
-	;;
-    esac
-
-    args="${args} '${i}'"
-done
-
-eval "exec perl $args"
--- a/build/win32/Makefile.in
+++ b/build/win32/Makefile.in
@@ -22,11 +22,14 @@ libs-preqs = \
 	$(NULL)
 
 libs:: $(libs-preqs)
 	install --preserve-timestamps $(REDIST_FILES) $(FINAL_TARGET)
 endif
 
 # run the binscope tool to make sure the binary and all libraries
 # are using all available Windows OS-level security mechanisms
+# Don't do this in clang-cl since it doesn't support debug information yet.
+ifndef CLANG_CL
 check::
 	$(PYTHON) $(srcdir)/autobinscope.py $(DIST)/bin/$(MOZ_APP_NAME)$(BIN_SUFFIX) $(DIST)/crashreporter-symbols/
 	$(PYTHON) $(srcdir)/autobinscope.py $(DIST)/bin/plugin-container.exe $(DIST)/crashreporter-symbols/
+endif
--- a/config/external/nss/Makefile.in
+++ b/config/external/nss/Makefile.in
@@ -259,23 +259,16 @@ DEFAULT_GMAKE_FLAGS += MAKE_OBJDIR='$$(I
 # Work around NSS adding IMPORT_LIBRARY to TARGETS with no rule for
 # it, creating race conditions. See bug #836220
 DEFAULT_GMAKE_FLAGS += TARGETS='$$(LIBRARY) $$(SHARED_LIBRARY) $$(PROGRAM)'
 
 ifdef MOZ_FOLD_LIBS_FLAGS
 DEFAULT_GMAKE_FLAGS += XCFLAGS='$(MOZ_FOLD_LIBS_FLAGS)'
 endif
 
-ifndef WARNINGS_AS_ERRORS
-DEFAULT_GMAKE_FLAGS += NSS_ENABLE_WERROR=0
-endif
-ifeq ($(OS_TARGET),Android)
-DEFAULT_GMAKE_FLAGS += NSS_ENABLE_WERROR=0
-endif
-
 NSS_SRCDIR = $(topsrcdir)
 
 NSS_DIRS =
 ifndef MOZ_FOLD_LIBS
 NSS_DIRS += nss/lib
 else
 ifndef NSS_DISABLE_DBM
 NSS_DIRS += nss/lib/dbm
@@ -345,16 +338,20 @@ IMPORT_LIB_FILES = $(IMPORT_LIBRARY)
 IMPORT_LIB_DEST ?= $(DIST)/lib
 IMPORT_LIB_TARGET = target
 INSTALL_TARGETS += IMPORT_LIB
 
 endif # MOZ_FOLD_LIBS
 
 include $(topsrcdir)/config/rules.mk
 
+ifeq (1,$(ALLOW_COMPILER_WARNINGS))
+DEFAULT_GMAKE_FLAGS += NSS_ENABLE_WERROR=0
+endif
+
 # Can't pass this in DEFAULT_GMAKE_FLAGS because that overrides
 # definitions in NSS, so just export it into the sub-make's environment.
 ifeq (WINNT_1,$(OS_TARGET)_$(MOZ_MEMORY))
 ifdef MOZ_CRT
 # OS_LIBS comes from having mozcrt as a dependency in moz.build.
 DLLFLAGS := $(OS_LIBS)
 else
 DLLFLAGS := -LIBPATH:$(ABS_DIST)/../mozglue/build -DEFAULTLIB:mozglue
--- a/config/faster/rules.mk
+++ b/config/faster/rules.mk
@@ -32,21 +32,16 @@
 #
 # A convention used between this file and the Makefile including it is that
 # global Make variables names are uppercase, while "local" Make variables
 # applied to specific targets are lowercase.
 
 # Targets to be triggered for a default build
 default: $(addprefix install-,$(INSTALL_MANIFESTS))
 
-# Explicit files to be built for a default build
-ifndef TEST_MOZBUILD
-default: $(TOPOBJDIR)/dist/bin/platform.ini
-endif
-
 ifndef NO_XPIDL
 # Targets from the recursive make backend to be built for a default build
 default: $(TOPOBJDIR)/config/makefiles/xpidl/xpidl
 endif
 
 # Mac builds require to copy things in dist/bin/*.app
 # TODO: remove the MOZ_WIDGET_TOOLKIT and MOZ_BUILD_APP variables from
 # faster/Makefile and python/mozbuild/mozbuild/test/backend/test_build.py
@@ -67,23 +62,16 @@ endif
 # use of those. As of writing the only ones are in
 # toolkit/content/buildconfig.html and browser/locales/jar.mn.
 ACDEFINES += -DBUILD_FASTER
 
 # Files under the faster/ sub-directory, however, are not meant to use the
 # fallback
 $(TOPOBJDIR)/faster/%: ;
 
-# And files under dist/ are meant to be copied from their first dependency
-# if there is no other rule.
-$(TOPOBJDIR)/dist/%:
-	rm -f $@
-	mkdir -p $(@D)
-	cp $< $@
-
 # Generic rule to fall back to the recursive make backend.
 # This needs to stay after other $(TOPOBJDIR)/* rules because GNU Make
 # <3.82 apply pattern rules in definition order, not stem length like
 # modern GNU Make.
 $(TOPOBJDIR)/%: FORCE
 	$(MAKE) -C $(dir $@) $(notdir $@)
 
 # Install files using install manifests
@@ -98,29 +86,24 @@ ACDEFINES += -DBUILD_FASTER
 	@# support for defines tracking in process_install_manifest.
 	@touch install_$(subst /,_,$*)
 	@# BOOKMARKS_INCLUDE_DIR is for bookmarks.html only.
 	$(PYTHON) -m mozbuild.action.process_install_manifest \
 		--track install_$(subst /,_,$*).track \
 		$(TOPOBJDIR)/$* \
 		-DAB_CD=en-US \
 		-DBOOKMARKS_INCLUDE_DIR=$(TOPSRCDIR)/browser/locales/en-US/profile \
-		-DMOZ_APP_BUILDID=$(shell cat $(TOPOBJDIR)/config/buildid) \
+		-DMOZ_BUILDID=$(shell cat $(TOPOBJDIR)/config/buildid) \
 		$(ACDEFINES) \
 		install_$(subst /,_,$*)
 
 # ============================================================================
 # Below is a set of additional dependencies and variables used to build things
 # that are not supported by data in moz.build.
 
-# Files to build with the recursive backend and simply copy
-$(TOPOBJDIR)/dist/bin/platform.ini: $(TOPOBJDIR)/toolkit/xre/platform.ini
-
-$(TOPOBJDIR)/toolkit/xre/platform.ini: $(TOPOBJDIR)/config/buildid
-
 # The xpidl target in config/makefiles/xpidl requires the install manifest for
 # dist/idl to have been processed. When using the hybrid
 # FasterMake/RecursiveMake backend, this dependency is handled in the top-level
 # Makefile.
 ifndef FASTER_RECURSIVE_MAKE
 $(TOPOBJDIR)/config/makefiles/xpidl/xpidl: $(TOPOBJDIR)/install-dist_idl
 endif
 # It also requires all the install manifests for dist/bin to have been processed
--- a/config/system-headers
+++ b/config/system-headers
@@ -1299,16 +1299,17 @@ QtSparql/qsparqlconnection.h
 QtSparql/qsparqlquery.h
 QtSparql/qsparqlresult.h
 #endif
 
 #if MOZ_TREE_PIXMAN!=1
 pixman.h
 #endif
 #if MOZ_NATIVE_LIBVPX==1
+vpx/svc_context.h
 vpx/vpx_codec.h
 vpx/vpx_decoder.h
 vpx/vpx_encoder.h
 vpx/vp8cx.h
 vpx/vp8dx.h
 vpx_mem/vpx_mem.h
 #endif
 gst/gst.h
--- a/configure.in
+++ b/configure.in
@@ -564,24 +564,17 @@ case "$target" in
             AC_MSG_ERROR([This version (${_CC_MAJOR_VERSION}.${_CC_MINOR_VERSION}.${_CC_BUILD_VERSION}) of the MSVC compiler is unsupported.
 You must install Visual C++ 2013 Update 3, Visual C++ 2015 Update 1, or newer in order to build.
 See https://developer.mozilla.org/en/Windows_Build_Prerequisites.])
         fi
         AC_SUBST(MSVS_VERSION)
         AC_SUBST(MSVC_C_RUNTIME_DLL)
         AC_SUBST(MSVC_CXX_RUNTIME_DLL)
 
-        # Disable SEH on clang-cl because it doesn't implement them yet.
-        if test -z "$CLANG_CL"; then
-            AC_DEFINE(HAVE_SEH_EXCEPTIONS)
-        else
-            # Send our CFLAGS to NSS
-            MOZ_CFLAGS_NSS=1
-            AC_DEFINE_UNQUOTED(GTEST_HAS_SEH, 0)
-        fi
+        AC_DEFINE(HAVE_SEH_EXCEPTIONS)
 
         if test -n "$WIN32_REDIST_DIR"; then
           if test ! -d "$WIN32_REDIST_DIR"; then
             AC_MSG_ERROR([Invalid Win32 Redist directory: ${WIN32_REDIST_DIR}])
           fi
           WIN32_REDIST_DIR=`cd "$WIN32_REDIST_DIR" && pwd`
         fi
 
@@ -1841,21 +1834,16 @@ case "$host" in
         HOST_CFLAGS="$HOST_CFLAGS -TC -nologo"
         HOST_RANLIB='echo ranlib'
     else
         HOST_CFLAGS="$HOST_CFLAGS -mwindows"
     fi
     HOST_CFLAGS="$HOST_CFLAGS -DXP_WIN32 -DXP_WIN -DWIN32 -D_WIN32 -DNO_X11 -D_CRT_SECURE_NO_WARNINGS"
     HOST_OPTIMIZE_FLAGS="${HOST_OPTIMIZE_FLAGS=-O2}"
     HOST_BIN_SUFFIX=.exe
-    case "$host" in
-    *mingw*)
-        PERL="/bin/sh ${_topsrcdir}/build/msys-perl-wrapper"
-        ;;
-    esac
 
     case "${host_cpu}" in
     i*86)
         if test -n "$_WIN32_MSVC"; then
             HOST_LDFLAGS="$HOST_LDFLAGS -MACHINE:X86"
         fi
         ;;
     x86_64)
--- a/dom/animation/AnimationEffectTimingReadOnly.cpp
+++ b/dom/animation/AnimationEffectTimingReadOnly.cpp
@@ -1,18 +1,20 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim:set ts=2 sw=2 sts=2 et cindent: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/dom/AnimationEffectTimingReadOnly.h"
 
+#include "mozilla/AnimationUtils.h"
 #include "mozilla/dom/AnimatableBinding.h"
 #include "mozilla/dom/AnimationEffectTimingReadOnlyBinding.h"
+#include "mozilla/dom/CSSPseudoElement.h"
 #include "mozilla/dom/KeyframeEffectBinding.h"
 
 namespace mozilla {
 
 TimingParams::TimingParams(const dom::AnimationEffectTimingProperties& aRhs,
                            const dom::Element* aTarget)
   : mDuration(aRhs.mDuration)
   , mDelay(TimeDuration::FromMilliseconds(aRhs.mDelay))
@@ -23,40 +25,80 @@ TimingParams::TimingParams(const dom::An
   mFunction = AnimationUtils::ParseEasing(aTarget, aRhs.mEasing);
 }
 
 TimingParams::TimingParams(double aDuration)
 {
   mDuration.SetAsUnrestrictedDouble() = aDuration;
 }
 
-/* static */ TimingParams
-TimingParams::FromOptionsUnion(
-  const dom::UnrestrictedDoubleOrKeyframeEffectOptions& aOptions,
-  const dom::Element* aTarget)
+template <class OptionsType>
+static const dom::AnimationEffectTimingProperties&
+GetTimingProperties(const OptionsType& aOptions);
+
+template <>
+/* static */ const dom::AnimationEffectTimingProperties&
+GetTimingProperties(
+  const dom::UnrestrictedDoubleOrKeyframeEffectOptions& aOptions)
+{
+  MOZ_ASSERT(aOptions.IsKeyframeEffectOptions());
+  return aOptions.GetAsKeyframeEffectOptions();
+}
+
+template <>
+/* static */ const dom::AnimationEffectTimingProperties&
+GetTimingProperties(
+  const dom::UnrestrictedDoubleOrKeyframeAnimationOptions& aOptions)
+{
+  MOZ_ASSERT(aOptions.IsKeyframeAnimationOptions());
+  return aOptions.GetAsKeyframeAnimationOptions();
+}
+
+template <class OptionsType>
+static TimingParams
+TimingParamsFromOptionsUnion(
+  const OptionsType& aOptions,
+  const Nullable<dom::ElementOrCSSPseudoElement>& aTarget)
 {
   if (aOptions.IsUnrestrictedDouble()) {
     return TimingParams(aOptions.GetAsUnrestrictedDouble());
   } else {
-    MOZ_ASSERT(aOptions.IsKeyframeEffectOptions());
-    return TimingParams(aOptions.GetAsKeyframeEffectOptions(), aTarget);
+    // If aTarget is a pseudo element, we pass its parent element because
+    // TimingParams only needs its owner doc to parse easing and both pseudo
+    // element and its parent element should have the same owner doc.
+    // Bug 1246320: Avoid passing the element for parsing the timing function
+    RefPtr<dom::Element> targetElement;
+    if (!aTarget.IsNull()) {
+      const dom::ElementOrCSSPseudoElement& target = aTarget.Value();
+      MOZ_ASSERT(target.IsElement() || target.IsCSSPseudoElement(),
+                 "Uninitialized target");
+      if (target.IsElement()) {
+        targetElement = &target.GetAsElement();
+      } else {
+        targetElement = target.GetAsCSSPseudoElement().ParentElement();
+      }
+    }
+    return TimingParams(GetTimingProperties(aOptions), targetElement);
   }
 }
 
 /* static */ TimingParams
 TimingParams::FromOptionsUnion(
-  const dom::UnrestrictedDoubleOrKeyframeAnimationOptions& aOptions,
-  const dom::Element* aTarget)
+  const dom::UnrestrictedDoubleOrKeyframeEffectOptions& aOptions,
+  const Nullable<dom::ElementOrCSSPseudoElement>& aTarget)
 {
-  if (aOptions.IsUnrestrictedDouble()) {
-    return TimingParams(aOptions.GetAsUnrestrictedDouble());
-  } else {
-    MOZ_ASSERT(aOptions.IsKeyframeAnimationOptions());
-    return TimingParams(aOptions.GetAsKeyframeAnimationOptions(), aTarget);
-  }
+  return TimingParamsFromOptionsUnion(aOptions, aTarget);
+}
+
+/* static */ TimingParams
+TimingParams::FromOptionsUnion(
+  const dom::UnrestrictedDoubleOrKeyframeAnimationOptions& aOptions,
+  const Nullable<dom::ElementOrCSSPseudoElement>& aTarget)
+{
+  return TimingParamsFromOptionsUnion(aOptions, aTarget);
 }
 
 bool
 TimingParams::operator==(const TimingParams& aOther) const
 {
   bool durationEqual;
   if (mDuration.IsUnrestrictedDouble()) {
     durationEqual = aOther.mDuration.IsUnrestrictedDouble() &&
--- a/dom/animation/AnimationEffectTimingReadOnly.h
+++ b/dom/animation/AnimationEffectTimingReadOnly.h
@@ -24,32 +24,32 @@
 
 namespace mozilla {
 
 namespace dom {
 struct AnimationEffectTimingProperties;
 class Element;
 class UnrestrictedDoubleOrKeyframeEffectOptions;
 class UnrestrictedDoubleOrKeyframeAnimationOptions;
+class ElementOrCSSPseudoElement;
 }
 
 struct TimingParams
 {
   TimingParams() = default;
-  explicit TimingParams(
-    const dom::AnimationEffectTimingProperties& aTimingProperties,
-    const dom::Element* aTarget);
+  TimingParams(const dom::AnimationEffectTimingProperties& aTimingProperties,
+               const dom::Element* aTarget);
   explicit TimingParams(double aDuration);
 
   static TimingParams FromOptionsUnion(
     const dom::UnrestrictedDoubleOrKeyframeEffectOptions& aOptions,
-    const dom::Element* aTarget);
+    const Nullable<dom::ElementOrCSSPseudoElement>& aTarget);
   static TimingParams FromOptionsUnion(
     const dom::UnrestrictedDoubleOrKeyframeAnimationOptions& aOptions,
-    const dom::Element* aTarget);
+    const Nullable<dom::ElementOrCSSPseudoElement>& aTarget);
 
   // The unitialized state of mDuration represents "auto".
   // Bug 1237173: We will replace this with Maybe<TimeDuration>.
   dom::OwningUnrestrictedDoubleOrString mDuration;
   TimeDuration mDelay;      // Initializes to zero
   double mIterations = 1.0; // Can be NaN, negative, +/-Infinity
   dom::PlaybackDirection mDirection = dom::PlaybackDirection::Normal;
   dom::FillMode mFill = dom::FillMode::Auto;
new file mode 100644
--- /dev/null
+++ b/dom/animation/CSSPseudoElement.cpp
@@ -0,0 +1,111 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "mozilla/dom/CSSPseudoElement.h"
+#include "mozilla/dom/CSSPseudoElementBinding.h"
+#include "mozilla/dom/Element.h"
+
+namespace mozilla {
+namespace dom {
+
+NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(CSSPseudoElement, mParentElement)
+
+NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(CSSPseudoElement, AddRef)
+NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(CSSPseudoElement, Release)
+
+CSSPseudoElement::CSSPseudoElement(Element* aElement,
+                                   nsCSSPseudoElements::Type aType)
+  : mParentElement(aElement)
+  , mPseudoType(aType)
+{
+  MOZ_ASSERT(aElement);
+  MOZ_ASSERT(aType == nsCSSPseudoElements::ePseudo_after ||
+             aType == nsCSSPseudoElements::ePseudo_before,
+             "Unexpected Pseudo Type");
+}
+
+CSSPseudoElement::~CSSPseudoElement()
+{
+  // Element might have been unlinked already, so we have to do null check.
+  if (mParentElement) {
+    mParentElement->DeleteProperty(
+      GetCSSPseudoElementPropertyAtom(mPseudoType));
+  }
+}
+
+JSObject*
+CSSPseudoElement::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
+{
+  return CSSPseudoElementBinding::Wrap(aCx, this, aGivenProto);
+}
+
+void
+CSSPseudoElement::GetAnimations(nsTArray<RefPtr<Animation>>& aRetVal)
+{
+  // Bug 1234403: Implement this API.
+  NS_NOTREACHED("CSSPseudoElement::GetAnimations() is not implemented yet.");
+}
+
+already_AddRefed<Animation>
+CSSPseudoElement::Animate(
+    JSContext* aContext,
+    JS::Handle<JSObject*> aFrames,
+    const UnrestrictedDoubleOrKeyframeAnimationOptions& aOptions,
+    ErrorResult& aError)
+{
+  // Bug 1241784: Implement this API.
+  NS_NOTREACHED("CSSPseudoElement::Animate() is not implemented yet.");
+  return nullptr;
+}
+
+/* static */ already_AddRefed<CSSPseudoElement>
+CSSPseudoElement::GetCSSPseudoElement(Element* aElement,
+                                      nsCSSPseudoElements::Type aType)
+{
+  if (!aElement) {
+    return nullptr;
+  }
+
+  nsIAtom* propName = CSSPseudoElement::GetCSSPseudoElementPropertyAtom(aType);
+  RefPtr<CSSPseudoElement> pseudo =
+    static_cast<CSSPseudoElement*>(aElement->GetProperty(propName));
+  if (pseudo) {
+    return pseudo.forget();
+  }
+
+  // CSSPseudoElement is a purely external interface created on-demand, and
+  // when all references from script to the pseudo are dropped, we can drop the
+  // CSSPseudoElement object, so use a non-owning reference from Element to
+  // CSSPseudoElement.
+  pseudo = new CSSPseudoElement(aElement, aType);
+  nsresult rv = aElement->SetProperty(propName, pseudo, nullptr, true);
+  if (NS_FAILED(rv)) {
+    NS_WARNING("SetProperty failed");
+    return nullptr;
+  }
+  return pseudo.forget();
+}
+
+/* static */ nsIAtom*
+CSSPseudoElement::GetCSSPseudoElementPropertyAtom(
+    nsCSSPseudoElements::Type aType)
+{
+  switch (aType) {
+    case nsCSSPseudoElements::ePseudo_before:
+      return nsGkAtoms::cssPseudoElementBeforeProperty;
+
+    case nsCSSPseudoElements::ePseudo_after:
+      return nsGkAtoms::cssPseudoElementAfterProperty;
+
+    default:
+      NS_NOTREACHED("Should not try to get CSSPseudoElement "
+                    "other than ::before or ::after");
+      return nullptr;
+  }
+}
+
+} // namespace dom
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/animation/CSSPseudoElement.h
@@ -0,0 +1,88 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* 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/. */
+
+#ifndef mozilla_dom_CSSPseudoElement_h
+#define mozilla_dom_CSSPseudoElement_h
+
+#include "js/TypeDecls.h"
+#include "mozilla/Attributes.h"
+#include "mozilla/ErrorResult.h"
+#include "mozilla/dom/BindingDeclarations.h"
+#include "mozilla/RefPtr.h"
+#include "nsCSSPseudoElements.h"
+#include "nsWrapperCache.h"
+
+namespace mozilla {
+namespace dom {
+
+class Animation;
+class Element;
+class UnrestrictedDoubleOrKeyframeAnimationOptions;
+
+class CSSPseudoElement final : public nsWrapperCache
+{
+public:
+  NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(CSSPseudoElement)
+  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(CSSPseudoElement)
+
+protected:
+  virtual ~CSSPseudoElement();
+
+public:
+  ParentObject GetParentObject() const
+  {
+    return mParentElement->GetParentObject();
+  }
+
+  virtual JSObject* WrapObject(JSContext* aCx,
+                               JS::Handle<JSObject*> aGivenProto) override;
+
+  nsCSSPseudoElements::Type GetType() const { return mPseudoType; }
+  void GetType(nsString& aRetVal) const
+  {
+    MOZ_ASSERT(nsCSSPseudoElements::GetPseudoAtom(mPseudoType),
+               "All pseudo-types allowed by this class should have a"
+               " corresponding atom");
+    nsCSSPseudoElements::GetPseudoAtom(mPseudoType)->ToString(aRetVal);
+  }
+  already_AddRefed<Element> ParentElement() const
+  {
+    RefPtr<Element> retVal(mParentElement);
+    return retVal.forget();
+  }
+
+  void GetAnimations(nsTArray<RefPtr<Animation>>& aRetVal);
+  already_AddRefed<Animation>
+    Animate(JSContext* aContext,
+            JS::Handle<JSObject*> aFrames,
+            const UnrestrictedDoubleOrKeyframeAnimationOptions& aOptions,
+            ErrorResult& aError);
+
+  // Given an element:pseudoType pair, returns the CSSPseudoElement stored as a
+  // property on |aElement|. If there is no CSSPseudoElement for the specified
+  // pseudo-type on element, a new CSSPseudoElement will be created and stored
+  // on the element.
+  static already_AddRefed<CSSPseudoElement>
+    GetCSSPseudoElement(Element* aElement, nsCSSPseudoElements::Type aType);
+
+private:
+  // Only ::before and ::after are supported.
+  CSSPseudoElement(Element* aElement, nsCSSPseudoElements::Type aType);
+
+  static nsIAtom*
+  GetCSSPseudoElementPropertyAtom(nsCSSPseudoElements::Type aType);
+
+  // mParentElement needs to be an owning reference since if script is holding
+  // on to the pseudo-element, it needs to continue to be able to refer to
+  // the parent element.
+  RefPtr<Element> mParentElement;
+  nsCSSPseudoElements::Type mPseudoType;
+};
+
+} // namespace dom
+} // namespace mozilla
+
+#endif // mozilla_dom_CSSPseudoElement_h
--- a/dom/animation/KeyframeEffect.cpp
+++ b/dom/animation/KeyframeEffect.cpp
@@ -1142,32 +1142,36 @@ ApplyDistributeSpacing(nsTArray<OffsetIn
  * Splits out each property's keyframe animation segment information
  * from the OffsetIndexedKeyframe objects into an array of KeyframeValueEntry.
  *
  * The easing string value in OffsetIndexedKeyframe objects is parsed
  * into a ComputedTimingFunction value in the corresponding KeyframeValueEntry
  * objects.
  *
  * @param aTarget The target of the animation.
+ * @param aPseudoType The pseudo type of the target if it is a pseudo element.
  * @param aKeyframes The keyframes to read.
  * @param aResult The array to append the resulting KeyframeValueEntry
  *   objects to.
  */
 static void
 GenerateValueEntries(Element* aTarget,
+                     nsCSSPseudoElements::Type aPseudoType,
                      nsTArray<OffsetIndexedKeyframe>& aKeyframes,
                      nsTArray<KeyframeValueEntry>& aResult,
                      ErrorResult& aRv)
 {
   nsCSSPropertySet properties;              // All properties encountered.
   nsCSSPropertySet propertiesWithFromValue; // Those with a defined 0% value.
   nsCSSPropertySet propertiesWithToValue;   // Those with a defined 100% value.
 
   for (OffsetIndexedKeyframe& keyframe : aKeyframes) {
     float offset = float(keyframe.mKeyframeDict.mOffset.Value());
+    // ParseEasing uses element's owner doc, so if it is a pseudo element,
+    // we use its parent element's owner doc.
     Maybe<ComputedTimingFunction> easing =
       AnimationUtils::ParseEasing(aTarget, keyframe.mKeyframeDict.mEasing);
     // We ignore keyframe.mKeyframeDict.mComposite since we don't support
     // composite modes on keyframes yet.
 
     // keyframe.mPropertyValuePairs is currently sorted by CSS property IDL
     // name, since that was the order we read the properties from the JS
     // object.  Re-sort the list so that longhand properties appear before
@@ -1195,16 +1199,17 @@ GenerateValueEntries(Element* aTarget,
                  "ConvertKeyframeSequence should have parsed single "
                  "DOMString values from the property-values pairs");
       // Parse the property's string value and produce a KeyframeValueEntry (or
       // more than one, for shorthands) for it.
       nsTArray<PropertyStyleAnimationValuePair> values;
       if (StyleAnimationValue::ComputeValues(pair.mProperty,
                                              nsCSSProps::eEnabledForAllContent,
                                              aTarget,
+                                             aPseudoType,
                                              pair.mValues[0],
                                              /* aUseSVGMode */ false,
                                              values)) {
         for (auto& value : values) {
           // If we already got a value for this property on the keyframe,
           // skip this one.
           if (propertiesOnThisKeyframe.HasProperty(value.mProperty)) {
             continue;
@@ -1348,16 +1353,17 @@ BuildSegmentsFromValueEntries(nsTArray<K
  *   object to iterate over as a sequence.
  * @param aResult The array into which the resulting AnimationProperty
  *   objects will be appended.
  */
 static void
 BuildAnimationPropertyListFromKeyframeSequence(
     JSContext* aCx,
     Element* aTarget,
+    nsCSSPseudoElements::Type aPseudoType,
     JS::ForOfIterator& aIterator,
     nsTArray<AnimationProperty>& aResult,
     ErrorResult& aRv)
 {
   // Convert the object in aIterator to sequence<Keyframe>, producing
   // an array of OffsetIndexedKeyframe objects.
   AutoTArray<OffsetIndexedKeyframe,4> keyframes;
   if (!ConvertKeyframeSequence(aCx, aIterator, keyframes)) {
@@ -1381,17 +1387,17 @@ BuildAnimationPropertyListFromKeyframeSe
   // Fill in 0%/100% values if the first/element keyframes don't have
   // a specified offset, and evenly space those that have a missing
   // offset.  (We don't support paced spacing yet.)
   ApplyDistributeSpacing(keyframes);
 
   // Convert the OffsetIndexedKeyframes into a list of KeyframeValueEntry
   // objects.
   nsTArray<KeyframeValueEntry> entries;
-  GenerateValueEntries(aTarget, keyframes, entries, aRv);
+  GenerateValueEntries(aTarget, aPseudoType, keyframes, entries, aRv);
   if (aRv.Failed()) {
     return;
   }
 
   // Finally, build an array of AnimationProperty objects in aResult
   // corresponding to the entries.
   BuildSegmentsFromValueEntries(entries, aResult);
 }
@@ -1405,31 +1411,34 @@ BuildAnimationPropertyListFromKeyframeSe
  * @param aValue The JS object.
  * @param aResult The array into which the resulting AnimationProperty
  *   objects will be appended.
  */
 static void
 BuildAnimationPropertyListFromPropertyIndexedKeyframes(
     JSContext* aCx,
     Element* aTarget,
+    nsCSSPseudoElements::Type aPseudoType,
     JS::Handle<JS::Value> aValue,
     InfallibleTArray<AnimationProperty>& aResult,
     ErrorResult& aRv)
 {
   MOZ_ASSERT(aValue.isObject());
 
   // Convert the object to a PropertyIndexedKeyframes dictionary to
   // get its explicit dictionary members.
   binding_detail::FastPropertyIndexedKeyframes keyframes;
   if (!keyframes.Init(aCx, aValue, "PropertyIndexedKeyframes argument",
                       false)) {
     aRv.Throw(NS_ERROR_FAILURE);
     return;
   }
 
+  // ParseEasing uses element's owner doc, so if it is a pseudo element,
+  // we use its parent element's owner doc.
   Maybe<ComputedTimingFunction> easing =
     AnimationUtils::ParseEasing(aTarget, keyframes.mEasing);
 
   // We ignore easing.mComposite since we don't support composite modes on
   // keyframes yet.
 
   // Get all the property--value-list pairs off the object.
   JS::Rooted<JSObject*> object(aCx, &aValue.toObject());
@@ -1475,16 +1484,17 @@ BuildAnimationPropertyListFromPropertyIn
     // With future spec clarifications we might decide to preserve the invalid
     // value on the segment and make the animation code deal with the invalid
     // value instead.
     nsTArray<PropertyStyleAnimationValuePair> fromValues;
     float fromKey = 0.0f;
     if (!StyleAnimationValue::ComputeValues(pair.mProperty,
                                             nsCSSProps::eEnabledForAllContent,
                                             aTarget,
+                                            aPseudoType,
                                             pair.mValues[0],
                                             /* aUseSVGMode */ false,
                                             fromValues)) {
       // We need to throw for an invalid first value, since that would imply an
       // additive animation, which we don't support yet.
       aRv.Throw(NS_ERROR_DOM_ANIM_MISSING_PROPS_ERR);
       return;
     }
@@ -1527,16 +1537,17 @@ BuildAnimationPropertyListFromPropertyIn
 
     double portion = 1.0 / (count - 1);
     for (size_t i = 0; i < count - 1; ++i) {
       nsTArray<PropertyStyleAnimationValuePair> toValues;
       float toKey = (i + 1) * portion;
       if (!StyleAnimationValue::ComputeValues(pair.mProperty,
                                               nsCSSProps::eEnabledForAllContent,
                                               aTarget,
+                                              aPseudoType,
                                               pair.mValues[i + 1],
                                               /* aUseSVGMode */ false,
                                               toValues)) {
         if (i + 1 == count - 1) {
           // We need to throw for an invalid last value, since that would
           // imply an additive animation, which we don't support yet.
           aRv.Throw(NS_ERROR_DOM_ANIM_MISSING_PROPS_ERR);
           return;
@@ -1575,16 +1586,17 @@ BuildAnimationPropertyListFromPropertyIn
  *   that is the keyframe list specification.
  * @param aResult The array into which the resulting AnimationProperty
  *   objects will be appended.
  */
 /* static */ void
 KeyframeEffectReadOnly::BuildAnimationPropertyList(
     JSContext* aCx,
     Element* aTarget,
+    nsCSSPseudoElements::Type aPseudoType,
     JS::Handle<JSObject*> aFrames,
     InfallibleTArray<AnimationProperty>& aResult,
     ErrorResult& aRv)
 {
   MOZ_ASSERT(aResult.IsEmpty());
 
   // A frame list specification in the IDL is:
   //
@@ -1608,62 +1620,102 @@ KeyframeEffectReadOnly::BuildAnimationPr
   JS::Rooted<JS::Value> objectValue(aCx, JS::ObjectValue(*aFrames));
   JS::ForOfIterator iter(aCx);
   if (!iter.init(objectValue, JS::ForOfIterator::AllowNonIterable)) {
     aRv.Throw(NS_ERROR_FAILURE);
     return;
   }
 
   if (iter.valueIsIterable()) {
-    BuildAnimationPropertyListFromKeyframeSequence(aCx, aTarget, iter,
-                                                   aResult, aRv);
+    BuildAnimationPropertyListFromKeyframeSequence(aCx, aTarget, aPseudoType,
+                                                   iter, aResult, aRv);
   } else {
     BuildAnimationPropertyListFromPropertyIndexedKeyframes(aCx, aTarget,
+                                                           aPseudoType,
                                                            objectValue, aResult,
                                                            aRv);
   }
 }
 
 /* static */ already_AddRefed<KeyframeEffectReadOnly>
 KeyframeEffectReadOnly::Constructor(
     const GlobalObject& aGlobal,
-    Element* aTarget,
+    const Nullable<ElementOrCSSPseudoElement>& aTarget,
     JS::Handle<JSObject*> aFrames,
     const TimingParams& aTiming,
     ErrorResult& aRv)
 {
-  if (!aTarget) {
+  if (aTarget.IsNull()) {
     // We don't support null targets yet.
     aRv.Throw(NS_ERROR_DOM_ANIM_NO_TARGET_ERR);
     return nullptr;
   }
 
-  if (!aTarget->GetCurrentDoc()) {
+  const ElementOrCSSPseudoElement& target = aTarget.Value();
+  MOZ_ASSERT(target.IsElement() || target.IsCSSPseudoElement(),
+             "Uninitialized target");
+
+  RefPtr<Element> targetElement;
+  nsCSSPseudoElements::Type pseudoType =
+    nsCSSPseudoElements::ePseudo_NotPseudoElement;
+  if (target.IsElement()) {
+    targetElement = &target.GetAsElement();
+  } else {
+    targetElement = target.GetAsCSSPseudoElement().ParentElement();
+    pseudoType = target.GetAsCSSPseudoElement().GetType();
+  }
+
+  if (!targetElement->GetCurrentDoc()) {
     // Bug 1245748: We don't support targets that are not in a document yet.
     aRv.Throw(NS_ERROR_DOM_ANIM_TARGET_NOT_IN_DOC_ERR);
     return nullptr;
   }
 
   InfallibleTArray<AnimationProperty> animationProperties;
-  BuildAnimationPropertyList(aGlobal.Context(), aTarget, aFrames,
-                             animationProperties, aRv);
+  BuildAnimationPropertyList(aGlobal.Context(), targetElement, pseudoType,
+                             aFrames, animationProperties, aRv);
 
   if (aRv.Failed()) {
     return nullptr;
   }
 
   RefPtr<KeyframeEffectReadOnly> effect =
-    new KeyframeEffectReadOnly(aTarget->OwnerDoc(), aTarget,
-                               nsCSSPseudoElements::ePseudo_NotPseudoElement,
-                               aTiming);
+    new KeyframeEffectReadOnly(targetElement->OwnerDoc(), targetElement,
+                               pseudoType, aTiming);
   effect->mProperties = Move(animationProperties);
   return effect.forget();
 }
 
 void
+KeyframeEffectReadOnly::GetTarget(
+    Nullable<OwningElementOrCSSPseudoElement>& aRv) const
+{
+  if (!mTarget) {
+    aRv.SetNull();
+    return;
+  }
+
+  switch (mPseudoType) {
+    case nsCSSPseudoElements::ePseudo_before:
+    case nsCSSPseudoElements::ePseudo_after:
+      aRv.SetValue().SetAsCSSPseudoElement() =
+        CSSPseudoElement::GetCSSPseudoElement(mTarget, mPseudoType);
+      break;
+
+    case nsCSSPseudoElements::ePseudo_NotPseudoElement:
+      aRv.SetValue().SetAsElement() = mTarget;
+      break;
+
+    default:
+      NS_NOTREACHED("Animation of unsupported pseudo-type");
+      aRv.SetNull();
+  }
+}
+
+void
 KeyframeEffectReadOnly::GetFrames(JSContext*& aCx,
                                   nsTArray<JSObject*>& aResult,
                                   ErrorResult& aRv)
 {
   nsTArray<OrderedKeyframeValueEntry> entries;
 
   for (const AnimationProperty& property : mProperties) {
     for (size_t i = 0, n = property.mSegments.Length(); i < n; i++) {
--- a/dom/animation/KeyframeEffect.h
+++ b/dom/animation/KeyframeEffect.h
@@ -34,16 +34,18 @@ class nsIFrame;
 class nsPresContext;
 
 namespace mozilla {
 
 struct AnimationCollection;
 class AnimValuesStyleRule;
 
 namespace dom {
+class ElementOrCSSPseudoElement;
+class OwningElementOrCSSPseudoElement;
 class UnrestrictedDoubleOrKeyframeEffectOptions;
 enum class IterationCompositeOperation : uint32_t;
 enum class CompositeOperation : uint32_t;
 }
 
 /**
  * Stores the results of calculating the timing properties of an animation
  * at a given sample time.
@@ -183,44 +185,36 @@ public:
   virtual const ElementPropertyTransition* AsTransition() const
   {
     return nullptr;
   }
 
   // KeyframeEffectReadOnly interface
   static already_AddRefed<KeyframeEffectReadOnly>
   Constructor(const GlobalObject& aGlobal,
-              Element* aTarget,
+              const Nullable<ElementOrCSSPseudoElement>& aTarget,
               JS::Handle<JSObject*> aFrames,
               const UnrestrictedDoubleOrKeyframeEffectOptions& aOptions,
               ErrorResult& aRv)
   {
     return Constructor(aGlobal, aTarget, aFrames,
                        TimingParams::FromOptionsUnion(aOptions, aTarget),
                        aRv);
   }
 
   // More generalized version for Animatable.animate.
   // Not exposed to content.
   static already_AddRefed<KeyframeEffectReadOnly>
   Constructor(const GlobalObject& aGlobal,
-              Element* aTarget,
+              const Nullable<ElementOrCSSPseudoElement>& aTarget,
               JS::Handle<JSObject*> aFrames,
               const TimingParams& aTiming,
               ErrorResult& aRv);
 
-  Element* GetTarget() const {
-    // Currently we never return animations from the API whose effect
-    // targets a pseudo-element so this should never be called when
-    // mPseudoType is not 'none' (see bug 1174575).
-    MOZ_ASSERT(mPseudoType == nsCSSPseudoElements::ePseudo_NotPseudoElement,
-               "Requesting the target of a KeyframeEffect that targets a"
-               " pseudo-element is not yet supported.");
-    return mTarget;
-  }
+  void GetTarget(Nullable<OwningElementOrCSSPseudoElement>& aRv) const;
   void GetFrames(JSContext*& aCx,
                  nsTArray<JSObject*>& aResult,
                  ErrorResult& aRv);
 
   // Temporary workaround to return both the target element and pseudo-type
   // until we implement PseudoElement (bug 1174575).
   void GetTarget(Element*& aTarget,
                  nsCSSPseudoElements::Type& aPseudoType) const {
@@ -346,16 +340,17 @@ protected:
   // As a result, we need to make sure this gets called whenever anything
   // changes with regards to this effects's timing including changes to the
   // owning Animation's timing.
   void UpdateTargetRegistration();
 
   static void BuildAnimationPropertyList(
     JSContext* aCx,
     Element* aTarget,
+    nsCSSPseudoElements::Type aPseudoType,
     JS::Handle<JSObject*> aFrames,
     InfallibleTArray<AnimationProperty>& aResult,
     ErrorResult& aRv);
 
   nsCOMPtr<Element> mTarget;
   RefPtr<Animation> mAnimation;
 
   OwningNonNull<AnimationEffectTimingReadOnly> mTiming;
--- a/dom/animation/moz.build
+++ b/dom/animation/moz.build
@@ -7,16 +7,17 @@
 MOCHITEST_MANIFESTS += ['test/mochitest.ini']
 MOCHITEST_CHROME_MANIFESTS += ['test/chrome.ini']
 
 EXPORTS.mozilla.dom += [
     'Animation.h',
     'AnimationEffectReadOnly.h',
     'AnimationEffectTimingReadOnly.h',
     'AnimationTimeline.h',
+    'CSSPseudoElement.h',
     'DocumentTimeline.h',
     'KeyframeEffect.h',
 ]
 
 EXPORTS.mozilla += [
     'AnimationComparator.h',
     'AnimationUtils.h',
     'AnimValuesStyleRule.h',
@@ -30,16 +31,17 @@ EXPORTS.mozilla += [
 UNIFIED_SOURCES += [
     'Animation.cpp',
     'AnimationEffectReadOnly.cpp',
     'AnimationEffectTimingReadOnly.cpp',
     'AnimationTimeline.cpp',
     'AnimationUtils.cpp',
     'AnimValuesStyleRule.cpp',
     'ComputedTimingFunction.cpp',
+    'CSSPseudoElement.cpp',
     'DocumentTimeline.cpp',
     'EffectCompositor.cpp',
     'EffectSet.cpp',
     'KeyframeEffect.cpp',
     'PendingAnimationTracker.cpp',
 ]
 
 LOCAL_INCLUDES += [
--- a/dom/base/DOMRequest.cpp
+++ b/dom/base/DOMRequest.cpp
@@ -226,17 +226,17 @@ DOMRequest::Then(JSContext* aCx, AnyCall
         mPromise->MaybeRejectBrokenly(mError);
       } else {
         mPromise->MaybeResolve(mResult);
       }
     }
   }
 
   // Just use the global of the Promise itself as the callee global.
-  JS::Rooted<JSObject*> global(aCx, mPromise->GetWrapper());
+  JS::Rooted<JSObject*> global(aCx, mPromise->PromiseObj());
   global = js::GetGlobalForObjectCrossCompartment(global);
   mPromise->Then(aCx, global, aResolveCallback, aRejectCallback, aRetval, aRv);
 }
 
 NS_IMPL_ISUPPORTS(DOMRequestService, nsIDOMRequestService)
 
 NS_IMETHODIMP
 DOMRequestService::CreateRequest(mozIDOMWindow* aWindow,
--- a/dom/base/Element.cpp
+++ b/dom/base/Element.cpp
@@ -3331,20 +3331,22 @@ Element::Animate(JSContext* aContext,
   if (js::GetContextCompartment(aContext) !=
       js::GetObjectCompartment(ownerGlobal->GetGlobalJSObject())) {
     ac.emplace(aContext, ownerGlobal->GetGlobalJSObject());
     if (!JS_WrapObject(aContext, &frames)) {
       return nullptr;
     }
   }
 
+  Nullable<ElementOrCSSPseudoElement> target;
+  target.SetValue().SetAsElement() = this;
   // Bug 1211783: Use KeyframeEffect here (instead of KeyframeEffectReadOnly)
   RefPtr<KeyframeEffectReadOnly> effect =
-    KeyframeEffectReadOnly::Constructor(global, this, frames,
-      TimingParams::FromOptionsUnion(aOptions, this), aError);
+    KeyframeEffectReadOnly::Constructor(global, target, frames,
+      TimingParams::FromOptionsUnion(aOptions, target), aError);
   if (aError.Failed()) {
     return nullptr;
   }
 
   RefPtr<Animation> animation =
     Animation::Constructor(global, effect, OwnerDoc()->Timeline(), aError);
   if (aError.Failed()) {
     return nullptr;
--- a/dom/base/WindowNamedPropertiesHandler.cpp
+++ b/dom/base/WindowNamedPropertiesHandler.cpp
@@ -4,16 +4,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "WindowNamedPropertiesHandler.h"
 #include "mozilla/dom/EventTargetBinding.h"
 #include "mozilla/dom/WindowBinding.h"
 #include "nsContentUtils.h"
 #include "nsDOMClassInfo.h"
+#include "nsDOMWindowList.h"
 #include "nsGlobalWindow.h"
 #include "nsHTMLDocument.h"
 #include "nsJSUtils.h"
 #include "xpcprivate.h"
 
 namespace mozilla {
 namespace dom {
 
@@ -170,24 +171,38 @@ WindowNamedPropertiesHandler::ownPropNam
   if (!(flags & JSITER_HIDDEN)) {
     // None of our named properties are enumerable.
     return true;
   }
 
   // Grab the DOM window.
   nsGlobalWindow* win = xpc::WindowOrNull(JS_GetGlobalForObject(aCx, aProxy));
   nsTArray<nsString> names;
-  win->GetSupportedNames(names);
-  // Filter out the ones we wouldn't expose from getOwnPropertyDescriptor.
-  // We iterate backwards so we can remove things from the list easily.
-  for (size_t i = names.Length(); i > 0; ) {
-    --i; // Now we're pointing at the next name we want to look at
-    nsCOMPtr<nsPIDOMWindowOuter> childWin = win->GetChildWindow(names[i]);
-    if (!childWin || !ShouldExposeChildWindow(names[i], childWin)) {
-      names.RemoveElementAt(i);
+  // The names live on the outer window, which might be null
+  nsGlobalWindow* outer = win->GetOuterWindowInternal();
+  if (outer) {
+    nsDOMWindowList* childWindows = outer->GetWindowList();
+    uint32_t length = childWindows->GetLength();
+    for (uint32_t i = 0; i < length; ++i) {
+      nsCOMPtr<nsIDocShellTreeItem> item =
+        childWindows->GetDocShellTreeItemAt(i);
+      // This is a bit silly, since we could presumably just do
+      // item->GetWindow().  But it's not obvious whether this does the same
+      // thing as GetChildWindow() with the item's name (due to the complexity
+      // of FindChildWithName).  Since GetChildWindow is what we use in
+      // getOwnPropDescriptor, let's try to be consistent.
+      nsString name;
+      item->GetName(name);
+      if (!names.Contains(name)) {
+        // Make sure we really would expose it from getOwnPropDescriptor.
+        nsCOMPtr<nsPIDOMWindowOuter> childWin = win->GetChildWindow(name);
+        if (childWin && ShouldExposeChildWindow(name, childWin)) {
+          names.AppendElement(name);
+        }
+      }
     }
   }
   if (!AppendNamedPropertyIds(aCx, aProxy, names, false, aProps)) {
     return false;
   }
 
   names.Clear();
   nsCOMPtr<nsIHTMLDocument> htmlDoc = do_QueryInterface(win->GetExtantDoc());
--- a/dom/base/nsDOMMutationObserver.cpp
+++ b/dom/base/nsDOMMutationObserver.cpp
@@ -383,17 +383,19 @@ void
 nsAnimationReceiver::RecordAnimationMutation(Animation* aAnimation,
                                              AnimationMutation aMutationType)
 {
   mozilla::dom::KeyframeEffectReadOnly* effect = aAnimation->GetEffect();
   if (!effect) {
     return;
   }
 
-  mozilla::dom::Element* animationTarget = effect->GetTarget();
+  mozilla::dom::Element* animationTarget;
+  nsCSSPseudoElements::Type pseudoType;
+  effect->GetTarget(animationTarget, pseudoType);
   if (!animationTarget) {
     return;
   }
 
   if (!Animations() || !(Subtree() || animationTarget == Target()) ||
       animationTarget->ChromeOnlyAccess()) {
     return;
   }
--- a/dom/base/nsDOMWindowUtils.cpp
+++ b/dom/base/nsDOMWindowUtils.cpp
@@ -2153,25 +2153,25 @@ nsDOMWindowUtils::GetSupportsHardwareH26
 #ifdef MOZ_FMP4
   nsCOMPtr<nsIWidget> widget = GetWidget();
   NS_ENSURE_STATE(widget);
   LayerManager *mgr = widget->GetLayerManager();
   NS_ENSURE_STATE(mgr);
   RefPtr<Promise> promise =
     MP4Decoder::IsVideoAccelerated(mgr->GetCompositorBackendType(), parentObject);
   NS_ENSURE_STATE(promise);
-  aPromise.setObject(*promise->GetWrapper());
+  aPromise.setObject(*promise->PromiseObj());
 #else
   ErrorResult rv;
   RefPtr<Promise> promise = Promise::Create(parentObject, rv);
   if (rv.Failed()) {
     return rv.StealNSResult();
   }
   promise.MaybeResolve(NS_LITERAL_STRING("No; Compiled without MP4 support."));
-  aPromise.setObject(*promise->GetWrapper());
+  aPromise.setObject(*promise->PromiseObj());
 #endif
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::StartFrameTimeRecording(uint32_t *startIndex)
 {
   NS_ENSURE_ARG_POINTER(startIndex);
@@ -2242,18 +2242,23 @@ nsDOMWindowUtils::BeginTabSwitch()
 
 static bool
 ComputeAnimationValue(nsCSSProperty aProperty,
                       Element* aElement,
                       const nsAString& aInput,
                       StyleAnimationValue& aOutput)
 {
 
-  if (!StyleAnimationValue::ComputeValue(aProperty, aElement, aInput,
-                                         false, aOutput)) {
+  if (!StyleAnimationValue::ComputeValue(
+        aProperty,
+        aElement,
+        nsCSSPseudoElements::ePseudo_NotPseudoElement,
+        aInput,
+        false,
+        aOutput)) {
     return false;
   }
 
   // This matches TransExtractComputedValue in nsTransitionManager.cpp.
   if (aProperty == eCSSProperty_visibility) {
     MOZ_ASSERT(aOutput.GetUnit() == StyleAnimationValue::eUnit_Enumerated,
                "unexpected unit");
     aOutput.SetIntValue(aOutput.GetIntValue(),
--- a/dom/base/nsGkAtomList.h
+++ b/dom/base/nsGkAtomList.h
@@ -2107,16 +2107,18 @@ GK_ATOM(ongamepaddisconnected, "ongamepa
 
 // Content property names
 GK_ATOM(animationsProperty, "AnimationsProperty")        // FrameAnimations*
 GK_ATOM(animationsOfBeforeProperty, "AnimationsOfBeforeProperty") // FrameAnimations*
 GK_ATOM(animationsOfAfterProperty, "AnimationsOfAfterProperty") // FrameAnimations*
 GK_ATOM(animationEffectsProperty, "AnimationEffectsProperty") // EffectSet*
 GK_ATOM(animationEffectsForBeforeProperty, "AnimationsEffectsForBeforeProperty") // EffectSet*
 GK_ATOM(animationEffectsForAfterProperty, "AnimationsEffectsForAfterProperty") // EffectSet*
+GK_ATOM(cssPseudoElementBeforeProperty, "CSSPseudoElementBeforeProperty") // CSSPseudoElement*
+GK_ATOM(cssPseudoElementAfterProperty, "CSSPseudoElementAfterProperty") // CSSPseudoElement*
 GK_ATOM(transitionsProperty, "TransitionsProperty")        // FrameTransitions*
 GK_ATOM(transitionsOfBeforeProperty, "TransitionsOfBeforeProperty") // FrameTransitions*
 GK_ATOM(transitionsOfAfterProperty, "TransitionsOfAfterProperty") // FrameTransitions*
 GK_ATOM(genConInitializerProperty, "QuoteNodeProperty")
 GK_ATOM(labelMouseDownPtProperty, "LabelMouseDownPtProperty")
 GK_ATOM(baseURIProperty, "baseURIProperty")
 GK_ATOM(lockedStyleStates, "lockedStyleStates")
 GK_ATOM(apzCallbackTransform, "apzCallbackTransform")
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -4181,33 +4181,16 @@ nsGlobalWindow::IndexedGetterOuter(uint3
 
 already_AddRefed<nsPIDOMWindowOuter>
 nsGlobalWindow::IndexedGetter(uint32_t aIndex)
 {
   FORWARD_TO_OUTER(IndexedGetterOuter, (aIndex), nullptr);
   MOZ_CRASH();
 }
 
-void
-nsGlobalWindow::GetSupportedNames(nsTArray<nsString>& aNames)
-{
-  FORWARD_TO_OUTER_VOID(GetSupportedNames, (aNames));
-
-  nsDOMWindowList* windows = GetWindowList();
-  if (windows) {
-    uint32_t length = windows->GetLength();
-    nsString* name = aNames.AppendElements(length);
-    for (uint32_t i = 0; i < length; ++i, ++name) {
-      nsCOMPtr<nsIDocShellTreeItem> item =
-        windows->GetDocShellTreeItemAt(i);
-      item->GetName(*name);
-    }
-  }
-}
-
 bool
 nsGlobalWindow::DoResolve(JSContext* aCx, JS::Handle<JSObject*> aObj,
                           JS::Handle<jsid> aId,
                           JS::MutableHandle<JS::PropertyDescriptor> aDesc)
 {
   MOZ_ASSERT(IsInnerWindow());
 
   // Note: Keep this in sync with MayResolve.
--- a/dom/base/nsGlobalWindow.h
+++ b/dom/base/nsGlobalWindow.h
@@ -499,18 +499,16 @@ public:
 
   // nsIInterfaceRequestor
   NS_DECL_NSIINTERFACEREQUESTOR
 
   // WebIDL interface.
   already_AddRefed<nsPIDOMWindowOuter> IndexedGetterOuter(uint32_t aIndex);
   already_AddRefed<nsPIDOMWindowOuter> IndexedGetter(uint32_t aIndex);
 
-  void GetSupportedNames(nsTArray<nsString>& aNames);
-
   static bool IsPrivilegedChromeWindow(JSContext* /* unused */, JSObject* aObj);
 
   static bool IsShowModalDialogEnabled(JSContext* /* unused */ = nullptr,
                                        JSObject* /* unused */ = nullptr);
 
   bool DoResolve(JSContext* aCx, JS::Handle<JSObject*> aObj,
                  JS::Handle<jsid> aId,
                  JS::MutableHandle<JS::PropertyDescriptor> aDesc);
@@ -1599,19 +1597,21 @@ protected:
   void ClearDocumentDependentSlots(JSContext* aCx);
 
   // Inner windows only.
   already_AddRefed<mozilla::dom::StorageEvent>
   CloneStorageEvent(const nsAString& aType,
                     const RefPtr<mozilla::dom::StorageEvent>& aEvent,
                     mozilla::ErrorResult& aRv);
 
+public:
   // Outer windows only.
   nsDOMWindowList* GetWindowList();
 
+protected:
   // Helper for getComputedStyle and getDefaultComputedStyle
   already_AddRefed<nsICSSDeclaration>
     GetComputedStyleHelperOuter(mozilla::dom::Element& aElt,
                                 const nsAString& aPseudoElt,
                                 bool aDefaultStylesOnly);
   already_AddRefed<nsICSSDeclaration>
     GetComputedStyleHelper(mozilla::dom::Element& aElt,
                            const nsAString& aPseudoElt,
--- a/dom/base/nsNodeUtils.cpp
+++ b/dom/base/nsNodeUtils.cpp
@@ -240,17 +240,17 @@ nsNodeUtils::GetTargetForAnimation(const
 
   // If the animation targets a pseudo-element, we don't dispatch
   // notifications for it.  (In the future we will have PseudoElement
   // objects we can use as the target of the notifications.)
   if (pseudoType != nsCSSPseudoElements::ePseudo_NotPseudoElement) {
     return nullptr;
   }
 
-  return effect->GetTarget();
+  return target;
 }
 
 void
 nsNodeUtils::AnimationAdded(Animation* aAnimation)
 {
   Element* target = GetTargetForAnimation(aAnimation);
   if (!target) {
     return;
--- a/dom/bindings/BindingUtils.cpp
+++ b/dom/bindings/BindingUtils.cpp
@@ -2785,16 +2785,17 @@ StaticMethodPromiseWrapper(JSContext* cx
                                    args.rval());
 }
 
 bool
 ConvertExceptionToPromise(JSContext* cx,
                           JSObject* promiseScope,
                           JS::MutableHandle<JS::Value> rval)
 {
+#ifndef SPIDERMONKEY_PROMISE
   GlobalObject global(cx, promiseScope);
   if (global.Failed()) {
     return false;
   }
 
   JS::Rooted<JS::Value> exn(cx);
   if (!JS_GetPendingException(cx, &exn)) {
     // This is very important: if there is no pending exception here but we're
@@ -2819,16 +2820,43 @@ ConvertExceptionToPromise(JSContext* cx,
     // We just give up.  We put the exception from the ErrorResult on
     // the JSContext just to make sure to not leak memory on the
     // ErrorResult, but now just put the original exception back.
     JS_SetPendingException(cx, exn);
     return false;
   }
 
   return GetOrCreateDOMReflector(cx, promise, rval);
+#else // SPIDERMONKEY_PROMISE
+  {
+    JSAutoCompartment ac(cx, promiseScope);
+
+    JS::Rooted<JS::Value> exn(cx);
+    if (!JS_GetPendingException(cx, &exn)) {
+      // This is very important: if there is no pending exception here but we're
+      // ending up in this code, that means the callee threw an uncatchable
+      // exception.  Just propagate that out as-is.
+      return false;
+    }
+
+    JS_ClearPendingException(cx);
+
+    JSObject* promise = JS::CallOriginalPromiseReject(cx, exn);
+    if (!promise) {
+      // We just give up.  Put the exception back.
+      JS_SetPendingException(cx, exn);
+      return false;
+    }
+
+    rval.setObject(*promise);
+  }
+
+  // Now make sure we rewrap promise back into the compartment we want
+  return JS_WrapValue(cx, rval);
+#endif // SPIDERMONKEY_PROMISE
 }
 
 /* static */
 void
 CreateGlobalOptions<nsGlobalWindow>::TraceGlobal(JSTracer* aTrc, JSObject* aObj)
 {
   xpc::TraceXPCGlobal(aTrc, aObj);
 }
--- a/dom/bindings/BindingUtils.h
+++ b/dom/bindings/BindingUtils.h
@@ -1135,27 +1135,41 @@ WrapNewBindingNonWrapperCachedObject(JSC
   // We can end up here in all sorts of compartments, per above.  Make
   // sure to JS_WrapValue!
   rval.set(JS::ObjectValue(*obj));
   return MaybeWrapObjectValue(cx, rval);
 }
 
 // Helper for smart pointers (nsRefPtr/nsCOMPtr).
 template <template <typename> class SmartPtr, typename T,
-          typename U=typename EnableIf<IsRefcounted<T>::value, T>::Type>
+          typename U=typename EnableIf<IsRefcounted<T>::value, T>::Type,
+          typename V=typename EnableIf<IsSmartPtr<SmartPtr<T>>::value, T>::Type>
 inline bool
 WrapNewBindingNonWrapperCachedObject(JSContext* cx, JS::Handle<JSObject*> scope,
                                      const SmartPtr<T>& value,
                                      JS::MutableHandle<JS::Value> rval,
                                      JS::Handle<JSObject*> givenProto = nullptr)
 {
   return WrapNewBindingNonWrapperCachedObject(cx, scope, value.get(), rval,
                                               givenProto);
 }
 
+// Helper for object references (as opposed to pointers).
+template <typename T,
+          typename U=typename EnableIf<!IsSmartPtr<T>::value, T>::Type>
+inline bool
+WrapNewBindingNonWrapperCachedObject(JSContext* cx, JS::Handle<JSObject*> scope,
+                                     T& value,
+                                     JS::MutableHandle<JS::Value> rval,
+                                     JS::Handle<JSObject*> givenProto = nullptr)
+{
+  return WrapNewBindingNonWrapperCachedObject(cx, scope, &value, rval,
+                                              givenProto);
+}
+
 // Only set allowNativeWrapper to false if you really know you need it, if in
 // doubt use true. Setting it to false disables security wrappers.
 bool
 NativeInterface2JSObjectAndThrowIfFailed(JSContext* aCx,
                                          JS::Handle<JSObject*> aScope,
                                          JS::MutableHandle<JS::Value> aRetval,
                                          xpcObjectHelper& aHelper,
                                          const nsIID* aIID,
--- a/dom/bindings/Bindings.conf
+++ b/dom/bindings/Bindings.conf
@@ -964,16 +964,20 @@ DOMInterfaces = {
 'Promise': {
     'implicitJSContext': [ 'then', 'catch' ],
 },
 
 'PromiseDebugging': {
     'concrete': False,
 },
 
+'PromiseNativeHandler': {
+    'wrapperCache': False,
+},
+
 'PropertyNodeList': {
     'headerFile': 'HTMLPropertiesCollection.h',
 },
 
 'PushEvent': {
     'headerFile': 'ServiceWorkerEvents.h',
     'nativeType': 'mozilla::dom::workers::PushEvent',
     'workers': True
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -2986,23 +2986,25 @@ class CGCreateInterfaceObjectsMethod(CGA
             unforgeableHolderSetup = CGList(
                 [createUnforgeableHolder, installUnforgeableHolder], "\n")
         else:
             unforgeableHolderSetup = None
 
         if self.descriptor.name == "Promise":
             speciesSetup = CGGeneric(fill(
                 """
+                #ifndef SPIDERMONKEY_PROMISE
                 JS::Rooted<JSObject*> promiseConstructor(aCx, *interfaceCache);
                 JS::Rooted<jsid> species(aCx,
                   SYMBOL_TO_JSID(JS::GetWellKnownSymbol(aCx, JS::SymbolCode::species)));
                 if (!JS_DefinePropertyById(aCx, promiseConstructor, species, JS::UndefinedHandleValue,
                                            JSPROP_SHARED, Promise::PromiseSpecies, nullptr)) {
                   $*{failureCode}
                 }
+                #endif // SPIDERMONKEY_PROMISE
                 """,
                 failureCode=failureCode))
         else:
             speciesSetup = None
 
         if (self.descriptor.interface.isOnGlobalProtoChain() and
             needInterfacePrototypeObject):
             makeProtoPrototypeImmutable = CGGeneric(fill(
@@ -5184,39 +5186,55 @@ def getJSToNativeConversionInfo(type, de
 
                   JS::Rooted<JSObject*> globalObj(cx, JS::CurrentGlobalOrNull(cx));
                   $*{getPromiseGlobal}
                   JSAutoCompartment ac(cx, globalObj);
                   GlobalObject promiseGlobal(cx, globalObj);
                   if (promiseGlobal.Failed()) {
                     $*{exceptionCode}
                   }
+
+                  JS::Rooted<JS::Value> valueToResolve(cx, $${val});
+                  if (!JS_WrapValue(cx, &valueToResolve)) {
+                    $*{exceptionCode}
+                  }
                   ErrorResult promiseRv;
+                #ifdef SPIDERMONKEY_PROMISE
+                  nsCOMPtr<nsIGlobalObject> global =
+                    do_QueryInterface(promiseGlobal.GetAsSupports());
+                  if (!global) {
+                    promiseRv.Throw(NS_ERROR_UNEXPECTED);
+                    promiseRv.MaybeSetPendingException(cx);
+                    $*{exceptionCode}
+                  }
+                  $${declName} = Promise::Resolve(global, cx, valueToResolve,
+                                                  promiseRv);
+                  if (promiseRv.MaybeSetPendingException(cx)) {
+                    $*{exceptionCode}
+                  }
+                #else
                   JS::Handle<JSObject*> promiseCtor =
                     PromiseBinding::GetConstructorObjectHandle(cx, globalObj);
                   if (!promiseCtor) {
                     $*{exceptionCode}
                   }
                   JS::Rooted<JS::Value> resolveThisv(cx, JS::ObjectValue(*promiseCtor));
                   JS::Rooted<JS::Value> resolveResult(cx);
-                  JS::Rooted<JS::Value> valueToResolve(cx, $${val});
-                  if (!JS_WrapValue(cx, &valueToResolve)) {
-                    $*{exceptionCode}
-                  }
                   Promise::Resolve(promiseGlobal, resolveThisv, valueToResolve,
                                    &resolveResult, promiseRv);
                   if (promiseRv.MaybeSetPendingException(cx)) {
                     $*{exceptionCode}
                   }
                   nsresult unwrapRv = UNWRAP_OBJECT(Promise, &resolveResult.toObject(), $${declName});
                   if (NS_FAILED(unwrapRv)) { // Quite odd
                     promiseRv.Throw(unwrapRv);
                     promiseRv.MaybeSetPendingException(cx);
                     $*{exceptionCode}
                   }
+                #endif // SPIDERMONKEY_PROMISE
                 }
                 """,
                 getPromiseGlobal=getPromiseGlobal,
                 exceptionCode=exceptionCode)
         elif not descriptor.skipGen and not descriptor.interface.isConsequential() and not descriptor.interface.isExternal():
             if failureCode is not None:
                 templateBody += str(CastableObjectUnwrapper(
                     descriptor,
@@ -6327,17 +6345,23 @@ def getWrapTemplateForType(type, descrip
         else:
             wrappingCode = ""
 
         if not descriptor.interface.isExternal() and not descriptor.skipGen:
             if descriptor.wrapperCache:
                 wrapMethod = "GetOrCreateDOMReflector"
                 wrapArgs = "cx, %s, ${jsvalHandle}" % result
             else:
-                if not returnsNewObject:
+                # Hack: the "Promise" interface is OK to return from
+                # non-newobject things even when it's not wrappercached; that
+                # happens when using SpiderMonkey promises, and the WrapObject()
+                # method will just return the existing reflector, which is just
+                # not stored in a wrappercache.
+                if (not returnsNewObject and
+                    descriptor.interface.identifier.name != "Promise"):
                     raise MethodNotNewObjectError(descriptor.interface.identifier.name)
                 wrapMethod = "WrapNewBindingNonWrapperCachedObject"
                 wrapArgs = "cx, ${obj}, %s, ${jsvalHandle}" % result
             if isConstructorRetval:
                 wrapArgs += ", desiredProto"
             wrap = "%s(%s)" % (wrapMethod, wrapArgs)
             if not descriptor.hasXPConnectImpls:
                 # Can only fail to wrap as a new-binding object
--- a/dom/bindings/Configuration.py
+++ b/dom/bindings/Configuration.py
@@ -535,16 +535,23 @@ class Descriptor(DescriptorProvider):
                     iface.setUserData('hasProxyDescendant', True)
                     iface = iface.parent
 
         if desc.get('wantsQI', None) is not None:
             self._wantsQI = desc.get('wantsQI', None)
         self.wrapperCache = (not self.interface.isCallback() and
                              not self.interface.isIteratorInterface() and
                              desc.get('wrapperCache', True))
+        # Nasty temporary hack for supporting both DOM and SpiderMonkey promises
+        # without too much pain
+        if self.interface.identifier.name == "Promise":
+            assert self.wrapperCache
+            # But really, we're only wrappercached if we have an interface
+            # object (that is, when we're not using SpiderMonkey promises).
+            self.wrapperCache = self.interface.hasInterfaceObject()
 
         def make_name(name):
             return name + "_workers" if self.workers else name
         self.name = make_name(interface.identifier.name)
 
         # self.extendedAttributes is a dict of dicts, keyed on
         # all/getterOnly/setterOnly and then on member name. Values are an
         # array of extended attributes.
--- a/dom/bindings/DOMJSProxyHandler.cpp
+++ b/dom/bindings/DOMJSProxyHandler.cpp
@@ -255,23 +255,16 @@ bool
 BaseDOMProxyHandler::getOwnEnumerablePropertyKeys(JSContext* cx,
                                                   JS::Handle<JSObject*> proxy,
                                                   JS::AutoIdVector& props) const
 {
   return ownPropNames(cx, proxy, JSITER_OWNONLY, props);
 }
 
 bool
-BaseDOMProxyHandler::enumerate(JSContext *cx, JS::Handle<JSObject*> proxy,
-                               JS::MutableHandle<JSObject*> objp) const
-{
-  return BaseProxyHandler::enumerate(cx, proxy, objp);
-}
-
-bool
 DOMProxyHandler::has(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id, bool* bp) const
 {
   if (!hasOwn(cx, proxy, id, bp)) {
     return false;
   }
 
   if (*bp) {
     // We have the property ourselves; no need to worry about our prototype
--- a/dom/bindings/DOMJSProxyHandler.h
+++ b/dom/bindings/DOMJSProxyHandler.h
@@ -54,19 +54,16 @@ public:
   // Implementations of methods that can be implemented in terms of
   // other lower-level methods.
   bool getOwnPropertyDescriptor(JSContext* cx, JS::Handle<JSObject*> proxy,
                                 JS::Handle<jsid> id,
                                 JS::MutableHandle<JS::PropertyDescriptor> desc) const override;
   virtual bool ownPropertyKeys(JSContext* cx, JS::Handle<JSObject*> proxy,
                                JS::AutoIdVector &props) const override;
 
-  virtual bool enumerate(JSContext *cx, JS::Handle<JSObject*> proxy,
-                         JS::MutableHandle<JSObject*> objp) const override;
-
   // We override getOwnEnumerablePropertyKeys() and implement it directly
   // instead of using the default implementation, which would call
   // ownPropertyKeys and then filter out the non-enumerable ones. This avoids
   // unnecessary work during enumeration.
   virtual bool getOwnEnumerablePropertyKeys(JSContext* cx, JS::Handle<JSObject*> proxy,
                                             JS::AutoIdVector &props) const override;
 
   bool watch(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id,
--- a/dom/bindings/ToJSValue.cpp
+++ b/dom/bindings/ToJSValue.cpp
@@ -2,16 +2,19 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/dom/ToJSValue.h"
 #include "mozilla/dom/DOMException.h"
 #include "mozilla/dom/Exceptions.h"
+#ifdef SPIDERMONKEY_PROMISE
+#include "mozilla/dom/Promise.h"
+#endif // SPIDERMONKEY_PROMISE
 #include "nsAString.h"
 #include "nsContentUtils.h"
 #include "nsStringBuffer.h"
 #include "xpcpublic.h"
 
 namespace mozilla {
 namespace dom {
 
@@ -59,10 +62,20 @@ ToJSValue(JSContext* aCx,
   DebugOnly<bool> throwResult = aArgument.MaybeSetPendingException(aCx);
   MOZ_ASSERT(throwResult);
   DebugOnly<bool> getPendingResult = JS_GetPendingException(aCx, aValue);
   MOZ_ASSERT(getPendingResult);
   JS_ClearPendingException(aCx);
   return true;
 }
 
+#ifdef SPIDERMONKEY_PROMISE
+bool
+ToJSValue(JSContext* aCx, Promise& aArgument,
+          JS::MutableHandle<JS::Value> aValue)
+{
+  aValue.setObject(*aArgument.PromiseObj());
+  return true;
+}
+#endif // SPIDERMONKEY_PROMISE
+
 } // namespace dom
 } // namespace mozilla
--- a/dom/bindings/ToJSValue.h
+++ b/dom/bindings/ToJSValue.h
@@ -14,16 +14,18 @@
 #include "jsapi.h"
 #include "nsISupports.h"
 #include "nsTArray.h"
 #include "nsWrapperCache.h"
 
 namespace mozilla {
 namespace dom {
 
+class Promise;
+
 // If ToJSValue returns false, it must set an exception on the
 // JSContext.
 
 // Accept strings.
 MOZ_WARN_UNUSED_RESULT bool
 ToJSValue(JSContext* aCx,
           const nsAString& aArgument,
           JS::MutableHandle<JS::Value> aValue);
@@ -299,16 +301,24 @@ MOZ_WARN_UNUSED_RESULT
 typename EnableIf<IsPointer<T>::value, bool>::Type
 ToJSValue(JSContext* aCx,
           T aArgument,
           JS::MutableHandle<JS::Value> aValue)
 {
   return ToJSValue(aCx, *aArgument, aValue);
 }
 
+#ifdef SPIDERMONKEY_PROMISE
+// Accept Promise objects, which need special handling.
+MOZ_WARN_UNUSED_RESULT bool
+ToJSValue(JSContext* aCx,
+          Promise& aArgument,
+          JS::MutableHandle<JS::Value> aValue);
+#endif // SPIDERMONKEY_PROMISE
+
 // Accept arrays of other things we accept
 template <typename T>
 MOZ_WARN_UNUSED_RESULT bool
 ToJSValue(JSContext* aCx,
           T* aArguments,
           size_t aLength,
           JS::MutableHandle<JS::Value> aValue)
 {
--- a/dom/events/EventListenerManager.cpp
+++ b/dom/events/EventListenerManager.cpp
@@ -27,17 +27,16 @@
 #include "mozilla/dom/Event.h"
 #include "mozilla/TimelineConsumers.h"
 #include "mozilla/EventTimelineMarker.h"
 
 #include "EventListenerService.h"
 #include "nsCOMArray.h"
 #include "nsCOMPtr.h"
 #include "nsContentUtils.h"
-#include "nsDocShell.h"
 #include "nsDOMCID.h"
 #include "nsError.h"
 #include "nsGkAtoms.h"
 #include "nsHtml5Atoms.h"
 #include "nsIContent.h"
 #include "nsIContentSecurityPolicy.h"
 #include "nsIDocument.h"
 #include "nsIDOMEventListener.h"
@@ -1194,25 +1193,24 @@ EventListenerManager::HandleEventInterna
             if (usingLegacyMessage && !legacyAutoOverride) {
               // Override the aDOMEvent's event-message (its .type) until we
               // finish traversing listeners (when legacyAutoOverride destructs)
               legacyAutoOverride.emplace(*aDOMEvent, eventMessage);
             }
 
             // Maybe add a marker to the docshell's timeline, but only
             // bother with all the logic if some docshell is recording.
-            nsDocShell* docShell;
+            nsCOMPtr<nsIDocShell> docShell;
             RefPtr<TimelineConsumers> timelines = TimelineConsumers::Get();
             bool needsEndEventMarker = false;
 
             if (mIsMainThreadELM &&
                 listener->mListenerType != Listener::eNativeListener) {
-              nsCOMPtr<nsIDocShell> docShellComPtr = GetDocShellForTarget();
-              if (docShellComPtr) {
-                docShell = static_cast<nsDocShell*>(docShellComPtr.get());
+              docShell = GetDocShellForTarget();
+              if (docShell) {
                 if (timelines && timelines->HasConsumer(docShell)) {
                   needsEndEventMarker = true;
                   nsAutoString typeStr;
                   (*aDOMEvent)->GetType(typeStr);
                   uint16_t phase;
                   (*aDOMEvent)->GetEventPhase(&phase);
                   timelines->AddMarkerForDocShell(docShell, Move(
                     MakeUnique<EventTimelineMarker>(
--- a/dom/fetch/FetchDriver.cpp
+++ b/dom/fetch/FetchDriver.cpp
@@ -387,28 +387,27 @@ FetchDriver::BeginAndGetFilteredResponse
 
   MOZ_ASSERT(filteredResponse);
   MOZ_ASSERT(mObserver);
   mObserver->OnResponseAvailable(filteredResponse);
   mResponseAvailableCalled = true;
   return filteredResponse.forget();
 }
 
-nsresult
+void
 FetchDriver::FailWithNetworkError()
 {
   workers::AssertIsOnMainThread();
   RefPtr<InternalResponse> error = InternalResponse::NetworkError();
   if (mObserver) {
     mObserver->OnResponseAvailable(error);
     mResponseAvailableCalled = true;
     mObserver->OnResponseEnd();
     mObserver = nullptr;
   }
-  return NS_OK;
 }
 
 namespace {
 class FillResponseHeaders final : public nsIHttpHeaderVisitor {
   InternalResponse* mResponse;
 
   ~FillResponseHeaders()
   { }
--- a/dom/fetch/FetchDriver.h
+++ b/dom/fetch/FetchDriver.h
@@ -95,17 +95,17 @@ private:
   nsresult HttpFetch();
   // Returns the filtered response sent to the observer.
   // Callers who don't have access to a channel can pass null for aFinalURI.
   already_AddRefed<InternalResponse>
   BeginAndGetFilteredResponse(InternalResponse* aResponse, nsIURI* aFinalURI,
                               bool aFoundOpaqueRedirect);
   // Utility since not all cases need to do any post processing of the filtered
   // response.
-  nsresult FailWithNetworkError();
+  void FailWithNetworkError();
 
   void SetRequestHeaders(nsIHttpChannel* aChannel) const;
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_FetchDriver_h
--- a/dom/imptests/failures/html/html/browsers/the-window-object/test_window-named-properties.html.json
+++ b/dom/imptests/failures/html/html/browsers/the-window-object/test_window-named-properties.html.json
@@ -1,4 +1,2 @@
 {
-  "Static name on the prototype": true,
-  "constructor": true
 }
--- a/dom/imptests/html/html/browsers/the-window-object/test_window-named-properties.html
+++ b/dom/imptests/html/html/browsers/the-window-object/test_window-named-properties.html
@@ -26,33 +26,32 @@ test(function() {
 test(function() {
   assert_true("bar" in Window.prototype, "bar in Window.prototype");
   assert_false(Window.prototype.hasOwnProperty("bar"), "Window.prototype.hasOwnProperty(\"bar\")");
 
   var gsp = Object.getPrototypeOf(Object.getPrototypeOf(window));
   assert_true("bar" in gsp, "bar in gsp");
   assert_true(gsp.hasOwnProperty("bar"), "gsp.hasOwnProperty(\"bar\")");
   assert_data_propdesc(Object.getOwnPropertyDescriptor(gsp, "bar"),
-                       false, true, true);
+                       true, false, true);
 }, "Static name on the prototype");
 test(function() {
   assert_equals(window.constructor, Window);
   assert_false(window.hasOwnProperty("constructor"), "window.constructor should not be an own property.");
 
   var proto = Object.getPrototypeOf(window);
   assert_equals(proto.constructor, Window);
   assert_true("constructor" in proto, "constructor in proto");
   assert_data_propdesc(Object.getOwnPropertyDescriptor(proto, "constructor"),
                        true, false, true);
 
   var gsp = Object.getPrototypeOf(proto);
   assert_true("constructor" in gsp, "constructor in gsp");
-  assert_true(gsp.hasOwnProperty("constructor"), "gsp.hasOwnProperty(\"constructor\")");
-  assert_data_propdesc(Object.getOwnPropertyDescriptor(gsp, "constructor"),
-                       false, true, true);
+  assert_false(gsp.hasOwnProperty("constructor"), "gsp.hasOwnProperty(\"constructor\")");
+  assert_equals(Object.getOwnPropertyDescriptor(gsp, "constructor"), undefined)
 }, "constructor");
 var t = async_test("Dynamic name")
 var t2 = async_test("Ghost name")
 t.step(function() {
   var iframe = document.getElementsByTagName("iframe")[0];
   iframe.setAttribute("src", "data:text/html,<script>window.name='foo'<\/script>");
   iframe.onload = function() {
     t.step(function() {
--- a/dom/manifest/test/mochitest.ini
+++ b/dom/manifest/test/mochitest.ini
@@ -3,18 +3,20 @@ support-files =
 	common.js
 	resource.sjs
 	manifestLoader.html
 [test_ImageObjectProcessor_background_color.html]
 [test_ImageObjectProcessor_density.html]
 [test_ImageObjectProcessor_sizes.html]
 [test_ImageObjectProcessor_src.html]
 [test_ImageObjectProcessor_type.html]
+[test_ManifestProcessor_background_color.html]
 [test_ManifestProcessor_display.html]
 [test_ManifestProcessor_icons.html]
 [test_ManifestProcessor_JSON.html]
 [test_ManifestProcessor_lang.html]
 [test_ManifestProcessor_name_and_short_name.html]
 [test_ManifestProcessor_orientation.html]
 [test_ManifestProcessor_scope.html]
 [test_ManifestProcessor_splash_screens.html]
 [test_ManifestProcessor_start_url.html]
+[test_ManifestProcessor_theme_color.html]
 [test_ManifestProcessor_warnings.html]
new file mode 100644
--- /dev/null
+++ b/dom/manifest/test/test_ManifestProcessor_background_color.html
@@ -0,0 +1,94 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1195018
+-->
+<head>
+  <meta charset="utf-8">
+  <title>Test for Bug 1195018</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+  <script src="common.js"></script>
+  <script>
+/**
+ * background_color member
+ * https://w3c.github.io/manifest/#background_color-member
+ **/
+'use strict';
+
+typeTests.forEach(type => {
+  data.jsonText = JSON.stringify({
+    background_color: type
+  });
+  var result = processor.process(data);
+
+  is(result.background_color, undefined, `Expect non-string background_color to be undefined: ${typeof type}.`);
+});
+
+var validThemeColors = [
+  'maroon',
+  '#f00',
+  '#ff0000',
+  'rgb(255,0,0)',
+  'rgb(100%, 0%, 0%)',
+  'rgb(255,0,0)',
+  'rgb(300,0,0)',
+  'rgb(255,-10,0)',
+  'rgb(110%, 0%, 0%)',
+  'rgb(255,0,0)',
+  'rgba(255,0,0,1)',
+  'rgb(100%,0%,0%)',
+  'rgba(100%,0%,0%,1)',
+  'rgba(0,0,255,0.5)',
+  'rgba(100%, 50%, 0%, 0.1)',
+  'hsl(120, 100%, 50%)',
+  'hsla(120, 100%, 50%, 1)',
+];
+
+validThemeColors.forEach(background_color => {
+  data.jsonText = JSON.stringify({
+    background_color: background_color
+  });
+  var result = processor.process(data);
+
+  is(result.background_color, background_color, `Expect background_color to be returned: ${background_color}.`);
+});
+
+var invalidThemeColors = [
+  'marooon',
+  'f000000',
+  '#ff00000',
+  'rgb(255 0 0)',
+  'rgb(100, 0%, 0%)',
+  'rgb(255,0)',
+  'rgb(300 0 0)',
+  'rbg(255,-10,0)',
+  'rgb(110, 0%, 0%)',
+  '(255,0,0) }',
+  'rgba(255)',
+  ' rgb(100%,0%,0%) }',
+  'hsl 120, 100%, 50%',
+  'hsla{120, 100%, 50%, 1}',
+]
+
+invalidThemeColors.forEach(background_color => {
+  data.jsonText = JSON.stringify({
+    background_color: background_color
+  });
+  var result = processor.process(data);
+
+  is(result.background_color, undefined, `Expect background_color to be undefined: ${background_color}.`);
+});
+
+// Trim tests
+validThemeColors.forEach(background_color => {
+  var expandedThemeColor = `${seperators}${lineTerminators}${background_color}${lineTerminators}${seperators}`;
+  data.jsonText = JSON.stringify({
+    background_color: expandedThemeColor
+  });
+  var result = processor.process(data);
+
+  is(result.background_color, background_color, `Expect trimmed background_color to be returned.`);
+});
+  </script>
+</head>
new file mode 100644
--- /dev/null
+++ b/dom/manifest/test/test_ManifestProcessor_theme_color.html
@@ -0,0 +1,94 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1195018
+-->
+<head>
+  <meta charset="utf-8">
+  <title>Test for Bug 1195018</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+  <script src="common.js"></script>
+  <script>
+/**
+ * theme_color member
+ * https://w3c.github.io/manifest/#theme_color-member
+ **/
+'use strict';
+
+typeTests.forEach(type => {
+  data.jsonText = JSON.stringify({
+    theme_color: type
+  });
+  var result = processor.process(data);
+
+  is(result.theme_color, undefined, `Expect non-string theme_color to be undefined: ${typeof type}.`);
+});
+
+var validThemeColors = [
+  'maroon',
+  '#f00',
+  '#ff0000',
+  'rgb(255,0,0)',
+  'rgb(100%, 0%, 0%)',
+  'rgb(255,0,0)',
+  'rgb(300,0,0)',
+  'rgb(255,-10,0)',
+  'rgb(110%, 0%, 0%)',
+  'rgb(255,0,0)',
+  'rgba(255,0,0,1)',
+  'rgb(100%,0%,0%)',
+  'rgba(100%,0%,0%,1)',
+  'rgba(0,0,255,0.5)',
+  'rgba(100%, 50%, 0%, 0.1)',
+  'hsl(120, 100%, 50%)',
+  'hsla(120, 100%, 50%, 1)',
+];
+
+validThemeColors.forEach(theme_color => {
+  data.jsonText = JSON.stringify({
+    theme_color: theme_color
+  });
+  var result = processor.process(data);
+
+  is(result.theme_color, theme_color, `Expect theme_color to be returned: ${theme_color}.`);
+});
+
+var invalidThemeColors = [
+  'marooon',
+  'f000000',
+  '#ff00000',
+  'rgb(255 0 0)',
+  'rgb(100, 0%, 0%)',
+  'rgb(255,0)',
+  'rgb(300 0 0)',
+  'rbg(255,-10,0)',
+  'rgb(110, 0%, 0%)',
+  '(255,0,0) }',
+  'rgba(255)',
+  ' rgb(100%,0%,0%) }',
+  'hsl 120, 100%, 50%',
+  'hsla{120, 100%, 50%, 1}',
+]
+
+invalidThemeColors.forEach(theme_color => {
+  data.jsonText = JSON.stringify({
+    theme_color: theme_color
+  });
+  var result = processor.process(data);
+
+  is(result.theme_color, undefined, `Expect theme_color to be undefined: ${theme_color}.`);
+});
+
+// Trim tests
+validThemeColors.forEach(theme_color => {
+  var expandedThemeColor = `${seperators}${lineTerminators}${theme_color}${lineTerminators}${seperators}`;
+  data.jsonText = JSON.stringify({
+    theme_color: expandedThemeColor
+  });
+  var result = processor.process(data);
+
+  is(result.theme_color, theme_color, `Expect trimmed theme_color to be returned.`);
+});
+  </script>
+</head>
--- a/dom/media/eme/DetailedPromise.cpp
+++ b/dom/media/eme/DetailedPromise.cpp
@@ -27,17 +27,20 @@ DetailedPromise::DetailedPromise(nsIGlob
   : DetailedPromise(aGlobal, aName)
 {
   mSuccessLatencyProbe.Construct(aSuccessLatencyProbe);
   mFailureLatencyProbe.Construct(aFailureLatencyProbe);
 }
 
 DetailedPromise::~DetailedPromise()
 {
-  MOZ_ASSERT(mResponded == IsPending());
+  // It would be nice to assert that mResponded is identical to
+  // GetPromiseState() == PromiseState::Rejected.  But by now we've been
+  // unlinked, so don't have a reference to our actual JS Promise object
+  // anymore.
   MaybeReportTelemetry(Failed);
 }
 
 void
 DetailedPromise::MaybeReject(nsresult aArg, const nsACString& aReason)
 {
   nsPrintfCString msg("%s promise rejected 0x%x '%s'", mName.get(), aArg,
                       PromiseFlatCString(aReason).get());
--- a/dom/media/gmp/GMPChild.cpp
+++ b/dom/media/gmp/GMPChild.cpp
@@ -60,33 +60,29 @@ GMPChild::GMPChild()
 
 GMPChild::~GMPChild()
 {
   LOGD("GMPChild dtor");
 }
 
 static bool
 GetFileBase(const nsAString& aPluginPath,
-#if defined(XP_MACOSX) && defined(MOZ_GMP_SANDBOX)
             nsCOMPtr<nsIFile>& aLibDirectory,
-#endif
             nsCOMPtr<nsIFile>& aFileBase,
             nsAutoString& aBaseName)
 {
   nsresult rv = NS_NewLocalFile(aPluginPath,
                                 true, getter_AddRefs(aFileBase));
   if (NS_FAILED(rv)) {
     return false;
   }
 
-#if defined(XP_MACOSX) && defined(MOZ_GMP_SANDBOX)
   if (NS_FAILED(aFileBase->Clone(getter_AddRefs(aLibDirectory)))) {
     return false;
   }
-#endif
 
   nsCOMPtr<nsIFile> parent;
   rv = aFileBase->GetParent(getter_AddRefs(parent));
   if (NS_FAILED(rv)) {
     return false;
   }
 
   nsAutoString parentLeafName;
@@ -97,84 +93,95 @@ GetFileBase(const nsAString& aPluginPath
 
   aBaseName = Substring(parentLeafName,
                         4,
                         parentLeafName.Length() - 1);
   return true;
 }
 
 static bool
+GetFileBase(const nsAString& aPluginPath,
+            nsCOMPtr<nsIFile>& aFileBase,
+            nsAutoString& aBaseName)
+{
+  nsCOMPtr<nsIFile> unusedLibDir;
+  return GetFileBase(aPluginPath, unusedLibDir, aFileBase, aBaseName);
+}
+
+static bool
 GetPluginFile(const nsAString& aPluginPath,
-#if defined(XP_MACOSX) && defined(MOZ_GMP_SANDBOX)
               nsCOMPtr<nsIFile>& aLibDirectory,
-#endif
               nsCOMPtr<nsIFile>& aLibFile)
 {
   nsAutoString baseName;
-#if defined(XP_MACOSX) && defined(MOZ_GMP_SANDBOX)
   GetFileBase(aPluginPath, aLibDirectory, aLibFile, baseName);
-#else
-  GetFileBase(aPluginPath, aLibFile, baseName);
-#endif
 
 #if defined(XP_MACOSX)
   nsAutoString binaryName = NS_LITERAL_STRING("lib") + baseName + NS_LITERAL_STRING(".dylib");
 #elif defined(OS_POSIX)
   nsAutoString binaryName = NS_LITERAL_STRING("lib") + baseName + NS_LITERAL_STRING(".so");
 #elif defined(XP_WIN)
   nsAutoString binaryName =                            baseName + NS_LITERAL_STRING(".dll");
 #else
 #error not defined
 #endif
   aLibFile->AppendRelativePath(binaryName);
   return true;
 }
 
+#if !defined(XP_MACOSX)
+static bool
+GetPluginFile(const nsAString& aPluginPath,
+              nsCOMPtr<nsIFile>& aLibFile)
+{
+  nsCOMPtr<nsIFile> unusedlibDir;
+  return GetPluginFile(aPluginPath, unusedlibDir, aLibFile);
+}
+#endif
+
 static bool
 GetInfoFile(const nsAString& aPluginPath,
             nsCOMPtr<nsIFile>& aInfoFile)
 {
   nsAutoString baseName;
-#if defined(XP_MACOSX) && defined(MOZ_GMP_SANDBOX)
-  nsCOMPtr<nsIFile> unusedLibDir;
-  GetFileBase(aPluginPath, unusedLibDir, aInfoFile, baseName);
-#else
   GetFileBase(aPluginPath, aInfoFile, baseName);
-#endif
   nsAutoString infoFileName = baseName + NS_LITERAL_STRING(".info");
   aInfoFile->AppendRelativePath(infoFileName);
   return true;
 }
 
 #if defined(XP_MACOSX) && defined(MOZ_GMP_SANDBOX)
+static nsCString
+GetNativeTarget(nsIFile* aFile)
+{
+  bool isLink;
+  nsCString path;
+  aFile->IsSymlink(&isLink);
+  if (isLink) {
+    aFile->GetNativeTarget(path);
+  } else {
+    aFile->GetNativePath(path);
+  }
+  return path;
+}
+
 static bool
 GetPluginPaths(const nsAString& aPluginPath,
                nsCString &aPluginDirectoryPath,
                nsCString &aPluginFilePath)
 {
   nsCOMPtr<nsIFile> libDirectory, libFile;
   if (!GetPluginFile(aPluginPath, libDirectory, libFile)) {
     return false;
   }
 
   // Mac sandbox rules expect paths to actual files and directories -- not
   // soft links.
-  bool isLink;
-  libDirectory->IsSymlink(&isLink);
-  if (isLink) {
-    libDirectory->GetNativeTarget(aPluginDirectoryPath);
-  } else {
-    libDirectory->GetNativePath(aPluginDirectoryPath);
-  }
-  libFile->IsSymlink(&isLink);
-  if (isLink) {
-    libFile->GetNativeTarget(aPluginFilePath);
-  } else {
-    libFile->GetNativePath(aPluginFilePath);
-  }
+  aPluginDirectoryPath = GetNativeTarget(libDirectory);
+  aPluginFilePath = GetNativeTarget(libFile);
 
   return true;
 }
 
 static bool
 GetAppPaths(nsCString &aAppPath, nsCString &aAppBinaryPath)
 {
   nsAutoCString appPath;
@@ -200,29 +207,20 @@ GetAppPaths(nsCString &aAppPath, nsCStri
     return false;
   }
   rv = NS_NewLocalFile(NS_ConvertUTF8toUTF16(appBinaryPath),
                        true, getter_AddRefs(appBinary));
   if (NS_FAILED(rv)) {
     return false;
   }
 
-  bool isLink;
-  app->IsSymlink(&isLink);
-  if (isLink) {
-    app->GetNativeTarget(aAppPath);
-  } else {
-    app->GetNativePath(aAppPath);
-  }
-  appBinary->IsSymlink(&isLink);
-  if (isLink) {
-    appBinary->GetNativeTarget(aAppBinaryPath);
-  } else {
-    appBinary->GetNativePath(aAppBinaryPath);
-  }
+  // Mac sandbox rules expect paths to actual files and directories -- not
+  // soft links.
+  aAppPath = GetNativeTarget(app);
+  appBinaryPath = GetNativeTarget(appBinary);
 
   return true;
 }
 
 bool
 GMPChild::SetMacSandboxInfo()
 {
   if (!mGMPLoader) {
@@ -583,22 +581,17 @@ GMPChild::ShutdownComplete()
   SendAsyncShutdownComplete();
 }
 
 static void
 GetPluginVoucherFile(const nsAString& aPluginPath,
                      nsCOMPtr<nsIFile>& aOutVoucherFile)
 {
   nsAutoString baseName;
-#if defined(XP_MACOSX) && defined(MOZ_GMP_SANDBOX)
-  nsCOMPtr<nsIFile> libDir;
-  GetFileBase(aPluginPath, aOutVoucherFile, libDir, baseName);
-#else
   GetFileBase(aPluginPath, aOutVoucherFile, baseName);
-#endif
   nsAutoString infoFileName = baseName + NS_LITERAL_STRING(".voucher");
   aOutVoucherFile->AppendRelativePath(infoFileName);
 }
 
 bool
 GMPChild::PreLoadPluginVoucher()
 {
   nsCOMPtr<nsIFile> voucherFile;
--- a/dom/media/gmp/GMPProcessParent.cpp
+++ b/dom/media/gmp/GMPProcessParent.cpp
@@ -3,16 +3,19 @@
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "GMPProcessParent.h"
 #include "GMPUtils.h"
 #include "nsIFile.h"
 #include "nsIRunnable.h"
+#if defined(XP_WIN) && defined(MOZ_SANDBOX)
+#include "WinUtils.h"
+#endif
 
 #include "base/string_util.h"
 #include "base/process_util.h"
 
 #include <string>
 
 using std::vector;
 using std::string;
@@ -50,24 +53,36 @@ GMPProcessParent::Launch(int32_t aTimeou
   if (!GetEMEVoucherPath(getter_AddRefs(path))) {
     NS_WARNING("GMPProcessParent can't get EME voucher path!");
     return false;
   }
   nsAutoCString voucherPath;
   path->GetNativePath(voucherPath);
 
   vector<string> args;
-  args.push_back(mGMPPath);
-  args.push_back(string(voucherPath.BeginReading(), voucherPath.EndReading()));
 
 #if defined(XP_WIN) && defined(MOZ_SANDBOX)
   std::wstring wGMPPath = UTF8ToWide(mGMPPath.c_str());
+
+  // The sandbox doesn't allow file system rules where the paths contain
+  // symbolic links or junction points. Sometimes the Users folder has been
+  // moved to another drive using a junction point, so allow for this specific
+  // case. See bug 1236680 for details.
+  if (!widget::WinUtils::ResolveMovedUsersFolder(wGMPPath)) {
+    NS_WARNING("ResolveMovedUsersFolder failed for GMP path.");
+    return false;
+  }
   mAllowedFilesRead.push_back(wGMPPath + L"\\*");
+  args.push_back(WideToUTF8(wGMPPath));
+#else
+  args.push_back(mGMPPath);
 #endif
 
+  args.push_back(string(voucherPath.BeginReading(), voucherPath.EndReading()));
+
   return SyncLaunch(args, aTimeoutMs, base::GetCurrentProcessArchitecture());
 }
 
 void
 GMPProcessParent::Delete(nsCOMPtr<nsIRunnable> aCallback)
 {
   mDeletedCallback = aCallback;
   XRE_GetIOMessageLoop()->PostTask(FROM_HERE, NewRunnableMethod(this, &GMPProcessParent::DoDelete));
--- a/dom/media/mediasink/DecodedAudioDataSink.cpp
+++ b/dom/media/mediasink/DecodedAudioDataSink.cpp
@@ -286,13 +286,16 @@ DecodedAudioDataSink::Ended() const
   // Return true when error encountered so AudioStream can start draining.
   return AudioQueue().IsFinished() || mErrored;
 }
 
 void
 DecodedAudioDataSink::Drained()
 {
   SINK_LOG("Drained");
-  mEndPromise.Resolve(true, __func__);
+  // FIXME : In OSX, the audio backend could trigger Drained() twice, then it
+  // cause the crash because the promise had already been resolve and free.
+  // You can fix it on the bug 1246108.
+  mEndPromise.ResolveIfExists(true, __func__);
 }
 
 } // namespace media
 } // namespace mozilla
--- a/dom/media/mediasink/VideoSink.cpp
+++ b/dom/media/mediasink/VideoSink.cpp
@@ -29,17 +29,16 @@ VideoSink::VideoSink(AbstractThread* aTh
                      uint32_t aVQueueSentToCompositerSize)
   : mOwnerThread(aThread)
   , mAudioSink(aAudioSink)
   , mVideoQueue(aVideoQueue)
   , mContainer(aContainer)
   , mProducerID(ImageContainer::AllocateProducerID())
   , mFrameStats(aFrameStats)
   , mVideoFrameEndTime(-1)
-  , mOldDroppedCount(0)
   , mHasVideo(false)
   , mUpdateScheduler(aThread)
   , mVideoQueueSendToCompositorSize(aVQueueSentToCompositerSize)
 {
   MOZ_ASSERT(mAudioSink, "AudioSink should exist.");
 }
 
 VideoSink::~VideoSink()
@@ -359,20 +358,16 @@ VideoSink::RenderVideoFrames(int32_t aMa
     img->mImage = frame->mImage;
     img->mFrameID = frame->mFrameID;
     img->mProducerID = mProducerID;
 
     VSINK_LOG_V("playing video frame %lld (id=%x) (vq-queued=%i)",
                 frame->mTime, frame->mFrameID, VideoQueue().GetSize());
   }
   mContainer->SetCurrentFrames(frames[0]->As<VideoData>()->mDisplay, images);
-
-  uint32_t dropped = mContainer->GetDroppedImageCount();
-  mFrameStats.NotifyDecodedFrames(0, 0, dropped - mOldDroppedCount);
-  mOldDroppedCount = dropped;
 }
 
 void
 VideoSink::UpdateRenderedVideoFrames()
 {
   AssertOwnerThread();
   MOZ_ASSERT(mAudioSink->IsPlaying(), "should be called while playing.");
 
--- a/dom/media/mediasink/VideoSink.h
+++ b/dom/media/mediasink/VideoSink.h
@@ -121,18 +121,16 @@ private:
   RefPtr<GenericPromise> mEndPromise;
   MozPromiseHolder<GenericPromise> mEndPromiseHolder;
   MozPromiseRequestHolder<GenericPromise> mVideoSinkEndRequest;
 
   // The presentation end time of the last video frame which has been displayed
   // in microseconds.
   int64_t mVideoFrameEndTime;
 
-  uint32_t mOldDroppedCount;
-
   // Event listeners for VideoQueue
   MediaEventListener mPushListener;
   MediaEventListener mFinishListener;
 
   // True if this sink is going to handle video track.
   bool mHasVideo;
 
   // Used to trigger another update of rendered frames in next round.
--- a/dom/media/test/crashtests/crashtests.list
+++ b/dom/media/test/crashtests/crashtests.list
@@ -87,11 +87,12 @@ load audiocontext-double-suspend.html
 load buffer-source-duration-1.html
 load buffer-source-ended-1.html
 load buffer-source-resampling-start-1.html
 load doppler-1.html
 HTTP load media-element-source-seek-1.html
 load offline-buffer-source-ended-1.html
 load oscillator-ended-1.html
 load oscillator-ended-2.html
+skip-if(winWidget) load video-replay-after-audio-end.html
 
 # This needs to run at the end to avoid leaking busted state into other tests.
 skip-if(B2G) load 691096-1.html # bug 852821
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..9532113d87ae59497ab5e9482615c57cc51c8672
GIT binary patch
literal 58482
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
new file mode 100644
--- /dev/null
+++ b/dom/media/test/crashtests/video-replay-after-audio-end.html
@@ -0,0 +1,43 @@
+<html class="reftest-wait">
+<head>
+  <title> Bug 1242774 : video crashed if pause and play again after audio track ends </title>
+</head>
+<body>
+<script type="text/javascript">
+function assert(value, msg) {
+  if (!value) {
+    dump("### Error : " + msg + "\n");
+  }
+}
+
+var AUDIO_END_TIME = 4.5;
+var video = document.createElement('video');
+video.src = "video-crash.webm";
+video.play();
+
+video.ontimeupdate = function () {
+  assert(AUDIO_END_TIME < video.duration,
+         "AUDIO_END_TIME should be smaller than the duration!");
+
+  if (video.currentTime > AUDIO_END_TIME) {
+    dump("### Pause video during silent part.\n");
+    video.ontimeupdate = null;
+    video.pause();
+  }
+
+  video.onpause = function () {
+    video.onpause = null;
+    setTimeout(function() {
+      dump("### Re-play after pausing during silent part.\n");
+      video.play();
+      video.onended = function () {
+        video.onended = null;
+        dump("### Video is ended.\n");
+        document.documentElement.removeAttribute("class");
+      }
+    }, 1000);
+  }
+}
+</script>
+</body>
+</html>
\ No newline at end of file
--- a/dom/mobilemessage/android/SmsManager.cpp
+++ b/dom/mobilemessage/android/SmsManager.cpp
@@ -33,19 +33,19 @@ SmsManager::NotifySmsReceived(int32_t aI
 {
     // TODO Need to correct the message `threadId` parameter value. Bug 859098
     SmsMessageData message;
     message.id() = aId;
     message.threadId() = 0;
     message.iccId() = EmptyString();
     message.delivery() = eDeliveryState_Received;
     message.deliveryStatus() = eDeliveryStatus_Success;
-    message.sender() = aSender ? nsString(aSender) : EmptyString();
+    message.sender() = aSender ? aSender->ToString() : EmptyString();
     message.receiver() = EmptyString();
-    message.body() = aBody ? nsString(aBody) : EmptyString();
+    message.body() = aBody ? aBody->ToString() : EmptyString();
     message.messageClass() = static_cast<MessageClass>(aMessageClass);
     message.timestamp() = aTimestamp;
     message.sentTimestamp() = aSentTimestamp;
     message.deliveryTimestamp() = aTimestamp;
     message.read() = false;
 
     nsCOMPtr<nsIRunnable> runnable = NS_NewRunnableFunction([=] () {
         nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
@@ -71,18 +71,18 @@ SmsManager::NotifySmsSent(int32_t aId,
     // TODO Need to correct the message `threadId` parameter value. Bug 859098
     SmsMessageData message;
     message.id() = aId;
     message.threadId() = 0;
     message.iccId() = EmptyString();
     message.delivery() = eDeliveryState_Sent;
     message.deliveryStatus() = eDeliveryStatus_Pending;
     message.sender() = EmptyString();
-    message.receiver() = aReceiver ? nsString(aReceiver) : EmptyString();
-    message.body() = aBody ? nsString(aBody) : EmptyString();
+    message.receiver() = aReceiver ? aReceiver->ToString() : EmptyString();
+    message.body() = aBody ? aBody->ToString() : EmptyString();
     message.messageClass() = eMessageClass_Normal;
     message.timestamp() = aTimestamp;
     message.sentTimestamp() = aTimestamp;
     message.deliveryTimestamp() = aTimestamp;
     message.read() = true;
 
     nsCOMPtr<nsIRunnable> runnable = NS_NewRunnableFunction([=]() {
         /*
@@ -120,18 +120,18 @@ SmsManager::NotifySmsDelivery(int32_t aI
     // TODO Need to correct the message `threadId` parameter value. Bug 859098
     SmsMessageData message;
     message.id() = aId;
     message.threadId() = 0;
     message.iccId() = EmptyString();
     message.delivery() = eDeliveryState_Sent;
     message.deliveryStatus() = static_cast<DeliveryStatus>(aDeliveryStatus);
     message.sender() = EmptyString();
-    message.receiver() = aReceiver ? nsString(aReceiver) : EmptyString();
-    message.body() = aBody ? nsString(aBody) : EmptyString();
+    message.receiver() = aReceiver ? aReceiver->ToString() : EmptyString();
+    message.body() = aBody ? aBody->ToString() : EmptyString();
     message.messageClass() = eMessageClass_Normal;
     message.timestamp() = aTimestamp;
     message.sentTimestamp() = aTimestamp;
     message.deliveryTimestamp() = aTimestamp;
     message.read() = true;
 
     nsCOMPtr<nsIRunnable> runnable = NS_NewRunnableFunction([=]() {
         nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
@@ -170,31 +170,31 @@ SmsManager::NotifyGetSms(int32_t aId,
                          int32_t aDeliveryStatus,
                          jni::String::Param aReceiver,
                          jni::String::Param aSender,
                          jni::String::Param aBody,
                          int64_t aTimestamp,
                          bool aRead,
                          int32_t aRequestId)
 {
-    nsString receiver(aReceiver);
+    nsString receiver(aReceiver->ToString());
     DeliveryState state = receiver.IsEmpty() ? eDeliveryState_Received
                                              : eDeliveryState_Sent;
 
     // TODO Need to add the message `messageClass` parameter value. Bug 804476
     // TODO Need to correct the message `threadId` parameter value. Bug 859098
     SmsMessageData message;
     message.id() = aId;
     message.threadId() = 0;
     message.iccId() = EmptyString();
     message.delivery() = state;
     message.deliveryStatus() = static_cast<DeliveryStatus>(aDeliveryStatus);
-    message.sender() = aSender ? nsString(aSender) : EmptyString();
+    message.sender() = aSender ? aSender->ToString() : EmptyString();
     message.receiver() = receiver;
-    message.body() = aBody ? nsString(aBody) : EmptyString();
+    message.body() = aBody ? aBody->ToString() : EmptyString();
     message.messageClass() = eMessageClass_Normal;
     message.timestamp() = aTimestamp;
     message.sentTimestamp() = aTimestamp;
     message.deliveryTimestamp() = aTimestamp;
     message.read() = aRead;
 
     nsCOMPtr<nsIRunnable> runnable = NS_NewRunnableFunction([=]() {
         nsCOMPtr<nsIMobileMessageCallback> request =
@@ -284,19 +284,19 @@ SmsManager::NotifyThreadCursorResult(int
                                      jni::ObjectArray::Param aParticipants,
                                      int64_t aTimestamp,
                                      jni::String::Param aLastMessageType,
                                      int32_t aRequestId)
 {
     ThreadData thread;
     thread.id() = aId;
     thread.lastMessageSubject() = aLastMessageSubject ?
-                                    nsString(aLastMessageSubject) :
+                                    aLastMessageSubject->ToString() :
                                     EmptyString();
-    thread.body() = aBody ? nsString(aBody) : EmptyString();
+    thread.body() = aBody ? aBody->ToString() : EmptyString();
     thread.unreadCount() = aUnreadCount;
     thread.timestamp() = aTimestamp;
     thread.lastMessageType() = eMessageType_SMS;
 
     JNIEnv* const env = jni::GetEnvForThread();
 
     jobjectArray participants = aParticipants.Get();
     jsize length = env->GetArrayLength(participants);
@@ -335,30 +335,30 @@ SmsManager::NotifyMessageCursorResult(in
                                       jni::String::Param aReceiver,
                                       jni::String::Param aSender,
                                       jni::String::Param aBody,
                                       int64_t aTimestamp,
                                       int64_t aThreadId,
                                       bool aRead,
                                       int32_t aRequestId)
 {
-    nsString receiver = nsString(aReceiver);
+    nsString receiver = aReceiver->ToString();
     DeliveryState state = receiver.IsEmpty() ? eDeliveryState_Received
                                              : eDeliveryState_Sent;
 
     // TODO Need to add the message `messageClass` parameter value. Bug 804476
     SmsMessageData message;
     message.id() = aMessageId;
     message.threadId() = aThreadId;
     message.iccId() = EmptyString();
     message.delivery() = state;
     message.deliveryStatus() = static_cast<DeliveryStatus>(aDeliveryStatus);
-    message.sender() = aSender ? nsString(aSender) : EmptyString();
+    message.sender() = aSender ? aSender->ToString() : EmptyString();
     message.receiver() = receiver;
-    message.body() = aBody ? nsString(aBody) : EmptyString();
+    message.body() = aBody ? aBody->ToString() : EmptyString();
     message.messageClass() = eMessageClass_Normal;
     message.timestamp() = aTimestamp;
     message.sentTimestamp() = aTimestamp;
     message.deliveryTimestamp() = aTimestamp;
     message.read() = aRead;
 
     nsCOMPtr<nsIRunnable> runnable = NS_NewRunnableFunction([=]() {
         nsCOMPtr<nsIMobileMessageCursorCallback> request =
--- a/dom/plugins/base/nsJSNPRuntime.cpp
+++ b/dom/plugins/base/nsJSNPRuntime.cpp
@@ -1900,18 +1900,19 @@ nsNPObjWrapper::GetNewOrUsed(NPP npp, JS
   // No existing JSObject, create one.
 
   JS::Rooted<JSObject*> obj(cx, ::JS_NewObject(cx, js::Jsvalify(&sNPObjectJSWrapperClass)));
 
   if (generation != sNPObjWrappers->Generation()) {
       // Reload entry if the JS_NewObject call caused a GC and reallocated
       // the table (see bug 445229). This is guaranteed to succeed.
 
-      NS_ASSERTION(sNPObjWrappers->Search(npobj),
-                   "Hashtable didn't find what we just added?");
+      entry =
+         static_cast<NPObjWrapperHashEntry*>(sNPObjWrappers->Search(npobj));
+      NS_ASSERTION(entry, "Hashtable didn't find what we just added?");
   }
 
   if (!obj) {
     // OOM? Remove the stale entry from the hash.
 
     sNPObjWrappers->RawRemove(entry);
 
     return nullptr;
--- a/dom/plugins/base/nsPluginHost.cpp
+++ b/dom/plugins/base/nsPluginHost.cpp
@@ -3404,17 +3404,18 @@ nsresult nsPluginHost::NewPluginURLStrea
   rv = NS_NewChannel(getter_AddRefs(channel),
                      url,
                      requestingNode,
                      nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_INHERITS |
                      nsILoadInfo::SEC_FORCE_INHERIT_PRINCIPAL,
                      nsIContentPolicy::TYPE_OBJECT_SUBREQUEST,
                      nullptr,  // aLoadGroup
                      listenerPeer,
-                     nsIRequest::LOAD_NORMAL | nsIChannel::LOAD_CLASSIFY_URI);
+                     nsIRequest::LOAD_NORMAL | nsIChannel::LOAD_CLASSIFY_URI |
+                     nsIChannel::LOAD_BYPASS_SERVICE_WORKER);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (doc) {
     // And if it's a script allow it to execute against the
     // document's script context.
     nsCOMPtr<nsIScriptChannel> scriptChannel(do_QueryInterface(channel));
     if (scriptChannel) {
       scriptChannel->SetExecutionPolicy(nsIScriptChannel::EXECUTE_NORMAL);
--- a/dom/plugins/base/nsPluginStreamListenerPeer.cpp
+++ b/dom/plugins/base/nsPluginStreamListenerPeer.cpp
@@ -690,31 +690,33 @@ nsPluginStreamListenerPeer::RequestRead(
   nsCOMPtr<nsINode> requestingNode(do_QueryInterface(element));
   if (requestingNode) {
     rv = NS_NewChannel(getter_AddRefs(channel),
                        mURL,
                        requestingNode,
                        nsILoadInfo::SEC_NORMAL,
                        nsIContentPolicy::TYPE_OTHER,
                        loadGroup,
-                       callbacks);
+                       callbacks,
+                       nsIChannel::LOAD_BYPASS_SERVICE_WORKER);
   }
   else {
     // in this else branch we really don't know where the load is coming
     // from and in fact should use something better than just using
     // a nullPrincipal as the loadingPrincipal.
     nsCOMPtr<nsIPrincipal> principal = nsNullPrincipal::Create();
     NS_ENSURE_TRUE(principal, NS_ERROR_FAILURE);
     rv = NS_NewChannel(getter_AddRefs(channel),
                        mURL,
                        principal,
                        nsILoadInfo::SEC_NORMAL,
                        nsIContentPolicy::TYPE_OTHER,
                        loadGroup,
-                       callbacks);
+                       callbacks,
+                       nsIChannel::LOAD_BYPASS_SERVICE_WORKER);
   }
 
   if (NS_FAILED(rv))
     return rv;
 
   nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel));
   if (!httpChannel)
     return NS_ERROR_FAILURE;
--- a/dom/plugins/test/testplugin/testplugin.mk
+++ b/dom/plugins/test/testplugin/testplugin.mk
@@ -1,18 +1,13 @@
 #
 # 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/.
 
-ifeq ($(MOZ_WIDGET_TOOLKIT),windows)
-# Windows opt builds without PGO break nptest.dll
-MOZ_OPTIMIZE=
-endif
-
 TEST_PLUGIN_FILES = $(SHARED_LIBRARY)
 
 ifeq ($(MOZ_WIDGET_TOOLKIT),cocoa)
 MAC_PLIST_FILES += $(srcdir)/Info.plist
 MAC_PLIST_DEST   = $(DIST)/plugins/$(COCOA_NAME).plugin/Contents
 TEST_PLUGIN_DEST = $(DIST)/plugins/$(COCOA_NAME).plugin/Contents/MacOS
 INSTALL_TARGETS += \
 	TEST_PLUGIN \
--- a/dom/promise/Promise.cpp
+++ b/dom/promise/Promise.cpp
@@ -45,16 +45,17 @@ namespace dom {
 
 namespace {
 // Generator used by Promise::GetID.
 Atomic<uintptr_t> gIDGenerator(0);
 } // namespace
 
 using namespace workers;
 
+#ifndef SPIDERMONKEY_PROMISE
 // This class processes the promise's callbacks with promise's result.
 class PromiseReactionJob final : public nsRunnable
 {
 public:
   PromiseReactionJob(Promise* aPromise,
                      PromiseCallback* aCallback,
                      const JS::Value& aValue)
     : mPromise(aPromise)
@@ -375,47 +376,62 @@ Promise::PromiseCapability::PromiseValue
 
   if (mNativePromise) {
     return JS::ObjectValue(*mNativePromise->GetWrapper());
   }
 
   return JS::ObjectValue(*mPromise);
 }
 
+#endif // SPIDERMONKEY_PROMISE
+
 // Promise
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(Promise)
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(Promise)
+#ifndef SPIDERMONKEY_PROMISE
 #if defined(DOM_PROMISE_DEPRECATED_REPORTING)
   tmp->MaybeReportRejectedOnce();
 #else
   tmp->mResult = JS::UndefinedValue();
 #endif // defined(DOM_PROMISE_DEPRECATED_REPORTING)
+#endif // SPIDERMONKEY_PROMISE
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mGlobal)
+#ifndef SPIDERMONKEY_PROMISE
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mResolveCallbacks)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mRejectCallbacks)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
+#else // SPIDERMONKEY_PROMISE
+  tmp->mPromiseObj = nullptr;
+#endif // SPIDERMONKEY_PROMISE
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(Promise)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mGlobal)
+#ifndef SPIDERMONKEY_PROMISE
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mResolveCallbacks)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mRejectCallbacks)
+#endif // SPIDERMONKEY_PROMISE
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(Promise)
+#ifndef SPIDERMONKEY_PROMISE
   NS_IMPL_CYCLE_COLLECTION_TRACE_JSVAL_MEMBER_CALLBACK(mResult)
   NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mAllocationStack)
   NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mRejectionStack)
   NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mFullfillmentStack)
   NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
+#else // SPIDERMONKEY_PROMISE
+  NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mPromiseObj);
+#endif // SPIDERMONKEY_PROMISE
 NS_IMPL_CYCLE_COLLECTION_TRACE_END
 
+#ifndef SPIDERMONKEY_PROMISE
 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(Promise)
   if (tmp->IsBlack()) {
     JS::ExposeValueToActiveJS(tmp->mResult);
     if (tmp->mAllocationStack) {
       JS::ExposeObjectToActiveJS(tmp->mAllocationStack);
     }
     if (tmp->mRejectionStack) {
       JS::ExposeObjectToActiveJS(tmp->mRejectionStack);
@@ -429,57 +445,403 @@ NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_END
 
 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_BEGIN(Promise)
   return tmp->IsBlackAndDoesNotNeedTracing(tmp);
 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_END
 
 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_BEGIN(Promise)
   return tmp->IsBlack();
 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_END
+#endif // SPIDERMONKEY_PROMISE
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(Promise)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(Promise)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Promise)
+#ifndef SPIDERMONKEY_PROMISE
   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
+#endif // SPIDERMONKEY_PROMISE
   NS_INTERFACE_MAP_ENTRY(nsISupports)
   NS_INTERFACE_MAP_ENTRY(Promise)
 NS_INTERFACE_MAP_END
 
 Promise::Promise(nsIGlobalObject* aGlobal)
   : mGlobal(aGlobal)
+#ifndef SPIDERMONKEY_PROMISE
   , mResult(JS::UndefinedValue())
   , mAllocationStack(nullptr)
   , mRejectionStack(nullptr)
   , mFullfillmentStack(nullptr)
   , mState(Pending)
 #if defined(DOM_PROMISE_DEPRECATED_REPORTING)
   , mHadRejectCallback(false)
 #endif // defined(DOM_PROMISE_DEPRECATED_REPORTING)
   , mTaskPending(false)
   , mResolvePending(false)
   , mIsLastInChain(true)
   , mWasNotifiedAsUncaught(false)
   , mID(0)
+#else // SPIDERMONKEY_PROMISE
+  , mPromiseObj(nullptr)
+#endif // SPIDERMONKEY_PROMISE
 {
   MOZ_ASSERT(mGlobal);
 
   mozilla::HoldJSObjects(this);
 
+#ifndef SPIDERMONKEY_PROMISE
   mCreationTimestamp = TimeStamp::Now();
+#endif // SPIDERMONKEY_PROMISE
 }
 
 Promise::~Promise()
 {
+#ifndef SPIDERMONKEY_PROMISE
 #if defined(DOM_PROMISE_DEPRECATED_REPORTING)
   MaybeReportRejectedOnce();
 #endif // defined(DOM_PROMISE_DEPRECATED_REPORTING)
+#endif // SPIDERMONKEY_PROMISE
   mozilla::DropJSObjects(this);
 }
 
+#ifdef SPIDERMONKEY_PROMISE
+
+bool
+Promise::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto,
+                    JS::MutableHandle<JSObject*> aWrapper)
+{
+#ifdef DEBUG
+  binding_detail::AssertReflectorHasGivenProto(aCx, mPromiseObj, aGivenProto);
+#endif // DEBUG
+  JS::ExposeObjectToActiveJS(mPromiseObj);
+  aWrapper.set(mPromiseObj);
+  return true;
+}
+
+// static
+already_AddRefed<Promise>
+Promise::Create(nsIGlobalObject* aGlobal, ErrorResult& aRv)
+{
+  RefPtr<Promise> p = new Promise(aGlobal);
+  p->CreateWrapper(nullptr, aRv);
+  if (aRv.Failed()) {
+    return nullptr;
+  }
+  return p.forget();
+}
+
+// static
+already_AddRefed<Promise>
+Promise::Resolve(nsIGlobalObject* aGlobal, JSContext* aCx,
+                 JS::Handle<JS::Value> aValue, ErrorResult& aRv)
+{
+  JSAutoCompartment ac(aCx, aGlobal->GetGlobalJSObject());
+  JS::Rooted<JSObject*> p(aCx,
+                          JS::CallOriginalPromiseResolve(aCx, aValue));
+  if (!p) {
+    aRv.NoteJSContextException();
+    return nullptr;
+  }
+
+  return CreateFromExisting(aGlobal, p);
+}
+
+// static
+already_AddRefed<Promise>
+Promise::Reject(nsIGlobalObject* aGlobal, JSContext* aCx,
+                JS::Handle<JS::Value> aValue, ErrorResult& aRv)
+{
+  JSAutoCompartment ac(aCx, aGlobal->GetGlobalJSObject());
+  JS::Rooted<JSObject*> p(aCx,
+                          JS::CallOriginalPromiseReject(aCx, aValue));
+  if (!p) {
+    aRv.NoteJSContextException();
+    return nullptr;
+  }
+
+  return CreateFromExisting(aGlobal, p);
+}
+
+// static
+already_AddRefed<Promise>
+Promise::All(const GlobalObject& aGlobal,
+             const nsTArray<RefPtr<Promise>>& aPromiseList, ErrorResult& aRv)
+{
+  nsCOMPtr<nsIGlobalObject> global;
+  global = do_QueryInterface(aGlobal.GetAsSupports());
+  if (!global) {
+    aRv.Throw(NS_ERROR_UNEXPECTED);
+    return nullptr;
+  }
+
+  JSContext* cx = aGlobal.Context();
+
+  JS::AutoObjectVector promises(cx);
+  if (!promises.reserve(aPromiseList.Length())) {
+    aRv.NoteJSContextException();
+    return nullptr;
+  }
+
+  for (auto& promise : aPromiseList) {
+    JS::Rooted<JSObject*> promiseObj(cx, promise->PromiseObj());
+    // Just in case, make sure these are all in the context compartment.
+    if (!JS_WrapObject(cx, &promiseObj)) {
+      aRv.NoteJSContextException();
+      return nullptr;
+    }
+    promises.infallibleAppend(promiseObj);
+  }
+
+  JS::Rooted<JSObject*> result(cx, JS::GetWaitForAllPromise(cx, promises));
+  if (!result) {
+    aRv.NoteJSContextException();
+    return nullptr;
+  }
+
+  return CreateFromExisting(global, result);
+}
+
+void
+Promise::Then(JSContext* aCx,
+              // aCalleeGlobal may not be in the compartment of aCx, when called over
+              // Xrays.
+              JS::Handle<JSObject*> aCalleeGlobal,
+              AnyCallback* aResolveCallback, AnyCallback* aRejectCallback,
+              JS::MutableHandle<JS::Value> aRetval,
+              ErrorResult& aRv)
+{
+  // Let's hope this does the right thing with Xrays...  Ensure everything is
+  // just in the caller compartment; that ought to do the trick.  In theory we
+  // should consider aCalleeGlobal, but in practice our only caller is
+  // DOMRequest::Then, which is not working with a Promise subclass, so things
+  // should be OK.
+  JS::Rooted<JSObject*> promise(aCx, PromiseObj());
+  if (!JS_WrapObject(aCx, &promise)) {
+    aRv.NoteJSContextException();
+    return;
+  }
+
+  JS::Rooted<JSObject*> resolveCallback(aCx);
+  if (aResolveCallback) {
+    resolveCallback = aResolveCallback->Callback();
+    if (!JS_WrapObject(aCx, &resolveCallback)) {
+      aRv.NoteJSContextException();
+      return;
+    }
+  }
+
+  JS::Rooted<JSObject*> rejectCallback(aCx);
+  if (aRejectCallback) {
+    rejectCallback = aRejectCallback->Callback();
+    if (!JS_WrapObject(aCx, &rejectCallback)) {
+      aRv.NoteJSContextException();
+      return;
+    }
+  }
+
+  JS::Rooted<JSObject*> retval(aCx);
+  retval = JS::CallOriginalPromiseThen(aCx, promise, resolveCallback,
+                                       rejectCallback);
+  if (!retval) {
+    aRv.NoteJSContextException();
+    return;
+  }
+
+  aRetval.setObject(*retval);
+}
+
+// We need a dummy function to pass to JS::NewPromiseObject.
+static bool
+DoNothingPromiseExecutor(JSContext*, unsigned aArgc, JS::Value* aVp)
+{
+  JS::CallArgs args = CallArgsFromVp(aArgc, aVp);
+  args.rval().setUndefined();
+  return true;
+}
+
+void
+Promise::CreateWrapper(JS::Handle<JSObject*> aDesiredProto, ErrorResult& aRv)
+{
+  AutoJSAPI jsapi;
+  if (!jsapi.Init(mGlobal)) {
+    aRv.Throw(NS_ERROR_UNEXPECTED);
+    return;
+  }
+  JSContext* cx = jsapi.cx();
+
+  JSFunction* doNothingFunc =
+    JS_NewFunction(cx, DoNothingPromiseExecutor, /* nargs = */ 2,
+                   /* flags = */ 0, nullptr);
+  if (!doNothingFunc) {
+    JS_ClearPendingException(cx);
+    aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
+    return;
+  }
+
+  JS::Rooted<JSObject*> doNothingObj(cx, JS_GetFunctionObject(doNothingFunc));
+  mPromiseObj = JS::NewPromiseObject(cx, doNothingObj, aDesiredProto);
+  if (!mPromiseObj) {
+    JS_ClearPendingException(cx);
+    aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
+    return;
+  }
+}
+
+void
+Promise::MaybeResolve(JSContext* aCx,
+                      JS::Handle<JS::Value> aValue)
+{
+  JS::Rooted<JSObject*> p(aCx, PromiseObj());
+  if (!JS::ResolvePromise(aCx, p, aValue)) {
+    // Now what?  There's nothing sane to do here.
+    JS_ClearPendingException(aCx);
+  }
+}
+
+void
+Promise::MaybeReject(JSContext* aCx,
+                     JS::Handle<JS::Value> aValue)
+{
+  JS::Rooted<JSObject*> p(aCx, PromiseObj());
+  if (!JS::RejectPromise(aCx, p, aValue)) {
+    // Now what?  There's nothing sane to do here.
+    JS_ClearPendingException(aCx);
+  }
+}
+
+#define SLOT_NATIVEHANDLER 0
+#define SLOT_NATIVEHANDLER_TASK 1
+
+enum class NativeHandlerTask : int32_t {
+  Resolve,
+  Reject
+};
+
+static bool
+NativeHandlerCallback(JSContext* aCx, unsigned aArgc, JS::Value* aVp)
+{
+  JS::CallArgs args = CallArgsFromVp(aArgc, aVp);
+
+  JS::Rooted<JS::Value> v(aCx,
+                          js::GetFunctionNativeReserved(&args.callee(),
+                                                        SLOT_NATIVEHANDLER));
+  MOZ_ASSERT(v.isObject());
+
+  PromiseNativeHandler* handler;
+  if (NS_FAILED(UNWRAP_OBJECT(PromiseNativeHandler, &v.toObject(),
+                              handler))) {
+    return Throw(aCx, NS_ERROR_UNEXPECTED);
+  }
+
+  v = js::GetFunctionNativeReserved(&args.callee(), SLOT_NATIVEHANDLER_TASK);
+  NativeHandlerTask task = static_cast<NativeHandlerTask>(v.toInt32());
+
+  if (task == NativeHandlerTask::Resolve) {
+    handler->ResolvedCallback(aCx, args.get(0));
+  } else {
+    MOZ_ASSERT(task == NativeHandlerTask::Reject);
+    handler->RejectedCallback(aCx, args.get(0));
+  }
+
+  return true;
+}
+
+static JSObject*
+CreateNativeHandlerFunction(JSContext* aCx, JS::Handle<JSObject*> aHolder,
+                            NativeHandlerTask aTask)
+{
+  JSFunction* func = js::NewFunctionWithReserved(aCx, NativeHandlerCallback,
+                                                 /* nargs = */ 1,
+                                                 /* flags = */ 0, nullptr);
+  if (!func) {
+    return nullptr;
+  }
+
+  JS::Rooted<JSObject*> obj(aCx, JS_GetFunctionObject(func));
+
+  JS::ExposeObjectToActiveJS(aHolder);
+  js::SetFunctionNativeReserved(obj, SLOT_NATIVEHANDLER,
+                                JS::ObjectValue(*aHolder));
+  js::SetFunctionNativeReserved(obj, SLOT_NATIVEHANDLER_TASK,
+                                JS::Int32Value(static_cast<int32_t>(aTask)));
+
+  return obj;
+}
+
+void
+Promise::AppendNativeHandler(PromiseNativeHandler* aRunnable)
+{
+  AutoJSAPI jsapi;
+  if (NS_WARN_IF(!jsapi.Init(mGlobal))) {
+    // Our API doesn't allow us to return a useful error.  Not like this should
+    // happen anyway.
+    return;
+  }
+  jsapi.TakeOwnershipOfErrorReporting();
+
+  JSContext* cx = jsapi.cx();
+  JS::Rooted<JSObject*> handlerWrapper(cx);
+  // Note: PromiseNativeHandler is NOT wrappercached.  So we can't use
+  // ToJSValue here, because it will try to do XPConnect wrapping on it, sadly.
+  if (NS_WARN_IF(!aRunnable->WrapObject(cx, nullptr, &handlerWrapper))) {
+    // Again, no way to report errors.
+    jsapi.ClearException();
+    return;
+  }
+
+  JS::Rooted<JSObject*> resolveFunc(cx);
+  resolveFunc =
+    CreateNativeHandlerFunction(cx, handlerWrapper, NativeHandlerTask::Resolve);
+  if (NS_WARN_IF(!resolveFunc)) {
+    jsapi.ClearException();
+    return;
+  }
+
+  JS::Rooted<JSObject*> rejectFunc(cx);
+  rejectFunc =
+    CreateNativeHandlerFunction(cx, handlerWrapper, NativeHandlerTask::Reject);
+  if (NS_WARN_IF(!rejectFunc)) {
+    jsapi.ClearException();
+    return;
+  }
+
+  JS::Rooted<JSObject*> promiseObj(cx, PromiseObj());
+  if (NS_WARN_IF(!JS::AddPromiseReactions(cx, promiseObj, resolveFunc,
+                                          rejectFunc))) {
+    jsapi.ClearException();
+    return;
+  }
+}
+
+void
+Promise::HandleException(JSContext* aCx)
+{
+  JS::Rooted<JS::Value> exn(aCx);
+  if (JS_GetPendingException(aCx, &exn)) {
+    JS_ClearPendingException(aCx);
+    // This is only called from MaybeSomething, so it's OK to MaybeReject here,
+    // unlike in the version that's used when !SPIDERMONKEY_PROMISE.
+    MaybeReject(aCx, exn);
+  }
+}
+
+// static
+already_AddRefed<Promise>
+Promise::CreateFromExisting(nsIGlobalObject* aGlobal,
+                            JS::Handle<JSObject*> aPromiseObj)
+{
+  MOZ_ASSERT(js::GetObjectCompartment(aGlobal->GetGlobalJSObject()) ==
+             js::GetObjectCompartment(aPromiseObj));
+  RefPtr<Promise> p = new Promise(aGlobal);
+  p->mPromiseObj = aPromiseObj;
+  return p.forget();
+}
+
+#else // SPIDERMONKEY_PROMISE
+
 JSObject*
 Promise::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
 {
   return PromiseBinding::Wrap(aCx, this, aGivenProto);
 }
 
 already_AddRefed<Promise>
 Promise::Create(nsIGlobalObject* aGlobal, ErrorResult& aRv,
@@ -532,16 +894,18 @@ Promise::MaybeResolve(JSContext* aCx,
 
 void
 Promise::MaybeReject(JSContext* aCx,
                      JS::Handle<JS::Value> aValue)
 {
   MaybeRejectInternal(aCx, aValue);
 }
 
+#endif // SPIDERMONKEY_PROMISE
+
 void
 Promise::MaybeReject(const RefPtr<MediaStreamError>& aArg) {
   MaybeSomething(aArg, &Promise::MaybeReject);
 }
 
 void
 Promise::MaybeRejectWithNull()
 {
@@ -578,16 +942,18 @@ Promise::PerformMicroTaskCheckpoint()
       JS_CheckForInterrupt(cx.ref());
     }
     runtime->AfterProcessMicrotask();
   } while (!microtaskQueue.empty());
 
   return true;
 }
 
+#ifndef SPIDERMONKEY_PROMISE
+
 /* static */ bool
 Promise::JSCallback(JSContext* aCx, unsigned aArgc, JS::Value* aVp)
 {
   JS::CallArgs args = CallArgsFromVp(aArgc, aVp);
 
   JS::Rooted<JS::Value> v(aCx,
                           js::GetFunctionNativeReserved(&args.callee(),
                                                         SLOT_PROMISE));
@@ -1980,28 +2346,31 @@ Promise::AppendNativeHandler(PromiseNati
     new NativePromiseCallback(aRunnable, Resolved);
 
   RefPtr<PromiseCallback> rejectCb =
     new NativePromiseCallback(aRunnable, Rejected);
 
   AppendCallbacks(resolveCb, rejectCb);
 }
 
+#endif // SPIDERMONKEY_PROMISE
+
 JSObject*
 Promise::GlobalJSObject() const
 {
   return mGlobal->GetGlobalJSObject();
 }
 
 JSCompartment*
 Promise::Compartment() const
 {
   return js::GetObjectCompartment(GlobalJSObject());
 }
 
+#ifndef SPIDERMONKEY_PROMISE
 void
 Promise::AppendCallbacks(PromiseCallback* aResolveCallback,
                          PromiseCallback* aRejectCallback)
 {
   if (!mGlobal || mGlobal->IsDying()) {
     return;
   }
 
@@ -2028,60 +2397,31 @@ Promise::AppendCallbacks(PromiseCallback
 
   // If promise's state is fulfilled, queue a task to process our fulfill
   // callbacks with promise's result. If promise's state is rejected, queue a
   // task to process our reject callbacks with promise's result.
   if (mState != Pending) {
     TriggerPromiseReactions();
   }
 }
-
-class WrappedWorkerRunnable final : public WorkerSameThreadRunnable
-{
-public:
-  WrappedWorkerRunnable(workers::WorkerPrivate* aWorkerPrivate, nsIRunnable* aRunnable)
-    : WorkerSameThreadRunnable(aWorkerPrivate)
-    , mRunnable(aRunnable)
-  {
-    MOZ_ASSERT(aRunnable);
-    MOZ_COUNT_CTOR(WrappedWorkerRunnable);
-  }
-
-  bool
-  WorkerRun(JSContext* aCx, workers::WorkerPrivate* aWorkerPrivate) override
-  {
-    NS_ASSERT_OWNINGTHREAD(WrappedWorkerRunnable);
-    mRunnable->Run();
-    return true;
-  }
-
-private:
-  virtual
-  ~WrappedWorkerRunnable()
-  {
-    MOZ_COUNT_DTOR(WrappedWorkerRunnable);
-    NS_ASSERT_OWNINGTHREAD(WrappedWorkerRunnable);
-  }
-
-  nsCOMPtr<nsIRunnable> mRunnable;
-  NS_DECL_OWNINGTHREAD
-};
+#endif // SPIDERMONKEY_PROMISE
 
 /* static */ void
 Promise::DispatchToMicroTask(nsIRunnable* aRunnable)
 {
   MOZ_ASSERT(aRunnable);
 
   CycleCollectedJSRuntime* runtime = CycleCollectedJSRuntime::Get();
   std::queue<nsCOMPtr<nsIRunnable>>& microtaskQueue =
     runtime->GetPromiseMicroTaskQueue();
 
   microtaskQueue.push(aRunnable);
 }
 
+#ifndef SPIDERMONKEY_PROMISE
 #if defined(DOM_PROMISE_DEPRECATED_REPORTING)
 void
 Promise::MaybeReportRejected()
 {
   if (mState != Rejected || mHadRejectCallback || mResult.isUndefined()) {
     return;
   }
 
@@ -2364,16 +2704,18 @@ Promise::GetDependentPromises(nsTArray<R
   for (size_t i = 0; i < mRejectCallbacks.Length(); ++i) {
     Promise* p = mRejectCallbacks[i]->GetDependentPromise();
     if (p) {
       aPromises.AppendElement(p);
     }
   }
 }
 
+#endif // SPIDERMONKEY_PROMISE
+
 // A WorkerRunnable to resolve/reject the Promise on the worker thread.
 // Calling thread MUST hold PromiseWorkerProxy's mutex before creating this.
 class PromiseWorkerProxyRunnable : public workers::WorkerRunnable
 {
 public:
   PromiseWorkerProxyRunnable(PromiseWorkerProxy* aPromiseWorkerProxy,
                              PromiseWorkerProxy::RunCallbackFunc aFunc)
     : WorkerRunnable(aPromiseWorkerProxy->GetWorkerPrivate(),
@@ -2565,24 +2907,24 @@ PromiseWorkerProxy::RunCallback(JSContex
 
   runnable->Dispatch(aCx);
 }
 
 void
 PromiseWorkerProxy::ResolvedCallback(JSContext* aCx,
                                      JS::Handle<JS::Value> aValue)
 {
-  RunCallback(aCx, aValue, &Promise::ResolveInternal);
+  RunCallback(aCx, aValue, &Promise::MaybeResolve);
 }
 
 void
 PromiseWorkerProxy::RejectedCallback(JSContext* aCx,
                                      JS::Handle<JS::Value> aValue)
 {
-  RunCallback(aCx, aValue, &Promise::RejectInternal);
+  RunCallback(aCx, aValue, &Promise::MaybeReject);
 }
 
 bool
 PromiseWorkerProxy::Notify(JSContext* aCx, Status aStatus)
 {
   if (aStatus >= Canceling) {
     CleanUp(aCx);
   }
@@ -2648,18 +2990,20 @@ template<>
 void Promise::MaybeRejectBrokenly(const RefPtr<DOMError>& aArg) {
   MaybeSomething(aArg, &Promise::MaybeReject);
 }
 template<>
 void Promise::MaybeRejectBrokenly(const nsAString& aArg) {
   MaybeSomething(aArg, &Promise::MaybeReject);
 }
 
+#ifndef SPIDERMONKEY_PROMISE
 uint64_t
 Promise::GetID() {
   if (mID != 0) {
     return mID;
   }
   return mID = ++gIDGenerator;
 }
+#endif // SPIDERMONKEY_PROMISE
 
 } // namespace dom
 } // namespace mozilla
--- a/dom/promise/Promise.h
+++ b/dom/promise/Promise.h
@@ -66,17 +66,22 @@ public:
 };
 #endif // defined(DOM_PROMISE_DEPRECATED_REPORTING)
 
 #define NS_PROMISE_IID \
   { 0x1b8d6215, 0x3e67, 0x43ba, \
     { 0x8a, 0xf9, 0x31, 0x5e, 0x8f, 0xce, 0x75, 0x65 } }
 
 class Promise : public nsISupports,
+#ifndef SPIDERMONKEY_PROMISE
+                // Only wrappercached when we're not using SpiderMonkey
+                // promises, because those don't have a useful object moved
+                // hook, which wrappercache needs.
                 public nsWrapperCache,
+#endif // SPIDERMONKEY_PROMISE
                 public SupportsWeakPtr<Promise>
 {
   friend class NativePromiseCallback;
   friend class PromiseReactionJob;
   friend class PromiseResolverTask;
   friend class PromiseTask;
 #if defined(DOM_PROMISE_DEPRECATED_REPORTING)
   friend class PromiseReportRejectFeature;
@@ -87,27 +92,37 @@ class Promise : public nsISupports,
   friend class ResolvePromiseCallback;
   friend class PromiseResolveThenableJob;
   friend class FastPromiseResolveThenableJob;
   friend class WrapperPromiseCallback;
 
 public:
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_PROMISE_IID)
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+#ifdef SPIDERMONKEY_PROMISE
+  // We're not skippable, since we're not owned from JS to start with.
+  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(Promise)
+#else // SPIDERMONKEY_PROMISE
   NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS(Promise)
+#endif // SPIDERMONKEY_PROMISE
   MOZ_DECLARE_WEAKREFERENCE_TYPENAME(Promise)
 
   // Promise creation tries to create a JS reflector for the Promise, so is
   // fallible.  Furthermore, we don't want to do JS-wrapping on a 0-refcount
   // object, so we addref before doing that and return the addrefed pointer
   // here.
+#ifdef SPIDERMONKEY_PROMISE
+  static already_AddRefed<Promise>
+  Create(nsIGlobalObject* aGlobal, ErrorResult& aRv);
+#else
   static already_AddRefed<Promise>
   Create(nsIGlobalObject* aGlobal, ErrorResult& aRv,
          // Passing null for aDesiredProto will use Promise.prototype.
          JS::Handle<JSObject*> aDesiredProto = nullptr);
+#endif // SPIDERMONKEY_PROMISE
 
   typedef void (Promise::*MaybeFunc)(JSContext* aCx,
                                      JS::Handle<JS::Value> aValue);
 
   void MaybeResolve(JSContext* aCx,
                     JS::Handle<JS::Value> aValue);
   void MaybeReject(JSContext* aCx,
                    JS::Handle<JS::Value> aValue);
@@ -153,16 +168,62 @@ public:
 
   // WebIDL
 
   nsIGlobalObject* GetParentObject() const
   {
     return mGlobal;
   }
 
+#ifdef SPIDERMONKEY_PROMISE
+  bool
+  WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto,
+             JS::MutableHandle<JSObject*> aWrapper);
+
+  // Do the equivalent of Promise.resolve in the current compartment of aCx.
+  // Errorrs are reported on the ErrorResult; if aRv comes back !Failed(), this
+  // function MUST return a non-null value.
+  static already_AddRefed<Promise>
+  Resolve(nsIGlobalObject* aGlobal, JSContext* aCx,
+          JS::Handle<JS::Value> aValue, ErrorResult& aRv);
+
+  // Do the equivalent of Promise.reject in the current compartment of aCx.
+  // Errorrs are reported on the ErrorResult; if aRv comes back !Failed(), this
+  // function MUST return a non-null value.
+  static already_AddRefed<Promise>
+  Reject(nsIGlobalObject* aGlobal, JSContext* aCx,
+         JS::Handle<JS::Value> aValue, ErrorResult& aRv);
+
+  static already_AddRefed<Promise>
+  All(const GlobalObject& aGlobal,
+      const nsTArray<RefPtr<Promise>>& aPromiseList, ErrorResult& aRv);
+
+  void
+  Then(JSContext* aCx,
+       // aCalleeGlobal may not be in the compartment of aCx, when called over
+       // Xrays.
+       JS::Handle<JSObject*> aCalleeGlobal,
+       AnyCallback* aResolveCallback, AnyCallback* aRejectCallback,
+       JS::MutableHandle<JS::Value> aRetval,
+       ErrorResult& aRv);
+
+  JSObject* PromiseObj() const
+  {
+    if (mPromiseObj) {
+      JS::ExposeObjectToActiveJS(mPromiseObj);
+    }
+    return mPromiseObj;
+  }
+
+#else // SPIDERMONKEY_PROMISE
+  JSObject* PromiseObj()
+  {
+    return GetWrapper();
+  }
+
   virtual JSObject*
   WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
 
   static already_AddRefed<Promise>
   Constructor(const GlobalObject& aGlobal, PromiseInit& aInit,
               ErrorResult& aRv, JS::Handle<JSObject*> aDesiredProto);
 
   static void
@@ -209,48 +270,63 @@ public:
 
   static void
   Race(const GlobalObject& aGlobal, JS::Handle<JS::Value> aThisv,
        JS::Handle<JS::Value> aIterable, JS::MutableHandle<JS::Value> aRetval,
        ErrorResult& aRv);
 
   static bool
   PromiseSpecies(JSContext* aCx, unsigned aArgc, JS::Value* aVp);
+#endif // SPIDERMONKEY_PROMISE
 
   void AppendNativeHandler(PromiseNativeHandler* aRunnable);
 
   JSObject* GlobalJSObject() const;
 
   JSCompartment* Compartment() const;
 
+#ifndef SPIDERMONKEY_PROMISE
   // Return a unique-to-the-process identifier for this Promise.
   uint64_t GetID();
+#endif // SPIDERMONKEY_PROMISE
 
   // Queue an async microtask to current main or worker thread.
   static void
   DispatchToMicroTask(nsIRunnable* aRunnable);
 
+#ifndef SPIDERMONKEY_PROMISE
   enum JSCallbackSlots {
     SLOT_PROMISE = 0,
     SLOT_DATA
   };
+#endif // SPIDERMONKEY_PROMISE
+
+#ifdef SPIDERMONKEY_PROMISE
+  // Create a dom::Promise from a given SpiderMonkey Promise object.
+  // aPromiseObj MUST be in the compartment of aGlobal's global JS object.
+  static already_AddRefed<Promise>
+  CreateFromExisting(nsIGlobalObject* aGlobal,
+                     JS::Handle<JSObject*> aPromiseObj);
+#endif // SPIDERMONKEY_PROMISE
 
 protected:
   struct PromiseCapability;
 
-  // Do NOT call this unless you're Promise::Create.  I wish we could enforce
-  // that from inside this class too, somehow.
+  // Do NOT call this unless you're Promise::Create or
+  // Promise::CreateFromExisting.  I wish we could enforce that from inside this
+  // class too, somehow.
   explicit Promise(nsIGlobalObject* aGlobal);
 
   virtual ~Promise();
 
   // Do JS-wrapping after Promise creation.  Passing null for aDesiredProto will
   // use the default prototype for the sort of Promise we have.
   void CreateWrapper(JS::Handle<JSObject*> aDesiredProto, ErrorResult& aRv);
 
+#ifndef SPIDERMONKEY_PROMISE
   // Create the JS resolving functions of resolve() and reject(). And provide
   // references to the two functions by calling PromiseInit passed from Promise
   // constructor.
   void CallInitFunction(const GlobalObject& aGlobal, PromiseInit& aInit,
                         ErrorResult& aRv);
 
   // The NewPromiseCapability function from
   // <http://www.ecma-international.org/ecma-262/6.0/#sec-newpromisecapability>.
@@ -279,26 +355,28 @@ protected:
   {
     mWasNotifiedAsUncaught = true;
   }
 
   bool WasNotifiedAsUncaught() const
   {
     return mWasNotifiedAsUncaught;
   }
+#endif // SPIDERMONKEY_PROMISE
 
 private:
-  friend class PromiseDebugging;
-
   enum PromiseState {
     Pending,
     Resolved,
     Rejected
   };
 
+#ifndef SPIDERMONKEY_PROMISE
+  friend class PromiseDebugging;
+
   void SetState(PromiseState aState)
   {
     MOZ_ASSERT(mState == Pending);
     MOZ_ASSERT(aState != Pending);
     mState = aState;
   }
 
   void SetResult(JS::Handle<JS::Value> aValue)
@@ -335,33 +413,35 @@ private:
                             JS::Handle<JS::Value> aValue);
   void MaybeRejectInternal(JSContext* aCx,
                            JS::Handle<JS::Value> aValue);
 
   void ResolveInternal(JSContext* aCx,
                        JS::Handle<JS::Value> aValue);
   void RejectInternal(JSContext* aCx,
                       JS::Handle<JS::Value> aValue);
+#endif // SPIDERMONKEY_PROMISE
 
   template <typename T>
   void MaybeSomething(T& aArgument, MaybeFunc aFunc) {
     ThreadsafeAutoJSContext cx;
-    JSObject* wrapper = GetWrapper();
+    JSObject* wrapper = PromiseObj();
     MOZ_ASSERT(wrapper); // We preserved it!
 
     JSAutoCompartment ac(cx, wrapper);
     JS::Rooted<JS::Value> val(cx);
     if (!ToJSValue(cx, aArgument, &val)) {
       HandleException(cx);
       return;
     }
 
     (this->*aFunc)(cx, val);
   }
 
+#ifndef SPIDERMONKEY_PROMISE
   // Static methods for the PromiseInit functions.
   static bool
   JSCallback(JSContext *aCx, unsigned aArgc, JS::Value *aVp);
 
   static bool
   ThenableResolverCommon(JSContext* aCx, uint32_t /* PromiseCallback::Task */ aTask,
                          unsigned aArgc, JS::Value* aVp);
   static bool
@@ -370,28 +450,30 @@ private:
   JSCallbackThenableRejecter(JSContext *aCx, unsigned aArgc, JS::Value *aVp);
 
   static JSObject*
   CreateFunction(JSContext* aCx, Promise* aPromise, int32_t aTask);
 
   static JSObject*
   CreateThenableFunction(JSContext* aCx, Promise* aPromise, uint32_t aTask);
 
-  void HandleException(JSContext* aCx);
-
 #if defined(DOM_PROMISE_DEPRECATED_REPORTING)
   void RemoveFeature();
 #endif // defined(DOM_PROMISE_DEPRECATED_REPORTING)
 
   // Capture the current stack and store it in aTarget.  If false is
   // returned, an exception is presumably pending on aCx.
   bool CaptureStack(JSContext* aCx, JS::Heap<JSObject*>& aTarget);
+#endif // SPIDERMONKEY_PROMISE
+
+  void HandleException(JSContext* aCx);
 
   RefPtr<nsIGlobalObject> mGlobal;
 
+#ifndef SPIDERMONKEY_PROMISE
   nsTArray<RefPtr<PromiseCallback> > mResolveCallbacks;
   nsTArray<RefPtr<PromiseCallback> > mRejectCallbacks;
 
   JS::Heap<JS::Value> mResult;
   // A stack that shows where this promise was allocated, if there was
   // JS running at the time.  Otherwise null.
   JS::Heap<JSObject*> mAllocationStack;
   // mRejectionStack is only set when the promise is rejected directly from
@@ -432,16 +514,19 @@ private:
   TimeStamp mCreationTimestamp;
 
   // The time when this promise transitioned out of the pending state.
   TimeStamp mSettlementTimestamp;
 
   // Once `GetID()` has been called, a unique-to-the-process identifier for this
   // promise. Until then, `0`.
   uint64_t mID;
+#else // SPIDERMONKEY_PROMISE
+  JS::Heap<JSObject*> mPromiseObj;
+#endif // SPIDERMONKEY_PROMISE
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(Promise, NS_PROMISE_IID)
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_Promise_h
--- a/dom/promise/PromiseCallback.cpp
+++ b/dom/promise/PromiseCallback.cpp
@@ -10,16 +10,18 @@
 
 #include "jsapi.h"
 #include "jsfriendapi.h"
 #include "jswrapper.h"
 
 namespace mozilla {
 namespace dom {
 
+#ifndef SPIDERMONKEY_PROMISE
+
 NS_IMPL_CYCLE_COLLECTING_ADDREF(PromiseCallback)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(PromiseCallback)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(PromiseCallback)
   NS_INTERFACE_MAP_ENTRY(nsISupports)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_CYCLE_COLLECTION_0(PromiseCallback)
@@ -561,10 +563,12 @@ PromiseCallback::Factory(Promise* aNextP
   if (aTask == Reject) {
     return new RejectPromiseCallback(aNextPromise, aGlobal);
   }
 
   MOZ_ASSERT(false, "This should not happen");
   return nullptr;
 }
 
+#endif // SPIDERMONKEY_PROMISE
+
 } // namespace dom
 } // namespace mozilla
--- a/dom/promise/PromiseCallback.h
+++ b/dom/promise/PromiseCallback.h
@@ -8,16 +8,17 @@
 #define mozilla_dom_PromiseCallback_h
 
 #include "mozilla/dom/Promise.h"
 #include "nsCycleCollectionParticipant.h"
 
 namespace mozilla {
 namespace dom {
 
+#ifndef SPIDERMONKEY_PROMISE
 // This is the base class for any PromiseCallback.
 // It's a logical step in the promise chain of callbacks.
 class PromiseCallback : public nsISupports
 {
 protected:
   virtual ~PromiseCallback();
 
 public:
@@ -189,12 +190,14 @@ public:
 
 private:
   ~NativePromiseCallback();
 
   RefPtr<PromiseNativeHandler> mHandler;
   Promise::PromiseState mState;
 };
 
+#endif // SPIDERMONKEY_PROMISE
+
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_PromiseCallback_h
--- a/dom/promise/PromiseDebugging.cpp
+++ b/dom/promise/PromiseDebugging.cpp
@@ -61,16 +61,17 @@ private:
   // `true` if an instance of `FlushRejections` is currently dispatched
   // and has not been executed yet.
   static MOZ_THREAD_LOCAL(bool) sDispatched;
 };
 
 /* static */ MOZ_THREAD_LOCAL(bool)
 FlushRejections::sDispatched;
 
+#ifndef SPIDERMONKEY_PROMISE
 static Promise*
 UnwrapPromise(JS::Handle<JSObject*> aPromise, ErrorResult& aRv)
 {
   Promise* promise;
   if (NS_WARN_IF(NS_FAILED(UNWRAP_OBJECT(Promise, aPromise, promise)))) {
     aRv.ThrowTypeError<MSG_IS_NOT_PROMISE>(NS_LITERAL_STRING("Argument"));
     return nullptr;
   }
@@ -98,16 +99,18 @@ PromiseDebugging::GetState(GlobalObject&
   case Promise::Rejected:
     aState.mState = PromiseDebuggingState::Rejected;
     JS::ExposeValueToActiveJS(promise->mResult);
     aState.mReason = promise->mResult;
     break;
   }
 }
 
+#endif // SPIDERMONKEY_PROMISE
+
 /*static */ nsString
 PromiseDebugging::sIDPrefix;
 
 /* static */ void
 PromiseDebugging::Init()
 {
   FlushRejections::Init();
 
@@ -125,20 +128,25 @@ PromiseDebugging::Init()
 PromiseDebugging::Shutdown()
 {
   sIDPrefix.SetIsVoid(true);
 }
 
 /* static */ void
 PromiseDebugging::FlushUncaughtRejections()
 {
+  // XXXbz figure out the plan
+#ifndef SPIDERMONKEY_PROMISE
   MOZ_ASSERT(!NS_IsMainThread());
   FlushRejections::FlushSync();
+#endif // SPIDERMONKEY_PROMISE
 }
 
+#ifndef SPIDERMONKEY_PROMISE
+
 /* static */ void
 PromiseDebugging::GetAllocationStack(GlobalObject&, JS::Handle<JSObject*> aPromise,
                                      JS::MutableHandle<JSObject*> aStack,
                                      ErrorResult& aRv)
 {
   Promise* promise = UnwrapPromise(aPromise, aRv);
   if (aRv.Failed()) {
     return;
@@ -205,16 +213,18 @@ PromiseDebugging::GetTimeToSettle(Global
   if (promise->mState == Promise::Pending) {
     aRv.Throw(NS_ERROR_UNEXPECTED);
     return 0;
   }
   return (promise->mSettlementTimestamp -
           promise->mCreationTimestamp).ToMilliseconds();
 }
 
+#endif // SPIDERMONKEY_PROMISE
+
 /* static */ void
 PromiseDebugging::AddUncaughtRejectionObserver(GlobalObject&,
                                                UncaughtRejectionObserver& aObserver)
 {
   CycleCollectedJSRuntime* storage = CycleCollectedJSRuntime::Get();
   nsTArray<nsCOMPtr<nsISupports>>& observers = storage->mUncaughtRejectionObservers;
   observers.AppendElement(&aObserver);
 }
@@ -230,16 +240,18 @@ PromiseDebugging::RemoveUncaughtRejectio
     if (*observer == aObserver) {
       observers.RemoveElementAt(i);
       return true;
     }
   }
   return false;
 }
 
+#ifndef SPIDERMONKEY_PROMISE
+
 /* static */ void
 PromiseDebugging::AddUncaughtRejection(Promise& aPromise)
 {
   CycleCollectedJSRuntime::Get()->mUncaughtRejections.AppendElement(&aPromise);
   FlushRejections::DispatchNeeded();
 }
 
 /* void */ void
@@ -258,20 +270,23 @@ PromiseDebugging::GetPromiseID(GlobalObj
   Promise* promise = UnwrapPromise(aPromise, aRv);
   if (aRv.Failed()) {
     return;
   }
   uint64_t promiseID = promise->GetID();
   aID = sIDPrefix;
   aID.AppendInt(promiseID);
 }
+#endif // SPIDERMONKEY_PROMISE
 
 /* static */ void
 PromiseDebugging::FlushUncaughtRejectionsInternal()
 {
+  // XXXbz talk to till about replacement for this stuff.
+#ifndef SPIDERMONKEY_PROMISE
   CycleCollectedJSRuntime* storage = CycleCollectedJSRuntime::Get();
 
   // The Promise that have been left uncaught (rejected and last in
   // their chain) since the last call to this function.
   nsTArray<nsCOMPtr<nsISupports>> uncaught;
   storage->mUncaughtRejections.SwapElements(uncaught);
 
   // The Promise that have been left uncaught at some point, but that
@@ -322,12 +337,13 @@ PromiseDebugging::FlushUncaughtRejection
     for (size_t j = 0; j < observers.Length(); ++j) {
       ErrorResult err;
       RefPtr<UncaughtRejectionObserver> obs =
         static_cast<UncaughtRejectionObserver*>(observers[j].get());
 
       obs->OnConsumed(*promise, err); // Ignore errors
     }
   }
+#endif // SPIDERMONKEY_PROMISE
 }
 
 } // namespace dom
 } // namespace mozilla
--- a/dom/promise/PromiseDebugging.h
+++ b/dom/promise/PromiseDebugging.h
@@ -27,16 +27,17 @@ class UncaughtRejectionObserver;
 class FlushRejections;
 
 class PromiseDebugging
 {
 public:
   static void Init();
   static void Shutdown();
 
+#ifndef SPIDERMONKEY_PROMISE
   static void GetState(GlobalObject&, JS::Handle<JSObject*> aPromise,
                        PromiseDebuggingStateHolder& aState,
                        ErrorResult& aRv);
 
   static void GetAllocationStack(GlobalObject&, JS::Handle<JSObject*> aPromise,
                                  JS::MutableHandle<JSObject*> aStack,
                                  ErrorResult& aRv);
   static void GetRejectionStack(GlobalObject&, JS::Handle<JSObject*> aPromise,
@@ -53,30 +54,35 @@ public:
   static double GetPromiseLifetime(GlobalObject&,
                                    JS::Handle<JSObject*> aPromise,
                                    ErrorResult& aRv);
   static double GetTimeToSettle(GlobalObject&, JS::Handle<JSObject*> aPromise,
                                 ErrorResult& aRv);
 
   static void GetPromiseID(GlobalObject&, JS::Handle<JSObject*>, nsString&,
                            ErrorResult&);
+#endif // SPIDERMONKEY_PROMISE
 
   // Mechanism for watching uncaught instances of Promise.
+  // XXXbz figure out the plan
   static void AddUncaughtRejectionObserver(GlobalObject&,
                                            UncaughtRejectionObserver& aObserver);
   static bool RemoveUncaughtRejectionObserver(GlobalObject&,
                                               UncaughtRejectionObserver& aObserver);
 
+#ifndef SPIDERMONKEY_PROMISE
   // Mark a Promise as having been left uncaught at script completion.
   static void AddUncaughtRejection(Promise&);
   // Mark a Promise previously added with `AddUncaughtRejection` as
   // eventually consumed.
   static void AddConsumedRejection(Promise&);
+#endif // SPIDERMONKEY_PROMISE
   // Propagate the informations from AddUncaughtRejection
   // and AddConsumedRejection to observers.
+  // XXXbz figure out the plan.
   static void FlushUncaughtRejections();
 
 protected:
   static void FlushUncaughtRejectionsInternal();
   friend class FlushRejections;
   friend class WorkerPrivate;
 private:
   // Identity of the process.
new file mode 100644
--- /dev/null
+++ b/dom/promise/PromiseNativeHandler.cpp
@@ -0,0 +1,26 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+* License, v. 2.0. If a copy of the MPL was not distributed with this file,
+* You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "mozilla/dom/PromiseNativeHandler.h"
+#include "mozilla/dom/PromiseBinding.h"
+
+namespace mozilla {
+namespace dom {
+
+#ifdef SPIDERMONKEY_PROMISE
+bool
+PromiseNativeHandler::WrapObject(JSContext* aCx,
+                                       JS::Handle<JSObject*> aGivenProto,
+                                       JS::MutableHandle<JSObject*> aWrapper)
+{
+  return PromiseNativeHandlerBinding::Wrap(aCx, this, aGivenProto, aWrapper);
+}
+#endif // SPIDERMONKEY_PROMISE
+
+} // namespace dom
+} // namespace mozilla
+
+
--- a/dom/promise/PromiseNativeHandler.h
+++ b/dom/promise/PromiseNativeHandler.h
@@ -25,14 +25,20 @@ protected:
   { }
 
 public:
   virtual void
   ResolvedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) = 0;
 
   virtual void
   RejectedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) = 0;
+
+#ifdef SPIDERMONKEY_PROMISE
+    bool WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto,
+                  JS::MutableHandle<JSObject*> aWrapper);
+#endif // SPIDERMONKEY_PROMISE
+
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_PromiseNativeHandler_h
--- a/dom/promise/moz.build
+++ b/dom/promise/moz.build
@@ -9,17 +9,18 @@ EXPORTS.mozilla.dom += [
     'PromiseDebugging.h',
     'PromiseNativeHandler.h',
     'PromiseWorkerProxy.h',
 ]
 
 UNIFIED_SOURCES += [
     'Promise.cpp',
     'PromiseCallback.cpp',
-    'PromiseDebugging.cpp'
+    'PromiseDebugging.cpp',
+    'PromiseNativeHandler.cpp',
 ]
 
 LOCAL_INCLUDES += [
     '../base',
     '../ipc',
     '../workers',
 ]
 
--- a/dom/push/PushServiceHttp2.jsm
+++ b/dom/push/PushServiceHttp2.jsm
@@ -548,19 +548,17 @@ this.PushServiceHttp2 = {
     this._conns[aSubscriptionUri].lastStartListening = Date.now();
     this._conns[aSubscriptionUri].channel = conn.channel;
     this._conns[aSubscriptionUri].listener = conn.listener;
 
   },
 
   _ackMsgRecv: function(aAckUri) {
     console.debug("ackMsgRecv()", aAckUri);
-    // We can't do anything about it if it fails,
-    // so we don't listen for response.
-    this._deleteResource(aAckUri);
+    return this._deleteResource(aAckUri);
   },
 
   init: function(aOptions, aMainPushService, aServerURL) {
     console.debug("init()");
     this._mainPushService = aMainPushService;
     this._serverURI = aServerURL;
 
     return Promise.resolve();
--- a/dom/security/test/csp/file_child-src_service_worker.html
+++ b/dom/security/test/csp/file_child-src_service_worker.html
@@ -4,23 +4,24 @@
     <title>Bug 1045891</title>
   </head>
   <body>
   <script type="text/javascript">
     page_id = window.location.hash.substring(1);
     try {
       if ('serviceWorker' in navigator) {
         navigator.serviceWorker.register(
-            'file_child-src_service_worker.js'
-            + "#"
-            + page_id
+            'file_child-src_service_worker.js',
+            { scope: './' + page_id + '/' }
             ).then(function(reg)
               {
                 // registration worked
-                window.parent.postMessage({id:page_id, message:"allowed"}, 'http://mochi.test:8888');
+                reg.unregister().then(function() {
+                  window.parent.postMessage({id:page_id, message:"allowed"}, 'http://mochi.test:8888');
+                });
               }).catch(function(error) {
               // registration failed
               window.parent.postMessage({id:page_id, message:"blocked"}, 'http://mochi.test:8888');
             });
       };
     } catch(ex) {
       window.parent.postMessage({id:page_id, message:"exception"}, 'http://mochi.test:8888');
     }
--- a/dom/security/test/mixedcontentblocker/file_frameNavigation_grandchild.html
+++ b/dom/security/test/mixedcontentblocker/file_frameNavigation_grandchild.html
@@ -7,18 +7,18 @@ https://bugzilla.mozilla.org/show_bug.cg
 <head>
   <meta charset="utf-8">
   <title>Tests for Mixed Content Frame Navigation</title>
 </head>
 <body>
 <iframe src="https://example.com/tests/dom/security/test/mixedcontentblocker/file_frameNavigation_innermost.html?insecurePage_navigate_grandchild" id="child"></iframe>
 
 <script>
-  // For tests that require setTimeout, set the maximum polling time to 50 x 100ms = 5 seconds.
-  var MAX_COUNT = 50;
+  // For tests that require setTimeout, set the maximum polling time to 100 x 100ms = 10 seconds.
+  var MAX_COUNT = 100;
   var TIMEOUT_INTERVAL = 100;
   var counter = 0;
 
   var child = document.getElementById("child");
   function navigationStatus(child)
   {
     // When the page is navigating, it goes through about:blank and we will get a permission denied for loc.
     // Catch that specific exception and return
--- a/dom/smil/nsSMILCSSValueType.cpp
+++ b/dom/smil/nsSMILCSSValueType.cpp
@@ -355,19 +355,24 @@ ValueFromStringHelper(nsCSSProperty aPro
   if (aPropID != eCSSProperty_stroke_dasharray) {
     int32_t absValuePos = nsSMILParserUtils::CheckForNegativeNumber(aString);
     if (absValuePos > 0) {
       isNegative = true;
       subStringBegin = (uint32_t)absValuePos; // Start parsing after '-' sign
     }
   }
   nsDependentSubstring subString(aString, subStringBegin);
-  if (!StyleAnimationValue::ComputeValue(aPropID, aTargetElement, subString,
-                                         true, aStyleAnimValue,
-                                         aIsContextSensitive)) {
+  if (!StyleAnimationValue::ComputeValue(
+        aPropID,
+        aTargetElement,
+        nsCSSPseudoElements::ePseudo_NotPseudoElement,
+        subString,
+        true,
+        aStyleAnimValue,
+        aIsContextSensitive)) {
     return false;
   }
   if (isNegative) {
     InvertSign(aStyleAnimValue);
   }
 
   if (aPropID == eCSSProperty_font_size) {
     // Divide out text-zoom, since SVG is supposed to ignore it
--- a/dom/tests/browser/browser_frame_elements.js
+++ b/dom/tests/browser/browser_frame_elements.js
@@ -1,44 +1,47 @@
 /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
 /* vim: set ts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 const TEST_URI = "http://example.com/browser/dom/tests/browser/browser_frame_elements.html";
-var gWindow;
 
-function test() {
-  waitForExplicitFinish();
-
-  var tab = gBrowser.addTab(TEST_URI);
-  gBrowser.selectedTab = tab;
-  var browser = gBrowser.selectedBrowser;
-
-  registerCleanupFunction(function () {
-    gBrowser.removeTab(tab);
-    gWindow = null;
-  });
-
-  browser.addEventListener("DOMContentLoaded", function onLoad(event) {
-    browser.removeEventListener("DOMContentLoaded", onLoad, false);
-    executeSoon(function test_executeSoon() {
-      gWindow = browser.contentWindow;
-      startTests();
-    });
-  }, false);
+function getWindowUtils(window) {
+  return window.
+    QueryInterface(Components.interfaces.nsIInterfaceRequestor).
+    getInterface(Components.interfaces.nsIDOMWindowUtils);
 }
 
+add_task(function* test() {
+  yield BrowserTestUtils.withNewTab({ gBrowser, url: TEST_URI }, function* (browser) {
+    if (!browser.isRemoteBrowser) {
+      // Non-e10s, access contentWindow and confirm its container is the browser:
+      let windowUtils = getWindowUtils(browser.contentWindow);
+      is (windowUtils.containerElement, browser,
+          "Container element for main window is xul:browser");
+
+    }
+
+    yield ContentTask.spawn(browser, null, startTests);
+    yield Task.spawn(mozBrowserTests(browser));
+  });
+});
+
 function startTests() {
+  function getWindowUtils(window) {
+    return window.
+      QueryInterface(Components.interfaces.nsIInterfaceRequestor).
+      getInterface(Components.interfaces.nsIDOMWindowUtils);
+  }
   info("Frame tests started");
 
   info("Checking top window");
-  let windowUtils = getWindowUtils(gWindow);
-  is (windowUtils.containerElement, gBrowser.selectedBrowser, "Container element for main window is xul:browser");
+  let gWindow = content;
   is (gWindow.top, gWindow, "gWindow is top");
   is (gWindow.parent, gWindow, "gWindow is parent");
 
   info("Checking about:blank iframe");
   let iframeBlank = gWindow.document.querySelector("#iframe-blank");
   ok (iframeBlank, "Iframe exists on page");
   let iframeBlankUtils = getWindowUtils(iframeBlank.contentWindow);
   is (iframeBlankUtils.containerElement, iframeBlank, "Container element for iframe window is iframe");
@@ -55,33 +58,30 @@ function startTests() {
 
   info("Checking object with data url data attribute");
   let objectDataUrl = gWindow.document.querySelector("#object-data-url");
   ok (objectDataUrl, "Object exists on page");
   let objectDataUrlUtils = getWindowUtils(objectDataUrl.contentWindow);
   is (objectDataUrlUtils.containerElement, objectDataUrl, "Container element for object window is the object");
   is (objectDataUrl.contentWindow.top, gWindow, "gWindow is top");
   is (objectDataUrl.contentWindow.parent, gWindow, "gWindow is parent");
+}
 
+function* mozBrowserTests(browser) {
   info("Granting special powers for mozbrowser");
-  SpecialPowers.addPermission("browser", true, gWindow.document);
+  SpecialPowers.addPermission("browser", true, TEST_URI);
   SpecialPowers.setBoolPref('dom.mozBrowserFramesEnabled', true);
 
-  info("Checking mozbrowser iframe");
-  let mozBrowserFrame = gWindow.document.createElement("iframe");
-  mozBrowserFrame.setAttribute("mozbrowser", "");
-  gWindow.document.body.appendChild(mozBrowserFrame);
-  is (mozBrowserFrame.contentWindow.top, mozBrowserFrame.contentWindow, "Mozbrowser top == iframe window");
-  is (mozBrowserFrame.contentWindow.parent, mozBrowserFrame.contentWindow, "Mozbrowser parent == iframe window");
+  yield ContentTask.spawn(browser, null, function() {
+    info("Checking mozbrowser iframe");
+    let mozBrowserFrame = content.document.createElement("iframe");
+    mozBrowserFrame.setAttribute("mozbrowser", "");
+    content.document.body.appendChild(mozBrowserFrame);
+    is (mozBrowserFrame.contentWindow.top, mozBrowserFrame.contentWindow,
+        "Mozbrowser top == iframe window");
+    is (mozBrowserFrame.contentWindow.parent, mozBrowserFrame.contentWindow,
+        "Mozbrowser parent == iframe window");
+  });
 
   info("Revoking special powers for mozbrowser");
   SpecialPowers.clearUserPref('dom.mozBrowserFramesEnabled')
-  SpecialPowers.removePermission("browser", gWindow.document);
-
-  finish();
+  SpecialPowers.removePermission("browser", TEST_URI);
 }
-
-function getWindowUtils(window)
-{
-  return window.
-    QueryInterface(Components.interfaces.nsIInterfaceRequestor).
-    getInterface(Components.interfaces.nsIDOMWindowUtils);
-}
--- a/dom/tests/mochitest/general/test_interfaces.html
+++ b/dom/tests/mochitest/general/test_interfaces.html
@@ -347,16 +347,18 @@ var interfaceNamesInGlobalScope =
     "CSSMozDocumentRule",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "CSSNameSpaceRule",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "CSSPageRule",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "CSSPrimitiveValue",
 // IMPORTANT: Do not change this list without review from a DOM peer!
+    {name: "CSSPseudoElement", release: false},
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "CSSRule",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "CSSRuleList",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "CSSStyleDeclaration",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "CSSStyleRule",
 // IMPORTANT: Do not change this list without review from a DOM peer!
new file mode 100644
--- /dev/null
+++ b/dom/webidl/CSSPseudoElement.webidl
@@ -0,0 +1,25 @@
+/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * The origin of this IDL file is
+ * https://drafts.csswg.org/css-pseudo/#CSSPseudoElement-interface
+ * https://drafts.csswg.org/cssom/#pseudoelement
+ *
+ * Copyright © 2015 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C
+ * liability, trademark and document use rules apply.
+ */
+
+// Both CSSOM and CSS Pseudo-Elements 4 provide contradictory definitions for
+// this interface.
+// What we implement here is a minimal subset of the two definitions which we
+// ship behind a pref until the specification issues have been resolved.
+[Func="nsDocument::IsWebAnimationsEnabled"]
+interface CSSPseudoElement {
+  readonly attribute DOMString type;
+  readonly attribute Element parentElement;
+};
+
+// https://w3c.github.io/web-animations/#extensions-to-the-pseudoelement-interface
+CSSPseudoElement implements Animatable;
--- a/dom/webidl/DummyBinding.webidl
+++ b/dom/webidl/DummyBinding.webidl
@@ -4,12 +4,13 @@
  * You can obtain one at http://mozilla.org/MPL/2.0/.
  */
 
 // Dummy bindings that we need to force generation of things that
 // aren't actually referenced anywhere in IDL yet but are used in C++.
 
 interface DummyInterface {
   void lifecycleCallbacks(optional LifecycleCallbacks arg);
+  void promiseJobCallback(PromiseJobCallback arg);
 };
 
 interface DummyInterfaceWorkers {
 };
--- a/dom/webidl/KeyframeEffect.webidl
+++ b/dom/webidl/KeyframeEffect.webidl
@@ -16,25 +16,28 @@ enum IterationCompositeOperation {
 };
 
 dictionary KeyframeEffectOptions : AnimationEffectTimingProperties {
   IterationCompositeOperation iterationComposite = "replace";
   CompositeOperation          composite = "replace";
   DOMString                   spacing = "distribute";
 };
 
-// For the constructor we use Element? for the first argument since we
-// don't support Animatable for pseudo-elements yet.
+// Bug 1241783: For the constructor we use (Element or CSSPseudoElement)? for
+// the first argument since we cannot convert a mixin into a union type
+// automatically.
 [HeaderFile="mozilla/dom/KeyframeEffect.h",
  Func="nsDocument::IsWebAnimationsEnabled",
- Constructor(Element? target,
+ Constructor((Element or CSSPseudoElement)? target,
              object? frames,
              optional (unrestricted double or KeyframeEffectOptions) options)]
 interface KeyframeEffectReadOnly : AnimationEffectReadOnly {
-  readonly attribute Element?  target;
+  // Bug 1241783: As with the constructor, we use (Element or CSSPseudoElement)?
+  // for the type of |target| instead of Animatable?
+  readonly attribute (Element or CSSPseudoElement)?  target;
   readonly attribute IterationCompositeOperation iterationComposite;
   readonly attribute CompositeOperation          composite;
   readonly attribute DOMString                   spacing;
 
   // Not yet implemented:
   // KeyframeEffect             clone();
 
   // We use object instead of ComputedKeyframe so that we can put the
--- a/dom/webidl/Promise.webidl
+++ b/dom/webidl/Promise.webidl
@@ -7,20 +7,25 @@
  * http://dom.spec.whatwg.org/#promises
  */
 
 // TODO We use object instead Function.  There is an open issue on WebIDL to
 // have different types for "platform-provided function" and "user-provided
 // function"; for now, we just use "object".
 callback PromiseInit = void (object resolve, object reject);
 
+callback PromiseJobCallback = void();
+
 [TreatNonCallableAsNull]
 callback AnyCallback = any (any value);
 
-// REMOVE THE RELEVANT ENTRY FROM test_interfaces.html WHEN THIS IS IMPLEMENTED IN JS.
+// When using SpiderMonkey promises, we don't want to define all this stuff;
+// just define a tiny interface to make codegen of Promise arguments and return
+// values work.
+#ifndef SPIDERMONKEY_PROMISE
 [Constructor(PromiseInit init),
  Exposed=(Window,Worker,System)]
 // Need to escape "Promise" so it's treated as an identifier.
 interface _Promise {
   // Have to use "any" (or "object", but "any" is simpler) as the type to
   // support the subclassing behavior, since nothing actually requires the
   // return value of PromiseSubclass.resolve/reject to be a Promise object.
   [NewObject, Throws]
@@ -51,8 +56,22 @@ interface _Promise {
   // Have to use "any" (or "object", but "any" is simpler) as the type to
   // support the subclassing behavior, since nothing actually requires the
   // return value of PromiseSubclass.race to be a Promise object.  As a result,
   // we also have to do our argument conversion manually, because we want to
   // convert its exceptions into rejections.
   [NewObject, Throws]
   static any race(optional any iterable);
 };
+#else // SPIDERMONKEY_PROMISE
+[NoInterfaceObject,
+ Exposed=(Window,Worker,System)]
+// Need to escape "Promise" so it's treated as an identifier.
+interface _Promise {
+};
+
+// Hack to allow us to have JS owning and properly tracing/CCing/etc a
+// PromiseNativeHandler.
+[NoInterfaceObject,
+ Exposed=(Window,Worker,System)]
+interface PromiseNativeHandler {
+};
+#endif // SPIDERMONKEY_PROMISE
--- a/dom/webidl/PromiseDebugging.webidl
+++ b/dom/webidl/PromiseDebugging.webidl
@@ -47,16 +47,17 @@ callback interface UncaughtRejectionObse
    * @param p A Promise that was previously left in uncaught state is
    * now caught, i.e. it is not the last in its chain anymore.
    */
   void onConsumed(Promise<any> p);
 };
 
 [ChromeOnly, Exposed=(Window,System)]
 interface PromiseDebugging {
+#ifndef SPIDERMONKEY_PROMISE
   /**
    * The various functions on this interface all expect to take promises but
    * don't want the WebIDL behavior of assimilating random passed-in objects
    * into promises.  They also want to treat Promise subclass instances as
    * promises instead of wrapping them in a vanilla Promise, which is what the
    * IDL spec says to do.  So we list all our arguments as "object" instead of
    * "Promise" and check for them being a Promise internally.
    */
@@ -125,16 +126,18 @@ interface PromiseDebugging {
   /*
    * Get the number of milliseconds elapsed between the promise being created
    * and being settled.  Throws NS_ERROR_UNEXPECTED if the promise has not
    * settled.
    */
   [Throws]
   static DOMHighResTimeStamp getTimeToSettle(object p);
 
+#endif // SPIDERMONKEY_PROMISE
+
   /**
    * Watching uncaught rejections on the current thread.
    *
    * Adding an observer twice will cause it to be notified twice
    * of events.
    */
   static void addUncaughtRejectionObserver(UncaughtRejectionObserver o);
   static boolean removeUncaughtRejectionObserver(UncaughtRejectionObserver o);
--- a/dom/webidl/moz.build
+++ b/dom/webidl/moz.build
@@ -6,16 +6,18 @@
 
 GENERATED_WEBIDL_FILES = [
     'CSS2Properties.webidl',
 ]
 
 PREPROCESSED_WEBIDL_FILES = [
     'HTMLMediaElement.webidl',
     'Navigator.webidl',
+    'Promise.webidl',
+    'PromiseDebugging.webidl',
     'ServiceWorkerRegistration.webidl',
     'Window.webidl',
 ]
 
 WEBIDL_FILES = [
     'AbstractWorker.webidl',
     'ActivityRequestHandler.webidl',
     'AlarmsManager.webidl',
@@ -92,16 +94,17 @@ WEBIDL_FILES = [
     'CreateOfferRequest.webidl',
     'Crypto.webidl',
     'CSPDictionaries.webidl',
     'CSPReport.webidl',
     'CSS.webidl',
     'CSSAnimation.webidl',
     'CSSLexer.webidl',
     'CSSPrimitiveValue.webidl',
+    'CSSPseudoElement.webidl',
     'CSSRuleList.webidl',
     'CSSStyleDeclaration.webidl',
     'CSSStyleSheet.webidl',
     'CSSTransition.webidl',
     'CSSValue.webidl',
     'CSSValueList.webidl',
     'DataContainerEvent.webidl',
     'DataStore.webidl',
@@ -384,18 +387,16 @@ WEBIDL_FILES = [
     'Presentation.webidl',
     'PresentationAvailability.webidl',
     'PresentationConnection.webidl',
     'PresentationDeviceInfoManager.webidl',
     'PresentationReceiver.webidl',
     'PresentationRequest.webidl',
     'ProcessingInstruction.webidl',
     'ProfileTimelineMarker.webidl',
-    'Promise.webidl',
-    'PromiseDebugging.webidl',
     'PropertyIndexedKeyframes.webidl',
     'RadioNodeList.webidl',
     'Range.webidl',
     'Rect.webidl',
     'Request.webidl',
     'RequestSyncManager.webidl',
     'RequestSyncScheduler.webidl',
     'ResourceStats.webidl',
--- a/dom/workers/ServiceWorkerManager.cpp
+++ b/dom/workers/ServiceWorkerManager.cpp
@@ -3228,16 +3228,28 @@ ServiceWorkerManager::RemoveScopeAndRegi
   }
 
   nsCOMPtr<nsITimer> timer = data->mUpdateTimers.Get(aRegistration->mScope);
   if (timer) {
     timer->Cancel();
     data->mUpdateTimers.Remove(aRegistration->mScope);
   }
 
+  // The registration should generally only be removed if there are no controlled
+  // documents, but mControlledDocuments can contain references to potentially
+  // controlled docs.  This happens when the service worker is not active yet.
+  // We must purge these references since we are evicting the registration.
+  for (auto iter = swm->mControlledDocuments.Iter(); !iter.Done(); iter.Next()) {
+    ServiceWorkerRegistrationInfo* reg = iter.UserData();
+    MOZ_ASSERT(reg);
+    if (reg->mScope.Equals(aRegistration->mScope)) {
+      iter.Remove();
+    }
+  }
+
   RefPtr<ServiceWorkerRegistrationInfo> info;
   data->mInfos.Get(aRegistration->mScope, getter_AddRefs(info));
 
   data->mInfos.Remove(aRegistration->mScope);
   data->mOrderedScopes.RemoveElement(aRegistration->mScope);
   swm->NotifyListenersOnUnregister(info);
 
   swm->MaybeRemoveRegistrationInfo(scopeKey);
--- a/dom/xul/XULDocument.cpp
+++ b/dom/xul/XULDocument.cpp
@@ -87,16 +87,17 @@
 #include "mozilla/dom/XULDocumentBinding.h"
 #include "mozilla/EventDispatcher.h"
 #include "mozilla/LoadInfo.h"
 #include "mozilla/Preferences.h"
 #include "nsTextNode.h"
 #include "nsJSUtils.h"
 #include "mozilla/dom/URL.h"
 #include "nsIContentPolicy.h"
+#include "mozAutoDocUpdate.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 //----------------------------------------------------------------------
 //
 // CIDs
 //
@@ -2962,20 +2963,24 @@ nsresult
 XULDocument::DoneWalking()
 {
     NS_PRECONDITION(mPendingSheets == 0, "there are sheets to be loaded");
     NS_PRECONDITION(!mStillWalking, "walk not done");
 
     // XXXldb This is where we should really be setting the chromehidden
     // attribute.
 
-    uint32_t count = mOverlaySheets.Length();
-    for (uint32_t i = 0; i < count; ++i) {
-        AddStyleSheet(mOverlaySheets[i]);
+    {
+        mozAutoDocUpdate updateBatch(this, UPDATE_STYLE, true);
+        uint32_t count = mOverlaySheets.Length();
+        for (uint32_t i = 0; i < count; ++i) {
+            AddStyleSheet(mOverlaySheets[i]);
+        }
     }
+
     mOverlaySheets.Clear();
 
     if (!mDocumentLoaded) {
         // Make sure we don't reenter here from StartLayout().  Note that
         // setting mDocumentLoaded to true here means that if StartLayout()
         // causes ResumeWalk() to be reentered, we'll take the other branch of
         // the |if (!mDocumentLoaded)| check above and since
         // mInitialLayoutComplete will be false will follow the else branch
--- a/editor/libeditor/tests/mochitest.ini
+++ b/editor/libeditor/tests/mochitest.ini
@@ -136,16 +136,17 @@ skip-if = toolkit == 'android'
 [test_bug787432.html]
 [test_bug790475.html]
 [test_bug795785.html]
 [test_bug796839.html]
 [test_bug832025.html]
 [test_bug857487.html]
 [test_bug858918.html]
 [test_bug915962.html]
+[test_bug974309.html]
 skip-if = toolkit == 'android'
 [test_bug966155.html]
 skip-if = os != "win"
 [test_bug966552.html]
 skip-if = os != "win"
 [test_bug998188.html]
 [test_bug1026397.html]
 [test_bug1067255.html]
new file mode 100644
--- /dev/null
+++ b/editor/libeditor/tests/test_bug974309.html
@@ -0,0 +1,78 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=974309
+-->
+<head>
+  <title>Test for Bug 974309</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+  <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=974309">Mozilla Bug 974309</a>
+<div id="edit_not_table_parent" contenteditable="true"></div>
+<div>
+  <table id="table" border="1" width="100%">
+    <tbody>
+      <tr>
+        <td>a</td>
+        <td>b</td>
+        <td>c</td>
+      </tr>
+      <tr>
+        <td>d</td>
+        <td id="cell">e</td>
+        <td>f</td>
+      </tr>
+      <tr>
+        <td>g</td>
+        <td>h</td>
+        <td>i</td>
+      </tr>
+    </tbody>
+  </table>
+</div>
+<script type="application/javascript">
+
+/**
+ * Test for Bug 974309
+ *
+ * Tests that editing a table row fails when the table or row is _not_ a child of a contenteditable node.
+ * See bug 857487 for tests that cover when the table or row _is_ a child of a contenteditable node.
+ */
+
+function getEditor() {
+  const Ci = SpecialPowers.Ci;
+  var editingSession = SpecialPowers.wrap(window)
+                                    .QueryInterface(Ci.nsIInterfaceRequestor)
+                                    .getInterface(Ci.nsIWebNavigation)
+                                    .QueryInterface(Ci.nsIInterfaceRequestor)
+                                    .getInterface(Ci.nsIEditingSession);
+  return editingSession.getEditorForWindow(window).QueryInterface(Ci.nsITableEditor);
+}
+
+var cell = document.getElementById("cell");
+cell.focus();
+
+// place caret at end of center cell
+var sel = getSelection();
+sel.collapse(cell, cell.childNodes.length);
+
+var table = document.getElementById("table");
+
+var tableHTML = table.innerHTML;
+
+var editor = getEditor();
+editor.deleteTableRow(1);
+
+is(table.innerHTML == tableHTML, true, "editor should not modify non-editable table" );
+
+isnot(table.innerHTML == "\n    <tbody>\n      <tr>\n        <td>a</td>\n        <td>b</td>\n        <td>c</td>\n      </tr>\n      \n      <tr>\n        <td>g</td>\n        <td>h</td>\n        <td>i</td>\n      </tr>\n    </tbody>\n  ",
+   true, "editor.deleteTableRow(1) should not delete a non-editable row containing the selection");
+
+</script>
+
+
+</body>
+</html>
--- a/gfx/2d/DrawTargetSkia.cpp
+++ b/gfx/2d/DrawTargetSkia.cpp
@@ -435,27 +435,22 @@ DrawTargetSkia::DrawSurfaceWithShadow(So
   SkAutoTUnref<SkImageFilter> blurFilter(SkBlurImageFilter::Create(aSigma, aSigma));
   SkAutoTUnref<SkColorFilter> colorFilter(
     SkColorFilter::CreateModeFilter(ColorToSkColor(aColor, 1.0), SkXfermode::kSrcIn_Mode));
 
   shadowPaint.setXfermode(paint.getXfermode());
   shadowPaint.setImageFilter(blurFilter.get());
   shadowPaint.setColorFilter(colorFilter.get());
 
-  // drawBitmap implicitly calls saveLayer with a src-over xfer mode if given
-  // an image filter, whereas the supplied xfer mode gets used to render into
-  // the layer, which is the wrong order. We instead must use drawSprite which
-  // applies the image filter directly to the bitmap without rendering it first,
-  // then uses the xfer mode to composite it.
   IntPoint shadowDest = RoundedToInt(aDest + aOffset);
-  mCanvas->drawSprite(bitmap, shadowDest.x, shadowDest.y, &shadowPaint);
+  mCanvas->drawBitmap(bitmap, shadowDest.x, shadowDest.y, &shadowPaint);
 
   // Composite the original image after the shadow
   IntPoint dest = RoundedToInt(aDest);
-  mCanvas->drawSprite(bitmap, dest.x, dest.y, &paint);
+  mCanvas->drawBitmap(bitmap, dest.x, dest.y, &paint);
 
   mCanvas->restore();
 }
 
 void
 DrawTargetSkia::FillRect(const Rect &aRect,
                          const Pattern &aPattern,
                          const DrawOptions &aOptions)
@@ -661,18 +656,18 @@ DrawTargetSkia::MaskSurface(const Patter
   if (bitmap.colorType() != kAlpha_8_SkColorType &&
       !bitmap.extractAlpha(&bitmap)) {
     gfxDebug() << *this << ": MaskSurface() failed to extract alpha for mask";
     return;
   }
 
   if (aOffset != Point(0, 0)) {
     SkMatrix transform;
-    transform.setTranslate(SkFloatToScalar(-aOffset.x), SkFloatToScalar(-aOffset.y));
-    SkShader* matrixShader = SkShader::CreateLocalMatrixShader(paint.mPaint.getShader(), transform);
+    transform.setTranslate(PointToSkPoint(-aOffset));
+    SkShader* matrixShader = paint.mPaint.getShader()->newWithLocalMatrix(transform);
     SkSafeUnref(paint.mPaint.setShader(matrixShader));
   }
 
   mCanvas->drawBitmap(bitmap, aOffset.x, aOffset.y, &paint.mPaint);
 }
 
 already_AddRefed<SourceSurface>
 DrawTargetSkia::CreateSourceSurfaceFromData(unsigned char *aData,
@@ -999,60 +994,74 @@ DrawTargetSkia::PushClipRect(const Rect&
 }
 
 void
 DrawTargetSkia::PopClip()
 {
   mCanvas->restore();
 }
 
+// Image filter that just passes the source through to the result unmodified.
+class CopyLayerImageFilter : public SkImageFilter
+{
+public:
+  CopyLayerImageFilter()
+    : SkImageFilter(0, nullptr)
+  {}
+
+  virtual bool onFilterImage(Proxy*, const SkBitmap& src, const Context&,
+                             SkBitmap* result, SkIPoint* offset) const override {
+    *result = src;
+    offset->set(0, 0);
+    return true;
+  }
+
+  SK_TO_STRING_OVERRIDE()
+  SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(CopyLayerImageFilter)
+};
+
+SkFlattenable*
+CopyLayerImageFilter::CreateProc(SkReadBuffer& buffer)
+{
+  SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 0);
+  return new CopyLayerImageFilter;
+}
+
+#ifndef SK_IGNORE_TO_STRING
+void
+CopyLayerImageFilter::toString(SkString* str) const
+{
+  str->append("CopyLayerImageFilter: ()");
+}
+#endif
+
 void
 DrawTargetSkia::PushLayer(bool aOpaque, Float aOpacity, SourceSurface* aMask,
                           const Matrix& aMaskTransform, const IntRect& aBounds,
                           bool aCopyBackground)
 {
   PushedLayer layer(GetPermitSubpixelAA(), aOpaque, aOpacity, aMask, aMaskTransform);
   mPushedLayers.push_back(layer);
 
   SkPaint paint;
 
   // If we have a mask, set the opacity to 0 so that SkCanvas::restore skips
   // implicitly drawing the layer so that we can properly mask it in PopLayer.
   paint.setAlpha(aMask ? 0 : ColorFloatToByte(aOpacity));
 
   SkRect bounds = IntRectToSkRect(aBounds);
-  SkRect* boundsPtr = aBounds.IsEmpty() ? nullptr : &bounds;
 
-  // TODO: Replace this with SaveLayerFlags when available in Skia update (m49+)
-  SkCanvas::SaveFlags saveFlags =
-    aOpaque ?
-      SkCanvas::SaveFlags(SkCanvas::kARGB_ClipLayer_SaveFlag & ~SkCanvas::kHasAlphaLayer_SaveFlag) :
-      SkCanvas::kARGB_ClipLayer_SaveFlag;
-
-  if (aCopyBackground) {
-    // Get a reference to the background before we save the layer.
-    SkAutoTUnref<SkBaseDevice> bgDevice(SkSafeRef(mCanvas->getTopDevice()));
-    SkIPoint bgOrigin = bgDevice->getOrigin();
-    SkBitmap bgBitmap = bgDevice->accessBitmap(false);
+  SkAutoTUnref<SkImageFilter> backdrop(aCopyBackground ? new CopyLayerImageFilter : nullptr);
 
-    mCanvas->saveLayer(boundsPtr, &paint, saveFlags);
-
-    // Draw the background into the layer.
-    SkPaint bgPaint;
-    if (!bgBitmap.isOpaque()) {
-      bgPaint.setXfermodeMode(SkXfermode::kSrc_Mode);
-    }
+  SkCanvas::SaveLayerRec saveRec(aBounds.IsEmpty() ? nullptr : &bounds,
+                                 &paint,
+                                 backdrop.get(),
+                                 aOpaque ? SkCanvas::kIsOpaque_SaveLayerFlag : 0);
 
-    mCanvas->save();
-    mCanvas->resetMatrix();
-    mCanvas->drawBitmap(bgBitmap, bgOrigin.x(), bgOrigin.y(), &bgPaint);
-    mCanvas->restore();
-  } else {
-    mCanvas->saveLayer(boundsPtr, &paint, saveFlags);
-  }
+  mCanvas->saveLayer(saveRec);
 
   SetPermitSubpixelAA(aOpaque);
 }
 
 void
 DrawTargetSkia::PopLayer()
 {
   MarkChanged();
--- a/gfx/2d/HelpersSkia.h
+++ b/gfx/2d/HelpersSkia.h
@@ -162,19 +162,19 @@ StrokeOptionsToPaint(SkPaint& aPaint, co
 
     std::vector<SkScalar> pattern;
     pattern.resize(dashCount);
 
     for (uint32_t i = 0; i < dashCount; i++) {
       pattern[i] = SkFloatToScalar(aOptions.mDashPattern[i % aOptions.mDashLength]);
     }
 
-    SkDashPathEffect* dash = SkDashPathEffect::Create(&pattern.front(),
-                                                      dashCount,
-                                                      SkFloatToScalar(aOptions.mDashOffset));
+    SkPathEffect* dash = SkDashPathEffect::Create(&pattern.front(),
+                                                  dashCount,
+                                                  SkFloatToScalar(aOptions.mDashOffset));
     SkSafeUnref(aPaint.setPathEffect(dash));
   }
 
   aPaint.setStyle(SkPaint::kStroke_Style);
   return true;
 }
 
 static inline SkXfermode::Mode
--- a/gfx/skia/generate_mozbuild.py
+++ b/gfx/skia/generate_mozbuild.py
@@ -32,17 +32,16 @@ FINAL_LIBRARY = 'gkmedias'
 LOCAL_INCLUDES += [
     'skia/include/c',
     'skia/include/config',
     'skia/include/core',
     'skia/include/effects',
     'skia/include/gpu',
     'skia/include/images',
     'skia/include/pathops',
-    'skia/include/pipe',
     'skia/include/ports',
     'skia/include/private',
     'skia/include/utils',
     'skia/include/utils/mac',
     'skia/include/utils/win',
     'skia/include/views',
     'skia/src/core',
     'skia/src/gpu',
--- a/gfx/skia/moz.build
+++ b/gfx/skia/moz.build
@@ -20,17 +20,16 @@ UNIFIED_SOURCES += [
     'skia/src/core/SkAlphaRuns.cpp',
     'skia/src/core/SkAnnotation.cpp',
     'skia/src/core/SkBBHFactory.cpp',
     'skia/src/core/SkBigPicture.cpp',
     'skia/src/core/SkBitmap.cpp',
     'skia/src/core/SkBitmapCache.cpp',
     'skia/src/core/SkBitmapController.cpp',
     'skia/src/core/SkBitmapDevice.cpp',
-    'skia/src/core/SkBitmapFilter.cpp',
     'skia/src/core/SkBitmapHeap.cpp',
     'skia/src/core/SkBitmapProcShader.cpp',
     'skia/src/core/SkBitmapProcState.cpp',
     'skia/src/core/SkBitmapProvider.cpp',
     'skia/src/core/SkBitmapScaler.cpp',
     'skia/src/core/SkBlitMask_D32.cpp',
     'skia/src/core/SkBlitRow_D16.cpp',
     'skia/src/core/SkBlitRow_D32.cpp',
@@ -38,16 +37,17 @@ UNIFIED_SOURCES += [
     'skia/src/core/SkBuffer.cpp',
     'skia/src/core/SkCachedData.cpp',
     'skia/src/core/SkCanvas.cpp',
     'skia/src/core/SkChecksum.cpp',
     'skia/src/core/SkChunkAlloc.cpp',
     'skia/src/core/SkClipStack.cpp',
     'skia/src/core/SkColor.cpp',
     'skia/src/core/SkColorFilter.cpp',
+    'skia/src/core/SkColorFilterShader.cpp',
     'skia/src/core/SkColorTable.cpp',
     'skia/src/core/SkComposeShader.cpp',
     'skia/src/core/SkConfig8888.cpp',
     'skia/src/core/SkConvolver.cpp',
     'skia/src/core/SkCubicClipper.cpp',
     'skia/src/core/SkData.cpp',
     'skia/src/core/SkDataTable.cpp',
     'skia/src/core/SkDebug.cpp',
@@ -60,27 +60,27 @@ UNIFIED_SOURCES += [
     'skia/src/core/SkDraw.cpp',
     'skia/src/core/SkDrawable.cpp',
     'skia/src/core/SkDrawLooper.cpp',
     'skia/src/core/SkEdge.cpp',
     'skia/src/core/SkEdgeBuilder.cpp',
     'skia/src/core/SkEdgeClipper.cpp',
     'skia/src/core/SkError.cpp',
     'skia/src/core/SkFilterProc.cpp',
-    'skia/src/core/SkFilterShader.cpp',
     'skia/src/core/SkFlattenable.cpp',
     'skia/src/core/SkFlattenableSerialization.cpp',
     'skia/src/core/SkFloatBits.cpp',
     'skia/src/core/SkFont.cpp',
     'skia/src/core/SkFontDescriptor.cpp',
     'skia/src/core/SkFontMgr.cpp',
     'skia/src/core/SkFontStream.cpp',
     'skia/src/core/SkFontStyle.cpp',
     'skia/src/core/SkForceCPlusPlusLinking.cpp',
     'skia/src/core/SkGeometry.cpp',
+    'skia/src/core/SkGlobalInitialization_core.cpp',
     'skia/src/core/SkGlyphCache.cpp',
     'skia/src/core/SkGraphics.cpp',
     'skia/src/core/SkHalf.cpp',
     'skia/src/core/SkImageCacherator.cpp',
     'skia/src/core/SkImageFilter.cpp',
     'skia/src/core/SkImageGenerator.cpp',
     'skia/src/core/SkImageInfo.cpp',
     'skia/src/core/SkLightingShader.cpp',
@@ -93,16 +93,17 @@ UNIFIED_SOURCES += [
     'skia/src/core/SkMaskFilter.cpp',
     'skia/src/core/SkMaskGamma.cpp',
     'skia/src/core/SkMath.cpp',
     'skia/src/core/SkMatrix.cpp',
     'skia/src/core/SkMatrixImageFilter.cpp',
     'skia/src/core/SkMetaData.cpp',
     'skia/src/core/SkMiniRecorder.cpp',
     'skia/src/core/SkMipMap.cpp',
+    'skia/src/core/SkModeColorFilter.cpp',
     'skia/src/core/SkMultiPictureDraw.cpp',
     'skia/src/core/SkNinePatchIter.cpp',
     'skia/src/core/SkPackBits.cpp',
     'skia/src/core/SkPaint.cpp',
     'skia/src/core/SkPaintPriv.cpp',
     'skia/src/core/SkPath.cpp',
     'skia/src/core/SkPathEffect.cpp',
     'skia/src/core/SkPathMeasure.cpp',
@@ -188,17 +189,16 @@ UNIFIED_SOURCES += [
     'skia/src/effects/SkArcToPathEffect.cpp',
     'skia/src/effects/SkArithmeticMode.cpp',
     'skia/src/effects/SkBlurDrawLooper.cpp',
     'skia/src/effects/SkBlurImageFilter.cpp',
     'skia/src/effects/SkBlurMask.cpp',
     'skia/src/effects/SkBlurMaskFilter.cpp',
     'skia/src/effects/SkColorCubeFilter.cpp',
     'skia/src/effects/SkColorFilterImageFilter.cpp',
-    'skia/src/effects/SkColorFilters.cpp',
     'skia/src/effects/SkColorMatrix.cpp',
     'skia/src/effects/SkColorMatrixFilter.cpp',
     'skia/src/effects/SkComposeImageFilter.cpp',
     'skia/src/effects/SkCornerPathEffect.cpp',
     'skia/src/effects/SkDashPathEffect.cpp',
     'skia/src/effects/SkDiscretePathEffect.cpp',
     'skia/src/effects/SkDisplacementMapEffect.cpp',
     'skia/src/effects/SkDropShadowImageFilter.cpp',
@@ -211,20 +211,20 @@ UNIFIED_SOURCES += [
     'skia/src/effects/SkLightingImageFilter.cpp',
     'skia/src/effects/SkLumaColorFilter.cpp',
     'skia/src/effects/SkMagnifierImageFilter.cpp',
     'skia/src/effects/SkMatrixConvolutionImageFilter.cpp',
     'skia/src/effects/SkMergeImageFilter.cpp',
     'skia/src/effects/SkMorphologyImageFilter.cpp',
     'skia/src/effects/SkOffsetImageFilter.cpp',
     'skia/src/effects/SkPaintFlagsDrawFilter.cpp',
+    'skia/src/effects/SkPaintImageFilter.cpp',
     'skia/src/effects/SkPerlinNoiseShader.cpp',
     'skia/src/effects/SkPictureImageFilter.cpp',
     'skia/src/effects/SkPixelXorXfermode.cpp',
-    'skia/src/effects/SkRectShaderImageFilter.cpp',
     'skia/src/effects/SkTableColorFilter.cpp',
     'skia/src/effects/SkTableMaskFilter.cpp',
     'skia/src/effects/SkTestImageFilters.cpp',
     'skia/src/effects/SkTileImageFilter.cpp',
     'skia/src/effects/SkXfermodeImageFilter.cpp',
     'skia/src/fonts/SkFontMgr_indirect.cpp',
     'skia/src/fonts/SkGScalerContext.cpp',
     'skia/src/fonts/SkRandomScalerContext.cpp',
@@ -268,36 +268,32 @@ UNIFIED_SOURCES += [
     'skia/src/pathops/SkPathOpsRect.cpp',
     'skia/src/pathops/SkPathOpsSimplify.cpp',
     'skia/src/pathops/SkPathOpsTightBounds.cpp',
     'skia/src/pathops/SkPathOpsTSect.cpp',
     'skia/src/pathops/SkPathOpsTypes.cpp',
     'skia/src/pathops/SkPathOpsWinding.cpp',
     'skia/src/pathops/SkPathWriter.cpp',
     'skia/src/pathops/SkReduceOrder.cpp',
-    'skia/src/pipe/SkGPipeRead.cpp',
-    'skia/src/pipe/SkGPipeWrite.cpp',
     'skia/src/ports/SkDiscardableMemory_none.cpp',
     'skia/src/ports/SkGlobalInitialization_default.cpp',
     'skia/src/ports/SkImageDecoder_empty.cpp',
     'skia/src/ports/SkImageGenerator_skia.cpp',
     'skia/src/ports/SkMemory_mozalloc.cpp',
+    'skia/src/ports/SkOSEnvironment.cpp',
     'skia/src/ports/SkOSFile_stdio.cpp',
     'skia/src/sfnt/SkOTTable_name.cpp',
     'skia/src/sfnt/SkOTUtils.cpp',
-    'skia/src/utils/android/SkAndroidSDKCanvas.cpp',
     'skia/src/utils/SkBase64.cpp',
     'skia/src/utils/SkBitmapSourceDeserializer.cpp',
     'skia/src/utils/SkBitSet.cpp',
     'skia/src/utils/SkBoundaryPatch.cpp',
     'skia/src/utils/SkCamera.cpp',
     'skia/src/utils/SkCanvasStack.cpp',
     'skia/src/utils/SkCanvasStateUtils.cpp',
-    'skia/src/utils/SkCubicInterval.cpp',
-    'skia/src/utils/SkCullPoints.cpp',
     'skia/src/utils/SkDashPath.cpp',
     'skia/src/utils/SkDumpCanvas.cpp',
     'skia/src/utils/SkEventTracer.cpp',
     'skia/src/utils/SkFrontBufferedStream.cpp',
     'skia/src/utils/SkImageGeneratorUtils.cpp',
     'skia/src/utils/SkInterpolator.cpp',
     'skia/src/utils/SkLayer.cpp',
     'skia/src/utils/SkMatrix22.cpp',
@@ -386,33 +382,30 @@ if CONFIG['MOZ_ENABLE_SKIA_GPU']:
         'skia/src/gpu/gl/debug/GrFrameBufferObj.cpp',
         'skia/src/gpu/gl/debug/GrProgramObj.cpp',
         'skia/src/gpu/gl/debug/GrShaderObj.cpp',
         'skia/src/gpu/gl/debug/GrTextureObj.cpp',
         'skia/src/gpu/gl/debug/GrTextureUnitObj.cpp',
         'skia/src/gpu/gl/debug/SkDebugGLContext.cpp',
         'skia/src/gpu/gl/SkGLContext.cpp',
         'skia/src/gpu/gl/SkNullGLContext.cpp',
-        'skia/src/gpu/GrAtlasTextBlob.cpp',
-        'skia/src/gpu/GrAtlasTextContext.cpp',
+        'skia/src/gpu/GrAuditTrail.cpp',
         'skia/src/gpu/GrBatchFlushState.cpp',
-        'skia/src/gpu/GrBatchFontCache.cpp',
         'skia/src/gpu/GrBatchTest.cpp',
         'skia/src/gpu/GrBlend.cpp',
         'skia/src/gpu/GrBlurUtils.cpp',
         'skia/src/gpu/GrBufferAllocPool.cpp',
         'skia/src/gpu/GrCaps.cpp',
         'skia/src/gpu/GrClip.cpp',
         'skia/src/gpu/GrClipMaskManager.cpp',
         'skia/src/gpu/GrContext.cpp',
         'skia/src/gpu/GrCoordTransform.cpp',
         'skia/src/gpu/GrDefaultGeoProcFactory.cpp',
         'skia/src/gpu/GrDrawingManager.cpp',
         'skia/src/gpu/GrDrawTarget.cpp',
-        'skia/src/gpu/GrFontScaler.cpp',
         'skia/src/gpu/GrFragmentProcessor.cpp',
         'skia/src/gpu/GrGpu.cpp',
         'skia/src/gpu/GrGpuFactory.cpp',
         'skia/src/gpu/GrGpuResource.cpp',
         'skia/src/gpu/GrGpuResourceRef.cpp',
         'skia/src/gpu/GrImageIDTextureAdjuster.cpp',
         'skia/src/gpu/GrInvariantOutput.cpp',
         'skia/src/gpu/GrLayerAtlas.cpp',
@@ -438,36 +431,43 @@ if CONFIG['MOZ_ENABLE_SKIA_GPU']:
         'skia/src/gpu/GrRecordReplaceDraw.cpp',
         'skia/src/gpu/GrRectanizer_pow2.cpp',
         'skia/src/gpu/GrRectanizer_skyline.cpp',
         'skia/src/gpu/GrReducedClip.cpp',
         'skia/src/gpu/GrRenderTarget.cpp',
         'skia/src/gpu/GrResourceProvider.cpp',
         'skia/src/gpu/GrSoftwarePathRenderer.cpp',
         'skia/src/gpu/GrStencil.cpp',
-        'skia/src/gpu/GrStencilAndCoverTextContext.cpp',
         'skia/src/gpu/GrStencilAttachment.cpp',
         'skia/src/gpu/GrStrokeInfo.cpp',
         'skia/src/gpu/GrSurface.cpp',
         'skia/src/gpu/GrSWMaskHelper.cpp',
+        'skia/src/gpu/GrTessellator.cpp',
         'skia/src/gpu/GrTestUtils.cpp',
-        'skia/src/gpu/GrTextBlobCache.cpp',
-        'skia/src/gpu/GrTextContext.cpp',
         'skia/src/gpu/GrTexture.cpp',
         'skia/src/gpu/GrTextureAccess.cpp',
         'skia/src/gpu/GrTextureParamsAdjuster.cpp',
         'skia/src/gpu/GrTextureProvider.cpp',
         'skia/src/gpu/GrTraceMarker.cpp',
         'skia/src/gpu/GrXferProcessor.cpp',
         'skia/src/gpu/GrYUVProvider.cpp',
         'skia/src/gpu/SkGpuDevice.cpp',
         'skia/src/gpu/SkGpuDevice_drawTexture.cpp',
         'skia/src/gpu/SkGr.cpp',
         'skia/src/gpu/SkGrPixelRef.cpp',
         'skia/src/gpu/SkGrTexturePixelRef.cpp',
+        'skia/src/gpu/text/GrAtlasTextBlob.cpp',
+        'skia/src/gpu/text/GrAtlasTextContext.cpp',
+        'skia/src/gpu/text/GrBatchFontCache.cpp',
+        'skia/src/gpu/text/GrDistanceFieldAdjustTable.cpp',
+        'skia/src/gpu/text/GrFontScaler.cpp',
+        'skia/src/gpu/text/GrStencilAndCoverTextContext.cpp',
+        'skia/src/gpu/text/GrTextBlobCache.cpp',
+        'skia/src/gpu/text/GrTextContext.cpp',
+        'skia/src/gpu/text/GrTextUtils.cpp',
         'skia/src/image/SkSurface_Gpu.cpp',
     ]
     SOURCES += [
         'skia/src/effects/SkArithmeticMode_gpu.cpp',
         'skia/src/gpu/batches/GrAAConvexPathRenderer.cpp',
         'skia/src/gpu/batches/GrAAConvexTessellator.cpp',
         'skia/src/gpu/batches/GrAADistanceFieldPathRenderer.cpp',
         'skia/src/gpu/batches/GrAAFillRectBatch.cpp',
@@ -485,28 +485,29 @@ if CONFIG['MOZ_ENABLE_SKIA_GPU']:
         'skia/src/gpu/gl/GrGLCreateNullInterface.cpp',
         'skia/src/gpu/gl/GrGLDefaultInterface_native.cpp',
         'skia/src/gpu/gl/GrGLExtensions.cpp',
         'skia/src/gpu/gl/GrGLGLSL.cpp',
         'skia/src/gpu/gl/GrGLGpu.cpp',
         'skia/src/gpu/gl/GrGLGpuProgramCache.cpp',
         'skia/src/gpu/gl/GrGLIndexBuffer.cpp',
         'skia/src/gpu/gl/GrGLInterface.cpp',
-        'skia/src/gpu/gl/GrGLNameAllocator.cpp',
         'skia/src/gpu/gl/GrGLNoOpInterface.cpp',
         'skia/src/gpu/gl/GrGLPath.cpp',
         'skia/src/gpu/gl/GrGLPathRange.cpp',
         'skia/src/gpu/gl/GrGLPathRendering.cpp',
         'skia/src/gpu/gl/GrGLProgram.cpp',
         'skia/src/gpu/gl/GrGLProgramDataManager.cpp',
         'skia/src/gpu/gl/GrGLProgramDesc.cpp',
         'skia/src/gpu/gl/GrGLRenderTarget.cpp',
         'skia/src/gpu/gl/GrGLStencilAttachment.cpp',
         'skia/src/gpu/gl/GrGLTexture.cpp',
         'skia/src/gpu/gl/GrGLTextureRenderTarget.cpp',
+        'skia/src/gpu/gl/GrGLTransferBuffer.cpp',
+        'skia/src/gpu/gl/GrGLUniformHandler.cpp',
         'skia/src/gpu/gl/GrGLUtil.cpp',
         'skia/src/gpu/gl/GrGLVaryingHandler.cpp',
         'skia/src/gpu/gl/GrGLVertexArray.cpp',
         'skia/src/gpu/gl/GrGLVertexBuffer.cpp',
         'skia/src/gpu/glsl/GrGLSL.cpp',
         'skia/src/gpu/glsl/GrGLSLBlend.cpp',
         'skia/src/gpu/glsl/GrGLSLCaps.cpp',
         'skia/src/gpu/glsl/GrGLSLFragmentProcessor.cpp',
@@ -649,17 +650,16 @@ FINAL_LIBRARY = 'gkmedias'
 LOCAL_INCLUDES += [
     'skia/include/c',
     'skia/include/config',
     'skia/include/core',
     'skia/include/effects',
     'skia/include/gpu',
     'skia/include/images',
     'skia/include/pathops',
-    'skia/include/pipe',
     'skia/include/ports',
     'skia/include/private',
     'skia/include/utils',
     'skia/include/utils/mac',
     'skia/include/utils/win',
     'skia/include/views',
     'skia/src/core',
     'skia/src/gpu',
--- a/gfx/skia/skia/include/codec/SkAndroidCodec.h
+++ b/gfx/skia/skia/include/codec/SkAndroidCodec.h
@@ -45,17 +45,35 @@ public:
     virtual ~SkAndroidCodec() {}
 
 
     const SkImageInfo& getInfo() const { return fInfo; }
 
     /**
      *  Format of the encoded data.
      */
-    SkEncodedFormat getEncodedFormat() const { return this->onGetEncodedFormat(); }
+    SkEncodedFormat getEncodedFormat() const { return fCodec->getEncodedFormat(); }
+
+    /**
+     *  @param requestedColorType Color type requested by the client
+     *
+     *  If it is possible to decode to requestedColorType, this returns
+     *  requestedColorType.  Otherwise, this returns whichever color type
+     *  is suggested by the codec as the best match for the encoded data.
+     */
+    SkColorType computeOutputColorType(SkColorType requestedColorType);
+
+    /**
+     *  @param requestedUnpremul  Indicates if the client requested
+     *                            unpremultiplied output
+     *
+     *  Returns the appropriate alpha type to decode to.  If the image
+     *  has alpha, the value of requestedUnpremul will be honored.
+     */
+    SkAlphaType computeOutputAlphaType(bool requestedUnpremul);
 
     /**
      *  Returns the dimensions of the scaled output image, for an input
      *  sampleSize.
      *
      *  When the sample size divides evenly into the original dimensions, the
      *  scaled output dimensions will simply be equal to the original
      *  dimensions divided by the sample size.
@@ -205,26 +223,28 @@ public:
      *
      *  This will return an error if the info is kIndex_8_SkColorType and also will not perform
      *  any scaling or subsetting.
      */
     SkCodec::Result getAndroidPixels(const SkImageInfo& info, void* pixels, size_t rowBytes);
 
 protected:
 
-    SkAndroidCodec(const SkImageInfo&);
+    SkAndroidCodec(SkCodec*);
 
-    virtual SkEncodedFormat onGetEncodedFormat() const = 0;
+    SkCodec* codec() const { return fCodec.get(); }
 
     virtual SkISize onGetSampledDimensions(int sampleSize) const = 0;
 
     virtual bool onGetSupportedSubset(SkIRect* desiredSubset) const = 0;
 
     virtual SkCodec::Result onGetAndroidPixels(const SkImageInfo& info, void* pixels,
             size_t rowBytes, const AndroidOptions& options) = 0;
 
 private:
 
     // This will always be a reference to the info that is contained by the
     // embedded SkCodec.
     const SkImageInfo& fInfo;
+
+    SkAutoTDelete<SkCodec> fCodec;
 };
 #endif // SkAndroidCodec_DEFINED
--- a/gfx/skia/skia/include/codec/SkCodec.h
+++ b/gfx/skia/skia/include/codec/SkCodec.h
@@ -21,19 +21,44 @@ class SkPngChunkReader;
 class SkSampler;
 
 /**
  *  Abstraction layer directly on top of an image codec.
  */
 class SkCodec : SkNoncopyable {
 public:
     /**
+     *  Minimum number of bytes that must be buffered in SkStream input.
+     *
+     *  An SkStream passed to NewFromStream must be able to use this many
+     *  bytes to determine the image type. Then the same SkStream must be
+     *  passed to the correct decoder to read from the beginning.
+     *
+     *  This can be accomplished by implementing peek() to support peeking
+     *  this many bytes, or by implementing rewind() to be able to rewind()
+     *  after reading this many bytes.
+     */
+    static size_t MinBufferedBytesNeeded();
+
+    /**
      *  If this stream represents an encoded image that we know how to decode,
      *  return an SkCodec that can decode it. Otherwise return NULL.
      *
+     *  As stated above, this call must be able to peek or read
+     *  MinBufferedBytesNeeded to determine the correct format, and then start
+     *  reading from the beginning. First it will attempt to peek, and it
+     *  assumes that if less than MinBufferedBytesNeeded bytes (but more than
+     *  zero) are returned, this is because the stream is shorter than this,
+     *  so falling back to reading would not provide more data. If peek()
+     *  returns zero bytes, this call will instead attempt to read(). This
+     *  will require that the stream can be rewind()ed.
+     *
+     *  If SkPngChunkReader is not NULL, take a ref and pass it to libpng if
+     *  the image is a png.
+     *
      *  If the SkPngChunkReader is not NULL then:
      *      If the image is not a PNG, the SkPngChunkReader will be ignored.
      *      If the image is a PNG, the SkPngChunkReader will be reffed.
      *      If the PNG has unknown chunks, the SkPngChunkReader will be used
      *      to handle these chunks.  SkPngChunkReader will be called to read
      *      any unknown chunk at any point during the creation of the codec
      *      or the decode.  Note that if SkPngChunkReader fails to read a
      *      chunk, this could result in a failure to create the codec or a
@@ -248,28 +273,16 @@ public:
 
     /**
      *  Simplified version of getPixels() that asserts that info is NOT kIndex8_SkColorType and
      *  uses the default Options.
      */
     Result getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes);
 
     /**
-     *  Some images may initially report that they have alpha due to the format
-     *  of the encoded data, but then never use any colors which have alpha
-     *  less than 100%. This function can be called *after* decoding to
-     *  determine if such an image truly had alpha. Calling it before decoding
-     *  is undefined.
-     *  FIXME: see skbug.com/3582.
-     */
-    bool reallyHasAlpha() const {
-        return this->onReallyHasAlpha();
-    }
-
-    /**
      * The remaining functions revolve around decoding scanlines.
      */
 
     /**
      *  Prepare for a scanline decode with the specified options.
      *
      *  After this call, this class will be ready to decode the first scanline.
      *
@@ -395,34 +408,36 @@ public:
          * Interlaced pngs are an example.
          */
         kNone_SkScanlineOrder,
     };
 
     /**
      *  An enum representing the order in which scanlines will be returned by
      *  the scanline decoder.
+     *
+     *  This is undefined before startScanlineDecode() is called.
      */
     SkScanlineOrder getScanlineOrder() const { return this->onGetScanlineOrder(); }
 
     /**
      *  Returns the y-coordinate of the next row to be returned by the scanline
      *  decoder.
      *
      *  This will equal fCurrScanline, except in the case of strangely
      *  encoded image types (bottom-up bmps, interlaced gifs).
      *
      *  Results are undefined when not in scanline decoding mode.
      */
     int nextScanline() const { return this->outputScanline(fCurrScanline); }
 
     /**
-     * Returns the output y-coordinate of the row that corresponds to an input
-     * y-coordinate.  The input y-coordinate represents where the scanline
-     * is located in the encoded data.
+     *  Returns the output y-coordinate of the row that corresponds to an input
+     *  y-coordinate.  The input y-coordinate represents where the scanline
+     *  is located in the encoded data.
      *
      *  This will equal inputScanline, except in the case of strangely
      *  encoded image types (bottom-up bmps, interlaced gifs).
      */
     int outputScanline(int inputScanline) const;
 
 protected:
     SkCodec(const SkImageInfo&, SkStream*);
@@ -454,18 +469,16 @@ protected:
                                SkPMColor ctable[], int* ctableCount,
                                int* rowsDecoded) = 0;
 
     virtual bool onGetValidSubset(SkIRect* /* desiredSubset */) const {
         // By default, subsets are not supported.
         return false;
     }
 
-    virtual bool onReallyHasAlpha() const { return false; }
-
     /**
      *  If the stream was previously read, attempt to rewind.
      *
      *  If the stream needed to be rewound, call onRewind.
      *  @returns true if the codec is at the right position and can be used.
      *      false if there was a failure to rewind.
      *
      *  This is called by getPixels() and start(). Subclasses may call if they
@@ -524,24 +537,32 @@ protected:
      */
 
     /**
      *  Most images types will be kTopDown and will not need to override this function.
      */
     virtual SkScanlineOrder onGetScanlineOrder() const { return kTopDown_SkScanlineOrder; }
 
     /**
-     *  Update the next scanline. Used by interlaced png.
+     *  Update the current scanline. Used by interlaced png.
      */
-    void updateNextScanline(int newY) { fCurrScanline = newY; }
+    void updateCurrScanline(int newY) { fCurrScanline = newY; }
 
     const SkImageInfo& dstInfo() const { return fDstInfo; }
 
     const SkCodec::Options& options() const { return fOptions; }
 
+    /**
+     *  Returns the number of scanlines that have been decoded so far.
+     *  This is unaffected by the SkScanlineOrder.
+     *
+     *  Returns -1 if we have not started a scanline decode.
+     */
+    int currScanline() const { return fCurrScanline; }
+
     virtual int onOutputScanline(int inputScanline) const;
 
 private:
     const SkImageInfo       fSrcInfo;
     SkAutoTDelete<SkStream> fStream;
     bool                    fNeedsRewind;
     // These fields are only meaningful during scanline decodes.
     SkImageInfo             fDstInfo;
@@ -605,10 +626,11 @@ private:
      *  May create a sampler, if one is not currently being used. Otherwise, does
      *  not affect ownership.
      *
      *  Only valid during scanline decoding.
      */
     virtual SkSampler* getSampler(bool /*createIfNecessary*/) { return nullptr; }
 
     friend class SkSampledCodec;
+    friend class SkIcoCodec;
 };
 #endif // SkCodec_DEFINED
--- a/gfx/skia/skia/include/core/SkBitmap.h
+++ b/gfx/skia/skia/include/core/SkBitmap.h
@@ -49,22 +49,34 @@ public:
      *  Copy the settings from the src into this bitmap. If the src has pixels
      *  allocated, they will be shared, not copied, so that the two bitmaps will
      *  reference the same memory for the pixels. If a deep copy is needed,
      *  where the new bitmap has its own separate copy of the pixels, use
      *  deepCopyTo().
      */
     SkBitmap(const SkBitmap& src);
 
+    /**
+     *  Copy the settings from the src into this bitmap. If the src has pixels
+     *  allocated, ownership of the pixels will be taken.
+     */
+    SkBitmap(SkBitmap&& src);
+
     ~SkBitmap();
 
-    /** Copies the src bitmap into this bitmap. Ownership of the src bitmap's pixels remains
-        with the src bitmap.
+    /** Copies the src bitmap into this bitmap. Ownership of the src
+        bitmap's pixels is shared with the src bitmap.
     */
     SkBitmap& operator=(const SkBitmap& src);
+
+    /** Copies the src bitmap into this bitmap. Takes ownership of the src
+        bitmap's pixels.
+    */
+    SkBitmap& operator=(SkBitmap&& src);
+
     /** Swap the fields of the two bitmaps. This routine is guaranteed to never fail or throw.
     */
     //  This method is not exported to java.
     void swap(SkBitmap& other);
 
     ///////////////////////////////////////////////////////////////////////////
 
     const SkImageInfo& info() const { return fInfo; }
@@ -290,16 +302,24 @@ public:
      *  caller must ensure that the specified pixels are valid for the lifetime
      *  of the created bitmap (and its pixelRef).
      */
     bool installPixels(const SkImageInfo& info, void* pixels, size_t rowBytes) {
         return this->installPixels(info, pixels, rowBytes, NULL, NULL, NULL);
     }
 
     /**
+     *  Call installPixels with no ReleaseProc specified. This means
+     *  that the caller must ensure that the specified pixels and
+     *  colortable are valid for the lifetime of the created bitmap
+     *  (and its pixelRef).
+     */
+    bool installPixels(const SkPixmap&);
+
+    /**
      *  Calls installPixels() with the value in the SkMask. The caller must
      *  ensure that the specified mask pixels are valid for the lifetime
      *  of the created bitmap (and its pixelRef).
      */
     bool installMaskPixels(const SkMask&);
 
     /** Use this to assign a new pixel address for an existing bitmap. This
         will automatically release any pixelref previously installed. Only call
--- a/gfx/skia/skia/include/core/SkCanvas.h
+++ b/gfx/skia/skia/include/core/SkCanvas.h
@@ -32,32 +32,46 @@ class SkPath;
 class SkPicture;
 class SkPixmap;
 class SkRRect;
 struct SkRSXform;
 class SkSurface;
 class SkSurface_Base;
 class SkTextBlob;
 
+/*
+ *  If you want the legacy cliptolayer flag (i.e. android), then you must have the new
+ *  legacy saveflags.
+ */
+#ifdef SK_SUPPORT_LEGACY_CLIPTOLAYERFLAG
+#ifndef SK_SUPPORT_LEGACY_SAVEFLAGS
+    #define SK_SUPPORT_LEGACY_SAVEFLAGS
+#endif
+#endif
+
 /** \class SkCanvas
 
     A Canvas encapsulates all of the state about drawing into a device (bitmap).
     This includes a reference to the device itself, and a stack of matrix/clip
     values. For any given draw call (e.g. drawRect), the geometry of the object
     being drawn is transformed by the concatenation of all the matrices in the
     stack. The transformed geometry is clipped by the intersection of all of
     the clips in the stack.
 
     While the Canvas holds the state of the drawing device, the state (style)
     of the object being drawn is held by the Paint, which is provided as a
     parameter to each of the draw() methods. The Paint holds attributes such as
     color, typeface, textSize, strokeWidth, shader (e.g. gradients, patterns),
     etc.
 */
 class SK_API SkCanvas : public SkRefCnt {
+    enum PrivateSaveLayerFlags {
+        kDontClipToLayer_PrivateSaveLayerFlag   = 1 << 31,
+    };
+    
 public:
     /**
      *  Attempt to allocate raster canvas, matching the ImageInfo, that will draw directly into the
      *  specified pixels. To access the pixels after drawing to them, the caller should call
      *  flush() or call peekPixels(...).
      *
      *  On failure, return NULL. This can fail for several reasons:
      *  1. invalid ImageInfo (e.g. negative dimensions)
@@ -276,16 +290,17 @@ public:
     /**
      *  Helper for calling writePixels(info, ...) by passing its pixels and rowbytes. If the bitmap
      *  is just wrapping a texture, returns false and does nothing.
      */
     bool writePixels(const SkBitmap& bitmap, int x, int y);
 
     ///////////////////////////////////////////////////////////////////////////
 
+#ifdef SK_SUPPORT_LEGACY_SAVEFLAGS
     enum SaveFlags {
         /** save the matrix state, restoring it on restore() */
         // [deprecated] kMatrix_SaveFlag            = 0x01,
         kMatrix_SaveFlag            = 0x01,
         /** save the clip state, restoring it on restore() */
         // [deprecated] kClip_SaveFlag              = 0x02,
         kClip_SaveFlag              = 0x02,
         /** the layer needs to support per-pixel alpha */
@@ -302,16 +317,17 @@ public:
         // helper masks for common choices
         // [deprecated] kMatrixClip_SaveFlag        = 0x03,
         kMatrixClip_SaveFlag        = 0x03,
 #ifdef SK_SUPPORT_LEGACY_CLIPTOLAYERFLAG
         kARGB_NoClipLayer_SaveFlag  = 0x0F,
 #endif
         kARGB_ClipLayer_SaveFlag    = 0x1F
     };
+#endif
 
     /** This call saves the current matrix, clip, and drawFilter, and pushes a
         copy onto a private stack. Subsequent calls to translate, scale,
         rotate, skew, concat or clipRect, clipPath, and setDrawFilter all
         operate on this copy.
         When the balancing call to restore() is made, the previous matrix, clip,
         and drawFilter are restored.
 
@@ -331,16 +347,24 @@ public:
                      offscreen when restore() is called
         @return The value to pass to restoreToCount() to balance this save()
     */
     int saveLayer(const SkRect* bounds, const SkPaint* paint);
     int saveLayer(const SkRect& bounds, const SkPaint* paint) {
         return this->saveLayer(&bounds, paint);
     }
 
+    /**
+     *  Temporary name.
+     *  Will allow any requests for LCD text to be respected, so the caller must be careful to
+     *  only draw on top of opaque sections of the layer to get good results.
+     */
+    int saveLayerPreserveLCDTextRequests(const SkRect* bounds, const SkPaint* paint);
+
+#ifdef SK_SUPPORT_LEGACY_SAVEFLAGS
     /** DEPRECATED - use saveLayer(const SkRect*, const SkPaint*) instead.
 
         This behaves the same as saveLayer(const SkRect*, const SkPaint*),
         but it allows fine-grained control of which state bits to be saved
         (and subsequently restored).
 
         @param bounds (may be null) This rect, if non-null, is used as a hint to
                       limit the size of the offscreen, and thus drawing may be
@@ -348,46 +372,85 @@ public:
                       happen. If exact clipping is desired, use clipRect().
         @param paint (may be null) This is copied, and is applied to the
                      offscreen when restore() is called
         @param flags  LayerFlags
         @return The value to pass to restoreToCount() to balance this save()
     */
     SK_ATTR_EXTERNALLY_DEPRECATED("SaveFlags use is deprecated")
     int saveLayer(const SkRect* bounds, const SkPaint* paint, SaveFlags flags);
+#endif
 
     /** This behaves the same as save(), but in addition it allocates an
         offscreen bitmap. All drawing calls are directed there, and only when
         the balancing call to restore() is made is that offscreen transfered to
         the canvas (or the previous layer).
         @param bounds (may be null) This rect, if non-null, is used as a hint to
                       limit the size of the offscreen, and thus drawing may be
                       clipped to it, though that clipping is not guaranteed to
                       happen. If exact clipping is desired, use clipRect().
         @param alpha  This is applied to the offscreen when restore() is called.
         @return The value to pass to restoreToCount() to balance this save()
     */
     int saveLayerAlpha(const SkRect* bounds, U8CPU alpha);
 
+#ifdef SK_SUPPORT_LEGACY_SAVEFLAGS
     /** DEPRECATED - use saveLayerAlpha(const SkRect*, U8CPU) instead.
 
         This behaves the same as saveLayerAlpha(const SkRect*, U8CPU),
         but it allows fine-grained control of which state bits to be saved
         (and subsequently restored).
 
         @param bounds (may be null) This rect, if non-null, is used as a hint to
                       limit the size of the offscreen, and thus drawing may be
                       clipped to it, though that clipping is not guaranteed to
                       happen. If exact clipping is desired, use clipRect().
         @param alpha  This is applied to the offscreen when restore() is called.
         @param flags  LayerFlags
         @return The value to pass to restoreToCount() to balance this save()
     */
     SK_ATTR_EXTERNALLY_DEPRECATED("SaveFlags use is deprecated")
     int saveLayerAlpha(const SkRect* bounds, U8CPU alpha, SaveFlags flags);
+#endif
+
+    enum {
+        kIsOpaque_SaveLayerFlag         = 1 << 0,
+        kPreserveLCDText_SaveLayerFlag  = 1 << 1,
+
+#ifdef SK_SUPPORT_LEGACY_CLIPTOLAYERFLAG
+        kDontClipToLayer_Legacy_SaveLayerFlag = kDontClipToLayer_PrivateSaveLayerFlag,
+#endif
+    };
+    typedef uint32_t SaveLayerFlags;
+
+    struct SaveLayerRec {
+        SaveLayerRec()
+            : fBounds(nullptr), fPaint(nullptr), fBackdrop(nullptr), fSaveLayerFlags(0)
+        {}
+        SaveLayerRec(const SkRect* bounds, const SkPaint* paint, SaveLayerFlags saveLayerFlags = 0)
+            : fBounds(bounds)
+            , fPaint(paint)
+            , fBackdrop(nullptr)
+            , fSaveLayerFlags(saveLayerFlags)
+        {}
+        SaveLayerRec(const SkRect* bounds, const SkPaint* paint, const SkImageFilter* backdrop,
+                     SaveLayerFlags saveLayerFlags)
+            : fBounds(bounds)
+            , fPaint(paint)
+            , fBackdrop(backdrop)
+            , fSaveLayerFlags(saveLayerFlags)
+        {}
+
+        const SkRect*           fBounds;    // optional
+        const SkPaint*          fPaint;     // optional
+        const SkImageFilter*    fBackdrop;  // optional
+        SaveLayerFlags          fSaveLayerFlags;
+    };
+
+    int saveLayer(const SaveLayerRec&);
 
     /** This call balances a previous call to save(), and is used to remove all
         modifications to the matrix/clip/drawFilter state since the last save
         call.
         It is an error to call restore() more times than save() was called.
     */
     void restore();
 
@@ -601,28 +664,28 @@ public:
     void clear(SkColor color) {
         this->drawColor(color, SkXfermode::kSrc_Mode);
     }
 
     /**
      * This makes the contents of the canvas undefined. Subsequent calls that
      * require reading the canvas contents will produce undefined results. Examples
      * include blending and readPixels. The actual implementation is backend-
-     * dependent and one legal implementation is to do nothing. Like clear(), this
-     * ignores the clip.
+     * dependent and one legal implementation is to do nothing. This method
+     * ignores the current clip.
      *
      * This function should only be called if the caller intends to subsequently
      * draw to the canvas. The canvas may do real work at discard() time in order
      * to optimize performance on subsequent draws. Thus, if you call this and then
      * never draw to the canvas subsequently you may pay a perfomance penalty.
      */
     void discard() { this->onDiscard(); }
 
     /**
-     *  Fill the entire canvas' bitmap (restricted to the current clip) with the
+     *  Fill the entire canvas (restricted to the current clip) with the
      *  specified paint.
      *  @param paint    The paint used to fill the canvas
      */
     void drawPaint(const SkPaint& paint);
 
     enum PointMode {
         /** drawPoints draws each point separately */
         kPoints_PointMode,
@@ -899,29 +962,16 @@ public:
      *  - The center is stretched in both axes.
      * Else, for each axis where dst < bitmap,
      *  - The corners shrink proportionally
      *  - The sides (along the shrink axis) and center are not drawn
      */
     void drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst,
                         const SkPaint* paint = NULL);
 
-    /** Draw the specified bitmap, with its top/left corner at (x,y),
-        NOT transformed by the current matrix. Note: if the paint
-        contains a maskfilter that generates a mask which extends beyond the
-        bitmap's original width/height, then the bitmap will be drawn as if it
-        were in a Shader with CLAMP mode. Thus the color outside of the original
-        width/height will be the edge color replicated.
-        @param bitmap   The bitmap to be drawn
-        @param left     The position of the left side of the bitmap being drawn
-        @param top      The position of the top side of the bitmap being drawn
-        @param paint    The paint used to draw the bitmap, or NULL
-    */
-    void drawSprite(const SkBitmap& bitmap, int left, int top, const SkPaint* paint = NULL);
-
     /** Draw the text, with origin at (x,y), using the specified paint.
         The origin is interpreted based on the Align setting in the paint.
         @param text The text to be drawn
         @param byteLength   The number of bytes to read from the text parameter
         @param x        The x-coordinate of the origin of the text being drawn
         @param y        The y-coordinate of the origin of the text being drawn
         @param paint    The paint used for the text (e.g. color, size, style)
     */
@@ -1218,24 +1268,25 @@ protected:
     virtual SkSurface* onNewSurface(const SkImageInfo&, const SkSurfaceProps&);
 
     // default impl defers to its device
     virtual bool onPeekPixels(SkPixmap*);
     virtual bool onAccessTopLayerPixels(SkPixmap*);
 
     // Subclass save/restore notifiers.
     // Overriders should call the corresponding INHERITED method up the inheritance chain.
-    // willSaveLayer()'s return value may suppress full layer allocation.
+    // getSaveLayerStrategy()'s return value may suppress full layer allocation.
     enum SaveLayerStrategy {
         kFullLayer_SaveLayerStrategy,
-        kNoLayer_SaveLayerStrategy
+        kNoLayer_SaveLayerStrategy,
     };
 
     virtual void willSave() {}
-    virtual SaveLayerStrategy willSaveLayer(const SkRect*, const SkPaint*, SaveFlags) {
+    // Overriders should call the corresponding INHERITED method up the inheritance chain.
+    virtual SaveLayerStrategy getSaveLayerStrategy(const SaveLayerRec&) {
         return kFullLayer_SaveLayerStrategy;
     }
     virtual void willRestore() {}
     virtual void didRestore() {}
     virtual void didConcat(const SkMatrix&) {}
     virtual void didSetMatrix(const SkMatrix&) {}
 
     virtual void onDrawDRRect(const SkRRect&, const SkRRect&, const SkPaint&);
@@ -1280,17 +1331,16 @@ protected:
     virtual void onDrawImageNine(const SkImage*, const SkIRect& center, const SkRect& dst,
                                  const SkPaint*);
 
     virtual void onDrawBitmap(const SkBitmap&, SkScalar dx, SkScalar dy, const SkPaint*);
     virtual void onDrawBitmapRect(const SkBitmap&, const SkRect*, const SkRect&, const SkPaint*,
                                   SrcRectConstraint);
     virtual void onDrawBitmapNine(const SkBitmap&, const SkIRect& center, const SkRect& dst,
                                   const SkPaint*);
-    virtual void onDrawSprite(const SkBitmap&, int left, int top, const SkPaint*);
 
     enum ClipEdgeStyle {
         kHard_ClipEdgeStyle,
         kSoft_ClipEdgeStyle
     };
 
     virtual void onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyle edgeStyle);
     virtual void onClipRRect(const SkRRect& rrect, SkRegion::Op op, ClipEdgeStyle edgeStyle);
@@ -1306,21 +1356,31 @@ protected:
     // need to overload this method. The impl must keep track of this, as it
     // is not released or deleted by the caller.
     virtual SkCanvas* canvasForDrawIter();
 
     // Clip rectangle bounds. Called internally by saveLayer.
     // returns false if the entire rectangle is entirely clipped out
     // If non-NULL, The imageFilter parameter will be used to expand the clip
     // and offscreen bounds for any margin required by the filter DAG.
-    bool clipRectBounds(const SkRect* bounds, SaveFlags flags,
-                        SkIRect* intersection,
+    bool clipRectBounds(const SkRect* bounds, SaveLayerFlags, SkIRect* intersection,
                         const SkImageFilter* imageFilter = NULL);
 
+#ifdef SK_SUPPORT_LEGACY_SAVEFLAGS
+    // Needed by SkiaCanvasProxy in Android. Make sure that class is updated
+    // before removing this method.
+    static uint32_t SaveLayerFlagsToSaveFlags(SaveLayerFlags);
+#endif
 private:
+    static bool BoundsAffectsClip(SaveLayerFlags);
+#ifdef SK_SUPPORT_LEGACY_SAVEFLAGS
+    static uint32_t SaveFlagsToSaveLayerFlags(SaveFlags);
+#endif
+    static SaveLayerFlags LegacySaveFlagsToSaveLayerFlags(uint32_t legacySaveFlags);
+
     enum ShaderOverrideOpacity {
         kNone_ShaderOverrideOpacity,        //!< there is no overriding shader (bitmap or image)
         kOpaque_ShaderOverrideOpacity,      //!< the overriding shader is opaque
         kNotOpaque_ShaderOverrideOpacity,   //!< the overriding shader may not be opaque
     };
 
     // notify our surface (if we have one) that we are about to draw, so it
     // can perform copy-on-write or invalidate any cached images
@@ -1370,16 +1430,17 @@ private:
     friend class AutoDrawLooper;
     friend class SkLua;             // needs top layer size and offset
     friend class SkDebugCanvas;     // needs experimental fAllowSimplifyClip
     friend class SkSurface_Raster;  // needs getDevice()
     friend class SkRecorder;        // InitFlags
     friend class SkNoSaveLayerCanvas;   // InitFlags
     friend class SkPictureImageFilter;  // SkCanvas(SkBaseDevice*, SkSurfaceProps*, InitFlags)
     friend class SkPictureRecord;   // predrawNotify (why does it need it? <reed>)
+    friend class SkPicturePlayback; // SaveFlagsToSaveLayerFlags
 
     enum InitFlags {
         kDefault_InitFlags                  = 0,
         kConservativeRasterClip_InitFlag    = 1 << 0,
     };
     SkCanvas(const SkIRect& bounds, InitFlags);
     SkCanvas(SkBaseDevice* device, InitFlags);
 
@@ -1401,17 +1462,17 @@ private:
      */
     SkISize getTopLayerSize() const;
     SkIPoint getTopLayerOrigin() const;
 
     void internalDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src,
                                 const SkRect& dst, const SkPaint* paint,
                                 SrcRectConstraint);
     void internalDrawPaint(const SkPaint& paint);
-    void internalSaveLayer(const SkRect* bounds, const SkPaint*, SaveFlags, SaveLayerStrategy);
+    void internalSaveLayer(const SaveLayerRec&, SaveLayerStrategy);
     void internalDrawDevice(SkBaseDevice*, int x, int y, const SkPaint*, bool isBitmapDevice);
 
     // shared by save() and saveLayer()
     void internalSave();
     void internalRestore();
     static void DrawRect(const SkDraw& draw, const SkPaint& paint,
                          const SkRect& r, SkScalar textSize);
     static void DrawTextDecorations(const SkDraw& draw, const SkPaint& paint,
@@ -1423,16 +1484,20 @@ private:
 
     /*
      *  Returns true if drawing the specified rect (or all if it is null) with the specified
      *  paint (or default if null) would overwrite the entire root device of the canvas
      *  (i.e. the canvas' surface if it had one).
      */
     bool wouldOverwriteEntireSurface(const SkRect*, const SkPaint*, ShaderOverrideOpacity) const;
 
+    /**
+     *  Returns true if the paint's imagefilter can be invoked directly, without needed a layer.
+     */
+    bool canDrawBitmapAsSprite(SkScalar x, SkScalar y, int w, int h, const SkPaint&);
 
     /*  These maintain a cache of the clip bounds in local coordinates,
         (converted to 2s-compliment if floats are slow).
      */
     mutable SkRect fCachedLocalClipBounds;
     mutable bool   fCachedLocalClipBoundsDirty;
     bool fAllowSoftClip;
     bool fAllowSimplifyClip;
@@ -1500,69 +1565,28 @@ public:
     }
 
 private:
     SkCanvas*   fCanvas;
     int         fSaveCount;
 };
 #define SkAutoCanvasRestore(...) SK_REQUIRE_LOCAL_VAR(SkAutoCanvasRestore)
 
-/**
- *  If the caller wants read-only access to the pixels in a canvas, it can just
- *  call canvas->peekPixels(), since that is the fastest way to "peek" at the
- *  pixels on a raster-backed canvas.
- *
- *  If the canvas has pixels, but they are not readily available to the CPU
- *  (e.g. gpu-backed), then peekPixels() will fail, but readPixels() will
- *  succeed (though be slower, since it will return a copy of the pixels).
- *
- *  SkAutoROCanvasPixels encapsulates these two techniques, trying first to call
- *  peekPixels() (for performance), but if that fails, calling readPixels() and
- *  storing the copy locally.
- *
- *  The caller must respect the restrictions associated with peekPixels(), since
- *  that may have been called: The returned information is invalidated if...
- *      - any API is called on the canvas (or its parent surface if present)
- *      - the canvas goes out of scope
- */
-class SkAutoROCanvasPixels : SkNoncopyable {
-public:
-    SkAutoROCanvasPixels(SkCanvas* canvas);
-
-    // returns NULL on failure
-    const void* addr() const { return fAddr; }
-
-    // undefined if addr() == NULL
-    size_t rowBytes() const { return fRowBytes; }
-
-    // undefined if addr() == NULL
-    const SkImageInfo& info() const { return fInfo; }
-
-    // helper that, if returns true, installs the pixels into the bitmap. Note
-    // that the bitmap may reference the address returned by peekPixels(), so
-    // the caller must respect the restrictions associated with peekPixels().
-    bool asROBitmap(SkBitmap*) const;
-
-private:
-    SkBitmap    fBitmap;    // used if peekPixels() fails
-    const void* fAddr;      // NULL on failure
-    SkImageInfo fInfo;
-    size_t      fRowBytes;
-};
-
+#ifdef SK_SUPPORT_LEGACY_SAVEFLAGS
 static inline SkCanvas::SaveFlags operator|(const SkCanvas::SaveFlags lhs,
                                             const SkCanvas::SaveFlags rhs) {
     return static_cast<SkCanvas::SaveFlags>(static_cast<int>(lhs) | static_cast<int>(rhs));
 }
 
 static inline SkCanvas::SaveFlags& operator|=(SkCanvas::SaveFlags& lhs,
                                               const SkCanvas::SaveFlags rhs) {
     lhs = lhs | rhs;
     return lhs;
 }
+#endif
 
 class SkCanvasClipVisitor {
 public:
     virtual ~SkCanvasClipVisitor();
     virtual void clipRect(const SkRect&, SkRegion::Op, bool antialias) = 0;
     virtual void clipRRect(const SkRRect&, SkRegion::Op, bool antialias) = 0;
     virtual void clipPath(const SkPath&, SkRegion::Op, bool antialias) = 0;
 };
--- a/gfx/skia/skia/include/core/SkColorFilter.h
+++ b/gfx/skia/skia/include/core/SkColorFilter.h
@@ -101,23 +101,16 @@ public:
         @param c    The source color used with the specified mode
         @param mode The xfermode mode that is applied to each color in
                         the colorfilter's filterSpan[16,32] methods
         @return colorfilter object that applies the src color and mode,
                     or NULL if the mode will have no effect.
     */
     static SkColorFilter* CreateModeFilter(SkColor c, SkXfermode::Mode mode);
 
-    /** Create a colorfilter that multiplies the RGB channels by one color, and
-        then adds a second color, pinning the result for each component to
-        [0..255]. The alpha components of the mul and add arguments
-        are ignored.
-    */
-    static SkColorFilter* CreateLightingFilter(SkColor mul, SkColor add);
-
     /** Construct a colorfilter whose effect is to first apply the inner filter and then apply
      *  the outer filter to the result of the inner's.
      *  The reference counts for outer and inner are incremented.
      *
      *  Due to internal limits, it is possible that this will return NULL, so the caller must
      *  always check.
      */
     static SkColorFilter* CreateComposeFilter(SkColorFilter* outer, SkColorFilter* inner);
--- a/gfx/skia/skia/include/core/SkDevice.h
+++ b/gfx/skia/skia/include/core/SkDevice.h
@@ -328,26 +328,36 @@ protected:
      *  perform its own rendering pass. It is acceptable for the backend
      *  to perform some device-specific warm up tasks and then let SkCanvas
      *  perform the main rendering loop (by return false from here).
      */
     virtual bool EXPERIMENTAL_drawPicture(SkCanvas*, const SkPicture*, const SkMatrix*,
                                           const SkPaint*);
 
     struct CreateInfo {
-        static SkPixelGeometry AdjustGeometry(const SkImageInfo&, TileUsage, SkPixelGeometry);
+        static SkPixelGeometry AdjustGeometry(const SkImageInfo&, TileUsage, SkPixelGeometry,
+                                              bool preserveLCDText);
 
         // The constructor may change the pixel geometry based on other parameters.
         CreateInfo(const SkImageInfo& info,
                    TileUsage tileUsage,
-                   SkPixelGeometry geo,
-                   bool forImageFilter = false)
+                   SkPixelGeometry geo)
             : fInfo(info)
             , fTileUsage(tileUsage)
-            , fPixelGeometry(AdjustGeometry(info, tileUsage, geo))
+            , fPixelGeometry(AdjustGeometry(info, tileUsage, geo, false))
+            , fForImageFilter(false) {}
+
+        CreateInfo(const SkImageInfo& info,
+                   TileUsage tileUsage,
+                   SkPixelGeometry geo,
+                   bool preserveLCDText,
+                   bool forImageFilter)
+            : fInfo(info)
+            , fTileUsage(tileUsage)
+            , fPixelGeometry(AdjustGeometry(info, tileUsage, geo, preserveLCDText))
             , fForImageFilter(forImageFilter) {}
 
         const SkImageInfo       fInfo;
         const TileUsage         fTileUsage;
         const SkPixelGeometry   fPixelGeometry;
         const bool              fForImageFilter;
     };
 
@@ -369,18 +379,22 @@ protected:
 private:
     friend class SkCanvas;
     friend struct DeviceCM; //for setMatrixClip
     friend class SkDraw;
     friend class SkDrawIter;
     friend class SkDeviceFilteredPaint;
     friend class SkImageFilter::DeviceProxy;
     friend class SkNoPixelsBitmapDevice;
+    friend class SkSurface_Raster;
 
-    friend class SkSurface_Raster;
+    /**
+     *  Calls through to drawSprite, processing imagefilter as needed.
+     */
+    void drawBitmapAsSprite(const SkDraw&, const SkBitmap&, int x, int y, const SkPaint&);
 
     // used to change the backend's pixels (and possibly config/rowbytes)
     // but cannot change the width/height, so there should be no change to
     // any clip information.
     // TODO: move to SkBitmapDevice
     virtual void replaceBitmapBackendForRasterSurface(const SkBitmap&) {}
 
     virtual bool forceConservativeRasterClip() const { return false; }
--- a/gfx/skia/skia/include/core/SkDocument.h
+++ b/gfx/skia/skia/include/core/SkDocument.h
@@ -11,16 +11,17 @@
 #include "SkBitmap.h"
 #include "SkPicture.h"
 #include "SkRect.h"
 #include "SkRefCnt.h"
 #include "SkString.h"
 #include "SkTime.h"
 
 class SkCanvas;
+class SkPixelSerializer;
 class SkWStream;
 
 /** SK_ScalarDefaultDPI is 72 DPI.
 */
 #define SK_ScalarDefaultRasterDPI           72.0f
 
 /**
  *  High-level API for creating a document-based canvas. To use..
@@ -53,16 +54,34 @@ public:
      *         or sent online or to printer.
      *  @returns NULL if there is an error, otherwise a newly created
      *           PDF-backed SkDocument.
      */
     static SkDocument* CreatePDF(SkWStream*,
                                  SkScalar dpi = SK_ScalarDefaultRasterDPI);
 
     /**
+     *  @param jpegEncoder For PDF documents, if a jpegEncoder is set,
+     *         use it to encode SkImages and SkBitmaps as [JFIF]JPEGs.
+     *         This feature is deprecated and is only supplied for
+     *         backwards compatability.
+     *
+     *         The prefered method to create PDFs with JPEG images is
+     *         to use SkImage::NewFromEncoded() and not jpegEncoder.
+     *         Chromium uses NewFromEncoded.
+     *
+     *         If the encoder is unset, or if jpegEncoder->onEncode()
+     *         returns NULL, fall back on encoding images losslessly
+     *         with Deflate.
+     */
+    static SkDocument* CreatePDF(SkWStream*,
+                                 SkScalar dpi,
+                                 SkPixelSerializer* jpegEncoder);
+
+    /**
      *  Create a PDF-backed document, writing the results into a file.
      */
     static SkDocument* CreatePDF(const char outputFilePath[],
                                  SkScalar dpi = SK_ScalarDefaultRasterDPI);
 
     /**
      *  Create a XPS-backed document, writing the results into the stream.
      *  Returns NULL if XPS is not supported.
--- a/gfx/skia/skia/include/core/SkDrawFilter.h
+++ b/gfx/skia/skia/include/core/SkDrawFilter.h
@@ -11,16 +11,18 @@
 #define SkDrawFilter_DEFINED
 
 #include "SkRefCnt.h"
 
 class SkCanvas;
 class SkPaint;
 
 /**
+ *  DEPRECATED - use SkPaintFilterCanvas instead.
+ *
  *  Right before something is being draw, filter() is called with the
  *  paint. The filter may modify the paint as it wishes, which will then be
  *  used for the actual drawing. Note: this modification only lasts for the
  *  current draw, as a temporary copy of the paint is used.
  */
 class SK_API SkDrawFilter : public SkRefCnt {
 public:
     enum Type {
--- a/gfx/skia/skia/include/core/SkFixed.h
+++ b/gfx/skia/skia/include/core/SkFixed.h
@@ -81,19 +81,19 @@ typedef int32_t             SkFixed;
 
 #define SkFixedAbs(x)       SkAbs32(x)
 #define SkFixedAve(a, b)    (((a) + (b)) >> 1)
 
 // Blink layout tests are baselined to Clang optimizing through undefined behavior in SkDivBits.
 #if defined(SK_SUPPORT_LEGACY_DIVBITS_UB)
     #define SkFixedDiv(numer, denom) SkDivBits(numer, denom, 16)
 #else
-    // TODO(reed): this clamp shouldn't be needed.  Use SkToS32().
+    // The divide may exceed 32 bits. Clamp to a signed 32 bit result.
     #define SkFixedDiv(numer, denom) \
-        SkTPin<int32_t>(((int64_t)numer << 16) / denom, SK_MinS32, SK_MaxS32)
+        SkToS32(SkTPin<int64_t>((SkLeftShift((int64_t)numer, 16) / denom), SK_MinS32, SK_MaxS32))
 #endif
 
 //////////////////////////////////////////////////////////////////////////////////////////////////////
 // Now look for ASM overrides for our portable versions (should consider putting this in its own file)
 
 inline SkFixed SkFixedMul_longlong(SkFixed a, SkFixed b) {
     return (SkFixed)((int64_t)a * b >> 16);
 }
@@ -140,19 +140,19 @@ inline SkFixed SkFixedMul_longlong(SkFix
     #undef SkFloatToFixed
     #define SkFloatToFixed(x)  SkFloatToFixed_arm(x)
 #endif
 
 ///////////////////////////////////////////////////////////////////////////////
 
 typedef int64_t SkFixed3232;   // 32.32
 
-#define SkIntToFixed3232(x)       ((SkFixed3232)(x) << 32)
+#define SkIntToFixed3232(x)       (SkLeftShift((SkFixed3232)(x), 32))
 #define SkFixed3232ToInt(x)       ((int)((x) >> 32))
-#define SkFixedToFixed3232(x)     ((SkFixed3232)(x) << 16)
+#define SkFixedToFixed3232(x)     (SkLeftShift((SkFixed3232)(x), 16))
 #define SkFixed3232ToFixed(x)     ((SkFixed)((x) >> 16))
 #define SkFloatToFixed3232(x)     ((SkFixed3232)((x) * (65536.0f * 65536.0f)))
 
 #define SkScalarToFixed3232(x)    SkFloatToFixed3232(x)
 
 ///////////////////////////////////////////////////////////////////////////////
 
 // 64bits wide, with a 16bit bias. Useful when accumulating lots of 16.16 so
--- a/gfx/skia/skia/include/core/SkFlattenable.h
+++ b/gfx/skia/skia/include/core/SkFlattenable.h
@@ -44,17 +44,17 @@ class SkPrivateEffectInitializer;
 
 #define SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(flattenable) \
     SkFlattenable::Register(#flattenable, flattenable::CreateProc, \
                             flattenable::GetFlattenableType());
 
 #define SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(flattenable)    \
     private:                                                                \
     static SkFlattenable* CreateProc(SkReadBuffer&);                        \
-    friend class ::SkPrivateEffectInitializer;                              \
+    friend class SkFlattenable::PrivateInitializer;                         \
     public:                                                                 \
     Factory getFactory() const override { return CreateProc; }
 
 /** For SkFlattenable derived objects with a valid type
     This macro should only be used in base class objects in core
   */
 #define SK_DEFINE_FLATTENABLE_TYPE(flattenable) \
     static Type GetFlattenableType() { \
@@ -103,16 +103,23 @@ public:
     static void Register(const char name[], Factory, Type);
 
     /**
      *  Override this if your subclass needs to record data that it will need to recreate itself
      *  from its CreateProc (returned by getFactory()).
      */
     virtual void flatten(SkWriteBuffer&) const {}
 
+protected:
+    class PrivateInitializer {
+    public:
+        static void InitCore();
+        static void InitEffects();
+    };
+
 private:
     static void InitializeFlattenablesIfNeeded();
 
     friend class SkGraphics;
 
     typedef SkRefCnt INHERITED;
 };
 
--- a/gfx/skia/skia/include/core/SkImage.h
+++ b/gfx/skia/skia/include/core/SkImage.h
@@ -262,17 +262,17 @@ public:
      */
     SkData* encode(SkImageEncoder::Type, int quality) const;
 
     /**
      *  Encode the image and return the result as a caller-managed SkData.  This will
      *  attempt to reuse existing encoded data (as returned by refEncoded).
      *
      *  We defer to the SkPixelSerializer both for vetting existing encoded data
-     *  (useEncodedData) and for encoding the image (encodePixels) when no such data is
+     *  (useEncodedData) and for encoding the image (encode) when no such data is
      *  present or is rejected by the serializer.
      *
      *  If not specified, we use a default serializer which 1) always accepts existing data
      *  (in any format) and 2) encodes to PNG.
      *
      *  If no compatible encoded data exists and encoding fails, this method will also
      *  fail (return NULL).
      */
@@ -319,38 +319,16 @@ public:
     bool asLegacyBitmap(SkBitmap*, LegacyBitmapMode) const;
     
     /**
      *  Returns true if the image is backed by an image-generator or other src that creates
      *  (and caches) its pixels / texture on-demand.
      */
     bool isLazyGenerated() const;
 
-    /**
-     *  Apply the specified filter to this image, and return the result as a new image.
-     *
-     *  if forceResultToOriginalSize is true, then the resulting image will be the same size as the
-     *  src, regardless of the normal output of the filter.
-     *
-     *  If offset is non-null, it is set to the relative offset needed to draw the resulting image
-     *  in the same logical place as the original.
-     *
-     *  e.g.
-     *      If the filter makes the result larger by a margin of 4 the output would be:
-     *          result->width()  == this->width + 8
-     *          result->height() == this->height + 8
-     *          offset.x()       == -4
-     *          offset.y()       == -4
-     *
-     *  If the filter fails to create a resulting image, null is returned, and the offset parameter
-     *  (if specified) will be undefined.
-     */
-    SkImage* applyFilter(SkImageFilter* filter, SkIPoint* offset,
-                         bool forceResultToOriginalSize) const;
-
 protected:
     SkImage(int width, int height, uint32_t uniqueID);
 
 private:
     const int       fWidth;
     const int       fHeight;
     const uint32_t  fUniqueID;
 
--- a/gfx/skia/skia/include/core/SkImageDecoder.h
+++ b/gfx/skia/skia/include/core/SkImageDecoder.h
@@ -11,18 +11,16 @@
 #include "SkBitmap.h"
 #include "SkImage.h"
 #include "SkPngChunkReader.h"
 #include "SkRect.h"
 #include "SkRefCnt.h"
 #include "SkTRegistry.h"
 #include "SkTypes.h"
 
-//#define SK_LEGACY_PEEKER
-
 class SkStream;
 class SkStreamRewindable;
 
 /** \class SkImageDecoder
 
     Base class for decoding compressed images into a SkBitmap
 */
 class SkImageDecoder : SkNoncopyable {
@@ -124,28 +122,16 @@ public:
         fRequireUnpremultipliedColors = request;
     }
 
     /** Returns true if the decoder will only return bitmaps with unpremultiplied
         colors.
     */
     bool getRequireUnpremultipliedColors() const { return fRequireUnpremultipliedColors; }
 
-#ifdef SK_LEGACY_PEEKER
-    // Android subclasses SkImageDecoder::Peeker, which has been changed into SkPngChunkReader.
-    // Temporarily use this class until Android can be updated to directly inherit from
-    // SkPngChunkReader.
-    class Peeker : public SkPngChunkReader {
-    public:
-        bool readChunk(const char tag[], const void* data, size_t length) final {
-            return this->peek(tag, data, length);
-        }
-        virtual bool peek(const char tag[], const void* data, size_t length) = 0;
-    };
-#endif
     SkPngChunkReader* getPeeker() const { return fPeeker; }
     SkPngChunkReader* setPeeker(SkPngChunkReader*);
 
     /**
      *  By default, the codec will try to comply with the "pref" colortype
      *  that is passed to decode() or decodeSubset(). However, this can be called
      *  to override that, causing the codec to try to match the src depth instead
      *  (as shown below).
--- a/gfx/skia/skia/include/core/SkImageEncoder.h
+++ b/gfx/skia/skia/include/core/SkImageEncoder.h
@@ -7,16 +7,18 @@
 
 #ifndef SkImageEncoder_DEFINED
 #define SkImageEncoder_DEFINED
 
 #include "SkImageInfo.h"
 #include "SkTRegistry.h"
 
 class SkBitmap;
+class SkPixelSerializer;
+class SkPixmap;
 class SkData;
 class SkWStream;
 
 class SkImageEncoder {
 public:
     // TODO (scroggo): Merge with SkEncodedFormat.
     enum Type {
         kUnknown_Type,
@@ -59,21 +61,27 @@ public:
      * range 0-100). Returns false on failure.
      */
     bool encodeStream(SkWStream* stream, const SkBitmap& bm, int quality);
 
     static SkData* EncodeData(const SkImageInfo&, const void* pixels, size_t rowBytes,
                               Type, int quality);
     static SkData* EncodeData(const SkBitmap&, Type, int quality);
 
+    static SkData* EncodeData(const SkPixmap&, Type, int quality);
+
     static bool EncodeFile(const char file[], const SkBitmap&, Type,
                            int quality);
     static bool EncodeStream(SkWStream*, const SkBitmap&, Type,
                            int quality);
 
+    /** Uses SkImageEncoder to serialize images that are not already
+        encoded as SkImageEncoder::kPNG_Type images. */
+    static SkPixelSerializer* CreatePixelSerializer();
+
 protected:
     /**
      * Encode bitmap 'bm' in the desired format, writing results to
      * stream 'stream', at quality level 'quality' (which can be in
      * range 0-100).
      *
      * This must be overridden by each SkImageEncoder implementation.
      */
--- a/gfx/skia/skia/include/core/SkImageFilter.h
+++ b/gfx/skia/skia/include/core/SkImageFilter.h
@@ -37,43 +37,35 @@ public:
     public:
         struct Key;
         virtual ~Cache() {}
         static Cache* Create(size_t maxBytes);
         static Cache* Get();
         virtual bool get(const Key& key, SkBitmap* result, SkIPoint* offset) const = 0;
         virtual void set(const Key& key, const SkBitmap& result, const SkIPoint& offset) = 0;
         virtual void purge() {}
-    };
-
-    enum SizeConstraint {
-        kExact_SizeConstraint,
-        kApprox_SizeConstraint,
+        virtual void purgeByImageFilterId(uint32_t) {}
     };
 
     class Context {
     public:
-        Context(const SkMatrix& ctm, const SkIRect& clipBounds, Cache* cache,
-                SizeConstraint constraint)
+        Context(const SkMatrix& ctm, const SkIRect& clipBounds, Cache* cache)
             : fCTM(ctm)
             , fClipBounds(clipBounds)
             , fCache(cache)
-            , fSizeConstraint(constraint)
         {}
 
         const SkMatrix& ctm() const { return fCTM; }
         const SkIRect& clipBounds() const { return fClipBounds; }
         Cache* cache() const { return fCache; }
-        SizeConstraint sizeConstraint() const { return fSizeConstraint; }
 
     private:
         SkMatrix        fCTM;
         SkIRect         fClipBounds;
         Cache*          fCache;
-        SizeConstraint  fSizeConstraint;
     };
 
     class CropRect {
     public:
         enum CropEdge {
             kHasLeft_CropEdge   = 0x01,
             kHasTop_CropEdge    = 0x02,
             kHasWidth_CropEdge  = 0x04,
@@ -101,34 +93,41 @@ public:
          */
         bool applyTo(const SkIRect& imageBounds, const Context&, SkIRect* cropped) const;
 
     private:
         SkRect fRect;
         uint32_t fFlags;
     };
 
+    enum TileUsage {
+        kPossible_TileUsage,    //!< the created device may be drawn tiled
+        kNever_TileUsage,       //!< the created device will never be drawn tiled
+    };
+
     class Proxy {
     public:
         virtual ~Proxy() {}
 
-        virtual SkBaseDevice* createDevice(int width, int height) = 0;
+        virtual SkBaseDevice* createDevice(int width, int height,
+                                           TileUsage usage = kNever_TileUsage) = 0;
 
         // Returns true if the proxy handled the filter itself. If this returns
         // false then the filter's code will be called.
         virtual bool filterImage(const SkImageFilter*, const SkBitmap& src,
                                  const SkImageFilter::Context&,
                                  SkBitmap* result, SkIPoint* offset) = 0;
     };
 
     class DeviceProxy : public Proxy {
     public:
         DeviceProxy(SkBaseDevice* device) : fDevice(device) {}
 
-        SkBaseDevice* createDevice(int width, int height) override;
+        SkBaseDevice* createDevice(int width, int height,
+                                   TileUsage usage = kNever_TileUsage) override;
 
         // Returns true if the proxy handled the filter itself. If this returns
         // false then the filter's code will be called.
         bool filterImage(const SkImageFilter*, const SkBitmap& src, const SkImageFilter::Context&,
                          SkBitmap* result, SkIPoint* offset) override;
 
     private:
         SkBaseDevice* fDevice;
@@ -194,22 +193,17 @@ public:
         return this->isColorFilterNode(filterPtr);
     }
 
     /**
      *  Returns true (and optionally returns a ref'd filter) if this imagefilter can be completely
      *  replaced by the returned colorfilter. i.e. the two effects will affect drawing in the
      *  same way.
      */
-    bool asAColorFilter(SkColorFilter** filterPtr) const {
-        return this->countInputs() > 0 &&
-               NULL == this->getInput(0) &&
-               !this->affectsTransparentBlack() &&
-               this->isColorFilterNode(filterPtr);
-    }
+    bool asAColorFilter(SkColorFilter** filterPtr) const;
 
     /**
      *  Returns the number of inputs this filter will accept (some inputs can
      *  be NULL).
      */
     int countInputs() const { return fInputCount; }
 
     /**
@@ -235,45 +229,40 @@ public:
     bool cropRectIsSet() const { return fCropRect.flags() != 0x0; }
 
     CropRect getCropRect() const { return fCropRect; }
 
     // Default impl returns union of all input bounds.
     virtual void computeFastBounds(const SkRect&, SkRect*) const;
 
     // Can this filter DAG compute the resulting bounds of an object-space rectangle?
-    bool canComputeFastBounds() const;
+    virtual bool canComputeFastBounds() const;
 
     /**
      *  If this filter can be represented by another filter + a localMatrix, return that filter,
      *  else return null.
      */
     SkImageFilter* newWithLocalMatrix(const SkMatrix& matrix) const;
 
     /**
      * Create an SkMatrixImageFilter, which transforms its input by the given matrix.
      */
     static SkImageFilter* CreateMatrixFilter(const SkMatrix& matrix,
                                              SkFilterQuality,
                                              SkImageFilter* input = NULL);
 
 #if SK_SUPPORT_GPU
-    /**
-     * Wrap the given texture in a texture-backed SkBitmap.
-     */
-    static void WrapTexture(GrTexture* texture, int width, int height, SkBitmap* result);
-
     // Helper function which invokes GPU filter processing on the
     // input at the specified "index". If the input is null, it leaves
     // "result" and "offset" untouched, and returns true. If the input
     // has a GPU implementation, it will be invoked directly.
     // Otherwise, the filter will be processed in software and
     // uploaded to the GPU.
     bool filterInputGPU(int index, SkImageFilter::Proxy* proxy, const SkBitmap& src, const Context&,
-                        SkBitmap* result, SkIPoint* offset, bool relaxSizeConstraint = true) const;
+                        SkBitmap* result, SkIPoint* offset) const;
 #endif
 
     SK_TO_STRING_PUREVIRT()
     SK_DEFINE_FLATTENABLE_TYPE(SkImageFilter)
 
 protected:
     class Common {
     public:
@@ -346,24 +335,43 @@ protected:
     // Given the bounds of the destination rect to be filled in device
     // coordinates (first parameter), and the CTM, compute (conservatively)
     // which rect of the source image would be required (third parameter).
     // Used for clipping and temp-buffer allocations, so the result need not
     // be exact, but should never be smaller than the real answer. The default
     // implementation recursively unions all input bounds, or returns false if
     // no inputs.
     virtual bool onFilterBounds(const SkIRect&, const SkMatrix&, SkIRect*) const;
+    enum MapDirection {
+        kForward_MapDirection,
+        kReverse_MapDirection
+    };
+
+    /**
+     * Performs a forwards or reverse mapping of the given rect to accommodate
+     * this filter's margin requirements. kForward_MapDirection is used to
+     * determine the destination pixels which would be touched by filtering
+     * the given given source rect (e.g., given source bitmap bounds,
+     * determine the optimal bounds of the filtered offscreen bitmap).
+     * kReverse_MapDirection is used to determine which pixels of the
+     * input(s) would be required to fill the given destination rect
+     * (e.g., clip bounds). NOTE: these operations may not be the
+     * inverse of the other. For example, blurring expands the given rect
+     * in both forward and reverse directions. Unlike
+     * onFilterBounds(), this function is non-recursive.
+     */
+    virtual void onFilterNodeBounds(const SkIRect&, const SkMatrix&, SkIRect*, MapDirection) const;
 
     // Helper function which invokes filter processing on the input at the
     // specified "index". If the input is null, it leaves "result" and
     // "offset" untouched, and returns true. If the input is non-null, it
     // calls filterImage() on that input, and returns true on success.
     // i.e., return !getInput(index) || getInput(index)->filterImage(...);
     bool filterInput(int index, Proxy*, const SkBitmap& src, const Context&,
-                     SkBitmap* result, SkIPoint* offset, bool relaxSizeConstraint = true) const;
+                     SkBitmap* result, SkIPoint* offset) const;
 
     /**
      *  Return true (and return a ref'd colorfilter) if this node in the DAG is just a
      *  colorfilter w/o CropRect constraints.
      */
     virtual bool onIsColorFilterNode(SkColorFilter** /*filterPtr*/) const {
         return false;
     }
@@ -406,22 +414,22 @@ protected:
      *  parameters before they are used in the effect. Note that this function
      *  will be called with (NULL, NULL, SkMatrix::I()) to query for support,
      *  so returning "true" indicates support for all possible matrices.
      */
     virtual bool asFragmentProcessor(GrFragmentProcessor**, GrTexture*, const SkMatrix&,
                                      const SkIRect& bounds) const;
 
     /**
-     * Returns true if this filter can cause transparent black pixels to become
-     * visible (ie., alpha > 0). The default implementation returns false. This
-     * function is non-recursive, i.e., only queries this filter and not its
-     * inputs.
+     *  Creates a modified Context for use when recursing up the image filter DAG.
+     *  The clip bounds are adjusted to accommodate any margins that this
+     *  filter requires by calling this node's
+     *  onFilterNodeBounds(..., kReverse_MapDirection).
      */
-    virtual bool affectsTransparentBlack() const;
+    Context mapContext(const Context& ctx) const;
 
 private:
     friend class SkGraphics;
     static void PurgeCache();
 
     bool usesSrcInput() const { return fUsesSrcInput; }
 
     typedef SkFlattenable INHERITED;
--- a/gfx/skia/skia/include/core/SkImageGenerator.h
+++ b/gfx/skia/skia/include/core/SkImageGenerator.h
@@ -17,16 +17,22 @@ class GrTexture;
 class GrTextureParams;
 class SkBitmap;
 class SkData;
 class SkImageGenerator;
 class SkMatrix;
 class SkPaint;
 class SkPicture;
 
+#ifdef SK_SUPPORT_LEGACY_REFENCODEDDATA_NOCTX
+    #define SK_REFENCODEDDATA_CTXPARAM
+#else
+    #define SK_REFENCODEDDATA_CTXPARAM  GrContext* ctx
+#endif
+
 /**
  *  Takes ownership of SkImageGenerator.  If this method fails for
  *  whatever reason, it will return false and immediatetely delete
  *  the generator.  If it succeeds, it will modify destination
  *  bitmap.
  *
  *  If generator is NULL, will safely return false.
  *
@@ -59,22 +65,30 @@ public:
      *  will call the image generator's destructor.
      */
     virtual ~SkImageGenerator() { }
 
     uint32_t uniqueID() const { return fUniqueID; }
 
     /**
      *  Return a ref to the encoded (i.e. compressed) representation,
-     *  of this data.
+     *  of this data. If the GrContext is non-null, then the caller is only interested in
+     *  gpu-specific formats, so the impl may return null even if they have encoded data,
+     *  assuming they know it is not suitable for the gpu.
      *
      *  If non-NULL is returned, the caller is responsible for calling
      *  unref() on the data when it is finished.
      */
-    SkData* refEncodedData() { return this->onRefEncodedData(); }
+    SkData* refEncodedData(GrContext* ctx = nullptr) {
+#ifdef SK_SUPPORT_LEGACY_REFENCODEDDATA_NOCTX
+        return this->onRefEncodedData();
+#else
+        return this->onRefEncodedData(ctx);
+#endif
+    }
 
     /**
      *  Return the ImageInfo associated with this generator.
      */
     const SkImageInfo& getInfo() const { return fInfo; }
 
     /**
      *  Decode into the given pixels, a block of memory of size at
@@ -225,17 +239,17 @@ public:
         if (!this->tryGenerateBitmap(bm, &info, nullptr)) {
             sk_throw();
         }
     }
 
 protected:
     SkImageGenerator(const SkImageInfo& info);
 
-    virtual SkData* onRefEncodedData();
+    virtual SkData* onRefEncodedData(SK_REFENCODEDDATA_CTXPARAM);
 
     virtual bool onGetPixels(const SkImageInfo& info, void* pixels, size_t rowBytes,
                              SkPMColor ctable[], int* ctableCount);
     virtual bool onGetYUV8Planes(SkISize sizes[3], void* planes[3], size_t rowBytes[3]);
     virtual bool onGetYUV8Planes(SkISize sizes[3], void* planes[3], size_t rowBytes[3],
                                  SkYUVColorSpace* colorSpace);
 
     virtual GrTexture* onGenerateTexture(GrContext*, const SkIRect*) {
--- a/gfx/skia/skia/include/core/SkMask.h
+++ b/gfx/skia/skia/include/core/SkMask.h
@@ -12,16 +12,18 @@
 
 #include "SkRect.h"
 
 /** \class SkMask
     SkMask is used to describe alpha bitmaps, either 1bit, 8bit, or
     the 3-channel 3D format. These are passed to SkMaskFilter objects.
 */
 struct SkMask {
+    SkMask() : fImage(nullptr) {}
+
     enum Format {
         kBW_Format, //!< 1bit per pixel mask (e.g. monochrome)
         kA8_Format, //!< 8bits per pixel mask (e.g. antialiasing)
         k3D_Format, //!< 3 8bit per pixl planes: alpha, mul, add
         kARGB32_Format,         //!< SkPMColor
         kLCD16_Format,          //!< 565 alpha for r/g/b
     };
 
--- a/gfx/skia/skia/include/core/SkMaskFilter.h
+++ b/gfx/skia/skia/include/core/SkMaskFilter.h
@@ -179,19 +179,17 @@ protected:
     enum FilterReturn {
         kFalse_FilterReturn,
         kTrue_FilterReturn,
         kUnimplemented_FilterReturn
     };
 
     class NinePatch : ::SkNoncopyable {
     public:
-        NinePatch() : fCache(NULL) {
-            fMask.fImage = NULL;
-        }
+        NinePatch() : fCache(nullptr) { }
         ~NinePatch();
 
         SkMask      fMask;      // fBounds must have [0,0] in its top-left
         SkIRect     fOuterRect; // width/height must be >= fMask.fBounds'
         SkIPoint    fCenter;    // identifies center row/col for stretching
         SkCachedData* fCache;
     };
 
--- a/gfx/skia/skia/include/core/SkMatrix.h
+++ b/gfx/skia/skia/include/core/SkMatrix.h
@@ -630,36 +630,38 @@ public:
      */
     size_t readFromMemory(const void* buffer, size_t length);
 
     void dump() const;
     void toString(SkString*) const;
 
     /**
      * Calculates the minimum scaling factor of the matrix as computed from the SVD of the upper
-     * left 2x2. If the matrix has perspective -1 is returned.
+     * left 2x2. If the max scale factor cannot be computed (for example overflow or perspective)
+     * -1 is returned.
      *
-     * @return minumum scale factor
+     * @return minimum scale factor
      */
     SkScalar getMinScale() const;
 
     /**
      * Calculates the maximum scaling factor of the matrix as computed from the SVD of the upper
-     * left 2x2. If the matrix has perspective -1 is returned.
+     * left 2x2. If the max scale factor cannot be computed (for example overflow or perspective)
+     * -1 is returned.
      *
      * @return maximum scale factor
      */
     SkScalar getMaxScale() const;
 
     /**
      * Gets both the min and max scale factors. The min scale factor is scaleFactors[0] and the max
-     * is scaleFactors[1]. If the matrix has perspective false will be returned and scaleFactors
-     * will be unchanged.
+     * is scaleFactors[1]. If the min/max scale factors cannot be computed false is returned and the
+     * values of scaleFactors[] are undefined.
      */
-    bool getMinMaxScales(SkScalar scaleFactors[2]) const;
+    bool SK_WARN_UNUSED_RESULT getMinMaxScales(SkScalar scaleFactors[2]) const;
 
     /**
      *  Attempt to decompose this matrix into a scale-only component and whatever remains, where
      *  the scale component is to be applied first.
      *
      *  M -> Remaining * Scale
      *
      *  On success, return true and assign the scale and remaining components (assuming their
--- a/gfx/skia/skia/include/core/SkOSFile.h
+++ b/gfx/skia/skia/include/core/SkOSFile.h
@@ -36,16 +36,17 @@ size_t  sk_fgetsize(FILE*);
 bool    sk_frewind(FILE*);
 
 size_t  sk_fread(void* buffer, size_t byteCount, FILE*);
 size_t  sk_fwrite(const void* buffer, size_t byteCount, FILE*);
 
 char*   sk_fgets(char* str, int size, FILE* f);
 
 void    sk_fflush(FILE*);
+void    sk_fsync(FILE*);
 
 bool    sk_fseek(FILE*, size_t);
 bool    sk_fmove(FILE*, long);
 size_t  sk_ftell(FILE*);
 
 /** Maps a file into memory. Returns the address and length on success, NULL otherwise.
  *  The mapping is read only.
  *  When finished with the mapping, free the returned pointer with sk_fmunmap.
--- a/gfx/skia/skia/include/core/SkPaint.h
+++ b/gfx/skia/skia/include/core/SkPaint.h
@@ -627,23 +627,16 @@ public:
 
     SkImageFilter* getImageFilter() const { return fImageFilter; }
     SkImageFilter* setImageFilter(SkImageFilter*);
 
     SkAnnotation* getAnnotation() const { return fAnnotation; }
     SkAnnotation* setAnnotation(SkAnnotation*);
 
     /**
-     *  Returns true if there is an annotation installed on this paint, and
-     *  the annotation specifics no-drawing.
-     */
-    SK_ATTR_DEPRECATED("use getAnnotation and check for non-null")
-    bool isNoDrawAnnotation() const { return this->getAnnotation() != NULL; }
-
-    /**
      *  Return the paint's SkDrawLooper (if any). Does not affect the looper's
      *  reference count.
      */
     SkDrawLooper* getLooper() const { return fLooper; }
 
     /**
      *  Set or clear the looper object.
      *  <p />
@@ -1084,21 +1077,20 @@ private:
         return kMag2Max;
     }
 
     friend class SkAutoGlyphCache;
     friend class SkAutoGlyphCacheNoGamma;
     friend class SkCanvas;
     friend class SkDraw;
     friend class SkPDFDevice;
-    friend class GrBitmapTextContext;
+    friend class GrAtlasTextBlob;
     friend class GrAtlasTextContext;
-    friend class GrDistanceFieldTextContext;
     friend class GrStencilAndCoverTextContext;
     friend class GrPathRendering;
-    friend class GrTextContext;
+    friend class GrTextUtils;
     friend class GrGLPathRendering;
     friend class SkScalerContext;
     friend class SkTextToPathIter;
     friend class SkCanonicalizePaint;
 };
 
 #endif
--- a/gfx/skia/skia/include/core/SkPath.h
+++ b/gfx/skia/skia/include/core/SkPath.h
@@ -951,16 +951,24 @@ public:
             @param  pts The points representing the current verb and/or segment
                         This must not be NULL.
             @return The verb for the current segment
         */
         Verb next(SkPoint pts[4]) {
             return (Verb) fRawIter.next(pts);
         }
 
+        /** Return what the next verb will be, but do not visit the next segment.
+
+            @return The verb for the next segment
+        */
+        Verb peek() const {
+            return (Verb) fRawIter.peek();
+        }
+
         SkScalar conicWeight() const {
             return fRawIter.conicWeight();
         }
 
     private:
         SkPathRef::Iter fRawIter;
         friend class SkPath;
     };
--- a/gfx/skia/skia/include/core/SkPathMeasure.h
+++ b/gfx/skia/skia/include/core/SkPathMeasure.h
@@ -84,18 +84,22 @@ private:
     const SkPath*   fPath;
     SkScalar        fLength;            // relative to the current contour
     int             fFirstPtIndex;      // relative to the current contour
     bool            fIsClosed;          // relative to the current contour
     bool            fForceClosed;
 
     struct Segment {
         SkScalar    fDistance;  // total distance up to this point
-        unsigned    fPtIndex : 15; // index into the fPts array
+        unsigned    fPtIndex; // index into the fPts array
+#ifdef SK_SUPPORT_LEGACY_PATH_MEASURE_TVALUE
         unsigned    fTValue : 15;
+#else
+        unsigned    fTValue : 30;
+#endif
         unsigned    fType : 2;
 
         SkScalar getScalarT() const;
     };
     SkTDArray<Segment>  fSegments;
     SkTDArray<SkPoint>  fPts; // Points used to define the segments
 
     static const Segment* NextSegment(const Segment*);
--- a/gfx/skia/skia/include/core/SkPathRef.h
+++ b/gfx/skia/skia/include/core/SkPathRef.h
@@ -119,16 +119,17 @@ public:
         /** Return the next verb in this iteration of the path. When all
             segments have been visited, return kDone_Verb.
 
             @param  pts The points representing the current verb and/or segment
                         This must not be NULL.
             @return The verb for the current segment
         */
         uint8_t next(SkPoint pts[4]);
+        uint8_t peek() const;
 
         SkScalar conicWeight() const { return *fConicWeights; }
 
     private:
         const SkPoint*  fPts;
         const uint8_t*  fVerbs;
         const uint8_t*  fVerbStop;
         const SkScalar* fConicWeights;
--- a/gfx/skia/skia/include/core/SkPixelRef.h
+++ b/gfx/skia/skia/include/core/SkPixelRef.h
@@ -220,17 +220,18 @@ public:
      *  If colorSpace is not NULL, the YUV color space of the data should be stored in the address
      *  it points at.
      */
     bool getYUV8Planes(SkISize sizes[3], void* planes[3], size_t rowBytes[3],
                        SkYUVColorSpace* colorSpace) {
         return this->onGetYUV8Planes(sizes, planes, rowBytes, colorSpace);
     }
 
-    bool readPixels(SkBitmap* dst, const SkIRect* subset = NULL);
+    /** Populates dst with the pixels of this pixelRef, converting them to colorType. */
+    bool readPixels(SkBitmap* dst, SkColorType colorType, const SkIRect* subset = NULL);
 
     /**
      *  Makes a deep copy of this PixelRef, respecting the requested config.
      *  @param colorType Desired colortype.
      *  @param profileType Desired colorprofiletype.
      *  @param subset Subset of this PixelRef to copy. Must be fully contained within the bounds of
      *         of this PixelRef.
      *  @return A new SkPixelRef, or NULL if either there is an error (e.g. the destination could
@@ -294,17 +295,17 @@ protected:
     virtual bool onLockPixelsAreWritable() const;
 
     /**
      *  For pixelrefs that don't have access to their raw pixels, they may be
      *  able to make a copy of them (e.g. if the pixels are on the GPU).
      *
      *  The base class implementation returns false;
      */
-    virtual bool onReadPixels(SkBitmap* dst, const SkIRect* subsetOrNull);
+    virtual bool onReadPixels(SkBitmap* dst, SkColorType colorType, const SkIRect* subsetOrNull);
 
     // default impl returns NULL.
     virtual SkData* onRefEncodedData();
 
     // default impl does nothing.
     virtual void onNotifyPixelsChanged();
 
     // default impl returns false.
--- a/gfx/skia/skia/include/core/SkPixelSerializer.h
+++ b/gfx/skia/skia/include/core/SkPixelSerializer.h
@@ -4,19 +4,19 @@
  * Use of this source code is governed by a BSD-style license that can be
  * found in the LICENSE file.
  */
 
 #ifndef SkPixelSerializer_DEFINED
 #define SkPixelSerializer_DEFINED
 
 #include "SkRefCnt.h"
+#include "SkPixmap.h"
 
 class SkData;
-struct SkImageInfo;
 
 /**
  *  Interface for serializing pixels, e.g. SkBitmaps in an SkPicture.
  */
 class SkPixelSerializer : public SkRefCnt {
 public:
     virtual ~SkPixelSerializer() {}
 
@@ -27,26 +27,24 @@ public:
     bool useEncodedData(const void* data, size_t len) {
         return this->onUseEncodedData(data, len);
     }
 
     /**
      *  Call to get the client's version of encoding these pixels. If it
      *  returns NULL, serialize the raw pixels.
      */
-    SkData* encodePixels(const SkImageInfo& info, const void* pixels, size_t rowBytes) {
-        return this->onEncodePixels(info, pixels, rowBytes);
-    }
+    SkData* encode(const SkPixmap& pixmap) { return this->onEncode(pixmap); }
 
 protected:
     /**
      *  Return true if you want to serialize the encoded data, false if you want
-     *  another version serialized (e.g. the result of encodePixels).
+     *  another version serialized (e.g. the result of this->encode()).
      */
     virtual bool onUseEncodedData(const void* data, size_t len) = 0;
 
     /**
      *  If you want to encode these pixels, return the encoded data as an SkData
      *  Return null if you want to serialize the raw pixels.
      */
-    virtual SkData* onEncodePixels(const SkImageInfo&, const void* pixels, size_t rowBytes) = 0;
+    virtual SkData* onEncode(const SkPixmap&) = 0;
 };
 #endif // SkPixelSerializer_DEFINED
--- a/gfx/skia/skia/include/core/SkPostConfig.h
+++ b/gfx/skia/skia/include/core/SkPostConfig.h
@@ -295,24 +295,16 @@
 #if !defined(SK_ALWAYS_INLINE)
 #  if defined(SK_BUILD_FOR_WIN)
 #    define SK_ALWAYS_INLINE __forceinline
 #  else
 #    define SK_ALWAYS_INLINE SK_ATTRIBUTE(always_inline) inline
 #  endif
 #endif
 
-#if defined(_MSC_VER) && SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE2
-    #define SK_VECTORCALL __vectorcall
-#elif defined(SK_CPU_ARM32)
-    #define SK_VECTORCALL __attribute__((pcs("aapcs-vfp")))
-#else
-    #define SK_VECTORCALL
-#endif
-
 //////////////////////////////////////////////////////////////////////
 
 #if SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE1
     #define SK_PREFETCH(ptr)       _mm_prefetch(reinterpret_cast<const char*>(ptr), _MM_HINT_T0)
     #define SK_WRITE_PREFETCH(ptr) _mm_prefetch(reinterpret_cast<const char*>(ptr), _MM_HINT_T0)
 #elif defined(__GNUC__)
     #define SK_PREFETCH(ptr)       __builtin_prefetch(ptr)
     #define SK_WRITE_PREFETCH(ptr) __builtin_prefetch(ptr, 1)
--- a/gfx/skia/skia/include/core/SkPreConfig.h
+++ b/gfx/skia/skia/include/core/SkPreConfig.h
@@ -25,17 +25,18 @@
     #endif
 
     #if defined(WIN32) || defined(__SYMBIAN32__)
         #define SK_BUILD_FOR_WIN32
     #elif defined(ANDROID)
         #define SK_BUILD_FOR_ANDROID
     #elif defined(linux) || defined(__linux) || defined(__FreeBSD__) || \
           defined(__OpenBSD__) || defined(__sun) || defined(__NetBSD__) || \
-          defined(__DragonFly__) || defined(__GLIBC__) || defined(__GNU__)
+          defined(__DragonFly__) || defined(__GLIBC__) || defined(__GNU__) || \
+          defined(__unix__)
         #define SK_BUILD_FOR_UNIX
     #elif TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR
         #define SK_BUILD_FOR_IOS
     #else
         #define SK_BUILD_FOR_MAC
     #endif
 
 #endif
--- a/gfx/skia/skia/include/core/SkRRect.h
+++ b/gfx/skia/skia/include/core/SkRRect.h
@@ -148,16 +148,22 @@ public:
     }
     
     static SkRRect MakeOval(const SkRect& oval) {
         SkRRect rr;
         rr.setOval(oval);
         return rr;
     }
 
+    static SkRRect MakeRectXY(const SkRect& rect, SkScalar xRad, SkScalar yRad) {
+        SkRRect rr;
+        rr.setRectXY(rect, xRad, yRad);
+        return rr;
+    }
+
     /**
      * Set this RR to match the supplied oval. All x radii will equal half the
      * width and all y radii will equal half the height.
      */
     void setOval(const SkRect& oval) {
         fRect = oval;
         fRect.sort();
 
--- a/gfx/skia/skia/include/core/SkRect.h
+++ b/gfx/skia/skia/include/core/SkRect.h
@@ -820,34 +820,16 @@ public:
      */
     void round(SkIRect* dst) const {
         SkASSERT(dst);
         dst->set(SkScalarRoundToInt(fLeft), SkScalarRoundToInt(fTop),
                  SkScalarRoundToInt(fRight), SkScalarRoundToInt(fBottom));
     }
 
     /**
-     *  Variant of round() that explicitly performs the rounding step (i.e. floor(x + 0.5)) using
-     *  double instead of SkScalar (float). It does this by calling SkDScalarRoundToInt(), which
-     *  may be slower than calling SkScalarRountToInt(), but gives slightly more accurate results.
-     *
-     *  e.g.
-     *      SkScalar x = 0.49999997f;
-     *      int ix = SkScalarRoundToInt(x);
-     *      SkASSERT(0 == ix);  // <--- fails
-     *      ix = SkDScalarRoundToInt(x);
-     *      SkASSERT(0 == ix);  // <--- succeeds
-     */
-    void dround(SkIRect* dst) const {
-        SkASSERT(dst);
-        dst->set(SkDScalarRoundToInt(fLeft), SkDScalarRoundToInt(fTop),
-                 SkDScalarRoundToInt(fRight), SkDScalarRoundToInt(fBottom));
-    }
-
-    /**
      *  Set the dst rectangle by rounding "out" this rectangle, choosing the
      *  SkScalarFloor of top and left, and the SkScalarCeil of right and bottom.
      */
     void roundOut(SkIRect* dst) const {
         SkASSERT(dst);
         dst->set(SkScalarFloorToInt(fLeft), SkScalarFloorToInt(fTop),
                  SkScalarCeilToInt(fRight), SkScalarCeilToInt(fBottom));
     }
--- a/gfx/skia/skia/include/core/SkRefCnt.h
+++ b/gfx/skia/skia/include/core/SkRefCnt.h
@@ -211,17 +211,17 @@ public:
     //   - ref() doesn't need any barrier;
     //   - unref() needs a release barrier, and an acquire if it's going to call delete.
 
     bool unique() const { return 1 == sk_atomic_load(&fRefCnt, sk_memory_order_acquire); }
     void    ref() const { (void)sk_atomic_fetch_add(&fRefCnt, +1, sk_memory_order_relaxed); }
     void  unref() const {
         if (1 == sk_atomic_fetch_add(&fRefCnt, -1, sk_memory_order_acq_rel)) {
             SkDEBUGCODE(fRefCnt = 1;)  // restore the 1 for our destructor's assert
-                    delete (const Derived*)this;
+            delete (const Derived*)this;
         }
     }
     void  deref() const { this->unref(); }
 
 private:
     mutable int32_t fRefCnt;
 };
 
--- a/gfx/skia/skia/include/core/SkShader.h
+++ b/gfx/skia/skia/include/core/SkShader.h
@@ -10,16 +10,17 @@
 
 #include "SkBitmap.h"
 #include "SkFlattenable.h"
 #include "SkMask.h"
 #include "SkMatrix.h"
 #include "SkPaint.h"
 #include "../gpu/GrColor.h"
 
+class SkColorFilter;
 class SkPath;
 class SkPicture;
 class SkXfermode;
 class GrContext;
 class GrFragmentProcessor;
 
 /** \class SkShader
  *
@@ -67,41 +68,24 @@ public:
     enum {
         kTileModeCount = kMirror_TileMode + 1
     };
 
     // override these in your subclass
 
     enum Flags {
         //!< set if all of the colors will be opaque
-        kOpaqueAlpha_Flag  = 0x01,
-
-        //! set if this shader's shadeSpan16() method can be called
-        kHasSpan16_Flag = 0x02,
-
-        /** Set this bit if the shader's native data type is instrinsically 16
-            bit, meaning that calling the 32bit shadeSpan() entry point will
-            mean the the impl has to up-sample 16bit data into 32bit. Used as a
-            a means of clearing a dither request if the it will have no effect
-        */
-        kIntrinsicly16_Flag = 0x04,
+        kOpaqueAlpha_Flag = 1 << 0,
 
         /** set if the spans only vary in X (const in Y).
             e.g. an Nx1 bitmap that is being tiled in Y, or a linear-gradient
             that varies from left-to-right. This flag specifies this for
             shadeSpan().
          */
-        kConstInY32_Flag = 0x08,
-
-        /** same as kConstInY32_Flag, but is set if this is true for shadeSpan16
-            which may not always be the case, since shadeSpan16 may be
-            predithered, which would mean it was not const in Y, even though
-            the 32bit shadeSpan() would be const.
-         */
-        kConstInY16_Flag = 0x10
+        kConstInY32_Flag = 1 << 1,
     };
 
     /**
      *  Returns true if the shader is guaranteed to produce only opaque
      *  colors, subject to the SkPaint using the shader to apply an opaque
      *  alpha value. Subclasses should override this to allow some
      *  optimizations.
      */
@@ -132,52 +116,36 @@ public:
          *  alpha your shader will return. The default implementation returns 0.
          *  Your subclass should override if it can (even sometimes) report a
          *  non-zero value, since that will enable various blitters to perform
          *  faster.
          */
         virtual uint32_t getFlags() const { return 0; }
 
         /**
-         *  Return the alpha associated with the data returned by shadeSpan16(). If
-         *  kHasSpan16_Flag is not set, this value is meaningless.
-         */
-        virtual uint8_t getSpan16Alpha() const { return fPaintAlpha; }
-
-        /**
          *  Called for each span of the object being drawn. Your subclass should
          *  set the appropriate colors (with premultiplied alpha) that correspond
          *  to the specified device coordinates.
          */
         virtual void shadeSpan(int x, int y, SkPMColor[], int count) = 0;
 
-        typedef void (*ShadeProc)(void* ctx, int x, int y, SkPMColor[], int count);
+        /**
+         * The const void* ctx is only const because all the implementations are const.
+         * This can be changed to non-const if a new shade proc needs to change the ctx.
+         */
+        typedef void (*ShadeProc)(const void* ctx, int x, int y, SkPMColor[], int count);
         virtual ShadeProc asAShadeProc(void** ctx);
 
         /**
-         *  Called only for 16bit devices when getFlags() returns
-         *  kOpaqueAlphaFlag | kHasSpan16_Flag
-         */
-        virtual void shadeSpan16(int x, int y, uint16_t[], int count);
-
-        /**
          *  Similar to shadeSpan, but only returns the alpha-channel for a span.
          *  The default implementation calls shadeSpan() and then extracts the alpha
          *  values from the returned colors.
          */
         virtual void shadeSpanAlpha(int x, int y, uint8_t alpha[], int count);
 
-        /**
-         *  Helper function that returns true if this shader's shadeSpan16() method
-         *  can be called.
-         */
-        bool canCallShadeSpan16() {
-            return SkShader::CanCallShadeSpan16(this->getFlags());
-        }
-
         // Notification from blitter::blitMask in case we need to see the non-alpha channels
         virtual void set3DMask(const SkMask*) {}
 
     protected:
         // Reference to shader, so we don't have to dupe information.
         const SkShader& fShader;
 
         enum MatrixClass {
@@ -211,23 +179,16 @@ public:
      *  Return the size of a Context returned by createContext.
      *
      *  Override this if your subclass overrides createContext, to return the correct size of
      *  your subclass' context.
      */
     virtual size_t contextSize() const;
 
     /**
-     *  Helper to check the flags to know if it is legal to call shadeSpan16()
-     */
-    static bool CanCallShadeSpan16(uint32_t flags) {
-        return (flags & kHasSpan16_Flag) != 0;
-    }
-
-    /**
      *  Returns true if this shader is just a bitmap, and if not null, returns the bitmap,
      *  localMatrix, and tilemodes. If this is not a bitmap, returns false and ignores the
      *  out-parameters.
      */
     bool isABitmap(SkBitmap* outTexture, SkMatrix* outMatrix, TileMode xy[2]) const {
         return this->onIsABitmap(outTexture, outMatrix, xy);
     }
 
@@ -337,18 +298,33 @@ public:
     /**
      *  If the shader is a custom shader which has data the caller might want, call this function
      *  to get that data.
      */
     virtual bool asACustomShader(void** /* customData */) const { return false; }
 #endif
 
     //////////////////////////////////////////////////////////////////////////
+    //  Methods to create combinations or variants of shaders
+
+    /**
+     *  Return a shader that will apply the specified localMatrix to this shader.
+     *  The specified matrix will be applied before any matrix associated with this shader.
+     */
+    SkShader* newWithLocalMatrix(const SkMatrix&) const;
+
+    /**
+     *  Create a new shader that produces the same colors as invoking this shader and then applying
+     *  the colorfilter.
+     */
+    SkShader* newWithColorFilter(SkColorFilter*) const;
+    
+    //////////////////////////////////////////////////////////////////////////
     //  Factory methods for stock shaders
-
+    
     /**
      *  Call this to create a new "empty" shader, that will not draw anything.
      */
     static SkShader* CreateEmptyShader();
 
     /**
      *  Call this to create a new shader that just draws the specified color. This should always
      *  draw the same as a paint with this color (and no shader).
@@ -390,24 +366,16 @@ public:
      *  @return     Returns a new shader object. Note: this function never returns null.
     */
     static SkShader* CreatePictureShader(const SkPicture* src,
                                          TileMode tmx, TileMode tmy,
                                          const SkMatrix* localMatrix,
                                          const SkRect* tile);
 
     /**
-     *  Return a shader that will apply the specified localMatrix to the proxy shader.
-     *  The specified matrix will be applied before any matrix associated with the proxy.
-     *
-     *  Note: ownership of the proxy is not transferred (though a ref is taken).
-     */
-    static SkShader* CreateLocalMatrixShader(SkShader* proxy, const SkMatrix& localMatrix);
-
-    /**
      *  If this shader can be represented by another shader + a localMatrix, return that shader
      *  and, if not NULL, the localMatrix. If not, return NULL and ignore the localMatrix parameter.
      *
      *  Note: the returned shader (if not NULL) will have been ref'd, and it is the responsibility
      *  of the caller to balance that with unref() when they are done.
      */
     virtual SkShader* refAsALocalMatrixShader(SkMatrix* localMatrix) const;
 
--- a/gfx/skia/skia/include/core/SkStream.h
+++ b/gfx/skia/skia/include/core/SkStream.h
@@ -60,27 +60,28 @@ public:
      *  @return the actual number bytes that could be skipped.
      */
     size_t skip(size_t size) {
         return this->read(NULL, size);
     }
 
     /**
      *  Attempt to peek at size bytes.
-     *  If this stream supports peeking, and it can peek size bytes, copy size
-     *  bytes into buffer, and return true.
-     *  If the stream does not support peeking, or cannot peek size bytes,
-     *  return false and leave buffer unchanged.
+     *  If this stream supports peeking, copy min(size, peekable bytes) into
+     *  buffer, and return the number of bytes copied.
+     *  If the stream does not support peeking, or cannot peek any bytes,
+     *  return 0 and leave buffer unchanged.
      *  The stream is guaranteed to be in the same visible state after this
      *  call, regardless of success or failure.
-     *  @param buffer Must not be NULL. Destination to copy bytes.
+     *  @param buffer Must not be NULL, and must be at least size bytes. Destination
+     *      to copy bytes.
      *  @param size Number of bytes to copy.
-     *  @return Whether the peek was performed.
+     *  @return The number of bytes peeked/copied.
      */
-    virtual bool peek(void* /* buffer */, size_t /* size */) const { return false; }
+    virtual size_t peek(void* /*buffer*/, size_t /*size*/) const { return 0; }
 
     /** Returns true when all the bytes in the stream have been read.
      *  This may return true early (when there are no more bytes to be read)
      *  or late (after the first unsuccessful read).
      */
     virtual bool isAtEnd() const = 0;
 
     int8_t   readS8();
@@ -320,17 +321,17 @@ public:
     SkData* setData(SkData*);
 
     void skipToAlign4();
     const void* getAtPos();
 
     size_t read(void* buffer, size_t size) override;
     bool isAtEnd() const override;
 
-    bool peek(void* buffer, size_t size) const override;
+    size_t peek(void* buffer, size_t size) const override;
 
     bool rewind() override;
     SkMemoryStream* duplicate() const override;
 
     size_t getPosition() const override;
     bool seek(size_t position) override;
     bool move(long offset) override;
     SkMemoryStream* fork() const override;
@@ -354,16 +355,17 @@ public:
     virtual ~SkFILEWStream();
 
     /** Returns true if the current path could be opened.
     */
     bool isValid() const { return fFILE != NULL; }
 
     bool write(const void* buffer, size_t size) override;
     void flush() override;
+    void fsync();
     size_t bytesWritten() const override;
 
 private:
     FILE* fFILE;
 
     typedef SkWStream INHERITED;
 };
 
--- a/gfx/skia/skia/include/core/SkString.h
+++ b/gfx/skia/skia/include/core/SkString.h
@@ -262,12 +262,27 @@ private:
 SkString SkStringPrintf(const char* format, ...);
 
 // Specialized to take advantage of SkString's fast swap path. The unspecialized function is
 // declared in SkTypes.h and called by SkTSort.
 template <> inline void SkTSwap(SkString& a, SkString& b) {
     a.swap(b);
 }
 
+enum SkStrSplitMode {
+    // Strictly return all results. If the input is ",," and the separator is ',' this will return
+    // an array of three empty strings.
+    kStrict_SkStrSplitMode,
+
+    // Only nonempty results will be added to the results. Multiple separators will be
+    // coalesced. Separators at the beginning and end of the input will be ignored.  If the input is
+    // ",," and the separator is ',', this will return an empty vector.
+    kCoalesce_SkStrSplitMode
+};
+
 // Split str on any characters in delimiters into out.  (Think, strtok with a sane API.)
-void SkStrSplit(const char* str, const char* delimiters, SkTArray<SkString>* out);
+void SkStrSplit(const char* str, const char* delimiters, SkStrSplitMode splitMode,
+                SkTArray<SkString>* out);
+inline void SkStrSplit(const char* str, const char* delimiters, SkTArray<SkString>* out) {
+    SkStrSplit(str, delimiters, kCoalesce_SkStrSplitMode, out);
+}
 
 #endif
--- a/gfx/skia/skia/include/core/SkTArray.h
+++ b/gfx/skia/skia/include/core/SkTArray.h
@@ -7,32 +7,33 @@
 
 #ifndef SkTArray_DEFINED
 #define SkTArray_DEFINED
 
 #include "../private/SkTemplates.h"
 #include "SkTypes.h"
 
 #include <new>
+#include <utility>
 
 template <typename T, bool MEM_COPY = false> class SkTArray;
 
 namespace SkTArrayExt {
 
 template<typename T>
 inline void copy(SkTArray<T, true>* self, int dst, int src) {
     memcpy(&self->fItemArray[dst], &self->fItemArray[src], sizeof(T));
 }
 template<typename T>
 inline void copy(SkTArray<T, true>* self, const T* array) {
-    memcpy(self->fMemArray, array, self->fCount * sizeof(T));
+    sk_careful_memcpy(self->fMemArray, array, self->fCount * sizeof(T));
 }
 template<typename T>
 inline void copyAndDelete(SkTArray<T, true>* self, char* newMemArray) {
-    memcpy(newMemArray, self->fMemArray, self->fCount * sizeof(T));
+    sk_careful_memcpy(newMemArray, self->fMemArray, self->fCount * sizeof(T));
 }
 
 template<typename T>
 inline void copy(SkTArray<T, false>* self, int dst, int src) {
     new (&self->fItemArray[dst]) T(self->fItemArray[src]);
 }
 template<typename T>
 inline void copy(SkTArray<T, false>* self, const T* array) {
@@ -193,17 +194,17 @@ public:
         return *newT;
     }
 
     /**
      *  Construct a new T at the back of this array.
      */
     template<class... Args> T& emplace_back(Args&&... args) {
         T* newT = reinterpret_cast<T*>(this->push_back_raw(1));
-        return *new (newT) T(skstd::forward<Args>(args)...);
+        return *new (newT) T(std::forward<Args>(args)...);
     }
 
     /**
      * Allocates n more default-initialized T values, and returns the address of
      * the start of that new range. Note: this address is only valid until the
      * next API call made on the array that might add or remove elements.
      */
     T* push_back_n(int n) {
--- a/gfx/skia/skia/include/core/SkTDArray.h
+++ b/gfx/skia/skia/include/core/SkTDArray.h
@@ -40,17 +40,17 @@ public:
     }
 
     SkTDArray<T>& operator=(const SkTDArray<T>& src) {
         if (this != &src) {
             if (src.fCount > fReserve) {
                 SkTDArray<T> tmp(src.fArray, src.fCount);
                 this->swap(tmp);
             } else {
-                memcpy(fArray, src.fArray, sizeof(T) * src.fCount);
+                sk_careful_memcpy(fArray, src.fArray, sizeof(T) * src.fCount);
                 fCount = src.fCount;
             }
         }
         return *this;
     }
 
     friend bool operator==(const SkTDArray<T>& a, const SkTDArray<T>& b) {
         return  a.fCount == b.fCount &&
--- a/gfx/skia/skia/include/core/SkTLazy.h
+++ b/gfx/skia/skia/include/core/SkTLazy.h
@@ -6,16 +6,17 @@
  */
 
 #ifndef SkTLazy_DEFINED
 #define SkTLazy_DEFINED
 
 #include "../private/SkTemplates.h"
 #include "SkTypes.h"
 #include <new>
+#include <utility>
 
 /**
  *  Efficient way to defer allocating/initializing a class until it is needed
  *  (if ever).
  */
 template <typename T> class SkTLazy {
 public:
     SkTLazy() : fPtr(NULL) {}
@@ -45,17 +46,17 @@ public:
      *  If a previous instance had been initialized (either from init() or
      *  set()) it will first be destroyed, so that a freshly initialized
      *  instance is always returned.
      */
     template <typename... Args> T* init(Args&&... args) {
         if (this->isValid()) {
             fPtr->~T();
         }
-        fPtr = new (SkTCast<T*>(fStorage.get())) T(skstd::forward<Args>(args)...);
+        fPtr = new (SkTCast<T*>(fStorage.get())) T(std::forward<Args>(args)...);
         return fPtr;
     }
 
     /**
      *  Copy src into this, and return a pointer to a copy of it. Note this
      *  will always return the same pointer, so if it is called on a lazy that
      *  has already been initialized, then this will copy over the previous
      *  contents.
@@ -125,16 +126,18 @@ private:
  *
  * consume_a_thing(thing); // could be constThing or a modified copy.
  */
 template <typename T>
 class SkTCopyOnFirstWrite {
 public:
     SkTCopyOnFirstWrite(const T& initial) : fObj(&initial) {}
 
+    SkTCopyOnFirstWrite(const T* initial) : fObj(initial) {}
+
     // Constructor for delayed initialization.
     SkTCopyOnFirstWrite() : fObj(NULL) {}
 
     // Should only be called once, and only if the default constructor was used.
     void init(const T& initial) {
         SkASSERT(NULL == fObj);
         SkASSERT(!fLazy.isValid());
         fObj = &initial;
--- a/gfx/skia/skia/include/core/SkTime.h
+++ b/gfx/skia/skia/include/core/SkTime.h
@@ -33,20 +33,16 @@ public:
         void toISO8601(SkString* dst) const;
     };
     static void GetDateTime(DateTime*);
 
     static SkMSec GetMSecs() { return (SkMSec)(GetNSecs() * 1e-6); }
     static double GetNSecs();
 };
 
-#if defined(SK_DEBUG) && defined(SK_BUILD_FOR_WIN32)
-    extern SkMSec gForceTickCount;
-#endif
-
 #define SK_TIME_FACTOR      1
 
 ///////////////////////////////////////////////////////////////////////////////
 
 class SkAutoTime {
 public:
     // The label is not deep-copied, so its address must remain valid for the
     // lifetime of this object
--- a/gfx/skia/skia/include/core/SkTypes.h
+++ b/gfx/skia/skia/include/core/SkTypes.h
@@ -19,16 +19,38 @@
     #include <arm_neon.h>
 #elif SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE2
     #include <immintrin.h>
 #endif
 // IWYU pragma: end_exports
 
 #include <string.h>
 
+/**
+ *  sk_careful_memcpy() is just like memcpy(), but guards against undefined behavior.
+ *
+ * It is undefined behavior to call memcpy() with null dst or src, even if len is 0.
+ * If an optimizer is "smart" enough, it can exploit this to do unexpected things.
+ *     memcpy(dst, src, 0);
+ *     if (src) {
+ *         printf("%x\n", *src);
+ *     }
+ * In this code the compiler can assume src is not null and omit the if (src) {...} check,
+ * unconditionally running the printf, crashing the program if src really is null.
+ * Of the compilers we pay attention to only GCC performs this optimization in practice.
+ */
+static inline void* sk_careful_memcpy(void* dst, const void* src, size_t len) {
+    // When we pass >0 len we had better already be passing valid pointers.
+    // So we just need to skip calling memcpy when len == 0.
+    if (len) {
+        memcpy(dst,src,len);
+    }
+    return dst;
+}
+
 /** \file SkTypes.h
 */
 
 /** See SkGraphics::GetVersion() to retrieve these at runtime
  */
 #define SKIA_VERSION_MAJOR  1
 #define SKIA_VERSION_MINOR  0
 #define SKIA_VERSION_PATCH  0
@@ -73,17 +95,20 @@ SK_API extern void sk_free(void*);
 SK_API extern void* sk_calloc(size_t size);
 
 /** Same as sk_calloc, but throws an exception instead of returning NULL on failure.
  */
 SK_API extern void* sk_calloc_throw(size_t size);
 
 // bzero is safer than memset, but we can't rely on it, so... sk_bzero()
 static inline void sk_bzero(void* buffer, size_t size) {
-    memset(buffer, 0, size);
+    // Please c.f. sk_careful_memcpy.  It's undefined behavior to call memset(null, 0, 0).
+    if (size) {
+        memset(buffer, 0, size);
+    }
 }
 
 ///////////////////////////////////////////////////////////////////////////////
 
 #ifdef override_GLOBAL_NEW
 #include <new>
 
 inline void* operator new(size_t size) {
@@ -218,22 +243,16 @@ typedef int S16CPU;
 
 /**
  *  Fast type for unsigned 16 bits. Use for parameter passing and local
  *  variables, not for storage
  */
 typedef unsigned U16CPU;
 
 /**
- *  Meant to be faster than bool (doesn't promise to be 0 or 1,
- *  just 0 or non-zero
- */
-typedef int SkBool;
-
-/**
  *  Meant to be a small version of bool, for storage purposes. Will be 0 or 1
  */
 typedef uint8_t SkBool8;
 
 #ifdef SK_DEBUG
     SK_API int8_t      SkToS8(intmax_t);
     SK_API uint8_t     SkToU8(uintmax_t);
     SK_API int16_t     SkToS16(intmax_t);
@@ -252,17 +271,17 @@ typedef uint8_t SkBool8;
     #define SkToU32(x)  ((uint32_t)(x))
     #define SkToInt(x)  ((int)(x))
     #define SkToUInt(x) ((unsigned)(x))
     #define SkToSizeT(x) ((size_t)(x))
 #endif
 
 /** Returns 0 or 1 based on the condition
 */
-#define SkToBool(cond)  ((cond) != 0)
+#define SkToBool(cond)  (!!(cond))
 
 #define SK_MaxS16   32767
 #define SK_MinS16   -32767
 #define SK_MaxU16   0xFFFF
 #define SK_MinU16   0
 #define SK_MaxS32   0x7FFFFFFF
 #define SK_MinS32   -SK_MaxS32
 #define SK_MaxU32   0xFFFFFFFF
@@ -276,16 +295,24 @@ static inline bool SkIsS16(long x) {
 }
 
 /** Returns true if the value can be represented with unsigned 16bits
  */
 static inline bool SkIsU16(long x) {
     return (uint16_t)x == x;
 }
 
+static inline int32_t SkLeftShift(int32_t value, int32_t shift) {
+    return (int32_t) ((uint32_t) value << shift);
+}
+
+static inline int64_t SkLeftShift(int64_t value, int32_t shift) {
+    return (int64_t) ((uint64_t) value << shift);
+}
+
 //////////////////////////////////////////////////////////////////////////////
 
 /** Returns the number of entries in an array (not a pointer) */
 template <typename T, size_t N> char (&SkArrayCountHelper(T (&array)[N]))[N];
 #define SK_ARRAY_COUNT(array) (sizeof(SkArrayCountHelper(array)))
 
 // Can be used to bracket data types that must be dense, e.g. hash keys.
 #if defined(__clang__)  // This should work on GCC too, but GCC diagnostic pop didn't seem to work!
@@ -403,27 +430,16 @@ static inline int32_t SkFastMin32(int32_
     return value;
 }
 
 /** Returns value pinned between min and max, inclusively. */
 template <typename T> static inline const T& SkTPin(const T& value, const T& min, const T& max) {
     return SkTMax(SkTMin(value, max), min);
 }
 
-static inline uint32_t SkSetClearShift(uint32_t bits, bool cond,
-                                       unsigned shift) {
-    SkASSERT((int)cond == 0 || (int)cond == 1);
-    return (bits & ~(1 << shift)) | ((int)cond << shift);
-}
-
-static inline uint32_t SkSetClearMask(uint32_t bits, bool cond,
-                                      uint32_t mask) {
-    return cond ? bits | mask : bits & ~mask;
-}
-
 ///////////////////////////////////////////////////////////////////////////////
 
 /** Use to combine multiple bits in a bitmask in a type safe way.
  */
 template <typename T>
 T SkTBitOr(T a, T b) {
     return (T)(a | b);
 }
--- a/gfx/skia/skia/include/core/SkWriter32.h
+++ b/gfx/skia/skia/include/core/SkWriter32.h
@@ -160,17 +160,17 @@ public:
     }
 
     /**
      *  Write size bytes from values. size must be a multiple of 4, though
      *  values need not be 4-byte aligned.
      */
     void write(const void* values, size_t size) {
         SkASSERT(SkAlign4(size) == size);
-        memcpy(this->reserve(size), values, size);
+        sk_careful_memcpy(this->reserve(size), values, size);
     }
 
     /**
      *  Reserve size bytes. Does not need to be 4 byte aligned. The remaining space (if any) will be
      *  filled in with zeroes.
      */
     uint32_t* reservePad(size_t size) {
         size_t alignedSize = SkAlign4(size);
@@ -181,17 +181,17 @@ public:
         }
         return p;
     }
 
     /**
      *  Write size bytes from src, and pad to 4 byte alignment with zeroes.
      */
     void writePad(const void* src, size_t size) {
-        memcpy(this->reservePad(size), src, size);
+        sk_careful_memcpy(this->reservePad(size), src, size);
     }
 
     /**
      *  Writes a string to the writer, which can be retrieved with
      *  SkReader32::readString().
      *  The length can be specified, or if -1 is passed, it will be computed by
      *  calling strlen(). The length must be < max size_t.
      *
--- a/gfx/skia/skia/include/effects/Sk1DPathEffect.h
+++ b/gfx/skia/skia/include/effects/Sk1DPathEffect.h
@@ -51,18 +51,17 @@ public:
 
     /** Dash by replicating the specified path.
         @param path The path to replicate (dash)
         @param advance The space between instances of path
         @param phase distance (mod advance) along path for its initial position
         @param style how to transform path at each point (based on the current
                      position and tangent)
     */
-    static SkPath1DPathEffect* Create(const SkPath& path, SkScalar advance, SkScalar phase,
-                                      Style style) {
+    static SkPathEffect* Create(const SkPath& path, SkScalar advance, SkScalar phase, Style style) {
         return new SkPath1DPathEffect(path, advance, phase, style);
     }
 
     virtual bool filterPath(SkPath*, const SkPath&,
                             SkStrokeRec*, const SkRect*) const override;
 
     SK_TO_STRING_OVERRIDE()
     SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkPath1DPathEffect)
--- a/gfx/skia/skia/include/effects/Sk2DPathEffect.h
+++ b/gfx/skia/skia/include/effects/Sk2DPathEffect.h
@@ -50,17 +50,17 @@ private:
     Sk2DPathEffect& operator=(const Sk2DPathEffect&);
 
     friend class Sk2DPathEffectBlitter;
     typedef SkPathEffect INHERITED;
 };
 
 class SK_API SkLine2DPathEffect : public Sk2DPathEffect {
 public:
-    static SkLine2DPathEffect* Create(SkScalar width, const SkMatrix& matrix) {
+    static SkPathEffect* Create(SkScalar width, const SkMatrix& matrix) {
         return new SkLine2DPathEffect(width, matrix);
     }
 
     virtual bool filterPath(SkPath* dst, const SkPath& src,
                             SkStrokeRec*, const SkRect*) const override;
 
     SK_TO_STRING_OVERRIDE()
     SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkLine2DPathEffect)
@@ -79,17 +79,17 @@ private:
 };
 
 class SK_API SkPath2DPathEffect : public Sk2DPathEffect {
 public:
     /**
      *  Stamp the specified path to fill the shape, using the matrix to define
      *  the latice.
      */
-    static SkPath2DPathEffect* Create(const SkMatrix& matrix, const SkPath& path) {
+    static SkPathEffect* Create(const SkMatrix& matrix, const SkPath& path) {
         return new SkPath2DPathEffect(matrix, path);
     }
 
     SK_TO_STRING_OVERRIDE()
     SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkPath2DPathEffect)
 
 protected:
     SkPath2DPathEffect(const SkMatrix&, const SkPath&);
--- a/gfx/skia/skia/include/effects/SkAlphaThresholdFilter.h
+++ b/gfx/skia/skia/include/effects/SkAlphaThresholdFilter.h
@@ -17,11 +17,12 @@ public:
      * Creates an image filter that samples a region. If the sample is inside the
      * region the alpha of the image is boosted up to a threshold value. If it is
      * outside the region then the alpha is decreased to the threshold value.
      * The 0,0 point of the region corresponds to the upper left corner of the
      * source image.
      */
     static SkImageFilter* Create(const SkRegion& region, SkScalar innerThreshold,
                                  SkScalar outerThreshold, SkImageFilter* input = NULL);
+    SK_DECLARE_FLATTENABLE_REGISTRAR_GROUP();
 };
 
 #endif
--- a/gfx/skia/skia/include/effects/SkBlurDrawLooper.h
+++ b/gfx/skia/skia/include/effects/SkBlurDrawLooper.h
@@ -30,18 +30,18 @@ public:
         */
         kIgnoreTransform_BlurFlag   = 0x01,
         kOverrideColor_BlurFlag     = 0x02,
         kHighQuality_BlurFlag       = 0x04,
         /** mask for all blur flags */
         kAll_BlurFlag               = 0x07
     };
 
-    static SkBlurDrawLooper* Create(SkColor color, SkScalar sigma, SkScalar dx, SkScalar dy,
-                                    uint32_t flags = kNone_BlurFlag) {
+    static SkDrawLooper* Create(SkColor color, SkScalar sigma, SkScalar dx, SkScalar dy,
+                                uint32_t flags = kNone_BlurFlag) {
         return new SkBlurDrawLooper(color, sigma, dx, dy, flags);
     }
 
     virtual ~SkBlurDrawLooper();
 
     SkDrawLooper::Context* createContext(SkCanvas*, void* storage) const override;
 
     size_t contextSize() const override { return sizeof(BlurDrawLooperContext); }
--- a/gfx/skia/skia/include/effects/SkBlurImageFilter.h
+++ b/gfx/skia/skia/include/effects/SkBlurImageFilter.h
@@ -10,29 +10,33 @@
 
 #include "SkImageFilter.h"
 #include "SkSize.h"
 
 class SK_API SkBlurImageFilter : public SkImageFilter {
 public:
     static SkImageFilter* Create(SkScalar sigmaX, SkScalar sigmaY, SkImageFilter* input = NULL,
                                  const CropRect* cropRect = NULL) {
+        if (0 == sigmaX && 0 == sigmaY && nullptr == cropRect) {
+            return SkSafeRef(input);
+        }
         return new SkBlurImageFilter(sigmaX, sigmaY, input, cropRect);
     }
 
     void computeFastBounds(const SkRect&, SkRect*) const override;
 
     SK_TO_STRING_OVERRIDE()
     SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkBlurImageFilter)
 
 protected:
     void flatten(SkWriteBuffer&) const override;
     bool onFilterImage(Proxy*, const SkBitmap& src, const Context&, SkBitmap* result,
                        SkIPoint* offset) const override;
-    bool onFilterBounds(const SkIRect& src, const SkMatrix&, SkIRect* dst) const override;
+    void onFilterNodeBounds(const SkIRect& src, const SkMatrix&,
+                            SkIRect* dst, MapDirection) const override;
     bool canFilterImageGPU() const override { return true; }
     bool filterImageGPU(Proxy* proxy, const SkBitmap& src, const Context& ctx, SkBitmap* result,
                         SkIPoint* offset) const override;
 
 private:
     SkBlurImageFilter(SkScalar sigmaX,
                       SkScalar sigmaY,
                       SkImageFilter* input,
--- a/gfx/skia/skia/include/effects/SkColorCubeFilter.h
+++ b/gfx/skia/skia/include/effects/SkColorCubeFilter.h
@@ -6,16 +6,17 @@
  */
 
 #ifndef SkColorCubeFilter_DEFINED
 #define SkColorCubeFilter_DEFINED
 
 #include "SkColorFilter.h"
 #include "SkData.h"
 #include "../private/SkMutex.h"
+#include "../private/SkTemplates.h"
 
 class SK_API SkColorCubeFilter : public SkColorFilter {
 public:
     /** cubeData must containt a 3D data in the form of cube of the size:
      *  cubeDimension * cubeDimension * cubeDimension * sizeof(SkColor)
      *  This cube contains a transform where (x,y,z) maps to the (r,g,b).
      *  The alpha components of the colors must be 0xFF.
      */
@@ -50,17 +51,17 @@ private:
 
     private:
         // Working pointers. If any of these is NULL,
         // we need to recompute the corresponding cache values.
         int* fColorToIndex[2];
         SkScalar* fColorToFactors[2];
         SkScalar* fColorToScalar;
 
-        SkAutoMalloc fLutStorage;
+        SkAutoTMalloc<uint8_t> fLutStorage;
 
         const int fCubeDimension;
 
         // Make sure we only initialize the caches once.
         SkMutex fLutsMutex;
         bool fLutsInited;
 
         static void initProcessingLuts(ColorCubeProcesingCache* cache);
--- a/gfx/skia/skia/include/effects/SkColorFilterImageFilter.h
+++ b/gfx/skia/skia/include/effects/SkColorFilterImageFilter.h
@@ -20,17 +20,17 @@ public:
     SK_TO_STRING_OVERRIDE()
     SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkColorFilterImageFilter)
 
 protected:
     void flatten(SkWriteBuffer&) const override;
     bool onFilterImage(Proxy*, const SkBitmap& src, const Context&, SkBitmap* result,
                        SkIPoint* loc) const override;
     bool onIsColorFilterNode(SkColorFilter**) const override;
-    bool affectsTransparentBlack() const override;
+    bool canComputeFastBounds() const override;
 
 private:
     SkColorFilterImageFilter(SkColorFilter* cf,
                              SkImageFilter* input,
                              const CropRect* cropRect);
     virtual ~SkColorFilterImageFilter();
 
     SkColorFilter*  fColorFilter;
--- a/gfx/skia/skia/include/effects/SkColorMatrixFilter.h
+++ b/gfx/skia/skia/include/effects/SkColorMatrixFilter.h
@@ -8,55 +8,52 @@
 #ifndef SkColorMatrixFilter_DEFINED
 #define SkColorMatrixFilter_DEFINED
 
 #include "SkColorFilter.h"
 #include "SkColorMatrix.h"
 
 class SK_API SkColorMatrixFilter : public SkColorFilter {
 public:
-    static SkColorMatrixFilter* Create(const SkColorMatrix& cm) {
+    static SkColorFilter* Create(const SkColorMatrix& cm) {
         return new SkColorMatrixFilter(cm);
     }
-    static SkColorMatrixFilter* Create(const SkScalar array[20]) {
+    static SkColorFilter* Create(const SkScalar array[20]) {
         return new SkColorMatrixFilter(array);
     }
 
+    /**
+     *  Create a colorfilter that multiplies the RGB channels by one color, and
+     *  then adds a second color, pinning the result for each component to
+     *  [0..255]. The alpha components of the mul and add arguments
+     *  are ignored.
+     */
+    static SkColorFilter* CreateLightingFilter(SkColor mul, SkColor add);
+
     void filterSpan(const SkPMColor src[], int count, SkPMColor[]) const override;
     uint32_t getFlags() const override;
     bool asColorMatrix(SkScalar matrix[20]) const override;
     SkColorFilter* newComposed(const SkColorFilter*) const override;
 
 #if SK_SUPPORT_GPU
     const GrFragmentProcessor* asFragmentProcessor(GrContext*) const override;
 #endif
 
-    struct State {
-        int32_t fArray[20];
-        int     fShift;
-    };
-
     SK_TO_STRING_OVERRIDE()
 
     SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkColorMatrixFilter)
 
 protected:
     explicit SkColorMatrixFilter(const SkColorMatrix&);
     explicit SkColorMatrixFilter(const SkScalar array[20]);
     void flatten(SkWriteBuffer&) const override;
 
 private:
     SkColorMatrix   fMatrix;
     float           fTranspose[SkColorMatrix::kCount]; // for Sk4s
-
-    typedef void (*Proc)(const State&, unsigned r, unsigned g, unsigned b,
-                         unsigned a, int32_t result[4]);
-
-    Proc        fProc;
-    State       fState;
-    uint32_t    fFlags;
+    uint32_t        fFlags;
 
     void initState(const SkScalar array[20]);
 
     typedef SkColorFilter INHERITED;
 };
 
 #endif
--- a/gfx/skia/skia/include/effects/SkCornerPathEffect.h
+++ b/gfx/skia/skia/include/effects/SkCornerPathEffect.h
@@ -15,30 +15,31 @@
     SkCornerPathEffect is a subclass of SkPathEffect that can turn sharp corners
     into various treatments (e.g. rounded corners)
 */
 class SK_API SkCornerPathEffect : public SkPathEffect {
 public:
     /** radius must be > 0 to have an effect. It specifies the distance from each corner
         that should be "rounded".
     */
-    static SkCornerPathEffect* Create(SkScalar radius) { return new SkCornerPathEffect(radius); }
-    virtual ~SkCornerPathEffect();
+    static SkPathEffect* Create(SkScalar radius) { return new SkCornerPathEffect(radius); }
 
     virtual bool filterPath(SkPath* dst, const SkPath& src,
                             SkStrokeRec*, const SkRect*) const override;
 
     SK_TO_STRING_OVERRIDE()
     SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkCornerPathEffect)
 
 #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
     bool exposedInAndroidJavaAPI() const override { return true; }
 #endif
 
 protected:
+    virtual ~SkCornerPathEffect();
+
     explicit SkCornerPathEffect(SkScalar radius);
     void flatten(SkWriteBuffer&) const override;
 
 private:
     SkScalar    fRadius;
 
     typedef SkPathEffect INHERITED;
 };
--- a/gfx/skia/skia/include/effects/SkDashPathEffect.h
+++ b/gfx/skia/skia/include/effects/SkDashPathEffect.h
@@ -31,18 +31,17 @@ public:
          10 pixels on
          20 pixels off
          ...
         A phase of -5, 25, 55, 85, etc. would all result in the same path,
          because the sum of all the intervals is 30.
 
         Note: only affects stroked paths.
     */
-    static SkDashPathEffect* Create(const SkScalar intervals[], int count,
-                                    SkScalar phase) {
+    static SkPathEffect* Create(const SkScalar intervals[], int count, SkScalar phase) {
         return new SkDashPathEffect(intervals, count, phase);
     }
     virtual ~SkDashPathEffect();
 
     virtual bool filterPath(SkPath* dst, const SkPath& src,
                             SkStrokeRec*, const SkRect*) const override;
 
     virtual bool asPoints(PointData* results, const SkPath& src,
--- a/gfx/skia/skia/include/effects/SkDiscretePathEffect.h
+++ b/gfx/skia/skia/include/effects/SkDiscretePathEffect.h
@@ -24,19 +24,17 @@ public:
                           the seed value that is used to randomize the path
                           segments' endpoints. If not supplied it defaults to 0,
                           in which case filtering a path multiple times will
                           result in the same set of segments (this is useful for
                           testing). If a caller does not want this behaviour
                           they can pass in a different seedAssist to get a
                           different set of path segments.
     */
-    static SkDiscretePathEffect* Create(SkScalar segLength,
-                                        SkScalar deviation,
-                                        uint32_t seedAssist=0) {
+    static SkPathEffect* Create(SkScalar segLength, SkScalar deviation, uint32_t seedAssist = 0) {
         return new SkDiscretePathEffect(segLength, deviation, seedAssist);
     }
 
     virtual bool filterPath(SkPath* dst, const SkPath& src,
                             SkStrokeRec*, const SkRect*) const override;
 
     SK_TO_STRING_OVERRIDE()
     SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDiscretePathEffect)
--- a/gfx/skia/skia/include/effects/SkDisplacementMapEffect.h
+++ b/gfx/skia/skia/include/effects/SkDisplacementMapEffect.h
@@ -18,33 +18,34 @@ public:
         kR_ChannelSelectorType,
         kG_ChannelSelectorType,
         kB_ChannelSelectorType,
         kA_ChannelSelectorType
     };
 
     ~SkDisplacementMapEffect();
 
-    static SkDisplacementMapEffect* Create(ChannelSelectorType xChannelSelector,
-                                           ChannelSelectorType yChannelSelector,
-                                           SkScalar scale, SkImageFilter* displacement,
-                                           SkImageFilter* color = NULL,
-                                           const CropRect* cropRect = NULL);
+    static SkImageFilter* Create(ChannelSelectorType xChannelSelector,
+                                 ChannelSelectorType yChannelSelector,
+                                 SkScalar scale, SkImageFilter* displacement,
+                                 SkImageFilter* color = NULL,
+                                 const CropRect* cropRect = NULL);
 
     SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDisplacementMapEffect)
 
     virtual bool onFilterImage(Proxy* proxy,
                                const SkBitmap& src,
                                const Context& ctx,
                                SkBitmap* dst,
                                SkIPoint* offset) const override;
     void computeFastBounds(const SkRect& src, SkRect* dst) const override;
 
     virtual bool onFilterBounds(const SkIRect& src, const SkMatrix&,
                                 SkIRect* dst) const override;
+    void onFilterNodeBounds(const SkIRect&, const SkMatrix&, SkIRect*, MapDirection) const override;
 
 #if SK_SUPPORT_GPU
     bool canFilterImageGPU() const override { return true; }
     virtual bool filterImageGPU(Proxy* proxy, const SkBitmap& src, const Context& ctx,
                                 SkBitmap* result, SkIPoint* offset) const override;
 #endif
 
     SK_TO_STRING_OVERRIDE()
--- a/gfx/skia/skia/include/effects/SkDropShadowImageFilter.h
+++ b/gfx/skia/skia/include/effects/SkDropShadowImageFilter.h
@@ -30,17 +30,18 @@ public:
     void computeFastBounds(const SkRect&, SkRect*) const override;
     SK_TO_STRING_OVERRIDE()
     SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDropShadowImageFilter)
 
 protected:
     void flatten(SkWriteBuffer&) const override;
     bool onFilterImage(Proxy*, const SkBitmap& source, const Context&, SkBitmap* result,
                        SkIPoint* loc) const override;
-    bool onFilterBounds(const SkIRect& src, const SkMatrix&, SkIRect* dst) const override;
+    void onFilterNodeBounds(const SkIRect& src, const SkMatrix&,
+                            SkIRect* dst, MapDirection) const override;
 
 private:
     SkDropShadowImageFilter(SkScalar dx, SkScalar dy, SkScalar sigmaX, SkScalar sigmaY, SkColor,
                             ShadowMode shadowMode, SkImageFilter* input, const CropRect* cropRect);
 
     SkScalar fDx, fDy, fSigmaX, fSigmaY;
     SkColor fColor;
     ShadowMode fShadowMode;
--- a/gfx/skia/skia/include/effects/SkEmbossMaskFilter.h
+++ b/gfx/skia/skia/include/effects/SkEmbossMaskFilter.h
@@ -18,24 +18,24 @@ class SK_API SkEmbossMaskFilter : public
 public:
     struct Light {
         SkScalar    fDirection[3];  // x,y,z
         uint16_t    fPad;
         uint8_t     fAmbient;
         uint8_t     fSpecular;      // exponent, 4.4 right now
     };
 
-    static SkEmbossMaskFilter* Create(SkScalar blurSigma, const Light& light);
+    static SkMaskFilter* Create(SkScalar blurSigma, const Light& light);
 
     // overrides from SkMaskFilter
     //  This method is not exported to java.
     SkMask::Format getFormat() const override;
     //  This method is not exported to java.
-    virtual bool filterMask(SkMask* dst, const SkMask& src, const SkMatrix&,
-                            SkIPoint* margin) const override;
+    bool filterMask(SkMask* dst, const SkMask& src, const SkMatrix&,
+                    SkIPoint* margin) const override;
 
     SK_TO_STRING_OVERRIDE()
     SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkEmbossMaskFilter)
 
 protected:
     SkEmbossMaskFilter(SkScalar blurSigma, const Light& light);
     void flatten(SkWriteBuffer&) const override;
 
--- a/gfx/skia/skia/include/effects/SkLightingImageFilter.h
+++ b/gfx/skia/skia/include/effects/SkLightingImageFilter.h
@@ -44,17 +44,17 @@ public:
 protected:
     SkLightingImageFilter(SkImageFilterLight* light,
                           SkScalar surfaceScale,
                           SkImageFilter* input,
                           const CropRect* cropRect);
     void flatten(SkWriteBuffer&) const override;
     const SkImageFilterLight* light() const { return fLight.get(); }
     SkScalar surfaceScale() const { return fSurfaceScale; }
-    bool affectsTransparentBlack() const override { return true; }
+    bool canComputeFastBounds() const override { return false; }
 
 private:
     typedef SkImageFilter INHERITED;
     SkAutoTUnref<SkImageFilterLight> fLight;
     SkScalar fSurfaceScale;
 };
 
 #endif
--- a/gfx/skia/skia/include/effects/SkMatrixConvolutionImageFilter.h
+++ b/gfx/skia/skia/include/effects/SkMatrixConvolutionImageFilter.h
@@ -47,25 +47,25 @@ public:
                               TileMode).
         @param convolveAlpha  If true, all channels are convolved.  If false,
                               only the RGB channels are convolved, and
                               alpha is copied from the source image.
         @param input          The input image filter.  If NULL, the src bitmap
                               passed to filterImage() is used instead.
         @param cropRect       The rectangle to which the output processing will be limited.
     */
-    static SkMatrixConvolutionImageFilter* Create(const SkISize& kernelSize,
-                                                  const SkScalar* kernel,
-                                                  SkScalar gain,
-                                                  SkScalar bias,
-                                                  const SkIPoint& kernelOffset,
-                                                  TileMode tileMode,
-                                                  bool convolveAlpha,
-                                                  SkImageFilter* input = NULL,
-                                                  const CropRect* cropRect = NULL);
+    static SkImageFilter* Create(const SkISize& kernelSize,
+                                 const SkScalar* kernel,
+                                 SkScalar gain,
+                                 SkScalar bias,
+                                 const SkIPoint& kernelOffset,
+                                 TileMode tileMode,
+                                 bool convolveAlpha,
+                                 SkImageFilter* input = NULL,
+                                 const CropRect* cropRect = NULL);
 
     SK_TO_STRING_OVERRIDE()
     SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkMatrixConvolutionImageFilter)
 
 protected:
     SkMatrixConvolutionImageFilter(const SkISize& kernelSize,
                                    const SkScalar* kernel,
                                    SkScalar gain,
@@ -74,18 +74,18 @@ protected:
                                    TileMode tileMode,
                                    bool convolveAlpha,
                                    SkImageFilter* input,
                                    const CropRect* cropRect);
     void flatten(SkWriteBuffer&) const override;
 
     bool onFilterImage(Proxy*, const SkBitmap& src, const Context&,
                        SkBitmap* result, SkIPoint* loc) const override;
-    bool onFilterBounds(const SkIRect&, const SkMatrix&, SkIRect*) const override;
-
+    void onFilterNodeBounds(const SkIRect&, const SkMatrix&, SkIRect*, MapDirection) const override;
+    bool canComputeFastBounds() const override;
 
 #if SK_SUPPORT_GPU
     bool asFragmentProcessor(GrFragmentProcessor**, GrTexture*, const SkMatrix&,
                              const SkIRect& bounds) const override;
 #endif
 
 private:
     SkISize   fKernelSize;
deleted file mode 100644
--- a/gfx/skia/skia/include/effects/SkModeColorFilter.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright 2015 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef SkModeColorFilter_DEFINED
-#define SkModeColorFilter_DEFINED
-
-#include "SkColorFilter.h"
-#include "SkColorPriv.h"
-#include "SkString.h"
-#include "SkXfermode.h"
-
-class SkModeColorFilter : public SkColorFilter {
-public:
-    static SkColorFilter* Create(SkColor color, SkXfermode::Mode mode) {
-        return new SkModeColorFilter(color, mode);
-    }
-
-    SkColor getColor() const { return fColor; }
-    SkXfermode::Mode getMode() const { return fMode; }
-    SkPMColor getPMColor() const { return fPMColor; }
-
-    bool asColorMode(SkColor*, SkXfermode::Mode*) const override;
-    uint32_t getFlags() const override;
-    void filterSpan(const SkPMColor shader[], int count, SkPMColor result[]) const override;
-
-#ifndef SK_IGNORE_TO_STRING
-    void toString(SkString* str) const override {
-        str->append("SkModeColorFilter: color: 0x");
-        str->appendHex(fColor);
-        str->append(" mode: ");
-        str->append(SkXfermode::ModeName(fMode));
-    }
-#endif
-
-#if SK_SUPPORT_GPU
-    const GrFragmentProcessor* asFragmentProcessor(GrContext*) const override;
-#endif
-    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkModeColorFilter)
-
-protected:
-    SkModeColorFilter(SkColor color, SkXfermode::Mode mode) {
-        fColor = color;
-        fMode = mode;
-        this->updateCache();
-    };
-
-    void flatten(SkWriteBuffer&) const override;
-
-private:
-    SkColor             fColor;
-    SkXfermode::Mode    fMode;
-    // cache
-    SkPMColor           fPMColor;
-    SkXfermodeProc      fProc;
-
-    void updateCache();
-
-    typedef SkColorFilter INHERITED;
-};
-
-#endif
--- a/gfx/skia/skia/include/effects/SkMorphologyImageFilter.h
+++ b/gfx/skia/skia/include/effects/SkMorphologyImageFilter.h
@@ -11,17 +11,18 @@
 
 #include "SkColor.h"
 #include "SkImageFilter.h"
 #include "SkSize.h"
 
 class SK_API SkMorphologyImageFilter : public SkImageFilter {
 public:
     void computeFastBounds(const SkRect& src, SkRect* dst) const override;
-    bool onFilterBounds(const SkIRect& src, const SkMatrix& ctm, SkIRect* dst) const override;
+    void onFilterNodeBounds(const SkIRect& src, const SkMatrix& ctm,
+                            SkIRect* dst, MapDirection) const override;
 
     /**
      * All morphology procs have the same signature: src is the source buffer, dst the
      * destination buffer, radius is the morphology radius, width and height are the bounds
      * of the destination buffer (in pixels), and srcStride and dstStride are the
      * number of pixels per row in each buffer. All buffers are 8888.
      */
 
--- a/gfx/skia/skia/include/effects/SkOffsetImageFilter.h
+++ b/gfx/skia/skia/include/effects/SkOffsetImageFilter.h
@@ -25,17 +25,17 @@ public:
 
     SK_TO_STRING_OVERRIDE()
     SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkOffsetImageFilter)
 
 protected:
     void flatten(SkWriteBuffer&) const override;
     bool onFilterImage(Proxy*, const SkBitmap& src, const Context&, SkBitmap* result,
                        SkIPoint* loc) const override;
-    bool onFilterBounds(const SkIRect&, const SkMatrix&, SkIRect*) const override;
+    void onFilterNodeBounds(const SkIRect&, const SkMatrix&, SkIRect*, MapDirection) const override;
 
 private:
     SkOffsetImageFilter(SkScalar dx, SkScalar dy, SkImageFilter* input, const CropRect*);
 
     SkVector fOffset;
 
     typedef SkImageFilter INHERITED;
 };
new file mode 100644
--- /dev/null
+++ b/gfx/skia/skia/include/effects/SkPaintImageFilter.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkPaintImageFilter_DEFINED
+#define SkPaintImageFilter_DEFINED
+
+#include "SkImageFilter.h"
+#include "SkPaint.h"
+
+class SK_API SkPaintImageFilter : public SkImageFilter {
+public:
+    /** Create a new image filter which fills the given rectangle using the
+     *  given paint. If no rectangle is specified, an output is produced with
+     *  the same bounds as the input primitive (even though the input
+     *  primitive's pixels are not used for processing).
+     *  @param paint  Paint to use when filling the rect.
+     *  @param rect   Rectangle of output pixels. If NULL or a given crop edge is
+     *                not specified, the source primitive's bounds are used
+     *                instead.
+     */
+    static SkImageFilter* Create(const SkPaint& paint, const CropRect* rect = NULL);
+
+    bool canComputeFastBounds() const override;
+
+    SK_TO_STRING_OVERRIDE()
+    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkPaintImageFilter)
+
+protected:
+    void flatten(SkWriteBuffer&) const override;
+    bool onFilterImage(Proxy*, const SkBitmap& src, const Context&, SkBitmap* result,
+                       SkIPoint* loc) const override;
+
+private:
+    SkPaintImageFilter(const SkPaint& paint, const CropRect* rect);
+
+    SkPaint fPaint;
+
+    typedef SkImageFilter INHERITED;
+};
+
+#endif
--- a/gfx/skia/skia/include/effects/SkPerlinNoiseShader.h
+++ b/gfx/skia/skia/include/effects/SkPerlinNoiseShader.h
@@ -75,17 +75,16 @@ public:
     size_t contextSize() const override;
 
     class PerlinNoiseShaderContext : public SkShader::Context {
     public:
         PerlinNoiseShaderContext(const SkPerlinNoiseShader& shader, const ContextRec&);
         virtual ~PerlinNoiseShaderContext();
 
         void shadeSpan(int x, int y, SkPMColor[], int count) override;
-        void shadeSpan16(int x, int y, uint16_t[], int count) override;
 
     private:
         SkPMColor shade(const SkPoint& point, StitchData& stitchData) const;
         SkScalar calculateTurbulenceValueForPoint(
             int channel,
             StitchData& stitchData, const SkPoint& point) const;
         SkScalar noise2D(int channel,
                          const StitchData& stitchData, const SkPoint& noiseVector) const;
deleted file mode 100644
--- a/gfx/skia/skia/include/effects/SkRectShaderImageFilter.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright 2013 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef SkRectShaderImageFilter_DEFINED
-#define SkRectShaderImageFilter_DEFINED
-
-#include "SkImageFilter.h"
-#include "SkRect.h"
-
-class SkShader;
-
-class SK_API SkRectShaderImageFilter : public SkImageFilter {
-public:
-    /** Create a new image filter which fills the given rectangle with pixels
-     *  produced by the given SkShader. If no rectangle is specified, an output
-     *  is produced with the same bounds as the input primitive (even though
-     *  the input primitive's pixels are not used for processing).
-     *  @param s     Shader to call for processing. Cannot be NULL. Will be
-     *               ref'ed by the new image filter.
-     *  @param rect  Rectangle of output pixels in which to apply the shader.
-     *               If NULL or a given crop edge is not specified, the source
-     *               primitive's bounds are used instead.
-     */
-    SK_ATTR_DEPRECATED("use Create(SkShader*, const CropRect*)")
-    static SkImageFilter* Create(SkShader* s, const SkRect& rect);
-    static SkImageFilter* Create(SkShader* s, const CropRect* rect = NULL);
-
-    bool affectsTransparentBlack() const override;
-
-    SK_TO_STRING_OVERRIDE()
-    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkRectShaderImageFilter)
-
-protected:
-    virtual ~SkRectShaderImageFilter();
-
-    void flatten(SkWriteBuffer&) const override;
-    bool onFilterImage(Proxy*, const SkBitmap& src, const Context&, SkBitmap* result,
-                       SkIPoint* loc) const override;
-
-private:
-    SkRectShaderImageFilter(SkShader* s, const CropRect* rect);
-
-    SkShader*  fShader;
-
-    typedef SkImageFilter INHERITED;
-};
-
-#endif
--- a/gfx/skia/skia/include/effects/SkTileImageFilter.h
+++ b/gfx/skia/skia/include/effects/SkTileImageFilter.h
@@ -20,16 +20,17 @@ public:
         @param input    Input from which the subregion defined by srcRect will be tiled
     */
     static SkImageFilter* Create(const SkRect& src, const SkRect& dst, SkImageFilter* input);
 
     bool onFilterImage(Proxy* proxy, const SkBitmap& src, const Context& ctx,
                        SkBitmap* dst, SkIPoint* offset) const override;
     bool onFilterBounds(const SkIRect& src, const SkMatrix&,
                         SkIRect* dst) const override;
+    void onFilterNodeBounds(const SkIRect&, const SkMatrix&, SkIRect*, MapDirection) const override;
     void computeFastBounds(const SkRect& src, SkRect* dst) const override;
 
     SK_TO_STRING_OVERRIDE()
     SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkTileImageFilter)
 
 protected:
     void flatten(SkWriteBuffer& buffer) const override;
 
--- a/gfx/skia/skia/include/effects/SkXfermodeImageFilter.h
+++ b/gfx/skia/skia/include/effects/SkXfermodeImageFilter.h
@@ -18,19 +18,19 @@ class SK_API SkXfermodeImageFilter : pub
      * This filter takes an xfermode, and uses it to composite the foreground
      * over the background.  If foreground or background is NULL, the input
      * bitmap (src) is used instead.
       */
 
 public:
     virtual ~SkXfermodeImageFilter();
 
-    static SkXfermodeImageFilter* Create(SkXfermode* mode, SkImageFilter* background,
-                                         SkImageFilter* foreground = NULL,
-                                         const CropRect* cropRect = NULL) {
+    static SkImageFilter* Create(SkXfermode* mode, SkImageFilter* background,
+                                 SkImageFilter* foreground = NULL,
+                                 const CropRect* cropRect = NULL) {
         SkImageFilter* inputs[2] = { background, foreground };
         return new SkXfermodeImageFilter(mode, inputs, cropRect);
     }
 
     SK_TO_STRING_OVERRIDE()
     SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkXfermodeImageFilter)
 
     bool onFilterImage(Proxy* proxy,
--- a/gfx/skia/skia/include/gpu/GrCaps.h
+++ b/gfx/skia/skia/include/gpu/GrCaps.h
@@ -65,17 +65,17 @@ public:
 
     /**
     * Get the precision info for a variable of type kFloat_GrSLType, kVec2f_GrSLType, etc in a
     * given shader type. If the shader type is not supported or the precision level is not
     * supported in that shader type then the returned struct will report false when supported() is
     * called.
     */
     const PrecisionInfo& getFloatShaderPrecisionInfo(GrShaderType shaderType,
-        GrSLPrecision precision) const {
+                                                     GrSLPrecision precision) const {
         return fFloatPrecisions[shaderType][precision];
     };
 
     /**
     * Is there any difference between the float shader variable precision types? If this is true
     * then unless the shader type is not supported, any call to getFloatShaderPrecisionInfo() would
     * report the same info for all precisions in all shader types.
     */
@@ -113,21 +113,17 @@ public:
 
     bool npotTextureTileSupport() const { return fNPOTTextureTileSupport; }
     /** To avoid as-yet-unnecessary complexity we don't allow any partial support of MIP Maps (e.g.
         only for POT textures) */
     bool mipMapSupport() const { return fMipMapSupport; }
     bool twoSidedStencilSupport() const { return fTwoSidedStencilSupport; }
     bool stencilWrapOpsSupport() const { return  fStencilWrapOpsSupport; }
     bool discardRenderTargetSupport() const { return fDiscardRenderTargetSupport; }
-#if GR_FORCE_GPU_TRACE_DEBUGGING
-    bool gpuTracingSupport() const { return true; }
-#else
     bool gpuTracingSupport() const { return fGpuTracingSupport; }
-#endif
     bool compressedTexSubImageSupport() const { return fCompressedTexSubImageSupport; }
     bool oversizedStencilSupport() const { return fOversizedStencilSupport; }
     bool textureBarrierSupport() const { return fTextureBarrierSupport; }
     bool mixedSamplesSupport() const { return fMixedSamplesSupport; }
 
     bool useDrawInsteadOfClear() const { return fUseDrawInsteadOfClear; }
     bool useDrawInsteadOfPartialRenderTargetWrite() const {
         return fUseDrawInsteadOfPartialRenderTargetWrite;
@@ -189,25 +185,18 @@ public:
     int maxTextureSize() const { return fMaxTextureSize; }
     /** This is the maximum tile size to use by GPU devices for rendering sw-backed images/bitmaps.
         It is usually the max texture size, unless we're overriding it for testing. */
     int maxTileSize() const { SkASSERT(fMaxTileSize <= fMaxTextureSize); return fMaxTileSize; }
 
     // Will be 0 if MSAA is not supported
     int maxSampleCount() const { return fMaxSampleCount; }
 
-    bool isConfigRenderable(GrPixelConfig config, bool withMSAA) const {
-        SkASSERT(kGrPixelConfigCnt > config);
-        return fConfigRenderSupport[config][withMSAA];
-    }
-
-    bool isConfigTexturable(GrPixelConfig config) const {
-        SkASSERT(kGrPixelConfigCnt > config);
-        return fConfigTextureSupport[config];
-    }
+    virtual bool isConfigTexturable(GrPixelConfig config) const = 0;
+    virtual bool isConfigRenderable(GrPixelConfig config, bool withMSAA) const = 0;
 
     bool suppressPrints() const { return fSuppressPrints; }
 
     bool immediateFlush() const { return fImmediateFlush; }
 
     bool drawPathMasksToCompressedTexturesSupport() const {
         return fDrawPathMasksToCompressedTextureSupport;
     }
@@ -265,20 +254,16 @@ protected:
     uint32_t fMapBufferFlags;
     int fGeometryBufferMapThreshold;
 
     int fMaxRenderTargetSize;
     int fMaxTextureSize;
     int fMaxTileSize;
     int fMaxSampleCount;
 
-    // The first entry for each config is without msaa and the second is with.
-    bool fConfigRenderSupport[kGrPixelConfigCnt][2];
-    bool fConfigTextureSupport[kGrPixelConfigCnt];
-
 private:
     virtual void onApplyOptionsOverrides(const GrContextOptions&) {};
 
     bool fSuppressPrints : 1;
     bool fImmediateFlush: 1;
     bool fDrawPathMasksToCompressedTextureSupport : 1;
 
     typedef SkRefCnt INHERITED;
--- a/gfx/skia/skia/include/gpu/GrClip.h
+++ b/gfx/skia/skia/include/gpu/GrClip.h
@@ -80,17 +80,17 @@ public:
                 } else {
                     return this->clipStack() == other.clipStack();
                 }
                 break;
             case kIRect_ClipType:
                 return this->irect() == other.irect();
                 break;
         }
-
+        SkFAIL("This should not occur\n");
         return false;
     }
 
     bool operator!=(const GrClip& other) const {
         return !(*this == other);
     }
 
     const SkClipStack* clipStack() const {
--- a/gfx/skia/skia/include/gpu/GrConfig.h
+++ b/gfx/skia/skia/include/gpu/GrConfig.h
@@ -181,16 +181,16 @@ typedef unsigned __int64 uint64_t;
         template <> class GR_STATIC_ASSERT_FAILURE<true> {};
         #define GR_STATIC_ASSERT(CONDITION) \
             enum {GR_CONCAT(X,__LINE__) = \
             sizeof(GR_STATIC_ASSERT_FAILURE<CONDITION>)}
     #endif
 #endif
 
 /**
- * GR_FORCE_GPU_TRACE_DEBUGGING will force gpu tracing/debug markers to be turned on. The trace
- * markers will be printed out instead of making the backend calls to push and pop them.
+ * Enable batch debugging output as json.  The enabler of this flag is responsible for making sure
+ * GrAuditTrail is reset occasionally.
+ * TODO make this runtime configurable
  */
-#if !defined(GR_FORCE_GPU_TRACE_DEBUGGING)
-    #define GR_FORCE_GPU_TRACE_DEBUGGING 0
+#if !defined(GR_BATCH_DEBUGGING_OUTPUT)
+    #define GR_BATCH_DEBUGGING_OUTPUT 0
 #endif
-
 #endif
--- a/gfx/skia/skia/include/gpu/GrContext.h
+++ b/gfx/skia/skia/include/gpu/GrContext.h
@@ -10,19 +10,21 @@
 
 #include "GrCaps.h"
 #include "GrClip.h"
 #include "GrColor.h"
 #include "GrPaint.h"
 #include "GrRenderTarget.h"
 #include "GrTextureProvider.h"
 #include "SkMatrix.h"
-#include "../private/SkMutex.h"
 #include "SkPathEffect.h"
 #include "SkTypes.h"
+#include "../private/GrAuditTrail.h"
+#include "../private/GrSingleOwner.h"
+#include "../private/SkMutex.h"
 
 struct GrBatchAtlasConfig;
 class GrBatchFontCache;
 struct GrContextOptions;
 class GrDrawingManager;
 class GrDrawContext;
 class GrDrawTarget;
 class GrFragmentProcessor;
@@ -349,19 +351,23 @@ public:
 
     /** Specify the sizes of the GrAtlasTextContext atlases.  The configs pointer below should be
         to an array of 3 entries */
     void setTextContextAtlasSizes_ForTesting(const GrBatchAtlasConfig* configs);
 
     /** Enumerates all cached GPU resources and dumps their memory to traceMemoryDump. */
     void dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump) const;
 
-    /** Draw font cache texture to render target */
-    void drawFontCache(const SkRect& rect, GrMaskFormat format, const SkPaint& paint,
-                       GrRenderTarget* target);
+    /** Get pointer to atlas texture for given mask format */
+    GrTexture* getFontAtlasTexture(GrMaskFormat format);
+
+    GrAuditTrail* getAuditTrail() { return &fAuditTrail; }
+
+    /** This is only useful for debug purposes */
+    SkDEBUGCODE(GrSingleOwner* debugSingleOwner() const { return &fSingleOwner; } )
 
 private:
     GrGpu*                          fGpu;
     const GrCaps*                   fCaps;
     GrResourceCache*                fResourceCache;
     // this union exists because the inheritance of GrTextureProvider->GrResourceProvider
     // is in a private header.
     union {
@@ -386,27 +392,34 @@ private:
     // of fReadPixelsMutex and use a separate mutex to guard it. When it re-enters
     // readSurfacePixels it will grab fReadPixelsMutex and release it before the outer
     // readSurfacePixels proceeds to grab it.
     // TODO: Stop pretending to make GrContext thread-safe for sw rasterization and provide
     // a mechanism to make a SkPicture safe for multithreaded sw rasterization.
     SkMutex                         fReadPixelsMutex;
     SkMutex                         fTestPMConversionsMutex;
 
+    // In debug builds we guard against improper thread handling
+    // This guard is passed to the GrDrawingManager and, from there to all the
+    // GrDrawContexts.  It is also passed to the GrTextureProvider and SkGpuDevice.
+    mutable GrSingleOwner fSingleOwner;
+
     struct CleanUpData {
         PFCleanUpFunc fFunc;
         void*         fInfo;
     };
 
     SkTDArray<CleanUpData>          fCleanUpData;
 
     const uint32_t                  fUniqueID;
 
     SkAutoTDelete<GrDrawingManager> fDrawingManager;
 
+    GrAuditTrail                    fAuditTrail;
+
     // TODO: have the CMM use drawContexts and rm this friending
     friend class GrClipMaskManager; // the CMM is friended just so it can call 'drawingManager'
     friend class GrDrawingManager;  // for access to drawingManager for ProgramUnitTest
     GrDrawingManager* drawingManager() { return fDrawingManager; }
 
     GrContext(); // init must be called after the constructor.
     bool init(GrBackend, GrBackendContext, const GrContextOptions& options);
 
--- a/gfx/skia/skia/include/gpu/GrContextOptions.h
+++ b/gfx/skia/skia/include/gpu/GrContextOptions.h
@@ -16,16 +16,18 @@ struct GrContextOptions {
         , fSuppressPrints(false)
         , fMaxTextureSizeOverride(SK_MaxS32)
         , fMaxTileSizeOverride(0)
         , fSuppressDualSourceBlending(false)
         , fGeometryBufferMapThreshold(-1)
         , fUseDrawInsteadOfPartialRenderTargetWrite(false)
         , fImmediateMode(false)
         , fClipBatchToBounds(false)
+        , fDrawBatchBounds(false)
+        , fMaxBatchLookback(-1)
         , fUseShaderSwizzling(false) {}
 
     // EXPERIMENTAL
     // May be removed in the future, or may become standard depending
     // on the outcomes of a variety of internal tests.
     bool fDrawPathToCompressedTexture;
 
     // Suppress prints for the GrContext.
@@ -52,14 +54,22 @@ struct GrContextOptions {
     /** The GrContext operates in immediate mode. It will issue all draws to the backend API
         immediately. Intended to ease debugging. */
     bool fImmediateMode;
 
     /** For debugging purposes turn each GrBatch's bounds into a clip rect. This is used to
         verify that the clip bounds are conservative. */
     bool fClipBatchToBounds;
 
+    /** For debugging purposes draw a wireframe device bounds rect for each GrBatch. The wire
+        frame rect is draw before the GrBatch in order to visualize batches that draw outside
+        of their dev bounds. */
+    bool fDrawBatchBounds;
+
+    /** For debugging, override the default maximum look-back window for GrBatch combining. */
+    int fMaxBatchLookback;
+
     /** Force us to do all swizzling manually in the shader and don't rely on extensions to do
         swizzling. */
     bool fUseShaderSwizzling;
 };
 
 #endif
--- a/gfx/skia/skia/include/gpu/GrDrawContext.h
+++ b/gfx/skia/skia/include/gpu/GrDrawContext.h
@@ -7,26 +7,27 @@
 
 #ifndef GrDrawContext_DEFINED
 #define GrDrawContext_DEFINED
 
 #include "GrColor.h"
 #include "GrRenderTarget.h"
 #include "SkRefCnt.h"
 #include "SkSurfaceProps.h"
+#include "../private/GrSingleOwner.h"
 
+class GrAuditTrail;
 class GrClip;
 class GrContext;
 class GrDrawBatch;
+class GrDrawPathBatchBase;
 class GrDrawingManager;
 class GrDrawTarget;
 class GrPaint;
 class GrPathProcessor;
-class GrPathRange;
-class GrPathRangeDraw;
 class GrPipelineBuilder;
 class GrRenderTarget;
 class GrStrokeInfo;
 class GrSurface;
 class GrTextContext;
 class SkDrawFilter;
 struct SkIPoint;
 struct SkIRect;
@@ -58,27 +59,16 @@ public:
                      const SkMatrix& viewMatrix, const char text[], size_t byteLength,
                      const SkScalar pos[], int scalarsPerPosition,
                      const SkPoint& offset, const SkIRect& clipBounds);
     void drawTextBlob(const GrClip&, const SkPaint&,
                       const SkMatrix& viewMatrix, const SkTextBlob*,
                       SkScalar x, SkScalar y,
                       SkDrawFilter*, const SkIRect& clipBounds);
 
-    // drawPathsFromRange is thanks to GrStencilAndCoverTextContext
-    // TODO: remove once path batches can be created external to GrDrawTarget.
-    void drawPathsFromRange(const GrPipelineBuilder*,
-                            const SkMatrix& viewMatrix,
-                            const SkMatrix& localMatrix,
-                            GrColor color,
-                            GrPathRange* range,
-                            GrPathRangeDraw* draw,
-                            int /*GrPathRendering::FillType*/ fill,
-                            const SkRect& bounds);
-
     /**
      * Provides a perfomance hint that the render target's contents are allowed
      * to become undefined.
      */
     void discard();
 
     /**
      * Clear the entire or rect of the render target, ignoring any clips.
@@ -269,27 +259,42 @@ public:
     /**
      * Draws a batch
      *
      * @param paint    describes how to color pixels.
      * @param batch    the batch to draw
      */
     void drawBatch(const GrClip&, const GrPaint&, GrDrawBatch*);
 
+    /**
+     * Draws a path batch. This needs to be separate from drawBatch because we install path stencil
+     * settings late.
+     *
+     * TODO: Figure out a better model that allows us to roll this method into drawBatch.
+     */
+    void drawPathBatch(const GrPipelineBuilder&, GrDrawPathBatchBase*);
+
     int width() const { return fRenderTarget->width(); }
     int height() const { return fRenderTarget->height(); }
     int numColorSamples() const { return fRenderTarget->numColorSamples(); }
 
+    GrRenderTarget* accessRenderTarget() { return fRenderTarget; }
+
+    ///////////////////////////////////////////////////////////////////////////////////////////////
+    // Functions intended for internal use only.
+    void internal_drawBatch(const GrPipelineBuilder& pipelineBuilder, GrDrawBatch* batch);
+
 private:
-    friend class GrAtlasTextContext; // for access to drawBatch
+    friend class GrAtlasTextBlob; // for access to drawBatch
     friend class GrDrawingManager; // for ctor
 
     SkDEBUGCODE(void validate() const;)
 
-    GrDrawContext(GrDrawingManager*, GrRenderTarget*, const SkSurfaceProps* surfaceProps);
+    GrDrawContext(GrDrawingManager*, GrRenderTarget*, const SkSurfaceProps* surfaceProps,
+                  GrAuditTrail*, GrSingleOwner*);
 
     void internalDrawPath(GrPipelineBuilder*,
                           const SkMatrix& viewMatrix,
                           GrColor,
                           bool useAA,
                           const SkPath&,
                           const GrStrokeInfo&);
 
@@ -303,11 +308,15 @@ private:
     GrRenderTarget*   fRenderTarget;
 
     // In MDB-mode the drawTarget can be closed by some other drawContext that has picked
     // it up. For this reason, the drawTarget should only ever be accessed via 'getDrawTarget'.
     GrDrawTarget*     fDrawTarget;
     GrTextContext*    fTextContext; // lazily gotten from GrContext::DrawingManager
 
     SkSurfaceProps    fSurfaceProps;
+    GrAuditTrail*     fAuditTrail;
+
+    // In debug builds we guard against improper thread handling
+    SkDEBUGCODE(mutable GrSingleOwner* fSingleOwner;)
 };
 
 #endif
--- a/gfx/skia/skia/include/gpu/GrResourceKey.h
+++ b/gfx/skia/skia/include/gpu/GrResourceKey.h
@@ -288,21 +288,23 @@ private:
  * is unique. These macros create such a key in a thread safe manner so the key can be truly global
  * and only constructed once.
  */
 
 /** Place outside of function/class definitions. */
 #define GR_DECLAR