diff --git a/DEPS b/DEPS
index 93d3a63..4d76fd04 100644
--- a/DEPS
+++ b/DEPS
@@ -96,7 +96,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling catapult
   # and whatever else without interference from each other.
-  'catapult_revision': '67cf0dc183f8a484495aa7eb1984f241835d01c1',
+  'catapult_revision': '623e8078bffa79113055f14ffc65f8f20e0d9157',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # and whatever else without interference from each other.
diff --git a/chrome/VERSION b/chrome/VERSION
index 53a292e2..08526fa 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
 MAJOR=58
 MINOR=0
-BUILD=3011
+BUILD=3012
 PATCH=0
diff --git a/chrome/browser/webshare/share_service_impl.cc b/chrome/browser/webshare/share_service_impl.cc
index 7d2ddc1..eadfe7e 100644
--- a/chrome/browser/webshare/share_service_impl.cc
+++ b/chrome/browser/webshare/share_service_impl.cc
@@ -10,12 +10,15 @@
 
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
-#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/engagement/site_engagement_service.h"
+#include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser_commands.h"
 #include "chrome/browser/ui/browser_dialogs.h"
 #include "chrome/browser/ui/browser_list.h"
 #include "chrome/browser/ui/browser_tabstrip.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
+#include "chrome/common/pref_names.h"
+#include "components/prefs/pref_service.h"
 #include "mojo/public/cpp/bindings/strong_binding.h"
 #include "net/base/escape.h"
 
@@ -45,6 +48,9 @@
 
 }  // namespace
 
