diff --git a/DEPS b/DEPS
index 0603f67..4eabce1 100644
--- a/DEPS
+++ b/DEPS
@@ -59,7 +59,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling PDFium
   # and whatever else without interference from each other.
-  'pdfium_revision': '32b639de35f905a5e5559f305d9032cde5ae5c77',
+  'pdfium_revision': 'a76a6d8bcb76077fa248b64c5d64791dc8f23771',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling openmax_dl
   # and whatever else without interference from each other.
diff --git a/build/config/compiler/compiler.gni b/build/config/compiler/compiler.gni
index 6454b83f..dc95f22 100644
--- a/build/config/compiler/compiler.gni
+++ b/build/config/compiler/compiler.gni
@@ -27,12 +27,10 @@
     # With instrumentation enabled, debug info puts libchrome.so over 4gb, which
     # causes the linker to produce an invalid ELF. http://crbug.com/574476
     symbol_level = 0
-  }
-
-  # Linux is slowed by having symbols as part of the target binary, whereas
-  # Mac and Windows have them separate, so in Release Linux, default them off,
-  # but keep them on for Official builds.
-  if (!is_linux || (is_debug || is_official_build)) {
+  } else if (!is_linux || (is_debug || is_official_build)) {
+    # Linux is slowed by having symbols as part of the target binary, whereas
+    # Mac and Windows have them separate, so in Release Linux, default them off,
+    # but keep them on for Official builds.
     symbol_level = 2
   } else if (using_sanitizer) {
     # Sanitizers require symbols for filename suppressions to work.
diff --git a/cc/test/layer_tree_test.cc b/cc/test/layer_tree_test.cc
index 06822e34..90a0c8e 100644
--- a/cc/test/layer_tree_test.cc
+++ b/cc/test/layer_tree_test.cc
@@ -653,6 +653,13 @@
                  main_thread_weak_ptr_));
 }
 
+void LayerTreeTest::PostNextCommitWaitsForActivationToMainThread() {
+  main_task_runner_->PostTask(
+      FROM_HERE,
+      base::Bind(&LayerTreeTest::DispatchNextCommitWaitsForActivation,
+                 main_thread_weak_ptr_));
+}
+
 void LayerTreeTest::WillBeginTest() {
   layer_tree_host_->SetVisible(true);
 }
@@ -800,6 +807,12 @@
     layer_tree_host_->Composite(base::TimeTicks::Now());
 }
 
+void LayerTreeTest::DispatchNextCommitWaitsForActivation() {
+  DCHECK(!task_runner_provider() || task_runner_provider()->IsMainThread());
+  if (layer_tree_host_)
+    layer_tree_host_->SetNextCommitWaitsForActivation();
+}
+
 void LayerTreeTest::RunTest(CompositorMode mode, bool delegating_renderer) {
   mode_ = mode;
   if (mode_ == CompositorMode::Threaded) {
diff --git a/cc/test/layer_tree_test.h b/cc/test/layer_tree_test.h
index ea509d5..fd5800e 100644
--- a/cc/test/layer_tree_test.h
+++ b/cc/test/layer_tree_test.h
@@ -90,6 +90,7 @@
   void PostSetVisibleToMainThread(bool visible);
   void PostSetNextCommitForcesRedrawToMainThread();
   void PostCompositeImmediatelyToMainThread();
+  void PostNextCommitWaitsForActivationToMainThread();
 
   void DoBeginTest();
   void Timeout();
@@ -123,6 +124,7 @@
   void DispatchSetNextCommitForcesRedraw();
   void DispatchDidAddAnimation();
   void DispatchCompositeImmediately();
+  void DispatchNextCommitWaitsForActivation();
 
   virtual void AfterTest() = 0;
   virtual void WillBeginTest();
diff --git a/cc/trees/layer_tree_host_unittest_proxy.cc b/cc/trees/layer_tree_host_unittest_proxy.cc
index 4136221..55ec779a 100644
--- a/cc/trees/layer_tree_host_unittest_proxy.cc
+++ b/cc/trees/layer_tree_host_unittest_proxy.cc
@@ -293,16 +293,28 @@
         // completion event is cleared.
         EXPECT_FALSE(GetProxyImplForTest()->HasCommitCompletionEvent());
         EXPECT_FALSE(GetProxyImplForTest()->GetNextCommitWaitsForActivation());
+
+        // Set next commit waits for activation and start another commit.
+        commits_completed_++;
+        PostNextCommitWaitsForActivationToMainThread();
+        PostSetNeedsCommitToMainThread();
         break;
       case 1:
         // The second commit should be held until activation.
         EXPECT_TRUE(GetProxyImplForTest()->HasCommitCompletionEvent());
         EXPECT_TRUE(GetProxyImplForTest()->GetNextCommitWaitsForActivation());
+
+        // Start another commit to verify that this is not held until
+        // activation.
+        commits_completed_++;
+        PostSetNeedsCommitToMainThread();
         break;
       case 2:
         // The third commit should not wait for activation.
         EXPECT_FALSE(GetProxyImplForTest()->HasCommitCompletionEvent());
         EXPECT_FALSE(GetProxyImplForTest()->GetNextCommitWaitsForActivation());
+
+        commits_completed_++;
     }
   }
 
@@ -310,29 +322,17 @@
     // The next_commit_waits_for_activation should have been cleared after the
     // sync tree is activated.
     EXPECT_FALSE(GetProxyImplForTest()->GetNextCommitWaitsForActivation());
+    if (commits_completed_ == 3)
+      EndTest();
   }
 
