diff --git a/DEPS b/DEPS
index fe1289d..6fcea8f 100644
--- a/DEPS
+++ b/DEPS
@@ -44,7 +44,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
-  'v8_revision': '35e8c7b52802e62281d3c2b5e6c8694a54f7cdc0',
+  'v8_revision': 'c4ab5a664f9f210baaab32b169f802e48ae4cc32',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling swarming_client
   # and whatever else without interference from each other.
diff --git a/chrome/android/java/AndroidManifest.xml b/chrome/android/java/AndroidManifest.xml
index 7320d4a..d469ca2 100644
--- a/chrome/android/java/AndroidManifest.xml
+++ b/chrome/android/java/AndroidManifest.xml
@@ -1014,9 +1014,6 @@
         </receiver>
 
 
-        <meta-data android:name="com.google.android.gms.version"
-            android:value="@integer/google_play_services_version" />
-
         <meta-data android:name="org.chromium.content.browser.SMART_CLIP_PROVIDER"
             android:value="org.chromium.content.browser.SmartClipProvider"/>
 
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index 4cdb0d7..59ee04ea 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -1652,6 +1652,10 @@
      flag_descriptions::kServiceWorkerNavigationPreloadName,
      flag_descriptions::kServiceWorkerNavigationPreloadDescription, kOsAll,
      FEATURE_VALUE_TYPE(features::kServiceWorkerNavigationPreload)},
+    {"enable-service-worker-script-streaming",
+     flag_descriptions::kServiceWorkerScriptStreamingName,
+     flag_descriptions::kServiceWorkerScriptStreamingDescription, kOsAll,
+     FEATURE_VALUE_TYPE(features::kServiceWorkerScriptStreaming)},
     {"enable-suggestions-with-substring-match",
      flag_descriptions::kSuggestionsWithSubStringMatchName,
      flag_descriptions::kSuggestionsWithSubStringMatchDescription, kOsAll,
diff --git a/chrome/browser/banners/app_banner_settings_helper.h b/chrome/browser/banners/app_banner_settings_helper.h
index 6e2b8585..5c6cc2f 100644
--- a/chrome/browser/banners/app_banner_settings_helper.h
+++ b/chrome/browser/banners/app_banner_settings_helper.h
@@ -63,10 +63,10 @@
     // the banner from being shown too often.
     APP_BANNER_EVENT_DID_SHOW,
     // Records the latest time a banner was dismissed by the user. Used to
-    // suppress the banenr for some time if the user explicitly didn't want it.
+    // suppress the banner for some time if the user explicitly didn't want it.
     APP_BANNER_EVENT_DID_BLOCK,
-    // Records the latest time the user adds a site to the homescreen from a
-    // banner, or launched that site from homescreen. Used to ensure banenrs are
+    // Records the latest time the user added a site to the homescreen from a
+    // banner, or launched that site from homescreen. Used to ensure banners are
     // not shown for sites which were added, and to determine if sites were
     // launched recently.
     APP_BANNER_EVENT_DID_ADD_TO_HOMESCREEN,
diff --git a/chrome/browser/chromeos/policy/device_local_account_browsertest.cc b/chrome/browser/chromeos/policy/device_local_account_browsertest.cc
index 5a1e84c..66ec6d60 100644
--- a/chrome/browser/chromeos/policy/device_local_account_browsertest.cc
+++ b/chrome/browser/chromeos/policy/device_local_account_browsertest.cc
@@ -1703,7 +1703,9 @@
           "domAutomationController.send(pod.classList.contains('advanced'));",
           account_id_1_.Serialize().c_str()),
       &advanced));
-  EXPECT_FALSE(advanced);
+  // Public session pods switch to advanced form immediately upon being
+  // clicked, instead of waiting for animation to end which were in the old UI.
+  EXPECT_TRUE(advanced);
 
   // Manually select a different locale.
   ASSERT_TRUE(content::ExecuteScript(
diff --git a/chrome/browser/download/download_prefs.cc b/chrome/browser/download/download_prefs.cc
index 7a81ac5..c6b31c58 100644
--- a/chrome/browser/download/download_prefs.cc
+++ b/chrome/browser/download/download_prefs.cc
@@ -317,7 +317,9 @@
   DCHECK(extension[0] == base::FilePath::kExtensionSeparator);
   extension.erase(0, 1);
 #if defined(OS_WIN) || defined(OS_LINUX) || defined(OS_MACOSX)
-  if (extension == FILE_PATH_LITERAL("pdf") && ShouldOpenPdfInSystemReader())
+  if (base::FilePath::CompareEqualIgnoreCase(extension,
+                                             FILE_PATH_LITERAL("pdf")) &&
+      ShouldOpenPdfInSystemReader())
     return true;
 #endif
 
diff --git a/chrome/browser/download/download_request_limiter_unittest.cc b/chrome/browser/download/download_request_limiter_unittest.cc
index d748ff7..4699b79 100644
--- a/chrome/browser/download/download_request_limiter_unittest.cc
+++ b/chrome/browser/download/download_request_limiter_unittest.cc
@@ -373,7 +373,7 @@
   // The state should not be reset on a renderer-initiated load to either the
   // same host or a different host, in either the main frame or the subframe.
   content::NavigationSimulator::NavigateAndCommitFromDocument(
-      GURL("http://fooeybar.com/bar"), web_contents()->GetMainFrame());
+      GURL("http://fooey.com/bar2"), web_contents()->GetMainFrame());
   LoadCompleted();
   ASSERT_EQ(DownloadRequestLimiter::DOWNLOADS_NOT_ALLOWED,
             download_request_limiter_->GetDownloadStatus(web_contents()));
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index 1a30db5..28578c3 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -1053,6 +1053,13 @@
     "Enable web pages to use the experimental service worker navigation "
     "preload API.";
 
+const char kServiceWorkerScriptStreamingName[] =
+    "Service worker script streaming.";
+const char kServiceWorkerScriptStreamingDescription[] =
+    "Installed scripts for a service worker are sent over a dedicated "
+    "message pipe and data pipes, and that is never be blocked on the main "
+    "thread.";
+
 const char kSettingsWindowName[] = "Show settings in a window";
 const char kSettingsWindowDescription[] =
     "Settings will be shown in a dedicated window instead of as a browser tab.";
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index 8085303d..5370c7f 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -651,6 +651,9 @@
 extern const char kServiceWorkerNavigationPreloadName[];
 extern const char kServiceWorkerNavigationPreloadDescription[];
 
+extern const char kServiceWorkerScriptStreamingName[];
+extern const char kServiceWorkerScriptStreamingDescription[];
+
 extern const char kSettingsWindowName[];
 extern const char kSettingsWindowDescription[];
 
diff --git a/chrome/browser/net/websocket_browsertest.cc b/chrome/browser/net/websocket_browsertest.cc
index 56e33801..4bbf55c 100644
--- a/chrome/browser/net/websocket_browsertest.cc
+++ b/chrome/browser/net/websocket_browsertest.cc
@@ -7,6 +7,7 @@
 #include "base/macros.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
+#include "build/build_config.h"
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/login/login_handler.h"
@@ -299,7 +300,14 @@
 // HTTPS connection limits should not be applied to wss:. This is only tested
 // for secure connections here because the unencrypted case is tested in the
 // Blink layout tests, and browser tests are expensive to run.
-IN_PROC_BROWSER_TEST_F(WebSocketBrowserTest, SSLConnectionLimit) {
+// Flaky on windows. https://crbug.com/753261
+#if defined(OS_WIN)
+#define MAYBE_SSLConnectionLimit DISABLED_SSLConnectionLimit
+#else
+#define MAYBE_SSLConnectionLimit SSLConnectionLimit
+#endif
+
+IN_PROC_BROWSER_TEST_F(WebSocketBrowserTest, MAYBE_SSLConnectionLimit) {
   ASSERT_TRUE(wss_server_.Start());
 
   NavigateToHTTPS("multiple-connections.html");
diff --git a/chrome/browser/resources/chromeos/login/oobe.html b/chrome/browser/resources/chromeos/login/oobe.html
index 2d946e2..995f3fb4 100644
--- a/chrome/browser/resources/chromeos/login/oobe.html
+++ b/chrome/browser/resources/chromeos/login/oobe.html
@@ -7,7 +7,7 @@
 <meta charset="utf-8">
 <meta name="google" value="notranslate">
 <title i18n-content="title"></title>
-<include src="login_shared.html">
+<include src="md_login_shared.html">
 <include src="login_non_lock_shared.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/polymer/polymer.html">
 <link rel="import" href="chrome://oobe/custom_elements.html">
@@ -15,7 +15,7 @@
 <script src="chrome://oobe/oobe.js"></script>
 </head>
 <body class="oobe-display chromeos" i18n-values=".style.fontFamily:fontfamily;">
-  <include src="screen_container.html">
+  <include src="md_screen_container.html">
   <include src="accessibility_menu.html">
   <div id="popup-overlay" class="popup-overlay" hidden>
     <include src="oobe_screen_eula_installation_settings_overlay.html">
diff --git a/chrome/browser/resources/chromeos/login/oobe.js b/chrome/browser/resources/chromeos/login/oobe.js
index e11aaaa6..3a245cb7 100644
--- a/chrome/browser/resources/chromeos/login/oobe.js
+++ b/chrome/browser/resources/chromeos/login/oobe.js
@@ -7,7 +7,7 @@
  * This is the main code for the OOBE WebUI implementation.
  */
 
-// <include src="login_shared.js">
+// <include src="md_login_shared.js">
 // <include src="login_non_lock_shared.js">
 // <include src="oobe_screen_auto_enrollment_check.js">
 // <include src="oobe_screen_controller_pairing.js">
diff --git a/chrome/browser/resources/chromeos/login/oobe_screens.html b/chrome/browser/resources/chromeos/login/oobe_screens.html
index 4f51fab..7b3f79ed 100644
--- a/chrome/browser/resources/chromeos/login/oobe_screens.html
+++ b/chrome/browser/resources/chromeos/login/oobe_screens.html
@@ -13,7 +13,7 @@
 <include src="oobe_screen_hid_detection.html">
 <include src="oobe_screen_voice_interaction_value_prop.html">
 <include src="oobe_screen_wait_for_container_ready.html">
-<include src="../../../../../ui/login/account_picker/screen_account_picker.html">
+<include src="../../../../../ui/login/account_picker/md_screen_account_picker.html">
 <include src="screen_error_message.html">
 <include src="screen_arc_terms_of_service.html">
 <include src="screen_gaia_signin.html">
diff --git a/chrome/browser/ui/webui/snippets_internals_message_handler.cc b/chrome/browser/ui/webui/snippets_internals_message_handler.cc
index 441232f6..96b03881 100644
--- a/chrome/browser/ui/webui/snippets_internals_message_handler.cc
+++ b/chrome/browser/ui/webui/snippets_internals_message_handler.cc
@@ -575,16 +575,20 @@
 
 void SnippetsInternalsMessageHandler::PushDummySuggestion() {
   std::string json =
-      "{"
-      "  \"ids\" : [\"http://url.com\"],"
-      "  \"title\" : \"Pushed Dummy Title %s\","
-      "  \"snippet\" : \"Pushed Dummy Snippet\","
-      "  \"fullPageUrl\" : \"http://url.com\","
-      "  \"creationTime\" : \"%s\","
-      "  \"expirationTime\" : \"%s\","
-      "  \"attribution\" : \"Pushed Dummy Publisher\","
-      "  \"imageUrl\" : \"https://www.google.com/favicon.ico\" "
-      "}";
+      "{\"categories\" : [{"
+      "  \"id\": 1,"
+      "  \"localizedTitle\": \"section title\","
+      "  \"suggestions\" : [{"
+      "    \"ids\" : [\"http://url.com\"],"
+      "    \"title\" : \"Pushed Dummy Title %s\","
+      "    \"snippet\" : \"Pushed Dummy Snippet\","
+      "    \"fullPageUrl\" : \"http://url.com\","
+      "    \"creationTime\" : \"%s\","
+      "    \"expirationTime\" : \"%s\","
+      "    \"attribution\" : \"Pushed Dummy Publisher\","
+      "    \"imageUrl\" : \"https://www.google.com/favicon.ico\" "
+      "  }]"
+      "}]}";
 
   const base::Time now = base::Time::Now();
   json = base::StringPrintf(
@@ -592,24 +596,18 @@
       TimeToJSONTimeString(now).c_str(),
       TimeToJSONTimeString(now + base::TimeDelta::FromMinutes(60)).c_str());
 
-  std::unique_ptr<base::Value> suggestion_value = base::JSONReader::Read(json);
-  DCHECK(suggestion_value != nullptr);
+  gcm::IncomingMessage message;
+  message.data["payload"] = json;
 
-  const base::DictionaryValue* suggestion_dictionary = nullptr;
-  bool success = suggestion_value->GetAsDictionary(&suggestion_dictionary);
-  DCHECK(success);
-
-  std::unique_ptr<RemoteSuggestion> suggestion =
-      RemoteSuggestion::CreateFromContentSuggestionsDictionary(
-          *suggestion_dictionary, /*remote_category_id=*/1,
-          /*fetch_time=*/now);
-  DCHECK(suggestion != nullptr);
-
-  // TODO(vitaliii): Provide JSON directly to BreakingNewsAppHandler once it is
-  // connected to the provider.
-  static_cast<ntp_snippets::RemoteSuggestionsProviderImpl*>(
-      remote_suggestions_provider_)
-      ->PushArticleSuggestionToTheFrontForDebugging(std::move(suggestion));
+  RemoteSuggestionsProvider* provider =
+      content_suggestions_service_->remote_suggestions_provider_for_debugging();
+  DCHECK(provider);
+  ntp_snippets::BreakingNewsListener* listener =
+      static_cast<ntp_snippets::RemoteSuggestionsProviderImpl*>(provider)
+          ->breaking_news_listener_for_debugging();
+  DCHECK(listener);
+  static_cast<ntp_snippets::BreakingNewsGCMAppHandler*>(listener)->OnMessage(
+      "com.google.breakingnews.gcm", message);
 }
 
 void SnippetsInternalsMessageHandler::OnDismissedSuggestionsLoaded(
diff --git a/chrome/test/android/unit_tests_apk/AndroidManifest.xml b/chrome/test/android/unit_tests_apk/AndroidManifest.xml
index bfaf0c5f..3fdebe57 100644
--- a/chrome/test/android/unit_tests_apk/AndroidManifest.xml
+++ b/chrome/test/android/unit_tests_apk/AndroidManifest.xml
@@ -30,8 +30,6 @@
                 <category android:name="android.intent.category.LAUNCHER" />
             </intent-filter>
         </activity>
-        <meta-data android:name="com.google.android.gms.version"
-                android:value="@integer/google_play_services_version" />
     </application>
 
     <instrumentation android:name="org.chromium.native_test.NativeTestInstrumentationTestRunner"
diff --git a/components/ntp_snippets/breaking_news/breaking_news_listener.h b/components/ntp_snippets/breaking_news/breaking_news_listener.h
index 851184a..3647ce91 100644
--- a/components/ntp_snippets/breaking_news/breaking_news_listener.h
+++ b/components/ntp_snippets/breaking_news/breaking_news_listener.h
@@ -28,6 +28,7 @@
   // will be ignored. Must be called while listening.
   virtual void StopListening() = 0;
 };
+
 }  // namespace ntp_snippets
 
 #endif  // COMPONENTS_NTP_SNIPPETS_BREAKING_NEWS_BREAKING_NEWS_LISTENER_H_
diff --git a/components/ntp_snippets/content_suggestions_service.h b/components/ntp_snippets/content_suggestions_service.h
index 86594f3..e1624e6f 100644
--- a/components/ntp_snippets/content_suggestions_service.h
+++ b/components/ntp_snippets/content_suggestions_service.h
@@ -20,6 +20,7 @@
 #include "components/history/core/browser/history_service.h"
 #include "components/history/core/browser/history_service_observer.h"
 #include "components/keyed_service/core/keyed_service.h"
+#include "components/ntp_snippets/breaking_news/breaking_news_gcm_app_handler.h"
 #include "components/ntp_snippets/callbacks.h"
 #include "components/ntp_snippets/category.h"
 #include "components/ntp_snippets/category_rankers/category_ranker.h"
diff --git a/components/ntp_snippets/remote/remote_suggestions_provider_impl.cc b/components/ntp_snippets/remote/remote_suggestions_provider_impl.cc
index d5e3bc6b..f1ef51de 100644
--- a/components/ntp_snippets/remote/remote_suggestions_provider_impl.cc
+++ b/components/ntp_snippets/remote/remote_suggestions_provider_impl.cc
@@ -559,11 +559,6 @@
   return kMaxSuggestionCount;
 }
 
-void RemoteSuggestionsProviderImpl::PushArticleSuggestionToTheFrontForDebugging(
-    std::unique_ptr<RemoteSuggestion> suggestion) {
-  PrependArticleSuggestion(std::move(suggestion));
-}
-
 ////////////////////////////////////////////////////////////////////////////////
 // Private methods
 
diff --git a/components/ntp_snippets/remote/remote_suggestions_provider_impl.h b/components/ntp_snippets/remote/remote_suggestions_provider_impl.h
index 36b0167..44c02b5 100644
--- a/components/ntp_snippets/remote/remote_suggestions_provider_impl.h
+++ b/components/ntp_snippets/remote/remote_suggestions_provider_impl.h
@@ -144,8 +144,9 @@
   // the constructor.
   CachedImageFetcher& GetImageFetcherForTesting() { return image_fetcher_; }
 
-  void PushArticleSuggestionToTheFrontForDebugging(
-      std::unique_ptr<RemoteSuggestion> suggestion);
+  BreakingNewsListener* breaking_news_listener_for_debugging() {
+    return breaking_news_raw_data_provider_.get();
+  }
 
  private:
   friend class RemoteSuggestionsProviderImplTest;
diff --git a/components/ntp_snippets_strings.grdp b/components/ntp_snippets_strings.grdp
index bda97c2a..672811e 100644
--- a/components/ntp_snippets_strings.grdp
+++ b/components/ntp_snippets_strings.grdp
@@ -19,9 +19,17 @@
     Articles aren't available right now
   </message>
 
-  <message name="IDS_NTP_ARTICLE_SUGGESTIONS_SECTION_HEADER" desc="Header of the articles section, which is a list of news articles displayed as cards on the New Tab Page.">
-    Articles for you
-  </message>
+  <if expr="use_titlecase">
+    <message name="IDS_NTP_ARTICLE_SUGGESTIONS_SECTION_HEADER" desc="Header of the articles section, which is a list of news articles displayed as cards on the New Tab Page.">
+      Articles for You
+    </message>
+  </if>
+
+  <if expr="not use_titlecase">
+    <message name="IDS_NTP_ARTICLE_SUGGESTIONS_SECTION_HEADER" desc="Header of the articles section, which is a list of news articles displayed as cards on the New Tab Page.">
+      Articles for you
+    </message>
+  </if>
 
   <message name="IDS_NTP_ARTICLE_SUGGESTIONS_SECTION_EMPTY" desc="On the New Tab Page, text of the card explaining to the user that they can expect to see suggested articles in this area in the future.">
     Your suggested articles appear here
@@ -52,9 +60,17 @@
     Your nearby suggestions appear here
   </message>
 
-  <message name="IDS_NTP_READING_LIST_SUGGESTIONS_SECTION_HEADER" desc="Header of the Reading List section. The Reading List section shows a list of unread pages from the Reading List.">
-    Reading list
-  </message>
+  <if expr="use_titlecase">
+    <message name="IDS_NTP_READING_LIST_SUGGESTIONS_SECTION_HEADER" desc="Header of the Reading List section. The Reading List section shows a list of unread pages from the Reading List.">
+      Reading List
+    </message>
+  </if>
+
+  <if expr="not use_titlecase">
+    <message name="IDS_NTP_READING_LIST_SUGGESTIONS_SECTION_HEADER" desc="Header of the Reading List section. The Reading List section shows a list of unread pages from the Reading List.">
+      Reading list
+    </message>
+  </if>
 
   <message name="IDS_NTP_READING_LIST_SUGGESTIONS_SECTION_EMPTY" desc="On the New Tab Page, text of the card explaining to the user that they can expect to see Reading List articles in this area in the future.">
     Pages from your reading list appear here
diff --git a/components/search_provider_logos/logo_tracker.cc b/components/search_provider_logos/logo_tracker.cc
index 7fe8f2ba..9f0193ba 100644
--- a/components/search_provider_logos/logo_tracker.cc
+++ b/components/search_provider_logos/logo_tracker.cc
@@ -37,10 +37,8 @@
   base::TimeDelta offset =
       base::TimeDelta::FromMilliseconds(kMaxTimeToLiveMS * 3 / 2);
   base::Time distant_past = now - offset;
-  base::Time distant_future = now + offset;
   // Sanity check so logos aren't accidentally cached forever.
-  if (metadata.expiration_time < distant_past ||
-      metadata.expiration_time > distant_future) {
+  if (metadata.expiration_time < distant_past) {
     return false;
   }
   return metadata.can_show_after_expiration || metadata.expiration_time >= now;
diff --git a/content/child/service_worker/service_worker_dispatcher.cc b/content/child/service_worker/service_worker_dispatcher.cc
index ebd66c5c..6ec92852 100644
--- a/content/child/service_worker/service_worker_dispatcher.cc
+++ b/content/child/service_worker/service_worker_dispatcher.cc
@@ -386,26 +386,6 @@
   return registration;
 }
 
-void ServiceWorkerDispatcher::OnAssociateRegistrationForController(
-    int provider_id,
-    const ServiceWorkerRegistrationObjectInfo& info,
-    const ServiceWorkerVersionAttributes& attrs) {
-  // Adopt the references sent from the browser process and pass them to the
-  // provider context if it exists.
-  std::unique_ptr<ServiceWorkerRegistrationHandleReference> registration =
-      Adopt(info);
-  std::unique_ptr<ServiceWorkerHandleReference> installing =
-      Adopt(attrs.installing);
-  std::unique_ptr<ServiceWorkerHandleReference> waiting = Adopt(attrs.waiting);
-  std::unique_ptr<ServiceWorkerHandleReference> active = Adopt(attrs.active);
-  ProviderContextMap::iterator context = provider_contexts_.find(provider_id);
-  if (context != provider_contexts_.end()) {
-    context->second->OnAssociateRegistration(
-        std::move(registration), std::move(installing), std::move(waiting),
-        std::move(active));
-  }
-}
-
 void ServiceWorkerDispatcher::OnRegistered(
     int thread_id,
     int request_id,
diff --git a/content/child/service_worker/service_worker_dispatcher.h b/content/child/service_worker/service_worker_dispatcher.h
index 234b734..ff26eae 100644
--- a/content/child/service_worker/service_worker_dispatcher.h
+++ b/content/child/service_worker/service_worker_dispatcher.h
@@ -165,13 +165,6 @@
       const ServiceWorkerRegistrationObjectInfo& info,
       const ServiceWorkerVersionAttributes& attrs);
 
-  // TODO(falken): Change the caller to just call the appropriate function on
-  // ServiceWorkerProviderContext directly.
-  void OnAssociateRegistrationForController(
-      int provider_id,
-      const ServiceWorkerRegistrationObjectInfo& info,
-      const ServiceWorkerVersionAttributes& attrs);
-
   static ServiceWorkerDispatcher* GetOrCreateThreadSpecificInstance(
       ThreadSafeSender* thread_safe_sender,
       base::SingleThreadTaskRunner* main_thread_task_runner);
diff --git a/content/child/service_worker/service_worker_dispatcher_unittest.cc b/content/child/service_worker/service_worker_dispatcher_unittest.cc
index 2e7c41d..b2ac94c 100644
--- a/content/child/service_worker/service_worker_dispatcher_unittest.cc
+++ b/content/child/service_worker/service_worker_dispatcher_unittest.cc
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include "content/child/service_worker/service_worker_dispatcher.h"
+
 #include "base/macros.h"
 #include "base/message_loop/message_loop.h"
 #include "content/child/service_worker/service_worker_handle_reference.h"
@@ -73,13 +74,6 @@
     return ContainsKey(dispatcher_->registrations_, registration_handle_id);
   }
 
