diff --git a/DEPS b/DEPS
index aa52987..a5d1868 100644
--- a/DEPS
+++ b/DEPS
@@ -40,7 +40,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Skia
   # and whatever else without interference from each other.
-  'skia_revision': 'd37979c66d3003035457e978cfd58cb0f57d6d4b',
+  'skia_revision': 'e52577ff9f69c67a3872a4969e9ce3e9247edf52',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn
index 45a523d6..069f10b9 100644
--- a/build/config/compiler/BUILD.gn
+++ b/build/config/compiler/BUILD.gn
@@ -1450,6 +1450,7 @@
     cflags = [
       "/Od",  # Disable optimization.
       "/Ob0",  # Disable all inlining (on by default).
+      "/GF",  # Enable string pooling (off by default).
     ]
   } else if (is_android && !android_full_debug) {
     # On Android we kind of optimize some things that don't affect debugging
diff --git a/chrome/browser/media/encrypted_media_browsertest.cc b/chrome/browser/media/encrypted_media_browsertest.cc
index 09872a7..d4d06ee7 100644
--- a/chrome/browser/media/encrypted_media_browsertest.cc
+++ b/chrome/browser/media/encrypted_media_browsertest.cc
@@ -21,6 +21,7 @@
 #include "components/prefs/pref_service.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/test/browser_test_utils.h"
+#include "media/base/key_system_names.h"
 #include "media/base/media_switches.h"
 #include "media/media_features.h"
 #include "ppapi/features/features.h"
@@ -546,10 +547,15 @@
 
 IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, EncryptedMediaDisabled) {
   DisableEncryptedMedia();
+
+  // Clear Key key system is always supported.
+  std::string expected_title =
+      media::IsClearKey(CurrentKeySystem()) ? kEnded : kEmeNotSupportedError;
+
   RunEncryptedMediaTest(kDefaultEmePlayer, "bear-a_enc-a.webm",
                         kWebMVorbisAudioOnly, CurrentKeySystem(),
                         CurrentSourceType(), kNoSessionToLoad, false,
-                        PlayCount::ONCE, kEmeNotSupportedError);
+                        PlayCount::ONCE, expected_title);
 }
 
 #if BUILDFLAG(USE_PROPRIETARY_CODECS)
diff --git a/chrome/browser/resources/vr_shell/vr_shell_ui.js b/chrome/browser/resources/vr_shell/vr_shell_ui.js
index 18de7671..283434ce 100644
--- a/chrome/browser/resources/vr_shell/vr_shell_ui.js
+++ b/chrome/browser/resources/vr_shell/vr_shell_ui.js
@@ -836,6 +836,7 @@
           URL_INDICATOR_VISIBILITY_TIMEOUT_MS);
       this.secureOriginWarnings.setEnabled(
           mode == api.Mode.WEB_VR && !menuMode);
+      this.background.setEnabled(mode == api.Mode.STANDARD || menuMode);
       this.background.setFullscreen(this.fullscreen);
       this.tabContainer.setEnabled(mode == api.Mode.STANDARD && menuMode);
 