-  void DidCommit() override {
-    switch (commits_completed_) {
-      case 0:
-        // The first commit has been completed. Set next commit waits for
-        // activation and start another commit.
-        commits_completed_++;
-        proxy()->SetNextCommitWaitsForActivation();
-        proxy()->SetNeedsCommit();
-      case 1:
-        // Start another commit to verify that this is not held until
-        // activation.
-        commits_completed_++;
-        proxy()->SetNeedsCommit();
-      case 2:
-        commits_completed_++;
-        EndTest();
-    }
+  void AfterTest() override {
+    // It is safe to read commits_completed_ on the main thread now since
+    // AfterTest() runs after the LayerTreeHost is destroyed and the impl thread
+    // tear down is finished.
+    EXPECT_EQ(3, commits_completed_);
   }
 
-  void AfterTest() override { EXPECT_EQ(3, commits_completed_); }
-
  private:
   int commits_completed_;
 
diff --git a/chrome/VERSION b/chrome/VERSION
index d702865..cea62a0 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
-MAJOR=49
+MAJOR=50
 MINOR=0
-BUILD=2623
+BUILD=2624
 PATCH=0
diff --git a/chrome/browser/chromeos/resource_reporter/resource_reporter.cc b/chrome/browser/chromeos/resource_reporter/resource_reporter.cc
index d9842e2..a7cb8eb 100644
--- a/chrome/browser/chromeos/resource_reporter/resource_reporter.cc
+++ b/chrome/browser/chromeos/resource_reporter/resource_reporter.cc
@@ -359,8 +359,8 @@
 void ResourceReporter::OnMemoryPressure(
     MemoryPressureLevel memory_pressure_level) {
   if (have_seen_first_task_manager_refresh_ &&
-      memory_pressure_level >=
-      MemoryPressureLevel::MEMORY_PRESSURE_LEVEL_MODERATE) {
+      memory_pressure_level ==
+      MemoryPressureLevel::MEMORY_PRESSURE_LEVEL_CRITICAL) {
     // Report browser and GPU processes usage using UMA histograms.
     UMA_HISTOGRAM_ENUMERATION(
         "ResourceReporter.BrowserProcess.CpuUsage",
@@ -384,8 +384,8 @@
     if (!rappor_service)
       return;
 
-    // We only record Rappor samples only if it's the first ever moderate or
-    // critical memory pressure event we receive, or it has been more than
+    // We only record Rappor samples only if it's the first ever critical memory
+    // pressure event we receive, or it has been more than
     // |kMinimumTimeBetweenReportsInMs| since the last time we recorded samples.
     if (!have_seen_first_memory_pressure_event_) {
       have_seen_first_memory_pressure_event_ = true;
diff --git a/chrome/browser/chromeos/resource_reporter/resource_reporter.h b/chrome/browser/chromeos/resource_reporter/resource_reporter.h
index d238b5a..1b2f484 100644
--- a/chrome/browser/chromeos/resource_reporter/resource_reporter.h
+++ b/chrome/browser/chromeos/resource_reporter/resource_reporter.h
@@ -25,7 +25,7 @@
 
 // A system that tracks the top |kTopConsumersCount| CPU and memory consumer
 // Chrome tasks and reports a weighted random sample of them via Rappor whenever
-// memory pressure is moderate or higher. The reporting is limited to once per
+// memory pressure is critical. The reporting is limited to once per
 // |kMinimumTimeBetweenReportsInMS|.
 class ResourceReporter : public task_management::TaskManagerObserver {
  public:
@@ -159,7 +159,7 @@
   void OnMemoryPressure(MemoryPressureLevel memory_pressure_level);
 
   // We'll use this to watch for memory pressure events so that we can trigger
-  // Rappor sampling at moderate memory pressure or higher.
+  // Rappor sampling at at the critical memory pressure level.
   scoped_ptr<base::MemoryPressureListener> memory_pressure_listener_;
 
   // Contains the collected data about the currently running tasks from the most
@@ -174,9 +174,9 @@
   // descending order by their memory usage.
   std::vector<TaskRecord*> task_records_by_memory_;
 
-  // The time at which the previous memory pressure event (moderate or higher)
-  // was received at which we recorded Rappor samples. This is used to limit
-  // generating a Rappor report to once per |kMinimumTimeBetweenReportsInMS|.
+  // The time at which the previous critical memory pressure event was received
+  // at which we recorded Rappor samples. This is used to limit generating a
+  // Rappor report to once per |kMinimumTimeBetweenReportsInMS|.
   // This is needed to avoid generating a lot of samples that can lower the
   // Rappor privacy guarantees.
   base::TimeTicks last_memory_pressure_event_time_;
@@ -185,7 +185,7 @@
   const CpuCoresNumberRange system_cpu_cores_range_;
 
   // The most recent reading for the browser and GPU processes to be reported as
-  // UMA histograms when the system is under moderate memory pressure or higher.
+  // UMA histograms when the system is under critical memory pressure.
   double last_browser_process_cpu_ = 0.0;
   double last_gpu_process_cpu_ = 0.0;
   int64_t last_browser_process_memory_ = 0;
@@ -194,7 +194,7 @@
   // Tracks whether monitoring started or not.
   bool is_monitoring_ = false;
 
-  // True after we've seen a moderate memory pressure event or higher.
+  // True after we've seen a critical memory pressure event.
   bool have_seen_first_memory_pressure_event_ = false;
 
   // True after the first task manager OnTasksRefreshed() event is received.
diff --git a/chrome/browser/extensions/api/input_ime/input_ime_api_nonchromeos.cc b/chrome/browser/extensions/api/input_ime/input_ime_api_nonchromeos.cc
index 9511f01..98be0cc3 100644
--- a/chrome/browser/extensions/api/input_ime/input_ime_api_nonchromeos.cc
+++ b/chrome/browser/extensions/api/input_ime/input_ime_api_nonchromeos.cc
@@ -70,4 +70,9 @@
 
 void InputImeAPI::OnListenerAdded(const EventListenerInfo& details) {}
 
+ExtensionFunction::ResponseAction InputImeCreateWindowFunction::Run() {
+  // TODO(shuchen): Implement this API.
+  return RespondNow(NoArguments());
+}
+
 }  // namespace extensions
diff --git a/chrome/browser/extensions/api/input_ime/input_ime_api_nonchromeos.h b/chrome/browser/extensions/api/input_ime/input_ime_api_nonchromeos.h
index c3567ae..2378297 100644
--- a/chrome/browser/extensions/api/input_ime/input_ime_api_nonchromeos.h
+++ b/chrome/browser/extensions/api/input_ime/input_ime_api_nonchromeos.h
@@ -7,10 +7,12 @@
 
 #include "chrome/browser/extensions/api/input_ime/input_ime_event_router_base.h"
 #include "chrome/browser/profiles/profile.h"
+#include "extensions/browser/extension_function.h"
 
 class Profile;
 
 namespace extensions {
+
 class InputImeEventRouterBase;
 
 class InputImeEventRouter : public InputImeEventRouterBase {
@@ -21,6 +23,17 @@
   DISALLOW_COPY_AND_ASSIGN(InputImeEventRouter);
 };
 
+class InputImeCreateWindowFunction : public UIThreadExtensionFunction {
+ public:
+  DECLARE_EXTENSION_FUNCTION("input.ime.createWindow", INPUT_IME_CREATEWINDOW)
+
+ protected:
+  ~InputImeCreateWindowFunction() override {}
+
+  // ExtensionFunction:
+  ExtensionFunction::ResponseAction Run() override;
+};
+
 }  // namespace extensions
 
 #endif  // CHROME_BROWSER_EXTENSIONS_API_INPUT_IME_INPUT_IME_API_NONCHROMEOS_H_
diff --git a/chrome/common/extensions/api/input_ime.json b/chrome/common/extensions/api/input_ime.json
index ac19b70d..b8379add 100644
--- a/chrome/common/extensions/api/input_ime.json
+++ b/chrome/common/extensions/api/input_ime.json
@@ -98,6 +98,36 @@
         "type": "string",
         "description": "Which mouse buttons was clicked.",
         "enum": ["left", "middle", "right"]
+      },
+      {
+        "id": "WindowType",
+        "type": "string",
+        "description": "The IME window types.",
+        "platforms": ["win", "linux"],
+        "enum": ["normal", "followCursor"]
+      },
+      {
+        "id": "Bounds",
+        "type": "object",
+        "description": "Describes the screen coordinates of a rect.",
+        "platforms": ["win", "linux"],
+        "properties": {
+          "left": {"type": "integer", "description": "The left of the bounds."},
+          "top": {"type": "integer", "description": "The top of the bounds."},
+          "width": {"type": "integer", "description": "The width of the bounds." },
+          "height": {"type": "integer", "description": "The height of the bounds ."}
+        }
+      },
+      {
+        "id": "CreateWindowOptions",
+        "type": "object",
+        "description": "The options to create an IME window",
+        "platforms": ["win", "linux"],
+        "properties": {
+          "windowType": {"$ref": "WindowType"},
+          "url": {"type": "string", "optional": true},
+          "bounds": {"$ref": "Bounds", "optional": true}
+        }
       }
     ],
     "functions": [
@@ -542,6 +572,32 @@
           {"type": "string", "name": "requestId", "description": "Request id of the event that was handled.  This should come from keyEvent.requestId"},
           {"type": "boolean", "name": "response", "description": "True if the keystroke was handled, false if not"}
         ]
+      },
+      {
+        "name": "createWindow",
+        "type": "function",
+        "description": "Creates IME window.",
+        "platforms": ["win", "linux"],
+        "parameters": [
+          {
+            "$ref": "CreateWindowOptions",
+            "name": "options",
+            "description": "The options of the newly created IME window."
+          },
+          {
+            "type": "function",
+            "name": "callback",
+            "description": "Called when the operation completes.",
+            "parameters": [
+              {
+                "name": "windowObject",
+                "type": "object",
+                "isInstanceOf": "Window",
+                "description": "The JavaScript 'window' object of the newly created IME window."
+              }
+            ]
+          }
+        ]
       }
     ],
     "events": [
diff --git a/chromecast/base/cast_resource.cc b/chromecast/base/cast_resource.cc
index cbe9b51..7978d86 100644
--- a/chromecast/base/cast_resource.cc
+++ b/chromecast/base/cast_resource.cc
@@ -10,9 +10,9 @@
   client_ = client;
 }
 
-void CastResource::NotifyResourceAcquired() {
+void CastResource::RegisterWithClient() {
   if (client_)
-    client_->OnResourceAcquired(this);
+    client_->RegisterCastResource(this);
 }
 
 void CastResource::NotifyResourceReleased(Resource remain) {
diff --git a/chromecast/base/cast_resource.h b/chromecast/base/cast_resource.h
index cd248d77..67315ec 100644
--- a/chromecast/base/cast_resource.h
+++ b/chromecast/base/cast_resource.h
@@ -9,7 +9,13 @@
 
 namespace chromecast {
 
-// Interface for resources needed to run application.
+// A CastResource is a user of 1 or more Resources (primary screen, audio,
+// etc). As a user, it is responsible for doing any cast-specific component
+// initialization when the Resources it uses are granted. This initialization
+// is referred to as "acquiring" the Resources. Conversely, when the Resources
+// it uses are revoked, it must deinitialize these cast-specific components.
+// This deinitialization is referred to as "releasing" the Resources.
+// TODO(maclellant): RENAME/DESIGN THIS CLASS IN COMING REFACTOR.
 class CastResource {
  public:
   // Resources necessary to run cast apps. CastResource may contain union of the
@@ -33,11 +39,22 @@
         (kResourceAudio | kResourceScreenPrimary | kResourceScreenSecondary),
   };
 
+  // A Client is responsible for notifying all registered CastResource's when
+  // Resources are granted/revoked so that they can acquire/release those
+  // Resources. When a CastResource is done acquiring/releasing, it responds
+  // to the Client that it has completed. A Client can have multiple registered
+  // CastResource's, but each CastResouce has 1 Client that it responds to.
   class Client {
    public:
-    // Called when resource is created. CastResource should not be owned by
-    // Client. It can be called from any thread.
-    virtual void OnResourceAcquired(CastResource* cast_resource) = 0;
+    // Called to register a CastResource with a Client. After registering, a
+    // CastResource will start getting notified when to acquire/release
+    // Resources. The Client does not take ownership of |cast_resource|. It can
+    // be called from any thread.
+    virtual void RegisterCastResource(CastResource* cast_resource) = 0;
+
+    // TODO(esum): Add OnResourceAcquired() here once AcquireResource is
+    // allowed to be asynchronous.
+
     // Called when part or all resources are released. It can be called from any
     // thread.
     //   |cast_resource| the CastResource that is released. The pointer may be
@@ -52,7 +69,17 @@
     virtual ~Client() {}
   };
 
+  // Sets the Client for the CastResource to respond to when it is done with
+  // Acquire/ReleaseResource.
   void SetCastResourceClient(Client* client);
+  // Called to acquire resources after OEM has granted them, and before
+  // they start getting used by consumers. Implementation must be synchronous
+  // since consumers will start using the resource immediately afterwards.
+  // TODO(esum): We should allow this method to be asynchronous in case an
+  // implementer needs to make expensive calls and doesn't want to block the
+  // UI thread (b/26239576). For now, don't do anything expensive in your
+  // implementation; if you really need to, then this bug has to be resolved.
+  virtual void AcquireResource(Resource resource) = 0;
   // Called to release resources. Implementation should call
   // Client::OnResourceReleased when resource is released on its side.
   virtual void ReleaseResource(Resource resource) = 0;
@@ -61,7 +88,9 @@
   CastResource() : client_(nullptr) {}
   virtual ~CastResource() {}
 
-  void NotifyResourceAcquired();
+  // For derived classes to register themselves with their Client through
+  // Client::RegisterCastResource.
+  void RegisterWithClient();
   void NotifyResourceReleased(Resource remain);
 
  private:
diff --git a/chromecast/browser/media/cma_media_pipeline_client.cc b/chromecast/browser/media/cma_media_pipeline_client.cc
index 0507d87..a62e1ec 100644
--- a/chromecast/browser/media/cma_media_pipeline_client.cc
+++ b/chromecast/browser/media/cma_media_pipeline_client.cc
@@ -25,7 +25,7 @@
   media_pipeline_count_++;
 
   if (media_pipeline_count_ == 1)
-    NotifyResourceAcquired();
+    CastResource::RegisterWithClient();
 }
 
 void CmaMediaPipelineClient::OnMediaPipelineBackendDestroyed() {
@@ -36,6 +36,8 @@
     NotifyResourceReleased(CastResource::kResourceNone);
 }
 
+void CmaMediaPipelineClient::AcquireResource(CastResource::Resource resource) {}
+
 void CmaMediaPipelineClient::ReleaseResource(CastResource::Resource resource) {
   CastResource::Resource audio_video_resource =
       static_cast<CastResource::Resource>(CastResource::kResourceAudio |
diff --git a/chromecast/browser/media/cma_media_pipeline_client.h b/chromecast/browser/media/cma_media_pipeline_client.h
index 7c8ce004..0dcf8ba 100644
--- a/chromecast/browser/media/cma_media_pipeline_client.h
+++ b/chromecast/browser/media/cma_media_pipeline_client.h
@@ -32,6 +32,7 @@
   virtual void OnMediaPipelineBackendDestroyed();
 
   // cast::CastResource implementation:
+  void AcquireResource(CastResource::Resource resource) override;
   void ReleaseResource(CastResource::Resource resource) override;
 
  protected:
diff --git a/chromecast/media/base/video_plane_controller.cc b/chromecast/media/base/video_plane_controller.cc
index 7202b00..e6496f4 100644
--- a/chromecast/media/base/video_plane_controller.cc
+++ b/chromecast/media/base/video_plane_controller.cc
@@ -206,8 +206,27 @@
   MaybeRunSetGeometry();
 }
 
+void VideoPlaneController::Pause() {
+  DCHECK(thread_checker_.CalledOnValidThread());
+  VLOG(1) << "Pausing controller. No more VideoPlane SetGeometry calls.";
+  is_paused_ = true;
+}
+
+void VideoPlaneController::Resume() {
+  DCHECK(thread_checker_.CalledOnValidThread());
+  VLOG(1) << "Resuming controller. VideoPlane SetGeometry calls are active.";
+  is_paused_ = false;
+  MaybeRunSetGeometry();
+}
+
+bool VideoPlaneController::is_paused() const {
+  DCHECK(thread_checker_.CalledOnValidThread());
+  return is_paused_;
+}
+
 VideoPlaneController::VideoPlaneController()
-    : have_output_res_(false),
+    : is_paused_(false),
+      have_output_res_(false),
       have_graphics_res_(false),
       output_res_(0, 0),
       graphics_res_(0, 0),
@@ -222,8 +241,15 @@
 
 void VideoPlaneController::MaybeRunSetGeometry() {
   DCHECK(thread_checker_.CalledOnValidThread());
-  if (!HaveDataForSetGeometry())
+  if (is_paused_) {
+    VLOG(2) << "All VideoPlane SetGeometry calls are paused. Ignoring request.";
     return;
+  }
+
+  if (!HaveDataForSetGeometry()) {
+    VLOG(2) << "Don't have all VideoPlane SetGeometry data. Ignoring request.";
+    return;
+  }
 
   DCHECK(graphics_res_.width != 0 && graphics_res_.height != 0);
 
diff --git a/chromecast/media/base/video_plane_controller.h b/chromecast/media/base/video_plane_controller.h
index 74f91eb5..c14ae95 100644
--- a/chromecast/media/base/video_plane_controller.h
+++ b/chromecast/media/base/video_plane_controller.h
@@ -59,6 +59,20 @@
   // no-op.
   void SetGraphicsPlaneResolution(const Size& resolution);
 
+  // After Pause is called, no further calls to VideoPlane::SetGeometry will be
+  // made except for any pending calls already scheduled on the media thread.
+  // The Set methods will however update cached parameters that will take
+  // effect once the class is resumed. Safe to call multiple times.
+  // TODO(esum): Handle the case where there are pending calls already on the
+  // media thread. When this returns, the caller needs to know that absolutely
+  // no more SetGeometry calls will be made.
+  void Pause();
+  // Makes class active again. Also resets the video plane by posting a call to
+  // VideoPlane::SetGeometry with most recent resolution and geometry parameters
+  // (assuming they are all set). Safe to call multiple times.
+  void Resume();
+  bool is_paused() const;
+
  private:
   class RateLimitedSetVideoPlaneGeometry;
   friend struct base::DefaultSingletonTraits<VideoPlaneController>;
@@ -74,6 +88,8 @@
   // VideoPlane::SetGeometry.
   bool HaveDataForSetGeometry() const;
 
+  bool is_paused_;
+
   // Current resolutions
   bool have_output_res_;
   bool have_graphics_res_;
diff --git a/chromeos/CHROMEOS_LKGM b/chromeos/CHROMEOS_LKGM
index 20cbdce..186115a 100644
--- a/chromeos/CHROMEOS_LKGM
+++ b/chromeos/CHROMEOS_LKGM
@@ -1 +1 @@
-7828.0.0
\ No newline at end of file
+7830.0.0
\ No newline at end of file
diff --git a/extensions/browser/extension_function_histogram_value.h b/extensions/browser/extension_function_histogram_value.h
index 93e7e3e9..2ea86c99 100644
--- a/extensions/browser/extension_function_histogram_value.h
+++ b/extensions/browser/extension_function_histogram_value.h
@@ -1161,6 +1161,7 @@
   WEBRTCLOGGINGPRIVATE_STARTAUDIODEBUGRECORDINGS,
   WEBRTCLOGGINGPRIVATE_STOPAUDIODEBUGRECORDINGS,
   TERMINALPRIVATE_ACKOUTPUT,
+  INPUT_IME_CREATEWINDOW,
   // Last entry: Add new entries above, then run:
   // python tools/metrics/histograms/update_extension_histograms.py
   ENUM_BOUNDARY
diff --git a/skia/config/SkUserConfig.h b/skia/config/SkUserConfig.h
index 741f73d..42c7d7b 100644
--- a/skia/config/SkUserConfig.h
+++ b/skia/config/SkUserConfig.h
@@ -238,6 +238,10 @@
 #   define SK_SUPPORT_LEGACY_BITMAP_FILTER
 #endif
 
+#ifndef     SK_SUPPORT_LEGACY_MIPLEVEL_BUILDER
+#   define SK_SUPPORT_LEGACY_MIPLEVEL_BUILDER
+#endif
+
 ///////////////////////// Imported from BUILD.gn and skia_common.gypi
 
 /* In some places Skia can use static initializers for global initialization,
diff --git a/third_party/WebKit/LayoutTests/http/tests/preload/download_resources.html b/third_party/WebKit/LayoutTests/http/tests/preload/download_resources.html
new file mode 100644
index 0000000..dfee90ad
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/preload/download_resources.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<script src="../resources/testharness.js"></script>
+<script src="../resources/testharnessreport.js"></script>
+<script>
+    var t = async_test('Makes sure that preloaded resources are not downloaded again when used');
+</script>
+<link rel=preload href="../resources/dummy.js" as=script>
+<link rel=preload href="../resources/dummy.css" as=style>
+<link rel=preload href="../resources/square.png" as=image>
+<link rel=preload href="../resources/square.png?background" as=image>
+<link rel=preload href="../resources/Ahem.ttf" as=font crossorigin>
+<script src="../resources/slow-script.pl?delay=200"></script>
+<script>
+    window.addEventListener("load", t.step_func(function() {
+        assert_equals(performance.getEntriesByType("resource").length, 8);
+        t.done();
+    }));
+</script>
+
diff --git a/third_party/WebKit/LayoutTests/http/tests/preload/single_download_preload.html b/third_party/WebKit/LayoutTests/http/tests/preload/single_download_preload.html
index 1991f9c..059bb8b 100644
--- a/third_party/WebKit/LayoutTests/http/tests/preload/single_download_preload.html
+++ b/third_party/WebKit/LayoutTests/http/tests/preload/single_download_preload.html
@@ -8,6 +8,7 @@
 <link rel=preload href="../resources/dummy.css" as=style>
 <link rel=preload href="../resources/square.png" as=image>
 <link rel=preload href="../resources/square.png?background" as=image>
+<link rel=preload href="../resources/Ahem.ttf" as=font crossorigin>
 <script src="../resources/slow-script.pl?delay=200"></script>
 <style>
     #background {
@@ -15,6 +16,11 @@
         height: 200px;
         background-image: url(../resources/square.png?background);
     }
+    @font-face {
+      font-family:ahem;
+      src: url(../resources/Ahem.ttf);
+    }
+    span { font-family: ahem, Arial; }
 </style>
 <link rel="stylesheet" href="../resources/dummy.css">
 <script src="../resources/dummy.js"></script>
@@ -22,7 +28,8 @@
 <img src="../resources/square.png">
 <script>
     window.addEventListener("load", t.step_func(function() {
-        assert_equals(performance.getEntriesByType("resource").length, 7);
+        assert_equals(performance.getEntriesByType("resource").length, 8);
         t.done();
     }));
 </script>
+<span>PASS - this text is here just so that the browser will download the font.</span
diff --git a/third_party/WebKit/Source/config.gni b/third_party/WebKit/Source/config.gni
index 6d584ff3..9f210232 100644
--- a/third_party/WebKit/Source/config.gni
+++ b/third_party/WebKit/Source/config.gni
@@ -25,15 +25,13 @@
   blink_asserts_off_in_release = false
 }
 
-# Whether Android ARM or x86 build uses OpenMAX DL FFT. Currently only
-# supported on Android ARMv7+, ia32 or x64 without webview. When enabled, this
-# will also enable WebAudio support on Android ARM, ia32 and x64. Default is
-# enabled. Whether WebAudio is actually available depends on runtime settings
-# and flags.
+# Whether Android build uses OpenMAX DL FFT. Currently supported only on
+# ARMv7+, ARM64, x86 or x64 without webview. Also enables WebAudio support.
+# Whether WebAudio is actually available depends on runtime settings and flags.
 use_openmax_dl_fft =
-    is_android &&
-    (current_cpu == "x86" || current_cpu == "x64" ||
-     (current_cpu == "arm" && arm_version >= 7) || current_cpu == "mipsel")
+    is_android && (current_cpu == "x86" || current_cpu == "x64" ||
+                   (current_cpu == "arm" && arm_version >= 7) ||
+                   current_cpu == "arm64" || current_cpu == "mipsel")
 
 use_webaudio_ffmpeg = !is_mac && !is_android
 
diff --git a/third_party/WebKit/Source/core/dom/IntersectionObserver.cpp b/third_party/WebKit/Source/core/dom/IntersectionObserver.cpp
index b29b69e8..2a9cd6f 100644
--- a/third_party/WebKit/Source/core/dom/IntersectionObserver.cpp
+++ b/third_party/WebKit/Source/core/dom/IntersectionObserver.cpp
@@ -186,7 +186,6 @@
 
 void IntersectionObserver::observe(Element* target, ExceptionState& exceptionState)
 {
-    checkRootAndDetachIfNeeded();
     if (!m_root) {
         exceptionState.throwDOMException(HierarchyRequestError, "Invalid observer: root element or containing document has been deleted.");
         return;
@@ -221,7 +220,6 @@
 
 void IntersectionObserver::unobserve(Element* target, ExceptionState&)
 {
-    checkRootAndDetachIfNeeded();
     if (!target || !target->intersectionObserverData())
         return;
     // TODO(szager): unobserve callback
@@ -231,7 +229,6 @@
 
 void IntersectionObserver::computeIntersectionObservations(double timestamp)
 {
-    checkRootAndDetachIfNeeded();
     if (!m_root)
         return;
     for (auto& observation : m_observations)
@@ -254,7 +251,6 @@
 
 HeapVector<Member<IntersectionObserverEntry>> IntersectionObserver::takeRecords()
 {
-    checkRootAndDetachIfNeeded();
     HeapVector<Member<IntersectionObserverEntry>> entries;
     entries.swap(m_entries);
     return entries;
@@ -299,8 +295,6 @@
 
 void IntersectionObserver::deliver()
 {
-    checkRootAndDetachIfNeeded();
-
     if (m_entries.isEmpty())
         return;
 
@@ -311,7 +305,6 @@
 
 void IntersectionObserver::setActive(bool active)
 {
-    checkRootAndDetachIfNeeded();
     for (auto& observation : m_observations)
         observation->setActive(m_root && active && isDescendantOfRoot(observation->target()));
 }
@@ -324,25 +317,17 @@
         || m_leftMargin.type() == Percent);
 }
 
-void IntersectionObserver::checkRootAndDetachIfNeeded()
+void IntersectionObserver::rootDisappearedCallback(Visitor* visitor, void* self)
 {
-#if ENABLE(OILPAN)
-    // TODO(szager): Pre-oilpan, ElementIntersectionObserverData::dispose() will take
-    // care of this cleanup.  When oilpan ships, there will be a potential leak of the
-    // callback's execution context when the root goes away.  For a detailed explanation:
-    //
-    //   https://goo.gl/PC2Baj
-    //
-    // When that happens, this method should catch most potential leaks, but a complete
-    // solution will still be needed, along the lines described in the above link.
-    if (m_root)
-        return;
-    disconnect();
-#endif
+    IntersectionObserver* observer = static_cast<IntersectionObserver*>(self);
+    observer->disconnect();
 }
 
 DEFINE_TRACE(IntersectionObserver)
 {
+#if ENABLE(OILPAN)
+    visitor->registerWeakMembers(this, m_root.get(), IntersectionObserver::rootDisappearedCallback);
+#endif
     visitor->trace(m_callback);
     visitor->trace(m_root);
     visitor->trace(m_observations);
diff --git a/third_party/WebKit/Source/core/dom/IntersectionObserver.h b/third_party/WebKit/Source/core/dom/IntersectionObserver.h
index f793a6f..a918acb 100644
--- a/third_party/WebKit/Source/core/dom/IntersectionObserver.h
+++ b/third_party/WebKit/Source/core/dom/IntersectionObserver.h
@@ -27,6 +27,7 @@
 public:
     static IntersectionObserver* create(const IntersectionObserverInit&, IntersectionObserverCallback&, ExceptionState&);
     static void resumeSuspendedObservers();
+    static void rootDisappearedCallback(Visitor*, void*);
 
     // API methods
     void observe(Element*, ExceptionState&);
@@ -56,8 +57,6 @@
 private:
     explicit IntersectionObserver(IntersectionObserverCallback&, Node&, const Vector<Length>& rootMargin, const Vector<float>& thresholds);
 
-    void checkRootAndDetachIfNeeded();
-
     Member<IntersectionObserverCallback> m_callback;
     WeakPtrWillBeWeakMember<Node> m_root;
     HeapHashSet<WeakMember<IntersectionObservation>> m_observations;
diff --git a/third_party/WebKit/Source/core/loader/DocumentLoader.cpp b/third_party/WebKit/Source/core/loader/DocumentLoader.cpp
index f17bb79..07439882 100644
--- a/third_party/WebKit/Source/core/loader/DocumentLoader.cpp
+++ b/third_party/WebKit/Source/core/loader/DocumentLoader.cpp
@@ -175,6 +175,8 @@
         break;
     case Resource::Font:
         resource = FontResource::fetch(request, fetcher());
+        // This is needed for fonts as loading doesn't start until there's usage.
+        toFontResource(resource)->beginLoadIfNeeded(fetcher());
         break;
     case Resource::Media:
         resource = RawResource::fetchMedia(request, fetcher());
diff --git a/third_party/WebKit/Source/devtools/front_end/emulation/DeviceModeModel.js b/third_party/WebKit/Source/devtools/front_end/emulation/DeviceModeModel.js
index c7a5096..169602e 100644
--- a/third_party/WebKit/Source/devtools/front_end/emulation/DeviceModeModel.js
+++ b/third_party/WebKit/Source/devtools/front_end/emulation/DeviceModeModel.js
@@ -14,6 +14,7 @@
     this._visiblePageRect = new WebInspector.Rect(0, 0, 1, 1);
     this._availableSize = new Size(1, 1);
     this._preferredSize = new Size(1, 1);
+    this._initialized = false;
     this._deviceMetricsThrottler = new WebInspector.Throttler(0);
     this._appliedDeviceSize = new Size(1, 1);
     this._currentDeviceScaleFactor = window.devicePixelRatio;
@@ -69,7 +70,7 @@
     DesktopTouch: "DesktopTouch"
 }
 
-WebInspector.DeviceModeModel.MaxDeviceSize = 10000;
+WebInspector.DeviceModeModel.MaxDeviceSize = 9999;
 
 /**
  * @param {string} value
@@ -95,6 +96,7 @@
     {
         this._availableSize = availableSize;
         this._preferredSize = preferredSize;
+        this._initialized = true;
         this._calculateAndEmulate(false);
     },
 
@@ -112,6 +114,10 @@
             console.assert(device && mode, "Must pass device and mode for device emulation");
             this._device = device;
             this._mode = mode;
+            if (this._initialized) {
+                var orientation = device.orientationByName(mode.orientation);
+                this._scaleSetting.set(this._calculateFitScale(orientation.width, orientation.height));
+            }
         } else {
             this._device = null;
             this._mode = null;
@@ -133,6 +139,16 @@
     },
 
     /**
+     * @param {number} width
+     */
+    setWidthAndScaleToFit: function(width)
+    {
+        width = Math.max(Math.min(width, WebInspector.DeviceModeModel.MaxDeviceSize), 1);
+        this._scaleSetting.set(this._calculateFitScale(width, this._heightSetting.get()));
+        this._widthSetting.set(width);
+    },
+
+    /**
      * @param {number} height
      */
     setHeight: function(height)
@@ -145,6 +161,18 @@
     },
 
     /**
+     * @param {number} height
+     */
+    setHeightAndScaleToFit: function(height)
+    {
+        height = Math.max(Math.min(height, WebInspector.DeviceModeModel.MaxDeviceSize), 0);
+        if (height === this._preferredScaledHeight())
+            height = 0;
+        this._scaleSetting.set(this._calculateFitScale(this._widthSetting.get(), height));
+        this._heightSetting.set(height);
+    },
+
+    /**
      * @param {number} scale
      */
     setScale: function(scale)
@@ -379,22 +407,18 @@
      */
     _calculateAndEmulate: function(resetScrollAndPageScale)
     {
-        if (!this._target) {
+        if (!this._target)
             this._onTargetAvailable = this._calculateAndEmulate.bind(this, resetScrollAndPageScale);
-            this._applyDeviceMetrics(this._availableSize, new Insets(0, 0, 0, 0), 1, 0, false, resetScrollAndPageScale);
-            this._updateCallback.call(null);
-            return;
-        }
 
         if (this._type === WebInspector.DeviceModeModel.Type.Device) {
             var orientation = this._device.orientationByName(this._mode.orientation);
-            this._calculateFitScale(orientation.width, orientation.height);
+            this._fitScale = this._calculateFitScale(orientation.width, orientation.height);
             this._applyDeviceMetrics(new Size(orientation.width, orientation.height), this._mode.insets, this._scaleSetting.get(), this._device.deviceScaleFactor, this._device.mobile(), resetScrollAndPageScale);
             this._applyUserAgent(this._device.userAgent);
             this._applyTouch(this._device.touch(), this._device.mobile());
             this._applyScreenOrientation(this._mode.orientation == WebInspector.EmulatedDevice.Horizontal ? "landscapePrimary" : "portraitPrimary");
         } else if (this._type === WebInspector.DeviceModeModel.Type.None) {
-            this._calculateFitScale(this._availableSize.width, this._availableSize.height);
+            this._fitScale = this._calculateFitScale(this._availableSize.width, this._availableSize.height);
             this._applyDeviceMetrics(this._availableSize, new Insets(0, 0, 0, 0), 1, 0, false, resetScrollAndPageScale);
             this._applyUserAgent("");
             this._applyTouch(false, false);
@@ -408,7 +432,7 @@
                 screenHeight = this._preferredScaledHeight();
             var mobile = this._uaSetting.get() === WebInspector.DeviceModeModel.UA.Mobile;
             var defaultDeviceScaleFactor = mobile ? WebInspector.DeviceModeModel._defaultMobileScaleFactor : 0;
-            this._calculateFitScale(this._widthSetting.get(), this._heightSetting.get());
+            this._fitScale = this._calculateFitScale(this._widthSetting.get(), this._heightSetting.get());
             this._applyDeviceMetrics(new Size(screenWidth, screenHeight), new Insets(0, 0, 0, 0), this._scaleSetting.get(), this._deviceScaleFactorSetting.get() || defaultDeviceScaleFactor, mobile, resetScrollAndPageScale);
             this._applyUserAgent(mobile ? WebInspector.DeviceModeModel._defaultMobileUserAgent : "");
             this._applyTouch(this._uaSetting.get() !== WebInspector.DeviceModeModel.UA.Desktop, mobile);
@@ -420,11 +444,12 @@
     /**
      * @param {number} screenWidth
      * @param {number} screenHeight
+     * @return {number}
      */
     _calculateFitScale: function(screenWidth, screenHeight)
     {
         var scale = Math.min(screenWidth ? this._preferredSize.width / screenWidth: 1, screenHeight ? this._preferredSize.height / screenHeight : 1);
-        this._fitScale = Math.min(scale, 1);
+        return Math.min(scale, 1);
     },
 
     /**
@@ -433,8 +458,7 @@
      */
     setSizeAndScaleToFit: function(width, height)
     {
-        var scale = Math.min(width ? this._preferredSize.width / width: 1, height ? this._preferredSize.height / height : 1);
-        this._scaleSetting.set(scale);
+        this._scaleSetting.set(this._calculateFitScale(width, height));
         this.setWidth(width);
     },
 
diff --git a/third_party/WebKit/Source/devtools/front_end/emulation/DeviceModeView.js b/third_party/WebKit/Source/devtools/front_end/emulation/DeviceModeView.js
index 66884aa..8461645 100644
--- a/third_party/WebKit/Source/devtools/front_end/emulation/DeviceModeView.js
+++ b/third_party/WebKit/Source/devtools/front_end/emulation/DeviceModeView.js
@@ -22,9 +22,9 @@
     this._showRulersSetting = WebInspector.settings.createSetting("emulation.showRulers", false);
     this._showRulersSetting.addChangeListener(this._updateUI, this);
 
-    this._topRuler = new WebInspector.DeviceModeView.Ruler(true, this._model.setWidth.bind(this._model));
+    this._topRuler = new WebInspector.DeviceModeView.Ruler(true, this._model.setWidthAndScaleToFit.bind(this._model));
     this._topRuler.element.classList.add("device-mode-ruler-top");
-    this._leftRuler = new WebInspector.DeviceModeView.Ruler(false, this._model.setHeight.bind(this._model));
+    this._leftRuler = new WebInspector.DeviceModeView.Ruler(false, this._model.setHeightAndScaleToFit.bind(this._model));
     this._leftRuler.element.classList.add("device-mode-ruler-left");
     this._createUI();
     WebInspector.zoomManager.addEventListener(WebInspector.ZoomManager.Events.ZoomChanged, this._zoomChanged, this);
@@ -225,7 +225,7 @@
         }
 
         if (showRulers !== this._cachedShowRulers) {
-            this._contentArea.classList.toggle("device-mode-rulers-visible", showRulers);
+            this._contentClip.classList.toggle("device-mode-rulers-visible", showRulers);
             if (showRulers) {
                 this._topRuler.show(this._contentClip, this._contentArea);
                 this._leftRuler.show(this._contentArea);
@@ -240,6 +240,7 @@
 
         if (this._model.scale() !== this._cachedScale) {
             updateRulers = true;
+            callDoResize = true;
             for (var block of this._presetBlocks)
                 block.style.width = block.__width * this._model.scale() + "px";
             this._cachedScale = this._model.scale();
@@ -256,14 +257,6 @@
         }
         if (contentAreaResized)
             this._contentAreaResized();
-
-        if (this._model.type() !== this._cachedModelType) {
-            this._cachedModelType = this._model.type();
-            this._contentArea.classList.toggle("device-mode-type-none", this._cachedModelType === WebInspector.DeviceModeModel.Type.None);
-            this._contentArea.classList.toggle("device-mode-type-responsive", this._cachedModelType === WebInspector.DeviceModeModel.Type.Responsive);
-            this._contentArea.classList.toggle("device-mode-type-device", this._cachedModelType === WebInspector.DeviceModeModel.Type.Device);
-            this._responsivePresetsContainer.classList.toggle("hidden", this._cachedModelType === WebInspector.DeviceModeModel.Type.None);
-        }
     },
 
     /**
@@ -290,19 +283,30 @@
     {
         var zoomFactor = WebInspector.zoomManager.zoomFactor();
         var rect = this._contentArea.getBoundingClientRect();
-        this._handleWidth = this._handleWidth || this._widthResizerElement.offsetWidth;
-        this._handleHeight = this._handleHeight || this._heightResizerElement.offsetHeight;
         var availableSize = new Size(Math.max(rect.width * zoomFactor, 1), Math.max(rect.height * zoomFactor, 1));
         var preferredSize = new Size(Math.max((rect.width - 2 * this._handleWidth) * zoomFactor, 1), Math.max((rect.height - this._handleHeight) * zoomFactor, 1));
         this._model.setAvailableSize(availableSize, preferredSize);
     },
 
+    _measureHandles: function()
+    {
+        var hidden = this._widthResizerElement.classList.contains("hidden");
+        this._widthResizerElement.classList.toggle("hidden", false);
+        this._heightResizerElement.classList.toggle("hidden", false);
+        this._handleWidth = this._widthResizerElement.offsetWidth;
+        this._handleHeight = this._heightResizerElement.offsetHeight;
+        this._widthResizerElement.classList.toggle("hidden", hidden);
+        this._heightResizerElement.classList.toggle("hidden", hidden);
+    },
+
     _zoomChanged: function()
     {
         delete this._handleWidth;
         delete this._handleHeight;
-        if (this.isShowing())
+        if (this.isShowing()) {
+            this._measureHandles();
             this._contentAreaResized();
+        }
     },
 
     /**
@@ -319,6 +323,7 @@
      */
     wasShown: function()
     {
+        this._measureHandles();
         this._mediaInspector.setEnabled(true);
         this._toolbar.restore();
     },
@@ -349,108 +354,75 @@
     this._lastMode = new Map();
     /** @type {?WebInspector.EmulatedDevice} */
     this._lastDevice = null;
-    /** @type {!Array<!WebInspector.ToolbarButton>} */
-    this._appliedSizeItems = [];
-    /** @type {!Array<!WebInspector.ToolbarMenuButton>} */
-    this._scaleItems = [];
-    /** @type {?Element} */
-    this._visibleToolbar = null;
 
     this._element = createElementWithClass("div", "device-mode-toolbar");
 
-    var leftContainer = this._element.createChild("div", "device-mode-toolbar-left");
+    var leftContainer = this._element.createChild("div", "device-mode-toolbar-spacer");
+    leftContainer.createChild("div", "device-mode-toolbar-spacer");
     var leftToolbar = new WebInspector.Toolbar("", leftContainer);
-    this._noneItem = new WebInspector.ToolbarToggle(WebInspector.UIString("Full"), "enter-fullscreen-toolbar-item");
-    leftToolbar.appendToolbarItem(this._noneItem);
-    this._noneItem.addEventListener("click", this._noneButtonClick, this);
-    this._responsiveItem = new WebInspector.ToolbarToggle(WebInspector.UIString("Responsive"), "responsive-toolbar-item");
-    leftToolbar.appendToolbarItem(this._responsiveItem);
-    this._responsiveItem.addEventListener("click", this._responsiveButtonClick, this);
-    this._deviceItem = new WebInspector.ToolbarToggle(WebInspector.UIString("Device"), "phone-toolbar-item");
-    leftToolbar.appendToolbarItem(this._deviceItem);
-    this._deviceItem.addEventListener("click", this._deviceButtonClick, this);
-    leftToolbar.appendSeparator();
+    leftToolbar.makeWrappable();
+    this._fillLeftToolbar(leftToolbar);
 
-    var middle = this._element.createChild("div", "device-mode-toolbar-middle-container");
-    this._noneToolbar = this._wrapMiddleToolbar(middle, this._createNoneToolbar());
-    this._responsiveToolbar = this._wrapMiddleToolbar(middle, this._createResponsiveToolbar());
-    this._deviceToolbar = this._wrapMiddleToolbar(middle, this._createDeviceToolbar());
+    var mainToolbar = new WebInspector.Toolbar("", this._element);
+    mainToolbar.makeWrappable();
+    this._fillMainToolbar(mainToolbar);
 
-    var rightContainer = this._element.createChild("div", "device-mode-toolbar-right");
-    rightContainer.createChild("div", "device-mode-toolbar-spacer");
+    var rightContainer = this._element.createChild("div", "device-mode-toolbar-spacer");
     var rightToolbar = new WebInspector.Toolbar("", rightContainer);
-    rightToolbar.makeWrappable(true);
-    this._uaItem = new WebInspector.ToolbarText();
-    this._uaItem.setVisible(false);
-    this._uaItem.setTitle(WebInspector.UIString("User agent type"));
-    rightToolbar.appendToolbarItem(this._uaItem);
-    this._deviceScaleItem = new WebInspector.ToolbarText();
-    this._deviceScaleItem.setVisible(false);
-    this._deviceScaleItem.setTitle(WebInspector.UIString("Device pixel ratio"));
-    rightToolbar.appendToolbarItem(this._deviceScaleItem);
-    rightToolbar.appendSeparator();
-    var moreOptionsButton = new WebInspector.ToolbarMenuButton(this._appendMenuItems.bind(this));
-    moreOptionsButton.setTitle(WebInspector.UIString("More options"));
-    rightToolbar.appendToolbarItem(moreOptionsButton);
+    this._fillRightToolbar(rightToolbar);
+    var modeToolbar = new WebInspector.Toolbar("", rightContainer);
+    this._fillModeToolbar(modeToolbar);
+    rightContainer.createChild("div", "device-mode-toolbar-spacer");
+    var optionsToolbar = new WebInspector.Toolbar("", rightContainer);
+    optionsToolbar.makeWrappable(true);
+    this._fillOptionsToolbar(optionsToolbar);
 
-    this._persistenceSetting = WebInspector.settings.createSetting("emulation.deviceModeViewPersistence", {type: WebInspector.DeviceModeModel.Type.None, device: "", orientation: "", mode: ""});
+    WebInspector.emulatedDevicesList.addEventListener(WebInspector.EmulatedDevicesList.Events.CustomDevicesUpdated, this._deviceListChanged, this);
+    WebInspector.emulatedDevicesList.addEventListener(WebInspector.EmulatedDevicesList.Events.StandardDevicesUpdated, this._deviceListChanged, this);
+
+    this._persistenceSetting = WebInspector.settings.createSetting("emulation.deviceModeViewPersistence", {type: WebInspector.DeviceModeModel.Type.Responsive, device: "", orientation: "", mode: ""});
     this._restored = false;
 }
 
 WebInspector.DeviceModeView.Toolbar.prototype = {
     /**
-     * @param {!Element} parent
      * @param {!WebInspector.Toolbar} toolbar
-     * @return {!Element}
      */
-    _wrapMiddleToolbar: function(parent, toolbar)
+    _fillLeftToolbar: function(toolbar)
     {
-        toolbar.makeWrappable();
-        var container = parent.createChild("div", "device-mode-toolbar-middle fill");
-        container.createChild("div", "device-mode-toolbar-spacer");
-        container.appendChild(toolbar.element);
-        container.createChild("div", "device-mode-toolbar-spacer");
-        container.classList.add("hidden");
-        return container;
+        this._deviceSelectItem = new WebInspector.ToolbarMenuButton(this._appendDeviceMenuItems.bind(this));
+        this._deviceSelectItem.setGlyph("");
+        this._deviceSelectItem.turnIntoSelect(95);
+        toolbar.appendToolbarItem(this._deviceSelectItem);
     },
 
     /**
-     * @return {!WebInspector.Toolbar}
+     * @param {!WebInspector.Toolbar} toolbar
      */
-    _createNoneToolbar: function()
+    _fillMainToolbar: function(toolbar)
     {
-        var toolbar = new WebInspector.Toolbar("");
-        this._appendAppliedSizeItems(toolbar);
-        return toolbar;
-    },
-
-    /**
-     * @return {!WebInspector.Toolbar}
-     */
-    _createResponsiveToolbar: function()
-    {
-        var toolbar = new WebInspector.Toolbar("");
-
         var widthInput = createElementWithClass("input", "device-mode-size-input");
-        widthInput.maxLength = 5;
+        widthInput.maxLength = 4;
+        widthInput.type = "text";
         widthInput.title = WebInspector.UIString("Width");
-        this._updateWidthInput = this._bindInput(widthInput, this._model.setWidth.bind(this._model), WebInspector.DeviceModeModel.deviceSizeValidator);
-        toolbar.appendToolbarItem(this._wrapToolbarItem(widthInput));
+        this._updateWidthInput = this._bindInput(widthInput, this._model.setWidthAndScaleToFit.bind(this._model), WebInspector.DeviceModeModel.deviceSizeValidator);
+        this._widthInput = widthInput;
+        this._widthItem = this._wrapToolbarItem(widthInput);
+        toolbar.appendToolbarItem(this._widthItem);
 
         var xElement = createElementWithClass("div", "device-mode-x");
         xElement.textContent = "\u00D7";
-        toolbar.appendToolbarItem(this._wrapToolbarItem(xElement));
+        this._xItem = this._wrapToolbarItem(xElement);
+        toolbar.appendToolbarItem(this._xItem);
 
         var heightInput = createElementWithClass("input", "device-mode-size-input");
-        heightInput.maxLength = 5;
+        heightInput.maxLength = 4;
+        heightInput.type = "text";
         heightInput.title = WebInspector.UIString("Height (leave empty for full)");
-        this._updateHeightInput = this._bindInput(heightInput, this._model.setHeight.bind(this._model), validateHeight);
-        toolbar.appendToolbarItem(this._wrapToolbarItem(heightInput));
+        this._updateHeightInput = this._bindInput(heightInput, this._model.setHeightAndScaleToFit.bind(this._model), validateHeight);
         this._heightInput = heightInput;
-
-        toolbar.appendSeparator();
-        this._appendScaleItem(toolbar);
-        return toolbar;
+        this._heightItem = this._wrapToolbarItem(heightInput);
+        toolbar.appendToolbarItem(this._heightItem);
 
         /**
          * @param {string} value
@@ -463,6 +435,49 @@
     },
 
     /**
+     * @param {!WebInspector.Toolbar} toolbar
+     */
+    _fillRightToolbar: function(toolbar)
+    {
+        this._scaleItem = new WebInspector.ToolbarMenuButton(this._appendScaleMenuItems.bind(this));
+        this._scaleItem.setTitle(WebInspector.UIString("Zoom"));
+        this._scaleItem.setGlyph("");
+        this._scaleItem.turnIntoSelect();
+        toolbar.appendToolbarItem(this._scaleItem);
+    },
+
+    /**
+     * @param {!WebInspector.Toolbar} toolbar
+     */
+    _fillModeToolbar: function(toolbar)
+    {
+        this._modeButton = new WebInspector.ToolbarButton("", "rotate-screen-toolbar-item");
+        this._modeButton.addEventListener("click", this._modeMenuClicked, this);
+        toolbar.appendToolbarItem(this._modeButton);
+    },
+
+    /**
+     * @param {!WebInspector.Toolbar} toolbar
+     */
+    _fillOptionsToolbar: function(toolbar)
+    {
+        this._uaItem = new WebInspector.ToolbarText();
+        this._uaItem.setVisible(false);
+        this._uaItem.setTitle(WebInspector.UIString("User agent type"));
+        toolbar.appendToolbarItem(this._uaItem);
+
+        this._deviceScaleItem = new WebInspector.ToolbarText();
+        this._deviceScaleItem.setVisible(false);
+        this._deviceScaleItem.setTitle(WebInspector.UIString("Device pixel ratio"));
+        toolbar.appendToolbarItem(this._deviceScaleItem);
+
+        var moreOptionsButton = new WebInspector.ToolbarMenuButton(this._appendOptionsMenuItems.bind(this));
+        moreOptionsButton.setTitle(WebInspector.UIString("More options"));
+        toolbar.appendToolbarItem(moreOptionsButton);
+    },
+
+
+    /**
      * @param {!Element} input
      * @param {function(number)} apply
      * @param {function(string):?string} validate
@@ -473,6 +488,7 @@
         input.addEventListener("change", onChange, false);
         input.addEventListener("input", onInput, false);
         input.addEventListener("keydown", onKeyDown, false);
+        input.addEventListener("focus", input.select.bind(input), false);
 
         function onInput()
         {
@@ -536,51 +552,6 @@
     },
 
     /**
-     * @return {!WebInspector.Toolbar}
-     */
-    _createDeviceToolbar: function()
-    {
-        var toolbar = new WebInspector.Toolbar("");
-
-        this._deviceSelect = this._createDeviceSelect();
-        toolbar.appendToolbarItem(this._wrapToolbarItem(this._deviceSelect));
-
-        this._modeButton = new WebInspector.ToolbarButton("", "rotate-screen-toolbar-item");
-        this._modeButton.addEventListener("click", this._modeMenuClicked, this);
-        toolbar.appendToolbarItem(this._modeButton);
-
-        toolbar.appendSeparator();
-        this._appendAppliedSizeItems(toolbar);
-        toolbar.appendSeparator();
-        this._appendScaleItem(toolbar);
-
-        return toolbar;
-    },
-
-    /**
-     * @param {!WebInspector.Toolbar} toolbar
-     */
-    _appendAppliedSizeItems: function(toolbar)
-    {
-        var item = new WebInspector.ToolbarText("");
-        this._appliedSizeItems.push(item);
-        toolbar.appendToolbarItem(item);
-    },
-
-    /**
-     * @param {!WebInspector.Toolbar} toolbar
-     */
-    _appendScaleItem: function(toolbar)
-    {
-        var scaleItem = new WebInspector.ToolbarMenuButton(this._appendScaleMenuItems.bind(this));
-        scaleItem.setTitle(WebInspector.UIString("Zoom"));
-        scaleItem.setGlyph("");
-        scaleItem.addDropDownArrow();
-        toolbar.appendToolbarItem(scaleItem);
-        this._scaleItems.push(scaleItem);
-    },
-
-    /**
      * @param {!WebInspector.ContextMenu} contextMenu
      */
     _appendScaleMenuItems: function(contextMenu)
@@ -609,7 +580,7 @@
     /**
      * @param {!WebInspector.ContextMenu} contextMenu
      */
-    _appendMenuItems: function(contextMenu)
+    _appendOptionsMenuItems: function(contextMenu)
     {
         var uaDisabled = this._model.type() !== WebInspector.DeviceModeModel.Type.Responsive;
         var uaSetting = this._model.uaSetting();
@@ -688,21 +659,6 @@
         return new WebInspector.ToolbarItem(container);
     },
 
-    _noneButtonClick: function()
-    {
-        this._model.emulate(WebInspector.DeviceModeModel.Type.None, null, null);
-    },
-
-    _responsiveButtonClick: function()
-    {
-        this._model.emulate(WebInspector.DeviceModeModel.Type.Responsive, null, null);
-    },
-
-    _deviceButtonClick: function()
-    {
-        this._emulateDevice(this._lastDevice || this._deviceSelect.options[0].device || WebInspector.emulatedDevicesList.standard()[0]);
-    },
-
     /**
      * @param {!WebInspector.EmulatedDevice} device
      */
@@ -711,105 +667,82 @@
         this._model.emulate(WebInspector.DeviceModeModel.Type.Device, device, this._lastMode.get(device) || device.modes[0]);
     },
 
-    /**
-     * @return {!Element}
-     */
-    _createDeviceSelect: function()
+    _switchToResponsive: function()
     {
-        var select = createElementWithClass("select", "device-mode-device-select");
-        WebInspector.emulatedDevicesList.addEventListener(WebInspector.EmulatedDevicesList.Events.CustomDevicesUpdated, deviceListChanged, this);
-        WebInspector.emulatedDevicesList.addEventListener(WebInspector.EmulatedDevicesList.Events.StandardDevicesUpdated, deviceListChanged, this);
-        populateDeviceList.call(this);
-        select.addEventListener("change", optionSelected.bind(this), false);
-        return select;
+        this._model.emulate(WebInspector.DeviceModeModel.Type.Responsive, null, null);
+    },
+
+    /**
+     * @param {!Array<!WebInspector.EmulatedDevice>} devices
+     * @return {!Array<!WebInspector.EmulatedDevice>}
+     */
+    _filterDevices: function(devices)
+    {
+        devices = devices.filter(function(d) { return d.show(); });
+        devices.sort(WebInspector.EmulatedDevice.deviceComparator);
+        return devices;
+    },
+
+    /**
+     * @return {!Array<!WebInspector.EmulatedDevice>}
+     */
+    _standardDevices: function()
+    {
+        return this._filterDevices(WebInspector.emulatedDevicesList.standard());
+    },
+
+    /**
+     * @return {!Array<!WebInspector.EmulatedDevice>}
+     */
+    _customDevices: function()
+    {
+        return this._filterDevices(WebInspector.emulatedDevicesList.custom());
+    },
+
+    /**
+     * @return {!Array<!WebInspector.EmulatedDevice>}
+     */
+    _allDevices: function()
+    {
+        return this._standardDevices().concat(this._customDevices());
+    },
+
+    /**
+     * @param {!WebInspector.ContextMenu} contextMenu
+     */
+    _appendDeviceMenuItems: function(contextMenu)
+    {
+        contextMenu.appendCheckboxItem(WebInspector.UIString("Responsive"), this._switchToResponsive.bind(this), this._model.type() === WebInspector.DeviceModeModel.Type.Responsive, false);
+        appendGroup.call(this, this._standardDevices());
+        appendGroup.call(this, this._customDevices());
+        contextMenu.appendSeparator();
+        contextMenu.appendItem(WebInspector.UIString("Edit\u2026"), WebInspector.emulatedDevicesList.revealCustomSetting.bind(WebInspector.emulatedDevicesList), false);
 
         /**
-         * @this {WebInspector.DeviceModeView.Toolbar}
-         */
-        function populateDeviceList()
-        {
-            select.removeChildren();
-
-            var devicesGroup = select.createChild("optgroup");
-            devicesGroup.label = WebInspector.UIString("Devices");
-            addGroup.call(this, devicesGroup, WebInspector.emulatedDevicesList.standard());
-
-            var customGroup = select.createChild("optgroup");
-            customGroup.label = WebInspector.UIString("Custom");
-            addGroup.call(this, customGroup, WebInspector.emulatedDevicesList.custom());
-            var editCustomOption = new Option(WebInspector.UIString("Edit\u2026"), WebInspector.UIString("Edit\u2026"));
-            editCustomOption.edit = true;
-            customGroup.appendChild(editCustomOption);
-        }
-
-        /**
-         * @this {WebInspector.DeviceModeView.Toolbar}
-         */
-        function deviceListChanged()
-        {
-            populateDeviceList.call(this);
-            if (!this._updateDeviceSelectedIndex() && this._model.type() === WebInspector.DeviceModeModel.Type.Device) {
-                select.selectedIndex = 0;
-                if (!select.options[0].edit)
-                    this._emulateDevice(select.options[0].device);
-            }
-        }
-
-        /**
-         * @param {!Element} parent
          * @param {!Array<!WebInspector.EmulatedDevice>} devices
          * @this {WebInspector.DeviceModeView.Toolbar}
          */
-        function addGroup(parent, devices)
+        function appendGroup(devices)
         {
-            devices = devices.filter(function(d) { return d.show(); });
-            devices.sort(WebInspector.EmulatedDevice.deviceComparator);
+            if (!devices.length)
+                return;
+            contextMenu.appendSeparator();
             for (var device of devices)
-                addOption.call(this, parent, device);
-        }
-
-        /**
-         * @param {!Element} parent
-         * @param {!WebInspector.EmulatedDevice} device
-         * @this {WebInspector.DeviceModeView.Toolbar}
-         */
-        function addOption(parent, device)
-        {
-            var option = new Option(device.title, device.title);
-            option.device = device;
-            parent.appendChild(option);
-
-            if (device === this._model.device())
-                select.selectedIndex = Array.prototype.slice.call(select.options).indexOf(option);
-        }
-
-        /**
-         * @this {WebInspector.DeviceModeView.Toolbar}
-         */
-        function optionSelected()
-        {
-            var option = select.options[select.selectedIndex];
-            if (option.edit) {
-                WebInspector.emulatedDevicesList.revealCustomSetting();
-                this._updateDeviceSelectedIndex();
-            } else {
-                this._emulateDevice(option.device);
-            }
+                contextMenu.appendCheckboxItem(device.title, this._emulateDevice.bind(this, device), this._model.device() === device, false);
         }
     },
 
     /**
-     * @return {boolean}
+     * @this {WebInspector.DeviceModeView.Toolbar}
      */
-    _updateDeviceSelectedIndex: function()
+    _deviceListChanged: function()
     {
-        for (var i = 0; i < this._deviceSelect.options.length; ++i) {
-            if (this._deviceSelect.options[i].device === this._model.device()) {
-                this._deviceSelect.selectedIndex = i;
-                return true;
-            }
-        }
-        return false;
+        if (!this._model.device())
+            return;
+
+        var devices = this._allDevices();
+        if (devices.indexOf(this._model.device()) === -1)
+            this._emulateDevice(devices[0] || WebInspector.emulatedDevicesList.standard()[0]);
     },
 
     /**
@@ -881,48 +814,21 @@
         var updatePersistence = false;
 
         if (this._model.type() !== this._cachedModelType) {
-            this._noneItem.setToggled(this._model.type() === WebInspector.DeviceModeModel.Type.None);
-            this._responsiveItem.setToggled(this._model.type() === WebInspector.DeviceModeModel.Type.Responsive);
-            this._deviceItem.setToggled(this._model.type() === WebInspector.DeviceModeModel.Type.Device);
-
-            var toolbar = null;
-            if (this._model.type() === WebInspector.DeviceModeModel.Type.None)
-                toolbar = this._noneToolbar;
-            else if (this._model.type() === WebInspector.DeviceModeModel.Type.Responsive)
-                toolbar = this._responsiveToolbar;
-            else if (this._model.type() === WebInspector.DeviceModeModel.Type.Device)
-                toolbar = this._deviceToolbar;
-
-            if (this._visibleToolbar !== toolbar) {
-                if (this._visibleToolbar)
-                    this._visibleToolbar.classList.add("hidden");
-                if (toolbar) {
-                    toolbar.classList.remove("hidden");
-                    toolbar.animate([{opacity: "0"}, {opacity: "1"}], {duration: 100});
-                }
-                this._visibleToolbar = toolbar;
-            }
-
             this._previousModelType = this._cachedModelType;
             this._cachedModelType = this._model.type();
+            this._widthInput.disabled = this._model.type() !== WebInspector.DeviceModeModel.Type.Responsive;
+            this._heightInput.disabled = this._model.type() !== WebInspector.DeviceModeModel.Type.Responsive;
             updatePersistence = true;
         }
 
         var size = this._model.appliedDeviceSize();
-        this._updateHeightInput(this._model.isFullHeight() ? 0 : size.height);
+        this._updateHeightInput(this._model.type() === WebInspector.DeviceModeModel.Type.Responsive && this._model.isFullHeight() ? 0 : size.height);
         this._updateWidthInput(size.width);
-        if (!size.isEqual(this._cachedSize)) {
-            for (var item of this._appliedSizeItems)
-                item.setText(WebInspector.UIString("%d \u00D7 %d", size.width, size.height));
-            this._heightInput.placeholder = size.height;
-            this._cachedSize = size;
-        }
+        this._heightInput.placeholder = size.height;
 
         if (this._model.scale() !== this._cachedScale) {
-            for (var item of this._scaleItems) {
-                item.setText(WebInspector.UIString("%.0f%%", this._model.scale() * 100));
-                item.setState(this._model.scale() === 1 ? "off" : "on");
-            }
+            this._scaleItem.setText(WebInspector.UIString("%.0f%%", this._model.scale() * 100));
+            this._scaleItem.setState(this._model.scale() === 1 ? "off" : "on");
             this._cachedScale = this._model.scale();
         }
 
@@ -940,16 +846,21 @@
             this._cachedUaType = uaType;
         }
 
+        var deviceItemTitle = WebInspector.UIString("None");
+        if (this._model.type() === WebInspector.DeviceModeModel.Type.Responsive)
+            deviceItemTitle = WebInspector.UIString("Responsive");
+        if (this._model.type() === WebInspector.DeviceModeModel.Type.Device)
+            deviceItemTitle = this._model.device().title;
+        this._deviceSelectItem.setText(deviceItemTitle);
+
         if (this._model.device() !== this._cachedModelDevice) {
             var device = this._model.device();
-
+            this._modeButton.setVisible(!!device);
             if (device) {
                 var modeCount = device ? device.modes.length : 0;
                 this._modeButton.setEnabled(modeCount >= 2);
                 this._modeButton.setTitle(modeCount === 2 ? WebInspector.UIString("Rotate") : WebInspector.UIString("Screen options"));
             }
-            this._updateDeviceSelectedIndex();
-
             this._cachedModelDevice = device;
             updatePersistence = true;
         }
@@ -964,7 +875,7 @@
             updatePersistence = true;
         }
 
-        if (updatePersistence) {
+        if (updatePersistence && this._cachedModelType !== WebInspector.DeviceModeModel.Type.None) {
             var value = this._persistenceSetting.get();
             value.type = this._cachedModelType;
             if (this._cachedModelDevice) {
@@ -980,20 +891,16 @@
     {
         if (this._restored)
             return;
-
         this._restored = true;
 
-        for (var i = 0; i < this._deviceSelect.options.length; ++i) {
-            if (this._deviceSelect.options[i].device && this._deviceSelect.options[i].device.title === this._persistenceSetting.get().device)
-                this._lastDevice = this._deviceSelect.options[i].device;
-        }
-        if (this._lastDevice) {
-            for (var i = 0; i < this._lastDevice.modes.length; ++i) {
-                if (this._lastDevice.modes[i].orientation === this._persistenceSetting.get().orientation && this._lastDevice.modes[i].title === this._persistenceSetting.get().mode)
-                    this._lastMode.set(this._lastDevice, this._lastDevice.modes[i]);
+        for (var device of this._allDevices()) {
+            if (device.title === this._persistenceSetting.get().device) {
+                this._lastDevice = device;
+                for (var mode of device.modes) {
+                    if (mode.orientation === this._persistenceSetting.get().orientation && mode.title === this._persistenceSetting.get().mode)
+                        this._lastMode.set(device, mode);
+                }
             }
-        } else {
-            this._model.emulate(WebInspector.DeviceModeModel.Type.None, null, null);
         }
 
         this._applyType(/** @type {!WebInspector.DeviceModeModel.Type} */ (this._persistenceSetting.get().type));
@@ -1010,11 +917,11 @@
     _applyType: function(type)
     {
         if (type === WebInspector.DeviceModeModel.Type.Responsive)
-            this._responsiveButtonClick();
+            this._model.emulate(WebInspector.DeviceModeModel.Type.Responsive, null, null);
         else if (type === WebInspector.DeviceModeModel.Type.Device)
-            this._deviceButtonClick();
+            this._emulateDevice(this._lastDevice || this._allDevices()[0] || WebInspector.emulatedDevicesList.standard()[0]);
         else
-            this._noneButtonClick();
+            this._model.emulate(WebInspector.DeviceModeModel.Type.None, null, null);
     }
 }
 
@@ -1148,10 +1055,6 @@
             WebInspector.DeviceModeView._wrapperInstance._toggleDeviceMode();
             return true;
         }
-        if (actionId === "emulation.toggle-device-toolbar" && WebInspector.DeviceModeView._wrapperInstance) {
-            WebInspector.DeviceModeView._wrapperInstance._toggleDeviceToolbar();
-            return true;
-        }
         return false;
     }
 }
@@ -1168,9 +1071,10 @@
     WebInspector.DeviceModeView._wrapperInstance = this;
     this._inspectedPagePlaceholder = inspectedPagePlaceholder;
     this._deviceModeView = new WebInspector.DeviceModeView();
-    this._showDeviceToolbarSetting = WebInspector.settings.createSetting("emulation.showDeviceToolbar", true);
-    this._showDeviceToolbarSetting.addChangeListener(this._update, this);
-    this._update();
+    this._toggleDeviceModeAction = WebInspector.actionRegistry.action("emulation.toggle-device-mode");
+    this._showDeviceModeSetting = WebInspector.settings.createSetting("emulation.showDeviceMode", false);
+    this._showDeviceModeSetting.addChangeListener(this._update.bind(this, false));
+    this._update(true);
 }
 
 /** @type {!WebInspector.DeviceModeView.Wrapper} */