-  void OnAssociateRegistrationForController(
-      int provider_id,
-      const ServiceWorkerRegistrationObjectInfo& info,
-      const ServiceWorkerVersionAttributes& attrs) {
-    dispatcher_->OnAssociateRegistrationForController(provider_id, info, attrs);
-  }
-
   void OnSetControllerServiceWorker(int thread_id,
                                     int provider_id,
                                     const ServiceWorkerObjectInfo& info,
@@ -163,62 +157,6 @@
   std::set<uint32_t> used_features_;
 };
 
-TEST_F(ServiceWorkerDispatcherTest, OnAssociateRegistration_NoProviderContext) {
-  // Assume that these objects are passed from the browser process and own
-  // references to browser-side registration/worker representations.
-  ServiceWorkerRegistrationObjectInfo info;
-  ServiceWorkerVersionAttributes attrs;
-  CreateObjectInfoAndVersionAttributes(&info, &attrs);
-
-  // The passed references should be adopted but immediately released because
-  // there is no provider context to own the references.
-  const int kProviderId = 10;
-  OnAssociateRegistrationForController(kProviderId, info, attrs);
-  ASSERT_EQ(4UL, ipc_sink()->message_count());
-  EXPECT_EQ(ServiceWorkerHostMsg_DecrementServiceWorkerRefCount::ID,
-            ipc_sink()->GetMessageAt(0)->type());
-  EXPECT_EQ(ServiceWorkerHostMsg_DecrementServiceWorkerRefCount::ID,
-            ipc_sink()->GetMessageAt(1)->type());
-  EXPECT_EQ(ServiceWorkerHostMsg_DecrementServiceWorkerRefCount::ID,
-            ipc_sink()->GetMessageAt(2)->type());
-  EXPECT_EQ(ServiceWorkerHostMsg_DecrementRegistrationRefCount::ID,
-            ipc_sink()->GetMessageAt(3)->type());
-}
-
-TEST_F(ServiceWorkerDispatcherTest,
-       OnAssociateRegistration_ProviderContextForController) {
-  // Assume that these objects are passed from the browser process and own
-  // references to browser-side registration/worker representations.
-  ServiceWorkerRegistrationObjectInfo info;
-  ServiceWorkerVersionAttributes attrs;
-  CreateObjectInfoAndVersionAttributes(&info, &attrs);
-
-  // Set up ServiceWorkerProviderContext for ServiceWorkerGlobalScope.
-  const int kProviderId = 10;
-  scoped_refptr<ServiceWorkerProviderContext> provider_context(
-      new ServiceWorkerProviderContext(
-          kProviderId, SERVICE_WORKER_PROVIDER_FOR_CONTROLLER,
-          mojom::ServiceWorkerProviderAssociatedRequest(),
-          thread_safe_sender()));
-
-  // The passed references should be adopted and owned by the provider context.
-  OnAssociateRegistrationForController(kProviderId, info, attrs);
-  EXPECT_EQ(0UL, ipc_sink()->message_count());
-
-  // Destruction of the provider context should release references to the
-  // associated registration and its versions.
-  provider_context = nullptr;
-  ASSERT_EQ(4UL, ipc_sink()->message_count());
-  EXPECT_EQ(ServiceWorkerHostMsg_DecrementServiceWorkerRefCount::ID,
-            ipc_sink()->GetMessageAt(0)->type());
-  EXPECT_EQ(ServiceWorkerHostMsg_DecrementServiceWorkerRefCount::ID,
-            ipc_sink()->GetMessageAt(1)->type());
-  EXPECT_EQ(ServiceWorkerHostMsg_DecrementServiceWorkerRefCount::ID,
-            ipc_sink()->GetMessageAt(2)->type());
-  EXPECT_EQ(ServiceWorkerHostMsg_DecrementRegistrationRefCount::ID,
-            ipc_sink()->GetMessageAt(3)->type());
-}
-
 TEST_F(ServiceWorkerDispatcherTest, OnSetControllerServiceWorker) {
   const int kProviderId = 10;
   bool should_notify_controllerchange = true;
@@ -243,11 +181,9 @@
   // (2) In the case there is no WebSWProviderClient but SWProviderContext for
   // the provider, the passed referecence should be adopted and owned by the
   // provider context.
-  scoped_refptr<ServiceWorkerProviderContext> provider_context(
-      new ServiceWorkerProviderContext(
-          kProviderId, SERVICE_WORKER_PROVIDER_FOR_WINDOW,
-          mojom::ServiceWorkerProviderAssociatedRequest(),
-          thread_safe_sender()));
+  auto provider_context = base::MakeRefCounted<ServiceWorkerProviderContext>(
+      kProviderId, SERVICE_WORKER_PROVIDER_FOR_WINDOW,
+      mojom::ServiceWorkerProviderAssociatedRequest(), dispatcher());
   ipc_sink()->ClearMessages();
   OnSetControllerServiceWorker(kDocumentMainThreadId, kProviderId, attrs.active,
                                should_notify_controllerchange,
@@ -290,9 +226,9 @@
   // provider context. In addition, the new reference should be created for the
   // provider client and immediately released due to limitation of the mock
   // implementation.
-  provider_context = new ServiceWorkerProviderContext(
+  provider_context = base::MakeRefCounted<ServiceWorkerProviderContext>(
       kProviderId, SERVICE_WORKER_PROVIDER_FOR_WINDOW,
-      mojom::ServiceWorkerProviderAssociatedRequest(), thread_safe_sender());
+      mojom::ServiceWorkerProviderAssociatedRequest(), dispatcher());
   provider_client.reset(
       new MockWebServiceWorkerProviderClientImpl(kProviderId, dispatcher()));
   ASSERT_FALSE(provider_client->is_set_controlled_called());
@@ -320,11 +256,9 @@
 
   std::unique_ptr<MockWebServiceWorkerProviderClientImpl> provider_client(
       new MockWebServiceWorkerProviderClientImpl(kProviderId, dispatcher()));
-  scoped_refptr<ServiceWorkerProviderContext> provider_context(
-      new ServiceWorkerProviderContext(
-          kProviderId, SERVICE_WORKER_PROVIDER_FOR_WINDOW,
-          mojom::ServiceWorkerProviderAssociatedRequest(),
-          thread_safe_sender()));
+  auto provider_context = base::MakeRefCounted<ServiceWorkerProviderContext>(
+      kProviderId, SERVICE_WORKER_PROVIDER_FOR_WINDOW,
+      mojom::ServiceWorkerProviderAssociatedRequest(), dispatcher());
 
   // Set the controller to kInvalidServiceWorkerHandle.
   OnSetControllerServiceWorker(
diff --git a/content/child/service_worker/service_worker_network_provider.cc b/content/child/service_worker/service_worker_network_provider.cc
index b20919a..908fc029 100644
--- a/content/child/service_worker/service_worker_network_provider.cc
+++ b/content/child/service_worker/service_worker_network_provider.cc
@@ -10,6 +10,8 @@
 #include "content/child/service_worker/service_worker_dispatcher.h"
 #include "content/child/service_worker/service_worker_handle_reference.h"
 #include "content/child/service_worker/service_worker_provider_context.h"
+#include "content/child/service_worker/service_worker_registration_handle_reference.h"
+#include "content/child/thread_safe_sender.h"
 #include "content/common/navigation_params.h"
 #include "content/common/service_worker/service_worker_messages.h"
 #include "content/common/service_worker/service_worker_provider_host_info.h"
@@ -216,6 +218,7 @@
 ServiceWorkerNetworkProvider::ServiceWorkerNetworkProvider()
     : provider_id_(kInvalidServiceWorkerProviderId) {}
 
+// Constructor for service worker clients.
 ServiceWorkerNetworkProvider::ServiceWorkerNetworkProvider(
     int route_id,
     ServiceWorkerProviderType provider_type,
@@ -240,34 +243,47 @@
 
   DCHECK(host_info.host_request.is_pending());
   DCHECK(host_info.host_request.handle().is_valid());
-  context_ = new ServiceWorkerProviderContext(
-      provider_id_, provider_type, std::move(client_request),
-      ChildThreadImpl::current()->thread_safe_sender());
+  ServiceWorkerDispatcher* dispatcher =
+      ServiceWorkerDispatcher::GetOrCreateThreadSpecificInstance(
+          ChildThreadImpl::current()->thread_safe_sender(),
+          base::ThreadTaskRunnerHandle::Get().get());
+  context_ = base::MakeRefCounted<ServiceWorkerProviderContext>(
+      provider_id_, provider_type, std::move(client_request), dispatcher);
   ChildThreadImpl::current()->channel()->GetRemoteAssociatedInterface(
       &dispatcher_host_);
   dispatcher_host_->OnProviderCreated(std::move(host_info));
 }
 
+// Constructor for service worker execution contexts.
 ServiceWorkerNetworkProvider::ServiceWorkerNetworkProvider(
     mojom::ServiceWorkerProviderInfoForStartWorkerPtr info)
     : provider_id_(info->provider_id) {
-  context_ = new ServiceWorkerProviderContext(
+  // Initialize the provider context with info for
+  // ServiceWorkerGlobalScope#registration.
+  ThreadSafeSender* sender = ChildThreadImpl::current()->thread_safe_sender();
+  ServiceWorkerDispatcher* dispatcher =
+      ServiceWorkerDispatcher::GetOrCreateThreadSpecificInstance(
+          sender, base::ThreadTaskRunnerHandle::Get().get());
+  context_ = base::MakeRefCounted<ServiceWorkerProviderContext>(
       provider_id_, SERVICE_WORKER_PROVIDER_FOR_CONTROLLER,
-      std::move(info->client_request),
-      ChildThreadImpl::current()->thread_safe_sender());
+      std::move(info->client_request), dispatcher);
+  std::unique_ptr<ServiceWorkerRegistrationHandleReference> registration =
+      ServiceWorkerRegistrationHandleReference::Adopt(info->registration,
+                                                      sender);
+  std::unique_ptr<ServiceWorkerHandleReference> installing =
+      ServiceWorkerHandleReference::Adopt(info->attributes.installing, sender);
+  std::unique_ptr<ServiceWorkerHandleReference> waiting =
+      ServiceWorkerHandleReference::Adopt(info->attributes.waiting, sender);
+  std::unique_ptr<ServiceWorkerHandleReference> active =
+      ServiceWorkerHandleReference::Adopt(info->attributes.active, sender);
+  context_->SetRegistration(std::move(registration), std::move(installing),
+                            std::move(waiting), std::move(active));
 
   if (info->script_loader_factory_ptr_info.is_valid()) {
     script_loader_factory_.Bind(
         std::move(info->script_loader_factory_ptr_info));
   }
 
-  ServiceWorkerDispatcher* dispatcher =
-      ServiceWorkerDispatcher::GetOrCreateThreadSpecificInstance(
-          ChildThreadImpl::current()->thread_safe_sender(),
-          base::ThreadTaskRunnerHandle::Get().get());
-  // TODO(shimazu): Set registration/attributes directly to |context_|.
-  dispatcher->OnAssociateRegistrationForController(
-      info->provider_id, info->registration, info->attributes);
   provider_host_.Bind(std::move(info->host_ptr_info));
 }
 
diff --git a/content/child/service_worker/service_worker_provider_context.cc b/content/child/service_worker/service_worker_provider_context.cc
index db1b7d9..2b18d46a 100644
--- a/content/child/service_worker/service_worker_provider_context.cc
+++ b/content/child/service_worker/service_worker_provider_context.cc
@@ -20,15 +20,13 @@
 class ServiceWorkerProviderContext::Delegate {
  public:
   virtual ~Delegate() {}
-  virtual void AssociateRegistration(
+  virtual void SetRegistration(
       std::unique_ptr<ServiceWorkerRegistrationHandleReference> registration,
       std::unique_ptr<ServiceWorkerHandleReference> installing,
       std::unique_ptr<ServiceWorkerHandleReference> waiting,
       std::unique_ptr<ServiceWorkerHandleReference> active) = 0;
-  virtual void GetAssociatedRegistration(
-      ServiceWorkerRegistrationObjectInfo* info,
-      ServiceWorkerVersionAttributes* attrs) = 0;
-  virtual bool HasAssociatedRegistration() = 0;
+  virtual void GetRegistration(ServiceWorkerRegistrationObjectInfo* info,
+                               ServiceWorkerVersionAttributes* attrs) = 0;
   virtual void SetController(
       std::unique_ptr<ServiceWorkerHandleReference> controller) = 0;
   virtual ServiceWorkerHandleReference* controller() = 0;
@@ -42,7 +40,7 @@
   ControlleeDelegate() {}
   ~ControlleeDelegate() override {}
 
-  void AssociateRegistration(
+  void SetRegistration(
       std::unique_ptr<ServiceWorkerRegistrationHandleReference> registration,
       std::unique_ptr<ServiceWorkerHandleReference> /* installing */,
       std::unique_ptr<ServiceWorkerHandleReference> /* waiting */,
@@ -57,14 +55,8 @@
     controller_ = std::move(controller);
   }
 
-  bool HasAssociatedRegistration() override {
-    NOTREACHED();
-    return false;
-  }
-
-  void GetAssociatedRegistration(
-      ServiceWorkerRegistrationObjectInfo* /* info */,
-      ServiceWorkerVersionAttributes* /* attrs */) override {
+  void GetRegistration(ServiceWorkerRegistrationObjectInfo* /* info */,
+                       ServiceWorkerVersionAttributes* /* attrs */) override {
     NOTREACHED();
   }
 
@@ -86,7 +78,7 @@
   ControllerDelegate() {}
   ~ControllerDelegate() override {}
 
-  void AssociateRegistration(
+  void SetRegistration(
       std::unique_ptr<ServiceWorkerRegistrationHandleReference> registration,
       std::unique_ptr<ServiceWorkerHandleReference> installing,
       std::unique_ptr<ServiceWorkerHandleReference> waiting,
@@ -103,12 +95,9 @@
     NOTREACHED();
   }
 
-  bool HasAssociatedRegistration() override { return !!registration_; }
-
-  void GetAssociatedRegistration(
-      ServiceWorkerRegistrationObjectInfo* info,
-      ServiceWorkerVersionAttributes* attrs) override {
-    DCHECK(HasAssociatedRegistration());
+  void GetRegistration(ServiceWorkerRegistrationObjectInfo* info,
+                       ServiceWorkerVersionAttributes* attrs) override {
+    DCHECK(registration_);
     *info = registration_->info();
     if (installing_)
       attrs->installing = installing_->info();
@@ -136,19 +125,15 @@
     int provider_id,
     ServiceWorkerProviderType provider_type,
     mojom::ServiceWorkerProviderAssociatedRequest request,
-    ThreadSafeSender* thread_safe_sender)
+    ServiceWorkerDispatcher* dispatcher)
     : provider_id_(provider_id),
       main_thread_task_runner_(base::ThreadTaskRunnerHandle::Get()),
-      thread_safe_sender_(thread_safe_sender),
       binding_(this, std::move(request)) {
   if (provider_type == SERVICE_WORKER_PROVIDER_FOR_CONTROLLER)
     delegate_.reset(new ControllerDelegate);
   else
     delegate_.reset(new ControlleeDelegate);
 
-  ServiceWorkerDispatcher* dispatcher =
-      ServiceWorkerDispatcher::GetOrCreateThreadSpecificInstance(
-          thread_safe_sender_.get(), main_thread_task_runner_.get());
   dispatcher->AddProviderContext(this);
 }
 
@@ -160,15 +145,14 @@
   }
 }
 
-void ServiceWorkerProviderContext::OnAssociateRegistration(
+void ServiceWorkerProviderContext::SetRegistration(
     std::unique_ptr<ServiceWorkerRegistrationHandleReference> registration,
     std::unique_ptr<ServiceWorkerHandleReference> installing,
     std::unique_ptr<ServiceWorkerHandleReference> waiting,
     std::unique_ptr<ServiceWorkerHandleReference> active) {
   DCHECK(main_thread_task_runner_->RunsTasksInCurrentSequence());
-  delegate_->AssociateRegistration(std::move(registration),
-                                   std::move(installing), std::move(waiting),
-                                   std::move(active));
+  delegate_->SetRegistration(std::move(registration), std::move(installing),
+                             std::move(waiting), std::move(active));
 }
 
 void ServiceWorkerProviderContext::OnSetControllerServiceWorker(
@@ -182,15 +166,11 @@
     event_dispatcher_.Bind(std::move(event_dispatcher_ptr_info));
 }
 
-void ServiceWorkerProviderContext::GetAssociatedRegistration(
+void ServiceWorkerProviderContext::GetRegistration(
     ServiceWorkerRegistrationObjectInfo* info,
     ServiceWorkerVersionAttributes* attrs) {
   DCHECK(!main_thread_task_runner_->RunsTasksInCurrentSequence());
-  delegate_->GetAssociatedRegistration(info, attrs);
-}
-
-bool ServiceWorkerProviderContext::HasAssociatedRegistration() {
-  return delegate_->HasAssociatedRegistration();
+  delegate_->GetRegistration(info, attrs);
 }
 
 ServiceWorkerHandleReference* ServiceWorkerProviderContext::controller() {
diff --git a/content/child/service_worker/service_worker_provider_context.h b/content/child/service_worker/service_worker_provider_context.h
index 1501757..fbb37fd 100644
--- a/content/child/service_worker/service_worker_provider_context.h
+++ b/content/child/service_worker/service_worker_provider_context.h
@@ -12,6 +12,7 @@
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "base/sequenced_task_runner_helpers.h"
+#include "content/child/service_worker/service_worker_dispatcher.h"
 #include "content/common/content_export.h"
 #include "content/common/service_worker/service_worker_event_dispatcher.mojom.h"
 #include "content/common/service_worker/service_worker_provider_interfaces.mojom.h"
@@ -27,7 +28,6 @@
 class ServiceWorkerHandleReference;
 class ServiceWorkerRegistrationHandleReference;
 struct ServiceWorkerProviderContextDeleter;
-class ThreadSafeSender;
 
 // ServiceWorkerProviderContext has different roles depending on if it's for a
 // "controllee" (a Document or Worker execution context), or a "controller" (a
@@ -63,30 +63,32 @@
   // context. |request| is an endpoint which is connected to
   // content::ServiceWorkerProviderHost which notifies changes of the
   // registration's and workers' status. |request| is bound with |binding_|.
+  // The new instance is registered to |dispatcher|, which is not owned.
   ServiceWorkerProviderContext(
       int provider_id,
       ServiceWorkerProviderType provider_type,
       mojom::ServiceWorkerProviderAssociatedRequest request,
-      ThreadSafeSender* thread_safe_sender);
+      ServiceWorkerDispatcher* dispatcher);
 
-  // Called from ServiceWorkerDispatcher.
-  void OnAssociateRegistration(
+  // For service worker execution contexts. Sets the registration for
+  // ServiceWorkerGlobalScope#registration. Called on the main thread.
+  void SetRegistration(
       std::unique_ptr<ServiceWorkerRegistrationHandleReference> registration,
       std::unique_ptr<ServiceWorkerHandleReference> installing,
       std::unique_ptr<ServiceWorkerHandleReference> waiting,
       std::unique_ptr<ServiceWorkerHandleReference> active);
+
+  // For service worker clients. Sets the controller for
+  // ServiceWorkerContainer#controller. Called on the main thread.
   void OnSetControllerServiceWorker(
       std::unique_ptr<ServiceWorkerHandleReference> controller,
       const std::set<uint32_t>& used_features,
       mojom::ServiceWorkerEventDispatcherPtrInfo event_dispatcher_ptr_info);
 
   // Called on the worker thread. Used for initializing
-  // ServiceWorkerGlobalScope.
-  void GetAssociatedRegistration(ServiceWorkerRegistrationObjectInfo* info,
-                                 ServiceWorkerVersionAttributes* attrs);
-
-  // May be called on the main or worker thread.
-  bool HasAssociatedRegistration();
+  // ServiceWorkerGlobalScope#registration.
+  void GetRegistration(ServiceWorkerRegistrationObjectInfo* info,
+                       ServiceWorkerVersionAttributes* attrs);
 
   int provider_id() const { return provider_id_; }
 
@@ -113,13 +115,13 @@
 
   const int provider_id_;
   scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner_;
-  scoped_refptr<ThreadSafeSender> thread_safe_sender_;
   // Mojo binding for the |request| passed to the constructor. This keeps the
   // connection to the content::ServiceWorkerProviderHost in the browser process
   // alive.
   mojo::AssociatedBinding<mojom::ServiceWorkerProvider> binding_;
 
-  // To dispatch events to the controller ServiceWorker.
+  // Only used for controllee contexts. Used to dispatch events to the
+  // controller ServiceWorker.
   mojom::ServiceWorkerEventDispatcherPtr event_dispatcher_;
 
   std::unique_ptr<Delegate> delegate_;
diff --git a/content/child/service_worker/service_worker_provider_context_unittest.cc b/content/child/service_worker/service_worker_provider_context_unittest.cc
new file mode 100644
index 0000000..0858fb2
--- /dev/null
+++ b/content/child/service_worker/service_worker_provider_context_unittest.cc
@@ -0,0 +1,125 @@
+// 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.
+
+#include "content/child/service_worker/service_worker_provider_context.h"
+
+#include "base/macros.h"
+#include "base/message_loop/message_loop.h"
+#include "content/child/service_worker/service_worker_dispatcher.h"
+#include "content/child/service_worker/service_worker_handle_reference.h"
+#include "content/child/service_worker/service_worker_provider_context.h"
+#include "content/child/service_worker/service_worker_registration_handle_reference.h"
+#include "content/child/service_worker/web_service_worker_impl.h"
+#include "content/child/service_worker/web_service_worker_registration_impl.h"
+#include "content/child/thread_safe_sender.h"
+#include "content/common/service_worker/service_worker_messages.h"
+#include "content/common/service_worker/service_worker_provider_interfaces.mojom.h"
+#include "content/common/service_worker/service_worker_types.h"
+#include "ipc/ipc_sync_message_filter.h"
+#include "ipc/ipc_test_sink.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+
+namespace {
+
+class ServiceWorkerTestSender : public ThreadSafeSender {
+ public:
+  explicit ServiceWorkerTestSender(IPC::TestSink* ipc_sink)
+      : ThreadSafeSender(nullptr, nullptr), ipc_sink_(ipc_sink) {}
+
+  bool Send(IPC::Message* message) override { return ipc_sink_->Send(message); }
+
+ private:
+  ~ServiceWorkerTestSender() override {}
+
+  IPC::TestSink* ipc_sink_;
+
+  DISALLOW_COPY_AND_ASSIGN(ServiceWorkerTestSender);
+};
+
+}  // namespace
+
+class ServiceWorkerProviderContextTest : public testing::Test {
+ public:
+  ServiceWorkerProviderContextTest() = default;
+
+  void SetUp() override {
+    sender_ = new ServiceWorkerTestSender(&ipc_sink_);
+    dispatcher_.reset(new ServiceWorkerDispatcher(sender_.get(), nullptr));
+  }
+
+  void CreateObjectInfoAndVersionAttributes(
+      ServiceWorkerRegistrationObjectInfo* info,
+      ServiceWorkerVersionAttributes* attrs) {
+    info->handle_id = 10;
+    info->registration_id = 20;
+
+    attrs->active.handle_id = 100;
+    attrs->active.version_id = 200;
+    attrs->waiting.handle_id = 101;
+    attrs->waiting.version_id = 201;
+    attrs->installing.handle_id = 102;
+    attrs->installing.version_id = 202;
+  }
+
+  ThreadSafeSender* thread_safe_sender() { return sender_.get(); }
+  IPC::TestSink* ipc_sink() { return &ipc_sink_; }
+  ServiceWorkerDispatcher* dispatcher() { return dispatcher_.get(); }
+
+ private:
+  base::MessageLoop message_loop_;
+  IPC::TestSink ipc_sink_;
+  std::unique_ptr<ServiceWorkerDispatcher> dispatcher_;
+  scoped_refptr<ServiceWorkerTestSender> sender_;
+
+  DISALLOW_COPY_AND_ASSIGN(ServiceWorkerProviderContextTest);
+};
+
+TEST_F(ServiceWorkerProviderContextTest, CreateForController) {
+  // Assume that these objects are passed from the browser process and own
+  // references to browser-side registration/worker representations.
+  ServiceWorkerRegistrationObjectInfo registration_info;
+  ServiceWorkerVersionAttributes version_attrs;
+  CreateObjectInfoAndVersionAttributes(&registration_info, &version_attrs);
+  std::unique_ptr<ServiceWorkerRegistrationHandleReference> registration =
+      ServiceWorkerRegistrationHandleReference::Adopt(registration_info,
+                                                      thread_safe_sender());
+  std::unique_ptr<ServiceWorkerHandleReference> installing =
+      ServiceWorkerHandleReference::Adopt(version_attrs.installing,
+                                          thread_safe_sender());
+  std::unique_ptr<ServiceWorkerHandleReference> waiting =
+      ServiceWorkerHandleReference::Adopt(version_attrs.waiting,
+                                          thread_safe_sender());
+  std::unique_ptr<ServiceWorkerHandleReference> active =
+      ServiceWorkerHandleReference::Adopt(version_attrs.active,
+                                          thread_safe_sender());
+
+  // Set up ServiceWorkerProviderContext for ServiceWorkerGlobalScope.
+  const int kProviderId = 10;
+  auto provider_context = base::MakeRefCounted<ServiceWorkerProviderContext>(
+      kProviderId, SERVICE_WORKER_PROVIDER_FOR_CONTROLLER,
+      mojom::ServiceWorkerProviderAssociatedRequest(), dispatcher());
+
+  // The passed references should be adopted and owned by the provider context.
+  provider_context->SetRegistration(std::move(registration),
+                                    std::move(installing), std::move(waiting),
+                                    std::move(active));
+  EXPECT_EQ(0UL, ipc_sink()->message_count());
+
+  // Destruction of the provider context should release references to the
+  // associated registration and its versions.
+  provider_context = nullptr;
+  ASSERT_EQ(4UL, ipc_sink()->message_count());
+  EXPECT_EQ(ServiceWorkerHostMsg_DecrementServiceWorkerRefCount::ID,
+            ipc_sink()->GetMessageAt(0)->type());
+  EXPECT_EQ(ServiceWorkerHostMsg_DecrementServiceWorkerRefCount::ID,
+            ipc_sink()->GetMessageAt(1)->type());
+  EXPECT_EQ(ServiceWorkerHostMsg_DecrementServiceWorkerRefCount::ID,
+            ipc_sink()->GetMessageAt(2)->type());
+  EXPECT_EQ(ServiceWorkerHostMsg_DecrementRegistrationRefCount::ID,
+            ipc_sink()->GetMessageAt(3)->type());
+}
+
+}  // namespace content
diff --git a/content/child/service_worker/service_worker_registration_handle_reference.h b/content/child/service_worker/service_worker_registration_handle_reference.h
index 8f638bb..0e149052 100644
--- a/content/child/service_worker/service_worker_registration_handle_reference.h
+++ b/content/child/service_worker/service_worker_registration_handle_reference.h
@@ -22,7 +22,7 @@
 // managed in the browser process. The constructor and destructor sends a
 // message to increment or decrement the reference count to the browser
 // process.
-class ServiceWorkerRegistrationHandleReference {
+class CONTENT_EXPORT ServiceWorkerRegistrationHandleReference {
  public:
   // Creates a new ServiceWorkerRegistrationHandleReference and increments
   // ref-count.
diff --git a/content/renderer/service_worker/service_worker_context_client.cc b/content/renderer/service_worker/service_worker_context_client.cc
index 879ca23..a0f1feac 100644
--- a/content/renderer/service_worker/service_worker_context_client.cc
+++ b/content/renderer/service_worker/service_worker_context_client.cc
@@ -604,7 +604,6 @@
       service_worker_version_id_(service_worker_version_id),
       service_worker_scope_(service_worker_scope),
       script_url_(script_url),
-      is_script_streaming_(is_script_streaming),
       sender_(ChildThreadImpl::current()->thread_safe_sender()),
       main_thread_task_runner_(base::ThreadTaskRunnerHandle::Get()),
       proxy_(nullptr),
@@ -622,13 +621,9 @@
   TRACE_EVENT_NESTABLE_ASYNC_BEGIN1("ServiceWorker",
                                     "ServiceWorkerContextClient", this,
                                     "script_url", script_url_.spec());
-  if (is_script_streaming_) {
-    TRACE_EVENT_NESTABLE_ASYNC_BEGIN0("ServiceWorker", "START_WORKER_THREAD",
-                                      this);
-  } else {
-    TRACE_EVENT_NESTABLE_ASYNC_BEGIN1("ServiceWorker", "LOAD_SCRIPT", this,
-                                      "Type", "ResourceLoader");
-  }
+  TRACE_EVENT_NESTABLE_ASYNC_BEGIN1(
+      "ServiceWorker", "LOAD_SCRIPT", this, "Source",
+      (is_script_streaming ? "InstalledScriptsManager" : "ResourceLoader"));
 }
 
 ServiceWorkerContextClient::~ServiceWorkerContextClient() {}
@@ -734,16 +729,8 @@
 void ServiceWorkerContextClient::WorkerScriptLoaded() {
   (*instance_host_)->OnScriptLoaded();
   TRACE_EVENT_NESTABLE_ASYNC_END0("ServiceWorker", "LOAD_SCRIPT", this);
-  if (is_script_streaming_) {
-    TRACE_EVENT_NESTABLE_ASYNC_BEGIN0("ServiceWorker", "EVALUATE_SCRIPT", this);
-  } else {
-    TRACE_EVENT_NESTABLE_ASYNC_BEGIN0("ServiceWorker", "START_WORKER_THREAD",
-                                      this);
-  }
-}
-
-bool ServiceWorkerContextClient::HasAssociatedRegistration() {
-  return provider_context_ && provider_context_->HasAssociatedRegistration();
+  TRACE_EVENT_NESTABLE_ASYNC_BEGIN0("ServiceWorker", "START_WORKER_CONTEXT",
+                                    this);
 }
 
 void ServiceWorkerContextClient::WorkerContextStarted(
@@ -765,8 +752,7 @@
 
   ServiceWorkerRegistrationObjectInfo registration_info;
   ServiceWorkerVersionAttributes version_attrs;
-  provider_context_->GetAssociatedRegistration(&registration_info,
-                                               &version_attrs);
+  provider_context_->GetRegistration(&registration_info, &version_attrs);
   DCHECK_NE(registration_info.registration_id,
             kInvalidServiceWorkerRegistrationId);
 
@@ -779,13 +765,9 @@
 
   (*instance_host_)->OnThreadStarted(WorkerThread::GetCurrentId());
 
-  TRACE_EVENT_NESTABLE_ASYNC_END0("ServiceWorker", "START_WORKER_THREAD", this);
-  if (is_script_streaming_) {
-    TRACE_EVENT_NESTABLE_ASYNC_BEGIN1("ServiceWorker", "LOAD_SCRIPT", this,
-                                      "Type", "InstalledScriptsManager");
-  } else {
-    TRACE_EVENT_NESTABLE_ASYNC_BEGIN0("ServiceWorker", "EVALUATE_SCRIPT", this);
-  }
+  TRACE_EVENT_NESTABLE_ASYNC_END0("ServiceWorker", "START_WORKER_CONTEXT",
+                                  this);
+  TRACE_EVENT_NESTABLE_ASYNC_BEGIN0("ServiceWorker", "EVALUATE_SCRIPT", this);
 }
 
 void ServiceWorkerContextClient::DidEvaluateWorkerScript(bool success) {
diff --git a/content/renderer/service_worker/service_worker_context_client.h b/content/renderer/service_worker/service_worker_context_client.h
index 897f2ca..91e9bdf5 100644
--- a/content/renderer/service_worker/service_worker_context_client.h
+++ b/content/renderer/service_worker/service_worker_context_client.h
@@ -135,7 +135,6 @@
   void ClearCachedMetadata(const blink::WebURL&) override;
   void WorkerReadyForInspection() override;
   void WorkerContextFailedToStart() override;
-  bool HasAssociatedRegistration() override;
   void WorkerScriptLoaded() override;
   void WorkerContextStarted(
       blink::WebServiceWorkerContextProxy* proxy) override;
@@ -369,10 +368,6 @@
   const GURL service_worker_scope_;
   const GURL script_url_;
 
-  // True if the scripts for the worker are installed and its scripts are
-  // streamed from the browser process instead of ResourceLoader.
-  const bool is_script_streaming_;
-
   scoped_refptr<ThreadSafeSender> sender_;
   scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner_;
   scoped_refptr<base::TaskRunner> worker_task_runner_;
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn
index c5bbeaea..9efc433 100644
--- a/content/test/BUILD.gn
+++ b/content/test/BUILD.gn
@@ -1391,6 +1391,7 @@
     "../child/notifications/notification_data_conversions_unittest.cc",
     "../child/resource_dispatcher_unittest.cc",
     "../child/service_worker/service_worker_dispatcher_unittest.cc",
+    "../child/service_worker/service_worker_provider_context_unittest.cc",
     "../child/shared_memory_data_consumer_handle_unittest.cc",
     "../child/shared_memory_received_data_factory_unittest.cc",
     "../child/site_isolation_stats_gatherer_unittest.cc",
diff --git a/pdf/pdfium/fuzzers/BUILD.gn b/pdf/pdfium/fuzzers/BUILD.gn
index d348751b..118e9cc 100644
--- a/pdf/pdfium/fuzzers/BUILD.gn
+++ b/pdf/pdfium/fuzzers/BUILD.gn
@@ -28,7 +28,7 @@
     "//v8:external_startup_data",
   ]
   dict = "dicts/pdf.dict"
-  seed_corpus = "src/third_party/pdfium/test"
+  seed_corpus = "//third_party/pdfium/test"
 }
 
 fuzzer_test("pdf_cmap_fuzzer") {
@@ -145,7 +145,7 @@
     dict = "dicts/pdf_codec_png.dict"
     seed_corpuses = [
       "corpora/pdf_codec_png",
-      "//cc/test/data",
+      "//components/viz/test/data",
       "//third_party/WebKit/LayoutTests/images/png-suite/samples",
       "//third_party/WebKit/LayoutTests/images/resources/pngfuzz",
     ]
diff --git a/remoting/android/java/AndroidManifest.xml.jinja2 b/remoting/android/java/AndroidManifest.xml.jinja2
index 4fd0b3f..67cc7431 100644
--- a/remoting/android/java/AndroidManifest.xml.jinja2
+++ b/remoting/android/java/AndroidManifest.xml.jinja2
@@ -13,9 +13,6 @@
             android:allowBackup="false"
             android:resizeableActivity="true"
             android:supportsPictureInPicture="false">
-        <meta-data
-                android:name="com.google.android.gms.version"
-                android:value="@integer/google_play_services_version"/>
         <activity
             android:name="org.chromium.chromoting.Chromoting"
             android:configChanges="orientation|screenSize"
diff --git a/testing/libfuzzer/archive_corpus.py b/testing/libfuzzer/archive_corpus.py
index 9d3bf93..a3fd29f 100755
--- a/testing/libfuzzer/archive_corpus.py
+++ b/testing/libfuzzer/archive_corpus.py
@@ -28,6 +28,9 @@
   corpus_files = []
 
   for directory in args.corpus_directories:
+    if not os.path.exists(directory):
+      raise Exception('The given seed_corpus directory (%s) does not exist.' %
+                      directory)
     for (dirpath, _, filenames) in os.walk(directory):
       for filename in filenames:
         full_filename = os.path.join(dirpath, filename)
diff --git a/testing/libfuzzer/efficient_fuzzer.md b/testing/libfuzzer/efficient_fuzzer.md
index b14c7c0..01d34c45 100644
--- a/testing/libfuzzer/efficient_fuzzer.md
+++ b/testing/libfuzzer/efficient_fuzzer.md
@@ -53,7 +53,7 @@
 ```
 fuzzer_test("my_protocol_fuzzer") {
   ...
-  seed_corpus = "src/fuzz/testcases"
+  seed_corpus = "test/fuzz/testcases"
   ...
 }
 ```
@@ -63,7 +63,7 @@
 ```
 fuzzer_test("my_protocol_fuzzer") {
   ...
-  seed_corpuses = [ "src/fuzz/testcases", "src/unittest/data" ]
+  seed_corpuses = [ "test/fuzz/testcases", "test/unittest/data" ]
   ...
 }
 ```
diff --git a/testing/libfuzzer/fuzzers/BUILD.gn b/testing/libfuzzer/fuzzers/BUILD.gn
index 4fa3fca..4c39576 100644
--- a/testing/libfuzzer/fuzzers/BUILD.gn
+++ b/testing/libfuzzer/fuzzers/BUILD.gn
@@ -167,7 +167,7 @@
 }
 
 libpng_seed_corpuses = [
-  "//cc/test/data",
+  "//components/viz/test/data",
   "//third_party/WebKit/LayoutTests/images/png-suite/samples",
   "//third_party/WebKit/LayoutTests/images/resources/pngfuzz",
 ]
diff --git a/third_party/WebKit/LayoutTests/editing/assert_selection.html b/third_party/WebKit/LayoutTests/editing/assert_selection.html
index 1c8d757..c66e881e 100644
--- a/third_party/WebKit/LayoutTests/editing/assert_selection.html
+++ b/third_party/WebKit/LayoutTests/editing/assert_selection.html
@@ -147,7 +147,7 @@
             '<b id="abc">abc</b>',
             '<b id="def">def</b>',
         '</div>',
-    ].join(''),
+    ],
     selection => {
       const document = selection.document;
       const host = document.getElementById('host');
diff --git a/third_party/WebKit/LayoutTests/editing/assert_selection.js b/third_party/WebKit/LayoutTests/editing/assert_selection.js
index f9551de..dd110cc 100644
--- a/third_party/WebKit/LayoutTests/editing/assert_selection.js
+++ b/third_party/WebKit/LayoutTests/editing/assert_selection.js
@@ -893,14 +893,14 @@
 }
 
 /**
- * @param {string} inputText
+ * @param {string} passedInputText
  * @param {function(!Selection)|string}
  * @param {string} expectedText
  * @param {Object=} opt_options
  * @return {!Sample}
  */
 function assertSelection(
-    inputText, tester, expectedText, opt_options = {}) {
+    passedInputText, tester, expectedText, opt_options = {}) {
   const kDescription = 'description';
   const kDumpAs = 'dumpAs';
   const kRemoveSampleIfSucceeded = 'removeSampleIfSucceeded';
@@ -919,6 +919,14 @@
   /** @type {boolean} */
   const dumpFromRoot = options[kDumpFromRoot] || false;
 
+  const inputText = (() => {
+    if (typeof(passedInputText) === 'string')
+      return passedInputText;
+    if (Array.isArray(passedInputText))
+      return passedInputText.join("");
+    throw new Error('InputText must be a string or an array of strings.');
+  })();
+
   checkExpectedText(expectedText);
   const sample = new Sample(inputText);
   if (typeof(tester) === 'function') {
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/syntax/serializing-html-fragments/serializing-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/html/syntax/serializing-html-fragments/serializing-expected.txt
index d32e2b9..6dd7c0f 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/html/syntax/serializing-html-fragments/serializing-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/html/syntax/serializing-html-fragments/serializing-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 234 tests; 220 PASS, 14 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 234 tests; 222 PASS, 12 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS innerHTML 0  
 PASS innerHTML 1 <a></a> 
 PASS innerHTML 2 <a b="c"></a> 
@@ -58,13 +58,13 @@
 FAIL innerHTML Attribute in the XML namespace with the prefix not set to xml: assert_equals: expected "<svg xml:foo=\"test\"></svg>" but got "<svg abc:foo=\"test\"></svg>"
 PASS innerHTML Non-'xmlns' attribute in the xmlns namespace 
 PASS innerHTML 'xmlns' attribute in the xmlns namespace 
-FAIL innerHTML Attribute in non-standard namespace assert_equals: expected "<svg abc:def=\"test\"></svg>" but got "<svg def=\"test\"></svg>"
+PASS innerHTML Attribute in non-standard namespace 
 PASS innerHTML <span> starting with U+000A 
 PASS outerHTML Attribute in the XML namespace 
 FAIL outerHTML Attribute in the XML namespace with the prefix not set to xml: assert_equals: expected "<span><svg xml:foo=\"test\"></svg></span>" but got "<span><svg abc:foo=\"test\"></svg></span>"
 PASS outerHTML Non-'xmlns' attribute in the xmlns namespace 
 PASS outerHTML 'xmlns' attribute in the xmlns namespace 
-FAIL outerHTML Attribute in non-standard namespace assert_equals: expected "<span><svg abc:def=\"test\"></svg></span>" but got "<span><svg def=\"test\"></svg></span>"
+PASS outerHTML Attribute in non-standard namespace 
 PASS outerHTML <span> starting with U+000A 
 PASS innerHTML <pre> context starting with U+000A 
 PASS innerHTML <textarea> context starting with U+000A 
diff --git a/third_party/WebKit/Source/core/editing/LayoutSelection.cpp b/third_party/WebKit/Source/core/editing/LayoutSelection.cpp
index b08f574..b93ed45c 100644
--- a/third_party/WebKit/Source/core/editing/LayoutSelection.cpp
+++ b/third_party/WebKit/Source/core/editing/LayoutSelection.cpp
@@ -129,12 +129,6 @@
   return SelectionMode::kBlockCursor;
 }
 
-static PositionInFlatTree FindFirstVisiblePosition(
-    const PositionInFlatTree& start) {
-  return MostForwardCaretPosition(
-      CreateVisiblePosition(start).DeepEquivalent());
-}
-
 static PositionInFlatTree FindLastVisiblePosition(
     const PositionInFlatTree& end) {
   return MostBackwardCaretPosition(CreateVisiblePosition(end).DeepEquivalent());
@@ -391,40 +385,51 @@
 
   // Find first/last LayoutObject and its offset.
   // TODO(yoichio): Find LayoutObject w/o canonicalization.
-  const PositionInFlatTree& start_pos =
-      FindFirstVisiblePosition(selection.StartPosition());
   const PositionInFlatTree& end_pos =
       FindLastVisiblePosition(selection.EndPosition());
-  if (start_pos.IsNull() || end_pos.IsNull())
+  if (end_pos.IsNull())
     return {};
   // This case happens if we have
   // <div>foo<div style="visibility:hidden">^bar|</div>baz</div>.
-  if (start_pos >= end_pos)
+  if (selection.StartPosition() >= end_pos)
     return {};
 
-  LayoutObject* const start_layout_object =
-      start_pos.AnchorNode()->GetLayoutObject();
   LayoutObject* const end_layout_object =
       end_pos.AnchorNode()->GetLayoutObject();
-  DCHECK(start_layout_object);
   DCHECK(end_layout_object);
-  DCHECK(start_layout_object->View() == end_layout_object->View());
-  if (!start_layout_object || !end_layout_object)
+  if (!end_layout_object)
     return {};
 
   // Marking and collect invalidation candidate LayoutObjects.
+  LayoutObject* start_layout_object = nullptr;
+  int start_editing_offset = 0;
   PaintInvalidationSet invalidation_set;
   for (const Node& node :
-       EphemeralRangeInFlatTree(start_pos, end_pos).Nodes()) {
+       EphemeralRangeInFlatTree(selection.StartPosition(), end_pos).Nodes()) {
     LayoutObject* const layout_object = node.GetLayoutObject();
-    if (!layout_object || layout_object == start_layout_object ||
-        layout_object == end_layout_object ||
-        !layout_object->CanBeSelectionLeaf())
+    if (!layout_object || !layout_object->CanBeSelectionLeaf() ||
+        layout_object->Style()->Visibility() != EVisibility::kVisible)
+      continue;
+
+    if (!start_layout_object) {
+      start_layout_object = layout_object;
+      const PositionInFlatTree& offsetInAnchor =
+          selection.StartPosition().ToOffsetInAnchor();
+      if (node == offsetInAnchor.AnchorNode())
+        start_editing_offset = offsetInAnchor.OffsetInContainerNode();
+      continue;
+    }
+
+    if (layout_object == end_layout_object)
       continue;
     layout_object->SetSelectionStateIfNeeded(SelectionState::kInside);
     InsertLayoutObjectAndAncestorBlocks(&invalidation_set, layout_object);
   }
 
+  // No valid LayOutObject found.
+  if (!start_layout_object)
+    return {};
+
   if (start_layout_object == end_layout_object) {
     start_layout_object->SetSelectionStateIfNeeded(
         SelectionState::kStartAndEnd);
@@ -444,9 +449,8 @@
   DCHECK(end_layout_object->GetSelectionState() == SelectionState::kEnd ||
          end_layout_object->GetSelectionState() ==
              SelectionState::kStartAndEnd);
-  return {start_layout_object, start_pos.ComputeEditingOffset(),
-          end_layout_object, end_pos.ComputeEditingOffset(),
-          std::move(invalidation_set)};
+  return {start_layout_object, start_editing_offset, end_layout_object,
+          end_pos.ComputeEditingOffset(), std::move(invalidation_set)};
 }
 
 void LayoutSelection::SetHasPendingSelection() {
diff --git a/third_party/WebKit/Source/core/editing/serializers/MarkupFormatter.cpp b/third_party/WebKit/Source/core/editing/serializers/MarkupFormatter.cpp
index 7c40a15..47a698f1 100644
--- a/third_party/WebKit/Source/core/editing/serializers/MarkupFormatter.cpp
+++ b/third_party/WebKit/Source/core/editing/serializers/MarkupFormatter.cpp
@@ -365,7 +365,7 @@
   QualifiedName prefixed_name = attribute.GetName();
   if (document_is_html && !AttributeIsInSerializedNamespace(attribute)) {
     result.Append(' ');
-    result.Append(attribute.GetName().LocalName());
+    result.Append(prefixed_name.ToString());
   } else {
     if (attribute.NamespaceURI() == XMLNSNames::xmlnsNamespaceURI) {
       if (!attribute.Prefix() && attribute.LocalName() != g_xmlns_atom)
diff --git a/third_party/WebKit/Source/core/frame/LocalFrameView.h b/third_party/WebKit/Source/core/frame/LocalFrameView.h
index 468943db6..940304c 100644
--- a/third_party/WebKit/Source/core/frame/LocalFrameView.h
+++ b/third_party/WebKit/Source/core/frame/LocalFrameView.h
@@ -706,7 +706,10 @@
   TransformPaintPropertyNode* PreTranslation() const {
     return pre_translation_.Get();
   }
-
+  void SetScrollNode(RefPtr<ScrollPaintPropertyNode> scroll_node) {
+    scroll_node_ = std::move(scroll_node);
+  }
+  ScrollPaintPropertyNode* ScrollNode() const { return scroll_node_.Get(); }
   void SetScrollTranslation(
       RefPtr<TransformPaintPropertyNode> scroll_translation) {
     scroll_translation_ = std::move(scroll_translation);
@@ -714,7 +717,6 @@
   TransformPaintPropertyNode* ScrollTranslation() const {
     return scroll_translation_.Get();
   }
-
   void SetContentClip(RefPtr<ClipPaintPropertyNode> content_clip) {
     content_clip_ = std::move(content_clip);
   }
@@ -1162,6 +1164,7 @@
   // enabled.
   RefPtr<TransformPaintPropertyNode> pre_translation_;
   RefPtr<TransformPaintPropertyNode> scroll_translation_;
+  RefPtr<ScrollPaintPropertyNode> scroll_node_;
   // The content clip clips the document (= LayoutView) but not the scrollbars.
   // TODO(trchen): This will not be needed once settings->rootLayerScrolls() is
   // enabled.
diff --git a/third_party/WebKit/Source/core/html/HTMLOptionsCollection.idl b/third_party/WebKit/Source/core/html/HTMLOptionsCollection.idl
index bbbd08c..5948567 100644
--- a/third_party/WebKit/Source/core/html/HTMLOptionsCollection.idl
+++ b/third_party/WebKit/Source/core/html/HTMLOptionsCollection.idl
@@ -35,8 +35,7 @@
     // TODO(tkent): We need to declare this indexed property getter because our
     // IDL compiler doesn't support inheritance of indexed property
     // getters. crbug.com/752877
-    // TODO(tkent): This getter should return Element.
-    [ImplementedAs=item] getter Node (unsigned long index);
+    [ImplementedAs=item] getter Element? (unsigned long index);
 
     // TODO(tkent): This should return only Element. crbug.com/695902
     [ImplementedAs=namedGetter] getter (NodeList or Element)? namedItem(DOMString name);
diff --git a/third_party/WebKit/Source/core/layout/ng/README.md b/third_party/WebKit/Source/core/layout/ng/README.md
index 8dd6c3b..08ea583 100644
--- a/third_party/WebKit/Source/core/layout/ng/README.md
+++ b/third_party/WebKit/Source/core/layout/ng/README.md
@@ -116,3 +116,14 @@
 `chromium\src>node lcov-result-merger\bin\lcov-result-merger.js *.info output.info`
 * Generate the coverage html from the master lcov file
 `chromium\src>C:\Perl64\bin\perl.exe dynamorio.git\third_party\lcov\genhtml output.info -o output`
+
+### Debugging ###
+Both layout input node subtrees and layout output physical fragment subtrees
+may be dumped to stderr, for debugging purposes.
+
+#### For layout input node subtree ####
+Call NGLayoutInputNode::ShowNodeTree().
+
+#### For physical fragment subtree ####
+Call NGPhysicalFragment::ShowFragmentTree(). Fragments in the subtree are not
+required to be marked as placed (i.e. know their offset).
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_physical_fragment.cc b/third_party/WebKit/Source/core/layout/ng/ng_physical_fragment.cc
index 5ca8d14..5c33430 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_physical_fragment.cc
+++ b/third_party/WebKit/Source/core/layout/ng/ng_physical_fragment.cc
@@ -12,6 +12,74 @@
 #include "core/layout/ng/ng_unpositioned_float.h"
 
 namespace blink {
+namespace {
+
+#ifndef NDEBUG
+void AppendFragmentOffsetAndSize(const NGPhysicalFragment* fragment,
+                                 StringBuilder* string_builder) {
+  string_builder->Append("offset:");
+  if (fragment->IsPlaced())
+    string_builder->Append(fragment->Offset().ToString());
+  else
+    string_builder->Append("unplaced");
+  string_builder->Append(" size:");
+  string_builder->Append(fragment->Size().ToString());
+}
+
+void AppendFragmentToString(const NGPhysicalFragment* fragment,
+                            StringBuilder* string_builder,
+                            unsigned indent = 2) {
+  for (unsigned i = 0; i < indent; i++)
+    string_builder->Append(" ");
+
+  if (fragment->IsBox()) {
+    string_builder->Append("PhysicalBoxFragment ");
+    AppendFragmentOffsetAndSize(fragment, string_builder);
+
+    const auto* box = ToNGPhysicalBoxFragment(fragment);
+    string_builder->Append(" overflow:");
+    string_builder->Append(box->OverflowSize().ToString());
+    string_builder->Append("\n");
+
+    const auto& children = box->Children();
+    for (unsigned i = 0; i < children.size(); i++)
+      AppendFragmentToString(children[i].Get(), string_builder, indent + 2);
+    return;
+  }
+
+  if (fragment->IsLineBox()) {
+    string_builder->Append("NGPhysicalLineBoxFragment ");
+    AppendFragmentOffsetAndSize(fragment, string_builder);
+
+    const auto* line_box = ToNGPhysicalLineBoxFragment(fragment);
+    string_builder->Append("\n");
+
+    const auto& children = line_box->Children();
+    for (unsigned i = 0; i < children.size(); i++)
+      AppendFragmentToString(children[i].Get(), string_builder, indent + 2);
+    return;
+  }
+
+  if (fragment->IsText()) {
+    string_builder->Append("PhysicalTextFragment ");
+    AppendFragmentOffsetAndSize(fragment, string_builder);
+
+    const auto* text = ToNGPhysicalTextFragment(fragment);
+    string_builder->Append(" start: ");
+    string_builder->Append(String::Format("%u", text->StartOffset()));
+    string_builder->Append(" end: ");
+    string_builder->Append(String::Format("%u", text->EndOffset()));
+    string_builder->Append("\n");
+    return;
+  }
+
+  string_builder->Append("Unknown fragment type ");
+  AppendFragmentOffsetAndSize(fragment, string_builder);
+  string_builder->Append("\n");
+}
+#endif  // !NDEBUG
+
+}  // namespace
 
 NGPhysicalFragment::NGPhysicalFragment(LayoutObject* layout_object,
                                        const ComputedStyle& style,
@@ -88,4 +156,13 @@
                         Offset().ToString().Ascii().data(), IsPlaced());
 }
 
+#ifndef NDEBUG
+void NGPhysicalFragment::ShowFragmentTree() const {
+  StringBuilder string_builder;
+  string_builder.Append(".:: LayoutNG Physical Fragment Tree ::.\n");
+  AppendFragmentToString(this, &string_builder);
+  fprintf(stderr, "%s\n", string_builder.ToString().Utf8().data());
+}
+#endif  // !NDEBUG
+
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_physical_fragment.h b/third_party/WebKit/Source/core/layout/ng/ng_physical_fragment.h
index c3e4465c..c0785fa 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_physical_fragment.h
+++ b/third_party/WebKit/Source/core/layout/ng/ng_physical_fragment.h
@@ -85,6 +85,10 @@
 
   String ToString() const;
 
+#ifndef NDEBUG
+  void ShowFragmentTree() const;
+#endif
+
   // Override RefCounted's deref() to ensure operator delete is called on the
   // appropriate subclass type.
   void Deref() const {
diff --git a/third_party/WebKit/Source/core/paint/FindPropertiesNeedingUpdate.h b/third_party/WebKit/Source/core/paint/FindPropertiesNeedingUpdate.h
index d6791a6..dc083da7 100644
--- a/third_party/WebKit/Source/core/paint/FindPropertiesNeedingUpdate.h
+++ b/third_party/WebKit/Source/core/paint/FindPropertiesNeedingUpdate.h
@@ -66,6 +66,8 @@
       original_pre_translation_ = pre_translation->Clone();
     if (auto* content_clip = frame_view_->ContentClip())
       original_content_clip_ = content_clip->Clone();
+    if (auto* scroll_node = frame_view_->ScrollNode())
+      original_scroll_node_ = scroll_node->Clone();
     if (auto* scroll_translation = frame_view_->ScrollTranslation())
       original_scroll_translation_ = scroll_translation->Clone();
   }
@@ -85,6 +87,8 @@
                                  frame_view_->PreTranslation());
     DCHECK_FRAMEVIEW_PROPERTY_EQ(original_content_clip_,
                                  frame_view_->ContentClip());
+    DCHECK_FRAMEVIEW_PROPERTY_EQ(original_scroll_node_,
+                                 frame_view_->ScrollNode());
     DCHECK_FRAMEVIEW_PROPERTY_EQ(original_scroll_translation_,
                                  frame_view_->ScrollTranslation());
 
@@ -98,6 +102,7 @@
   bool needed_forced_subtree_update_;
   RefPtr<const TransformPaintPropertyNode> original_pre_translation_;
   RefPtr<const ClipPaintPropertyNode> original_content_clip_;
+  RefPtr<const ScrollPaintPropertyNode> original_scroll_node_;
   RefPtr<const TransformPaintPropertyNode> original_scroll_translation_;
 };
 
@@ -184,6 +189,8 @@
       DCHECK_OBJECT_PROPERTY_EQ(
           object_, original_properties_->SvgLocalToBorderBoxTransform(),
           object_properties->SvgLocalToBorderBoxTransform());
+      DCHECK_OBJECT_PROPERTY_EQ(object_, original_properties_->Scroll(),
+                                object_properties->Scroll());
       DCHECK_OBJECT_PROPERTY_EQ(object_,
                                 original_properties_->ScrollTranslation(),
                                 object_properties->ScrollTranslation());
diff --git a/third_party/WebKit/Source/core/paint/ObjectPaintProperties.h b/third_party/WebKit/Source/core/paint/ObjectPaintProperties.h
index 5051118..7cad67d1 100644
--- a/third_party/WebKit/Source/core/paint/ObjectPaintProperties.h
+++ b/third_party/WebKit/Source/core/paint/ObjectPaintProperties.h
@@ -76,6 +76,7 @@
   const TransformPaintPropertyNode* SvgLocalToBorderBoxTransform() const {
     return svg_local_to_border_box_transform_.Get();
   }
+  const ScrollPaintPropertyNode* Scroll() const { return scroll_.Get(); }
   const TransformPaintPropertyNode* ScrollTranslation() const {
     return scroll_translation_.Get();
   }
@@ -159,6 +160,7 @@
   bool ClearSvgLocalToBorderBoxTransform() {
     return Clear(svg_local_to_border_box_transform_);
   }
+  bool ClearScroll() { return Clear(scroll_); }
   bool ClearScrollTranslation() { return Clear(scroll_translation_); }
   bool ClearScrollbarPaintOffset() { return Clear(scrollbar_paint_offset_); }
 
@@ -195,19 +197,15 @@
                   std::forward<Args>(args)...);
   }
   template <typename... Args>
+  UpdateResult UpdateScroll(Args&&... args) {
+    return Update(scroll_, std::forward<Args>(args)...);
+  }
+  template <typename... Args>
   UpdateResult UpdateScrollTranslation(Args&&... args) {
     DCHECK(!SvgLocalToBorderBoxTransform())
         << "SVG elements cannot scroll so there should never be both a scroll "
            "translation and an SVG local to border box transform.";
-    if (scroll_translation_) {
-      return scroll_translation_->UpdateScrollTranslation(
-                 std::forward<Args>(args)...)
-                 ? UpdateResult::kValueChanged
-                 : UpdateResult::kUnchanged;
-    }
-    scroll_translation_ = TransformPaintPropertyNode::CreateScrollTranslation(
-        std::forward<Args>(args)...);
-    return UpdateResult::kNewNodeCreated;
+    return Update(scroll_translation_, std::forward<Args>(args)...);
   }
   template <typename... Args>
   UpdateResult UpdateScrollbarPaintOffset(Args&&... args) {
@@ -276,6 +274,8 @@
       cloned->svg_local_to_border_box_transform_ =
           svg_local_to_border_box_transform_->Clone();
     }
+    if (scroll_)
+      cloned->scroll_ = scroll_->Clone();
     if (scroll_translation_)
       cloned->scroll_translation_ = scroll_translation_->Clone();
     if (scrollbar_paint_offset_)
@@ -328,6 +328,7 @@
   RefPtr<TransformPaintPropertyNode> perspective_;
   // TODO(pdr): Only LayoutSVGRoot needs this and it should be moved there.
   RefPtr<TransformPaintPropertyNode> svg_local_to_border_box_transform_;
+  RefPtr<ScrollPaintPropertyNode> scroll_;
   RefPtr<TransformPaintPropertyNode> scroll_translation_;
   RefPtr<TransformPaintPropertyNode> scrollbar_paint_offset_;
 };
diff --git a/third_party/WebKit/Source/core/paint/PaintControllerPaintTest.cpp b/third_party/WebKit/Source/core/paint/PaintControllerPaintTest.cpp
index 02fdf8e..c474094e 100644
--- a/third_party/WebKit/Source/core/paint/PaintControllerPaintTest.cpp
+++ b/third_party/WebKit/Source/core/paint/PaintControllerPaintTest.cpp
@@ -135,8 +135,8 @@
 
   // Verify that the background does not scroll.
   const PaintChunk& background_chunk = RootPaintController().PaintChunks()[0];
-  EXPECT_FALSE(background_chunk.properties.property_tree_state.Transform()
-                   ->IsScrollTranslation());
+  auto* transform = background_chunk.properties.property_tree_state.Transform();
+  EXPECT_EQ(nullptr, transform->ScrollNode());
 
   const EffectPaintPropertyNode* effect_node =
       div.FirstFragment()->PaintProperties()->Effect();
diff --git a/third_party/WebKit/Source/core/paint/PaintInvalidator.cpp b/third_party/WebKit/Source/core/paint/PaintInvalidator.cpp
index 971ab59..da97738 100644
--- a/third_party/WebKit/Source/core/paint/PaintInvalidator.cpp
+++ b/third_party/WebKit/Source/core/paint/PaintInvalidator.cpp
@@ -268,12 +268,14 @@
         saved_context_(tree_builder_context_.current) {
     DCHECK(!RuntimeEnabledFeatures::RootLayerScrollingEnabled());
 
+    if (const auto* scroll_node = frame_view.ScrollNode()) {
+      DCHECK_EQ(scroll_node, saved_context_.scroll);
+      tree_builder_context_.current.scroll = saved_context_.scroll->Parent();
+    }
     if (const auto* scroll_translation = frame_view.ScrollTranslation()) {
       DCHECK_EQ(scroll_translation, saved_context_.transform);
-      DCHECK_EQ(scroll_translation->ScrollNode(), saved_context_.scroll);
       tree_builder_context_.current.transform =
           saved_context_.transform->Parent();
-      tree_builder_context_.current.scroll = saved_context_.scroll->Parent();
     }
     DCHECK_EQ(frame_view.PreTranslation(),
               tree_builder_context_.current.transform);
diff --git a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp
index 3c8a7d884..43ccd2a 100644
--- a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp
+++ b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp
@@ -78,12 +78,9 @@
 
 // True if a new property was created or a main thread scrolling reason changed
 // (which can affect descendants), false if an existing one was updated.
-static bool UpdateScrollTranslation(
+static bool UpdateScroll(
     LocalFrameView& frame_view,
-    RefPtr<const TransformPaintPropertyNode> parent,
-    const TransformationMatrix& matrix,
-    const FloatPoint3D& origin,
-    RefPtr<const ScrollPaintPropertyNode> scroll_parent,
+    RefPtr<const ScrollPaintPropertyNode> parent,
     const IntSize& clip,
     const IntSize& bounds,
     bool user_scrollable_horizontal,
@@ -91,26 +88,41 @@
     MainThreadScrollingReasons main_thread_scrolling_reasons,
     WebLayerScrollClient* scroll_client) {
   DCHECK(!RuntimeEnabledFeatures::RootLayerScrollingEnabled());
-  // TODO(pdr): Set the correct compositing reasons here.
   auto element_id = CompositorElementIdFromLayoutObjectId(
       frame_view.GetLayoutView()->UniqueId(),
       CompositorElementIdNamespace::kScrollTranslation);
-  if (auto* existing_scroll_translation = frame_view.ScrollTranslation()) {
-    auto existing_reasons = existing_scroll_translation->ScrollNode()
-                                ->GetMainThreadScrollingReasons();
-    existing_scroll_translation->UpdateScrollTranslation(
-        std::move(parent), matrix, origin, false, 0, kCompositingReasonNone,
-        std::move(scroll_parent), IntPoint(), clip, bounds,
-        user_scrollable_horizontal, user_scrollable_vertical,
-        main_thread_scrolling_reasons, element_id, scroll_client);
+  if (auto* existing_scroll = frame_view.ScrollNode()) {
+    auto existing_reasons = existing_scroll->GetMainThreadScrollingReasons();
+    existing_scroll->Update(
+        std::move(parent), IntPoint(), clip, bounds, user_scrollable_horizontal,
+        user_scrollable_vertical, main_thread_scrolling_reasons, element_id,
+        scroll_client);
     return existing_reasons != main_thread_scrolling_reasons;
   }
-  frame_view.SetScrollTranslation(
-      TransformPaintPropertyNode::CreateScrollTranslation(
-          std::move(parent), matrix, origin, false, 0, kCompositingReasonNone,
-          std::move(scroll_parent), IntPoint(), clip, bounds,
-          user_scrollable_horizontal, user_scrollable_vertical,
-          main_thread_scrolling_reasons, element_id, scroll_client));
+  frame_view.SetScrollNode(ScrollPaintPropertyNode::Create(
+      std::move(parent), IntPoint(), clip, bounds, user_scrollable_horizontal,
+      user_scrollable_vertical, main_thread_scrolling_reasons, element_id,
+      scroll_client));
+  return true;
+}
+
+// True if a new property was created, false if an existing one was updated.
+static bool UpdateScrollTranslation(
+    LocalFrameView& frame_view,
+    RefPtr<const TransformPaintPropertyNode> parent,
+    const TransformationMatrix& matrix,
+    PassRefPtr<ScrollPaintPropertyNode> scroll) {
+  DCHECK(!RuntimeEnabledFeatures::RootLayerScrollingEnabled());
+  // TODO(pdr): Set the correct compositing reasons here.
+  if (auto* existing_scroll_translation = frame_view.ScrollTranslation()) {
+    existing_scroll_translation->Update(
+        std::move(parent), matrix, FloatPoint3D(), false, 0,
+        kCompositingReasonNone, CompositorElementId(), std::move(scroll));
+    return false;
+  }
+  frame_view.SetScrollTranslation(TransformPaintPropertyNode::Create(
+      std::move(parent), matrix, FloatPoint3D(), false, 0,
+      kCompositingReasonNone, CompositorElementId(), std::move(scroll)));
   return true;
 }
 
@@ -166,11 +178,7 @@
         frame_view, context.current.clip, frame_view.PreTranslation(),
         content_clip, full_context.clip_changed);
 
-    ScrollOffset scroll_offset = frame_view.GetScrollOffset();
-    if (frame_view.IsScrollable() || !scroll_offset.IsZero()) {
-      TransformationMatrix frame_scroll;
-      frame_scroll.Translate(-scroll_offset.Width(), -scroll_offset.Height());
-
+    if (frame_view.IsScrollable()) {
       IntSize scroll_clip = frame_view.VisibleContentSize();
       IntSize scroll_bounds = frame_view.ContentsSize();
       bool user_scrollable_horizontal =
@@ -183,18 +191,31 @@
       auto reasons =
           GetMainThreadScrollingReasons(frame_view, ancestor_reasons);
 
-      full_context.force_subtree_update |= UpdateScrollTranslation(
-          frame_view, frame_view.PreTranslation(), frame_scroll, FloatPoint3D(),
-          context.current.scroll, scroll_clip, scroll_bounds,
+      full_context.force_subtree_update |= UpdateScroll(
+          frame_view, context.current.scroll, scroll_clip, scroll_bounds,
           user_scrollable_horizontal, user_scrollable_vertical, reasons,
           frame_view.GetScrollableArea());
-    } else {
-      if (frame_view.ScrollTranslation()) {
-        // Ensure pre-existing properties are cleared if there is no scrolling.
-        frame_view.SetScrollTranslation(nullptr);
-        // Rebuild all descendant properties because a property was removed.
-        full_context.force_subtree_update = true;
-      }
+    } else if (frame_view.ScrollNode()) {
+      // Ensure pre-existing properties are cleared if there is no scrolling.
+      frame_view.SetScrollNode(nullptr);
+      // Rebuild all descendant properties because a property was removed.
+      full_context.force_subtree_update = true;
+    }
+
+    // A scroll translation node is created for static offset (e.g., overflow
+    // hidden with scroll offset) or cases that scroll and have a scroll node.
+    ScrollOffset scroll_offset = frame_view.GetScrollOffset();
+    if (frame_view.IsScrollable() || !scroll_offset.IsZero()) {
+      TransformationMatrix frame_scroll;
+      frame_scroll.Translate(-scroll_offset.Width(), -scroll_offset.Height());
+      full_context.force_subtree_update |=
+          UpdateScrollTranslation(frame_view, frame_view.PreTranslation(),
+                                  frame_scroll, frame_view.ScrollNode());
+    } else if (frame_view.ScrollTranslation()) {
+      // Ensure pre-existing properties are cleared if there is no scrolling.
+      frame_view.SetScrollTranslation(nullptr);
+      // Rebuild all descendant properties because a property was removed.
+      full_context.force_subtree_update = true;
     }
   }
 
@@ -209,10 +230,10 @@
   context.current.transform = frame_view.PreTranslation();
   DCHECK(frame_view.ContentClip());
   context.current.clip = frame_view.ContentClip();
-  if (const auto* scroll_translation = frame_view.ScrollTranslation()) {
+  if (const auto* scroll_node = frame_view.ScrollNode())
+    context.current.scroll = scroll_node;
+  if (const auto* scroll_translation = frame_view.ScrollTranslation())
     context.current.transform = scroll_translation;
-    context.current.scroll = scroll_translation->ScrollNode();
-  }
   context.current.paint_offset = LayoutPoint();
   context.current.rendering_context_id = 0;
   context.current.should_flatten_inherited_transform = true;
@@ -946,13 +967,20 @@
                                        ancestor_reasons);
 }
 
-static bool NeedsScrollTranslation(const LayoutObject& object) {
+static bool NeedsScrollNode(const LayoutObject& object) {
   if (!object.HasOverflowClip())
     return false;
-  const LayoutBox& box = ToLayoutBox(object);
-  auto* scrollable_area = box.GetScrollableArea();
-  IntSize scroll_offset = box.ScrolledContentOffset();
-  return !scroll_offset.IsZero() || scrollable_area->ScrollsOverflow();
+  return ToLayoutBox(object).GetScrollableArea()->ScrollsOverflow();
+}
+
+// True if a scroll translation is needed for static scroll offset (e.g.,
+// overflow hidden with scroll), or if a scroll node is needed for composited
+// scrolling.
+static bool NeedsScrollOrScrollTranslation(const LayoutObject& object) {
+  if (!object.HasOverflowClip())
+    return false;
+  IntSize scroll_offset = ToLayoutBox(object).ScrolledContentOffset();
+  return !scroll_offset.IsZero() || NeedsScrollNode(object);
 }
 
 void PaintPropertyTreeBuilder::UpdateScrollAndScrollTranslation(
@@ -961,13 +989,9 @@
     PaintPropertyTreeBuilderFragmentContext& context,
     bool& force_subtree_update) {
   if (object.NeedsPaintPropertyUpdate() || force_subtree_update) {
-    if (NeedsScrollTranslation(object)) {
+    if (NeedsScrollNode(object)) {
       const LayoutBox& box = ToLayoutBox(object);
       auto* scrollable_area = box.GetScrollableArea();
-      IntSize scroll_offset = box.ScrolledContentOffset();
-      TransformationMatrix scroll_offset_matrix =
-          TransformationMatrix().Translate(-scroll_offset.Width(),
-                                           -scroll_offset.Height());
 
       // The container bounds are snapped to integers to match the equivalent
       // bounds on cc::ScrollNode. The offset is snapped to match the current
@@ -989,9 +1013,8 @@
 
       // Main thread scrolling reasons depend on their ancestor's reasons
       // so ensure the entire subtree is updated when reasons change.
-      if (auto* existing_scroll_translation = properties.ScrollTranslation()) {
-        auto* existing_scroll_node = existing_scroll_translation->ScrollNode();
-        if (existing_scroll_node->GetMainThreadScrollingReasons() != reasons)
+      if (auto* existing_scroll = properties.Scroll()) {
+        if (existing_scroll->GetMainThreadScrollingReasons() != reasons)
           force_subtree_update = true;
       }
 
@@ -999,13 +1022,29 @@
           object.UniqueId(), CompositorElementIdNamespace::kScrollTranslation);
 
       // TODO(pdr): Set the correct compositing reasons here.
+      auto result = properties.UpdateScroll(
+          context.current.scroll, bounds_offset, container_bounds,
+          scroll_bounds, user_scrollable_horizontal, user_scrollable_vertical,
+          reasons, element_id, scrollable_area);
+      force_subtree_update |= result.NewNodeCreated();
+    } else {
+      // Ensure pre-existing properties are cleared.
+      force_subtree_update |= properties.ClearScroll();
+    }
+
+    // A scroll translation node is created for static offset (e.g., overflow
+    // hidden with scroll offset) or cases that scroll and have a scroll node.
+    if (NeedsScrollOrScrollTranslation(object)) {
+      const LayoutBox& box = ToLayoutBox(object);
+      IntSize scroll_offset = box.ScrolledContentOffset();
+      TransformationMatrix scroll_offset_matrix =
+          TransformationMatrix().Translate(-scroll_offset.Width(),
+                                           -scroll_offset.Height());
       auto result = properties.UpdateScrollTranslation(
           context.current.transform, scroll_offset_matrix, FloatPoint3D(),
           context.current.should_flatten_inherited_transform,
           context.current.rendering_context_id, kCompositingReasonNone,
-          context.current.scroll, bounds_offset, container_bounds,
-          scroll_bounds, user_scrollable_horizontal, user_scrollable_vertical,
-          reasons, element_id, scrollable_area);
+          CompositorElementId(), properties.Scroll());
       force_subtree_update |= result.NewNodeCreated();
     } else {
       // Ensure pre-existing properties are cleared.
@@ -1013,9 +1052,10 @@
     }
   }
 
+  if (properties.Scroll())
+    context.current.scroll = properties.Scroll();
   if (properties.ScrollTranslation()) {
     context.current.transform = properties.ScrollTranslation();
-    context.current.scroll = context.current.transform->ScrollNode();
     context.current.should_flatten_inherited_transform = false;
   }
 }
@@ -1211,7 +1251,7 @@
       NeedsFilter(object) || NeedsCssClip(object) ||
       NeedsScrollbarPaintOffset(object) || NeedsOverflowClip(object) ||
       NeedsPerspective(object) || NeedsSVGLocalToBorderBoxTransform(object) ||
-      NeedsScrollTranslation(object);
+      NeedsScrollOrScrollTranslation(object);
 
   // We need at least the fragment for all PaintLayers, which store their
   // local border box properties on the fragment.
diff --git a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilderTest.cpp b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilderTest.cpp
index ac3cd96..499036b 100644
--- a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilderTest.cpp
+++ b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilderTest.cpp
@@ -59,15 +59,12 @@
   if (!frame_view)
     frame_view = GetDocument().View();
   if (RuntimeEnabledFeatures::RootLayerScrollingEnabled()) {
-    const auto* scroll_translation = frame_view->GetLayoutView()
-                                         ->FirstFragment()
-                                         ->PaintProperties()
-                                         ->ScrollTranslation();
-    return scroll_translation ? scroll_translation->ScrollNode() : nullptr;
+    return frame_view->GetLayoutView()
+        ->FirstFragment()
+        ->PaintProperties()
+        ->Scroll();
   }
-  return frame_view->ScrollTranslation()
-             ? frame_view->ScrollTranslation()->ScrollNode()
-             : nullptr;
+  return frame_view->ScrollNode();
 }
 
 const ObjectPaintProperties*
@@ -2751,7 +2748,6 @@
       "    overflow: hidden;"
       "    width: 5px;"
       "    height: 3px;"
-      "    border: 1px solid black;"
       "  }"
       "  .forceScroll {"
       "    height: 79px;"
@@ -2768,24 +2764,42 @@
 
   const ObjectPaintProperties* overflow_hidden_scroll_properties =
       overflow_hidden->GetLayoutObject()->FirstFragment()->PaintProperties();
-  // Because the frameView is does not scroll, overflowHidden's scroll should be
-  // under the root.
+
+  // Because the overflow hidden does not scroll and only has a static scroll
+  // offset, there should be a scroll translation node but no scroll node.
   auto* scroll_translation =
       overflow_hidden_scroll_properties->ScrollTranslation();
-  auto* overflow_hidden_scroll_node = scroll_translation->ScrollNode();
-  EXPECT_TRUE(overflow_hidden_scroll_node->Parent()->IsRoot());
   EXPECT_EQ(TransformationMatrix().Translate(0, -37),
             scroll_translation->Matrix());
-  // This should match the overflow's dimensions and should not include the
-  // box's border.
-  EXPECT_EQ(IntSize(5, 3), overflow_hidden_scroll_node->ContainerBounds());
-  // The scrolling content's bounds should include both the overflow's
-  // dimensions (5x3) and the 0x79 "forceScroll" object.
-  EXPECT_EQ(IntSize(5, 79), overflow_hidden_scroll_node->Bounds());
-  // Although overflow: hidden is programmatically scrollable, it is not user
-  // scrollable.
-  EXPECT_FALSE(overflow_hidden_scroll_node->UserScrollableHorizontal());
-  EXPECT_FALSE(overflow_hidden_scroll_node->UserScrollableVertical());
+  EXPECT_EQ(nullptr, scroll_translation->ScrollNode());
+  EXPECT_EQ(nullptr, overflow_hidden_scroll_properties->Scroll());
+}
+
+TEST_P(PaintPropertyTreeBuilderTest, FrameOverflowHiddenScrollProperties) {
+  SetBodyInnerHTML(
+      "<style>"
+      "  html {"
+      "    margin: 0px;"
+      "    overflow: hidden;"
+      "    width: 300px;"
+      "    height: 300px;"
+      "  }"
+      "  .forceScroll {"
+      "    height: 5000px;"
+      "  }"
+      "</style>"
+      "<div class='forceScroll'></div>");
+
+  GetDocument().domWindow()->scrollTo(0, 37);
+
+  GetDocument().View()->UpdateAllLifecyclePhases();
+
+  // Because the overflow hidden does not scroll and only has a static scroll
+  // offset, there should be a scroll translation node but no scroll node.
+  EXPECT_EQ(TransformationMatrix().Translate(0, -37),
+            FrameScrollTranslation()->Matrix());
+  EXPECT_EQ(nullptr, FrameScrollTranslation()->ScrollNode());
+  EXPECT_EQ(nullptr, FrameScroll());
 }
 
 TEST_P(PaintPropertyTreeBuilderTest, NestedScrollProperties) {
@@ -3394,9 +3408,8 @@
   // stored directly on the ScrollNode.
   EXPECT_EQ(CompositorElementId(),
             properties->ScrollTranslation()->GetCompositorElementId());
-  EXPECT_NE(
-      CompositorElementId(),
-      properties->ScrollTranslation()->ScrollNode()->GetCompositorElementId());
+  EXPECT_NE(CompositorElementId(),
+            properties->Scroll()->GetCompositorElementId());
 }
 
 TEST_P(PaintPropertyTreeBuilderTest, OverflowClipSubpixelPosition) {
diff --git a/third_party/WebKit/Source/core/paint/PaintPropertyTreePrinter.cpp b/third_party/WebKit/Source/core/paint/PaintPropertyTreePrinter.cpp
index f223403..38a7bd2 100644
--- a/third_party/WebKit/Source/core/paint/PaintPropertyTreePrinter.cpp
+++ b/third_party/WebKit/Source/core/paint/PaintPropertyTreePrinter.cpp
@@ -220,18 +220,16 @@
   static void AddFrameViewProperties(
       const LocalFrameView& frame_view,
       PropertyTreePrinter<ScrollPaintPropertyNode>& printer) {
-    if (const auto* scroll_translation = frame_view.ScrollTranslation()) {
-      const auto* scroll_node = scroll_translation->ScrollNode();
+    if (const auto* scroll_node = frame_view.ScrollNode())
       printer.AddPropertyNode(scroll_node, "Scroll (FrameView)");
-    }
   }
 
   static void AddObjectPaintProperties(
       const LayoutObject& object,
       const ObjectPaintProperties& paint_properties,
       PropertyTreePrinter<ScrollPaintPropertyNode>& printer) {
-    if (const auto* scroll_translation = paint_properties.ScrollTranslation()) {
-      printer.AddPropertyNode(scroll_translation->ScrollNode(),
+    if (const auto* scroll_node = paint_properties.Scroll()) {
+      printer.AddPropertyNode(scroll_node,
                               "Scroll (" + object.DebugName() + ")");
     }
   }
diff --git a/third_party/WebKit/Source/modules/exported/WebEmbeddedWorkerImpl.cpp b/third_party/WebKit/Source/modules/exported/WebEmbeddedWorkerImpl.cpp
index dd1ff07..73dc443 100644
--- a/third_party/WebKit/Source/modules/exported/WebEmbeddedWorkerImpl.cpp
+++ b/third_party/WebKit/Source/modules/exported/WebEmbeddedWorkerImpl.cpp
@@ -329,13 +329,7 @@
   if (asked_to_terminate_)
     return;
 
-  // The browser is expected to associate a registration and then load the
-  // script. If there's no associated registration, the browser could not
-  // successfully handle the SetHostedVersionID IPC, and the script load came
-  // through the normal network stack rather than through service worker
-  // loading code.
-  if (!worker_context_client_->HasAssociatedRegistration() ||
-      main_script_loader_->Failed()) {
+  if (main_script_loader_->Failed()) {
     TerminateWorkerContext();
     return;
   }
diff --git a/third_party/WebKit/Source/modules/serviceworkers/WebEmbeddedWorkerImplTest.cpp b/third_party/WebKit/Source/modules/serviceworkers/WebEmbeddedWorkerImplTest.cpp
index bf14909..5da92b4f65 100644
--- a/third_party/WebKit/Source/modules/serviceworkers/WebEmbeddedWorkerImplTest.cpp
+++ b/third_party/WebKit/Source/modules/serviceworkers/WebEmbeddedWorkerImplTest.cpp
@@ -54,13 +54,6 @@
     return std::unique_ptr<WebServiceWorkerProvider>(
         CreateServiceWorkerProviderProxy());
   }
-
-  bool HasAssociatedRegistration() override {
-    return has_associated_registration_;
-  }
-  void SetHasAssociatedRegistration(bool has_associated_registration) {
-    has_associated_registration_ = has_associated_registration;
-  }
   void GetClient(const WebString&,
                  std::unique_ptr<WebServiceWorkerClientCallbacks>) override {
     NOTREACHED();
@@ -111,7 +104,6 @@
   void WaitUntilThreadTermination() { termination_event_.Wait(); }
 
  private:
-  bool has_associated_registration_ = true;
   WaitableEvent script_evaluated_event_;
   WaitableEvent termination_event_;
 };
@@ -295,38 +287,6 @@
   ::testing::Mock::VerifyAndClearExpectations(mock_client_);
 }
 
-TEST_F(WebEmbeddedWorkerImplTest, NoRegistration) {
-  EXPECT_CALL(*mock_client_, WorkerReadyForInspection()).Times(1);
-  start_data_.pause_after_download_mode =
-      WebEmbeddedWorkerStartData::kPauseAfterDownload;
-  worker_->StartWorkerContext(start_data_);
-  ::testing::Mock::VerifyAndClearExpectations(mock_client_);
-
-  // Load the shadow page.
-  EXPECT_CALL(*mock_client_, CreateServiceWorkerNetworkProviderProxy())
-      .WillOnce(::testing::Return(nullptr));
-  if (mock_installed_scripts_manager_) {
-    EXPECT_CALL(*mock_installed_scripts_manager_,
-                IsScriptInstalled(start_data_.script_url))
-        .Times(1)
-        .WillOnce(::testing::Return(false));
-  }
-  Platform::Current()->GetURLLoaderMockFactory()->ServeAsynchronousRequests();
-  ::testing::Mock::VerifyAndClearExpectations(mock_client_);
-  if (mock_installed_scripts_manager_) {
-    ::testing::Mock::VerifyAndClearExpectations(
-        mock_installed_scripts_manager_);
-  }
-
-  // Load the script.
-  mock_client_->SetHasAssociatedRegistration(false);
-  EXPECT_CALL(*mock_client_, WorkerScriptLoaded()).Times(0);
-  EXPECT_CALL(*mock_client_, CreateServiceWorkerProviderProxy()).Times(0);
-  EXPECT_CALL(*mock_client_, WorkerContextFailedToStart()).Times(1);
-  Platform::Current()->GetURLLoaderMockFactory()->ServeAsynchronousRequests();
-  ::testing::Mock::VerifyAndClearExpectations(mock_client_);
-}
-
 // The running worker is detected as a memory leak. crbug.com/586897
 #if defined(ADDRESS_SANITIZER)
 #define MAYBE_DontPauseAfterDownload DISABLED_DontPauseAfterDownload
diff --git a/third_party/WebKit/Source/platform/BUILD.gn b/third_party/WebKit/Source/platform/BUILD.gn
index 04f6fa0..25fd52ea 100644
--- a/third_party/WebKit/Source/platform/BUILD.gn
+++ b/third_party/WebKit/Source/platform/BUILD.gn
@@ -2067,7 +2067,7 @@
   ]
   dict = "//testing/libfuzzer/fuzzers/dicts/png.dict"
   seed_corpuses = [
-    "//cc/test/data",
+    "//components/viz/test/data",
     "//third_party/WebKit/LayoutTests/images/png-suite/samples",
     "//third_party/WebKit/LayoutTests/images/resources/pngfuzz",
   ]
diff --git a/third_party/WebKit/Source/platform/graphics/compositing/PaintArtifactCompositorTest.cpp b/third_party/WebKit/Source/platform/graphics/compositing/PaintArtifactCompositorTest.cpp
index 8d1c7878..cbcc572 100644
--- a/third_party/WebKit/Source/platform/graphics/compositing/PaintArtifactCompositorTest.cpp
+++ b/third_party/WebKit/Source/platform/graphics/compositing/PaintArtifactCompositorTest.cpp
@@ -730,14 +730,15 @@
   FakeScrollClient scroll_client;
 
   CompositorElementId expected_compositor_element_id = CompositorElementId(2);
+  RefPtr<ScrollPaintPropertyNode> scroll = ScrollPaintPropertyNode::Create(
+      ScrollPaintPropertyNode::Root(), IntPoint(), IntSize(11, 13),
+      IntSize(27, 31), true, false, 0 /* mainThreadScrollingReasons */,
+      expected_compositor_element_id, &scroll_client);
   RefPtr<TransformPaintPropertyNode> scroll_translation =
-      TransformPaintPropertyNode::CreateScrollTranslation(
+      TransformPaintPropertyNode::Create(
           TransformPaintPropertyNode::Root(),
           TransformationMatrix().Translate(7, 9), FloatPoint3D(), false, 0,
-          kCompositingReasonNone, ScrollPaintPropertyNode::Root(), IntPoint(),
-          IntSize(11, 13), IntSize(27, 31), true, false,
-          0 /* mainThreadScrollingReasons */, expected_compositor_element_id,
-          &scroll_client);
+          kCompositingReasonNone, CompositorElementId(), scroll);
 
   TestPaintArtifact artifact;
   artifact
@@ -789,13 +790,15 @@
 }
 
 TEST_F(PaintArtifactCompositorTestWithPropertyTrees, TransformUnderScrollNode) {
+  RefPtr<ScrollPaintPropertyNode> scroll = ScrollPaintPropertyNode::Create(
+      ScrollPaintPropertyNode::Root(), IntPoint(), IntSize(11, 13),
+      IntSize(27, 31), true, false, 0 /* mainThreadScrollingReasons */,
+      CompositorElementId(), nullptr);
   RefPtr<TransformPaintPropertyNode> scroll_translation =
-      TransformPaintPropertyNode::CreateScrollTranslation(
+      TransformPaintPropertyNode::Create(
           TransformPaintPropertyNode::Root(),
           TransformationMatrix().Translate(7, 9), FloatPoint3D(), false, 0,
-          kCompositingReasonNone, ScrollPaintPropertyNode::Root(), IntPoint(),
-          IntSize(11, 13), IntSize(27, 31), true, false,
-          0 /* mainThreadScrollingReasons */, CompositorElementId(), nullptr);
+          kCompositingReasonNone, CompositorElementId(), scroll);
 
   RefPtr<TransformPaintPropertyNode> transform =
       TransformPaintPropertyNode::Create(
@@ -836,24 +839,28 @@
       CreateOpacityOnlyEffect(EffectPaintPropertyNode::Root(), 0.5);
 
   CompositorElementId expected_compositor_element_id_a = CompositorElementId(2);
+  RefPtr<ScrollPaintPropertyNode> scroll_a = ScrollPaintPropertyNode::Create(
+      ScrollPaintPropertyNode::Root(), IntPoint(), IntSize(2, 3), IntSize(5, 7),
+      false, true,
+      MainThreadScrollingReason::kHasBackgroundAttachmentFixedObjects,
+      expected_compositor_element_id_a, nullptr);
   RefPtr<TransformPaintPropertyNode> scroll_translation_a =
-      TransformPaintPropertyNode::CreateScrollTranslation(
+      TransformPaintPropertyNode::Create(
           TransformPaintPropertyNode::Root(),
           TransformationMatrix().Translate(11, 13), FloatPoint3D(), false, 0,
-          kCompositingReasonLayerForScrollingContents,
-          ScrollPaintPropertyNode::Root(), IntPoint(), IntSize(2, 3),
-          IntSize(5, 7), false, true,
-          MainThreadScrollingReason::kHasBackgroundAttachmentFixedObjects,
-          expected_compositor_element_id_a, nullptr);
+          kCompositingReasonLayerForScrollingContents, CompositorElementId(),
+          scroll_a);
 
   CompositorElementId expected_compositor_element_id_b = CompositorElementId(3);
+  RefPtr<ScrollPaintPropertyNode> scroll_b = ScrollPaintPropertyNode::Create(
+      scroll_translation_a->ScrollNode(), IntPoint(), IntSize(19, 23),
+      IntSize(29, 31), true, false, 0 /* mainThreadScrollingReasons */,
+      expected_compositor_element_id_b, nullptr);
   RefPtr<TransformPaintPropertyNode> scroll_translation_b =
-      TransformPaintPropertyNode::CreateScrollTranslation(
+      TransformPaintPropertyNode::Create(
           scroll_translation_a, TransformationMatrix().Translate(37, 41),
           FloatPoint3D(), false, 0, kCompositingReasonNone,
-          scroll_translation_a->ScrollNode(), IntPoint(), IntSize(19, 23),
-          IntSize(29, 31), true, false, 0 /* mainThreadScrollingReasons */,
-          expected_compositor_element_id_b, nullptr);
+          CompositorElementId(), scroll_b);
   TestPaintArtifact artifact;
   artifact.Chunk(scroll_translation_a, ClipPaintPropertyNode::Root(), effect)
       .RectDrawing(FloatRect(7, 11, 13, 17), Color::kWhite);
diff --git a/third_party/WebKit/Source/platform/graphics/compositing/PropertyTreeManager.cpp b/third_party/WebKit/Source/platform/graphics/compositing/PropertyTreeManager.cpp
index 5edac71e..500f83f 100644
--- a/third_party/WebKit/Source/platform/graphics/compositing/PropertyTreeManager.cpp
+++ b/third_party/WebKit/Source/platform/graphics/compositing/PropertyTreeManager.cpp
@@ -310,7 +310,7 @@
   layer->SetScrollTreeIndex(scroll_node_id);
   auto& compositor_scroll_node = *GetScrollTree().Node(scroll_node_id);
 
-  if (!transform->IsScrollTranslation())
+  if (!transform->ScrollNode())
     return;
 
   auto& compositor_transform_node =
diff --git a/third_party/WebKit/Source/platform/graphics/paint/ScrollPaintPropertyNode.h b/third_party/WebKit/Source/platform/graphics/paint/ScrollPaintPropertyNode.h
index e9006c8..b13eb8b 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/ScrollPaintPropertyNode.h
+++ b/third_party/WebKit/Source/platform/graphics/paint/ScrollPaintPropertyNode.h
@@ -22,16 +22,16 @@
 
 // A scroll node contains auxiliary scrolling information which includes how far
 // an area can be scrolled, main thread scrolling reasons, etc. Scroll nodes
-// are owned by TransformPaintPropertyNodes that are used for the scroll offset
-// translation.
+// are referenced by TransformPaintPropertyNodes that are used for the scroll
+// offset translation, though scroll offset translation can exist without a
+// scroll node (e.g., overflow: hidden).
 //
 // Main thread scrolling reasons force scroll updates to go to the main thread
 // and can have dependencies on other nodes. For example, all parents of a
 // scroll node with background attachment fixed set should also have it set.
 //
 // The scroll tree differs from the other trees because it does not affect
-// geometry directly. We may want to rename this class to reflect that it is
-// more like rare scroll data for TransformPaintPropertyNode.
+// geometry directly.
 class PLATFORM_EXPORT ScrollPaintPropertyNode
     : public PaintPropertyNode<ScrollPaintPropertyNode> {
  public:
diff --git a/third_party/WebKit/Source/platform/graphics/paint/TransformPaintPropertyNode.cpp b/third_party/WebKit/Source/platform/graphics/paint/TransformPaintPropertyNode.cpp
index 850d6b8..490be54 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/TransformPaintPropertyNode.cpp
+++ b/third_party/WebKit/Source/platform/graphics/paint/TransformPaintPropertyNode.cpp
@@ -45,8 +45,10 @@
       flattens_inherited_transform_ ? "yes" : "no", rendering_context_id_,
       CompositingReasonsAsString(direct_compositing_reasons_).Ascii().data(),
       compositor_element_id_.ToString().c_str());
-  if (scroll_)
-    return transform + " scroll=" + scroll_->ToString();
+  if (scroll_) {
+    return String::Format("%s scroll=%p", transform.Utf8().data(),
+                          scroll_.Get());
+  }
   return transform;
 }
 
diff --git a/third_party/WebKit/Source/platform/graphics/paint/TransformPaintPropertyNode.h b/third_party/WebKit/Source/platform/graphics/paint/TransformPaintPropertyNode.h
index ef02f33c..0b441ed 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/TransformPaintPropertyNode.h
+++ b/third_party/WebKit/Source/platform/graphics/paint/TransformPaintPropertyNode.h
@@ -21,9 +21,9 @@
 
 // A transform (e.g., created by css "transform" or "perspective", or for
 // internal positioning such as paint offset or scrolling) along with a
-// reference to the parent TransformPaintPropertyNode. The scroll tree is owned
-// by transform nodes and a transform node for scrolling will have a 2d
-// translation for the scroll offset and an associated ScrollPaintPropertyNode.
+// reference to the parent TransformPaintPropertyNode. The scroll tree is
+// referenced by transform nodes and a transform node with an associated scroll
+// node will be a 2d transform for scroll offset.
 //
 // The transform tree is rooted at a node with no parent. This root node should
 // not be modified.
@@ -41,43 +41,19 @@
       bool flattens_inherited_transform = false,
       unsigned rendering_context_id = 0,
       CompositingReasons direct_compositing_reasons = kCompositingReasonNone,
-      const CompositorElementId& compositor_element_id =
-          CompositorElementId()) {
+      const CompositorElementId& compositor_element_id = CompositorElementId(),
+      PassRefPtr<const ScrollPaintPropertyNode> scroll = nullptr) {
+    if (scroll) {
+      // If there is an associated scroll node, this can only be a 2d
+      // translation for scroll offset.
+      DCHECK(matrix.IsIdentityOr2DTranslation());
+      // The scroll compositor element id should be stored on the scroll node.
+      DCHECK(!compositor_element_id);
+    }
     return AdoptRef(new TransformPaintPropertyNode(
         std::move(parent), matrix, origin, flattens_inherited_transform,
-        rendering_context_id, direct_compositing_reasons,
-        compositor_element_id));
-  }
-
-  static PassRefPtr<TransformPaintPropertyNode> CreateScrollTranslation(
-      PassRefPtr<const TransformPaintPropertyNode> parent,
-      const TransformationMatrix& matrix,
-      const FloatPoint3D& origin,
-      bool flattens_inherited_transform,
-      unsigned rendering_context_id,
-      CompositingReasons direct_compositing_reasons,
-      PassRefPtr<const ScrollPaintPropertyNode> parent_scroll,
-      const IntPoint& bounds_offset,
-      const IntSize& scroll_container_bounds,
-      const IntSize& bounds,
-      bool user_scrollable_horizontal,
-      bool user_scrollable_vertical,
-      MainThreadScrollingReasons main_thread_scrolling_reasons,
-      const CompositorElementId& compositor_element_id,
-      WebLayerScrollClient* scroll_client) {
-    // If this transform is for scroll offset, it should be a 2d translation.
-    DCHECK(matrix.IsIdentityOr2DTranslation());
-    return AdoptRef(new TransformPaintPropertyNode(
-        std::move(parent), matrix, origin, flattens_inherited_transform,
-        rendering_context_id, direct_compositing_reasons,
-        // The compositor element id is empty because the element id is stored
-        // on the scroll node.
-        CompositorElementId(),
-        ScrollPaintPropertyNode::Create(
-            std::move(parent_scroll), bounds_offset, scroll_container_bounds,
-            bounds, user_scrollable_horizontal, user_scrollable_vertical,
-            main_thread_scrolling_reasons, compositor_element_id,
-            scroll_client)));
+        rendering_context_id, direct_compositing_reasons, compositor_element_id,
+        std::move(scroll)));
   }
 
   bool Update(
@@ -87,14 +63,23 @@
       bool flattens_inherited_transform = false,
       unsigned rendering_context_id = 0,
       CompositingReasons direct_compositing_reasons = kCompositingReasonNone,
-      CompositorElementId compositor_element_id = CompositorElementId()) {
+      CompositorElementId compositor_element_id = CompositorElementId(),
+      PassRefPtr<const ScrollPaintPropertyNode> scroll = nullptr) {
     bool parent_changed = PaintPropertyNode::Update(std::move(parent));
 
+    if (scroll) {
+      // If there is an associated scroll node, this can only be a 2d
+      // translation for scroll offset.
+      DCHECK(matrix.IsIdentityOr2DTranslation());
+      // The scroll compositor element id should be stored on the scroll node.
+      DCHECK(!compositor_element_id);
+    }
+
     if (matrix == matrix_ && origin == origin_ &&
         flattens_inherited_transform == flattens_inherited_transform_ &&
         rendering_context_id == rendering_context_id_ &&
         direct_compositing_reasons == direct_compositing_reasons_ &&
-        compositor_element_id == compositor_element_id_)
+        compositor_element_id == compositor_element_id_ && scroll == scroll_)
       return parent_changed;
 
     SetChanged();
@@ -104,44 +89,14 @@
     rendering_context_id_ = rendering_context_id;
     direct_compositing_reasons_ = direct_compositing_reasons;
     compositor_element_id_ = compositor_element_id;
+    scroll_ = std::move(scroll);
     return true;
   }
 
-  bool UpdateScrollTranslation(
-      PassRefPtr<const TransformPaintPropertyNode> parent,
-      const TransformationMatrix& matrix,
-      const FloatPoint3D& origin,
-      bool flattens_inherited_transform,
-      unsigned rendering_context_id,
-      CompositingReasons direct_compositing_reasons,
-      PassRefPtr<const ScrollPaintPropertyNode> parent_scroll,
-      const IntPoint& bounds_offset,
-      const IntSize& scroll_container_bounds,
-      const IntSize& bounds,
-      bool user_scrollable_horizontal,
-      bool user_scrollable_vertical,
-      MainThreadScrollingReasons main_thread_scrolling_reasons,
-      CompositorElementId compositor_element_id,
-      WebLayerScrollClient* scroll_client) {
-    bool changed = Update(std::move(parent), matrix, origin,
-                          flattens_inherited_transform, rendering_context_id,
-                          direct_compositing_reasons, CompositorElementId());
-    DCHECK(scroll_);
-    DCHECK(matrix.IsIdentityOr2DTranslation());
-    changed |= scroll_->Update(
-        std::move(parent_scroll), bounds_offset, scroll_container_bounds,
-        bounds, user_scrollable_horizontal, user_scrollable_vertical,
-        main_thread_scrolling_reasons, compositor_element_id, scroll_client);
-    return changed;
-  }
-
   const TransformationMatrix& Matrix() const { return matrix_; }
   const FloatPoint3D& Origin() const { return origin_; }
 
-  // True if this transform is for the scroll offset translation.
-  bool IsScrollTranslation() const { return !!scroll_; }
-  // The associated scroll node if this transform is the scroll offset for
-  // scrolling, or nullptr otherwise.
+  // The associated scroll node, or nullptr otherwise.
   const ScrollPaintPropertyNode* ScrollNode() const { return scroll_.Get(); }
 
   // Returns the scroll node this transform scrolls with respect to. If this
@@ -180,21 +135,19 @@
     return AdoptRef(new TransformPaintPropertyNode(
         Parent(), matrix_, origin_, flattens_inherited_transform_,
         rendering_context_id_, direct_compositing_reasons_,
-        compositor_element_id_, scroll_ ? scroll_->Clone() : nullptr));
+        compositor_element_id_, scroll_));
   }
 
   // The equality operator is used by FindPropertiesNeedingUpdate.h for checking
   // if a transform node has changed.
   bool operator==(const TransformPaintPropertyNode& o) const {
-    if (scroll_ && o.scroll_ && !(*scroll_ == *o.scroll_))
-      return false;
     return Parent() == o.Parent() && matrix_ == o.matrix_ &&
            origin_ == o.origin_ &&
            flattens_inherited_transform_ == o.flattens_inherited_transform_ &&
            rendering_context_id_ == o.rendering_context_id_ &&
            direct_compositing_reasons_ == o.direct_compositing_reasons_ &&
            compositor_element_id_ == o.compositor_element_id_ &&
-           !!scroll_ == !!o.scroll_;
+           scroll_ == o.scroll_;
   }
 
   String ToTreeString() const;
@@ -211,7 +164,7 @@
       unsigned rendering_context_id,
       CompositingReasons direct_compositing_reasons,
       CompositorElementId compositor_element_id,
-      PassRefPtr<ScrollPaintPropertyNode> scroll = nullptr)
+      PassRefPtr<const ScrollPaintPropertyNode> scroll = nullptr)
       : PaintPropertyNode(std::move(parent)),
         matrix_(matrix),
         origin_(origin),