+ShareServiceImpl::ShareServiceImpl() = default;
+ShareServiceImpl::~ShareServiceImpl() = default;
+
 // static
 void ShareServiceImpl::Create(blink::mojom::ShareServiceRequest request) {
   mojo::MakeStrongBinding(base::MakeUnique<ShareServiceImpl>(),
@@ -116,7 +122,7 @@
 void ShareServiceImpl::ShowPickerDialog(
     const std::vector<std::pair<base::string16, GURL>>& targets,
     const base::Callback<void(base::Optional<std::string>)>& callback) {
-  // TODO(mgiuca): Get the browser window as |parent_window|.
+// TODO(mgiuca): Get the browser window as |parent_window|.
 #if defined(OS_LINUX) || defined(OS_WIN)
   chrome::ShowWebShareTargetPickerDialog(nullptr /* parent_window */, targets,
                                          callback);
@@ -125,65 +131,145 @@
 #endif
 }
 
+Browser* ShareServiceImpl::GetBrowser() {
+// TODO(constantina): Prevent this code from being run/compiled in android.
+#if defined(OS_LINUX) || defined(OS_WIN)
+  return BrowserList::GetInstance()->GetLastActive();
+#else
+  return nullptr;
+#endif
+}
+
 void ShareServiceImpl::OpenTargetURL(const GURL& target_url) {
 // TODO(constantina): Prevent this code from being run/compiled in android.
 #if defined(OS_LINUX) || defined(OS_WIN)
-  Browser* browser = BrowserList::GetInstance()->GetLastActive();
+  Browser* browser = GetBrowser();
   chrome::AddTabAt(browser, target_url,
                    browser->tab_strip_model()->active_index() + 1, true);
 #endif
 }
 
+std::string ShareServiceImpl::GetTargetTemplate(
+    const std::string& target_url,
+    const base::DictionaryValue& share_targets) {
+  const base::DictionaryValue* share_target_info_dict = nullptr;
+  share_targets.GetDictionaryWithoutPathExpansion(target_url,
+                                                  &share_target_info_dict);
+
+  std::string url_template;
+  share_target_info_dict->GetString("url_template", &url_template);
+  return url_template;
+}
+
+PrefService* ShareServiceImpl::GetPrefService() {
+// TODO(constantina): Prevent this code from being run/compiled in android.
+#if defined(OS_LINUX) || defined(OS_WIN)
+  return GetBrowser()->profile()->GetPrefs();
+#else
+  return nullptr;
+#endif
+}
+
+blink::mojom::EngagementLevel ShareServiceImpl::GetEngagementLevel(
+    const GURL& url) {
+// TODO(constantina): Prevent this code from being run/compiled in android.
+#if defined(OS_LINUX) || defined(OS_WIN)
+  SiteEngagementService* site_engagement_service =
+      SiteEngagementService::Get(GetBrowser()->profile());
+  return site_engagement_service->GetEngagementLevel(url);
+#else
+  return blink::mojom::EngagementLevel::NONE;
+#endif
+}
+
+// static
+std::vector<std::pair<base::string16, GURL>>
+ShareServiceImpl::GetTargetsWithSufficientEngagement(
+    const base::DictionaryValue& share_targets) {
+  constexpr blink::mojom::EngagementLevel kMinimumEngagementLevel =
+      blink::mojom::EngagementLevel::LOW;
+
+  std::vector<std::pair<base::string16, GURL>> sufficiently_engaged_targets;
+
+  for (base::DictionaryValue::Iterator it(share_targets); !it.IsAtEnd();
+       it.Advance()) {
+    GURL manifest_url(it.key());
+    if (GetEngagementLevel(manifest_url) >= kMinimumEngagementLevel) {
+      const base::DictionaryValue* share_target_dict;
+      bool result = it.value().GetAsDictionary(&share_target_dict);
+      DCHECK(result);
+
+      std::string name;
+      share_target_dict->GetString("name", &name);
+
+      sufficiently_engaged_targets.push_back(
+          make_pair(base::UTF8ToUTF16(name), manifest_url));
+    }
+  }
+
+  return sufficiently_engaged_targets;
+}
+
 void ShareServiceImpl::Share(const std::string& title,
                              const std::string& text,
                              const GURL& share_url,
                              const ShareCallback& callback) {
-  // TODO(constantina): Replace hard-coded name and manifest URL with the list
-  // of registered targets' manifest URLs.
-  constexpr char kTargetName[] = "Web Share Target Test App";
-  constexpr char kManifestURL[] =
-      "https://wicg.github.io/web-share-target/demos/manifest.json";
-  // TODO(constantina): Pass vector of pairs of target names and manifest URLs
-  // to picker.
-  std::vector<std::pair<base::string16, GURL>> targets{make_pair(
-      base::ASCIIToUTF16(kTargetName), GURL(kManifestURL))};
+  std::unique_ptr<base::DictionaryValue> share_targets;
 
-  ShowPickerDialog(targets, base::Bind(&ShareServiceImpl::OnPickerClosed,
-                                       base::Unretained(this), title, text,
-                                       share_url, callback));
+// TODO(constantina): Prevent this code from being run/compiled in android.
+#if defined(OS_LINUX) || defined(OS_WIN)
+  share_targets = GetPrefService()
+                      ->GetDictionary(prefs::kWebShareVisitedTargets)
+                      ->CreateDeepCopy();
+#else
+  return;
+#endif
+
+  std::vector<std::pair<base::string16, GURL>> sufficiently_engaged_targets =
+      GetTargetsWithSufficientEngagement(*share_targets);
+
+  ShowPickerDialog(
+      sufficiently_engaged_targets,
+      base::Bind(&ShareServiceImpl::OnPickerClosed, base::Unretained(this),
+                 base::Passed(&share_targets), title, text, share_url,
+                 callback));
 }
 
-void ShareServiceImpl::OnPickerClosed(const std::string& title,
-                                      const std::string& text,
-                                      const GURL& share_url,
-                                      const ShareCallback& callback,
-                                      base::Optional<std::string> result) {
+void ShareServiceImpl::OnPickerClosed(
+    std::unique_ptr<base::DictionaryValue> share_targets,
+    const std::string& title,
+    const std::string& text,
+    const GURL& share_url,
+    const ShareCallback& callback,
+    base::Optional<std::string> result) {
   if (!result.has_value()) {
     callback.Run(base::Optional<std::string>("Share was cancelled"));
     return;
   }
 
-  // TODO(constantina): use manifest URL in result to look up corresponding URL
-  // template.
-  constexpr char kUrlTemplate[] =
-      "https://wicg.github.io/web-share-target/demos/"
-      "sharetarget.html?title={title}&text={text}&url={url}";
+  std::string chosen_target = result.value();
 
+  std::string url_template = GetTargetTemplate(chosen_target, *share_targets);
   std::string url_template_filled;
-  if (!ReplacePlaceholders(kUrlTemplate, title, text, share_url,
+  if (!ReplacePlaceholders(url_template, title, text, share_url,
                            &url_template_filled)) {
     callback.Run(base::Optional<std::string>(
         "Error: unable to replace placeholders in url template"));
     return;
   }
 
-  GURL target_url(url_template_filled);
-  if (!target_url.is_valid()) {
+  // The template is relative to the manifest URL (minus the filename).
+  // Concatenate to make an absolute URL.
+  base::StringPiece url_base(
+      chosen_target.data(),
+      chosen_target.size() - GURL(chosen_target).ExtractFileName().size());
+  const GURL target(url_base.as_string() + url_template_filled);
+  if (!target.is_valid()) {
     callback.Run(base::Optional<std::string>(
         "Error: url of share target is not a valid url."));
     return;
   }
-  OpenTargetURL(target_url);
+  OpenTargetURL(target);
 
   callback.Run(base::nullopt);
 }
diff --git a/chrome/browser/webshare/share_service_impl.h b/chrome/browser/webshare/share_service_impl.h
index 3bc47de..b2de060 100644
--- a/chrome/browser/webshare/share_service_impl.h
+++ b/chrome/browser/webshare/share_service_impl.h
@@ -5,20 +5,26 @@
 #ifndef CHROME_BROWSER_WEBSHARE_SHARE_SERVICE_IMPL_H_
 #define CHROME_BROWSER_WEBSHARE_SHARE_SERVICE_IMPL_H_
 
+#include <memory>
 #include <string>
+#include <vector>
 
 #include "base/gtest_prod_util.h"
 #include "base/strings/string16.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_dialogs.h"
 #include "mojo/public/cpp/bindings/interface_request.h"
 #include "third_party/WebKit/public/platform/modules/webshare/webshare.mojom.h"
+#include "third_party/WebKit/public/platform/site_engagement.mojom.h"
 
+class DictionaryValue;
 class GURL;
 
 // Desktop implementation of the ShareService Mojo service.
 class ShareServiceImpl : public blink::mojom::ShareService {
  public:
-  ShareServiceImpl() = default;
-  ~ShareServiceImpl() override = default;
+  ShareServiceImpl();
+  ~ShareServiceImpl() override;
 
   static void Create(mojo::InterfaceRequest<ShareService> request);
 
@@ -31,6 +37,20 @@
  private:
   FRIEND_TEST_ALL_PREFIXES(ShareServiceImplUnittest, ReplacePlaceholders);
 
+  Browser* GetBrowser();
+
+  // Returns the URL template of the target identified by |target_url|
+  std::string GetTargetTemplate(
+      const std::string& target_url,
+      const base::DictionaryValue& share_targets);
+
+  // Virtual for testing purposes.
+  virtual PrefService* GetPrefService();
+
+  // Returns the site engagement level of the site, |url|, with the user.
+  // Virtual for testing purposes.
+  virtual blink::mojom::EngagementLevel GetEngagementLevel(const GURL& url);
+
   // Shows the share picker dialog with |targets| as the list of applications
   // presented to the user. Passes the result to |callback|. If the user picks a
   // target, the result passed to |callback| is the manifest URL of the chosen
@@ -43,6 +63,12 @@
   // Virtual for testing purposes.
   virtual void OpenTargetURL(const GURL& target_url);
 
+  // Returns all stored Share Targets that have a high enough engagement score
+  // with the user.
+  std::vector<std::pair<base::string16, GURL>>
+  GetTargetsWithSufficientEngagement(
+      const base::DictionaryValue& share_targets);
+
   // Writes to |url_template_filled|, a copy of |url_template| with all
   // instances of "{title}", "{text}", and "{url}" replaced with
   // |title|, |text|, and |url| respectively.
@@ -57,7 +83,8 @@
                                   const GURL& share_url,
                                   std::string* url_template_filled);
 
-  void OnPickerClosed(const std::string& title,
+  void OnPickerClosed(std::unique_ptr<base::DictionaryValue> share_targets,
+                      const std::string& title,
                       const std::string& text,
                       const GURL& share_url,
                       const ShareCallback& callback,
diff --git a/chrome/browser/webshare/share_service_impl_unittest.cc b/chrome/browser/webshare/share_service_impl_unittest.cc
index ad9140a..c47c106 100644
--- a/chrome/browser/webshare/share_service_impl_unittest.cc
+++ b/chrome/browser/webshare/share_service_impl_unittest.cc
@@ -9,7 +9,11 @@
 #include "base/run_loop.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/webshare/share_service_impl.h"
+#include "chrome/common/pref_names.h"
 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
+#include "components/prefs/pref_registry_simple.h"
+#include "components/prefs/scoped_user_pref_update.h"
+#include "components/prefs/testing_pref_service.h"
 #include "mojo/public/cpp/bindings/interface_request.h"
 #include "mojo/public/cpp/bindings/strong_binding.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -21,38 +25,87 @@
 constexpr char kText[] = "My text";
 constexpr char kUrlSpec[] = "https://www.google.com/";
 
+constexpr char kTargetName[] = "Share Target";
+constexpr char kUrlTemplate[] = "share?title={title}&text={text}&url={url}";
+constexpr char kManifestUrlHigh[] =
+    "https://www.example-high.com/target/manifest.json";
+constexpr char kManifestUrlLow[] =
+    "https://www.example-low.com/target/manifest.json";
+constexpr char kManifestUrlMin[] =
+    "https://www.example-min.com/target/manifest.json";
+
 class ShareServiceTestImpl : public ShareServiceImpl {
  public:
-  static ShareServiceTestImpl* Create(
-      blink::mojom::ShareServiceRequest request) {
-    std::unique_ptr<ShareServiceTestImpl> share_service_helper =
-        base::MakeUnique<ShareServiceTestImpl>();
-    ShareServiceTestImpl* share_service_helper_raw = share_service_helper.get();
-    mojo::MakeStrongBinding(std::move(share_service_helper),
-                            std::move(request));
-    return share_service_helper_raw;
+  explicit ShareServiceTestImpl(blink::mojom::ShareServiceRequest request)
+      : binding_(this) {
+    binding_.Bind(std::move(request));
+
+    pref_service_.reset(new TestingPrefServiceSimple());
+    pref_service_->registry()->RegisterDictionaryPref(
+        prefs::kWebShareVisitedTargets);
   }
 
   void set_picker_result(base::Optional<std::string> result) {
     picker_result_ = result;
   }
 
+  void AddShareTargetToPrefs(const std::string& manifest_url,
+                             const std::string& name,
+                             const std::string& url_template) {
+    constexpr char kUrlTemplateKey[] = "url_template";
+    constexpr char kNameKey[] = "name";
+
+    DictionaryPrefUpdate update(GetPrefService(),
+                                prefs::kWebShareVisitedTargets);
+    base::DictionaryValue* share_target_dict = update.Get();
+
+    std::unique_ptr<base::DictionaryValue> origin_dict(
+        new base::DictionaryValue);
+
+    origin_dict->SetStringWithoutPathExpansion(kUrlTemplateKey, url_template);
+    origin_dict->SetStringWithoutPathExpansion(kNameKey, name);
+
+    share_target_dict->SetWithoutPathExpansion(manifest_url,
+                                               std::move(origin_dict));
+  }
+
+  void SetEngagementForTarget(const std::string& manifest_url,
+                              blink::mojom::EngagementLevel level) {
+    engagement_map_[manifest_url] = level;
+  }
+
   const std::string& GetLastUsedTargetURL() { return last_used_target_url_; }
 
- private:
-  base::Optional<std::string> picker_result_;
-  std::string last_used_target_url_;
+  const std::vector<std::pair<base::string16, GURL>>& GetTargetsInPicker() {
+    return targets_in_picker_;
+  }
 
+ private:
   void ShowPickerDialog(
       const std::vector<std::pair<base::string16, GURL>>& targets,
       const base::Callback<void(base::Optional<std::string>)>& callback)
       override {
+    targets_in_picker_ = targets;
     callback.Run(picker_result_);
   }
 
   void OpenTargetURL(const GURL& target_url) override {
     last_used_target_url_ = target_url.spec();
   }
+
+  PrefService* GetPrefService() override { return pref_service_.get(); }
+
+  blink::mojom::EngagementLevel GetEngagementLevel(const GURL& url) override {
+    return engagement_map_[url.spec()];
+  }
+
+  mojo::Binding<blink::mojom::ShareService> binding_;
+
+  base::Optional<std::string> picker_result_;
+  std::string last_used_target_url_;
+  std::unique_ptr<TestingPrefServiceSimple> pref_service_;
+  std::map<std::string, blink::mojom::EngagementLevel> engagement_map_;
+  std::vector<std::pair<base::string16, GURL>> targets_in_picker_;
 };
 
 class ShareServiceImplUnittest : public ChromeRenderViewHostTestHarness {
@@ -63,61 +116,87 @@
   void SetUp() override {
     ChromeRenderViewHostTestHarness::SetUp();
 
-    share_service_helper_ =
-        ShareServiceTestImpl::Create(mojo::MakeRequest(&share_service_));
+    share_service_helper_ = base::MakeUnique<ShareServiceTestImpl>(
+        mojo::MakeRequest(&share_service_));
+
+    share_service_helper_->SetEngagementForTarget(
+        kManifestUrlHigh, blink::mojom::EngagementLevel::HIGH);
+    share_service_helper_->SetEngagementForTarget(
+        kManifestUrlMin, blink::mojom::EngagementLevel::MINIMAL);
+    share_service_helper_->SetEngagementForTarget(
+        kManifestUrlLow, blink::mojom::EngagementLevel::LOW);
   }
 
   void TearDown() override { ChromeRenderViewHostTestHarness::TearDown(); }
 
-  void DidShare(const std::string& expected_target_url,
-                const base::Optional<std::string>& expected_param,
-                const base::Optional<std::string>& param) {
-    EXPECT_EQ(expected_param, param);
+  void DidShare(const std::vector<std::pair<base::string16, GURL>>&
+                    expected_targets_in_picker,
+                const std::string& expected_target_url,
+                const base::Optional<std::string>& expected_error,
+                const base::Optional<std::string>& error) {
+    std::vector<std::pair<base::string16, GURL>> targets_in_picker =
+        share_service_helper_->GetTargetsInPicker();
+    EXPECT_EQ(expected_targets_in_picker, targets_in_picker);
+
     std::string target_url = share_service_helper_->GetLastUsedTargetURL();
     EXPECT_EQ(expected_target_url, target_url);
 
+    EXPECT_EQ(expected_error, error);
+
     if (!on_callback_.is_null())
       on_callback_.Run();
   }
 
   blink::mojom::ShareServicePtr share_service_;
-  ShareServiceTestImpl* share_service_helper_;
+  std::unique_ptr<ShareServiceTestImpl> share_service_helper_;
   base::Closure on_callback_;
 };
 
 }  // namespace
 
+#if defined(OS_LINUX) || defined(OS_WIN)
+
 // Basic test to check the Share method calls the callback with the expected
 // parameters.
 TEST_F(ShareServiceImplUnittest, ShareCallbackParams) {
-  std::string expected_url =
-      "https://wicg.github.io/web-share-target/demos/"
-      "sharetarget.html?title=My%20title&text=My%20text&url=https%3A%2F%2Fwww."
-      "google.com%2F";
-  share_service_helper_->set_picker_result(base::Optional<std::string>(
-      "https://wicg.github.io/web-share-target/demos/"));
+  share_service_helper_->set_picker_result(
+      base::Optional<std::string>(kManifestUrlLow));
 
-  const GURL url(kUrlSpec);
+  share_service_helper_->AddShareTargetToPrefs(kManifestUrlLow, kTargetName,
+                                               kUrlTemplate);
+  share_service_helper_->AddShareTargetToPrefs(kManifestUrlHigh, kTargetName,
+                                               kUrlTemplate);
+
+  std::string expected_url =
+      "https://www.example-low.com/target/"
+      "share?title=My%20title&text=My%20text&url=https%3A%2F%2Fwww."
+      "google.com%2F";
+
+  std::vector<std::pair<base::string16, GURL>> expected_targets{
+      make_pair(base::UTF8ToUTF16(kTargetName), GURL(kManifestUrlHigh)),
+      make_pair(base::UTF8ToUTF16(kTargetName), GURL(kManifestUrlLow))};
   base::Callback<void(const base::Optional<std::string>&)> callback =
       base::Bind(&ShareServiceImplUnittest::DidShare, base::Unretained(this),
-                 expected_url, base::Optional<std::string>());
+                 expected_targets, expected_url, base::Optional<std::string>());
 
   base::RunLoop run_loop;
   on_callback_ = run_loop.QuitClosure();
 
+  const GURL url(kUrlSpec);
   share_service_->Share(kTitle, kText, url, callback);
 
   run_loop.Run();
 }
 
-// Tests the result of cancelling the share in the picker UI.
-TEST_F(ShareServiceImplUnittest, ShareCancel) {
+// Tests the result of cancelling the share in the picker UI, that doesn't have
+// any targets.
+TEST_F(ShareServiceImplUnittest, ShareCancelNoTargets) {
   // picker_result_ is set to nullopt by default, so this imitates the user
   // cancelling a share.
   // Expect an error message in response.
   base::Callback<void(const base::Optional<std::string>&)> callback =
       base::Bind(&ShareServiceImplUnittest::DidShare, base::Unretained(this),
-                 std::string(),
+                 std::vector<std::pair<base::string16, GURL>>(), std::string(),
                  base::Optional<std::string>("Share was cancelled"));
 
   base::RunLoop run_loop;
@@ -129,6 +208,65 @@
   run_loop.Run();
 }
 
+// Tests the result of cancelling the share in the picker UI, that has targets.
+TEST_F(ShareServiceImplUnittest, ShareCancelWithTargets) {
+  // picker_result_ is set to nullopt by default, so this imitates the user
+  // cancelling a share.
+  share_service_helper_->AddShareTargetToPrefs(kManifestUrlHigh, kTargetName,
+                                               kUrlTemplate);
+  share_service_helper_->AddShareTargetToPrefs(kManifestUrlLow, kTargetName,
+                                               kUrlTemplate);
+
+  std::vector<std::pair<base::string16, GURL>> expected_targets{
+      make_pair(base::UTF8ToUTF16(kTargetName), GURL(kManifestUrlHigh)),
+      make_pair(base::UTF8ToUTF16(kTargetName), GURL(kManifestUrlLow))};
+  // Expect an error message in response.
+  base::Callback<void(const base::Optional<std::string>&)> callback =
+      base::Bind(&ShareServiceImplUnittest::DidShare, base::Unretained(this),
+                 expected_targets, std::string(),
+                 base::Optional<std::string>("Share was cancelled"));
+
+  base::RunLoop run_loop;
+  on_callback_ = run_loop.QuitClosure();
+
+  const GURL url(kUrlSpec);
+  share_service_->Share(kTitle, kText, url, callback);
+
+  run_loop.Run();
+}
+
+// Test to check that only targets with enough engagement were in picker.
+TEST_F(ShareServiceImplUnittest, ShareWithSomeInsufficientlyEngagedTargets) {
+  std::string expected_url =
+      "https://www.example-low.com/target/"
+      "share?title=My%20title&text=My%20text&url=https%3A%2F%2Fwww."
+      "google.com%2F";
+
+  share_service_helper_->set_picker_result(
+      base::Optional<std::string>(kManifestUrlLow));
+
+  share_service_helper_->AddShareTargetToPrefs(kManifestUrlMin, kTargetName,
+                                               kUrlTemplate);
+  share_service_helper_->AddShareTargetToPrefs(kManifestUrlLow, kTargetName,
+                                               kUrlTemplate);
+
+  std::vector<std::pair<base::string16, GURL>> expected_targets{
+      make_pair(base::UTF8ToUTF16(kTargetName), GURL(kManifestUrlLow))};
+  base::Callback<void(const base::Optional<std::string>&)> callback =
+      base::Bind(&ShareServiceImplUnittest::DidShare, base::Unretained(this),
+                 expected_targets, expected_url, base::Optional<std::string>());
+
+  base::RunLoop run_loop;
+  on_callback_ = run_loop.QuitClosure();
+
+  const GURL url(kUrlSpec);
+  share_service_->Share(kTitle, kText, url, callback);
+
+  run_loop.Run();
+}
+
+#endif  // defined(OS_LINUX) || defined(OS_WIN)
+
 // Replace various numbers of placeholders in various orders. Placeholders are
 // adjacent to eachother; there are no padding characters.
 TEST_F(ShareServiceImplUnittest, ReplacePlaceholders) {
diff --git a/components/arc/audio/arc_audio_bridge.cc b/components/arc/audio/arc_audio_bridge.cc
index 4aaaa075..bdf7e4fe 100644
--- a/components/arc/audio/arc_audio_bridge.cc
+++ b/components/arc/audio/arc_audio_bridge.cc
@@ -35,7 +35,7 @@
 }
 
 void ArcAudioBridge::ShowVolumeControls() {
-  VLOG(2) << "ArcAudioBridge::ShowVolumeControls";
+  DVLOG(2) << "ArcAudioBridge::ShowVolumeControls";
   ash::TrayAudio::ShowPopUpVolumeView();
 }
 
@@ -54,8 +54,8 @@
       (input_device &&
        input_device->type == chromeos::AudioDeviceType::AUDIO_TYPE_MIC);
 
-  VLOG(1) << "HEADPHONE " << headphone_inserted << " MICROPHONE "
-          << microphone_inserted;
+  DVLOG(1) << "HEADPHONE " << headphone_inserted << " MICROPHONE "
+           << microphone_inserted;
   SendSwitchState(headphone_inserted, microphone_inserted);
 }
 
@@ -83,7 +83,7 @@
         (1 << static_cast<uint32_t>(mojom::AudioSwitch::SW_MICROPHONE_INSERT));
   }
 
-  VLOG(1) << "Send switch state " << switch_state;
+  DVLOG(1) << "Send switch state " << switch_state;
   mojom::AudioInstance* audio_instance = ARC_GET_INSTANCE_FOR_METHOD(
       arc_bridge_service()->audio(), NotifySwitchState);
   if (audio_instance)
diff --git a/headless/BUILD.gn b/headless/BUILD.gn
index 5fd0de8..f57c632 100644
--- a/headless/BUILD.gn
+++ b/headless/BUILD.gn
@@ -207,16 +207,10 @@
               "lib/browser/headless_devtools_manager_delegate.h",
               "lib/browser/headless_platform_event_source.cc",
               "lib/browser/headless_platform_event_source.h",
-              "lib/browser/headless_screen.cc",
-              "lib/browser/headless_screen.h",
               "lib/browser/headless_url_request_context_getter.cc",
               "lib/browser/headless_url_request_context_getter.h",
               "lib/browser/headless_web_contents_impl.cc",
               "lib/browser/headless_web_contents_impl.h",
-              "lib/browser/headless_window_parenting_client.cc",
-              "lib/browser/headless_window_parenting_client.h",
-              "lib/browser/headless_window_tree_host.cc",
-              "lib/browser/headless_window_tree_host.h",
               "lib/headless_content_client.cc",
               "lib/headless_content_client.h",
               "lib/headless_content_main_delegate.cc",
@@ -265,6 +259,18 @@
               "public/util/user_agent.h",
             ]
 
+  if (use_aura) {
+    sources += [
+      "lib/browser/headless_browser_impl_aura.cc",
+      "lib/browser/headless_screen.cc",
+      "lib/browser/headless_screen.h",
+      "lib/browser/headless_window_parenting_client.cc",
+      "lib/browser/headless_window_parenting_client.h",
+      "lib/browser/headless_window_tree_host.cc",
+      "lib/browser/headless_window_tree_host.h",
+    ]
+  }
+
   deps = [
     ":gen_devtools_client_api",
     "//base",
diff --git a/headless/lib/browser/headless_browser_context_impl.cc b/headless/lib/browser/headless_browser_context_impl.cc
index df65523f..0d4de19 100644
--- a/headless/lib/browser/headless_browser_context_impl.cc
+++ b/headless/lib/browser/headless_browser_context_impl.cc
@@ -21,7 +21,6 @@
 #include "headless/public/util/black_hole_protocol_handler.h"
 #include "headless/public/util/in_memory_protocol_handler.h"
 #include "net/url_request/url_request_context.h"
-#include "ui/aura/window_tree_host.h"
 
 namespace headless {
 
@@ -249,8 +248,7 @@
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
   std::unique_ptr<HeadlessWebContentsImpl> headless_web_contents =
-      HeadlessWebContentsImpl::Create(builder,
-                                      browser()->window_tree_host()->window());
+      HeadlessWebContentsImpl::Create(builder);
 
   if (!headless_web_contents) {
     return nullptr;
diff --git a/headless/lib/browser/headless_browser_impl.cc b/headless/lib/browser/headless_browser_impl.cc
index 15a042a..2ce9e1db 100644
--- a/headless/lib/browser/headless_browser_impl.cc
+++ b/headless/lib/browser/headless_browser_impl.cc
@@ -18,8 +18,6 @@
 #include "headless/lib/browser/headless_browser_context_impl.h"
 #include "headless/lib/browser/headless_browser_main_parts.h"
 #include "headless/lib/browser/headless_web_contents_impl.h"
-#include "headless/lib/browser/headless_window_parenting_client.h"
-#include "headless/lib/browser/headless_window_tree_host.h"
 #include "headless/lib/headless_content_main_delegate.h"
 #include "ui/aura/env.h"
 #include "ui/aura/window.h"
@@ -121,17 +119,7 @@
 }
 
 void HeadlessBrowserImpl::RunOnStartCallback() {
-  DCHECK(aura::Env::GetInstance());
-  ui::DeviceDataManager::CreateInstance();
-
-  window_tree_host_.reset(
-      new HeadlessWindowTreeHost(gfx::Rect(options()->window_size)));
-  window_tree_host_->InitHost();
-  window_tree_host_->window()->Show();
-
-  window_parenting_client_.reset(
-      new HeadlessWindowParentingClient(window_tree_host_->window()));
-
+  PlatformCreateWindow();
   on_start_callback_.Run(this);
   on_start_callback_ = base::Callback<void(HeadlessBrowser*)>();
 }
@@ -179,10 +167,6 @@
   return weak_ptr_factory_.GetWeakPtr();
 }
 
-aura::WindowTreeHost* HeadlessBrowserImpl::window_tree_host() const {
-  return window_tree_host_.get();
-}
-
 HeadlessWebContents* HeadlessBrowserImpl::GetWebContentsForDevToolsAgentHostId(
     const std::string& devtools_agent_host_id) {
   for (HeadlessBrowserContext* context : GetAllBrowserContexts()) {
diff --git a/headless/lib/browser/headless_browser_impl.h b/headless/lib/browser/headless_browser_impl.h
index f37dff1d..eb5af5e 100644
--- a/headless/lib/browser/headless_browser_impl.h
+++ b/headless/lib/browser/headless_browser_impl.h
@@ -13,16 +13,13 @@
 #include <vector>
 
 #include "base/memory/weak_ptr.h"
+#include "content/public/browser/web_contents.h"
 #include "headless/lib/browser/headless_devtools_manager_delegate.h"
 #include "headless/lib/browser/headless_web_contents_impl.h"
 
-namespace aura {
-class WindowTreeHost;
-
-namespace client {
-class WindowParentingClient;
-}
-}
+#if defined(USE_AURA)
+#include "headless/lib/browser/headless_window_tree_host.h"
+#endif
 
 namespace headless {
 
@@ -70,18 +67,24 @@
 
   base::WeakPtr<HeadlessBrowserImpl> GetWeakPtr();
 
-  aura::WindowTreeHost* window_tree_host() const;
+  // All the methods that begin with Platform need to be implemented by the
+  // platform specific headless implementation.
+  // Helper for one time initialization of application
+  void PlatformInitialize();
+  void PlatformCreateWindow();
+  void PlatformSetWebContents(const gfx::Size& initial_size,
+                              content::WebContents* web_contents);
 
  protected:
-  base::Callback<void(HeadlessBrowser*)> on_start_callback_;
-  HeadlessBrowser::Options options_;
-  HeadlessBrowserMainParts* browser_main_parts_;  // Not owned.
-
+#if defined(USE_AURA)
   // TODO(eseckler): Currently one window and one window_tree_host
   // is used for all web contents. We should probably use one
   // window per web contents, but additional investigation is needed.
-  std::unique_ptr<aura::WindowTreeHost> window_tree_host_;
-  std::unique_ptr<aura::client::WindowParentingClient> window_parenting_client_;
+  std::unique_ptr<HeadlessWindowTreeHost> window_tree_host_;
+#endif
+  base::Callback<void(HeadlessBrowser*)> on_start_callback_;
+  HeadlessBrowser::Options options_;
+  HeadlessBrowserMainParts* browser_main_parts_;  // Not owned.
 
   std::unordered_map<std::string, std::unique_ptr<HeadlessBrowserContextImpl>>
       browser_contexts_;
diff --git a/headless/lib/browser/headless_browser_impl_aura.cc b/headless/lib/browser/headless_browser_impl_aura.cc
new file mode 100644
index 0000000..d1159d18
--- /dev/null
+++ b/headless/lib/browser/headless_browser_impl_aura.cc
@@ -0,0 +1,50 @@
+// 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 "headless/lib/browser/headless_browser_impl.h"
+
+#include "content/public/browser/render_widget_host_view.h"
+#include "content/public/browser/web_contents.h"
+#include "headless/lib/browser/headless_screen.h"
+#include "ui/aura/env.h"
+#include "ui/aura/window.h"
+#include "ui/display/screen.h"
+#include "ui/events/devices/device_data_manager.h"
+#include "ui/gfx/geometry/size.h"
+
+namespace headless {
+
+void HeadlessBrowserImpl::PlatformInitialize() {
+  HeadlessScreen* screen = HeadlessScreen::Create(options()->window_size);
+  display::Screen::SetScreenInstance(screen);
+}
+
+void HeadlessBrowserImpl::PlatformCreateWindow() {
+  DCHECK(aura::Env::GetInstance());
+  ui::DeviceDataManager::CreateInstance();
+
+  window_tree_host_.reset(
+      new HeadlessWindowTreeHost(gfx::Rect(options()->window_size)));
+  window_tree_host_->InitHost();
+  window_tree_host_->window()->Show();
+  window_tree_host_->SetParentWindow(window_tree_host_->window());
+}
+
+void HeadlessBrowserImpl::PlatformSetWebContents(
+    const gfx::Size& initial_size,
+    content::WebContents* web_contents) {
+  gfx::NativeView contents = web_contents->GetNativeView();
+  gfx::NativeWindow parent_window = window_tree_host_->window();
+  DCHECK(!parent_window->Contains(contents));
+  parent_window->AddChild(contents);
+  contents->Show();
+  contents->SetBounds(gfx::Rect(initial_size));
+
+  content::RenderWidgetHostView* host_view =
+      web_contents->GetRenderWidgetHostView();
+  if (host_view)
+    host_view->SetSize(initial_size);
+}
+
+}  // namespace headless
diff --git a/headless/lib/browser/headless_browser_main_parts.cc b/headless/lib/browser/headless_browser_main_parts.cc
index b219480b..2ae52c3 100644
--- a/headless/lib/browser/headless_browser_main_parts.cc
+++ b/headless/lib/browser/headless_browser_main_parts.cc
@@ -8,23 +8,9 @@
 #include "headless/lib/browser/headless_browser_impl.h"
 #include "headless/lib/browser/headless_devtools.h"
 #include "headless/lib/browser/headless_screen.h"
-#include "ui/aura/env.h"
-#include "ui/display/screen.h"
 
 namespace headless {
 
-namespace {
-
-void PlatformInitialize(const gfx::Size& screen_size) {
-  HeadlessScreen* screen = HeadlessScreen::Create(screen_size);
-  display::Screen::SetScreenInstance(screen);
-}
-
-void PlatformExit() {
-}
-
-}  // namespace
-
 HeadlessBrowserMainParts::HeadlessBrowserMainParts(HeadlessBrowserImpl* browser)
     : browser_(browser)
     , devtools_http_handler_started_(false) {}
@@ -36,7 +22,7 @@
     StartLocalDevToolsHttpHandler(browser_->options());
     devtools_http_handler_started_ = true;
   }
-  PlatformInitialize(browser_->options()->window_size);
+  browser_->PlatformInitialize();
 }
 
 void HeadlessBrowserMainParts::PostMainMessageLoopRun() {
@@ -44,7 +30,6 @@
     StopLocalDevToolsHttpHandler();
     devtools_http_handler_started_ = false;
   }
-  PlatformExit();
 }
 
 }  // namespace headless
diff --git a/headless/lib/browser/headless_screen.cc b/headless/lib/browser/headless_screen.cc
index 9cc1e474..1d329885 100644
--- a/headless/lib/browser/headless_screen.cc
+++ b/headless/lib/browser/headless_screen.cc
@@ -9,8 +9,6 @@
 #include "base/logging.h"
 #include "ui/aura/env.h"
 #include "ui/aura/window.h"
-#include "ui/aura/window_event_dispatcher.h"
-#include "ui/aura/window_tree_host.h"
 #include "ui/base/ime/input_method.h"
 #include "ui/gfx/geometry/rect_conversions.h"
 #include "ui/gfx/geometry/size_conversions.h"
@@ -18,15 +16,6 @@
 
 namespace headless {
 
-namespace {
-
-bool IsRotationPortrait(display::Display::Rotation rotation) {
-  return rotation == display::Display::ROTATE_90 ||
-         rotation == display::Display::ROTATE_270;
-}
-
-}  // namespace
-
 // static
 HeadlessScreen* HeadlessScreen::Create(const gfx::Size& size) {
   return new HeadlessScreen(gfx::Rect(size));
@@ -34,101 +23,6 @@
 
 HeadlessScreen::~HeadlessScreen() {}
 
-aura::WindowTreeHost* HeadlessScreen::CreateHostForPrimaryDisplay() {
-  DCHECK(!host_);
-  host_ = aura::WindowTreeHost::Create(
-      gfx::Rect(GetPrimaryDisplay().GetSizeInPixel()));
-  // Some tests don't correctly manage window focus/activation states.
-  // Makes sure InputMethod is default focused so that IME basics can work.
-  host_->GetInputMethod()->OnFocus();
-  host_->window()->AddObserver(this);
-  host_->InitHost();
-  host_->window()->Show();
-  return host_;
-}
-
-void HeadlessScreen::SetDeviceScaleFactor(float device_scale_factor) {
-  display::Display display(GetPrimaryDisplay());
-  gfx::Rect bounds_in_pixel(display.GetSizeInPixel());
-  display.SetScaleAndBounds(device_scale_factor, bounds_in_pixel);
-  display_list().UpdateDisplay(display);
-}
-
-void HeadlessScreen::SetDisplayRotation(display::Display::Rotation rotation) {
-  display::Display display(GetPrimaryDisplay());
-  gfx::Rect bounds_in_pixel(display.GetSizeInPixel());
-  gfx::Rect new_bounds(bounds_in_pixel);
-  if (IsRotationPortrait(rotation) != IsRotationPortrait(display.rotation())) {
-    new_bounds.set_width(bounds_in_pixel.height());
-    new_bounds.set_height(bounds_in_pixel.width());
-  }
-  display.set_rotation(rotation);
-  display.SetScaleAndBounds(display.device_scale_factor(), new_bounds);
-  display_list().UpdateDisplay(display);
-  host_->SetRootTransform(GetRotationTransform() * GetUIScaleTransform());
-}
-
-void HeadlessScreen::SetUIScale(float ui_scale) {
-  ui_scale_ = ui_scale;
-  display::Display display(GetPrimaryDisplay());
-  gfx::Rect bounds_in_pixel(display.GetSizeInPixel());
-  gfx::Rect new_bounds = gfx::ToNearestRect(
-      gfx::ScaleRect(gfx::RectF(bounds_in_pixel), 1.0f / ui_scale));
-  display.SetScaleAndBounds(display.device_scale_factor(), new_bounds);
-  display_list().UpdateDisplay(display);
-  host_->SetRootTransform(GetRotationTransform() * GetUIScaleTransform());
-}
-
-void HeadlessScreen::SetWorkAreaInsets(const gfx::Insets& insets) {
-  display::Display display(GetPrimaryDisplay());
-  display.UpdateWorkAreaFromInsets(insets);
-  display_list().UpdateDisplay(display);
-}
-
-gfx::Transform HeadlessScreen::GetRotationTransform() const {
-  gfx::Transform rotate;
-  display::Display display(GetPrimaryDisplay());
-  switch (display.rotation()) {
-    case display::Display::ROTATE_0:
-      break;
-    case display::Display::ROTATE_90:
-      rotate.Translate(display.bounds().height(), 0);
-      rotate.Rotate(90);
-      break;
-    case display::Display::ROTATE_270:
-      rotate.Translate(0, display.bounds().width());
-      rotate.Rotate(270);
-      break;
-    case display::Display::ROTATE_180:
-      rotate.Translate(display.bounds().width(), display.bounds().height());
-      rotate.Rotate(180);
-      break;
-  }
-
-  return rotate;
-}
-
-gfx::Transform HeadlessScreen::GetUIScaleTransform() const {
-  gfx::Transform ui_scale;
-  ui_scale.Scale(1.0f / ui_scale_, 1.0f / ui_scale_);
-  return ui_scale;
-}
-
-void HeadlessScreen::OnWindowBoundsChanged(aura::Window* window,
-                                           const gfx::Rect& old_bounds,
-                                           const gfx::Rect& new_bounds) {
-  DCHECK_EQ(host_->window(), window);
-  display::Display display(GetPrimaryDisplay());
-  display.SetSize(gfx::ScaleToFlooredSize(new_bounds.size(),
-                                          display.device_scale_factor()));
-  display_list().UpdateDisplay(display);
-}
-
-void HeadlessScreen::OnWindowDestroying(aura::Window* window) {
-  if (host_->window() == window)
-    host_ = NULL;
-}
-
 gfx::Point HeadlessScreen::GetCursorScreenPoint() {
   return aura::Env::GetInstance()->last_mouse_location();
 }
@@ -139,18 +33,15 @@
 
 gfx::NativeWindow HeadlessScreen::GetWindowAtScreenPoint(
     const gfx::Point& point) {
-  if (!host_ || !host_->window())
-    return nullptr;
-  return host_->window()->GetTopWindowContainingPoint(point);
+  return nullptr;
 }
 
 display::Display HeadlessScreen::GetDisplayNearestWindow(
-    gfx::NativeWindow window) const {
+    gfx::NativeView window) const {
   return GetPrimaryDisplay();
 }
 
-HeadlessScreen::HeadlessScreen(const gfx::Rect& screen_bounds)
-    : host_(NULL), ui_scale_(1.0f) {
+HeadlessScreen::HeadlessScreen(const gfx::Rect& screen_bounds) {
   static int64_t synthesized_display_id = 2000;
   display::Display display(synthesized_display_id++);
   display.SetScaleAndBounds(1.0f, screen_bounds);
diff --git a/headless/lib/browser/headless_screen.h b/headless/lib/browser/headless_screen.h
index 8c5cb98..b8331a6 100644
--- a/headless/lib/browser/headless_screen.h
+++ b/headless/lib/browser/headless_screen.h
@@ -12,41 +12,18 @@
 #include "ui/display/screen_base.h"
 
 namespace gfx {
-class Insets;
 class Rect;
-class Transform;
-}
-
-namespace aura {
-class Window;
-class WindowTreeHost;
 }
 
 namespace headless {
 
-class HeadlessScreen : public display::ScreenBase, public aura::WindowObserver {
+class HeadlessScreen : public display::ScreenBase {
  public:
   // Creates a display::Screen of the specified size (physical pixels).
   static HeadlessScreen* Create(const gfx::Size& size);
   ~HeadlessScreen() override;
 
-  aura::WindowTreeHost* CreateHostForPrimaryDisplay();
-
-  void SetDeviceScaleFactor(float device_scale_fator);
-  void SetDisplayRotation(display::Display::Rotation rotation);
-  void SetUIScale(float ui_scale);
-  void SetWorkAreaInsets(const gfx::Insets& insets);
-
  protected:
-  gfx::Transform GetRotationTransform() const;
-  gfx::Transform GetUIScaleTransform() const;
-
-  // WindowObserver overrides:
-  void OnWindowBoundsChanged(aura::Window* window,
-                             const gfx::Rect& old_bounds,
-                             const gfx::Rect& new_bounds) override;
-  void OnWindowDestroying(aura::Window* window) override;
-
   // display::Screen overrides:
   gfx::Point GetCursorScreenPoint() override;
   bool IsWindowUnderCursor(gfx::NativeWindow window) override;
@@ -56,9 +33,6 @@
  private:
   explicit HeadlessScreen(const gfx::Rect& screen_bounds);
 
-  aura::WindowTreeHost* host_;
-  float ui_scale_;
-
   DISALLOW_COPY_AND_ASSIGN(HeadlessScreen);
 };
 
diff --git a/headless/lib/browser/headless_web_contents_impl.cc b/headless/lib/browser/headless_web_contents_impl.cc
index 094979f..6320a12 100644
--- a/headless/lib/browser/headless_web_contents_impl.cc
+++ b/headless/lib/browser/headless_web_contents_impl.cc
@@ -21,7 +21,6 @@
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/render_view_host.h"
-#include "content/public/browser/render_widget_host_view.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/browser/web_contents_delegate.h"
 #include "content/public/common/bindings_policy.h"
@@ -31,7 +30,6 @@
 #include "headless/lib/browser/headless_browser_main_parts.h"
 #include "headless/lib/browser/headless_devtools_client_impl.h"
 #include "services/service_manager/public/cpp/interface_registry.h"
-#include "ui/aura/window.h"
 
 namespace headless {
 
@@ -106,8 +104,7 @@
 
 // static
 std::unique_ptr<HeadlessWebContentsImpl> HeadlessWebContentsImpl::Create(
-    HeadlessWebContents::Builder* builder,
-    aura::Window* parent_window) {
+    HeadlessWebContents::Builder* builder) {
   content::WebContents::CreateParams create_params(builder->browser_context_,
                                                    nullptr);
   create_params.initial_size = builder->window_size_;
@@ -118,7 +115,7 @@
           builder->browser_context_));
 
   headless_web_contents->mojo_services_ = std::move(builder->mojo_services_);
-  headless_web_contents->InitializeScreen(parent_window, builder->window_size_);
+  headless_web_contents->InitializeScreen(builder->window_size_);
   if (!headless_web_contents->OpenURL(builder->initial_url_))
     return nullptr;
   return headless_web_contents;
@@ -136,18 +133,8 @@
   return headless_web_contents;
 }
 
-void HeadlessWebContentsImpl::InitializeScreen(aura::Window* parent_window,
-                                               const gfx::Size& initial_size) {
-  aura::Window* contents = web_contents_->GetNativeView();
-  DCHECK(!parent_window->Contains(contents));
-  parent_window->AddChild(contents);
-  contents->Show();
-
-  contents->SetBounds(gfx::Rect(initial_size));
-  content::RenderWidgetHostView* host_view =
-      web_contents_->GetRenderWidgetHostView();
-  if (host_view)
-    host_view->SetSize(initial_size);
+void HeadlessWebContentsImpl::InitializeScreen(const gfx::Size& initial_size) {
+  browser()->PlatformSetWebContents(initial_size, web_contents_.get());
 }
 
 HeadlessWebContentsImpl::HeadlessWebContentsImpl(
diff --git a/headless/lib/browser/headless_web_contents_impl.h b/headless/lib/browser/headless_web_contents_impl.h
index a18a46a..3346c64 100644
--- a/headless/lib/browser/headless_web_contents_impl.h
+++ b/headless/lib/browser/headless_web_contents_impl.h
@@ -15,10 +15,6 @@
 #include "headless/public/headless_devtools_target.h"
 #include "headless/public/headless_web_contents.h"
 
-namespace aura {
-class Window;
-}
-
 namespace content {
 class DevToolsAgentHost;
 class WebContents;
@@ -42,8 +38,7 @@
   static HeadlessWebContentsImpl* From(HeadlessWebContents* web_contents);
 
   static std::unique_ptr<HeadlessWebContentsImpl> Create(
-      HeadlessWebContents::Builder* builder,
-      aura::Window* parent_window);
+      HeadlessWebContents::Builder* builder);
 
   // Takes ownership of |web_contents|.
   static std::unique_ptr<HeadlessWebContentsImpl> CreateFromWebContents(
@@ -85,8 +80,7 @@
   HeadlessWebContentsImpl(content::WebContents* web_contents,
                           HeadlessBrowserContextImpl* browser_context);
 
-  void InitializeScreen(aura::Window* parent_window,
-                        const gfx::Size& initial_size);
+  void InitializeScreen(const gfx::Size& initial_size);
 
   using MojoService = HeadlessWebContents::Builder::MojoService;
 
diff --git a/headless/lib/browser/headless_window_tree_host.cc b/headless/lib/browser/headless_window_tree_host.cc
index 96cec1a..5cae74e 100644
--- a/headless/lib/browser/headless_window_tree_host.cc
+++ b/headless/lib/browser/headless_window_tree_host.cc
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include "headless/lib/browser/headless_window_tree_host.h"
+#include "ui/aura/window.h"
 
 #include "ui/gfx/icc_profile.h"
 
@@ -15,10 +16,15 @@
 }
 
 HeadlessWindowTreeHost::~HeadlessWindowTreeHost() {
+  window_parenting_client_.reset();
   DestroyCompositor();
   DestroyDispatcher();
 }
 
+void HeadlessWindowTreeHost::SetParentWindow(gfx::NativeWindow window) {
+  window_parenting_client_.reset(new HeadlessWindowParentingClient(window));
+}
+
 bool HeadlessWindowTreeHost::CanDispatchEvent(const ui::PlatformEvent& event) {
   return false;
 }
diff --git a/headless/lib/browser/headless_window_tree_host.h b/headless/lib/browser/headless_window_tree_host.h
index c01545c..0aadfc87 100644
--- a/headless/lib/browser/headless_window_tree_host.h
+++ b/headless/lib/browser/headless_window_tree_host.h
@@ -5,7 +5,10 @@
 #ifndef HEADLESS_LIB_BROWSER_HEADLESS_WINDOW_TREE_HOST_H_
 #define HEADLESS_LIB_BROWSER_HEADLESS_WINDOW_TREE_HOST_H_
 
+#include <memory>
+
 #include "base/macros.h"
+#include "headless/lib/browser/headless_window_parenting_client.h"
 #include "ui/aura/window_tree_host.h"
 #include "ui/events/platform/platform_event_dispatcher.h"
 #include "ui/gfx/geometry/rect.h"
@@ -18,6 +21,8 @@
   explicit HeadlessWindowTreeHost(const gfx::Rect& bounds);
   ~HeadlessWindowTreeHost() override;
 
+  void SetParentWindow(gfx::NativeWindow window);
+
   // ui::PlatformEventDispatcher:
   bool CanDispatchEvent(const ui::PlatformEvent& event) override;
   uint32_t DispatchEvent(const ui::PlatformEvent& event) override;
@@ -39,6 +44,7 @@
 
  private:
   gfx::Rect bounds_;
+  std::unique_ptr<aura::client::WindowParentingClient> window_parenting_client_;
 
   DISALLOW_COPY_AND_ASSIGN(HeadlessWindowTreeHost);
 };
diff --git a/third_party/WebKit/LayoutTests/animations/composition/rotate-composition.html b/third_party/WebKit/LayoutTests/animations/composition/rotate-composition.html
index ae01bc3..5b5359c9 100644
--- a/third_party/WebKit/LayoutTests/animations/composition/rotate-composition.html
+++ b/third_party/WebKit/LayoutTests/animations/composition/rotate-composition.html
@@ -107,7 +107,7 @@
   replaceTo: '0 1 0 100deg',
 }, [
   {at: -1, is: '0 1 0 -100deg'},
-  {at: 0, is: '0deg'},
+  {at: 0, is: 'none'},
   {at: 0.25, is: '-1.20172e-16 1 -3.60516e-16 25deg'},
   {at: 0.75, is: '-1.51909e-17 1 -4.55726e-17 75deg'},
   {at: 1, is: '0 1 0 100deg'},
@@ -124,7 +124,7 @@
   {at: 0, is: '2 4 6 270deg'},
   {at: 0.25, is: '2 4 6 202.5deg'},
   {at: 0.75, is: '2 4 6 67.5deg'},
-  {at: 1, is: '0deg'},
+  {at: 1, is: 'none'},
   {at: 2, is: '2 4 6 -270deg'},
 ]);
 
@@ -152,7 +152,7 @@
   {at: 0, is: '1 2 3 360deg'},
   {at: 0.25, is: '1 2 3 270deg'},
   {at: 0.75, is: '1 2 3 90deg'},
-  {at: 1, is: '0deg'},
+  {at: 1, is: 'none'},
   {at: 2, is: '1 2 3 -360deg'},
 ]);
 </script>
diff --git a/third_party/WebKit/LayoutTests/animations/interpolation/rotate-interpolation-expected.txt b/third_party/WebKit/LayoutTests/animations/interpolation/rotate-interpolation-expected.txt
deleted file mode 100644
index 7d1b36c..0000000
--- a/third_party/WebKit/LayoutTests/animations/interpolation/rotate-interpolation-expected.txt
+++ /dev/null
@@ -1,202 +0,0 @@
-This is a testharness.js-based test.
-PASS This test uses interpolation-test.js. 
-PASS CSS Transitions: property <rotate> from [none] to [30deg] at (-1) is [-30deg] 
-PASS CSS Transitions: property <rotate> from [none] to [30deg] at (0) is [none] 
-PASS CSS Transitions: property <rotate> from [none] to [30deg] at (0.25) is [7.5deg] 
-PASS CSS Transitions: property <rotate> from [none] to [30deg] at (0.75) is [22.5deg] 
-PASS CSS Transitions: property <rotate> from [none] to [30deg] at (1) is [30deg] 
-PASS CSS Transitions: property <rotate> from [none] to [30deg] at (2) is [60deg] 
-PASS CSS Transitions: property <rotate> from neutral to [30deg] at (-1) is [-10deg] 
-PASS CSS Transitions: property <rotate> from neutral to [30deg] at (0) is [10deg] 
-PASS CSS Transitions: property <rotate> from neutral to [30deg] at (0.25) is [15deg] 
-PASS CSS Transitions: property <rotate> from neutral to [30deg] at (0.75) is [25deg] 
-PASS CSS Transitions: property <rotate> from neutral to [30deg] at (1) is [30deg] 
-PASS CSS Transitions: property <rotate> from neutral to [30deg] at (2) is [50deg] 
-PASS CSS Transitions: property <rotate> from [unset] to [30deg] at (-1) is [-30deg] 
-PASS CSS Transitions: property <rotate> from [unset] to [30deg] at (0) is [none] 
-PASS CSS Transitions: property <rotate> from [unset] to [30deg] at (0.25) is [7.5deg] 
-PASS CSS Transitions: property <rotate> from [unset] to [30deg] at (0.75) is [22.5deg] 
-PASS CSS Transitions: property <rotate> from [unset] to [30deg] at (1) is [30deg] 
-PASS CSS Transitions: property <rotate> from [unset] to [30deg] at (2) is [60deg] 
-PASS CSS Transitions: property <rotate> from [100deg] to [-100deg] at (-1) is [300deg] 
-PASS CSS Transitions: property <rotate> from [100deg] to [-100deg] at (0) is [100deg] 
-PASS CSS Transitions: property <rotate> from [100deg] to [-100deg] at (0.25) is [50deg] 
-PASS CSS Transitions: property <rotate> from [100deg] to [-100deg] at (0.75) is [-50deg] 
-PASS CSS Transitions: property <rotate> from [100deg] to [-100deg] at (1) is [-100deg] 
-PASS CSS Transitions: property <rotate> from [100deg] to [-100deg] at (2) is [-300deg] 
-PASS CSS Transitions: property <rotate> from [100deg] to [-100deg] at (-1) is [300deg] 
-PASS CSS Transitions: property <rotate> from [100deg] to [-100deg] at (0) is [100deg] 
-PASS CSS Transitions: property <rotate> from [100deg] to [-100deg] at (0.25) is [50deg] 
-PASS CSS Transitions: property <rotate> from [100deg] to [-100deg] at (0.75) is [-50deg] 
-PASS CSS Transitions: property <rotate> from [100deg] to [-100deg] at (1) is [-100deg] 
-PASS CSS Transitions: property <rotate> from [100deg] to [-100deg] at (2) is [-300deg] 
-PASS CSS Transitions: property <rotate> from [0 1 0 100deg] to [0 1 0 -100deg] at (-1) is [0 1 0 300deg] 
-PASS CSS Transitions: property <rotate> from [0 1 0 100deg] to [0 1 0 -100deg] at (0) is [0 1 0 100deg] 
-PASS CSS Transitions: property <rotate> from [0 1 0 100deg] to [0 1 0 -100deg] at (0.25) is [0 1 0 50deg] 
-PASS CSS Transitions: property <rotate> from [0 1 0 100deg] to [0 1 0 -100deg] at (0.75) is [0 1 0 -50deg] 
-PASS CSS Transitions: property <rotate> from [0 1 0 100deg] to [0 1 0 -100deg] at (1) is [0 1 0 -100deg] 
-PASS CSS Transitions: property <rotate> from [0 1 0 100deg] to [0 1 0 -100deg] at (2) is [0 1 0 -300deg] 
-PASS CSS Transitions: property <rotate> from [1 -2.5 3.64 100deg] to [1 -2.5 3.64 -100deg] at (-1) is [1 -2.5 3.64 300deg] 
-PASS CSS Transitions: property <rotate> from [1 -2.5 3.64 100deg] to [1 -2.5 3.64 -100deg] at (0) is [1 -2.5 3.64 100deg] 
-PASS CSS Transitions: property <rotate> from [1 -2.5 3.64 100deg] to [1 -2.5 3.64 -100deg] at (0.25) is [1 -2.5 3.64 50deg] 
-PASS CSS Transitions: property <rotate> from [1 -2.5 3.64 100deg] to [1 -2.5 3.64 -100deg] at (0.75) is [1 -2.5 3.64 -50deg] 
-PASS CSS Transitions: property <rotate> from [1 -2.5 3.64 100deg] to [1 -2.5 3.64 -100deg] at (1) is [1 -2.5 3.64 -100deg] 
-PASS CSS Transitions: property <rotate> from [1 -2.5 3.64 100deg] to [1 -2.5 3.64 -100deg] at (2) is [1 -2.5 3.64 -300deg] 
-PASS CSS Transitions: property <rotate> from [1 0 0 0deg] to [0 1 0 10deg] at (-1) is [0 1 0 -10deg] 
-PASS CSS Transitions: property <rotate> from [1 0 0 0deg] to [0 1 0 10deg] at (0) is [1 0 0 0deg] 
-PASS CSS Transitions: property <rotate> from [1 0 0 0deg] to [0 1 0 10deg] at (0.25) is [0 1 0 2.5deg] 
-PASS CSS Transitions: property <rotate> from [1 0 0 0deg] to [0 1 0 10deg] at (0.75) is [0 1 0 7.5deg] 
-PASS CSS Transitions: property <rotate> from [1 0 0 0deg] to [0 1 0 10deg] at (1) is [0 1 0 10deg] 
-PASS CSS Transitions: property <rotate> from [1 0 0 0deg] to [0 1 0 10deg] at (2) is [0 1 0 20deg] 
-PASS CSS Transitions: property <rotate> from [1 1 0 90deg] to [0 1 1 135deg] at (-1) is [0.673392 -0.0631886 -0.73658 124.975deg] 
-PASS CSS Transitions: property <rotate> from [1 1 0 90deg] to [0 1 1 135deg] at (0) is [1 1 0 90deg] 
-PASS CSS Transitions: property <rotate> from [1 1 0 90deg] to [0 1 1 135deg] at (0.25) is [0.544172 0.799255 0.255083 94.834deg] 
-PASS CSS Transitions: property <rotate> from [1 1 0 90deg] to [0 1 1 135deg] at (0.75) is [0.167111 0.775694 0.608583 118.679deg] 
-PASS CSS Transitions: property <rotate> from [1 1 0 90deg] to [0 1 1 135deg] at (1) is [0 1 1 135deg] 
-PASS CSS Transitions: property <rotate> from [1 1 0 90deg] to [0 1 1 135deg] at (2) is [0.516398 -0.289524 -0.805921 151.045deg] 
-PASS CSS Transitions: property <rotate> from [0 1 0 0deg] to [1 0 0 450deg] at (-1) is [1 0 0 -450deg] 
-PASS CSS Transitions: property <rotate> from [0 1 0 0deg] to [1 0 0 450deg] at (0) is [0 1 0 0deg] 
-PASS CSS Transitions: property <rotate> from [0 1 0 0deg] to [1 0 0 450deg] at (0.25) is [1 0 0 112.5deg] 
-PASS CSS Transitions: property <rotate> from [0 1 0 0deg] to [1 0 0 450deg] at (0.75) is [1 0 0 337.5deg] 
-PASS CSS Transitions: property <rotate> from [0 1 0 0deg] to [1 0 0 450deg] at (1) is [1 0 0 450deg] 
-PASS CSS Transitions: property <rotate> from [0 1 0 0deg] to [1 0 0 450deg] at (2) is [1 0 0 900deg] 
-PASS CSS Transitions: property <rotate> from [1 0 0 450deg] to [0 1 0 0deg] at (-1) is [1 0 0 900deg] 
-PASS CSS Transitions: property <rotate> from [1 0 0 450deg] to [0 1 0 0deg] at (0) is [1 0 0 450deg] 
-PASS CSS Transitions: property <rotate> from [1 0 0 450deg] to [0 1 0 0deg] at (0.25) is [1 0 0 337.5deg] 
-PASS CSS Transitions: property <rotate> from [1 0 0 450deg] to [0 1 0 0deg] at (0.75) is [1 0 0 112.5deg] 
-PASS CSS Transitions: property <rotate> from [1 0 0 450deg] to [0 1 0 0deg] at (1) is [0 1 0 0deg] 
-PASS CSS Transitions: property <rotate> from [1 0 0 450deg] to [0 1 0 0deg] at (2) is [1 0 0 -450deg] 
-PASS CSS Animations: property <rotate> from [none] to [30deg] at (-1) is [-30deg] 
-FAIL CSS Animations: property <rotate> from [none] to [30deg] at (0) is [0deg] assert_equals: expected "none " but got "0deg "
-PASS CSS Animations: property <rotate> from [none] to [30deg] at (0.25) is [7.5deg] 
-PASS CSS Animations: property <rotate> from [none] to [30deg] at (0.75) is [22.5deg] 
-PASS CSS Animations: property <rotate> from [none] to [30deg] at (1) is [30deg] 
-PASS CSS Animations: property <rotate> from [none] to [30deg] at (2) is [60deg] 
-PASS CSS Animations: property <rotate> from neutral to [30deg] at (-1) is [-10deg] 
-PASS CSS Animations: property <rotate> from neutral to [30deg] at (0) is [10deg] 
-PASS CSS Animations: property <rotate> from neutral to [30deg] at (0.25) is [15deg] 
-PASS CSS Animations: property <rotate> from neutral to [30deg] at (0.75) is [25deg] 
-PASS CSS Animations: property <rotate> from neutral to [30deg] at (1) is [30deg] 
-PASS CSS Animations: property <rotate> from neutral to [30deg] at (2) is [50deg] 
-PASS CSS Animations: property <rotate> from [unset] to [30deg] at (-1) is [-30deg] 
-FAIL CSS Animations: property <rotate> from [unset] to [30deg] at (0) is [0deg] assert_equals: expected "none " but got "0deg "
-PASS CSS Animations: property <rotate> from [unset] to [30deg] at (0.25) is [7.5deg] 
-PASS CSS Animations: property <rotate> from [unset] to [30deg] at (0.75) is [22.5deg] 
-PASS CSS Animations: property <rotate> from [unset] to [30deg] at (1) is [30deg] 
-PASS CSS Animations: property <rotate> from [unset] to [30deg] at (2) is [60deg] 
-PASS CSS Animations: property <rotate> from [100deg] to [-100deg] at (-1) is [300deg] 
-PASS CSS Animations: property <rotate> from [100deg] to [-100deg] at (0) is [100deg] 
-PASS CSS Animations: property <rotate> from [100deg] to [-100deg] at (0.25) is [50deg] 
-PASS CSS Animations: property <rotate> from [100deg] to [-100deg] at (0.75) is [-50deg] 
-PASS CSS Animations: property <rotate> from [100deg] to [-100deg] at (1) is [-100deg] 
-PASS CSS Animations: property <rotate> from [100deg] to [-100deg] at (2) is [-300deg] 
-PASS CSS Animations: property <rotate> from [100deg] to [-100deg] at (-1) is [300deg] 
-PASS CSS Animations: property <rotate> from [100deg] to [-100deg] at (0) is [100deg] 
-PASS CSS Animations: property <rotate> from [100deg] to [-100deg] at (0.25) is [50deg] 
-PASS CSS Animations: property <rotate> from [100deg] to [-100deg] at (0.75) is [-50deg] 
-PASS CSS Animations: property <rotate> from [100deg] to [-100deg] at (1) is [-100deg] 
-PASS CSS Animations: property <rotate> from [100deg] to [-100deg] at (2) is [-300deg] 
-PASS CSS Animations: property <rotate> from [0 1 0 100deg] to [0 1 0 -100deg] at (-1) is [0 1 0 300deg] 
-PASS CSS Animations: property <rotate> from [0 1 0 100deg] to [0 1 0 -100deg] at (0) is [0 1 0 100deg] 
-PASS CSS Animations: property <rotate> from [0 1 0 100deg] to [0 1 0 -100deg] at (0.25) is [0 1 0 50deg] 
-PASS CSS Animations: property <rotate> from [0 1 0 100deg] to [0 1 0 -100deg] at (0.75) is [0 1 0 -50deg] 
-PASS CSS Animations: property <rotate> from [0 1 0 100deg] to [0 1 0 -100deg] at (1) is [0 1 0 -100deg] 
-PASS CSS Animations: property <rotate> from [0 1 0 100deg] to [0 1 0 -100deg] at (2) is [0 1 0 -300deg] 
-PASS CSS Animations: property <rotate> from [1 -2.5 3.64 100deg] to [1 -2.5 3.64 -100deg] at (-1) is [1 -2.5 3.64 300deg] 
-PASS CSS Animations: property <rotate> from [1 -2.5 3.64 100deg] to [1 -2.5 3.64 -100deg] at (0) is [1 -2.5 3.64 100deg] 
-PASS CSS Animations: property <rotate> from [1 -2.5 3.64 100deg] to [1 -2.5 3.64 -100deg] at (0.25) is [1 -2.5 3.64 50deg] 
-PASS CSS Animations: property <rotate> from [1 -2.5 3.64 100deg] to [1 -2.5 3.64 -100deg] at (0.75) is [1 -2.5 3.64 -50deg] 
-PASS CSS Animations: property <rotate> from [1 -2.5 3.64 100deg] to [1 -2.5 3.64 -100deg] at (1) is [1 -2.5 3.64 -100deg] 
-PASS CSS Animations: property <rotate> from [1 -2.5 3.64 100deg] to [1 -2.5 3.64 -100deg] at (2) is [1 -2.5 3.64 -300deg] 
-PASS CSS Animations: property <rotate> from [1 0 0 0deg] to [0 1 0 10deg] at (-1) is [0 1 0 -10deg] 
-PASS CSS Animations: property <rotate> from [1 0 0 0deg] to [0 1 0 10deg] at (0) is [1 0 0 0deg] 
-PASS CSS Animations: property <rotate> from [1 0 0 0deg] to [0 1 0 10deg] at (0.25) is [0 1 0 2.5deg] 
-PASS CSS Animations: property <rotate> from [1 0 0 0deg] to [0 1 0 10deg] at (0.75) is [0 1 0 7.5deg] 
-PASS CSS Animations: property <rotate> from [1 0 0 0deg] to [0 1 0 10deg] at (1) is [0 1 0 10deg] 
-PASS CSS Animations: property <rotate> from [1 0 0 0deg] to [0 1 0 10deg] at (2) is [0 1 0 20deg] 
-PASS CSS Animations: property <rotate> from [1 1 0 90deg] to [0 1 1 135deg] at (-1) is [0.673392 -0.0631886 -0.73658 124.975deg] 
-PASS CSS Animations: property <rotate> from [1 1 0 90deg] to [0 1 1 135deg] at (0) is [1 1 0 90deg] 
-PASS CSS Animations: property <rotate> from [1 1 0 90deg] to [0 1 1 135deg] at (0.25) is [0.544172 0.799255 0.255083 94.834deg] 
-PASS CSS Animations: property <rotate> from [1 1 0 90deg] to [0 1 1 135deg] at (0.75) is [0.167111 0.775694 0.608583 118.679deg] 
-PASS CSS Animations: property <rotate> from [1 1 0 90deg] to [0 1 1 135deg] at (1) is [0 1 1 135deg] 
-PASS CSS Animations: property <rotate> from [1 1 0 90deg] to [0 1 1 135deg] at (2) is [0.516398 -0.289524 -0.805921 151.045deg] 
-PASS CSS Animations: property <rotate> from [0 1 0 0deg] to [1 0 0 450deg] at (-1) is [1 0 0 -450deg] 
-PASS CSS Animations: property <rotate> from [0 1 0 0deg] to [1 0 0 450deg] at (0) is [0 1 0 0deg] 
-PASS CSS Animations: property <rotate> from [0 1 0 0deg] to [1 0 0 450deg] at (0.25) is [1 0 0 112.5deg] 
-PASS CSS Animations: property <rotate> from [0 1 0 0deg] to [1 0 0 450deg] at (0.75) is [1 0 0 337.5deg] 
-PASS CSS Animations: property <rotate> from [0 1 0 0deg] to [1 0 0 450deg] at (1) is [1 0 0 450deg] 
-PASS CSS Animations: property <rotate> from [0 1 0 0deg] to [1 0 0 450deg] at (2) is [1 0 0 900deg] 
-PASS CSS Animations: property <rotate> from [1 0 0 450deg] to [0 1 0 0deg] at (-1) is [1 0 0 900deg] 
-PASS CSS Animations: property <rotate> from [1 0 0 450deg] to [0 1 0 0deg] at (0) is [1 0 0 450deg] 
-PASS CSS Animations: property <rotate> from [1 0 0 450deg] to [0 1 0 0deg] at (0.25) is [1 0 0 337.5deg] 
-PASS CSS Animations: property <rotate> from [1 0 0 450deg] to [0 1 0 0deg] at (0.75) is [1 0 0 112.5deg] 
-PASS CSS Animations: property <rotate> from [1 0 0 450deg] to [0 1 0 0deg] at (1) is [0 1 0 0deg] 
-PASS CSS Animations: property <rotate> from [1 0 0 450deg] to [0 1 0 0deg] at (2) is [1 0 0 -450deg] 
-PASS Web Animations: property <rotate> from [none] to [30deg] at (-1) is [-30deg] 
-FAIL Web Animations: property <rotate> from [none] to [30deg] at (0) is [0deg] assert_equals: expected "none " but got "0deg "
-PASS Web Animations: property <rotate> from [none] to [30deg] at (0.25) is [7.5deg] 
-PASS Web Animations: property <rotate> from [none] to [30deg] at (0.75) is [22.5deg] 
-PASS Web Animations: property <rotate> from [none] to [30deg] at (1) is [30deg] 
-PASS Web Animations: property <rotate> from [none] to [30deg] at (2) is [60deg] 
-PASS Web Animations: property <rotate> from neutral to [30deg] at (-1) is [-10deg] 
-PASS Web Animations: property <rotate> from neutral to [30deg] at (0) is [10deg] 
-PASS Web Animations: property <rotate> from neutral to [30deg] at (0.25) is [15deg] 
-PASS Web Animations: property <rotate> from neutral to [30deg] at (0.75) is [25deg] 
-PASS Web Animations: property <rotate> from neutral to [30deg] at (1) is [30deg] 
-PASS Web Animations: property <rotate> from neutral to [30deg] at (2) is [50deg] 
-PASS Web Animations: property <rotate> from [unset] to [30deg] at (-1) is [-30deg] 
-FAIL Web Animations: property <rotate> from [unset] to [30deg] at (0) is [0deg] assert_equals: expected "none " but got "0deg "
-PASS Web Animations: property <rotate> from [unset] to [30deg] at (0.25) is [7.5deg] 
-PASS Web Animations: property <rotate> from [unset] to [30deg] at (0.75) is [22.5deg] 
-PASS Web Animations: property <rotate> from [unset] to [30deg] at (1) is [30deg] 
-PASS Web Animations: property <rotate> from [unset] to [30deg] at (2) is [60deg] 
-PASS Web Animations: property <rotate> from [100deg] to [-100deg] at (-1) is [300deg] 
-PASS Web Animations: property <rotate> from [100deg] to [-100deg] at (0) is [100deg] 
-PASS Web Animations: property <rotate> from [100deg] to [-100deg] at (0.25) is [50deg] 
-PASS Web Animations: property <rotate> from [100deg] to [-100deg] at (0.75) is [-50deg] 
-PASS Web Animations: property <rotate> from [100deg] to [-100deg] at (1) is [-100deg] 
-PASS Web Animations: property <rotate> from [100deg] to [-100deg] at (2) is [-300deg] 
-PASS Web Animations: property <rotate> from [100deg] to [-100deg] at (-1) is [300deg] 
-PASS Web Animations: property <rotate> from [100deg] to [-100deg] at (0) is [100deg] 
-PASS Web Animations: property <rotate> from [100deg] to [-100deg] at (0.25) is [50deg] 
-PASS Web Animations: property <rotate> from [100deg] to [-100deg] at (0.75) is [-50deg] 
-PASS Web Animations: property <rotate> from [100deg] to [-100deg] at (1) is [-100deg] 
-PASS Web Animations: property <rotate> from [100deg] to [-100deg] at (2) is [-300deg] 
-PASS Web Animations: property <rotate> from [0 1 0 100deg] to [0 1 0 -100deg] at (-1) is [0 1 0 300deg] 
-PASS Web Animations: property <rotate> from [0 1 0 100deg] to [0 1 0 -100deg] at (0) is [0 1 0 100deg] 
-PASS Web Animations: property <rotate> from [0 1 0 100deg] to [0 1 0 -100deg] at (0.25) is [0 1 0 50deg] 
-PASS Web Animations: property <rotate> from [0 1 0 100deg] to [0 1 0 -100deg] at (0.75) is [0 1 0 -50deg] 
-PASS Web Animations: property <rotate> from [0 1 0 100deg] to [0 1 0 -100deg] at (1) is [0 1 0 -100deg] 
-PASS Web Animations: property <rotate> from [0 1 0 100deg] to [0 1 0 -100deg] at (2) is [0 1 0 -300deg] 
-PASS Web Animations: property <rotate> from [1 -2.5 3.64 100deg] to [1 -2.5 3.64 -100deg] at (-1) is [1 -2.5 3.64 300deg] 
-PASS Web Animations: property <rotate> from [1 -2.5 3.64 100deg] to [1 -2.5 3.64 -100deg] at (0) is [1 -2.5 3.64 100deg] 
-PASS Web Animations: property <rotate> from [1 -2.5 3.64 100deg] to [1 -2.5 3.64 -100deg] at (0.25) is [1 -2.5 3.64 50deg] 
-PASS Web Animations: property <rotate> from [1 -2.5 3.64 100deg] to [1 -2.5 3.64 -100deg] at (0.75) is [1 -2.5 3.64 -50deg] 
-PASS Web Animations: property <rotate> from [1 -2.5 3.64 100deg] to [1 -2.5 3.64 -100deg] at (1) is [1 -2.5 3.64 -100deg] 
-PASS Web Animations: property <rotate> from [1 -2.5 3.64 100deg] to [1 -2.5 3.64 -100deg] at (2) is [1 -2.5 3.64 -300deg] 
-PASS Web Animations: property <rotate> from [1 0 0 0deg] to [0 1 0 10deg] at (-1) is [0 1 0 -10deg] 
-PASS Web Animations: property <rotate> from [1 0 0 0deg] to [0 1 0 10deg] at (0) is [1 0 0 0deg] 
-PASS Web Animations: property <rotate> from [1 0 0 0deg] to [0 1 0 10deg] at (0.25) is [0 1 0 2.5deg] 
-PASS Web Animations: property <rotate> from [1 0 0 0deg] to [0 1 0 10deg] at (0.75) is [0 1 0 7.5deg] 
-PASS Web Animations: property <rotate> from [1 0 0 0deg] to [0 1 0 10deg] at (1) is [0 1 0 10deg] 
-PASS Web Animations: property <rotate> from [1 0 0 0deg] to [0 1 0 10deg] at (2) is [0 1 0 20deg] 
-PASS Web Animations: property <rotate> from [1 1 0 90deg] to [0 1 1 135deg] at (-1) is [0.673392 -0.0631886 -0.73658 124.975deg] 
-PASS Web Animations: property <rotate> from [1 1 0 90deg] to [0 1 1 135deg] at (0) is [1 1 0 90deg] 
-PASS Web Animations: property <rotate> from [1 1 0 90deg] to [0 1 1 135deg] at (0.25) is [0.544172 0.799255 0.255083 94.834deg] 
-PASS Web Animations: property <rotate> from [1 1 0 90deg] to [0 1 1 135deg] at (0.75) is [0.167111 0.775694 0.608583 118.679deg] 
-PASS Web Animations: property <rotate> from [1 1 0 90deg] to [0 1 1 135deg] at (1) is [0 1 1 135deg] 
-PASS Web Animations: property <rotate> from [1 1 0 90deg] to [0 1 1 135deg] at (2) is [0.516398 -0.289524 -0.805921 151.045deg] 
-PASS Web Animations: property <rotate> from [0 1 0 0deg] to [1 0 0 450deg] at (-1) is [1 0 0 -450deg] 
-PASS Web Animations: property <rotate> from [0 1 0 0deg] to [1 0 0 450deg] at (0) is [0 1 0 0deg] 
-PASS Web Animations: property <rotate> from [0 1 0 0deg] to [1 0 0 450deg] at (0.25) is [1 0 0 112.5deg] 
-PASS Web Animations: property <rotate> from [0 1 0 0deg] to [1 0 0 450deg] at (0.75) is [1 0 0 337.5deg] 
-PASS Web Animations: property <rotate> from [0 1 0 0deg] to [1 0 0 450deg] at (1) is [1 0 0 450deg] 
-PASS Web Animations: property <rotate> from [0 1 0 0deg] to [1 0 0 450deg] at (2) is [1 0 0 900deg] 
-PASS Web Animations: property <rotate> from [1 0 0 450deg] to [0 1 0 0deg] at (-1) is [1 0 0 900deg] 
-PASS Web Animations: property <rotate> from [1 0 0 450deg] to [0 1 0 0deg] at (0) is [1 0 0 450deg] 
-PASS Web Animations: property <rotate> from [1 0 0 450deg] to [0 1 0 0deg] at (0.25) is [1 0 0 337.5deg] 
-PASS Web Animations: property <rotate> from [1 0 0 450deg] to [0 1 0 0deg] at (0.75) is [1 0 0 112.5deg] 
-PASS Web Animations: property <rotate> from [1 0 0 450deg] to [0 1 0 0deg] at (1) is [0 1 0 0deg] 
-PASS Web Animations: property <rotate> from [1 0 0 450deg] to [0 1 0 0deg] at (2) is [1 0 0 -450deg] 
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/Source/core/animation/CSSRotateInterpolationType.cpp b/third_party/WebKit/Source/core/animation/CSSRotateInterpolationType.cpp
index d8a22b29..fc36af9 100644
--- a/third_party/WebKit/Source/core/animation/CSSRotateInterpolationType.cpp
+++ b/third_party/WebKit/Source/core/animation/CSSRotateInterpolationType.cpp
@@ -12,20 +12,57 @@
 
 namespace blink {
 
+class OptionalRotation {
+ public:
+  OptionalRotation() : m_isNone(true) {}
+
+  explicit OptionalRotation(Rotation rotation)
+      : m_rotation(rotation), m_isNone(false) {}
+
+  bool isNone() const { return m_isNone; }
+  const Rotation& rotation() const {
+    DCHECK(!m_isNone);
+    return m_rotation;
+  }
+
+  static OptionalRotation add(const OptionalRotation& a,
+                              const OptionalRotation& b) {
+    if (a.isNone())
+      return b;
+    if (b.isNone())
+      return a;
+    return OptionalRotation(Rotation::add(a.rotation(), b.rotation()));
+  }
+  static OptionalRotation slerp(const OptionalRotation& from,
+                                const OptionalRotation& to,
+                                double progress) {
+    if (from.isNone() && to.isNone())
+      return OptionalRotation();
+
+    return OptionalRotation(
+        Rotation::slerp(from.isNone() ? Rotation() : from.rotation(),
+                        to.isNone() ? Rotation() : to.rotation(), progress));
+  }
+
+ private:
+  Rotation m_rotation;
+  bool m_isNone;
+};
+
 class CSSRotateNonInterpolableValue : public NonInterpolableValue {
  public:
   static PassRefPtr<CSSRotateNonInterpolableValue> create(
-      const Rotation& rotation) {
+      const OptionalRotation& rotation) {
     return adoptRef(new CSSRotateNonInterpolableValue(
-        true, rotation, Rotation(), false, false));
+        true, rotation, OptionalRotation(), false, false));
   }
 
   static PassRefPtr<CSSRotateNonInterpolableValue> create(
       const CSSRotateNonInterpolableValue& start,
       const CSSRotateNonInterpolableValue& end) {
     return adoptRef(new CSSRotateNonInterpolableValue(
-        false, start.rotation(), end.rotation(), start.isAdditive(),
-        end.isAdditive()));
+        false, start.optionalRotation(), end.optionalRotation(),
+        start.isAdditive(), end.isAdditive()));
   }
 
   PassRefPtr<CSSRotateNonInterpolableValue> composite(
@@ -35,17 +72,20 @@
     if (other.m_isSingle) {
       DCHECK_EQ(otherProgress, 0);
       DCHECK(other.isAdditive());
-      return create(Rotation::add(rotation(), other.rotation()));
+      return create(
+          OptionalRotation::add(optionalRotation(), other.optionalRotation()));
     }
 
     DCHECK(other.m_isStartAdditive || other.m_isEndAdditive);
-    Rotation start = other.m_isStartAdditive
-                         ? Rotation::add(rotation(), other.m_start)
-                         : other.m_start;
-    Rotation end = other.m_isEndAdditive
-                       ? Rotation::add(rotation(), other.m_end)
-                       : other.m_end;
-    return create(Rotation::slerp(start, end, otherProgress));
+    OptionalRotation start =
+        other.m_isStartAdditive
+            ? OptionalRotation::add(optionalRotation(), other.m_start)
+            : other.m_start;
+    OptionalRotation end =
+        other.m_isEndAdditive
+            ? OptionalRotation::add(optionalRotation(), other.m_end)
+            : other.m_end;
+    return create(OptionalRotation::slerp(start, end, otherProgress));
   }
 
   void setSingleAdditive() {
@@ -53,22 +93,22 @@
     m_isStartAdditive = true;
   }
 
-  Rotation slerpedRotation(double progress) const {
+  OptionalRotation slerpedRotation(double progress) const {
     DCHECK(!m_isStartAdditive && !m_isEndAdditive);
     DCHECK(!m_isSingle || progress == 0);
     if (progress == 0)
       return m_start;
     if (progress == 1)
       return m_end;
-    return Rotation::slerp(m_start, m_end, progress);
+    return OptionalRotation::slerp(m_start, m_end, progress);
   }
 
   DECLARE_NON_INTERPOLABLE_VALUE_TYPE();
 
  private:
   CSSRotateNonInterpolableValue(bool isSingle,
-                                const Rotation& start,
-                                const Rotation& end,
+                                const OptionalRotation& start,
+                                const OptionalRotation& end,
                                 bool isStartAdditive,
                                 bool isEndAdditive)
       : m_isSingle(isSingle),
@@ -77,7 +117,7 @@
         m_isStartAdditive(isStartAdditive),
         m_isEndAdditive(isEndAdditive) {}
 
-  const Rotation& rotation() const {
+  const OptionalRotation& optionalRotation() const {
     DCHECK(m_isSingle);
     return m_start;
   }
@@ -87,8 +127,8 @@
   }
 
   bool m_isSingle;
-  Rotation m_start;
-  Rotation m_end;
+  OptionalRotation m_start;
+  OptionalRotation m_end;
   bool m_isStartAdditive;
   bool m_isEndAdditive;
 };
@@ -98,13 +138,14 @@
 
 namespace {
 
-Rotation getRotation(const ComputedStyle& style) {
+OptionalRotation getRotation(const ComputedStyle& style) {
   if (!style.rotate())
-    return Rotation(FloatPoint3D(0, 0, 1), 0);
-  return Rotation(style.rotate()->axis(), style.rotate()->angle());
+    return OptionalRotation();
+  return OptionalRotation(
+      Rotation(style.rotate()->axis(), style.rotate()->angle()));
 }
 
-InterpolationValue convertRotation(const Rotation& rotation) {
+InterpolationValue convertRotation(const OptionalRotation& rotation) {
   return InterpolationValue(InterpolableNumber::create(0),
                             CSSRotateNonInterpolableValue::create(rotation));
 }
@@ -112,23 +153,27 @@
 class InheritedRotationChecker : public InterpolationType::ConversionChecker {
  public:
   static std::unique_ptr<InheritedRotationChecker> create(
-      const Rotation& inheritedRotation) {
+      const OptionalRotation& inheritedRotation) {
     return WTF::wrapUnique(new InheritedRotationChecker(inheritedRotation));
   }
 
   bool isValid(const InterpolationEnvironment& environment,
                const InterpolationValue& underlying) const final {
-    Rotation inheritedRotation =
+    OptionalRotation inheritedRotation =
         getRotation(*environment.state().parentStyle());
-    return m_inheritedRotation.axis == inheritedRotation.axis &&
-           m_inheritedRotation.angle == inheritedRotation.angle;
+    if (m_inheritedRotation.isNone() || inheritedRotation.isNone())
+      return inheritedRotation.isNone() == inheritedRotation.isNone();
+    return m_inheritedRotation.rotation().axis ==
+               inheritedRotation.rotation().axis &&
+           m_inheritedRotation.rotation().angle ==
+               inheritedRotation.rotation().angle;
   }
 
  private:
-  InheritedRotationChecker(const Rotation& inheritedRotation)
+  InheritedRotationChecker(const OptionalRotation& inheritedRotation)
       : m_inheritedRotation(inheritedRotation) {}
 
-  const Rotation m_inheritedRotation;
+  const OptionalRotation m_inheritedRotation;
 };
 
 }  // namespace
@@ -136,19 +181,19 @@
 InterpolationValue CSSRotateInterpolationType::maybeConvertNeutral(
     const InterpolationValue& underlying,
     ConversionCheckers&) const {
-  return convertRotation(Rotation());
+  return convertRotation(OptionalRotation(Rotation()));
 }
 
 InterpolationValue CSSRotateInterpolationType::maybeConvertInitial(
     const StyleResolverState&,
     ConversionCheckers&) const {
-  return convertRotation(getRotation(ComputedStyle::initialStyle()));
+  return convertRotation(OptionalRotation());
 }
 
 InterpolationValue CSSRotateInterpolationType::maybeConvertInherit(
     const StyleResolverState& state,
     ConversionCheckers& conversionCheckers) const {
-  Rotation inheritedRotation = getRotation(*state.parentStyle());
+  OptionalRotation inheritedRotation = getRotation(*state.parentStyle());
   conversionCheckers.push_back(
       InheritedRotationChecker::create(inheritedRotation));
   return convertRotation(inheritedRotation);
@@ -158,7 +203,12 @@
     const CSSValue& value,
     const StyleResolverState*,
     ConversionCheckers&) const {
-  return convertRotation(StyleBuilderConverter::convertRotation(value));
+  if (!value.isBaseValueList()) {
+    return convertRotation(OptionalRotation());
+  }
+
+  return convertRotation(
+      OptionalRotation(StyleBuilderConverter::convertRotation(value)));
 }
 
 void CSSRotateInterpolationType::additiveKeyframeHook(
@@ -205,9 +255,13 @@
   double progress = toInterpolableNumber(interpolableValue).value();
   const CSSRotateNonInterpolableValue& nonInterpolableValue =
       toCSSRotateNonInterpolableValue(*untypedNonInterpolableValue);
-  Rotation rotation = nonInterpolableValue.slerpedRotation(progress);
-  state.style()->setRotate(
-      RotateTransformOperation::create(rotation, TransformOperation::Rotate3D));
+  OptionalRotation rotation = nonInterpolableValue.slerpedRotation(progress);
+  if (rotation.isNone()) {
+    state.style()->setRotate(nullptr);
+    return;
+  }
+  state.style()->setRotate(RotateTransformOperation::create(
+      rotation.rotation(), TransformOperation::Rotate3D));
 }
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/editing/EditingStyle.cpp b/third_party/WebKit/Source/core/editing/EditingStyle.cpp
index 7ec4bbc..cd7d916 100644
--- a/third_party/WebKit/Source/core/editing/EditingStyle.cpp
+++ b/third_party/WebKit/Source/core/editing/EditingStyle.cpp
@@ -139,14 +139,6 @@
   return allEditingProperties().contains(static_cast<CSSPropertyID>(id));
 }
 
-static MutableStylePropertySet* editingStyleFromComputedStyle(
-    CSSComputedStyleDeclaration* style,
-    EditingPropertiesType type = OnlyInheritableEditingProperties) {
-  if (!style)
-    return MutableStylePropertySet::create(HTMLQuirksMode);
-  return copyEditingProperties(style, type);
-}
-
 static CSSComputedStyleDeclaration* ensureComputedStyle(
     const Position& position) {
   Element* elem = associatedElementOf(position);
@@ -166,11 +158,6 @@
                                       const CSSValue*,
                                       bool,
                                       LegacyFontSizeMode);
-static bool isTransparentColorValue(const CSSValue*);
-static bool hasTransparentBackgroundColor(CSSStyleDeclaration*);
-static bool hasTransparentBackgroundColor(StylePropertySet*);
-static const CSSValue* backgroundColorValueInEffect(Node*);
-static bool hasAncestorVerticalAlignStyle(Node&, CSSValueID);
 
 class HTMLElementEquivalent : public GarbageCollected<HTMLElementEquivalent> {
  public:
@@ -477,7 +464,7 @@
   m_mutableStyle =
       propertiesToInclude == AllProperties && computedStyleAtPosition
           ? computedStyleAtPosition->copyProperties()
-          : editingStyleFromComputedStyle(computedStyleAtPosition);
+          : copyEditingProperties(computedStyleAtPosition);
 
   if (propertiesToInclude == EditingPropertiesInEffect) {
     if (const CSSValue* value =
@@ -696,10 +683,10 @@
 void EditingStyle::removeStyleAddedByElement(Element* element) {
   if (!element || !element->parentNode())
     return;
-  MutableStylePropertySet* parentStyle = editingStyleFromComputedStyle(
+  MutableStylePropertySet* parentStyle = copyEditingProperties(
       CSSComputedStyleDeclaration::create(element->parentNode()),
       AllEditingProperties);
-  MutableStylePropertySet* nodeStyle = editingStyleFromComputedStyle(
+  MutableStylePropertySet* nodeStyle = copyEditingProperties(
       CSSComputedStyleDeclaration::create(element), AllEditingProperties);
   nodeStyle->removeEquivalentProperties(parentStyle);
   m_mutableStyle->removeEquivalentProperties(nodeStyle);
@@ -709,10 +696,10 @@
   if (!element || !element->parentNode() || !m_mutableStyle)
     return;
 
-  MutableStylePropertySet* parentStyle = editingStyleFromComputedStyle(
+  MutableStylePropertySet* parentStyle = copyEditingProperties(
       CSSComputedStyleDeclaration::create(element->parentNode()),
       AllEditingProperties);
-  MutableStylePropertySet* nodeStyle = editingStyleFromComputedStyle(
+  MutableStylePropertySet* nodeStyle = copyEditingProperties(
       CSSComputedStyleDeclaration::create(element), AllEditingProperties);
   nodeStyle->removeEquivalentProperties(parentStyle);
 
@@ -777,16 +764,6 @@
   return MixedTriState;
 }
 
-static bool hasAncestorVerticalAlignStyle(Node& node, CSSValueID value) {
-  for (Node& runner : NodeTraversal::inclusiveAncestorsOf(node)) {
-    CSSComputedStyleDeclaration* ancestorStyle =
-        CSSComputedStyleDeclaration::create(&runner);
-    if (getIdentifierValue(ancestorStyle, CSSPropertyVerticalAlign) == value)
-      return true;
-  }
-  return false;
-}
-
 TriState EditingStyle::triStateOfStyle(
     const VisibleSelection& selection) const {
   if (selection.isNone())
@@ -1254,46 +1231,6 @@
   }
 }
 
-EditingStyle* EditingStyle::wrappingStyleForAnnotatedSerialization(
-    ContainerNode* context) {
-  EditingStyle* wrappingStyle =
-      EditingStyle::create(context, EditingStyle::EditingPropertiesInEffect);
-
-  // Styles that Mail blockquotes contribute should only be placed on the Mail
-  // blockquote, to help us differentiate those styles from ones that the user
-  // has applied. This helps us get the color of content pasted into
-  // blockquotes right.
-  wrappingStyle->removeStyleAddedByElement(toHTMLElement(enclosingNodeOfType(
-      firstPositionInOrBeforeNode(context), isMailHTMLBlockquoteElement,
-      CanCrossEditingBoundary)));
-
-  // Call collapseTextDecorationProperties first or otherwise it'll copy the
-  // value over from in-effect to text-decorations.
-  wrappingStyle->collapseTextDecorationProperties();
-
-  return wrappingStyle;
-}
-
-EditingStyle* EditingStyle::wrappingStyleForSerialization(
-    ContainerNode* context) {
-  DCHECK(context);
-  EditingStyle* wrappingStyle = EditingStyle::create();
-
-  // When not annotating for interchange, we only preserve inline style
-  // declarations.
-  for (Node& node : NodeTraversal::inclusiveAncestorsOf(*context)) {
-    if (node.isDocumentNode())
-      break;
-    if (node.isStyledElement() && !isMailHTMLBlockquoteElement(&node)) {
-      wrappingStyle->mergeInlineAndImplicitStyleOfElement(
-          toElement(&node), EditingStyle::DoNotOverrideValues,
-          EditingStyle::EditingPropertiesInEffect);
-    }
-  }
-
-  return wrappingStyle;
-}
-
 static const CSSValueList& mergeTextDecorationValues(
     const CSSValueList& mergedValue,
     const CSSValueList& valueToMerge) {
@@ -1530,187 +1467,6 @@
                                     AlwaysUseLegacyFontSize);
 }
 
-EditingStyle* EditingStyle::styleAtSelectionStart(
-    const VisibleSelection& selection,
-    bool shouldUseBackgroundColorInEffect,
-    MutableStylePropertySet* styleToCheck) {
-  if (selection.isNone())
-    return nullptr;
-
-  Document& document = *selection.start().document();
-
-  DCHECK(!document.needsLayoutTreeUpdate());
-  DocumentLifecycle::DisallowTransitionScope disallowTransition(
-      document.lifecycle());
-
-  Position position = adjustedSelectionStartForStyleComputation(selection);
-
-  // If the pos is at the end of a text node, then this node is not fully
-  // selected. Move it to the next deep equivalent position to avoid removing
-  // the style from this node.
-  // e.g. if pos was at Position("hello", 5) in <b>hello<div>world</div></b>, we
-  // want Position("world", 0) instead.
-  // We only do this for range because caret at Position("hello", 5) in
-  // <b>hello</b>world should give you font-weight: bold.
-  Node* positionNode = position.computeContainerNode();
-  if (selection.isRange() && positionNode && positionNode->isTextNode() &&
-      position.computeOffsetInContainerNode() ==
-          positionNode->maxCharacterOffset())
-    position = nextVisuallyDistinctCandidate(position);
-
-  Element* element = associatedElementOf(position);
-  if (!element)
-    return nullptr;
-
-  EditingStyle* style =
-      EditingStyle::create(element, EditingStyle::AllProperties);
-  style->mergeTypingStyle(&element->document());
-
-  // If |element| has <sub> or <sup> ancestor element, apply the corresponding
-  // style(vertical-align) to it so that document.queryCommandState() works with
-  // the style. See bug http://crbug.com/582225.
-  CSSValueID valueID =
-      getIdentifierValue(styleToCheck, CSSPropertyVerticalAlign);
-  if (valueID == CSSValueSub || valueID == CSSValueSuper) {
-    CSSComputedStyleDeclaration* elementStyle =
-        CSSComputedStyleDeclaration::create(element);
-    // Find the ancestor that has CSSValueSub or CSSValueSuper as the value of
-    // CSS vertical-align property.
-    if (getIdentifierValue(elementStyle, CSSPropertyVerticalAlign) ==
-            CSSValueBaseline &&
-        hasAncestorVerticalAlignStyle(*element, valueID))
-      style->m_mutableStyle->setProperty(CSSPropertyVerticalAlign, valueID);
-  }
-
-  // If background color is transparent, traverse parent nodes until we hit a
-  // different value or document root Also, if the selection is a range, ignore
-  // the background color at the start of selection, and find the background
-  // color of the common ancestor.
-  if (shouldUseBackgroundColorInEffect &&
-      (selection.isRange() ||
-       hasTransparentBackgroundColor(style->m_mutableStyle.get()))) {
-    const EphemeralRange range(selection.toNormalizedEphemeralRange());
-    if (const CSSValue* value =
-            backgroundColorValueInEffect(Range::commonAncestorContainer(
-                range.startPosition().computeContainerNode(),
-                range.endPosition().computeContainerNode())))
-      style->setProperty(CSSPropertyBackgroundColor, value->cssText());
-  }
-
-  return style;
-}
-
-static bool isUnicodeBidiNestedOrMultipleEmbeddings(CSSValueID valueID) {
-  return valueID == CSSValueEmbed || valueID == CSSValueBidiOverride ||
-         valueID == CSSValueWebkitIsolate ||
-         valueID == CSSValueWebkitIsolateOverride ||
-         valueID == CSSValueWebkitPlaintext || valueID == CSSValueIsolate ||
-         valueID == CSSValueIsolateOverride || valueID == CSSValuePlaintext;
-}
-
-WritingDirection EditingStyle::textDirectionForSelection(
-    const VisibleSelection& selection,
-    EditingStyle* typingStyle,
-    bool& hasNestedOrMultipleEmbeddings) {
-  hasNestedOrMultipleEmbeddings = true;
-
-  if (selection.isNone())
-    return NaturalWritingDirection;
-
-  Position position = mostForwardCaretPosition(selection.start());
-
-  Node* node = position.anchorNode();
-  if (!node)
-    return NaturalWritingDirection;
-
-  Position end;
-  if (selection.isRange()) {
-    end = mostBackwardCaretPosition(selection.end());
-
-    DCHECK(end.document());
-    const EphemeralRange caretRange(position.parentAnchoredEquivalent(),
-                                    end.parentAnchoredEquivalent());
-    for (Node& n : caretRange.nodes()) {
-      if (!n.isStyledElement())
-        continue;
-
-      CSSComputedStyleDeclaration* style =
-          CSSComputedStyleDeclaration::create(&n);
-      const CSSValue* unicodeBidi =
-          style->getPropertyCSSValue(CSSPropertyUnicodeBidi);
-      if (!unicodeBidi || !unicodeBidi->isIdentifierValue())
-        continue;
-
-      CSSValueID unicodeBidiValue =
-          toCSSIdentifierValue(unicodeBidi)->getValueID();
-      if (isUnicodeBidiNestedOrMultipleEmbeddings(unicodeBidiValue))
-        return NaturalWritingDirection;
-    }
-  }
-
-  if (selection.isCaret()) {
-    WritingDirection direction;
-    if (typingStyle && typingStyle->textDirection(direction)) {
-      hasNestedOrMultipleEmbeddings = false;
-      return direction;
-    }
-    node = selection.visibleStart().deepEquivalent().anchorNode();
-  }
-  DCHECK(node);
-
-  // The selection is either a caret with no typing attributes or a range in
-  // which no embedding is added, so just use the start position to decide.
-  Node* block = enclosingBlock(node);
-  WritingDirection foundDirection = NaturalWritingDirection;
-
-  for (Node& runner : NodeTraversal::inclusiveAncestorsOf(*node)) {
-    if (runner == block)
-      break;
-    if (!runner.isStyledElement())
-      continue;
-
-    Element* element = &toElement(runner);
-    CSSComputedStyleDeclaration* style =
-        CSSComputedStyleDeclaration::create(element);
-    const CSSValue* unicodeBidi =
-        style->getPropertyCSSValue(CSSPropertyUnicodeBidi);
-    if (!unicodeBidi || !unicodeBidi->isIdentifierValue())
-      continue;
-
-    CSSValueID unicodeBidiValue =
-        toCSSIdentifierValue(unicodeBidi)->getValueID();
-    if (unicodeBidiValue == CSSValueNormal)
-      continue;
-
-    if (unicodeBidiValue == CSSValueBidiOverride)
-      return NaturalWritingDirection;
-
-    DCHECK(isEmbedOrIsolate(unicodeBidiValue)) << unicodeBidiValue;
-    const CSSValue* direction =
-        style->getPropertyCSSValue(CSSPropertyDirection);
-    if (!direction || !direction->isIdentifierValue())
-      continue;
-
-    int directionValue = toCSSIdentifierValue(direction)->getValueID();
-    if (directionValue != CSSValueLtr && directionValue != CSSValueRtl)
-      continue;
-
-    if (foundDirection != NaturalWritingDirection)
-      return NaturalWritingDirection;
-
-    // In the range case, make sure that the embedding element persists until
-    // the end of the range.
-    if (selection.isRange() && !end.anchorNode()->isDescendantOf(element))
-      return NaturalWritingDirection;
-
-    foundDirection = directionValue == CSSValueLtr
-                         ? LeftToRightWritingDirection
-                         : RightToLeftWritingDirection;
-  }
-  hasNestedOrMultipleEmbeddings = false;
-  return foundDirection;
-}
-
 DEFINE_TRACE(EditingStyle) {
   visitor->trace(m_mutableStyle);
 }
@@ -2021,36 +1777,4 @@
   return 0;
 }
 
-bool isTransparentColorValue(const CSSValue* cssValue) {
-  if (!cssValue)
-    return true;
-  if (cssValue->isColorValue())
-    return !toCSSColorValue(cssValue)->value().alpha();
-  if (!cssValue->isIdentifierValue())
-    return false;
-  return toCSSIdentifierValue(cssValue)->getValueID() == CSSValueTransparent;
-}
-
-bool hasTransparentBackgroundColor(CSSStyleDeclaration* style) {
-  const CSSValue* cssValue =
-      style->getPropertyCSSValueInternal(CSSPropertyBackgroundColor);
-  return isTransparentColorValue(cssValue);
-}
-
-bool hasTransparentBackgroundColor(StylePropertySet* style) {
-  const CSSValue* cssValue =
-      style->getPropertyCSSValue(CSSPropertyBackgroundColor);
-  return isTransparentColorValue(cssValue);
-}
-
-const CSSValue* backgroundColorValueInEffect(Node* node) {
-  for (Node* ancestor = node; ancestor; ancestor = ancestor->parentNode()) {
-    CSSComputedStyleDeclaration* ancestorStyle =
-        CSSComputedStyleDeclaration::create(ancestor);
-    if (!hasTransparentBackgroundColor(ancestorStyle))
-      return ancestorStyle->getPropertyCSSValue(CSSPropertyBackgroundColor);
-  }
-  return nullptr;
-}
-
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/editing/EditingStyle.h b/third_party/WebKit/Source/core/editing/EditingStyle.h
index 12bdc3f6..5088f5a4 100644
--- a/third_party/WebKit/Source/core/editing/EditingStyle.h
+++ b/third_party/WebKit/Source/core/editing/EditingStyle.h
@@ -151,9 +151,6 @@
   void mergeInlineAndImplicitStyleOfElement(Element*,
                                             CSSPropertyOverrideMode,
                                             PropertiesToInclude);
-  static EditingStyle* wrappingStyleForAnnotatedSerialization(
-      ContainerNode* context);
-  static EditingStyle* wrappingStyleForSerialization(ContainerNode* context);
   void mergeStyleFromRules(Element*);
   void mergeStyleFromRulesForSerialization(Element*);
   void removeStyleFromRulesAndContext(Element*, ContainerNode* context);
@@ -167,19 +164,6 @@
 
   void setProperty(CSSPropertyID, const String& value, bool important = false);
 
-  static EditingStyle* styleAtSelectionStart(
-      const VisibleSelection&,
-      bool shouldUseBackgroundColorInEffect = false,
-      MutableStylePropertySet* styleToCheck = nullptr);
-  static WritingDirection textDirectionForSelection(
-      const VisibleSelection&,
-      EditingStyle* typingStyle,
-      bool& hasNestedOrMultipleEmbeddings);
-  static bool isEmbedOrIsolate(CSSValueID unicodeBidi) {
-    return unicodeBidi == CSSValueIsolate ||
-           unicodeBidi == CSSValueWebkitIsolate || unicodeBidi == CSSValueEmbed;
-  }
-
   DECLARE_TRACE();
 
  private:
diff --git a/third_party/WebKit/Source/platform/heap/BlinkGC.h b/third_party/WebKit/Source/platform/heap/BlinkGC.h
index 6d13697..e32c8229 100644
--- a/third_party/WebKit/Source/platform/heap/BlinkGC.h
+++ b/third_party/WebKit/Source/platform/heap/BlinkGC.h
@@ -82,7 +82,7 @@
     MemoryPressureGC,
     PageNavigationGC,
     ThreadTerminationGC,
-    NumberOfGCReason,
+    LastGCReason = ThreadTerminationGC,
   };
 
   enum ArenaIndices {
diff --git a/third_party/WebKit/Source/platform/heap/ThreadState.cpp b/third_party/WebKit/Source/platform/heap/ThreadState.cpp
index 7b4404f..769710984 100644
--- a/third_party/WebKit/Source/platform/heap/ThreadState.cpp
+++ b/third_party/WebKit/Source/platform/heap/ThreadState.cpp
@@ -93,8 +93,8 @@
       return "MemoryPressureGC";
     case BlinkGC::PageNavigationGC:
       return "PageNavigationGC";
-    default:
-      NOTREACHED();
+    case BlinkGC::ThreadTerminationGC:
+      return "ThreadTerminationGC";
   }
   return "<Unknown>";
 }
@@ -1618,7 +1618,7 @@
     DEFINE_THREAD_SAFE_STATIC_LOCAL(
         EnumerationHistogram, gcReasonHistogram,
         new EnumerationHistogram("BlinkGC.GCReason",
-                                 BlinkGC::NumberOfGCReason));
+                                 BlinkGC::LastGCReason + 1));
     gcReasonHistogram.count(reason);
 
     heap().m_lastGCReason = reason;