@@ -1179,18 +1083,19 @@
 WebInspector.DeviceModeView.Wrapper.prototype = {
     _toggleDeviceMode: function()
     {
-        if (this._showDeviceToolbarSetting.get())
-            this._deviceModeView.toggleDeviceMode();
+        this._showDeviceModeSetting.set(!this._showDeviceModeSetting.get());
     },
 
-    _toggleDeviceToolbar: function()
+    /**
+     * @param {boolean} force
+     */
+    _update: function(force)
     {
-        this._showDeviceToolbarSetting.set(!this._showDeviceToolbarSetting.get());
-    },
+        this._toggleDeviceModeAction.setToggled(this._showDeviceModeSetting.get());
+        if (!force && this._showDeviceModeSetting.get() === this._deviceModeView.isShowing())
+            return;
 
-    _update: function()
-    {
-        if (this._showDeviceToolbarSetting.get()) {
+        if (this._showDeviceModeSetting.get()) {
             this._deviceModeView.show(this.element);
             this._inspectedPagePlaceholder.clearMinimumSizeAndMargins();
             this._inspectedPagePlaceholder.show(this._deviceModeView.element);
@@ -1198,8 +1103,8 @@
             this._deviceModeView.detach();
             this._inspectedPagePlaceholder.restoreMinimumSizeAndMargins();
             this._inspectedPagePlaceholder.show(this.element);
-            this._deviceModeView._model.emulate(WebInspector.DeviceModeModel.Type.None, null, null);
         }
+        this._deviceModeView.toggleDeviceMode();
     },
 
     __proto__: WebInspector.VBox.prototype
diff --git a/third_party/WebKit/Source/devtools/front_end/emulation/deviceModeToolbar.css b/third_party/WebKit/Source/devtools/front_end/emulation/deviceModeToolbar.css
index 72fb661..e45ca46b 100644
--- a/third_party/WebKit/Source/devtools/front_end/emulation/deviceModeToolbar.css
+++ b/third_party/WebKit/Source/devtools/front_end/emulation/deviceModeToolbar.css
@@ -8,8 +8,8 @@
     background: hsl(0, 0%, 100%);
     border: none;
     padding: 2px 0;
-    width: 39px !important;
-    margin: 0 3px;
+    width: 34px !important;
+    margin: 0 2px;
     text-align: center;
     box-shadow: 0px 0px 1px 0px hsla(0, 0%, 0%, 0.13);
     border-radius: 1px;
@@ -26,6 +26,7 @@
 
 .device-mode-size-input:disabled {
     background: transparent;
+    box-shadow: none;
     -webkit-user-select: none;
 }
 
@@ -33,21 +34,3 @@
     margin: 0 1px;
     font-size: 16px;
 }
-
-.device-mode-device-select {
-    background: none;
-    box-shadow: none;
-    border: none;
-    outline: none;
-    padding: 0 2px;
-    -webkit-appearance: menulist;
-    margin: 0;
-    width: 120px;
-}
-
-.device-mode-checkbox {
-    width: 120px;
-    display: flex;
-    flex-direction: row;
-    justify-content: center;
-}
diff --git a/third_party/WebKit/Source/devtools/front_end/emulation/deviceModeView.css b/third_party/WebKit/Source/devtools/front_end/emulation/deviceModeView.css
index a57a5f5..31bd416 100644
--- a/third_party/WebKit/Source/devtools/front_end/emulation/deviceModeView.css
+++ b/third_party/WebKit/Source/devtools/front_end/emulation/deviceModeView.css
@@ -18,43 +18,18 @@
     display: flex;
     flex-direction: row;
     align-items: stretch;
-    padding: 0 4px;
 }
 
 .device-mode-toolbar .toolbar {
-    padding: 0;
     overflow: hidden;
-    flex: auto;
-}
-
-.device-mode-toolbar-left {
-    flex: 0 1000 155px;
-    min-width: 93px;
-}
-
-.device-mode-toolbar-right {
-    flex: 0 1000 155px;
-    min-width: 40px;
-    display: flex;
-}
-
-.device-mode-toolbar-middle-container {
-    flex: 1 1 160px;
-    position: relative;
-}
-
-.device-mode-toolbar-middle {
-    display: flex;
-    justify-content: flex-start;
-    overflow: hidden;
-}
-
-.device-mode-toolbar-middle .toolbar {
-    flex: 0 1 auto;
+    flex: none;
+    padding: 0 5px;
 }
 
 .device-mode-toolbar-spacer {
-    flex: auto;
+    flex: 1 1 0;
+    display: flex;
+    flex-direction: row;
 }
 
 .device-mode-content-clip {
@@ -68,6 +43,10 @@
     box-shadow: inset 0 -1px #ccc;
 }
 