@@ -239,7 +192,7 @@
   unsigned rendering_context_id_;
   CompositingReasons direct_compositing_reasons_;
   CompositorElementId compositor_element_id_;
-  RefPtr<ScrollPaintPropertyNode> scroll_;
+  RefPtr<const ScrollPaintPropertyNode> scroll_;
 
   mutable std::unique_ptr<GeometryMapperTransformCache> transform_cache_;
 };
diff --git a/third_party/WebKit/public/web/modules/serviceworker/WebServiceWorkerContextClient.h b/third_party/WebKit/public/web/modules/serviceworker/WebServiceWorkerContextClient.h
index 9b75b5c..6e97462 100644
--- a/third_party/WebKit/public/web/modules/serviceworker/WebServiceWorkerContextClient.h
+++ b/third_party/WebKit/public/web/modules/serviceworker/WebServiceWorkerContextClient.h
@@ -108,12 +108,6 @@
   // completed. Called on the main thread.
   virtual void WorkerContextFailedToStart() {}
 
-  // True if the running service worker has a service worker registration. This
-  // should never be false and is currently used as a sanity check that the
-  // worker started up using the expected code path.
-  // TODO(falken): Investigate removing this method.
-  virtual bool HasAssociatedRegistration() { return false; }
-
   // The worker script successfully loaded. Called on the main thread when the
   // script is served from ResourceLoader or on the worker thread when the
   // script is served via WebServiceWorkerInstalledScriptsManager.
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index 97018e6..82080b9 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -23183,6 +23183,7 @@
   <int value="-345838366" label="enable-hosted-apps-in-windows"/>
   <int value="-345324571" label="enable-quirks-client"/>
   <int value="-344343842" label="disable-experimental-app-list"/>