diff --git a/docs/optimizing_web_uis.md b/docs/optimizing_web_uis.md
index 2e484b5..d1b0c5d 100644
--- a/docs/optimizing_web_uis.md
+++ b/docs/optimizing_web_uis.md
@@ -10,19 +10,6 @@
 is_debug = false
 ```
 
-If you make local changes, you likely need to re-run:
-
-```
-$ chrome/browser/resources/vulcanize.py
-```
-
-And rebuild Chrome to see effects. vulcanize.py will result in local changes to
-*crisper* and *vulcanized* files that you must currently check in.
-
-*NOTE: Vuclanize is being integrated directly into
-[GN/Ninja](https://crbug.com/673825), so this workflow is likely to change
-soon.*
-
 ## How is the code optimized?
 
 ### Resource combination
diff --git a/third_party/WebKit/LayoutTests/svg/crash-svg-marker-in-html.html b/third_party/WebKit/LayoutTests/svg/crash-svg-marker-in-html.html
new file mode 100644
index 0000000..6b1b253
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/svg/crash-svg-marker-in-html.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<script src="../resources/testharness.js"></script>
+<script src="../resources/testharnessreport.js"></script>
+<div></div>
+<script>
+test(function() {
+  document.querySelector('div').appendChild(
+    document.createElementNS('http://www.w3.org/2000/svg', 'marker'));
+  document.body.offsetTop;
+}, "Doesn't crash");
+</script>
diff --git a/third_party/WebKit/Source/core/svg/SVGMarkerElement.cpp b/third_party/WebKit/Source/core/svg/SVGMarkerElement.cpp
index ff874a5..f44a077 100644
--- a/third_party/WebKit/Source/core/svg/SVGMarkerElement.cpp
+++ b/third_party/WebKit/Source/core/svg/SVGMarkerElement.cpp
@@ -158,4 +158,9 @@
          m_markerHeight->currentValue()->isRelative();
 }
 
+bool SVGMarkerElement::layoutObjectIsNeeded(const ComputedStyle&) {
+  ContainerNode* parent = FlatTreeTraversal::parent(*this);
+  return parent && parent->isSVGElement() && isValid();
+}
+
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/svg/SVGMarkerElement.h b/third_party/WebKit/Source/core/svg/SVGMarkerElement.h
index 832ca1b..a40769a9 100644
--- a/third_party/WebKit/Source/core/svg/SVGMarkerElement.h
+++ b/third_party/WebKit/Source/core/svg/SVGMarkerElement.h
@@ -88,7 +88,7 @@
   void childrenChanged(const ChildrenChange&) override;
 
   LayoutObject* createLayoutObject(const ComputedStyle&) override;
-  bool layoutObjectIsNeeded(const ComputedStyle&) override { return true; }
+  bool layoutObjectIsNeeded(const ComputedStyle&) override;
 
   bool selfHasRelativeLengths() const override;
 
diff --git a/third_party/WebKit/Source/modules/encryptedmedia/NavigatorRequestMediaKeySystemAccess.cpp b/third_party/WebKit/Source/modules/encryptedmedia/NavigatorRequestMediaKeySystemAccess.cpp
index 7b7151e..9d0f6def 100644
--- a/third_party/WebKit/Source/modules/encryptedmedia/NavigatorRequestMediaKeySystemAccess.cpp
+++ b/third_party/WebKit/Source/modules/encryptedmedia/NavigatorRequestMediaKeySystemAccess.cpp
@@ -263,12 +263,21 @@
   ExecutionContext* executionContext = scriptState->getExecutionContext();
   Document* document = toDocument(executionContext);
 
-  // If encrypted media is disabled, return a rejected promise.
-  if (!document->settings() ||
-      !document->settings()->getEncryptedMediaEnabled()) {
-    return ScriptPromise::rejectWithDOMException(
-        scriptState, DOMException::create(NotSupportedError,
-                                          "Encrypted media is disabled."));
+  // From https://w3c.github.io/encrypted-media/#common-key-systems
+  // All user agents MUST support the common key systems described in this
+  // section.
+  // 9.1 Clear Key: The "org.w3.clearkey" Key System uses plain-text clear
+  //                (unencrypted) key(s) to decrypt the source.
+  //
+  // Do not check settings for Clear Key.
+  if (keySystem != "org.w3.clearkey") {
+    // For other key systems, check settings.
+    if (!document->settings() ||
+        !document->settings()->getEncryptedMediaEnabled()) {
+      return ScriptPromise::rejectWithDOMException(
+          scriptState,
+          DOMException::create(NotSupportedError, "Unsupported keySystem"));
+    }
   }
 
   // From https://w3c.github.io/encrypted-media/#requestMediaKeySystemAccess
diff --git a/third_party/polymer/v1_0/reproduce.sh b/third_party/polymer/v1_0/reproduce.sh
index 44a53b3..8051243 100755
--- a/third_party/polymer/v1_0/reproduce.sh
+++ b/third_party/polymer/v1_0/reproduce.sh
@@ -108,9 +108,6 @@
 echo 'Creating GYP files for interfaces and externs...'
 ./generate_gyp.sh
 
-echo 'Vulcanizing dependent UIs...'
-python ../../../chrome/browser/resources/vulcanize.py
-
 popd > /dev/null
 
 echo 'Searching for unused elements...'
diff --git a/ui/webui/resources/html/i18n_template.html b/ui/webui/resources/html/i18n_template.html
index 851d9d5..abacba8 100644
--- a/ui/webui/resources/html/i18n_template.html
+++ b/ui/webui/resources/html/i18n_template.html
@@ -1 +1,2 @@
-<script src="chrome://resources/js/i18n_template.js"></script>
+<script src="chrome://resources/js/i18n_template_no_process.js"></script>
+<script src="chrome://resources/js/i18n_template_process.js"></script>
diff --git a/ui/webui/resources/js/i18n_template.js b/ui/webui/resources/js/i18n_template.js
index a4dbcdc..02d7245 100644
--- a/ui/webui/resources/js/i18n_template.js
+++ b/ui/webui/resources/js/i18n_template.js
@@ -2,6 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// <include src="i18n_template_no_process.js">
+// Note: vulcanize sometimes disables GRIT processing. If you're importing i18n
+// stuff with <link rel="import">, you should probably be using
+// html/i18n_template.html instead of this file.
 
-i18nTemplate.process(document, loadTimeData);
+// <include src="i18n_template_no_process.js">
+// <include src="i18n_template_process.js">
diff --git a/ui/webui/resources/js/i18n_template_process.js b/ui/webui/resources/js/i18n_template_process.js
new file mode 100644
index 0000000..0e26b63a
--- /dev/null
+++ b/ui/webui/resources/js/i18n_template_process.js
@@ -0,0 +1,5 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+i18nTemplate.process(document, loadTimeData);
diff --git a/ui/webui/resources/webui_resources.grd b/ui/webui/resources/webui_resources.grd
index 9a6617c..8c8473fd 100644
--- a/ui/webui/resources/webui_resources.grd
+++ b/ui/webui/resources/webui_resources.grd
@@ -468,6 +468,9 @@
       <structure name="IDR_WEBUI_JS_I18N_TEMPLATE_NO_PROCESS"
                  file="js/i18n_template_no_process.js"
                  type="chrome_html" />
+      <structure name="IDR_WEBUI_JS_I18N_TEMPLATE_PROCESS"
+                 file="js/i18n_template_process.js"
+                 type="chrome_html" />
       <structure name="IDR_WEBUI_JS_LOAD_TIME_DATA"
                  file="js/load_time_data.js" type="chrome_html" />
       <structure name="IDR_WEBUI_JS_PARSE_HTML_SUBSET"