+.device-mode-content-clip:not(.device-mode-rulers-visible) .device-mode-media-container {
+    margin-bottom: 20px;
+}
+
 .device-mode-presets-container {
     flex: 0 0 20px;
     display: flex;
@@ -75,11 +54,12 @@
 
 .device-mode-presets-container-inner {
     flex: auto;
-    background-color: red;
     justify-content: center;
     position: relative;
     background-color: hsl(0, 0%, 90%);
-+}
+    border: 2px solid hsl(0, 0%, 98%);
+    border-bottom: 2px solid hsl(0, 0%, 98%);
+ }
 
 .device-mode-presets-container:hover {
     transition: opacity 0.1s;
@@ -94,16 +74,18 @@
 }
 
 .device-mode-preset-bar {
-    border: 2px solid hsl(0, 0%, 98%);
+    border-left: 2px solid hsl(0, 0%, 98%);
+    border-right: 2px solid hsl(0, 0%, 98%);
     pointer-events: auto;
     text-align: center;
     flex: none;
     cursor: pointer;
-    color: #333;
+    color: #5A5A5A;
     display: flex;
     align-items: center;
     justify-content: center;
     white-space: nowrap;
+    margin-bottom: 1px;
 }
 
 .device-mode-preset-bar:hover {
@@ -128,10 +110,6 @@
     margin: 0;
 }
 