+  <int value="-343769596" label="ServiceWorkerScriptStreaming:disabled"/>
   <int value="-340622848" label="disable-javascript-harmony-shipping"/>
   <int value="-340255045" label="allow-nacl-socket-api"/>
   <int value="-340023285" label="WebNFC:enabled"/>
@@ -23427,6 +23428,7 @@
   <int value="477967119" label="enable-unified-media-pipeline"/>
   <int value="479906041" label="RunAllFlashInAllowMode:disabled"/>
   <int value="480544447" label="NonValidatingReloadOnRefreshContentV2:enabled"/>
+  <int value="481506759" label="ServiceWorkerScriptStreaming:enabled"/>
   <int value="492113129" label="ExperimentalAppBanners:enabled"/>
   <int value="493903641" label="disable-appcontainer"/>
   <int value="494733611" label="disable-drop-sync-credential"/>
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index 9bba6d1..07b438e 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -91330,6 +91330,7 @@
   <suffix name="ForeignTabs" label="Open tabs on other devices"/>
   <suffix name="Experimental" label="Experimental"/>
   <suffix name="ReadingList" label="Reading List entries"/>
+  <suffix name="Contextual" label="Contextual suggestions"/>
   <affected-histogram
       name="NewTabPage.ContentSuggestions.CountOnNtpOpenedIfVisible"/>
   <affected-histogram name="NewTabPage.ContentSuggestions.DismissedUnvisited"/>