-.device-mode-content-area:not(.device-mode-type-none):not(.device-mode-rulers-visible) {
-    margin-top: 20px;
-}
-
 .device-mode-screen-area {
     position: absolute;
     left: 0;
@@ -168,14 +146,14 @@
 
 .device-mode-width-resizer {
     top: 0;
-    bottom: 0;
+    bottom: -2px;
     right: -20px;
     width: 20px;
 }
 
 .device-mode-height-resizer {
     left: 0;
-    right: 0;
+    right: -2px;
     bottom: -20px;
     height: 20px;
 }
@@ -203,8 +181,8 @@
 
 .device-mode-corner-resizer > div {
     position: absolute;
-    bottom: 5px;
-    right: 5px;
+    bottom: 3px;
+    right: 3px;
     width: 13px;
     height: 13px;
     content: url(Images/resizeDiagonal.png);
diff --git a/third_party/WebKit/Source/devtools/front_end/emulation/module.json b/third_party/WebKit/Source/devtools/front_end/emulation/module.json
index 92dca2e3..a43365c 100644
--- a/third_party/WebKit/Source/devtools/front_end/emulation/module.json
+++ b/third_party/WebKit/Source/devtools/front_end/emulation/module.json
@@ -40,7 +40,10 @@
             "type": "@WebInspector.ActionDelegate",
             "actionId": "emulation.toggle-device-mode",
             "className": "WebInspector.DeviceModeView.ActionDelegate",
+            "condition": "can_dock",
             "experiment": "deviceMode",
+            "title": "Toggle device mode",
+            "iconClass": "phone-toolbar-item",
             "bindings": [
                 {
                     "platform": "windows,linux",
@@ -53,11 +56,11 @@
             ]
         },
         {
-            "type": "@WebInspector.ActionDelegate",
-            "actionId": "emulation.toggle-device-toolbar",
-            "className": "WebInspector.DeviceModeView.ActionDelegate",
-            "experiment": "deviceMode",
-            "title": "Toggle device toolbar"
+            "type": "@WebInspector.ToolbarItem.Provider",
+            "actionId": "emulation.toggle-device-mode",
+            "condition": "can_dock",
+            "location": "main-toolbar-left",
+            "order": 1
         },
         {
             "type": "@WebInspector.Revealer",
diff --git a/third_party/WebKit/Source/devtools/front_end/timeline/CountersGraph.js b/third_party/WebKit/Source/devtools/front_end/timeline/CountersGraph.js
index ffbe3539..588ca4b 100644
--- a/third_party/WebKit/Source/devtools/front_end/timeline/CountersGraph.js
+++ b/third_party/WebKit/Source/devtools/front_end/timeline/CountersGraph.js
@@ -30,16 +30,15 @@
 
 /**
  * @constructor
- * @extends {WebInspector.SplitWidget}
+ * @extends {WebInspector.VBox}
  * @implements {WebInspector.TimelineModeView}
- * @param {string} title
  * @param {!WebInspector.TimelineModeViewDelegate} delegate
  * @param {!WebInspector.TimelineModel} model
  * @param {!Array<!WebInspector.TimelineModel.Filter>} filters
  */
-WebInspector.CountersGraph = function(title, delegate, model, filters)
+WebInspector.CountersGraph = function(delegate, model, filters)
 {
-    WebInspector.SplitWidget.call(this, true, false, "memoryCountersSidebar");
+    WebInspector.VBox.call(this);
 
     this.element.id = "memory-graphs-container";
 
@@ -48,11 +47,16 @@
     this._filters = filters;
     this._calculator = new WebInspector.CounterGraphCalculator(this._model);
 
+    // Create selectors
+    this._infoWidget = new WebInspector.HBox();
+    this._infoWidget.element.classList.add("memory-counter-selector-swatches");
+    this._infoWidget.show(this.element);
+
     this._graphsContainer = new WebInspector.VBox();
-    this.setMainWidget(this._graphsContainer);
-    this._createCurrentValuesBar();
+    this._graphsContainer.show(this.element);
     var canvasWidget = new WebInspector.VBoxWithResizeCallback(this._resize.bind(this));
     canvasWidget.show(this._graphsContainer.element);
+    this._createCurrentValuesBar();
     this._canvasContainer = canvasWidget.element;
     this._canvasContainer.id = "memory-graphs-canvas-container";
     this._canvas = this._canvasContainer.createChild("canvas");
@@ -66,11 +70,6 @@
     this._timelineGrid = new WebInspector.TimelineGrid();
     this._canvasContainer.appendChild(this._timelineGrid.dividersElement);
 
-    // Populate sidebar
-    this._infoWidget = new WebInspector.VBox();
-    this._infoWidget.element.classList.add("sidebar-tree");
-    this._infoWidget.element.createChild("div", "sidebar-tree-section").textContent = title;
-    this.setSidebarWidget(this._infoWidget);
     this._counters = [];
     this._counterUI = [];
 }
@@ -299,7 +298,7 @@
     {
     },
 
-    __proto__: WebInspector.SplitWidget.prototype
+    __proto__: WebInspector.VBox.prototype
 }
 
 /**
@@ -411,7 +410,7 @@
     this._memoryCountersPane = memoryCountersPane;
     this.counter = counter;
     this._formatter = formatter || Number.withThousandsSeparator;
-    var container = memoryCountersPane._infoWidget.element.createChild("div", "memory-counter-sidebar-info");
+    var container = memoryCountersPane._infoWidget.element.createChild("div", "memory-counter-selector-info");
 
     this._filter = new WebInspector.CheckboxFilterUI(title, title);
     var color = WebInspector.Color.parse(graphColor).setAlpha(0.5).asString(WebInspector.Color.Format.RGBA);
diff --git a/third_party/WebKit/Source/devtools/front_end/timeline/MemoryCountersGraph.js b/third_party/WebKit/Source/devtools/front_end/timeline/MemoryCountersGraph.js
index 4a04cbe4..6df0500 100644
--- a/third_party/WebKit/Source/devtools/front_end/timeline/MemoryCountersGraph.js
+++ b/third_party/WebKit/Source/devtools/front_end/timeline/MemoryCountersGraph.js
@@ -38,7 +38,7 @@
  */
 WebInspector.MemoryCountersGraph = function(delegate, model, filters)
 {
-    WebInspector.CountersGraph.call(this, WebInspector.UIString("MEMORY"), delegate, model, filters);
+    WebInspector.CountersGraph.call(this, delegate, model, filters);
     this._countersByName = {};
     this._countersByName["jsHeapSizeUsed"] = this.createCounter(WebInspector.UIString("JS Heap"), WebInspector.UIString("JS Heap: %s"), "hsl(220, 90%, 43%)", Number.bytesToString);
     this._countersByName["documents"] = this.createCounter(WebInspector.UIString("Documents"), WebInspector.UIString("Documents: %s"), "hsl(0, 90%, 43%)");
diff --git a/third_party/WebKit/Source/devtools/front_end/timeline/TimelineFlameChart.js b/third_party/WebKit/Source/devtools/front_end/timeline/TimelineFlameChart.js
index 2c7457c..3380e85 100644
--- a/third_party/WebKit/Source/devtools/front_end/timeline/TimelineFlameChart.js
+++ b/third_party/WebKit/Source/devtools/front_end/timeline/TimelineFlameChart.js
@@ -1327,14 +1327,6 @@
 
     /**
      * @override
-     * @param {number} width
-     */
-    setSidebarSize: function(width)
-    {
-    },
-
-    /**
-     * @override
      * @param {?WebInspector.TimelineModel.Record} record
      * @param {string=} regex
      * @param {boolean=} selectRecord
diff --git a/third_party/WebKit/Source/devtools/front_end/timeline/TimelinePanel.js b/third_party/WebKit/Source/devtools/front_end/timeline/TimelinePanel.js
index 4ab838e..e3f5981 100644
--- a/third_party/WebKit/Source/devtools/front_end/timeline/TimelinePanel.js
+++ b/third_party/WebKit/Source/devtools/front_end/timeline/TimelinePanel.js
@@ -220,16 +220,6 @@
     /**
      * @param {!WebInspector.Event} event
      */
-    _sidebarResized: function(event)
-    {
-        var width = /** @type {number} */ (event.data);
-        for (var i = 0; i < this._currentViews.length; ++i)
-            this._currentViews[i].setSidebarSize(width);
-    },
-
-    /**
-     * @param {!WebInspector.Event} event
-     */
     _onWindowChanged: function(event)
     {
         this._windowStartTime = event.data.startTime;
@@ -304,16 +294,12 @@
         modeView.setWindowTimes(this.windowStartTime(), this.windowEndTime());
         modeView.refreshRecords();
         this._stackView.appendView(modeView.view(), "timelinePanelTimelineStackSplitViewState", undefined, 112);
-        modeView.view().addEventListener(WebInspector.SplitWidget.Events.SidebarSizeChanged, this._sidebarResized, this);
         this._currentViews.push(modeView);
     },
 
     _removeAllModeViews: function()
     {
-        for (var i = 0; i < this._currentViews.length; ++i) {
-            this._currentViews[i].removeEventListener(WebInspector.SplitWidget.Events.SidebarSizeChanged, this._sidebarResized, this);
-            this._currentViews[i].dispose();
-        }
+        this._currentViews.forEach(view => view.dispose());
         this._currentViews = [];
         this._stackView.detachChildWidgets();
     },
@@ -1242,8 +1228,14 @@
         var leftTime = tasks[leftIndex].startTime();
         var rightTime = tasks[rightIndex].endTime();
         var span = rightTime - leftTime;
-        leftTime = Math.max(leftTime - 0.05 * span, this._tracingModel.minimumRecordTime());
-        rightTime = Math.min(rightTime + 0.05 * span, this._tracingModel.maximumRecordTime());
+        var totalSpan = this._tracingModel.maximumRecordTime() - this._tracingModel.minimumRecordTime();
+        if (span < totalSpan * 0.1) {
+            leftTime = this._tracingModel.minimumRecordTime();
+            rightTime = this._tracingModel.maximumRecordTime();
+        } else {
+            leftTime = Math.max(leftTime - 0.05 * span, this._tracingModel.minimumRecordTime());
+            rightTime = Math.min(rightTime + 0.05 * span, this._tracingModel.maximumRecordTime());
+        }
         this.requestWindowTimes(leftTime, rightTime);
     },
 
@@ -1310,13 +1302,6 @@
 
     /**
      * @override
-     */
-    setSidebarSize: function()
-    {
-    },
-
-    /**
-     * @override
      * @param {number} startTime
      * @param {number} endTime
      */
@@ -1579,11 +1564,6 @@
     setWindowTimes: function(startTime, endTime) {},
 
     /**
-     * @param {number} width
-     */
-    setSidebarSize: function(width) {},
-
-    /**
      * @param {?WebInspector.TimelineSelection} selection
      */
     setSelection: function(selection) {},
diff --git a/third_party/WebKit/Source/devtools/front_end/timeline/timelinePanel.css b/third_party/WebKit/Source/devtools/front_end/timeline/timelinePanel.css
index 0fb37fb..a5a6064 100644
--- a/third_party/WebKit/Source/devtools/front_end/timeline/timelinePanel.css
+++ b/third_party/WebKit/Source/devtools/front_end/timeline/timelinePanel.css
@@ -258,35 +258,32 @@
     margin-top: -2px;
 }
 
-#memory-graphs-container > div:last-child {
-    background-color: #eee;
-    overflow-y: hidden;
-}
-
-#memory-graphs-container .sidebar-tree-section {
+#memory-graphs-container .memory-counter-selector-swatches {
     flex: 0 0 24px;
-    padding: 5px 0 0 5px;
+    padding: 5px 0;
+    background-color: #eee;
+    border-bottom: 1px solid #ddd;
 }
 
-.memory-counter-sidebar-info {
-    flex: 0 0 20px;
+.memory-counter-selector-info {
+    flex: 0 0 auto;
     margin-left: 5px;
     white-space: nowrap;
 }
 
-.memory-counter-sidebar-info .range {
+.memory-counter-selector-info .range {
     margin: 0 4px;
     align-items: center;
     display: inline-flex;
 }
 
 .memory-counter-value {
-    margin: 4px;
+    margin: 8px;
 }
 
 #counter-values-bar {
-    flex: 0 0 18px;
-    border-bottom: solid 1px lightgray;
+    flex: 0 0 20px;
+    border-top: solid 1px lightgray;
     width: 100%;
     overflow: hidden;
     line-height: 18px;
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/Toolbar.js b/third_party/WebKit/Source/devtools/front_end/ui/Toolbar.js
index 7175fe9..64b1078 100644
--- a/third_party/WebKit/Source/devtools/front_end/ui/Toolbar.js
+++ b/third_party/WebKit/Source/devtools/front_end/ui/Toolbar.js
@@ -350,17 +350,14 @@
     },
 
     /**
-     * @param {boolean} dimmed
+     * @param {number=} width
      */
-    setDimmed: function(dimmed)
-    {
-        this.element.classList.toggle("toolbar-dimmed", dimmed);
-    },
-
-    addDropDownArrow: function()
+    turnIntoSelect: function(width)
     {
         this.element.classList.add("toolbar-has-dropdown");
         this.element.createChild("div", "toolbar-dropdown-arrow");
+        if (width)
+            this.element.style.width = width + "px";
     },
 
     /**
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/toolbar.css b/third_party/WebKit/Source/devtools/front_end/ui/toolbar.css
index f452d71c..efc1ede 100644
--- a/third_party/WebKit/Source/devtools/front_end/ui/toolbar.css
+++ b/third_party/WebKit/Source/devtools/front_end/ui/toolbar.css
@@ -57,6 +57,7 @@
     display: inline-block;
     pointer-events: none;
     margin: auto 0;
+    flex: none;
 }
 
 @media (-webkit-min-device-pixel-ratio: 1.5) {
@@ -80,8 +81,16 @@
     color: #5a5a5a;
 }
 
+.toolbar-has-dropdown {
+    justify-content: space-between;
+}
+
 .toolbar-has-dropdown .toolbar-text {
-    margin-right: 1px;
+    margin: 0 4px 0 0;
+    text-overflow: ellipsis;
+    flex: auto;
+    overflow: hidden;
+    text-align: right;
 }
 
 .toolbar-has-glyph .toolbar-text {
@@ -92,18 +101,10 @@
     font-weight: bold;
 }
 
-.toolbar-button:not(.toolbar-has-glyph).hover {
+.toolbar-button:not(.toolbar-has-glyph):not(.toolbar-has-dropdown):not(.menu-toolbar-item).hover {
     background-color: #f3f3f3;
 }
 
-.toolbar-dimmed .toolbar-text {
-    color: #999;
-}
-
-.toolbar-dimmed .toolbar-dropdown-arrow {
-    background-color: #999;
-}
-
 .toolbar-glyph {
     -webkit-mask-image: url(Images/toolbarButtonGlyphs.png);
     -webkit-mask-size: 352px 168px;
diff --git a/third_party/WebKit/Source/platform/image-decoders/gif/GIFImageDecoder.cpp b/third_party/WebKit/Source/platform/image-decoders/gif/GIFImageDecoder.cpp
index cc5954e..bf46ddc 100644
--- a/third_party/WebKit/Source/platform/image-decoders/gif/GIFImageDecoder.cpp
+++ b/third_party/WebKit/Source/platform/image-decoders/gif/GIFImageDecoder.cpp
@@ -220,15 +220,48 @@
 
 size_t GIFImageDecoder::clearCacheExceptFrame(size_t clearExceptFrame)
 {
-    // We need to preserve frames such that:
-    //  1. We don't clear |clearExceptFrame|;
-    //  2. We don't clear any frame from which a future initFrameBuffer() call
-    //     will copy bitmap data.
-    // All other frames can be cleared.
+    // We expect that after this call, we'll be asked to decode frames after
+    // this one.  So we want to avoid clearing frames such that those requests
+    // would force re-decoding from the beginning of the image.
+    //
+    // When |clearExceptFrame| is e.g. DisposeKeep, simply not clearing that
+    // frame is sufficient, as the next frame will be based on it, and in
+    // general future frames can't be based on anything previous.
+    //
+    // However, if this frame is DisposeOverwritePrevious, then subsequent
+    // frames will depend on this frame's required previous frame.  In this
+    // case, we need to preserve both this frame and that one.
+    size_t clearExceptFrame2 = kNotFound;
+    if (clearExceptFrame < m_frameBufferCache.size()) {
+        const ImageFrame& frame = m_frameBufferCache[clearExceptFrame];
+        if ((frame.status() != ImageFrame::FrameEmpty) && (frame.disposalMethod() == ImageFrame::DisposeOverwritePrevious)) {
+            clearExceptFrame2 = clearExceptFrame;
+            clearExceptFrame = frame.requiredPreviousFrameIndex();
+        }
+    }
+
+    // Now |clearExceptFrame| indicates the frame that future frames will
+    // depend on.  But if decoding is skipping forward past intermediate frames,
+    // this frame may be FrameEmpty.  So we need to keep traversing back through
+    // the required previous frames until we find the nearest non-empty
+    // ancestor.  Preserving that will minimize the amount of future decoding
+    // needed.
     while ((clearExceptFrame < m_frameBufferCache.size()) && (m_frameBufferCache[clearExceptFrame].status() == ImageFrame::FrameEmpty))
         clearExceptFrame = m_frameBufferCache[clearExceptFrame].requiredPreviousFrameIndex();
+    return clearCacheExceptTwoFrames(clearExceptFrame, clearExceptFrame2);
+}
 
-    return ImageDecoder::clearCacheExceptFrame(clearExceptFrame);
+
+size_t GIFImageDecoder::clearCacheExceptTwoFrames(size_t clearExceptFrame1, size_t clearExceptFrame2)
+{
+    size_t frameBytesCleared = 0;
+    for (size_t i = 0; i < m_frameBufferCache.size(); ++i) {
+        if (m_frameBufferCache[i].status() != ImageFrame::FrameEmpty && i != clearExceptFrame1 && i != clearExceptFrame2) {
+            frameBytesCleared += frameBytesAtIndex(i);
+            clearFrameBuffer(i);
+        }
+    }
+    return frameBytesCleared;
 }
 
 void GIFImageDecoder::clearFrameBuffer(size_t frameIndex)
diff --git a/third_party/WebKit/Source/platform/image-decoders/gif/GIFImageDecoder.h b/third_party/WebKit/Source/platform/image-decoders/gif/GIFImageDecoder.h
index 3ce2da9..f9aa02c4 100644
--- a/third_party/WebKit/Source/platform/image-decoders/gif/GIFImageDecoder.h
+++ b/third_party/WebKit/Source/platform/image-decoders/gif/GIFImageDecoder.h
@@ -81,6 +81,9 @@
     // failure, this will mark the image as failed.
     bool initFrameBuffer(size_t frameIndex);
 
+    // Like clearCacheExceptFrame(), but preserves two frames instead of one.
+    size_t clearCacheExceptTwoFrames(size_t, size_t);
+
     bool m_currentBufferSawAlpha;
     mutable int m_repetitionCount;
     OwnPtr<GIFImageReader> m_reader;
diff --git a/tools/clang/rewrite_to_chrome_style/RewriteToChromeStyle.cpp b/tools/clang/rewrite_to_chrome_style/RewriteToChromeStyle.cpp
index 41e3e5c..fcbd92165 100644
--- a/tools/clang/rewrite_to_chrome_style/RewriteToChromeStyle.cpp
+++ b/tools/clang/rewrite_to_chrome_style/RewriteToChromeStyle.cpp
@@ -14,8 +14,10 @@
 
 #include <assert.h>
 #include <algorithm>
+#include <fstream>
 #include <memory>
 #include <string>
+#include <unordered_map>
 #include <unordered_set>
 
 #include "clang/AST/ASTContext.h"
@@ -221,17 +223,28 @@
 
   void run(const MatchFinder::MatchResult& result) override {
     std::string name;
-    if (!GetNameForDecl(*result.Nodes.getNodeAs<DeclNode>("decl"), name))
+    const DeclNode* decl = result.Nodes.getNodeAs<DeclNode>("decl");
+    if (!GetNameForDecl(*decl, name))
       return;
-    replacements_->emplace(*result.SourceManager,
-                           TargetNodeTraits<TargetNode>::GetRange(
-                               *result.Nodes.getNodeAs<TargetNode>(
-                                   TargetNodeTraits<TargetNode>::kName)),
-                           name);
+    auto r = replacements_->emplace(
+        *result.SourceManager, TargetNodeTraits<TargetNode>::GetRange(
+                                   *result.Nodes.getNodeAs<TargetNode>(
+                                       TargetNodeTraits<TargetNode>::kName)),
+        name);
+    auto from = decl->getNameAsString();
+    auto to = r.first->getReplacementText().str();
+    if (from != to)
+      replacement_names_.emplace(std::move(from), std::move(to));
+  }
+
+  const std::unordered_map<std::string, std::string>& replacement_names()
+      const {
+    return replacement_names_;
   }
 
  private:
   Replacements* const replacements_;
+  std::unordered_map<std::string, std::string> replacement_names_;
 };
 
 using FieldDeclRewriter = RewriterBase<clang::FieldDecl, clang::NamedDecl>;
@@ -488,6 +501,18 @@
   if (result != 0)
     return result;
 
+  std::ofstream replacement_db_file("rewrite-sym.txt",
+                                    std::ios_base::out | std::ios_base::app);
+  for (const auto& p : field_decl_rewriter.replacement_names())
+    replacement_db_file << "var:" << p.first << ":" << p.second << "\n";
+  for (const auto& p : var_decl_rewriter.replacement_names())
+    replacement_db_file << "var:" << p.first << ":" << p.second << "\n";
+  for (const auto& p : function_decl_rewriter.replacement_names())
+    replacement_db_file << "fun:" << p.first << ":" << p.second << "\n";
+  for (const auto& p : method_decl_rewriter.replacement_names())
+    replacement_db_file << "fun:" << p.first << ":" << p.second << "\n";
+  replacement_db_file.close();
+
   // Serialization format is documented in tools/clang/scripts/run_tool.py
   llvm::outs() << "==== BEGIN EDITS ====\n";
   for (const auto& r : replacements) {
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index 24f60ef..129dd85 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -40148,8 +40148,8 @@
   <summary>
     The cpu usage range reported for the browser process when the chromeos
     device memory pressure (which is the percentage of total memory used by the
-    system) is moderate or critical. This is emitted only when memory pressure
-    changes from a low pressure to a higher pressure.
+    system) is critical. This is emitted only when memory pressure changes from
+    a low pressure to a higher pressure.
   </summary>
 </histogram>
 
@@ -40159,8 +40159,8 @@
   <summary>
     The system memory usage range reported for the browser process when the
     chromeos device memory pressure (which is the percentage of total memory
-    used by the system) is moderate or critical. This is emitted only when
-    memory pressure changes from a low pressure to a higher pressure.
+    used by the system) is critical. This is emitted only when memory pressure
+    changes from a low pressure to a higher pressure.
   </summary>
 </histogram>
 
@@ -40170,8 +40170,8 @@
   <summary>
     The cpu usage range reported for the GPU process when the chromeos device
     memory pressure (which is the percentage of total memory used by the system)
-    is moderate or critical. This is emitted only when memory pressure changes
-    from a low pressure to a higher pressure.
+    is critical. This is emitted only when memory pressure changes from a low
+    pressure to a higher pressure.
   </summary>
 </histogram>
 
@@ -40181,8 +40181,8 @@
   <summary>
     The system's RAM memory usage range reported for the GPU process when the
     chromeos device memory pressure (which is the percentage of total memory
-    used by the system) is moderate or critical. This is emitted only when
-    memory pressure changes from a low pressure to a higher pressure.
+    used by the system) is critical. This is emitted only when memory pressure
+    changes from a low pressure to a higher pressure.
   </summary>
 </histogram>
 
@@ -63482,6 +63482,7 @@
   <int value="1100" label="WEBRTCLOGGINGPRIVATE_STARTAUDIODEBUGRECORDINGS"/>
   <int value="1101" label="WEBRTCLOGGINGPRIVATE_STOPAUDIODEBUGRECORDINGS"/>
   <int value="1102" label="TERMINALPRIVATE_ACKOUTPUT"/>
+  <int value="1103" label="INPUT_IME_CREATEWINDOW"/>
 </enum>
 
 <enum name="ExtensionInstallCause" type="int">
diff --git a/tools/valgrind/gtest_exclude/content_browsertests.gtest-drmemory.txt b/tools/valgrind/gtest_exclude/content_browsertests.gtest-drmemory.txt
index 05c54d5..fcbaf975 100644
--- a/tools/valgrind/gtest_exclude/content_browsertests.gtest-drmemory.txt
+++ b/tools/valgrind/gtest_exclude/content_browsertests.gtest-drmemory.txt
@@ -53,9 +53,6 @@
 # https://crbug.com/536881
 IndexedDBBrowserTest.DiskFullOnCommit
 
-# https://crbug.com/569752
-SitePerProcessBrowserTest.*
-
 # https://crbug.com/571264
 WebRtcMediaRecorderTest.MediaRecorderPausePreventsDataavailableFromBeingFired