diff --git a/ui/login/account_picker/md_screen_account_picker.css b/ui/login/account_picker/md_screen_account_picker.css
index 491d148..6e69f2b 100644
--- a/ui/login/account_picker/md_screen_account_picker.css
+++ b/ui/login/account_picker/md_screen_account_picker.css
@@ -100,6 +100,10 @@
   display: block;
 }
 
+.small-pod-container::-webkit-scrollbar-corner {
+  background-color: transparent; /* Hides the default white box. */
+}
+
 .small-pod-container-mask {
   background: linear-gradient(#000, transparent);
   height: 112px;
diff --git a/ui/login/account_picker/md_user_pod_row.css b/ui/login/account_picker/md_user_pod_row.css
index a01e0064..58dfca6 100644
--- a/ui/login/account_picker/md_user_pod_row.css
+++ b/ui/login/account_picker/md_user_pod_row.css
@@ -165,7 +165,7 @@
   top: 182px;
 }
 
-.pod.focused:not(.multiprofiles-policy-applied) .auth-container {
+.pod.focused:not(.multiprofiles-policy-applied):not(.public-account) .auth-container {
   display: flex;
   height: 40px;
   left: 51px;
@@ -182,7 +182,7 @@
 </if>
 }
 
-html[dir=rtl] .pod.focused:not(.multiprofiles-policy-applied) .auth-container {
+html[dir=rtl] .pod.focused:not(.multiprofiles-policy-applied):not(.public-account) .auth-container {
   left: auto;
   right: 51px;
 }
diff --git a/ui/login/account_picker/user_pod_row.css b/ui/login/account_picker/user_pod_row.css
index 29bc6f66..b8a0ef6 100644
--- a/ui/login/account_picker/user_pod_row.css
+++ b/ui/login/account_picker/user_pod_row.css
@@ -163,7 +163,7 @@
 }
 
 .name-container,
-.pod.focused:not(.multiprofiles-policy-applied) .auth-container {
+.pod.focused:not(.multiprofiles-policy-applied):not(.public-account) .auth-container {
   background-color: white;
   display: flex;
   position: absolute;