diff --git a/DEPS b/DEPS
index 3a519fc..559c1f5 100644
--- a/DEPS
+++ b/DEPS
@@ -126,11 +126,11 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Skia
   # and whatever else without interference from each other.
-  'skia_revision': '30595ea7c7825fb170d546cf77602e37b2ec8bd6',
+  'skia_revision': '217acf58d0d80c50854c1fd8f6684c325d8d6de6',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
-  'v8_revision': '872455b5fe0cf1f09eb5550fb1e0bdd259523e8b',
+  'v8_revision': 'd24c8dd69f1c7e89553ce101272aedefdb41110d',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling swarming_client
   # and whatever else without interference from each other.
@@ -138,15 +138,15 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling ANGLE
   # and whatever else without interference from each other.
-  'angle_revision': '6b695c3ffb27ad1df71f4f1682dc7a1d8adc9f31',
+  'angle_revision': 'c66fb571be1a1599791a6d96d4055b3b84534a14',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling SwiftShader
   # and whatever else without interference from each other.
-  'swiftshader_revision': '64c44b0c53c45809c70e7b075ed3a74a9f3eec0d',
+  'swiftshader_revision': 'f969488577804ce90954f93da22b83ec9ae5d1e0',
   # 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': '7abb469ef7ebbce4645165d1d0e1dbb6c8e68461',
+  'pdfium_revision': '25d9272255438c45f6d91051a1092b54006eb797',
   # 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.
@@ -253,7 +253,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
-  'dawn_revision': '62e83971caa1099bdbc334817efa035047c90ddf',
+  'dawn_revision': '5987c4e8395aed194c987c051b56d35485180b46',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
@@ -643,7 +643,7 @@
     Var('chromium_git') + '/angle/angle.git' + '@' +  Var('angle_revision'),
 
   'src/third_party/dav1d/libdav1d':
-    Var('chromium_git') + '/external/github.com/videolan/dav1d.git' + '@' + 'f1b756ef5bdc0bb759b2b140f15362fec024c1ff',
+    Var('chromium_git') + '/external/github.com/videolan/dav1d.git' + '@' + '3cf4d32e74e38b99036c21b7d2d0fb2108223221',
 
   'src/third_party/dawn':
     Var('dawn_git') + '/dawn.git' + '@' +  Var('dawn_revision'),
@@ -732,7 +732,7 @@
 
   # Build tools for Chrome OS. Note: This depends on third_party/pyelftools.
   'src/third_party/chromite': {
-      'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + 'd416cb794c17c0a35c872ef4bfc03cf653af9cde',
+      'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '7073bb3d53887a693b1fec50a91a4a6bc1460298',
       'condition': 'checkout_linux',
   },
 
@@ -757,7 +757,7 @@
   },
 
   'src/third_party/depot_tools':
-    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + 'e893454f797fd9d52438c6a64fd6123073825b64',
+    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '70ce8736cbc2893abc8a5141b78a637ffaab2773',
 
   'src/third_party/devtools-node-modules':
     Var('chromium_git') + '/external/github.com/ChromeDevTools/devtools-node-modules' + '@' + Var('devtools_node_modules_revision'),
@@ -1296,7 +1296,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@c15741b70f84ee33de6a3f597dd13462bda11056',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@f06e184f930b7e69c94613ee2b1392d5edb0b297',
     'condition': 'checkout_src_internal',
   },
 
diff --git a/android_webview/browser/aw_content_browser_client.cc b/android_webview/browser/aw_content_browser_client.cc
index d9e368de..1d35d467 100644
--- a/android_webview/browser/aw_content_browser_client.cc
+++ b/android_webview/browser/aw_content_browser_client.cc
@@ -4,6 +4,7 @@
 
 #include "android_webview/browser/aw_content_browser_client.h"
 
+#include <memory>
 #include <string>
 #include <utility>
 #include <vector>
@@ -489,7 +490,8 @@
     content::StoragePartition* partition,
     storage::OptionalQuotaSettingsCallback callback) {
   storage::GetNominalDynamicSettings(
-      partition->GetPath(), context->IsOffTheRecord(), std::move(callback));
+      partition->GetPath(), context->IsOffTheRecord(),
+      storage::GetDefaultDiskInfoHelper(), std::move(callback));
 }
 
 content::GeneratedCodeCacheSettings
diff --git a/ash/shelf/app_list_button.cc b/ash/shelf/app_list_button.cc
index 6e7e8111..8f6c17e6 100644
--- a/ash/shelf/app_list_button.cc
+++ b/ash/shelf/app_list_button.cc
@@ -145,7 +145,7 @@
       // If assistant overlay animation starts, we need to make sure the event
       // is handled in order to end the animation in |ET_GESTURE_TAP| or
       // |ET_GESTURE_TAP_CANCEL|.
-      DCHECK(event->stopped_propagation());
+      DCHECK(event->handled());
       return;
     case ui::ET_GESTURE_LONG_PRESS:
       if (UseVoiceInteractionStyle()) {
diff --git a/ash/shelf/login_shelf_view.cc b/ash/shelf/login_shelf_view.cc
index de11a30..b8cbbfd 100644
--- a/ash/shelf/login_shelf_view.cc
+++ b/ash/shelf/login_shelf_view.cc
@@ -629,6 +629,16 @@
        dialog_state_ == mojom::OobeDialogState::GAIA_SIGNIN) &&
       kiosk_apps_button_->HasApps() && is_login_primary);
   Layout();
+  UpdateButtonUnionBounds();
+}
+
+void LoginShelfView::UpdateButtonUnionBounds() {
+  button_union_bounds_ = gfx::Rect();
+  View::Views children = GetChildrenInZOrder();
+  for (auto* child : children) {
+    if (child->visible())
+      button_union_bounds_.Union(child->bounds());
+  }
 }
 
 }  // namespace ash
diff --git a/ash/shelf/login_shelf_view.h b/ash/shelf/login_shelf_view.h
index 47658fd79..9daee64 100644
--- a/ash/shelf/login_shelf_view.h
+++ b/ash/shelf/login_shelf_view.h
@@ -102,6 +102,7 @@
   void ButtonPressed(views::Button* sender, const ui::Event& event) override;
 
   int ui_update_count() const { return ui_update_count_; }
+  gfx::Rect get_button_union_bounds() const { return button_union_bounds_; }
 
  protected:
   // TrayActionObserver:
@@ -128,6 +129,9 @@
   // policy updates, session state changes etc.
   void UpdateUi();
 
+  // Updates the total bounds of all buttons.
+  void UpdateButtonUnionBounds();
+
   mojom::OobeDialogState dialog_state_ = mojom::OobeDialogState::HIDDEN;
   bool allow_guest_ = true;
   bool allow_guest_in_oobe_ = false;
@@ -155,6 +159,11 @@
   // This is used in tests to wait until UI is updated.
   int ui_update_count_ = 0;
 
+  // The bounds of all the buttons that this view is showing. Useful for
+  // letting events that target the "empty space" pass through. These
+  // coordinates are local to the view.
+  gfx::Rect button_union_bounds_;
+
   DISALLOW_COPY_AND_ASSIGN(LoginShelfView);
 };
 
diff --git a/ash/shelf/shelf_widget.cc b/ash/shelf/shelf_widget.cc
index deded7c..895c5e8 100644
--- a/ash/shelf/shelf_widget.cc
+++ b/ash/shelf/shelf_widget.cc
@@ -282,6 +282,25 @@
   return opaque_background_.background_color();
 }
 
+bool ShelfWidget::GetHitTestRects(aura::Window* target,
+                                  gfx::Rect* hit_test_rect_mouse,
+                                  gfx::Rect* hit_test_rect_touch) {
+  // This should only get called when the login shelf is visible, i.e. not
+  // during an active session. In an active session, hit test rects should be
+  // calculated higher up in the class hierarchy by |EasyResizeWindowTargeter|.
+  // When in OOBE or locked/login screen, let events pass through empty parts
+  // of the shelf.
+  DCHECK(login_shelf_view_->visible());
+  gfx::Rect login_view_button_bounds =
+      login_shelf_view_->get_button_union_bounds();
+  aura::Window* source = login_shelf_view_->GetWidget()->GetNativeWindow();
+  aura::Window::ConvertRectToTarget(source, target->parent(),
+                                    &login_view_button_bounds);
+  *hit_test_rect_mouse = login_view_button_bounds;
+  *hit_test_rect_touch = login_view_button_bounds;
+  return true;
+}
+
 ShelfWidget::ShelfWidget(aura::Window* shelf_container, Shelf* shelf)
     : shelf_(shelf),
       background_animator_(SHELF_BACKGROUND_DEFAULT,
diff --git a/ash/shelf/shelf_widget.h b/ash/shelf/shelf_widget.h
index 1819182..6b89c32 100644
--- a/ash/shelf/shelf_widget.h
+++ b/ash/shelf/shelf_widget.h
@@ -117,6 +117,9 @@
   void OnSessionStateChanged(session_manager::SessionState state) override;
 
   SkColor GetShelfBackgroundColor() const;
+  bool GetHitTestRects(aura::Window* target,
+                       gfx::Rect* hit_test_rect_mouse,
+                       gfx::Rect* hit_test_rect_touch);
 
   // Internal implementation detail. Do not expose outside of tests.
   ShelfView* shelf_view_for_testing() const { return shelf_view_; }
diff --git a/ash/shelf/shelf_window_targeter.cc b/ash/shelf/shelf_window_targeter.cc
index e07938f..c0cdebb 100644
--- a/ash/shelf/shelf_window_targeter.cc
+++ b/ash/shelf/shelf_window_targeter.cc
@@ -4,9 +4,14 @@
 
 #include "ash/shelf/shelf_window_targeter.h"
 
+#include "ash/public/cpp/session_types.h"
 #include "ash/public/cpp/shelf_types.h"
+#include "ash/public/cpp/shell_window_ids.h"
+#include "ash/session/session_controller.h"
 #include "ash/shelf/shelf.h"
 #include "ash/shelf/shelf_constants.h"
+#include "ash/shelf/shelf_widget.h"
+#include "ash/shell.h"
 #include "ui/aura/window.h"
 
 namespace ash {
@@ -41,6 +46,26 @@
   return true;
 }
 
+bool ShelfWindowTargeter::GetHitTestRects(
+    aura::Window* target,
+    gfx::Rect* hit_test_rect_mouse,
+    gfx::Rect* hit_test_rect_touch) const {
+  // We only want to special case a very specific situation where we are not
+  // currently in an active session and change only the behavior of the login
+  // shelf.
+  if (target->id() == kShellWindowId_ShelfContainer &&
+      Shell::Get()->session_controller()->GetSessionState() !=
+          session_manager::SessionState::ACTIVE) {
+    // When this is the case, let events pass through the "empty" part of
+    // the shelf.
+    return shelf_->shelf_widget()->GetHitTestRects(target, hit_test_rect_mouse,
+                                                   hit_test_rect_touch);
+  }
+  // Otherwise, fall back to what our superclass does.
+  return EasyResizeWindowTargeter::GetHitTestRects(target, hit_test_rect_mouse,
+                                                   hit_test_rect_touch);
+}
+
 void ShelfWindowTargeter::OnWindowDestroying(aura::Window* window) {
   window->RemoveObserver(this);
   shelf_->RemoveObserver(this);
diff --git a/ash/shelf/shelf_window_targeter.h b/ash/shelf/shelf_window_targeter.h
index 70f1efc..b5fa37ee 100644
--- a/ash/shelf/shelf_window_targeter.h
+++ b/ash/shelf/shelf_window_targeter.h
@@ -27,6 +27,9 @@
  private:
   // ::wm::EasyResizeWindowTargeter:
   bool ShouldUseExtendedBounds(const aura::Window* window) const override;
+  bool GetHitTestRects(aura::Window* target,
+                       gfx::Rect* hit_test_rect_mouse,
+                       gfx::Rect* hit_test_rect_touch) const override;
 
   // aura::WindowObserver:
   void OnWindowDestroying(aura::Window* window) override;
diff --git a/ash/shell/content/client/shell_content_browser_client.cc b/ash/shell/content/client/shell_content_browser_client.cc
index 4d6e587..8119c3ab 100644
--- a/ash/shell/content/client/shell_content_browser_client.cc
+++ b/ash/shell/content/client/shell_content_browser_client.cc
@@ -4,6 +4,7 @@
 
 #include "ash/shell/content/client/shell_content_browser_client.h"
 
+#include <memory>
 #include <utility>
 
 #include "ash/ash_service.h"
@@ -85,7 +86,8 @@
     content::StoragePartition* partition,
     storage::OptionalQuotaSettingsCallback callback) {
   storage::GetNominalDynamicSettings(
-      partition->GetPath(), context->IsOffTheRecord(), std::move(callback));
+      partition->GetPath(), context->IsOffTheRecord(),
+      storage::GetDefaultDiskInfoHelper(), std::move(callback));
 }
 
 base::Optional<service_manager::Manifest>
diff --git a/ash/system/message_center/unified_message_center_view.cc b/ash/system/message_center/unified_message_center_view.cc
index 969db1a7..d1cd29bd 100644
--- a/ash/system/message_center/unified_message_center_view.cc
+++ b/ash/system/message_center/unified_message_center_view.cc
@@ -4,6 +4,8 @@
 
 #include "ash/system/message_center/unified_message_center_view.h"
 
+#include <algorithm>
+
 #include "ash/public/cpp/ash_features.h"
 #include "ash/session/session_controller.h"
 #include "ash/shell.h"
@@ -191,7 +193,7 @@
   }
 
   ScrollToTarget();
-  NotifyHeightBelowScroll();
+  NotifyRectBelowScroll();
 }
 
 gfx::Size UnifiedMessageCenterView::CalculatePreferredSize() const {
@@ -219,7 +221,7 @@
     scroll_bar_->ScrollByContentsOffset(previous_y - scroller_->y());
   }
 
-  NotifyHeightBelowScroll();
+  NotifyRectBelowScroll();
 }
 
 void UnifiedMessageCenterView::ButtonPressed(views::Button* sender,
@@ -237,9 +239,9 @@
   OnMessageCenterScrolled();
 }
 
-void UnifiedMessageCenterView::SetNotificationHeightBelowScroll(
-    int height_below_scroll) {
-  parent_->SetNotificationHeightBelowScroll(height_below_scroll);
+void UnifiedMessageCenterView::SetNotificationRectBelowScroll(
+    const gfx::Rect& rect_below_scroll) {
+  parent_->SetNotificationRectBelowScroll(rect_below_scroll);
 }
 
 void UnifiedMessageCenterView::UpdateVisibility() {
@@ -317,9 +319,19 @@
   return message_list_view_->CountNotificationsAboveY(y_offset);
 }
 
-void UnifiedMessageCenterView::NotifyHeightBelowScroll() {
-  SetNotificationHeightBelowScroll(std::max(
-      0, message_list_view_->height() - scroller_->GetVisibleRect().bottom()));
+void UnifiedMessageCenterView::NotifyRectBelowScroll() {
+  gfx::Rect rect_below_scroll;
+  rect_below_scroll.set_height(
+      std::max(0, message_list_view_->GetLastNotificationBounds().bottom() -
+                      scroller_->GetVisibleRect().bottom()));
+
+  gfx::Rect notification_bounds =
+      message_list_view_->GetNotificationBoundsBelowY(
+          scroller_->GetVisibleRect().bottom());
+  rect_below_scroll.set_x(notification_bounds.x());
+  rect_below_scroll.set_width(notification_bounds.width());
+
+  SetNotificationRectBelowScroll(rect_below_scroll);
 }
 
 }  // namespace ash
diff --git a/ash/system/message_center/unified_message_center_view.h b/ash/system/message_center/unified_message_center_view.h
index f9b7bee..313f2b40 100644
--- a/ash/system/message_center/unified_message_center_view.h
+++ b/ash/system/message_center/unified_message_center_view.h
@@ -80,7 +80,8 @@
 
  protected:
   // Virtual for testing.
-  virtual void SetNotificationHeightBelowScroll(int height_below_scroll);
+  virtual void SetNotificationRectBelowScroll(
+      const gfx::Rect& rect_below_scroll);
 
  private:
   friend class UnifiedMessageCenterViewTest;
@@ -90,9 +91,9 @@
   // Scroll the notification list to the target position.
   void ScrollToTarget();
 
-  // Notifies height below scroll to |parent_| so that it can update
+  // Notifies rect below scroll to |parent_| so that it can update
   // TopCornerBorder.
-  void NotifyHeightBelowScroll();
+  void NotifyRectBelowScroll();
 
   UnifiedSystemTrayView* const parent_;
   UnifiedSystemTrayModel* const model_;
diff --git a/ash/system/message_center/unified_message_center_view_unittest.cc b/ash/system/message_center/unified_message_center_view_unittest.cc
index 487ccf5..a164797 100644
--- a/ash/system/message_center/unified_message_center_view_unittest.cc
+++ b/ash/system/message_center/unified_message_center_view_unittest.cc
@@ -45,14 +45,15 @@
 
   ~TestUnifiedMessageCenterView() override = default;
 
-  void SetNotificationHeightBelowScroll(int height_below_scroll) override {
-    height_below_scroll_ = height_below_scroll;
+  void SetNotificationRectBelowScroll(
+      const gfx::Rect& rect_below_scroll) override {
+    rect_below_scroll_ = rect_below_scroll;
   }
 
-  int height_below_scroll() const { return height_below_scroll_; }
+  const gfx::Rect& rect_below_scroll() const { return rect_below_scroll_; }
 
  private:
-  int height_below_scroll_ = -1;
+  gfx::Rect rect_below_scroll_;
 
   DISALLOW_COPY_AND_ASSIGN(TestUnifiedMessageCenterView);
 };
@@ -422,7 +423,7 @@
   EXPECT_FALSE(GetStackingCounter()->visible());
 }
 
-TEST_F(UnifiedMessageCenterViewTest, HeightBelowScroll) {
+TEST_F(UnifiedMessageCenterViewTest, RectBelowScroll) {
   for (size_t i = 0; i < 6; ++i)
     AddNotification();
   CreateMessageCenterView();
@@ -433,15 +434,15 @@
             message_center_view()->bounds().height());
   message_center_view()->OnMessageCenterScrolled();
 
-  EXPECT_EQ(0, message_center_view()->height_below_scroll());
+  EXPECT_EQ(0, message_center_view()->rect_below_scroll().height());
 
   GetScroller()->ScrollToPosition(GetScrollBar(), 0);
   message_center_view()->OnMessageCenterScrolled();
-  EXPECT_LT(0, message_center_view()->height_below_scroll());
+  EXPECT_LT(0, message_center_view()->rect_below_scroll().height());
 }
 
 TEST_F(UnifiedMessageCenterViewTest,
-       HeightBelowScrollWithTargetingFirstNotification) {
+       RectBelowScrollWithTargetingFirstNotification) {
   std::vector<std::string> ids;
   for (size_t i = 0; i < 10; ++i)
     ids.push_back(AddNotification());
@@ -458,11 +459,10 @@
   EXPECT_EQ(0, GetScroller()->GetVisibleRect().y());
   EXPECT_EQ(
       GetMessageListView()->height() - GetScroller()->GetVisibleRect().height(),
-      message_center_view()->height_below_scroll());
+      message_center_view()->rect_below_scroll().height());
 }
 
-TEST_F(UnifiedMessageCenterViewTest,
-       HeightBelowScrollWithTargetingNotification) {
+TEST_F(UnifiedMessageCenterViewTest, RectBelowScrollWithTargetingNotification) {
   std::vector<std::string> ids;
   for (size_t i = 0; i < 10; ++i)
     ids.push_back(AddNotification());
@@ -477,11 +477,11 @@
   message_center_view()->OnMessageCenterScrolled();
 
   EXPECT_EQ(GetMessageListView()->GetLastNotificationBounds().height(),
-            message_center_view()->height_below_scroll());
+            message_center_view()->rect_below_scroll().height());
 }
 
 TEST_F(UnifiedMessageCenterViewTest,
-       HeightBelowScrollWithTargetingLastNotification) {
+       RectBelowScrollWithTargetingLastNotification) {
   std::vector<std::string> ids;
   for (size_t i = 0; i < 10; ++i)
     ids.push_back(AddNotification());
@@ -495,11 +495,11 @@
             message_center_view()->bounds().height());
   message_center_view()->OnMessageCenterScrolled();
 
-  EXPECT_EQ(0, message_center_view()->height_below_scroll());
+  EXPECT_EQ(0, message_center_view()->rect_below_scroll().height());
 }
 
 TEST_F(UnifiedMessageCenterViewTest,
-       HeightBelowScrollWithTargetingInvalidNotification) {
+       RectBelowScrollWithTargetingInvalidNotification) {
   std::vector<std::string> ids;
   for (size_t i = 0; i < 10; ++i)
     ids.push_back(AddNotification());
@@ -513,7 +513,7 @@
             message_center_view()->bounds().height());
   message_center_view()->OnMessageCenterScrolled();
 
-  EXPECT_EQ(0, message_center_view()->height_below_scroll());
+  EXPECT_EQ(0, message_center_view()->rect_below_scroll().height());
 }
 
 }  // namespace ash
diff --git a/ash/system/message_center/unified_message_list_view.cc b/ash/system/message_center/unified_message_list_view.cc
index 7e50c21a..fff29f8 100644
--- a/ash/system/message_center/unified_message_list_view.cc
+++ b/ash/system/message_center/unified_message_list_view.cc
@@ -258,6 +258,16 @@
   return GetContainer(child_count() - 1)->bounds();
 }
 
+gfx::Rect UnifiedMessageListView::GetNotificationBoundsBelowY(
+    int y_offset) const {
+  for (int i = 0; i < child_count(); ++i) {
+    auto* view = GetContainer(i);
+    if (view->bounds().bottom() >= y_offset)
+      return view->bounds();
+  }
+  return gfx::Rect();
+}
+
 gfx::Size UnifiedMessageListView::CalculatePreferredSize() const {
   return gfx::Size(kTrayMenuWidth,
                    gfx::Tween::IntValueBetween(GetCurrentValue(), start_height_,
diff --git a/ash/system/message_center/unified_message_list_view.h b/ash/system/message_center/unified_message_list_view.h
index 998b4a49..acd45f9 100644
--- a/ash/system/message_center/unified_message_list_view.h
+++ b/ash/system/message_center/unified_message_list_view.h
@@ -54,6 +54,10 @@
   // return an empty rect.
   gfx::Rect GetLastNotificationBounds() const;
 
+  // Return the bounds of the first notification whose bottom is below
+  // |y_offset|.
+  gfx::Rect GetNotificationBoundsBelowY(int y_offset) const;
+
   // Count the number of notifications whose bottom position is above
   // |y_offset|. O(n) where n is number of notifications.
   int CountNotificationsAboveY(int y_offset) const;
diff --git a/ash/system/unified/unified_system_tray_view.cc b/ash/system/unified/unified_system_tray_view.cc
index 88e57301..1a4b496 100644
--- a/ash/system/unified/unified_system_tray_view.cc
+++ b/ash/system/unified/unified_system_tray_view.cc
@@ -36,13 +36,16 @@
 // Border applied to SystemTrayContainer and DetailedViewContainer to iminate
 // notification list scrolling under SystemTray part of UnifiedSystemTray.
 // The border paints mock notification frame behind the top corners based on
-// |height_below_scroll|.
+// |rect_below_scroll|.
 class TopCornerBorder : public views::Border {
  public:
   TopCornerBorder() = default;
 
   // views::Border:
   void Paint(const views::View& view, gfx::Canvas* canvas) override {
+    if (rect_below_scroll_.IsEmpty())
+      return;
+
     gfx::ScopedCanvas scoped(canvas);
 
     SkPath path;
@@ -56,25 +59,21 @@
     flags.setStyle(cc::PaintFlags::kFill_Style);
     flags.setAntiAlias(true);
 
-    const int height = kUnifiedTrayCornerRadius * 4;
-    canvas->DrawRoundRect(
-        gfx::RectF(0,
-                   -height + std::min(height_below_scroll_,
-                                      kUnifiedTrayCornerRadius * 2),
-                   view.width(), height),
-        kUnifiedTrayCornerRadius, flags);
+    gfx::Rect rect = rect_below_scroll_;
+    rect.Inset(gfx::Insets(-kUnifiedTrayCornerRadius * 4, 0, 0, 0));
+    canvas->DrawRoundRect(gfx::RectF(rect), kUnifiedTrayCornerRadius, flags);
   }
 
   gfx::Insets GetInsets() const override { return gfx::Insets(); }
 
   gfx::Size GetMinimumSize() const override { return gfx::Size(); }
 
-  void set_height_below_scroll(int height_below_scroll) {
-    height_below_scroll_ = height_below_scroll;
+  void set_rect_below_scroll(const gfx::Rect& rect_below_scroll) {
+    rect_below_scroll_ = rect_below_scroll;
   }
 
  private:
-  int height_below_scroll_ = 0;
+  gfx::Rect rect_below_scroll_;
 
   DISALLOW_COPY_AND_ASSIGN(TopCornerBorder);
 };
@@ -357,12 +356,12 @@
          !message_center_view_->visible();
 }
 
-void UnifiedSystemTrayView::SetNotificationHeightBelowScroll(
-    int height_below_scroll) {
+void UnifiedSystemTrayView::SetNotificationRectBelowScroll(
+    const gfx::Rect& rect_below_scroll) {
   static_cast<TopCornerBorder*>(system_tray_container_->border())
-      ->set_height_below_scroll(height_below_scroll);
+      ->set_rect_below_scroll(rect_below_scroll);
   static_cast<TopCornerBorder*>(detailed_view_container_->border())
-      ->set_height_below_scroll(height_below_scroll);
+      ->set_rect_below_scroll(rect_below_scroll);
   SchedulePaint();
 }
 
diff --git a/ash/system/unified/unified_system_tray_view.h b/ash/system/unified/unified_system_tray_view.h
index 448056d..6e4640de 100644
--- a/ash/system/unified/unified_system_tray_view.h
+++ b/ash/system/unified/unified_system_tray_view.h
@@ -91,8 +91,10 @@
   bool IsTransformEnabled() const;
 
   // Update the top of the SystemTray part to imitate notification list
-  // scrolling under SystemTray. |height_below_scroll| should not be negative.
-  void SetNotificationHeightBelowScroll(int height_below_scroll);
+  // scrolling under SystemTray. |rect_below_scroll| is the region of
+  // notifications covered by SystemTray part, and its coordinate is relative to
+  // UnifiedSystemTrayView. It can be empty.
+  void SetNotificationRectBelowScroll(const gfx::Rect& rect_below_scroll);
 
   // Create background of UnifiedSystemTray that is semi-transparent and has
   // rounded corners.
diff --git a/ash/wm/pip/pip_positioner_unittest.cc b/ash/wm/pip/pip_positioner_unittest.cc
index 66a1779..2e1b0125 100644
--- a/ash/wm/pip/pip_positioner_unittest.cc
+++ b/ash/wm/pip/pip_positioner_unittest.cc
@@ -584,4 +584,25 @@
             CallAvoidObstacles(display, gfx::Rect(100, 100, 100, 100)));
 }
 
+TEST_F(PipPositionerTest, PipInitailPositionAvoidsObstacles) {
+  // Place a keyboard window at the initial position of a PIP window.
+  auto* keyboard_controller = keyboard::KeyboardController::Get();
+  keyboard_controller->ShowKeyboard(/*lock=*/true);
+  aura::Window* keyboard_window = keyboard_controller->GetKeyboardWindow();
+  keyboard_window->SetBounds(gfx::Rect(0, 0, 400, 100));
+  ASSERT_TRUE(keyboard::WaitUntilShown());
+
+  std::unique_ptr<aura::Window> window(
+      CreateTestWindowInShellWithBounds(gfx::Rect(100, 100, 100, 100)));
+  wm::WindowState* window_state = wm::GetWindowState(window.get());
+  const wm::WMEvent enter_pip(wm::WM_EVENT_PIP);
+  window_state->OnWMEvent(&enter_pip);
+  EXPECT_TRUE(window_state->IsPip());
+
+  window->Show();
+  EXPECT_TRUE(window->layer()->visible());
+  // Ensure the initial PIP position is shifted below the keyboard.
+  EXPECT_EQ("8,100 100x100", window->layer()->GetTargetBounds().ToString());
+}
+
 }  // namespace ash
diff --git a/ash/wm/window_animations_unittest.cc b/ash/wm/window_animations_unittest.cc
index 2fe476b..412ec96 100644
--- a/ash/wm/window_animations_unittest.cc
+++ b/ash/wm/window_animations_unittest.cc
@@ -326,7 +326,7 @@
       ui::ScopedAnimationDurationScaleMode::ZERO_DURATION);
 
   std::unique_ptr<aura::Window> window(CreateTestWindowInShellWithId(0));
-  window->SetBounds(gfx::Rect(0, 0, 100, 100));
+  window->SetBounds(gfx::Rect(8, 8, 100, 100));
 
   wm::WindowState* window_state = wm::GetWindowState(window.get());
   const wm::WMEvent enter_pip(wm::WM_EVENT_PIP);
@@ -335,23 +335,25 @@
 
   window->Show();
   EXPECT_TRUE(window->layer()->visible());
+  EXPECT_EQ("8,8 100x100", window->layer()->GetTargetBounds().ToString());
 
   window->Hide();
   EXPECT_EQ(0.0f, window->layer()->GetTargetOpacity());
   EXPECT_FALSE(window->layer()->GetTargetVisibility());
   EXPECT_FALSE(window->layer()->visible());
-  EXPECT_EQ("-150,0 100x100", window->layer()->GetTargetBounds().ToString());
+  EXPECT_EQ("-142,8 100x100", window->layer()->GetTargetBounds().ToString());
 
   // Reset the position and try again.
   window->Show();
-  window->SetBounds(gfx::Rect(0, 0, 100, 100));
+  window->SetBounds(gfx::Rect(8, 8, 100, 100));
   EXPECT_TRUE(window->layer()->visible());
+  EXPECT_EQ("8,8 100x100", window->layer()->GetTargetBounds().ToString());
 
   window->Hide();
   EXPECT_EQ(0.0f, window->layer()->GetTargetOpacity());
   EXPECT_FALSE(window->layer()->GetTargetVisibility());
   EXPECT_FALSE(window->layer()->visible());
-  EXPECT_EQ("-150,0 100x100", window->layer()->GetTargetBounds().ToString());
+  EXPECT_EQ("-142,8 100x100", window->layer()->GetTargetBounds().ToString());
 }
 
 }  // namespace ash
diff --git a/ash/wm/window_state.cc b/ash/wm/window_state.cc
index cae029b..50cd282 100644
--- a/ash/wm/window_state.cc
+++ b/ash/wm/window_state.cc
@@ -276,7 +276,8 @@
 }
 
 bool WindowState::HasRestoreBounds() const {
-  return window_->GetProperty(aura::client::kRestoreBoundsKey) != nullptr;
+  gfx::Rect* bounds = window_->GetProperty(aura::client::kRestoreBoundsKey);
+  return bounds != nullptr && !bounds->IsEmpty();
 }
 
 void WindowState::Maximize() {
@@ -694,6 +695,9 @@
     }
     ::wm::SetWindowVisibilityAnimationType(
         window(), WINDOW_VISIBILITY_ANIMATION_TYPE_FADE_IN_SLIDE_OUT);
+
+    // There may already be a system ui window on the initial position.
+    UpdatePipBounds();
   } else if (was_pip) {
     if (widget) {
       widget->widget_delegate()->SetCanActivate(true);
diff --git a/build/config/c++/BUILD.gn b/build/config/c++/BUILD.gn
new file mode 100644
index 0000000..f5ac10e
--- /dev/null
+++ b/build/config/c++/BUILD.gn
@@ -0,0 +1,115 @@
+import("//build/config/c++/c++.gni")
+import("//build/config/chrome_build.gni")
+import("//buildtools/deps_revisions.gni")
+
+assert(use_custom_libcxx, "should only be used if use_custom_libcxx is set")
+
+declare_args() {
+  # lldb pretty printing only works when libc++ is built in the __1 (or __ndk1)
+  # namespaces.  For pretty printing to work out-of-the-box on Mac (where lldb
+  # is primarily used), this flag is set to false to build with the __1
+  # namespace (to maintain ABI compatibility, this implies building without
+  # _LIBCPP_ABI_UNSTABLE).  This is not necessary on non-component builds
+  # because we leave the ABI version set to __1 in that case because libc++
+  # symbols are not exported.
+  # TODO(thomasanderson): Set this to true by default once rL352899 is available
+  # in MacOS's lldb.
+  libcxx_abi_unstable = !(is_mac && is_debug && is_component_build)
+}
+
+# TODO(xiaohuic): https://crbug/917533 Crashes on internal ChromeOS build.
+# Do unconditionally once the underlying problem is fixed.
+if (is_chromeos && is_chrome_branded) {
+  libcxx_abi_unstable = false
+}
+
+# This is included by reference in the //build/config/compiler:runtime_library
+# config that is applied to all targets. It is here to separate out the logic
+# that is specific to libc++. Please see that target for advice on what should
+# go in :runtime_library vs. :compiler.
+config("runtime_library") {
+  cflags = []
+  cflags_cc = []
+  defines = []
+  ldflags = []
+  libs = []
+
+  if (libcxx_abi_unstable) {
+    defines += [ "_LIBCPP_ABI_UNSTABLE" ]
+  }
+
+  if (is_component_build) {
+    # In component builds, symbols from libc++.so are exported for all DSOs to
+    # use.  If the system libc++ gets loaded (indirectly through a system
+    # library), then it will conflict with our libc++.so.  Add a custom ABI
+    # version if we're building with _LIBCPP_ABI_UNSTABLE to avoid conflicts.
+    #
+    # Windows doesn't need to set _LIBCPP_ABI_VERSION since there's no system
+    # C++ library we could conflict with.
+    if (libcxx_abi_unstable && !is_win) {
+      defines += [ "_LIBCPP_ABI_VERSION=Cr" ]
+    }
+  } else {
+    # Don't leak any symbols on a static build.
+    defines += [ "_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS" ]
+    if (!export_libcxxabi_from_executables) {
+      assert(!is_win, "don't use libcxxabi on win, see below")
+      defines += [ "_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS" ]
+    }
+  }
+
+  defines += [
+    "CR_LIBCXX_REVISION=$libcxx_svn_revision",
+    "CR_LIBCXXABI_REVISION=$libcxxabi_svn_revision",
+    "_LIBCPP_ENABLE_NODISCARD",
+  ]
+
+  if (is_win) {
+    # Intentionally not using libc++abi on Windows because libc++abi only
+    # implements the Itanium C++ ABI, and not the Microsoft ABI which we use on
+    # Windows (and we need to use in order to interoperate correctly with COM
+    # among other things).
+    cflags_cc +=
+        [ "-I" + rebase_path("$libcxx_prefix/include", root_build_dir) ]
+
+    # Prevent libc++ from embedding linker flags to try to automatically link
+    # against its runtime library. This is unnecessary with our build system,
+    # and can also result in build failures if libc++'s name for a library
+    # does not match ours.
+    defines += [ "_LIBCPP_NO_AUTO_LINK" ]
+  } else {
+    cflags_cc += [
+      "-nostdinc++",
+      "-isystem" + rebase_path("$libcxx_prefix/include", root_build_dir),
+      "-isystem" + rebase_path("$libcxxabi_prefix/include", root_build_dir),
+    ]
+
+    # Make sure we don't link against the system libstdc++ or libc++.
+    if (is_clang) {
+      # //build/config/android:runtime_library adds -nostdlib, which suppresses
+      # linking against all system libraries.  -nostdlib++ would be redundant,
+      # and would generate an unused warning in this case.
+      if (!is_android) {
+        ldflags += [ "-nostdlib++" ]
+      }
+    } else {
+      # Gcc has a built-in abs() definition with default visibility.
+      # If it was not disabled, it would conflict with libc++'s abs()
+      # with hidden visibility.
+      cflags += [ "-fno-builtin-abs" ]
+
+      ldflags += [ "-nodefaultlibs" ]
+
+      # Unfortunately, there's no way to disable linking against just libc++
+      # (gcc doesn't have -notstdlib++:
+      # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83931); -nodefaultlibs
+      # removes all of the default libraries, so add back the ones that we need.
+      libs += [
+        "c",
+        "gcc_s",
+        "m",
+        "rt",
+      ]
+    }
+  }
+}
diff --git a/build/config/c++/c++.gni b/build/config/c++/c++.gni
index d7003bb..61f07bc 100644
--- a/build/config/c++/c++.gni
+++ b/build/config/c++/c++.gni
@@ -31,7 +31,8 @@
 # libc++abi needs to be exported from executables to be picked up by shared
 # libraries on certian instrumented builds.
 export_libcxxabi_from_executables =
-    use_custom_libcxx && !is_component_build && (is_asan || is_ubsan_vptr)
+    use_custom_libcxx && !is_win && !is_component_build &&
+    (is_asan || is_ubsan_vptr)
 libcxx_is_shared = use_custom_libcxx && is_component_build
 
 # On Android, many shared libraries get loaded from the context of a JRE.  In
diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn
index b56c759..21a83dab 100644
--- a/build/config/compiler/BUILD.gn
+++ b/build/config/compiler/BUILD.gn
@@ -1203,16 +1203,18 @@
 # target wants the option regardless, put it in the compiler config.
 
 config("runtime_library") {
-  defines = []
   configs = []
 
-  # TODO(crbug.com/830987): Come up with a better name for is POSIX + Fuchsia
-  # configuration.
-  #
   # The order of this config is important: it must appear before
   # android:runtime_library.  This is to ensure libc++ appears before
   # libandroid_support in the -isystem include order.  Otherwise, there will be
   # build errors related to symbols declared in math.h.
+  if (use_custom_libcxx) {
+    configs += [ "//build/config/c++:runtime_library" ]
+  }
+
+  # TODO(crbug.com/830987): Come up with a better name for is POSIX + Fuchsia
+  # configuration.
   if (is_posix || is_fuchsia) {
     configs += [ "//build/config/posix:runtime_library" ]
   }
@@ -1233,7 +1235,7 @@
   }
 
   if (is_component_build) {
-    defines += [ "COMPONENT_BUILD" ]
+    defines = [ "COMPONENT_BUILD" ]
   }
 }
 
diff --git a/build/config/posix/BUILD.gn b/build/config/posix/BUILD.gn
index 6aa12bc..ee42d42 100644
--- a/build/config/posix/BUILD.gn
+++ b/build/config/posix/BUILD.gn
@@ -2,37 +2,11 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-import("//build/config/c++/c++.gni")
-import("//build/config/chrome_build.gni")
-import("//build/config/clang/clang.gni")
-import("//build/config/compiler/compiler.gni")
-import("//build/config/sanitizers/sanitizers.gni")
 import("//build/config/sysroot.gni")
-import("//build/toolchain/toolchain.gni")
-import("//buildtools/deps_revisions.gni")
 
 # This build configuration is used by both Fuchsia and POSIX systems.
 assert(is_posix || is_fuchsia)
 
-declare_args() {
-  # lldb pretty printing only works when libc++ is built in the __1 (or __ndk1)
-  # namespaces.  For pretty printing to work out-of-the-box on Mac (where lldb
-  # is primarily used), this flag is set to false to build with the __1
-  # namespace (to maintain ABI compatibility, this implies building without
-  # _LIBCPP_ABI_UNSTABLE).  This is not necessary on non-component builds
-  # because we leave the ABI version set to __1 in that case because libc++
-  # symbols are not exported.
-  # TODO(thomasanderson): Set this to true by default once rL352899 is available
-  # in MacOS's lldb.
-  libcxx_abi_unstable = !(is_mac && is_debug && is_component_build)
-}
-
-# TODO(xiaohuic): https://crbug/917533 Crashes on internal ChromeOS build.
-# Do unconditionally once the underlying problem is fixed.
-if (is_chromeos && is_chrome_branded) {
-  libcxx_abi_unstable = false
-}
-
 group("posix") {
   visibility = [ "//:optimize_gn_gen" ]
 }
@@ -50,68 +24,6 @@
   cflags_objcc = []
   defines = []
   ldflags = []
-  lib_dirs = []
-  libs = []
-
-  if (use_custom_libcxx) {
-    if (libcxx_abi_unstable) {
-      defines += [ "_LIBCPP_ABI_UNSTABLE" ]
-    }
-
-    if (is_component_build) {
-      # In component builds, symbols from libc++.so are exported for all DSOs to
-      # use.  If the system libc++ gets loaded (indirectly through a system
-      # library), then it will conflict with our libc++.so.  Add a custom ABI
-      # version if we're building with _LIBCPP_ABI_UNSTABLE to avoid conflicts.
-      if (libcxx_abi_unstable) {
-        defines += [ "_LIBCPP_ABI_VERSION=Cr" ]
-      }
-    } else {
-      # Don't leak any symbols on a static build.
-      defines += [ "_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS" ]
-      if (!export_libcxxabi_from_executables) {
-        defines += [ "_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS" ]
-      }
-    }
-    cflags_cc += [
-      "-nostdinc++",
-      "-isystem" + rebase_path("$libcxx_prefix/include", root_build_dir),
-      "-isystem" + rebase_path("$libcxxabi_prefix/include", root_build_dir),
-    ]
-    defines += [
-      "CR_LIBCXX_REVISION=$libcxx_svn_revision",
-      "CR_LIBCXXABI_REVISION=$libcxxabi_svn_revision",
-      "_LIBCPP_ENABLE_NODISCARD",
-    ]
-
-    # Make sure we don't link against libc++ or libstdc++.
-    if (is_clang) {
-      # //build/config/android:runtime_library adds -nostdlib, which suppresses
-      # linking against all system libraries.  -nostdlib++ would be redundant,
-      # and would generate an unused warning in this case.
-      if (!is_android) {
-        ldflags += [ "-nostdlib++" ]
-      }
-    } else {
-      # Gcc has a built-in abs() definition with default visibility.
-      # If it was not disabled, it would conflict with libc++'s abs()
-      # with hidden visibility.
-      cflags += [ "-fno-builtin-abs" ]
-
-      ldflags += [ "-nodefaultlibs" ]
-
-      # Unfortunately, there's no way to disable linking against just libc++
-      # (gcc doesn't have -notstdlib++:
-      # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83931); -nodefaultlibs
-      # removes all of the default libraries, so add back the ones that we need.
-      libs += [
-        "c",
-        "gcc_s",
-        "m",
-        "rt",
-      ]
-    }
-  }
 
   if (!is_mac && !is_ios && sysroot != "") {
     # Pass the sysroot to all C compiler variants, the assembler, and linker.
diff --git a/build/config/win/BUILD.gn b/build/config/win/BUILD.gn
index 05ce8a9..2f6fe55 100644
--- a/build/config/win/BUILD.gn
+++ b/build/config/win/BUILD.gn
@@ -2,7 +2,6 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-import("//build/config/c++/c++.gni")
 import("//build/config/chrome_build.gni")
 import("//build/config/clang/clang.gni")
 import("//build/config/compiler/compiler.gni")
@@ -11,7 +10,6 @@
 import("//build/timestamp.gni")
 import("//build/toolchain/goma.gni")
 import("//build/toolchain/toolchain.gni")
-import("//buildtools/deps_revisions.gni")
 
 assert(is_win)
 
@@ -258,32 +256,6 @@
     defines += [ "_USING_V110_SDK71_" ]
   }
 
-  # TODO(thomasanderson): Move this into a target in //build/config/c++ and
-  # deduplicate with //build/config/posix/BUILD.gn.
-  if (use_custom_libcxx) {
-    cflags_cc +=
-        [ "-I" + rebase_path("$libcxx_prefix/include", root_build_dir) ]
-    if (!is_component_build) {
-      # Don't leak any symbols on a static build.
-      defines += [ "_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS" ]
-    }
-
-    # Windows doesn't need to set _LIBCPP_ABI_VERSION since there's no system
-    # C++ library we could conflict with.
-    defines += [
-      "CR_LIBCXX_REVISION=$libcxx_svn_revision",
-      "CR_LIBCXXABI_REVISION=$libcxxabi_svn_revision",
-      "_LIBCPP_ABI_UNSTABLE",
-      "_LIBCPP_ENABLE_NODISCARD",
-
-      # Prevent libc++ from embedding linker flags to try to automatically link
-      # against its runtime library. This is unnecessary with our build system,
-      # and can also result in build failures if libc++'s name for a library
-      # does not match ours.
-      "_LIBCPP_NO_AUTO_LINK",
-    ]
-  }
-
   if (current_os == "winuwp") {
     # When targeting Windows Runtime, certain compiler/linker flags are
     # necessary.
diff --git a/cc/test/layer_tree_test.cc b/cc/test/layer_tree_test.cc
index a1bf3e68..c0ec353 100644
--- a/cc/test/layer_tree_test.cc
+++ b/cc/test/layer_tree_test.cc
@@ -435,6 +435,8 @@
 
   void DidBeginMainFrame() override { test_hooks_->DidBeginMainFrame(); }
 
+  void DidUpdateLayers() override {}
+
   void BeginMainFrame(const viz::BeginFrameArgs& args) override {
     test_hooks_->BeginMainFrame(args);
   }
diff --git a/cc/test/stub_layer_tree_host_client.h b/cc/test/stub_layer_tree_host_client.h
index 47c43574..af112eb 100644
--- a/cc/test/stub_layer_tree_host_client.h
+++ b/cc/test/stub_layer_tree_host_client.h
@@ -17,6 +17,7 @@
   // LayerTreeHostClient implementation.
   void WillBeginMainFrame() override {}
   void DidBeginMainFrame() override {}
+  void DidUpdateLayers() override {}
   void BeginMainFrame(const viz::BeginFrameArgs& args) override {}
   void RecordStartOfFrameMetrics() override {}
   void RecordEndOfFrameMetrics(base::TimeTicks) override {}
diff --git a/cc/trees/layer_tree_host.cc b/cc/trees/layer_tree_host.cc
index f30eb2f..9c5737e 100644
--- a/cc/trees/layer_tree_host.cc
+++ b/cc/trees/layer_tree_host.cc
@@ -681,6 +681,7 @@
   base::ElapsedTimer timer;
 
   bool result = DoUpdateLayers();
+  client_->DidUpdateLayers();
   micro_benchmark_controller_.DidUpdateLayers();
 
   if (const char* client_name = GetClientNameForMetrics()) {
@@ -751,6 +752,13 @@
   gpu_rasterization_histogram_recorded_ = true;
 }
 
+std::string LayerTreeHost::LayersAsString() const {
+  std::string layers;
+  for (const auto* layer : *this)
+    layers += layer->ToString() + "\n";
+  return layers;
+}
+
 bool LayerTreeHost::CaptureContent(std::vector<NodeHolder>* content) {
   if (viewport_visible_rect_.IsEmpty())
     return false;
@@ -833,21 +841,6 @@
   draw_property_utils::FindLayersThatNeedUpdates(this, &property_trees_,
                                                  &update_layer_list);
 
-  // Dump property trees and layers if run with:
-  //   --vmodule=layer_tree_host=3
-  // This only prints output in unit test or for the renderer.
-  if (VLOG_IS_ON(3) && (!GetClientNameForMetrics() ||
-                        GetClientNameForMetrics() == std::string("Renderer"))) {
-    std::ostringstream layers;
-    for (auto* layer : *this)
-      layers << layer->ToString() << "\n";
-    VLOG(3) << "After updating layers on the main thread:\n"
-            << "property trees:\n"
-            << property_trees_.ToString() << "\n"
-            << "cc::Layers:\n"
-            << layers.str();
-  }
-
   bool painted_content_has_slow_paths = false;
   bool painted_content_has_non_aa_paint = false;
   bool did_paint_content =
diff --git a/cc/trees/layer_tree_host.h b/cc/trees/layer_tree_host.h
index 868f7ea..51dcb19 100644
--- a/cc/trees/layer_tree_host.h
+++ b/cc/trees/layer_tree_host.h
@@ -677,6 +677,8 @@
   void SetRenderFrameObserver(
       std::unique_ptr<RenderFrameMetadataObserver> observer);
 
+  std::string LayersAsString() const;
+
   // Captures the on-screen text content, if success, fills the associated
   // NodeHolder in |content| and return true, otherwise return false.
   bool CaptureContent(std::vector<NodeHolder>* content);
diff --git a/cc/trees/layer_tree_host_client.h b/cc/trees/layer_tree_host_client.h
index 9ac8155a..5809469 100644
--- a/cc/trees/layer_tree_host_client.h
+++ b/cc/trees/layer_tree_host_client.h
@@ -81,6 +81,7 @@
   virtual void BeginMainFrameNotExpectedSoon() = 0;
   virtual void BeginMainFrameNotExpectedUntil(base::TimeTicks time) = 0;
   virtual void DidBeginMainFrame() = 0;
+  virtual void DidUpdateLayers() = 0;
 
   // Visual frame-based updates to the state of the LayerTreeHost are expected
   // to happen only in calls to LayerTreeHostClient::UpdateLayerTreeHost, which
diff --git a/chrome/VERSION b/chrome/VERSION
index 20d904a0..82604b4 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
 MAJOR=74
 MINOR=0
-BUILD=3703
+BUILD=3704
 PATCH=0
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/service/DownloadBackgroundTask.java b/chrome/android/java/src/org/chromium/chrome/browser/download/service/DownloadBackgroundTask.java
index 4ed160e..da6029f 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/service/DownloadBackgroundTask.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/service/DownloadBackgroundTask.java
@@ -8,6 +8,7 @@
 
 import org.chromium.base.Callback;
 import org.chromium.base.annotations.JNINamespace;
+import org.chromium.base.library_loader.LibraryProcessType;
 import org.chromium.chrome.browser.background_task_scheduler.NativeBackgroundTask;
 import org.chromium.chrome.browser.background_task_scheduler.NativeBackgroundTask.StartBeforeNativeResult;
 import org.chromium.chrome.browser.download.DownloadUtils;
@@ -15,6 +16,7 @@
 import org.chromium.components.background_task_scheduler.TaskParameters;
 import org.chromium.components.download.DownloadTaskType;
 import org.chromium.components.download.internal.BatteryStatusListenerAndroid;
+import org.chromium.content_public.browser.BrowserStartupController;
 
 import java.util.HashMap;
 import java.util.Map;
@@ -43,6 +45,9 @@
     @DownloadTaskType
     private int mCurrentTaskType;
 
+    // Whether only service manager is required to start.
+    private boolean mStartsServiceManagerOnly;
+
     @Override
     protected @StartBeforeNativeResult int onStartTaskBeforeNativeLoaded(
             Context context, TaskParameters taskParameters, TaskFinishedCallback callback) {
@@ -51,6 +56,11 @@
         int optimalBatteryPercentage = taskParameters.getExtras().getInt(
                 DownloadTaskScheduler.EXTRA_OPTIMAL_BATTERY_PERCENTAGE);
         mCurrentTaskType = taskParameters.getExtras().getInt(DownloadTaskScheduler.EXTRA_TASK_TYPE);
+        // Return value from DownloadUtils.shouldStartServiceManagerOnly() could change during
+        // native initialization, store it first.
+        mStartsServiceManagerOnly =
+                mCurrentTaskType == DownloadTaskType.DOWNLOAD_AUTO_RESUMPTION_TASK
+                && DownloadUtils.shouldStartServiceManagerOnly();
         // Reschedule if minimum battery level is not satisfied.
         if (!requiresCharging
                 && BatteryStatusListenerAndroid.getBatteryPercentage() < optimalBatteryPercentage) {
@@ -82,7 +92,10 @@
             }
         };
 
-        Profile profile = supportsServiceManagerOnly()
+        assert BrowserStartupController.get(LibraryProcessType.PROCESS_BROWSER)
+                        .isStartupSuccessfullyCompleted()
+                || mStartsServiceManagerOnly;
+        Profile profile = mStartsServiceManagerOnly
                 ? null
                 : Profile.getLastUsedProfile().getOriginalProfile();
         incrementPendingCallbackCount(mCurrentTaskType);
@@ -97,8 +110,7 @@
 
     @Override
     protected boolean supportsServiceManagerOnly() {
-        return mCurrentTaskType == DownloadTaskType.DOWNLOAD_AUTO_RESUMPTION_TASK
-                && DownloadUtils.shouldStartServiceManagerOnly();
+        return mStartsServiceManagerOnly;
     }
 
     private void incrementPendingCallbackCount(@DownloadTaskType int taskType) {
@@ -131,7 +143,7 @@
         int taskType = taskParameters.getExtras().getInt(DownloadTaskScheduler.EXTRA_TASK_TYPE);
         mPendingTaskCounters.remove(taskType);
 
-        Profile profile = supportsServiceManagerOnly()
+        Profile profile = mStartsServiceManagerOnly
                 ? null
                 : Profile.getLastUsedProfile().getOriginalProfile();
         boolean needsReschedule = nativeStopBackgroundTask(profile, taskType);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/Tab.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/Tab.java
index c92b991..2c0e7cb9 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tab/Tab.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/Tab.java
@@ -202,6 +202,13 @@
     private int mParentId = INVALID_TAB_ID;
 
     /**
+     * By default, this id inherits from the tab that caused it to be opened, or it equals to tab
+     * id. This is used to restore the relationship that defined by {@link TabModelFilter} between
+     * this tab and other tabs. This id can be re-set whenever is needed.
+     */
+    private int mRootId;
+
+    /**
      * If this tab was opened from another tab in another Activity, this is the Intent that can be
      * fired to bring the parent Activity back.
      * TODO(dfalcantara): Remove this mechanism when we have a global TabManager.
@@ -479,6 +486,13 @@
         if (frozenState != null) {
             assert type == TabLaunchType.FROM_RESTORE;
             restoreFieldsFromState(frozenState);
+        } else {
+            if (mParentId == INVALID_TAB_ID || getTabModelSelector() == null
+                    || getTabModelSelector().getTabById(mParentId) == null) {
+                mRootId = mId;
+            } else {
+                mRootId = getTabModelSelector().getTabById(mParentId).getRootId();
+            }
         }
 
         addObserver(mTabObserver);
@@ -534,6 +548,7 @@
                 && LocalizationUtils.getFirstStrongCharacterDirection(mTitle)
                         == LocalizationUtils.RIGHT_TO_LEFT;
         mLaunchTypeAtCreation = state.tabLaunchTypeAtCreation;
+        mRootId = state.rootId == Tab.INVALID_TAB_ID ? mId : state.rootId;
     }
 
     /**
@@ -771,6 +786,7 @@
         tabState.timestampMillis = mTimestampMillis;
         tabState.tabLaunchTypeAtCreation = mLaunchTypeAtCreation;
         tabState.themeColor = TabThemeColorHelper.getColor(this);
+        tabState.rootId = mRootId;
         return tabState;
     }
 
@@ -921,6 +937,21 @@
         return mId;
     }
 
+    /**
+     * This is used to change how this tab related to other tabs.
+     * @param rootId New relationship id to be set.
+     */
+    public void setRootId(int rootId) {
+        mRootId = rootId;
+    }
+
+    /**
+     * @return Tab's relationship id.
+     */
+    public int getRootId() {
+        return mRootId;
+    }
+
     public boolean isIncognito() {
         return mIncognito;
     }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabState.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabState.java
index 64b6c7cf..261f191 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabState.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabState.java
@@ -137,6 +137,7 @@
     /** Navigation history of the WebContents. */
     public WebContentsState contentsState;
     public int parentId = Tab.INVALID_TAB_ID;
+    public int rootId;
 
     public long timestampMillis = TIMESTAMP_NOT_SET;
     public String openerAppId;
@@ -326,6 +327,14 @@
                         "Failed to read tab launch type at creation from tab state. "
                                 + "Assuming tab launch type is null");
             }
+            try {
+                tabState.rootId = stream.readInt();
+            } catch (EOFException eof) {
+                tabState.rootId = Tab.INVALID_TAB_ID;
+                Log.w(TAG,
+                        "Failed to read tab root id from tab state. "
+                                + "Assuming root id is Tab.INVALID_TAB_ID");
+            }
             return tabState;
         } finally {
             stream.close();
@@ -392,6 +401,7 @@
             dataOutputStream.writeInt(state.themeColor);
             dataOutputStream.writeInt(
                     state.tabLaunchTypeAtCreation != null ? state.tabLaunchTypeAtCreation : -1);
+            dataOutputStream.writeInt(state.rootId);
         } catch (FileNotFoundException e) {
             Log.w(TAG, "FileNotFoundException while attempting to save TabState.");
         } catch (IOException e) {
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/tabstate/TabStateUnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/tabstate/TabStateUnitTest.java
index e8aab04..44a53cd 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/tabstate/TabStateUnitTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/tabstate/TabStateUnitTest.java
@@ -40,6 +40,7 @@
     private static final boolean SHOULD_PRESERVE = true;
     private static final String OPENER_APP_ID = "test";
     private static final @Nullable @TabLaunchType Integer LAUNCH_TYPE_AT_CREATION = null;
+    private static final int ROOT_ID = 1;
 
     @Rule
     public TemporaryFolder temporaryFolder = new TemporaryFolder();
@@ -69,6 +70,7 @@
             state.shouldPreserve = SHOULD_PRESERVE;
             state.openerAppId = OPENER_APP_ID;
             state.tabLaunchTypeAtCreation = LAUNCH_TYPE_AT_CREATION;
+            state.rootId = ROOT_ID;
         } finally {
             StreamUtil.closeQuietly(fileInputStream);
         }
@@ -83,6 +85,7 @@
         assertEquals(SHOULD_PRESERVE, state.shouldPreserve);
         assertEquals(THEME_COLOR, state.getThemeColor());
         assertEquals(LAUNCH_TYPE_AT_CREATION, state.tabLaunchTypeAtCreation);
+        assertEquals(ROOT_ID, state.rootId);
         assertEquals(CONTENTS_STATE_BYTES.length, state.contentsState.buffer().remaining());
 
         byte[] bytesFromFile = new byte[CONTENTS_STATE_BYTES.length];
diff --git a/chrome/app/profiles_strings.grdp b/chrome/app/profiles_strings.grdp
index 52f9327..30e6671 100644
--- a/chrome/app/profiles_strings.grdp
+++ b/chrome/app/profiles_strings.grdp
@@ -17,8 +17,11 @@
   <message name="IDS_GENERIC_USER_AVATAR_LABEL" desc="Label shown for the user that is currently active, when there are multiple user accounts.">
     Current user
   </message>
-  <message name="IDS_AVATAR_BUTTON_INCOGNITO" desc="Short label for the avatar button when the user is in incognito mode." meaning="This window is browsing in incognito mode.">
-    Incognito
+  <message name="IDS_AVATAR_BUTTON_INCOGNITO" desc="Short label for the avatar button when the user is in incognito mode and the number of open incognito windows if there are more than one incognito window open. [ICU Syntax]" meaning="This window is browsing in incognito mode and there are more than one incognito windows open. The counter is not shown when there is only one incognito window open.">
+    {0, plural,
+      =1 {Incognito}
+      other {Incognito (#)}
+    }
   </message>
   <message name="IDS_AVATAR_BUTTON_INCOGNITO_TOOLTIP" desc="Tooltip for the inactive avatar button when the user is in incognito mode.">
     You're incognito
diff --git a/chrome/browser/apps/user_type_filter.cc b/chrome/browser/apps/user_type_filter.cc
index fdc9c6b..cba8cdf 100644
--- a/chrome/browser/apps/user_type_filter.cc
+++ b/chrome/browser/apps/user_type_filter.cc
@@ -8,12 +8,22 @@
 #include "chrome/browser/policy/profile_policy_connector.h"
 #include "chrome/browser/policy/profile_policy_connector_factory.h"
 #include "chrome/browser/profiles/profile.h"
+#include "content/public/browser/browser_thread.h"
 
 namespace apps {
 
-namespace {
+// kUserType is required key that specifies enumeration of user types for which
+// web app is visible. See kUserType* constants
+const char kKeyUserType[] = "user_type";
+
+const char kUserTypeChild[] = "child";
+const char kUserTypeGuest[] = "guest";
+const char kUserTypeManaged[] = "managed";
+const char kUserTypeSupervised[] = "supervised";
+const char kUserTypeUnmanaged[] = "unmanaged";
 
 std::string DetermineUserType(Profile* profile) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   DCHECK(!profile->IsOffTheRecord());
   if (profile->IsGuestSession())
     return kUserTypeGuest;
@@ -28,23 +38,10 @@
   return kUserTypeUnmanaged;
 }
 
-}  // namespace
-
-// kUserType is required key that specifies enumeration of user types for which
-// web app is visible. See kUserType* constants
-const char kKeyUserType[] = "user_type";
-
-const char kUserTypeChild[] = "child";
-const char kUserTypeGuest[] = "guest";
-const char kUserTypeManaged[] = "managed";
-const char kUserTypeSupervised[] = "supervised";
-const char kUserTypeUnmanaged[] = "unmanaged";
-
-bool ProfileMatchJsonUserType(Profile* profile,
-                              const std::string& app_id,
-                              const base::Value* json_root,
-                              const base::ListValue* default_user_types) {
-  DCHECK(profile);
+bool UserTypeMatchesJsonUserType(const std::string& user_type,
+                                 const std::string& app_id,
+                                 const base::Value* json_root,
+                                 const base::ListValue* default_user_types) {
   DCHECK(json_root);
 
   if (!json_root->is_dict()) {
@@ -66,7 +63,6 @@
   }
 
   bool user_type_match = false;
-  const std::string user_type = DetermineUserType(profile);
   for (const auto& it : value->GetList()) {
     if (!it.is_string()) {
       LOG(ERROR) << "Invalid user type value for " << app_id << ".";
diff --git a/chrome/browser/apps/user_type_filter.h b/chrome/browser/apps/user_type_filter.h
index abcc95d..3e8afde 100644
--- a/chrome/browser/apps/user_type_filter.h
+++ b/chrome/browser/apps/user_type_filter.h
@@ -24,18 +24,26 @@
 extern const char kUserTypeSupervised[];
 extern const char kUserTypeUnmanaged[];
 
-// This filter is used to verify that testing profile |profile| matches user
-// type filter defined in root Json element |json_root|. |json_root| should have
-// the list of acceptable user types. Following values are valid: child, guest,
-// managed, supervised, unmanaged. Primary use of this filter is to determine if
-// particular default webapp or extension has to be installed for current user.
+// Returns user type based on |profile|. Must be called on UI thread. List of
+// possible values are |kUserTypeChild|, |kUserTypeGuest|, |kUserTypeManaged|,
+// |kUserTypeSupervised| and |kUserTypeUnmanaged|.
+std::string DetermineUserType(Profile* profile);
+
+// This filter is used to verify that profile's user type |user_type| matches
+// the user type filter defined in root Json element |json_root|. |json_root|
+// should have the list of acceptable user types. Following values are valid:
+// |kUserTypeChild|, |kUserTypeGuest|, |kUserTypeManaged|, |kUserTypeSupervised|
+// and |kUserTypeUnmanaged|. Primary use of this filter is to determine if
+// particular default webapp or extension has to be installed for the current
+// user.
 // Returns true if profile is accepted for this filter. |default_user_types| is
 // optional and used to support transition for the extension based default apps.
 // |app_id| is used for error logging purpose.
-bool ProfileMatchJsonUserType(Profile* profile,
-                              const std::string& app_id,
-                              const base::Value* json_root,
-                              const base::ListValue* default_user_types);
+// Safe to call on non-UI thread.
+bool UserTypeMatchesJsonUserType(const std::string& user_type,
+                                 const std::string& app_id,
+                                 const base::Value* json_root,
+                                 const base::ListValue* default_user_types);
 
 }  // namespace apps
 
diff --git a/chrome/browser/apps/user_type_filter_unittest.cc b/chrome/browser/apps/user_type_filter_unittest.cc
index 13f5429..f4a5cd0 100644
--- a/chrome/browser/apps/user_type_filter_unittest.cc
+++ b/chrome/browser/apps/user_type_filter_unittest.cc
@@ -55,16 +55,17 @@
 
   bool Match(const std::unique_ptr<TestingProfile>& profile,
              const std::unique_ptr<base::Value>& json_root) {
-    return ProfileMatchJsonUserType(profile.get(), std::string() /* app_id */,
-                                    json_root.get(),
-                                    nullptr /* default_user_types */);
+    return UserTypeMatchesJsonUserType(
+        DetermineUserType(profile.get()), std::string() /* app_id */,
+        json_root.get(), nullptr /* default_user_types */);
   }
 
   bool MatchDefault(const std::unique_ptr<TestingProfile>& profile,
                     const base::ListValue& default_user_types) {
     base::DictionaryValue json_root;
-    return ProfileMatchJsonUserType(profile.get(), std::string() /* app_id */,
-                                    &json_root, &default_user_types);
+    return UserTypeMatchesJsonUserType(DetermineUserType(profile.get()),
+                                       std::string() /* app_id */, &json_root,
+                                       &default_user_types);
   }
 
  private:
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc
index d60fc85..8688e70 100644
--- a/chrome/browser/chrome_content_browser_client.cc
+++ b/chrome/browser/chrome_content_browser_client.cc
@@ -2642,7 +2642,8 @@
     return;
   }
   storage::GetNominalDynamicSettings(
-      partition->GetPath(), context->IsOffTheRecord(), std::move(callback));
+      partition->GetPath(), context->IsOffTheRecord(),
+      storage::GetDefaultDiskInfoHelper(), std::move(callback));
 }
 
 content::GeneratedCodeCacheSettings
@@ -5357,8 +5358,15 @@
       offline_pages::OfflinePageTabHelper::FromWebContents(
           navigation_handle->GetWebContents());
 
-  previews_user_data->set_offline_preview_used(
-      tab_helper && tab_helper->GetOfflinePreviewItem());
+  bool is_offline_page = tab_helper && tab_helper->IsLoadingOfflinePage();
+  bool is_offline_preview = tab_helper && tab_helper->GetOfflinePreviewItem();
+
+  // If this is an offline page, but not a preview, then we should not attempt
+  // any previews or surface the previews UI.
+  if (is_offline_page && !is_offline_preview)
+    return content::PREVIEWS_OFF;
+
+  previews_user_data->set_offline_preview_used(is_offline_preview);
 #endif  // BUILDFLAG(ENABLE_OFFLINE_PAGES)
 
   // Annotate request if no-transform directive found in response headers.
diff --git a/chrome/browser/chromeos/arc/auth/arc_auth_service.cc b/chrome/browser/chromeos/arc/auth/arc_auth_service.cc
index 92965882..ee8bc92 100644
--- a/chrome/browser/chromeos/arc/auth/arc_auth_service.cc
+++ b/chrome/browser/chromeos/arc/auth/arc_auth_service.cc
@@ -524,7 +524,8 @@
   // notifications. See crbug.com/904978.
 }
 
-void ArcAuthService::OnAccountRemovedWithInfo(const AccountInfo& account_info) {
+void ArcAuthService::OnExtendedAccountInfoRemoved(
+    const AccountInfo& account_info) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
   if (!chromeos::switches::IsAccountManagerEnabled())
diff --git a/chrome/browser/chromeos/arc/auth/arc_auth_service.h b/chrome/browser/chromeos/arc/auth/arc_auth_service.h
index c264f52..92f6599 100644
--- a/chrome/browser/chromeos/arc/auth/arc_auth_service.h
+++ b/chrome/browser/chromeos/arc/auth/arc_auth_service.h
@@ -102,7 +102,7 @@
       const chromeos::AccountManager::AccountKey& account_key) override;
 
   // IdentityManager::Observer:
-  void OnAccountRemovedWithInfo(const AccountInfo& account_info) override;
+  void OnExtendedAccountInfoRemoved(const AccountInfo& account_info) override;
 
   // ArcSessionManager::Observer:
   void OnArcInitialStart() override;
diff --git a/chrome/browser/chromeos/arc/auth/arc_auth_service_browsertest.cc b/chrome/browser/chromeos/arc/auth/arc_auth_service_browsertest.cc
index c9b7560..df078ee1 100644
--- a/chrome/browser/chromeos/arc/auth/arc_auth_service_browsertest.cc
+++ b/chrome/browser/chromeos/arc/auth/arc_auth_service_browsertest.cc
@@ -635,8 +635,8 @@
 
   AccountFetcherService* account_fetcher_service =
       AccountFetcherServiceFactory::GetForProfile(profile());
-  // Necessary to ensure that the OnAccountRemovedWithInfo() observer will be
-  // sent.
+  // Necessary to ensure that the OnExtendedAccountInfoRemoved() observer will
+  // be sent.
   account_fetcher_service->EnableNetworkFetchesForTest();
   identity_manager->GetAccountsMutator()->RemoveAccount(
       maybe_account_info.value().account_id,
diff --git a/chrome/browser/chromeos/crostini/crostini_manager.cc b/chrome/browser/chromeos/crostini/crostini_manager.cc
index 1d52617..b3aa550 100644
--- a/chrome/browser/chromeos/crostini/crostini_manager.cc
+++ b/chrome/browser/chromeos/crostini/crostini_manager.cc
@@ -2142,6 +2142,9 @@
   create_lxd_container_callbacks_.erase(range.first, range.second);
 }
 
+void CrostiniManager::OnLxdContainerDeleted(
+    const vm_tools::cicerone::LxdContainerDeletedSignal& signal) {}
+
 void CrostiniManager::OnLxdContainerDownloading(
     const vm_tools::cicerone::LxdContainerDownloadingSignal& signal) {
   if (owner_id_ != signal.owner_id()) {
diff --git a/chrome/browser/chromeos/crostini/crostini_manager.h b/chrome/browser/chromeos/crostini/crostini_manager.h
index 282e232..aad3531 100644
--- a/chrome/browser/chromeos/crostini/crostini_manager.h
+++ b/chrome/browser/chromeos/crostini/crostini_manager.h
@@ -544,6 +544,8 @@
       override;
   void OnLxdContainerCreated(
       const vm_tools::cicerone::LxdContainerCreatedSignal& signal) override;
+  void OnLxdContainerDeleted(
+      const vm_tools::cicerone::LxdContainerDeletedSignal& signal) override;
   void OnLxdContainerDownloading(
       const vm_tools::cicerone::LxdContainerDownloadingSignal& signal) override;
   void OnTremplinStarted(
diff --git a/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc b/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc
index 665e83e..f56ec2690 100644
--- a/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc
+++ b/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc
@@ -510,7 +510,6 @@
                       TestCase("openQuickViewAndroid"),
                       TestCase("openQuickViewCrostini"),
                       TestCase("openQuickViewUsb"),
-                      TestCase("openQuickViewRemovablePartitions"),
                       TestCase("openQuickViewMtp"),
                       TestCase("pressEnterOnInfoBoxToOpenClose"),
                       TestCase("closeQuickView"),
diff --git a/chrome/browser/extensions/BUILD.gn b/chrome/browser/extensions/BUILD.gn
index 27d64b1c..5a4aeff6 100644
--- a/chrome/browser/extensions/BUILD.gn
+++ b/chrome/browser/extensions/BUILD.gn
@@ -960,6 +960,7 @@
     }
     deps += [
       "//ash/public/cpp",
+      "//chrome/browser/resources/chromeos/camera:chrome_camera_app",
       "//chromeos/attestation",
       "//chromeos/components/proximity_auth",
       "//chromeos/cryptohome",
diff --git a/chrome/browser/extensions/api/identity/identity_api.cc b/chrome/browser/extensions/api/identity/identity_api.cc
index ce217762..49dbcec 100644
--- a/chrome/browser/extensions/api/identity/identity_api.cc
+++ b/chrome/browser/extensions/api/identity/identity_api.cc
@@ -175,7 +175,8 @@
   FireOnAccountSignInChanged(account_info.gaia, true);
 }
 
-void IdentityAPI::OnAccountRemovedWithInfo(const AccountInfo& account_info) {
+void IdentityAPI::OnExtendedAccountInfoRemoved(
+    const AccountInfo& account_info) {
   DCHECK(!account_info.gaia.empty());
   FireOnAccountSignInChanged(account_info.gaia, false);
 }
diff --git a/chrome/browser/extensions/api/identity/identity_api.h b/chrome/browser/extensions/api/identity/identity_api.h
index 6f7f860..057a33f3 100644
--- a/chrome/browser/extensions/api/identity/identity_api.h
+++ b/chrome/browser/extensions/api/identity/identity_api.h
@@ -134,7 +134,7 @@
   // NOTE: This class must listen for this callback rather than
   // OnRefreshTokenRemovedForAccount() to obtain the Gaia ID of the removed
   // account.
-  void OnAccountRemovedWithInfo(const AccountInfo& info) override;
+  void OnExtendedAccountInfoRemoved(const AccountInfo& info) override;
 
   // Fires the chrome.identity.onSignInChanged event.
   void FireOnAccountSignInChanged(const std::string& gaia_id,
diff --git a/chrome/browser/extensions/api/preference/preference_helpers.h b/chrome/browser/extensions/api/preference/preference_helpers.h
index 02d77ec..1b884290 100644
--- a/chrome/browser/extensions/api/preference/preference_helpers.h
+++ b/chrome/browser/extensions/api/preference/preference_helpers.h
@@ -15,7 +15,7 @@
 
 namespace base {
 class ListValue;
-};
+}
 
 namespace extensions {
 namespace preference_helpers {
diff --git a/chrome/browser/extensions/api/tabs/tabs_constants.h b/chrome/browser/extensions/api/tabs/tabs_constants.h
index a90dadb..286da52 100644
--- a/chrome/browser/extensions/api/tabs/tabs_constants.h
+++ b/chrome/browser/extensions/api/tabs/tabs_constants.h
@@ -107,7 +107,7 @@
 extern const char kMissingLockWindowFullscreenPrivatePermission[];
 extern const char kJavaScriptUrlsNotAllowedInTabsUpdate[];
 
-};  // namespace tabs_constants
-};  // namespace extensions
+}  // namespace tabs_constants
+}  // namespace extensions
 
 #endif  // CHROME_BROWSER_EXTENSIONS_API_TABS_TABS_CONSTANTS_H_
diff --git a/chrome/browser/extensions/bookmark_app_helper.cc b/chrome/browser/extensions/bookmark_app_helper.cc
index 339a4c949..03bccc3 100644
--- a/chrome/browser/extensions/bookmark_app_helper.cc
+++ b/chrome/browser/extensions/bookmark_app_helper.cc
@@ -58,7 +58,6 @@
 #include "extensions/browser/notification_types.h"
 #include "extensions/browser/pref_names.h"
 #include "extensions/common/extension.h"
-#include "extensions/common/url_pattern.h"
 #include "net/base/load_flags.h"
 #include "net/url_request/url_request.h"
 #include "third_party/blink/public/common/manifest/manifest.h"
@@ -580,10 +579,4 @@
   installer->Run();
 }
 
-bool IsValidBookmarkAppUrl(const GURL& url) {
-  URLPattern origin_only_pattern(Extension::kValidBookmarkAppSchemes);
-  origin_only_pattern.SetMatchAllURLs(true);
-  return url.is_valid() && origin_only_pattern.MatchesURL(url);
-}
-
 }  // namespace extensions
diff --git a/chrome/browser/extensions/bookmark_app_helper.h b/chrome/browser/extensions/bookmark_app_helper.h
index abf2d3497..3ad37a61 100644
--- a/chrome/browser/extensions/bookmark_app_helper.h
+++ b/chrome/browser/extensions/bookmark_app_helper.h
@@ -214,9 +214,6 @@
                                WebApplicationInfo* web_app_info,
                                bool is_locally_installed);
 
-// Returns whether the given |url| is a valid user bookmark app url.
-bool IsValidBookmarkAppUrl(const GURL& url);
-
 }  // namespace extensions
 
 #endif  // CHROME_BROWSER_EXTENSIONS_BOOKMARK_APP_HELPER_H_
diff --git a/chrome/browser/extensions/bookmark_app_helper_unittest.cc b/chrome/browser/extensions/bookmark_app_helper_unittest.cc
index 160419b..b8e37b51 100644
--- a/chrome/browser/extensions/bookmark_app_helper_unittest.cc
+++ b/chrome/browser/extensions/bookmark_app_helper_unittest.cc
@@ -628,24 +628,4 @@
   }
 }
 
-TEST_F(BookmarkAppHelperTest, IsValidBookmarkAppUrl) {
-  EXPECT_TRUE(IsValidBookmarkAppUrl(GURL("https://chromium.org")));
-  EXPECT_TRUE(IsValidBookmarkAppUrl(GURL("https://www.chromium.org")));
-  EXPECT_TRUE(IsValidBookmarkAppUrl(
-      GURL("https://www.chromium.org/path/to/page.html")));
-  EXPECT_TRUE(IsValidBookmarkAppUrl(GURL("http://chromium.org")));
-  EXPECT_TRUE(IsValidBookmarkAppUrl(GURL("http://www.chromium.org")));
-  EXPECT_TRUE(
-      IsValidBookmarkAppUrl(GURL("http://www.chromium.org/path/to/page.html")));
-  EXPECT_TRUE(IsValidBookmarkAppUrl(
-      GURL("chrome-extension://oafaagfgbdpldilgjjfjocjglfbolmac")));
-
-  EXPECT_FALSE(IsValidBookmarkAppUrl(GURL("ftp://www.chromium.org")));
-  EXPECT_FALSE(IsValidBookmarkAppUrl(GURL("chrome://flags")));
-  EXPECT_FALSE(IsValidBookmarkAppUrl(GURL("about:blank")));
-  EXPECT_FALSE(IsValidBookmarkAppUrl(
-      GURL("file://mhjfbmdgcfjbbpaeojofohoefgiehjai")));
-  EXPECT_FALSE(IsValidBookmarkAppUrl(GURL("chrome://extensions")));
-}
-
 }  // namespace extensions
diff --git a/chrome/browser/extensions/component_extensions_whitelist/whitelist.cc b/chrome/browser/extensions/component_extensions_whitelist/whitelist.cc
index 274405b..46aa36bb 100644
--- a/chrome/browser/extensions/component_extensions_whitelist/whitelist.cc
+++ b/chrome/browser/extensions/component_extensions_whitelist/whitelist.cc
@@ -36,6 +36,7 @@
     extension_misc::kSelectToSpeakExtensionId,
     extension_misc::kSwitchAccessExtensionId,
     extension_misc::kZipArchiverExtensionId,
+    extension_misc::kChromeCameraAppId,
 #endif
   };
 
diff --git a/chrome/browser/extensions/component_loader.cc b/chrome/browser/extensions/component_loader.cc
index 29b9f2c..a065710 100644
--- a/chrome/browser/extensions/component_loader.cc
+++ b/chrome/browser/extensions/component_loader.cc
@@ -20,6 +20,7 @@
 #include "chrome/browser/extensions/component_extensions_whitelist/whitelist.h"
 #include "chrome/browser/extensions/data_deleter.h"
 #include "chrome/browser/extensions/extension_service.h"
+#include "chrome/browser/extensions/launch_util.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/common/buildflags.h"
 #include "chrome/common/channel_info.h"
@@ -294,6 +295,17 @@
   return false;
 }
 
+void ComponentLoader::AddChromeCameraApp() {
+#if defined(OS_CHROMEOS)
+  base::FilePath resources_path;
+  if (base::PathService::Get(chrome::DIR_RESOURCES, &resources_path)) {
+    AddComponentFromDir(
+        resources_path.Append(extension_misc::kChromeCameraAppPath),
+        extension_misc::kChromeCameraAppId, base::RepeatingClosure());
+  }
+#endif  // defined(OS_CHROMEOS)
+}
+
 void ComponentLoader::AddFileManagerExtension() {
 #if defined(OS_CHROMEOS)
   AddWithNameAndDescription(
@@ -535,6 +547,7 @@
 #endif
 
   if (!skip_session_components) {
+    AddChromeCameraApp();
     AddVideoPlayerExtension();
     AddAudioPlayerExtension();
     AddFileManagerExtension();
diff --git a/chrome/browser/extensions/component_loader.h b/chrome/browser/extensions/component_loader.h
index 8a78a56..287069b 100644
--- a/chrome/browser/extensions/component_loader.h
+++ b/chrome/browser/extensions/component_loader.h
@@ -177,6 +177,7 @@
   void AddChromeApp();
   void AddKeyboardApp();
   void AddWebStoreApp();
+  void AddChromeCameraApp();
 
   scoped_refptr<const Extension> CreateExtension(
       const ComponentExtensionInfo& info, std::string* utf8_error);
diff --git a/chrome/browser/extensions/external_pref_loader.cc b/chrome/browser/extensions/external_pref_loader.cc
index e6f76fb..516720f0 100644
--- a/chrome/browser/extensions/external_pref_loader.cc
+++ b/chrome/browser/extensions/external_pref_loader.cc
@@ -170,7 +170,10 @@
 ExternalPrefLoader::ExternalPrefLoader(int base_path_id,
                                        int options,
                                        Profile* profile)
-    : base_path_id_(base_path_id), options_(options), profile_(profile) {
+    : base_path_id_(base_path_id),
+      options_(options),
+      profile_(profile),
+      user_type_(profile ? apps::DetermineUserType(profile) : std::string()) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
 }
 
@@ -349,9 +352,9 @@
       continue;
 
     if (options_ & USE_USER_TYPE_PROFILE_FILTER &&
-        !apps::ProfileMatchJsonUserType(profile_, id /* app_id */,
-                                        ext_prefs.get(),
-                                        default_user_types.get())) {
+        !apps::UserTypeMatchesJsonUserType(user_type_, id /* app_id */,
+                                           ext_prefs.get(),
+                                           default_user_types.get())) {
       // Already logged.
       continue;
     }
diff --git a/chrome/browser/extensions/external_pref_loader.h b/chrome/browser/extensions/external_pref_loader.h
index a13c0da..b06e9c9 100644
--- a/chrome/browser/extensions/external_pref_loader.h
+++ b/chrome/browser/extensions/external_pref_loader.h
@@ -112,6 +112,10 @@
   // Needed for waiting for waiting priority sync.
   Profile* profile_;
 
+  // User type determined by |profile_|. Used to filter extensions. In some unit
+  // tests may not be set.
+  const std::string user_type_;
+
   std::vector<std::unique_ptr<PrioritySyncReadyWaiter>> pending_waiter_list_;
 
   DISALLOW_COPY_AND_ASSIGN(ExternalPrefLoader);
diff --git a/chrome/browser/extensions/tab_helper.cc b/chrome/browser/extensions/tab_helper.cc
index 80963bfb..744e081 100644
--- a/chrome/browser/extensions/tab_helper.cc
+++ b/chrome/browser/extensions/tab_helper.cc
@@ -29,6 +29,7 @@
 #include "chrome/browser/ui/browser_dialogs.h"
 #include "chrome/browser/ui/browser_finder.h"
 #include "chrome/browser/web_applications/components/web_app_helpers.h"
+#include "chrome/browser/web_applications/extensions/bookmark_app_util.h"
 #include "chrome/common/extensions/extension_constants.h"
 #include "chrome/common/extensions/manifest_handlers/app_launch_info.h"
 #include "chrome/common/render_messages.h"
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json
index ec30bc8e..036d7c97 100644
--- a/chrome/browser/flag-metadata.json
+++ b/chrome/browser/flag-metadata.json
@@ -515,13 +515,17 @@
   },
   {
     "name": "disable-accelerated-mjpeg-decode",
-    // "owners": [ "your-team" ],
-    "expiry_milestone": 76
+    "owners": [ "chromeos-camera-eng@google.com" ],
+    // This flag does not expire because it allows users to disable HW mjpeg
+    // decoding for debugging purpose and temporary workaround for some issues.
+    "expiry_milestone": -1
   },
   {
     "name": "disable-accelerated-video-decode",
-    // "owners": [ "your-team" ],
-    "expiry_milestone": 76
+    "owners": [ "chromeos-video-eng@google.com" ],
+    // This flag does not expire because it allows users to disable HW video
+    // decoding for debugging purpose and temporary workaround for some issues.
+    "expiry_milestone": -1
   },
   {
     "name": "disable-audio-support-for-desktop-share",
@@ -654,13 +658,19 @@
   },
   {
     "name": "disable-webrtc-hw-decoding",
-    // "owners": [ "your-team" ],
-    "expiry_milestone": 76
+    "owners": [ "hiroh", "chromeos-video-eng@google.com" ],
+    // This flag does not expire because it allows users to disable HW video
+    // decoding only in webrtc usecase for debugging purpose and temporary
+    // workaround for some issues.
+    "expiry_milestone": -1
   },
   {
     "name": "disable-webrtc-hw-encoding",
-    // "owners": [ "your-team" ],
-    "expiry_milestone": 76
+    "owners": [ "hiroh", "chromeos-video-eng@google.com" ],
+    // This flag does not expire because it allows users to disable HW video
+    // encoding only in webrtc usecase for debugging purpose and temporary
+    // workaround for some issues.
+    "expiry_milestone": -1
   },
   {
     "name": "disallow-doc-written-script-loads",
@@ -1906,7 +1916,7 @@
   },
   {
     "name": "enable-vaapi-jpeg-image-decode-acceleration",
-    // "owners": [ "your-team" ],
+    "owners": [ "chromeos-camera-eng@google.com" ],
     "expiry_milestone": 76
   },
   {
@@ -2008,12 +2018,12 @@
   },
   {
     "name": "enable-webrtc-hw-h264-encoding",
-    // "owners": [ "your-team" ],
+    "owners": [ "hiroh", "chromeos-video-eng@google.com" ],
     "expiry_milestone": 76
   },
   {
     "name": "enable-webrtc-hw-vp8-encoding",
-    // "owners": [ "your-team" ],
+    "owners": [ "hiroh", "chromeos-video-eng@google.com" ],
     "expiry_milestone": 76
   },
   {
diff --git a/chrome/browser/offline_pages/offline_page_tab_helper.cc b/chrome/browser/offline_pages/offline_page_tab_helper.cc
index 58532e2..3d7460d 100644
--- a/chrome/browser/offline_pages/offline_page_tab_helper.cc
+++ b/chrome/browser/offline_pages/offline_page_tab_helper.cc
@@ -369,6 +369,10 @@
          (offline_info_.trusted_state != OfflinePageTrustedState::UNTRUSTED);
 }
 
+bool OfflinePageTabHelper::IsLoadingOfflinePage() const {
+  return provisional_offline_info_.offline_page.get() != nullptr;
+}
+
 const OfflinePageItem* OfflinePageTabHelper::GetOfflinePageForTest() const {
   return provisional_offline_info_.offline_page.get();
 }
diff --git a/chrome/browser/offline_pages/offline_page_tab_helper.h b/chrome/browser/offline_pages/offline_page_tab_helper.h
index 4ba558f..2d40cd3 100644
--- a/chrome/browser/offline_pages/offline_page_tab_helper.h
+++ b/chrome/browser/offline_pages/offline_page_tab_helper.h
@@ -95,6 +95,9 @@
   // during unit tests.
   const OfflinePageItem* GetOfflinePageForTest() const;
 
+  // True if an offline page is loading, but has not committed.
+  bool IsLoadingOfflinePage() const;
+
   // Returns trusted state of provisional offline page.
   OfflinePageTrustedState GetTrustedStateForTest() const;
 
diff --git a/chrome/browser/password_manager/password_store_signin_notifier_impl.cc b/chrome/browser/password_manager/password_store_signin_notifier_impl.cc
index 5a4027c..64dab721 100644
--- a/chrome/browser/password_manager/password_store_signin_notifier_impl.cc
+++ b/chrome/browser/password_manager/password_store_signin_notifier_impl.cc
@@ -34,7 +34,7 @@
 }
 
 // IdentityManager::Observer implementations.
-void PasswordStoreSigninNotifierImpl::OnAccountRemovedWithInfo(
+void PasswordStoreSigninNotifierImpl::OnExtendedAccountInfoRemoved(
     const AccountInfo& info) {
   // Only reacts to content area (non-primary) Gaia account sign-out event.
   if (info.account_id !=
diff --git a/chrome/browser/password_manager/password_store_signin_notifier_impl.h b/chrome/browser/password_manager/password_store_signin_notifier_impl.h
index c3ea13f..866755ef 100644
--- a/chrome/browser/password_manager/password_store_signin_notifier_impl.h
+++ b/chrome/browser/password_manager/password_store_signin_notifier_impl.h
@@ -29,7 +29,7 @@
 
   // IdentityManager::Observer implementations.
   void OnPrimaryAccountCleared(const CoreAccountInfo& account_info) override;
-  void OnAccountRemovedWithInfo(const AccountInfo& info) override;
+  void OnExtendedAccountInfoRemoved(const AccountInfo& info) override;
 
  private:
   Profile* const profile_;
diff --git a/chrome/browser/profiles/profile_downloader.cc b/chrome/browser/profiles/profile_downloader.cc
index 189954b..6146898 100644
--- a/chrome/browser/profiles/profile_downloader.cc
+++ b/chrome/browser/profiles/profile_downloader.cc
@@ -304,7 +304,7 @@
   StartFetchingImage();
 }
 
-void ProfileDownloader::OnAccountUpdated(const AccountInfo& info) {
+void ProfileDownloader::OnExtendedAccountInfoUpdated(const AccountInfo& info) {
   if (info.account_id == account_id_ && info.IsValid()) {
     account_info_ = info;
 
diff --git a/chrome/browser/profiles/profile_downloader.h b/chrome/browser/profiles/profile_downloader.h
index b127a5c..1f8d0774 100644
--- a/chrome/browser/profiles/profile_downloader.h
+++ b/chrome/browser/profiles/profile_downloader.h
@@ -95,7 +95,7 @@
   void OnDecodeImageFailed() override;
 
   // Overriden from identity::IdentityManager::Observer:
-  void OnAccountUpdated(const AccountInfo& info) override;
+  void OnExtendedAccountInfoUpdated(const AccountInfo& info) override;
 
   // Callback for AccessTokenFetcher.
   void OnAccessTokenFetchComplete(GoogleServiceAuthError error,
diff --git a/chrome/browser/resources/chromeos/camera/BUILD.gn b/chrome/browser/resources/chromeos/camera/BUILD.gn
new file mode 100644
index 0000000..1acc259
--- /dev/null
+++ b/chrome/browser/resources/chromeos/camera/BUILD.gn
@@ -0,0 +1,27 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+chrome_camera_app_dir = "$root_out_dir/resources/chromeos/camera"
+
+group("chrome_camera_app") {
+  deps = [
+    ":chrome_camera_app_base",
+    "//chrome/browser/resources/chromeos/camera/src/strings:camera_strings",
+  ]
+}
+
+copy("chrome_camera_app_base") {
+  sources = [
+    "src/css",
+    "src/images",
+    "src/js",
+    "src/manifest.json",
+    "src/sounds",
+    "src/views",
+  ]
+
+  outputs = [
+    "$chrome_camera_app_dir/{{source_file_part}}",
+  ]
+}
diff --git a/chrome/browser/resources/chromeos/camera/src/_locales/am/messages.json b/chrome/browser/resources/chromeos/camera/src/_locales/am/messages.json
index d3a71da..d7f2d53 100644
--- a/chrome/browser/resources/chromeos/camera/src/_locales/am/messages.json
+++ b/chrome/browser/resources/chromeos/camera/src/_locales/am/messages.json
@@ -1,21 +1,21 @@
 {
-  "name": {
+  "NAME": {
     "message": "ካሜራ",
     "description": "Name of the Camera App."
   },
-  "description": {
+  "DESCRIPTION": {
     "message": "በካሜራዎ ፎቶዎችን ያንሱ እና ቪዲዮዎችን ይቅረጹ።",
     "description": "Short description of the Camera App."
   },
-  "errorMsgFileSystemFailed": {
+  "ERROR_MSG_FILE_SYSTEM_FAILED": {
     "message": "የፋይል ሥርዓት ስህተቶች።",
     "description": "Error message shown when failing to read or write the file system."
   },
-  "errorMsgNoCamera": {
+  "ERROR_MSG_NO_CAMERA": {
     "message": "የእርስዎ ካሜራ አሁን ላይ ሊገኝ አይችልም።\nካሜራው በአግባቡ መገናኘቱን እባክዎ ይፈትሹ።",
     "description": "Error message shown when it was impossible to connect to the camera due to unavailability."
   },
-  "errorMsgGalleryExportFailed": {
+  "ERROR_MSG_GALLERY_EXPORT_FAILED": {
     "message": "$file$ን ወደ ውጭ መላክ አልተቻለም",
     "description": "Error message shown when exporting to an external directory failed. Expects a file name to be passed in.",
     "placeholders": {
@@ -25,27 +25,27 @@
       }
     }
   },
-  "errorMsgSaveFileFailed": {
+  "ERROR_MSG_SAVE_FILE_FAILED": {
     "message": "ፋይሉን ማስቀመጥ አልተሳካም",
     "description": "Error message shown when saving/adding a image or video to the file system failed."
   },
-  "errorMsgTakePhotoFailed": {
+  "ERROR_MSG_TAKE_PHOTO_FAILED": {
     "message": "ፎቶን ማንሳት አልተቻለም",
     "description": "Error message shown when failing to take photo."
   },
-  "errorMsgRecordStartFailed": {
+  "ERROR_MSG_RECORD_START_FAILED": {
     "message": "መቅረጽ መጀመር አልተቻለም",
     "description": "Error message shown when failing to start recording video."
   },
-  "errorMsgEmptyRecording": {
+  "ERROR_MSG_EMPTY_RECORDING": {
     "message": "ምንም አልተቀረጸም",
     "description": "Error message shown when no data is recorded for a recording and it won't be added to the gallery."
   },
-  "statusMsgRecordingStopped": {
+  "STATUS_MSG_RECORDING_STOPPED": {
     "message": "ቀረጻ ቆሟል",
     "description": "Status message for spoken feedback when video recording has been stopped."
   },
-  "statusMsgCameraSwitched": {
+  "STATUS_MSG_CAMERA_SWITCHED": {
     "message": "$camera$ ገቢር",
     "description": "Status message for spoken feedback when switching over to another camera.",
     "placeholders": {
@@ -55,131 +55,131 @@
       }
     }
   },
-  "galleryButton": {
+  "GALLERY_BUTTON": {
     "message": "ወደ ማዕከለ-ሥዕላት ሂድ",
     "description": "Label for the gallery button."
   },
-  "deleteButton": {
+  "DELETE_BUTTON": {
     "message": "ሰርዝ",
     "description": "Label for the delete button."
   },
-  "exportButton": {
+  "EXPORT_BUTTON": {
     "message": "ወደ ዲስክ ላክ",
     "description": "Label for the exporting button."
   },
-  "printButton": {
+  "PRINT_BUTTON": {
     "message": "አትም",
     "description": "Label for the printing button."
   },
-  "backButton": {
+  "BACK_BUTTON": {
     "message": "ተመለስ",
     "description": "Label for the back button."
   },
-  "galleryImages": {
+  "GALLERY_IMAGES": {
     "message": "የማዕከለ-ሥዕላት ምስሎች",
     "description": "Text to speech label for the gallery list."
   },
-  "settingsButton": {
+  "SETTINGS_BUTTON": {
     "message": "ቅንብሮች",
     "description": "Label for the settings button."
   },
-  "gridTypeButton": {
+  "GRID_TYPE_BUTTON": {
     "message": "የፍርግርግ ዓይነት",
     "description": "Label for the button of grid-type options."
   },
-  "timerDurationButton": {
+  "TIMER_DURATION_BUTTON": {
     "message": "የጊዜ ቆጣሪ ቆይታ",
     "description": "Label for the button of timer-duration options."
   },
-  "feedbackButton": {
+  "FEEDBACK_BUTTON": {
     "message": "ግብረመልስ ላክ",
     "description": "Label for the feedback button."
   },
-  "helpButton": {
+  "HELP_BUTTON": {
     "message": "እገዛ",
     "description": "Label for the help button."
   },
-  "labelGrid3x3": {
+  "LABEL_GRID_3X3": {
     "message": "3 x 3",
     "description": "Label for for grid-type: 3x3."
   },
-  "ariaGrid3x3": {
+  "ARIA_GRID_3X3": {
     "message": "3 በ3",
     "description": "Label for spoken feedback to read out grid-type: 3x3."
   },
-  "labelGrid4x4": {
+  "LABEL_GRID_4X4": {
     "message": "4 x 4",
     "description": "Label for for grid-type: 4x4."
   },
-  "ariaGrid4x4": {
+  "ARIA_GRID_4X4": {
     "message": "4 በ4",
     "description": "Label for spoken feedback to read out grid-type: 4x4."
   },
-  "labelGridGolden": {
+  "LABEL_GRID_GOLDEN": {
     "message": "ወርቃማ ውድር",
     "description": "Label for grid-type: golden ratio."
   },
-  "labelTimer3s": {
+  "LABEL_TIMER_3S": {
     "message": "3 ሰከንዶች",
     "description": "Label for timer-duration: 3 seconds."
   },
-  "labelTimer10s": {
+  "LABEL_TIMER_10S": {
     "message": "10 ሰከንዶች",
     "description": "Label for timer-duration: 10 seconds."
   },
-  "takePhotoButton": {
+  "TAKE_PHOTO_BUTTON": {
     "message": "ፎቶ ያንሱ",
     "description": "Label for the shutter button to take photo."
   },
-  "takePhotoCancelButton": {
+  "TAKE_PHOTO_CANCEL_BUTTON": {
     "message": "ፎቶን ማንሳት አቁም",
     "description": "Label for the shutter button to cancel countdown timer and stop taking photo."
   },
-  "recordVideoStartButton": {
+  "RECORD_VIDEO_START_BUTTON": {
     "message": "መቅረጽ ጀምር",
     "description": "Label for the shutter button to start recording."
   },
-  "recordVideoStopButton": {
+  "RECORD_VIDEO_STOP_BUTTON": {
     "message": "መቅረጽ አቁም",
     "description": "Label for the shutter button to stop recording."
   },
-  "switchCameraButton": {
+  "SWITCH_CAMERA_BUTTON": {
     "message": "ወደ ቀጣዩ ካሜራ ቀይር",
     "description": "Label for the button to switch to next connected camera. Eg. switching from front facing to back facing, or a camera connected via USB. The button is shown only when more than one camera is connected."
   },
-  "switchRecordVideoButton": {
+  "SWITCH_RECORD_VIDEO_BUTTON": {
     "message": "ቪዲዮ ለመቅረጽ ቀይር",
     "description": "Label for the button to switch to record video mode."
   },
-  "switchTakePhotoButton": {
+  "SWITCH_TAKE_PHOTO_BUTTON": {
     "message": "ፎቶ ለማንሳት ይቀይሩ",
     "description": "Label for the button to switch to take photo mode."
   },
-  "toggleTimerButton": {
+  "TOGGLE_TIMER_BUTTON": {
     "message": "የሰዓት ቆጣሪ",
     "description": "Label for the checkbox to toggle the countdown timer."
   },
-  "toggleMirrorButton": {
+  "TOGGLE_MIRROR_BUTTON": {
     "message": "ማስተላለፍ",
     "description": "Label for the checkbox to toggle the preview mirroring. Eg. if mirroring is toggled on, preview will be flipped horizontally."
   },
-  "toggleGridButton": {
+  "TOGGLE_GRID_BUTTON": {
     "message": "ፍርግርግ",
     "description": "Label for the checkbox to toggle the grid shown on preview."
   },
-  "toggleMicButton": {
+  "TOGGLE_MIC_BUTTON": {
     "message": "ማይክሮፎን",
     "description": "Label for the checkbox to toggle the microphone for recording video."
   },
-  "dialogOKButton": {
+  "DIALOG_OK_BUTTON": {
     "message": "እሺ",
     "description": "Label for the accepting button in the dialog."
   },
-  "dialogCancelButton": {
+  "DIALOG_CANCEL_BUTTON": {
     "message": "ይቅር",
     "description": "Label for the dismissing button in the dialog."
   },
-  "deleteConfirmationMsg": {
+  "DELETE_CONFIRMATION_MSG": {
     "message": "እርግጠኛ ነዎት $file$ን ማስወገድ ይፈልጋሉ?",
     "description": "Confirmation message before removing a selected item from the gallery. Expects a file name to be passed in.",
     "placeholders": {
@@ -189,7 +189,7 @@
       }
     }
   },
-  "deleteMultiConfirmationMsg": {
+  "DELETE_MULTI_CONFIRMATION_MSG": {
     "message": "እርግጠኛ ነዎት $count$ ንጥሎችን ማስወገድ ይፈልጋሉ?",
     "description": "Confirmation message before removing multiple selected items from the gallery. Expects a file count to be passed in.",
     "placeholders": {
@@ -199,7 +199,7 @@
       }
     }
   },
-  "migratePicturesMsg": {
+  "MIGRATE_PICTURES_MSG": {
     "message": "በካሜራው የተነሱ ፎቶዎች ወይም የተቀረጹ ቪዲዮዎች ወደ የውርዶች አቃፊው ይወሰዳሉ። በፋይሎች ውስጥ ሊደርሱባቸው ይችላሉ።\n\nየማከማቻ ፈቃዶች ያላቸው መተግበሪያዎች የእርስዎን ፎቶዎች እና ቪዲዮዎች መዳረሻ ይኖራቸዋል።",
     "description": "Message shown before moving all photos and videos stored in the Camera App to the Downloads folder."
   }
diff --git a/chrome/browser/resources/chromeos/camera/src/_locales/ar/messages.json b/chrome/browser/resources/chromeos/camera/src/_locales/ar/messages.json
index af75f23..9c2cc276 100644
--- a/chrome/browser/resources/chromeos/camera/src/_locales/ar/messages.json
+++ b/chrome/browser/resources/chromeos/camera/src/_locales/ar/messages.json
@@ -1,21 +1,21 @@
 {
-  "name": {
+  "NAME": {
     "message": "الكاميرا",
     "description": "Name of the Camera App."
   },
-  "description": {
+  "DESCRIPTION": {
     "message": "يمكنك التقاط الصور وتسجيل الفيديوهات باستخدام الكاميرا.",
     "description": "Short description of the Camera App."
   },
-  "errorMsgFileSystemFailed": {
+  "ERROR_MSG_FILE_SYSTEM_FAILED": {
     "message": "أخطاء نظام الملفات.",
     "description": "Error message shown when failing to read or write the file system."
   },
-  "errorMsgNoCamera": {
+  "ERROR_MSG_NO_CAMERA": {
     "message": "الكاميرا غير متاحة حاليًا.\nيُرجى التحقُّق من اتصال الكاميرا بشكلٍ صحيح.",
     "description": "Error message shown when it was impossible to connect to the camera due to unavailability."
   },
-  "errorMsgGalleryExportFailed": {
+  "ERROR_MSG_GALLERY_EXPORT_FAILED": {
     "message": "يتعذَّر تصدير $file$.",
     "description": "Error message shown when exporting to an external directory failed. Expects a file name to be passed in.",
     "placeholders": {
@@ -25,27 +25,27 @@
       }
     }
   },
-  "errorMsgSaveFileFailed": {
+  "ERROR_MSG_SAVE_FILE_FAILED": {
     "message": "يتعذَّر حفظ الملف.",
     "description": "Error message shown when saving/adding a image or video to the file system failed."
   },
-  "errorMsgTakePhotoFailed": {
+  "ERROR_MSG_TAKE_PHOTO_FAILED": {
     "message": "يتعذّر التقاط الصورة.",
     "description": "Error message shown when failing to take photo."
   },
-  "errorMsgRecordStartFailed": {
+  "ERROR_MSG_RECORD_START_FAILED": {
     "message": "يتعذّر بدء التسجيل.",
     "description": "Error message shown when failing to start recording video."
   },
-  "errorMsgEmptyRecording": {
+  "ERROR_MSG_EMPTY_RECORDING": {
     "message": "لم يتمّ تسجيل أيّ بيانات.",
     "description": "Error message shown when no data is recorded for a recording and it won't be added to the gallery."
   },
-  "statusMsgRecordingStopped": {
+  "STATUS_MSG_RECORDING_STOPPED": {
     "message": "تمّ إيقاف التسجيل.",
     "description": "Status message for spoken feedback when video recording has been stopped."
   },
-  "statusMsgCameraSwitched": {
+  "STATUS_MSG_CAMERA_SWITCHED": {
     "message": "الكاميرا $camera$ نشِطة.",
     "description": "Status message for spoken feedback when switching over to another camera.",
     "placeholders": {
@@ -55,131 +55,131 @@
       }
     }
   },
-  "galleryButton": {
+  "GALLERY_BUTTON": {
     "message": "الانتقال إلى المعرض",
     "description": "Label for the gallery button."
   },
-  "deleteButton": {
+  "DELETE_BUTTON": {
     "message": "حذف",
     "description": "Label for the delete button."
   },
-  "exportButton": {
+  "EXPORT_BUTTON": {
     "message": "تصدير إلى القرص",
     "description": "Label for the exporting button."
   },
-  "printButton": {
+  "PRINT_BUTTON": {
     "message": "طباعة",
     "description": "Label for the printing button."
   },
-  "backButton": {
+  "BACK_BUTTON": {
     "message": "رجوع",
     "description": "Label for the back button."
   },
-  "galleryImages": {
+  "GALLERY_IMAGES": {
     "message": "صور المعرض",
     "description": "Text to speech label for the gallery list."
   },
-  "settingsButton": {
+  "SETTINGS_BUTTON": {
     "message": "إعدادات",
     "description": "Label for the settings button."
   },
-  "gridTypeButton": {
+  "GRID_TYPE_BUTTON": {
     "message": "نوع الشبكة",
     "description": "Label for the button of grid-type options."
   },
-  "timerDurationButton": {
+  "TIMER_DURATION_BUTTON": {
     "message": "مدة المؤقِّت",
     "description": "Label for the button of timer-duration options."
   },
-  "feedbackButton": {
+  "FEEDBACK_BUTTON": {
     "message": "إرسال تعليقات",
     "description": "Label for the feedback button."
   },
-  "helpButton": {
+  "HELP_BUTTON": {
     "message": "مساعدة",
     "description": "Label for the help button."
   },
-  "labelGrid3x3": {
+  "LABEL_GRID_3X3": {
     "message": "وضع 3 × 3",
     "description": "Label for for grid-type: 3x3."
   },
-  "ariaGrid3x3": {
+  "ARIA_GRID_3X3": {
     "message": "وضع 3 في 3",
     "description": "Label for spoken feedback to read out grid-type: 3x3."
   },
-  "labelGrid4x4": {
+  "LABEL_GRID_4X4": {
     "message": "وضع 4 × 4",
     "description": "Label for for grid-type: 4x4."
   },
-  "ariaGrid4x4": {
+  "ARIA_GRID_4X4": {
     "message": "وضع 4 في 4",
     "description": "Label for spoken feedback to read out grid-type: 4x4."
   },
-  "labelGridGolden": {
+  "LABEL_GRID_GOLDEN": {
     "message": "وضع النسبة الذهبية",
     "description": "Label for grid-type: golden ratio."
   },
-  "labelTimer3s": {
+  "LABEL_TIMER_3S": {
     "message": "3 ثوانٍ",
     "description": "Label for timer-duration: 3 seconds."
   },
-  "labelTimer10s": {
+  "LABEL_TIMER_10S": {
     "message": "۱۰ ثوانٍ",
     "description": "Label for timer-duration: 10 seconds."
   },
-  "takePhotoButton": {
+  "TAKE_PHOTO_BUTTON": {
     "message": "التقاط صورة",
     "description": "Label for the shutter button to take photo."
   },
-  "takePhotoCancelButton": {
+  "TAKE_PHOTO_CANCEL_BUTTON": {
     "message": "إيقاف التقاط الصورة",
     "description": "Label for the shutter button to cancel countdown timer and stop taking photo."
   },
-  "recordVideoStartButton": {
+  "RECORD_VIDEO_START_BUTTON": {
     "message": "بدء التسجيل",
     "description": "Label for the shutter button to start recording."
   },
-  "recordVideoStopButton": {
+  "RECORD_VIDEO_STOP_BUTTON": {
     "message": "إيقاف التسجيل",
     "description": "Label for the shutter button to stop recording."
   },
-  "switchCameraButton": {
+  "SWITCH_CAMERA_BUTTON": {
     "message": "التبديل إلى الكاميرا التالية",
     "description": "Label for the button to switch to next connected camera. Eg. switching from front facing to back facing, or a camera connected via USB. The button is shown only when more than one camera is connected."
   },
-  "switchRecordVideoButton": {
+  "SWITCH_RECORD_VIDEO_BUTTON": {
     "message": "تبديل لوضع تسجيل الفيديو",
     "description": "Label for the button to switch to record video mode."
   },
-  "switchTakePhotoButton": {
+  "SWITCH_TAKE_PHOTO_BUTTON": {
     "message": "تبديل لوضع التقاط الصور",
     "description": "Label for the button to switch to take photo mode."
   },
-  "toggleTimerButton": {
+  "TOGGLE_TIMER_BUTTON": {
     "message": "الموقِّت",
     "description": "Label for the checkbox to toggle the countdown timer."
   },
-  "toggleMirrorButton": {
+  "TOGGLE_MIRROR_BUTTON": {
     "message": "النسخ المطابق",
     "description": "Label for the checkbox to toggle the preview mirroring. Eg. if mirroring is toggled on, preview will be flipped horizontally."
   },
-  "toggleGridButton": {
+  "TOGGLE_GRID_BUTTON": {
     "message": "الشبكة",
     "description": "Label for the checkbox to toggle the grid shown on preview."
   },
-  "toggleMicButton": {
+  "TOGGLE_MIC_BUTTON": {
     "message": "الميكروفون",
     "description": "Label for the checkbox to toggle the microphone for recording video."
   },
-  "dialogOKButton": {
+  "DIALOG_OK_BUTTON": {
     "message": "موافق",
     "description": "Label for the accepting button in the dialog."
   },
-  "dialogCancelButton": {
+  "DIALOG_CANCEL_BUTTON": {
     "message": "إلغاء",
     "description": "Label for the dismissing button in the dialog."
   },
-  "deleteConfirmationMsg": {
+  "DELETE_CONFIRMATION_MSG": {
     "message": "هل تريد فعلاً إزالة $file$؟",
     "description": "Confirmation message before removing a selected item from the gallery. Expects a file name to be passed in.",
     "placeholders": {
@@ -189,7 +189,7 @@
       }
     }
   },
-  "deleteMultiConfirmationMsg": {
+  "DELETE_MULTI_CONFIRMATION_MSG": {
     "message": "هل تريد فعلاً إزالة $count$ عنصر؟",
     "description": "Confirmation message before removing multiple selected items from the gallery. Expects a file count to be passed in.",
     "placeholders": {
@@ -199,7 +199,7 @@
       }
     }
   },
-  "migratePicturesMsg": {
+  "MIGRATE_PICTURES_MSG": {
     "message": "سيتمّ نقل الصور والفيديوهات الملتقَطة بالكاميرا إلى مجلد \"التنزيلات\" ويمكنك الوصول إليها من خلال تطبيق \"ملفات\".\n\nستتمكَّن التطبيقات من الوصول إلى صورك وفيديوهاتك في حال تزويدها بأذونات الاطّلاع على سعة التخزين.",
     "description": "Message shown before moving all photos and videos stored in the Camera App to the Downloads folder."
   }
diff --git a/chrome/browser/resources/chromeos/camera/src/_locales/bg/messages.json b/chrome/browser/resources/chromeos/camera/src/_locales/bg/messages.json
index 51698cbd..c7ae7bd 100644
--- a/chrome/browser/resources/chromeos/camera/src/_locales/bg/messages.json
+++ b/chrome/browser/resources/chromeos/camera/src/_locales/bg/messages.json
@@ -1,21 +1,21 @@
 {
-  "name": {
+  "NAME": {
     "message": "Камера",
     "description": "Name of the Camera App."
   },
-  "description": {
+  "DESCRIPTION": {
     "message": "Правете снимки и записвайте видеоклипове с камерата си.",
     "description": "Short description of the Camera App."
   },
-  "errorMsgFileSystemFailed": {
+  "ERROR_MSG_FILE_SYSTEM_FAILED": {
     "message": "Грешки в системата за съхранение на файлове.",
     "description": "Error message shown when failing to read or write the file system."
   },
-  "errorMsgNoCamera": {
+  "ERROR_MSG_NO_CAMERA": {
     "message": "Понастоящем няма достъп до камерата ви.\nМоля, проверете дали е свързана правилно.",
     "description": "Error message shown when it was impossible to connect to the camera due to unavailability."
   },
-  "errorMsgGalleryExportFailed": {
+  "ERROR_MSG_GALLERY_EXPORT_FAILED": {
     "message": "$file$ не може да се експортира",
     "description": "Error message shown when exporting to an external directory failed. Expects a file name to be passed in.",
     "placeholders": {
@@ -25,27 +25,27 @@
       }
     }
   },
-  "errorMsgSaveFileFailed": {
+  "ERROR_MSG_SAVE_FILE_FAILED": {
     "message": "Файлът не може да бъде запазен",
     "description": "Error message shown when saving/adding a image or video to the file system failed."
   },
-  "errorMsgTakePhotoFailed": {
+  "ERROR_MSG_TAKE_PHOTO_FAILED": {
     "message": "Не може да се направи снимка",
     "description": "Error message shown when failing to take photo."
   },
-  "errorMsgRecordStartFailed": {
+  "ERROR_MSG_RECORD_START_FAILED": {
     "message": "Записването не може да се стартира",
     "description": "Error message shown when failing to start recording video."
   },
-  "errorMsgEmptyRecording": {
+  "ERROR_MSG_EMPTY_RECORDING": {
     "message": "Нищо не е записано",
     "description": "Error message shown when no data is recorded for a recording and it won't be added to the gallery."
   },
-  "statusMsgRecordingStopped": {
+  "STATUS_MSG_RECORDING_STOPPED": {
     "message": "Записването спря",
     "description": "Status message for spoken feedback when video recording has been stopped."
   },
-  "statusMsgCameraSwitched": {
+  "STATUS_MSG_CAMERA_SWITCHED": {
     "message": "$camera$ е активна",
     "description": "Status message for spoken feedback when switching over to another camera.",
     "placeholders": {
@@ -55,131 +55,131 @@
       }
     }
   },
-  "galleryButton": {
+  "GALLERY_BUTTON": {
     "message": "Към галерията",
     "description": "Label for the gallery button."
   },
-  "deleteButton": {
+  "DELETE_BUTTON": {
     "message": "Изтриване",
     "description": "Label for the delete button."
   },
-  "exportButton": {
+  "EXPORT_BUTTON": {
     "message": "Експортиране в диска",
     "description": "Label for the exporting button."
   },
-  "printButton": {
+  "PRINT_BUTTON": {
     "message": "Печат",
     "description": "Label for the printing button."
   },
-  "backButton": {
+  "BACK_BUTTON": {
     "message": "Назад",
     "description": "Label for the back button."
   },
-  "galleryImages": {
+  "GALLERY_IMAGES": {
     "message": "Изображения в галерията",
     "description": "Text to speech label for the gallery list."
   },
-  "settingsButton": {
+  "SETTINGS_BUTTON": {
     "message": "Настройки",
     "description": "Label for the settings button."
   },
-  "gridTypeButton": {
+  "GRID_TYPE_BUTTON": {
     "message": "Тип решетка",
     "description": "Label for the button of grid-type options."
   },
-  "timerDurationButton": {
+  "TIMER_DURATION_BUTTON": {
     "message": "Продължителност на таймера",
     "description": "Label for the button of timer-duration options."
   },
-  "feedbackButton": {
+  "FEEDBACK_BUTTON": {
     "message": "Изпращане на отзиви",
     "description": "Label for the feedback button."
   },
-  "helpButton": {
+  "HELP_BUTTON": {
     "message": "Помощ",
     "description": "Label for the help button."
   },
-  "labelGrid3x3": {
+  "LABEL_GRID_3X3": {
     "message": "3 x 3",
     "description": "Label for for grid-type: 3x3."
   },
-  "ariaGrid3x3": {
+  "ARIA_GRID_3X3": {
     "message": "3 на 3",
     "description": "Label for spoken feedback to read out grid-type: 3x3."
   },
-  "labelGrid4x4": {
+  "LABEL_GRID_4X4": {
     "message": "4 x 4",
     "description": "Label for for grid-type: 4x4."
   },
-  "ariaGrid4x4": {
+  "ARIA_GRID_4X4": {
     "message": "4 на 4",
     "description": "Label for spoken feedback to read out grid-type: 4x4."
   },
-  "labelGridGolden": {
+  "LABEL_GRID_GOLDEN": {
     "message": "Златното сечение",
     "description": "Label for grid-type: golden ratio."
   },
-  "labelTimer3s": {
+  "LABEL_TIMER_3S": {
     "message": "3 секунди",
     "description": "Label for timer-duration: 3 seconds."
   },
-  "labelTimer10s": {
+  "LABEL_TIMER_10S": {
     "message": "10 секунди",
     "description": "Label for timer-duration: 10 seconds."
   },
-  "takePhotoButton": {
+  "TAKE_PHOTO_BUTTON": {
     "message": "Правене на снимка",
     "description": "Label for the shutter button to take photo."
   },
-  "takePhotoCancelButton": {
+  "TAKE_PHOTO_CANCEL_BUTTON": {
     "message": "Спиране на правенето на снимка",
     "description": "Label for the shutter button to cancel countdown timer and stop taking photo."
   },
-  "recordVideoStartButton": {
+  "RECORD_VIDEO_START_BUTTON": {
     "message": "Започване на запис",
     "description": "Label for the shutter button to start recording."
   },
-  "recordVideoStopButton": {
+  "RECORD_VIDEO_STOP_BUTTON": {
     "message": "Спиране на записа",
     "description": "Label for the shutter button to stop recording."
   },
-  "switchCameraButton": {
+  "SWITCH_CAMERA_BUTTON": {
     "message": "Превключване към следващата камера",
     "description": "Label for the button to switch to next connected camera. Eg. switching from front facing to back facing, or a camera connected via USB. The button is shown only when more than one camera is connected."
   },
-  "switchRecordVideoButton": {
+  "SWITCH_RECORD_VIDEO_BUTTON": {
     "message": "Превключване към режима за запис на видеоклипове",
     "description": "Label for the button to switch to record video mode."
   },
-  "switchTakePhotoButton": {
+  "SWITCH_TAKE_PHOTO_BUTTON": {
     "message": "Превключване към режима за правене на снимки",
     "description": "Label for the button to switch to take photo mode."
   },
-  "toggleTimerButton": {
+  "TOGGLE_TIMER_BUTTON": {
     "message": "Таймер",
     "description": "Label for the checkbox to toggle the countdown timer."
   },
-  "toggleMirrorButton": {
+  "TOGGLE_MIRROR_BUTTON": {
     "message": "Функция за огледално обръщане",
     "description": "Label for the checkbox to toggle the preview mirroring. Eg. if mirroring is toggled on, preview will be flipped horizontally."
   },
-  "toggleGridButton": {
+  "TOGGLE_GRID_BUTTON": {
     "message": "Решетка",
     "description": "Label for the checkbox to toggle the grid shown on preview."
   },
-  "toggleMicButton": {
+  "TOGGLE_MIC_BUTTON": {
     "message": "Микрофон",
     "description": "Label for the checkbox to toggle the microphone for recording video."
   },
-  "dialogOKButton": {
+  "DIALOG_OK_BUTTON": {
     "message": "OK",
     "description": "Label for the accepting button in the dialog."
   },
-  "dialogCancelButton": {
+  "DIALOG_CANCEL_BUTTON": {
     "message": "Отказ",
     "description": "Label for the dismissing button in the dialog."
   },
-  "deleteConfirmationMsg": {
+  "DELETE_CONFIRMATION_MSG": {
     "message": "Наистина ли искате да премахнете $file$?",
     "description": "Confirmation message before removing a selected item from the gallery. Expects a file name to be passed in.",
     "placeholders": {
@@ -189,7 +189,7 @@
       }
     }
   },
-  "deleteMultiConfirmationMsg": {
+  "DELETE_MULTI_CONFIRMATION_MSG": {
     "message": "Наистина ли искате да премахнете $count$ елемента?",
     "description": "Confirmation message before removing multiple selected items from the gallery. Expects a file count to be passed in.",
     "placeholders": {
@@ -199,7 +199,7 @@
       }
     }
   },
-  "migratePicturesMsg": {
+  "MIGRATE_PICTURES_MSG": {
     "message": "Направените с камерата снимки и видеоклипове ще бъдат преместени в папката „Изтегляния“. Можете да осъществите достъп до тях от „Файлове“.\n\nПриложенията с разрешения за хранилището ще имат достъп до снимките и видеоклиповете ви.",
     "description": "Message shown before moving all photos and videos stored in the Camera App to the Downloads folder."
   }
diff --git a/chrome/browser/resources/chromeos/camera/src/_locales/bn/messages.json b/chrome/browser/resources/chromeos/camera/src/_locales/bn/messages.json
index 0f65c08..d3055e0 100644
--- a/chrome/browser/resources/chromeos/camera/src/_locales/bn/messages.json
+++ b/chrome/browser/resources/chromeos/camera/src/_locales/bn/messages.json
@@ -1,21 +1,21 @@
 {
-  "name": {
+  "NAME": {
     "message": "ক্যামেরা",
     "description": "Name of the Camera App."
   },
-  "description": {
+  "DESCRIPTION": {
     "message": "আপনার ক্যামেরা ব্যবহার করে ছবি তুলুন এবং ভিডিও রেকর্ড করুন।",
     "description": "Short description of the Camera App."
   },
-  "errorMsgFileSystemFailed": {
+  "ERROR_MSG_FILE_SYSTEM_FAILED": {
     "message": "ফাইল সিস্টেমে সমস্যা।",
     "description": "Error message shown when failing to read or write the file system."
   },
-  "errorMsgNoCamera": {
+  "ERROR_MSG_NO_CAMERA": {
     "message": "আপনার ক্যামেরাটি বর্তমানে উপলভ্য নয়।\nক্যামেরাটি সঠিকভাবে কানেক্ট করা আছে কিনা দেখে নিন।",
     "description": "Error message shown when it was impossible to connect to the camera due to unavailability."
   },
-  "errorMsgGalleryExportFailed": {
+  "ERROR_MSG_GALLERY_EXPORT_FAILED": {
     "message": "$file$টি এক্সপোর্ট করা যায়নি",
     "description": "Error message shown when exporting to an external directory failed. Expects a file name to be passed in.",
     "placeholders": {
@@ -25,27 +25,27 @@
       }
     }
   },
-  "errorMsgSaveFileFailed": {
+  "ERROR_MSG_SAVE_FILE_FAILED": {
     "message": "ফাইলটি সেভ করা যায়নি",
     "description": "Error message shown when saving/adding a image or video to the file system failed."
   },
-  "errorMsgTakePhotoFailed": {
+  "ERROR_MSG_TAKE_PHOTO_FAILED": {
     "message": "ফটো তোলা যায়নি",
     "description": "Error message shown when failing to take photo."
   },
-  "errorMsgRecordStartFailed": {
+  "ERROR_MSG_RECORD_START_FAILED": {
     "message": "রেকর্ডিং শুরু করা যায়নি",
     "description": "Error message shown when failing to start recording video."
   },
-  "errorMsgEmptyRecording": {
+  "ERROR_MSG_EMPTY_RECORDING": {
     "message": "কিছুই রেকর্ড করা হয়নি",
     "description": "Error message shown when no data is recorded for a recording and it won't be added to the gallery."
   },
-  "statusMsgRecordingStopped": {
+  "STATUS_MSG_RECORDING_STOPPED": {
     "message": "রেকর্ডিং বন্ধ করা হয়েছে",
     "description": "Status message for spoken feedback when video recording has been stopped."
   },
-  "statusMsgCameraSwitched": {
+  "STATUS_MSG_CAMERA_SWITCHED": {
     "message": "$camera$ চালু আছে",
     "description": "Status message for spoken feedback when switching over to another camera.",
     "placeholders": {
@@ -55,131 +55,131 @@
       }
     }
   },
-  "galleryButton": {
+  "GALLERY_BUTTON": {
     "message": "গ্যালারিতে যান",
     "description": "Label for the gallery button."
   },
-  "deleteButton": {
+  "DELETE_BUTTON": {
     "message": "মুছুন",
     "description": "Label for the delete button."
   },
-  "exportButton": {
+  "EXPORT_BUTTON": {
     "message": "ডিস্কে এক্সপোর্ট করুন",
     "description": "Label for the exporting button."
   },
-  "printButton": {
+  "PRINT_BUTTON": {
     "message": "প্রিন্ট করুন",
     "description": "Label for the printing button."
   },
-  "backButton": {
+  "BACK_BUTTON": {
     "message": "ফিরে যান",
     "description": "Label for the back button."
   },
-  "galleryImages": {
+  "GALLERY_IMAGES": {
     "message": "গ্যালারির ছবিগুলি",
     "description": "Text to speech label for the gallery list."
   },
-  "settingsButton": {
+  "SETTINGS_BUTTON": {
     "message": "সেটিংস",
     "description": "Label for the settings button."
   },
-  "gridTypeButton": {
+  "GRID_TYPE_BUTTON": {
     "message": "গ্রিডের ধরন",
     "description": "Label for the button of grid-type options."
   },
-  "timerDurationButton": {
+  "TIMER_DURATION_BUTTON": {
     "message": "টাইমার সময়কাল",
     "description": "Label for the button of timer-duration options."
   },
-  "feedbackButton": {
+  "FEEDBACK_BUTTON": {
     "message": "মতামত দিন",
     "description": "Label for the feedback button."
   },
-  "helpButton": {
+  "HELP_BUTTON": {
     "message": "সহায়তা",
     "description": "Label for the help button."
   },
-  "labelGrid3x3": {
+  "LABEL_GRID_3X3": {
     "message": "৩ x ৩",
     "description": "Label for for grid-type: 3x3."
   },
-  "ariaGrid3x3": {
+  "ARIA_GRID_3X3": {
     "message": "৩ বাই ৩",
     "description": "Label for spoken feedback to read out grid-type: 3x3."
   },
-  "labelGrid4x4": {
+  "LABEL_GRID_4X4": {
     "message": "৪ x ৪",
     "description": "Label for for grid-type: 4x4."
   },
-  "ariaGrid4x4": {
+  "ARIA_GRID_4X4": {
     "message": "৪ বাই ৪",
     "description": "Label for spoken feedback to read out grid-type: 4x4."
   },
-  "labelGridGolden": {
+  "LABEL_GRID_GOLDEN": {
     "message": "গোল্ডেন রেশিও",
     "description": "Label for grid-type: golden ratio."
   },
-  "labelTimer3s": {
+  "LABEL_TIMER_3S": {
     "message": "৩ সেকেন্ড",
     "description": "Label for timer-duration: 3 seconds."
   },
-  "labelTimer10s": {
+  "LABEL_TIMER_10S": {
     "message": "১০ সেকেন্ড",
     "description": "Label for timer-duration: 10 seconds."
   },
-  "takePhotoButton": {
+  "TAKE_PHOTO_BUTTON": {
     "message": "ফটো তুলুন",
     "description": "Label for the shutter button to take photo."
   },
-  "takePhotoCancelButton": {
+  "TAKE_PHOTO_CANCEL_BUTTON": {
     "message": "ফটো তোলা বন্ধ করুন",
     "description": "Label for the shutter button to cancel countdown timer and stop taking photo."
   },
-  "recordVideoStartButton": {
+  "RECORD_VIDEO_START_BUTTON": {
     "message": "রেকর্ডিং শুরু করুন",
     "description": "Label for the shutter button to start recording."
   },
-  "recordVideoStopButton": {
+  "RECORD_VIDEO_STOP_BUTTON": {
     "message": "রেকর্ডিং বন্ধ করুন",
     "description": "Label for the shutter button to stop recording."
   },
-  "switchCameraButton": {
+  "SWITCH_CAMERA_BUTTON": {
     "message": "পরবর্তী ক্যামেরাতে যান",
     "description": "Label for the button to switch to next connected camera. Eg. switching from front facing to back facing, or a camera connected via USB. The button is shown only when more than one camera is connected."
   },
-  "switchRecordVideoButton": {
+  "SWITCH_RECORD_VIDEO_BUTTON": {
     "message": "ভিডিও রেকর্ড করতে পরিবর্তন করুন",
     "description": "Label for the button to switch to record video mode."
   },
-  "switchTakePhotoButton": {
+  "SWITCH_TAKE_PHOTO_BUTTON": {
     "message": "ফটো তুলতে পরিবর্তন করুন",
     "description": "Label for the button to switch to take photo mode."
   },
-  "toggleTimerButton": {
+  "TOGGLE_TIMER_BUTTON": {
     "message": "টাইমার",
     "description": "Label for the checkbox to toggle the countdown timer."
   },
-  "toggleMirrorButton": {
+  "TOGGLE_MIRROR_BUTTON": {
     "message": "মিররিং",
     "description": "Label for the checkbox to toggle the preview mirroring. Eg. if mirroring is toggled on, preview will be flipped horizontally."
   },
-  "toggleGridButton": {
+  "TOGGLE_GRID_BUTTON": {
     "message": "গ্রিড",
     "description": "Label for the checkbox to toggle the grid shown on preview."
   },
-  "toggleMicButton": {
+  "TOGGLE_MIC_BUTTON": {
     "message": "মাইক্রোফোন",
     "description": "Label for the checkbox to toggle the microphone for recording video."
   },
-  "dialogOKButton": {
+  "DIALOG_OK_BUTTON": {
     "message": "ঠিক আছে",
     "description": "Label for the accepting button in the dialog."
   },
-  "dialogCancelButton": {
+  "DIALOG_CANCEL_BUTTON": {
     "message": "বাতিল করুন",
     "description": "Label for the dismissing button in the dialog."
   },
-  "deleteConfirmationMsg": {
+  "DELETE_CONFIRMATION_MSG": {
     "message": "আপনি কি সত্যিই $file$ সরিয়ে ফেলতে চান?",
     "description": "Confirmation message before removing a selected item from the gallery. Expects a file name to be passed in.",
     "placeholders": {
@@ -189,7 +189,7 @@
       }
     }
   },
-  "deleteMultiConfirmationMsg": {
+  "DELETE_MULTI_CONFIRMATION_MSG": {
     "message": "আপনি কি সত্যিই $count$টি আইটেম সরিয়ে ফেলতে চান?",
     "description": "Confirmation message before removing multiple selected items from the gallery. Expects a file count to be passed in.",
     "placeholders": {
@@ -199,7 +199,7 @@
       }
     }
   },
-  "migratePicturesMsg": {
+  "MIGRATE_PICTURES_MSG": {
     "message": "ক্যামেরায় তোলা ফটো এবং ভিডিও ডাউনলোড ফোল্ডারে সরিয়ে দেওয়া হবে। আপনি সেগুলি ফাইল বিকল্প থেকে অ্যাক্সেস করতে পারবেন।\n\nযে অ্যাপগুলিকে স্টোরেজ ব্যবহারের অনুমতি দেওয়া আছে সেগুলি আপনার ফটো এবং ভিডিও অ্যাক্সেস করতে পারবে।",
     "description": "Message shown before moving all photos and videos stored in the Camera App to the Downloads folder."
   }
diff --git a/chrome/browser/resources/chromeos/camera/src/_locales/ca/messages.json b/chrome/browser/resources/chromeos/camera/src/_locales/ca/messages.json
index f3547e9d..3e72fd0 100644
--- a/chrome/browser/resources/chromeos/camera/src/_locales/ca/messages.json
+++ b/chrome/browser/resources/chromeos/camera/src/_locales/ca/messages.json
@@ -1,21 +1,21 @@
 {
-  "name": {
+  "NAME": {
     "message": "Càmera",
     "description": "Name of the Camera App."
   },
-  "description": {
+  "DESCRIPTION": {
     "message": "Fes fotos i grava vídeos amb la càmera.",
     "description": "Short description of the Camera App."
   },
-  "errorMsgFileSystemFailed": {
+  "ERROR_MSG_FILE_SYSTEM_FAILED": {
     "message": "Errors del sistema de fitxers.",
     "description": "Error message shown when failing to read or write the file system."
   },
-  "errorMsgNoCamera": {
+  "ERROR_MSG_NO_CAMERA": {
     "message": "La càmera no està disponible en aquest moment.\nComprova que la càmera estigui ben connectada.",
     "description": "Error message shown when it was impossible to connect to the camera due to unavailability."
   },
-  "errorMsgGalleryExportFailed": {
+  "ERROR_MSG_GALLERY_EXPORT_FAILED": {
     "message": "No es pot exportar el fitxer $file$",
     "description": "Error message shown when exporting to an external directory failed. Expects a file name to be passed in.",
     "placeholders": {
@@ -25,27 +25,27 @@
       }
     }
   },
-  "errorMsgSaveFileFailed": {
+  "ERROR_MSG_SAVE_FILE_FAILED": {
     "message": "No es pot desar el fitxer",
     "description": "Error message shown when saving/adding a image or video to the file system failed."
   },
-  "errorMsgTakePhotoFailed": {
+  "ERROR_MSG_TAKE_PHOTO_FAILED": {
     "message": "No es pot fer la foto",
     "description": "Error message shown when failing to take photo."
   },
-  "errorMsgRecordStartFailed": {
+  "ERROR_MSG_RECORD_START_FAILED": {
     "message": "No es pot iniciar la gravació",
     "description": "Error message shown when failing to start recording video."
   },
-  "errorMsgEmptyRecording": {
+  "ERROR_MSG_EMPTY_RECORDING": {
     "message": "No s'ha gravat res",
     "description": "Error message shown when no data is recorded for a recording and it won't be added to the gallery."
   },
-  "statusMsgRecordingStopped": {
+  "STATUS_MSG_RECORDING_STOPPED": {
     "message": "S'ha aturat la gravació",
     "description": "Status message for spoken feedback when video recording has been stopped."
   },
-  "statusMsgCameraSwitched": {
+  "STATUS_MSG_CAMERA_SWITCHED": {
     "message": "Càmera $camera$ activada",
     "description": "Status message for spoken feedback when switching over to another camera.",
     "placeholders": {
@@ -55,131 +55,131 @@
       }
     }
   },
-  "galleryButton": {
+  "GALLERY_BUTTON": {
     "message": "Ves a la galeria",
     "description": "Label for the gallery button."
   },
-  "deleteButton": {
+  "DELETE_BUTTON": {
     "message": "Suprimeix",
     "description": "Label for the delete button."
   },
-  "exportButton": {
+  "EXPORT_BUTTON": {
     "message": "Exporta al disc",
     "description": "Label for the exporting button."
   },
-  "printButton": {
+  "PRINT_BUTTON": {
     "message": "Imprimeix",
     "description": "Label for the printing button."
   },
-  "backButton": {
+  "BACK_BUTTON": {
     "message": "Torna",
     "description": "Label for the back button."
   },
-  "galleryImages": {
+  "GALLERY_IMAGES": {
     "message": "Imatges de la galeria",
     "description": "Text to speech label for the gallery list."
   },
-  "settingsButton": {
+  "SETTINGS_BUTTON": {
     "message": "Configuració",
     "description": "Label for the settings button."
   },
-  "gridTypeButton": {
+  "GRID_TYPE_BUTTON": {
     "message": "Tipus de quadrícula",
     "description": "Label for the button of grid-type options."
   },
-  "timerDurationButton": {
+  "TIMER_DURATION_BUTTON": {
     "message": "Durada del temporitzador",
     "description": "Label for the button of timer-duration options."
   },
-  "feedbackButton": {
+  "FEEDBACK_BUTTON": {
     "message": "Envia suggeriments",
     "description": "Label for the feedback button."
   },
-  "helpButton": {
+  "HELP_BUTTON": {
     "message": "Ajuda",
     "description": "Label for the help button."
   },
-  "labelGrid3x3": {
+  "LABEL_GRID_3X3": {
     "message": "3 x 3",
     "description": "Label for for grid-type: 3x3."
   },
-  "ariaGrid3x3": {
+  "ARIA_GRID_3X3": {
     "message": "3 per 3",
     "description": "Label for spoken feedback to read out grid-type: 3x3."
   },
-  "labelGrid4x4": {
+  "LABEL_GRID_4X4": {
     "message": "4 x 4",
     "description": "Label for for grid-type: 4x4."
   },
-  "ariaGrid4x4": {
+  "ARIA_GRID_4X4": {
     "message": "4 per 4",
     "description": "Label for spoken feedback to read out grid-type: 4x4."
   },
-  "labelGridGolden": {
+  "LABEL_GRID_GOLDEN": {
     "message": "Proporció àuria",
     "description": "Label for grid-type: golden ratio."
   },
-  "labelTimer3s": {
+  "LABEL_TIMER_3S": {
     "message": "3 segons",
     "description": "Label for timer-duration: 3 seconds."
   },
-  "labelTimer10s": {
+  "LABEL_TIMER_10S": {
     "message": "10 segons",
     "description": "Label for timer-duration: 10 seconds."
   },
-  "takePhotoButton": {
+  "TAKE_PHOTO_BUTTON": {
     "message": "Fes una foto",
     "description": "Label for the shutter button to take photo."
   },
-  "takePhotoCancelButton": {
+  "TAKE_PHOTO_CANCEL_BUTTON": {
     "message": "No facis la foto",
     "description": "Label for the shutter button to cancel countdown timer and stop taking photo."
   },
-  "recordVideoStartButton": {
+  "RECORD_VIDEO_START_BUTTON": {
     "message": "Comença a gravar",
     "description": "Label for the shutter button to start recording."
   },
-  "recordVideoStopButton": {
+  "RECORD_VIDEO_STOP_BUTTON": {
     "message": "Atura la gravació",
     "description": "Label for the shutter button to stop recording."
   },
-  "switchCameraButton": {
+  "SWITCH_CAMERA_BUTTON": {
     "message": "Canvia a la càmera següent",
     "description": "Label for the button to switch to next connected camera. Eg. switching from front facing to back facing, or a camera connected via USB. The button is shown only when more than one camera is connected."
   },
-  "switchRecordVideoButton": {
+  "SWITCH_RECORD_VIDEO_BUTTON": {
     "message": "Canvia al mode per gravar vídeo",
     "description": "Label for the button to switch to record video mode."
   },
-  "switchTakePhotoButton": {
+  "SWITCH_TAKE_PHOTO_BUTTON": {
     "message": "Canvia al mode per fer fotos",
     "description": "Label for the button to switch to take photo mode."
   },
-  "toggleTimerButton": {
+  "TOGGLE_TIMER_BUTTON": {
     "message": "Temporitzador",
     "description": "Label for the checkbox to toggle the countdown timer."
   },
-  "toggleMirrorButton": {
+  "TOGGLE_MIRROR_BUTTON": {
     "message": "Rèplica",
     "description": "Label for the checkbox to toggle the preview mirroring. Eg. if mirroring is toggled on, preview will be flipped horizontally."
   },
-  "toggleGridButton": {
+  "TOGGLE_GRID_BUTTON": {
     "message": "Quadrícula",
     "description": "Label for the checkbox to toggle the grid shown on preview."
   },
-  "toggleMicButton": {
+  "TOGGLE_MIC_BUTTON": {
     "message": "Micròfon",
     "description": "Label for the checkbox to toggle the microphone for recording video."
   },
-  "dialogOKButton": {
+  "DIALOG_OK_BUTTON": {
     "message": "D'acord",
     "description": "Label for the accepting button in the dialog."
   },
-  "dialogCancelButton": {
+  "DIALOG_CANCEL_BUTTON": {
     "message": "Cancel·la",
     "description": "Label for the dismissing button in the dialog."
   },
-  "deleteConfirmationMsg": {
+  "DELETE_CONFIRMATION_MSG": {
     "message": "Confirmes que vols suprimir el fitxer $file$?",
     "description": "Confirmation message before removing a selected item from the gallery. Expects a file name to be passed in.",
     "placeholders": {
@@ -189,7 +189,7 @@
       }
     }
   },
-  "deleteMultiConfirmationMsg": {
+  "DELETE_MULTI_CONFIRMATION_MSG": {
     "message": "Confirmes que vols suprimir $count$ elements?",
     "description": "Confirmation message before removing multiple selected items from the gallery. Expects a file count to be passed in.",
     "placeholders": {
@@ -199,7 +199,7 @@
       }
     }
   },
-  "migratePicturesMsg": {
+  "MIGRATE_PICTURES_MSG": {
     "message": "Les fotos i els vídeos que es facin amb la càmera es mouran a la carpeta Baixades. Pots accedir-hi des de Fitxers.\n\nLes aplicacions amb permisos d'emmagatzematge tindran accés a les fotos i als vídeos.",
     "description": "Message shown before moving all photos and videos stored in the Camera App to the Downloads folder."
   }
diff --git a/chrome/browser/resources/chromeos/camera/src/_locales/cs/messages.json b/chrome/browser/resources/chromeos/camera/src/_locales/cs/messages.json
index c5bd4ff..cc86309 100644
--- a/chrome/browser/resources/chromeos/camera/src/_locales/cs/messages.json
+++ b/chrome/browser/resources/chromeos/camera/src/_locales/cs/messages.json
@@ -1,21 +1,21 @@
 {
-  "name": {
+  "NAME": {
     "message": "Fotoaparát",
     "description": "Name of the Camera App."
   },
-  "description": {
+  "DESCRIPTION": {
     "message": "Foťte a nahrávejte videa pomocí fotoaparátu.",
     "description": "Short description of the Camera App."
   },
-  "errorMsgFileSystemFailed": {
+  "ERROR_MSG_FILE_SYSTEM_FAILED": {
     "message": "Chyby systému souborů.",
     "description": "Error message shown when failing to read or write the file system."
   },
-  "errorMsgNoCamera": {
+  "ERROR_MSG_NO_CAMERA": {
     "message": "Fotoaparát momentálně není dostupný.\nZkontrolujte, zda je fotoaparát správně připojen.",
     "description": "Error message shown when it was impossible to connect to the camera due to unavailability."
   },
-  "errorMsgGalleryExportFailed": {
+  "ERROR_MSG_GALLERY_EXPORT_FAILED": {
     "message": "Soubor $file$ se nepodařilo exportovat",
     "description": "Error message shown when exporting to an external directory failed. Expects a file name to be passed in.",
     "placeholders": {
@@ -25,27 +25,27 @@
       }
     }
   },
-  "errorMsgSaveFileFailed": {
+  "ERROR_MSG_SAVE_FILE_FAILED": {
     "message": "Soubor se nepodařilo uložit",
     "description": "Error message shown when saving/adding a image or video to the file system failed."
   },
-  "errorMsgTakePhotoFailed": {
+  "ERROR_MSG_TAKE_PHOTO_FAILED": {
     "message": "Fotku se nepodařilo pořídit",
     "description": "Error message shown when failing to take photo."
   },
-  "errorMsgRecordStartFailed": {
+  "ERROR_MSG_RECORD_START_FAILED": {
     "message": "Nahrávání se nepodařilo zahájit",
     "description": "Error message shown when failing to start recording video."
   },
-  "errorMsgEmptyRecording": {
+  "ERROR_MSG_EMPTY_RECORDING": {
     "message": "Nic nebylo zaznamenáno",
     "description": "Error message shown when no data is recorded for a recording and it won't be added to the gallery."
   },
-  "statusMsgRecordingStopped": {
+  "STATUS_MSG_RECORDING_STOPPED": {
     "message": "Nahrávání bylo zastaveno",
     "description": "Status message for spoken feedback when video recording has been stopped."
   },
-  "statusMsgCameraSwitched": {
+  "STATUS_MSG_CAMERA_SWITCHED": {
     "message": "$camera$ je aktivní",
     "description": "Status message for spoken feedback when switching over to another camera.",
     "placeholders": {
@@ -55,131 +55,131 @@
       }
     }
   },
-  "galleryButton": {
+  "GALLERY_BUTTON": {
     "message": "Přejít do galerie",
     "description": "Label for the gallery button."
   },
-  "deleteButton": {
+  "DELETE_BUTTON": {
     "message": "Smazat",
     "description": "Label for the delete button."
   },
-  "exportButton": {
+  "EXPORT_BUTTON": {
     "message": "Exportovat na disk",
     "description": "Label for the exporting button."
   },
-  "printButton": {
+  "PRINT_BUTTON": {
     "message": "Tisknout",
     "description": "Label for the printing button."
   },
-  "backButton": {
+  "BACK_BUTTON": {
     "message": "Zpět",
     "description": "Label for the back button."
   },
-  "galleryImages": {
+  "GALLERY_IMAGES": {
     "message": "Obrázky v galerii",
     "description": "Text to speech label for the gallery list."
   },
-  "settingsButton": {
+  "SETTINGS_BUTTON": {
     "message": "Nastavení",
     "description": "Label for the settings button."
   },
-  "gridTypeButton": {
+  "GRID_TYPE_BUTTON": {
     "message": "Typ mřížky",
     "description": "Label for the button of grid-type options."
   },
-  "timerDurationButton": {
+  "TIMER_DURATION_BUTTON": {
     "message": "Trvání časovače",
     "description": "Label for the button of timer-duration options."
   },
-  "feedbackButton": {
+  "FEEDBACK_BUTTON": {
     "message": "Odeslat zpětnou vazbu",
     "description": "Label for the feedback button."
   },
-  "helpButton": {
+  "HELP_BUTTON": {
     "message": "Nápověda",
     "description": "Label for the help button."
   },
-  "labelGrid3x3": {
+  "LABEL_GRID_3X3": {
     "message": "3 × 3",
     "description": "Label for for grid-type: 3x3."
   },
-  "ariaGrid3x3": {
+  "ARIA_GRID_3X3": {
     "message": "3 krát 3",
     "description": "Label for spoken feedback to read out grid-type: 3x3."
   },
-  "labelGrid4x4": {
+  "LABEL_GRID_4X4": {
     "message": "4 × 4",
     "description": "Label for for grid-type: 4x4."
   },
-  "ariaGrid4x4": {
+  "ARIA_GRID_4X4": {
     "message": "4 krát 4",
     "description": "Label for spoken feedback to read out grid-type: 4x4."
   },
-  "labelGridGolden": {
+  "LABEL_GRID_GOLDEN": {
     "message": "Zlatý řez",
     "description": "Label for grid-type: golden ratio."
   },
-  "labelTimer3s": {
+  "LABEL_TIMER_3S": {
     "message": "3 sekundy",
     "description": "Label for timer-duration: 3 seconds."
   },
-  "labelTimer10s": {
+  "LABEL_TIMER_10S": {
     "message": "10 sekund",
     "description": "Label for timer-duration: 10 seconds."
   },
-  "takePhotoButton": {
+  "TAKE_PHOTO_BUTTON": {
     "message": "Vyfotit",
     "description": "Label for the shutter button to take photo."
   },
-  "takePhotoCancelButton": {
+  "TAKE_PHOTO_CANCEL_BUTTON": {
     "message": "Zastavit focení",
     "description": "Label for the shutter button to cancel countdown timer and stop taking photo."
   },
-  "recordVideoStartButton": {
+  "RECORD_VIDEO_START_BUTTON": {
     "message": "Zahájit nahrávání",
     "description": "Label for the shutter button to start recording."
   },
-  "recordVideoStopButton": {
+  "RECORD_VIDEO_STOP_BUTTON": {
     "message": "Zastavit nahrávání",
     "description": "Label for the shutter button to stop recording."
   },
-  "switchCameraButton": {
+  "SWITCH_CAMERA_BUTTON": {
     "message": "Přepnout na další fotoaparát",
     "description": "Label for the button to switch to next connected camera. Eg. switching from front facing to back facing, or a camera connected via USB. The button is shown only when more than one camera is connected."
   },
-  "switchRecordVideoButton": {
+  "SWITCH_RECORD_VIDEO_BUTTON": {
     "message": "Přepnout na záznam videa",
     "description": "Label for the button to switch to record video mode."
   },
-  "switchTakePhotoButton": {
+  "SWITCH_TAKE_PHOTO_BUTTON": {
     "message": "Přepnout na focení",
     "description": "Label for the button to switch to take photo mode."
   },
-  "toggleTimerButton": {
+  "TOGGLE_TIMER_BUTTON": {
     "message": "Časovač",
     "description": "Label for the checkbox to toggle the countdown timer."
   },
-  "toggleMirrorButton": {
+  "TOGGLE_MIRROR_BUTTON": {
     "message": "Zrcadlení",
     "description": "Label for the checkbox to toggle the preview mirroring. Eg. if mirroring is toggled on, preview will be flipped horizontally."
   },
-  "toggleGridButton": {
+  "TOGGLE_GRID_BUTTON": {
     "message": "Mřížka",
     "description": "Label for the checkbox to toggle the grid shown on preview."
   },
-  "toggleMicButton": {
+  "TOGGLE_MIC_BUTTON": {
     "message": "Mikrofon",
     "description": "Label for the checkbox to toggle the microphone for recording video."
   },
-  "dialogOKButton": {
+  "DIALOG_OK_BUTTON": {
     "message": "OK",
     "description": "Label for the accepting button in the dialog."
   },
-  "dialogCancelButton": {
+  "DIALOG_CANCEL_BUTTON": {
     "message": "Zrušit",
     "description": "Label for the dismissing button in the dialog."
   },
-  "deleteConfirmationMsg": {
+  "DELETE_CONFIRMATION_MSG": {
     "message": "Opravdu chcete soubor $file$ odstranit?",
     "description": "Confirmation message before removing a selected item from the gallery. Expects a file name to be passed in.",
     "placeholders": {
@@ -189,7 +189,7 @@
       }
     }
   },
-  "deleteMultiConfirmationMsg": {
+  "DELETE_MULTI_CONFIRMATION_MSG": {
     "message": "Opravdu chcete tyto položky ($count$) odstranit?",
     "description": "Confirmation message before removing multiple selected items from the gallery. Expects a file count to be passed in.",
     "placeholders": {
@@ -199,7 +199,7 @@
       }
     }
   },
-  "migratePicturesMsg": {
+  "MIGRATE_PICTURES_MSG": {
     "message": "Fotky a videa pořízená fotoaparátem se přesunou do složky stažených souborů. Najdete je v aplikaci Soubory.\n\nK vašim fotkám a videím budou mít přístup aplikace s oprávněním k úložišti.",
     "description": "Message shown before moving all photos and videos stored in the Camera App to the Downloads folder."
   }
diff --git a/chrome/browser/resources/chromeos/camera/src/_locales/da/messages.json b/chrome/browser/resources/chromeos/camera/src/_locales/da/messages.json
index cbe678a..8917dcd0 100644
--- a/chrome/browser/resources/chromeos/camera/src/_locales/da/messages.json
+++ b/chrome/browser/resources/chromeos/camera/src/_locales/da/messages.json
@@ -1,21 +1,21 @@
 {
-  "name": {
+  "NAME": {
     "message": "Kamera",
     "description": "Name of the Camera App."
   },
-  "description": {
+  "DESCRIPTION": {
     "message": "Tag billeder, og optag videoer med dit kamera.",
     "description": "Short description of the Camera App."
   },
-  "errorMsgFileSystemFailed": {
+  "ERROR_MSG_FILE_SYSTEM_FAILED": {
     "message": "Der er opstået fejl i filsystemet.",
     "description": "Error message shown when failing to read or write the file system."
   },
-  "errorMsgNoCamera": {
+  "ERROR_MSG_NO_CAMERA": {
     "message": "Dit kamera er i øjeblikket utilgængeligt.\nTjek, om kameraet er tilsluttet korrekt.",
     "description": "Error message shown when it was impossible to connect to the camera due to unavailability."
   },
-  "errorMsgGalleryExportFailed": {
+  "ERROR_MSG_GALLERY_EXPORT_FAILED": {
     "message": "$file$ kan ikke eksporteres",
     "description": "Error message shown when exporting to an external directory failed. Expects a file name to be passed in.",
     "placeholders": {
@@ -25,27 +25,27 @@
       }
     }
   },
-  "errorMsgSaveFileFailed": {
+  "ERROR_MSG_SAVE_FILE_FAILED": {
     "message": "Filen kan ikke gemmes",
     "description": "Error message shown when saving/adding a image or video to the file system failed."
   },
-  "errorMsgTakePhotoFailed": {
+  "ERROR_MSG_TAKE_PHOTO_FAILED": {
     "message": "Det er ikke muligt at tage billeder",
     "description": "Error message shown when failing to take photo."
   },
-  "errorMsgRecordStartFailed": {
+  "ERROR_MSG_RECORD_START_FAILED": {
     "message": "Det er ikke muligt at starte en optagelse",
     "description": "Error message shown when failing to start recording video."
   },
-  "errorMsgEmptyRecording": {
+  "ERROR_MSG_EMPTY_RECORDING": {
     "message": "Der er ingen optagelser",
     "description": "Error message shown when no data is recorded for a recording and it won't be added to the gallery."
   },
-  "statusMsgRecordingStopped": {
+  "STATUS_MSG_RECORDING_STOPPED": {
     "message": "Optagelsen er stoppet",
     "description": "Status message for spoken feedback when video recording has been stopped."
   },
-  "statusMsgCameraSwitched": {
+  "STATUS_MSG_CAMERA_SWITCHED": {
     "message": "$camera$ er aktivt",
     "description": "Status message for spoken feedback when switching over to another camera.",
     "placeholders": {
@@ -55,131 +55,131 @@
       }
     }
   },
-  "galleryButton": {
+  "GALLERY_BUTTON": {
     "message": "Gå til galleri",
     "description": "Label for the gallery button."
   },
-  "deleteButton": {
+  "DELETE_BUTTON": {
     "message": "Slet",
     "description": "Label for the delete button."
   },
-  "exportButton": {
+  "EXPORT_BUTTON": {
     "message": "Eksportér til disk",
     "description": "Label for the exporting button."
   },
-  "printButton": {
+  "PRINT_BUTTON": {
     "message": "Udskriv",
     "description": "Label for the printing button."
   },
-  "backButton": {
+  "BACK_BUTTON": {
     "message": "Gå tilbage",
     "description": "Label for the back button."
   },
-  "galleryImages": {
+  "GALLERY_IMAGES": {
     "message": "Galleribilleder",
     "description": "Text to speech label for the gallery list."
   },
-  "settingsButton": {
+  "SETTINGS_BUTTON": {
     "message": "Indstillinger",
     "description": "Label for the settings button."
   },
-  "gridTypeButton": {
+  "GRID_TYPE_BUTTON": {
     "message": "Gittertype",
     "description": "Label for the button of grid-type options."
   },
-  "timerDurationButton": {
+  "TIMER_DURATION_BUTTON": {
     "message": "Varighed for timer",
     "description": "Label for the button of timer-duration options."
   },
-  "feedbackButton": {
+  "FEEDBACK_BUTTON": {
     "message": "Giv feedback",
     "description": "Label for the feedback button."
   },
-  "helpButton": {
+  "HELP_BUTTON": {
     "message": "Hjælp",
     "description": "Label for the help button."
   },
-  "labelGrid3x3": {
+  "LABEL_GRID_3X3": {
     "message": "3x3",
     "description": "Label for for grid-type: 3x3."
   },
-  "ariaGrid3x3": {
+  "ARIA_GRID_3X3": {
     "message": "3 gange 3",
     "description": "Label for spoken feedback to read out grid-type: 3x3."
   },
-  "labelGrid4x4": {
+  "LABEL_GRID_4X4": {
     "message": "4x4",
     "description": "Label for for grid-type: 4x4."
   },
-  "ariaGrid4x4": {
+  "ARIA_GRID_4X4": {
     "message": "4 gange 4",
     "description": "Label for spoken feedback to read out grid-type: 4x4."
   },
-  "labelGridGolden": {
+  "LABEL_GRID_GOLDEN": {
     "message": "Det gyldne snit",
     "description": "Label for grid-type: golden ratio."
   },
-  "labelTimer3s": {
+  "LABEL_TIMER_3S": {
     "message": "3 sekunder",
     "description": "Label for timer-duration: 3 seconds."
   },
-  "labelTimer10s": {
+  "LABEL_TIMER_10S": {
     "message": "10 sekunder",
     "description": "Label for timer-duration: 10 seconds."
   },
-  "takePhotoButton": {
+  "TAKE_PHOTO_BUTTON": {
     "message": "Tag billede",
     "description": "Label for the shutter button to take photo."
   },
-  "takePhotoCancelButton": {
+  "TAKE_PHOTO_CANCEL_BUTTON": {
     "message": "Stop med at tage billedet",
     "description": "Label for the shutter button to cancel countdown timer and stop taking photo."
   },
-  "recordVideoStartButton": {
+  "RECORD_VIDEO_START_BUTTON": {
     "message": "Start optagelse",
     "description": "Label for the shutter button to start recording."
   },
-  "recordVideoStopButton": {
+  "RECORD_VIDEO_STOP_BUTTON": {
     "message": "Stop optagelse",
     "description": "Label for the shutter button to stop recording."
   },
-  "switchCameraButton": {
+  "SWITCH_CAMERA_BUTTON": {
     "message": "Skift til næste kamera",
     "description": "Label for the button to switch to next connected camera. Eg. switching from front facing to back facing, or a camera connected via USB. The button is shown only when more than one camera is connected."
   },
-  "switchRecordVideoButton": {
+  "SWITCH_RECORD_VIDEO_BUTTON": {
     "message": "Skift til videooptagelse",
     "description": "Label for the button to switch to record video mode."
   },
-  "switchTakePhotoButton": {
+  "SWITCH_TAKE_PHOTO_BUTTON": {
     "message": "Skift til billedtilstand",
     "description": "Label for the button to switch to take photo mode."
   },
-  "toggleTimerButton": {
+  "TOGGLE_TIMER_BUTTON": {
     "message": "Timer",
     "description": "Label for the checkbox to toggle the countdown timer."
   },
-  "toggleMirrorButton": {
+  "TOGGLE_MIRROR_BUTTON": {
     "message": "Spejling",
     "description": "Label for the checkbox to toggle the preview mirroring. Eg. if mirroring is toggled on, preview will be flipped horizontally."
   },
-  "toggleGridButton": {
+  "TOGGLE_GRID_BUTTON": {
     "message": "Gitter",
     "description": "Label for the checkbox to toggle the grid shown on preview."
   },
-  "toggleMicButton": {
+  "TOGGLE_MIC_BUTTON": {
     "message": "Mikrofon",
     "description": "Label for the checkbox to toggle the microphone for recording video."
   },
-  "dialogOKButton": {
+  "DIALOG_OK_BUTTON": {
     "message": "OK",
     "description": "Label for the accepting button in the dialog."
   },
-  "dialogCancelButton": {
+  "DIALOG_CANCEL_BUTTON": {
     "message": "Annuller",
     "description": "Label for the dismissing button in the dialog."
   },
-  "deleteConfirmationMsg": {
+  "DELETE_CONFIRMATION_MSG": {
     "message": "Er du sikker på, at du vil fjerne $file$?",
     "description": "Confirmation message before removing a selected item from the gallery. Expects a file name to be passed in.",
     "placeholders": {
@@ -189,7 +189,7 @@
       }
     }
   },
-  "deleteMultiConfirmationMsg": {
+  "DELETE_MULTI_CONFIRMATION_MSG": {
     "message": "Er du sikker på, at du vil fjerne $count$ elementer?",
     "description": "Confirmation message before removing multiple selected items from the gallery. Expects a file count to be passed in.",
     "placeholders": {
@@ -199,7 +199,7 @@
       }
     }
   },
-  "migratePicturesMsg": {
+  "MIGRATE_PICTURES_MSG": {
     "message": "Billeder og videoer, der er taget med kameraet, flyttes til mappen Downloads. Du kan finde dem under Filer.\n\nApps med lagertilladelser vil have adgang til dine billeder og videoer.",
     "description": "Message shown before moving all photos and videos stored in the Camera App to the Downloads folder."
   }
diff --git a/chrome/browser/resources/chromeos/camera/src/_locales/de/messages.json b/chrome/browser/resources/chromeos/camera/src/_locales/de/messages.json
index e861ad30..ca71f64b 100644
--- a/chrome/browser/resources/chromeos/camera/src/_locales/de/messages.json
+++ b/chrome/browser/resources/chromeos/camera/src/_locales/de/messages.json
@@ -1,21 +1,21 @@
 {
-  "name": {
+  "NAME": {
     "message": "Kamera",
     "description": "Name of the Camera App."
   },
-  "description": {
+  "DESCRIPTION": {
     "message": "Nehmen Sie Fotos und Videos mit Ihrer Kamera auf.",
     "description": "Short description of the Camera App."
   },
-  "errorMsgFileSystemFailed": {
+  "ERROR_MSG_FILE_SYSTEM_FAILED": {
     "message": "Fehler im Dateisystem.",
     "description": "Error message shown when failing to read or write the file system."
   },
-  "errorMsgNoCamera": {
+  "ERROR_MSG_NO_CAMERA": {
     "message": "Ihre Kamera ist derzeit nicht verfügbar.\nÜberprüfen Sie bitte, ob die Kamera richtig verbunden ist.",
     "description": "Error message shown when it was impossible to connect to the camera due to unavailability."
   },
-  "errorMsgGalleryExportFailed": {
+  "ERROR_MSG_GALLERY_EXPORT_FAILED": {
     "message": "$file$ konnte nicht exportiert werden",
     "description": "Error message shown when exporting to an external directory failed. Expects a file name to be passed in.",
     "placeholders": {
@@ -25,27 +25,27 @@
       }
     }
   },
-  "errorMsgSaveFileFailed": {
+  "ERROR_MSG_SAVE_FILE_FAILED": {
     "message": "Datei konnte nicht gespeichert werden",
     "description": "Error message shown when saving/adding a image or video to the file system failed."
   },
-  "errorMsgTakePhotoFailed": {
+  "ERROR_MSG_TAKE_PHOTO_FAILED": {
     "message": "Foto konnte nicht aufgenommen werden",
     "description": "Error message shown when failing to take photo."
   },
-  "errorMsgRecordStartFailed": {
+  "ERROR_MSG_RECORD_START_FAILED": {
     "message": "Videoaufnahme konnte nicht gestartet werden",
     "description": "Error message shown when failing to start recording video."
   },
-  "errorMsgEmptyRecording": {
+  "ERROR_MSG_EMPTY_RECORDING": {
     "message": "Keine Aufzeichnung",
     "description": "Error message shown when no data is recorded for a recording and it won't be added to the gallery."
   },
-  "statusMsgRecordingStopped": {
+  "STATUS_MSG_RECORDING_STOPPED": {
     "message": "Aufzeichnung wurde beendet",
     "description": "Status message for spoken feedback when video recording has been stopped."
   },
-  "statusMsgCameraSwitched": {
+  "STATUS_MSG_CAMERA_SWITCHED": {
     "message": "$camera$ aktiv",
     "description": "Status message for spoken feedback when switching over to another camera.",
     "placeholders": {
@@ -55,131 +55,131 @@
       }
     }
   },
-  "galleryButton": {
+  "GALLERY_BUTTON": {
     "message": "Zur Galerie",
     "description": "Label for the gallery button."
   },
-  "deleteButton": {
+  "DELETE_BUTTON": {
     "message": "Löschen",
     "description": "Label for the delete button."
   },
-  "exportButton": {
+  "EXPORT_BUTTON": {
     "message": "Auf Festplatte exportieren",
     "description": "Label for the exporting button."
   },
-  "printButton": {
+  "PRINT_BUTTON": {
     "message": "Drucken",
     "description": "Label for the printing button."
   },
-  "backButton": {
+  "BACK_BUTTON": {
     "message": "Zurück",
     "description": "Label for the back button."
   },
-  "galleryImages": {
+  "GALLERY_IMAGES": {
     "message": "Galeriebilder",
     "description": "Text to speech label for the gallery list."
   },
-  "settingsButton": {
+  "SETTINGS_BUTTON": {
     "message": "Einstellungen",
     "description": "Label for the settings button."
   },
-  "gridTypeButton": {
+  "GRID_TYPE_BUTTON": {
     "message": "Rastertyp",
     "description": "Label for the button of grid-type options."
   },
-  "timerDurationButton": {
+  "TIMER_DURATION_BUTTON": {
     "message": "Timerdauer",
     "description": "Label for the button of timer-duration options."
   },
-  "feedbackButton": {
+  "FEEDBACK_BUTTON": {
     "message": "Feedback geben",
     "description": "Label for the feedback button."
   },
-  "helpButton": {
+  "HELP_BUTTON": {
     "message": "Hilfe",
     "description": "Label for the help button."
   },
-  "labelGrid3x3": {
+  "LABEL_GRID_3X3": {
     "message": "3 x 3",
     "description": "Label for for grid-type: 3x3."
   },
-  "ariaGrid3x3": {
+  "ARIA_GRID_3X3": {
     "message": "3 mal 3",
     "description": "Label for spoken feedback to read out grid-type: 3x3."
   },
-  "labelGrid4x4": {
+  "LABEL_GRID_4X4": {
     "message": "4 x 4",
     "description": "Label for for grid-type: 4x4."
   },
-  "ariaGrid4x4": {
+  "ARIA_GRID_4X4": {
     "message": "4 mal 4",
     "description": "Label for spoken feedback to read out grid-type: 4x4."
   },
-  "labelGridGolden": {
+  "LABEL_GRID_GOLDEN": {
     "message": "Goldener Schnitt",
     "description": "Label for grid-type: golden ratio."
   },
-  "labelTimer3s": {
+  "LABEL_TIMER_3S": {
     "message": "3 Sekunden",
     "description": "Label for timer-duration: 3 seconds."
   },
-  "labelTimer10s": {
+  "LABEL_TIMER_10S": {
     "message": "10 Sekunden",
     "description": "Label for timer-duration: 10 seconds."
   },
-  "takePhotoButton": {
+  "TAKE_PHOTO_BUTTON": {
     "message": "Foto aufnehmen",
     "description": "Label for the shutter button to take photo."
   },
-  "takePhotoCancelButton": {
+  "TAKE_PHOTO_CANCEL_BUTTON": {
     "message": "Fotoaufnahme beenden",
     "description": "Label for the shutter button to cancel countdown timer and stop taking photo."
   },
-  "recordVideoStartButton": {
+  "RECORD_VIDEO_START_BUTTON": {
     "message": "Video aufnehmen",
     "description": "Label for the shutter button to start recording."
   },
-  "recordVideoStopButton": {
+  "RECORD_VIDEO_STOP_BUTTON": {
     "message": "Videoaufnahme beenden",
     "description": "Label for the shutter button to stop recording."
   },
-  "switchCameraButton": {
+  "SWITCH_CAMERA_BUTTON": {
     "message": "Zur nächsten Kamera wechseln",
     "description": "Label for the button to switch to next connected camera. Eg. switching from front facing to back facing, or a camera connected via USB. The button is shown only when more than one camera is connected."
   },
-  "switchRecordVideoButton": {
+  "SWITCH_RECORD_VIDEO_BUTTON": {
     "message": "Zu Videomodus wechseln",
     "description": "Label for the button to switch to record video mode."
   },
-  "switchTakePhotoButton": {
+  "SWITCH_TAKE_PHOTO_BUTTON": {
     "message": "Zu Fotomodus wechseln",
     "description": "Label for the button to switch to take photo mode."
   },
-  "toggleTimerButton": {
+  "TOGGLE_TIMER_BUTTON": {
     "message": "Timer",
     "description": "Label for the checkbox to toggle the countdown timer."
   },
-  "toggleMirrorButton": {
+  "TOGGLE_MIRROR_BUTTON": {
     "message": "Spiegeln",
     "description": "Label for the checkbox to toggle the preview mirroring. Eg. if mirroring is toggled on, preview will be flipped horizontally."
   },
-  "toggleGridButton": {
+  "TOGGLE_GRID_BUTTON": {
     "message": "Raster",
     "description": "Label for the checkbox to toggle the grid shown on preview."
   },
-  "toggleMicButton": {
+  "TOGGLE_MIC_BUTTON": {
     "message": "Mikrofon",
     "description": "Label for the checkbox to toggle the microphone for recording video."
   },
-  "dialogOKButton": {
+  "DIALOG_OK_BUTTON": {
     "message": "OK",
     "description": "Label for the accepting button in the dialog."
   },
-  "dialogCancelButton": {
+  "DIALOG_CANCEL_BUTTON": {
     "message": "Abbrechen",
     "description": "Label for the dismissing button in the dialog."
   },
-  "deleteConfirmationMsg": {
+  "DELETE_CONFIRMATION_MSG": {
     "message": "Möchten Sie \"$file$\" wirklich entfernen?",
     "description": "Confirmation message before removing a selected item from the gallery. Expects a file name to be passed in.",
     "placeholders": {
@@ -189,7 +189,7 @@
       }
     }
   },
-  "deleteMultiConfirmationMsg": {
+  "DELETE_MULTI_CONFIRMATION_MSG": {
     "message": "Möchten Sie $count$ Elemente wirklich entfernen?",
     "description": "Confirmation message before removing multiple selected items from the gallery. Expects a file count to be passed in.",
     "placeholders": {
@@ -199,7 +199,7 @@
       }
     }
   },
-  "migratePicturesMsg": {
+  "MIGRATE_PICTURES_MSG": {
     "message": "Mit der Kamera aufgenommene Fotos und Videos werden in den Ordner \"Downloads\" verschoben. Sie können sie in der App \"Dateien\" ansehen.\n\nApps mit Speicherberechtigungen haben Zugriff auf Ihre Fotos und Videos.",
     "description": "Message shown before moving all photos and videos stored in the Camera App to the Downloads folder."
   }
diff --git a/chrome/browser/resources/chromeos/camera/src/_locales/el/messages.json b/chrome/browser/resources/chromeos/camera/src/_locales/el/messages.json
index 87f1866b..fb0c3d6 100644
--- a/chrome/browser/resources/chromeos/camera/src/_locales/el/messages.json
+++ b/chrome/browser/resources/chromeos/camera/src/_locales/el/messages.json
@@ -1,21 +1,21 @@
 {
-  "name": {
+  "NAME": {
     "message": "Κάμερα",
     "description": "Name of the Camera App."
   },
-  "description": {
+  "DESCRIPTION": {
     "message": "Τραβήξτε φωτογραφίες και βίντεο με την κάμερά σας.",
     "description": "Short description of the Camera App."
   },
-  "errorMsgFileSystemFailed": {
+  "ERROR_MSG_FILE_SYSTEM_FAILED": {
     "message": "Αρχειοθετήστε σφάλματα συστήματος.",
     "description": "Error message shown when failing to read or write the file system."
   },
-  "errorMsgNoCamera": {
+  "ERROR_MSG_NO_CAMERA": {
     "message": "Η κάμερά σας δεν είναι διαθέσιμη προς το παρόν.\nΕλέγξτε αν η κάμερα έχει συνδεθεί σωστά.",
     "description": "Error message shown when it was impossible to connect to the camera due to unavailability."
   },
-  "errorMsgGalleryExportFailed": {
+  "ERROR_MSG_GALLERY_EXPORT_FAILED": {
     "message": "Δεν είναι δυνατή η εξαγωγή του αρχείου $file$",
     "description": "Error message shown when exporting to an external directory failed. Expects a file name to be passed in.",
     "placeholders": {
@@ -25,27 +25,27 @@
       }
     }
   },
-  "errorMsgSaveFileFailed": {
+  "ERROR_MSG_SAVE_FILE_FAILED": {
     "message": "Δεν είναι δυνατή η αποθήκευση του αρχείου",
     "description": "Error message shown when saving/adding a image or video to the file system failed."
   },
-  "errorMsgTakePhotoFailed": {
+  "ERROR_MSG_TAKE_PHOTO_FAILED": {
     "message": "Δεν είναι δυνατή η λήψη φωτογραφίας",
     "description": "Error message shown when failing to take photo."
   },
-  "errorMsgRecordStartFailed": {
+  "ERROR_MSG_RECORD_START_FAILED": {
     "message": "Δεν είναι δυνατή η έναρξη της εγγραφής",
     "description": "Error message shown when failing to start recording video."
   },
-  "errorMsgEmptyRecording": {
+  "ERROR_MSG_EMPTY_RECORDING": {
     "message": "Καμία εγγραφή",
     "description": "Error message shown when no data is recorded for a recording and it won't be added to the gallery."
   },
-  "statusMsgRecordingStopped": {
+  "STATUS_MSG_RECORDING_STOPPED": {
     "message": "Η εγγραφή διακόπηκε",
     "description": "Status message for spoken feedback when video recording has been stopped."
   },
-  "statusMsgCameraSwitched": {
+  "STATUS_MSG_CAMERA_SWITCHED": {
     "message": "$camera$ ενεργή",
     "description": "Status message for spoken feedback when switching over to another camera.",
     "placeholders": {
@@ -55,131 +55,131 @@
       }
     }
   },
-  "galleryButton": {
+  "GALLERY_BUTTON": {
     "message": "Μετάβαση στο gallery",
     "description": "Label for the gallery button."
   },
-  "deleteButton": {
+  "DELETE_BUTTON": {
     "message": "Διαγραφή",
     "description": "Label for the delete button."
   },
-  "exportButton": {
+  "EXPORT_BUTTON": {
     "message": "Εξαγωγή σε δίσκο",
     "description": "Label for the exporting button."
   },
-  "printButton": {
+  "PRINT_BUTTON": {
     "message": "Εκτύπωση",
     "description": "Label for the printing button."
   },
-  "backButton": {
+  "BACK_BUTTON": {
     "message": "Πίσω",
     "description": "Label for the back button."
   },
-  "galleryImages": {
+  "GALLERY_IMAGES": {
     "message": "Εικόνες gallery",
     "description": "Text to speech label for the gallery list."
   },
-  "settingsButton": {
+  "SETTINGS_BUTTON": {
     "message": "Ρυθμίσεις",
     "description": "Label for the settings button."
   },
-  "gridTypeButton": {
+  "GRID_TYPE_BUTTON": {
     "message": "Τύπος πλέγματος",
     "description": "Label for the button of grid-type options."
   },
-  "timerDurationButton": {
+  "TIMER_DURATION_BUTTON": {
     "message": "Διάρκεια χρονομέτρου",
     "description": "Label for the button of timer-duration options."
   },
-  "feedbackButton": {
+  "FEEDBACK_BUTTON": {
     "message": "Αποστολή σχολίων",
     "description": "Label for the feedback button."
   },
-  "helpButton": {
+  "HELP_BUTTON": {
     "message": "Βοήθεια",
     "description": "Label for the help button."
   },
-  "labelGrid3x3": {
+  "LABEL_GRID_3X3": {
     "message": "3 x 3",
     "description": "Label for for grid-type: 3x3."
   },
-  "ariaGrid3x3": {
+  "ARIA_GRID_3X3": {
     "message": "3 x 3",
     "description": "Label for spoken feedback to read out grid-type: 3x3."
   },
-  "labelGrid4x4": {
+  "LABEL_GRID_4X4": {
     "message": "4 x 4",
     "description": "Label for for grid-type: 4x4."
   },
-  "ariaGrid4x4": {
+  "ARIA_GRID_4X4": {
     "message": "4 x 4",
     "description": "Label for spoken feedback to read out grid-type: 4x4."
   },
-  "labelGridGolden": {
+  "LABEL_GRID_GOLDEN": {
     "message": "Ιδανικός λόγος διαστάσεων",
     "description": "Label for grid-type: golden ratio."
   },
-  "labelTimer3s": {
+  "LABEL_TIMER_3S": {
     "message": "3 δευτερόλεπτα",
     "description": "Label for timer-duration: 3 seconds."
   },
-  "labelTimer10s": {
+  "LABEL_TIMER_10S": {
     "message": "10 δευτερόλεπτα",
     "description": "Label for timer-duration: 10 seconds."
   },
-  "takePhotoButton": {
+  "TAKE_PHOTO_BUTTON": {
     "message": "Λήψη φωτογραφίας",
     "description": "Label for the shutter button to take photo."
   },
-  "takePhotoCancelButton": {
+  "TAKE_PHOTO_CANCEL_BUTTON": {
     "message": "Διακοπή λήψης φωτογραφίας",
     "description": "Label for the shutter button to cancel countdown timer and stop taking photo."
   },
-  "recordVideoStartButton": {
+  "RECORD_VIDEO_START_BUTTON": {
     "message": "Έναρξη εγγραφής",
     "description": "Label for the shutter button to start recording."
   },
-  "recordVideoStopButton": {
+  "RECORD_VIDEO_STOP_BUTTON": {
     "message": "Διακοπή εγγραφής",
     "description": "Label for the shutter button to stop recording."
   },
-  "switchCameraButton": {
+  "SWITCH_CAMERA_BUTTON": {
     "message": "Μετάβαση στην επόμενη κάμερα",
     "description": "Label for the button to switch to next connected camera. Eg. switching from front facing to back facing, or a camera connected via USB. The button is shown only when more than one camera is connected."
   },
-  "switchRecordVideoButton": {
+  "SWITCH_RECORD_VIDEO_BUTTON": {
     "message": "Μετάβαση στη λειτουργία εγγραφής βίντεο",
     "description": "Label for the button to switch to record video mode."
   },
-  "switchTakePhotoButton": {
+  "SWITCH_TAKE_PHOTO_BUTTON": {
     "message": "Μετάβαση στη λειτουργία λήψης φωτογραφίας",
     "description": "Label for the button to switch to take photo mode."
   },
-  "toggleTimerButton": {
+  "TOGGLE_TIMER_BUTTON": {
     "message": "Χρονόμετρο",
     "description": "Label for the checkbox to toggle the countdown timer."
   },
-  "toggleMirrorButton": {
+  "TOGGLE_MIRROR_BUTTON": {
     "message": "Κατοπτρισμός",
     "description": "Label for the checkbox to toggle the preview mirroring. Eg. if mirroring is toggled on, preview will be flipped horizontally."
   },
-  "toggleGridButton": {
+  "TOGGLE_GRID_BUTTON": {
     "message": "Πλέγμα",
     "description": "Label for the checkbox to toggle the grid shown on preview."
   },
-  "toggleMicButton": {
+  "TOGGLE_MIC_BUTTON": {
     "message": "Μικρόφωνο",
     "description": "Label for the checkbox to toggle the microphone for recording video."
   },
-  "dialogOKButton": {
+  "DIALOG_OK_BUTTON": {
     "message": "ΟΚ",
     "description": "Label for the accepting button in the dialog."
   },
-  "dialogCancelButton": {
+  "DIALOG_CANCEL_BUTTON": {
     "message": "Ακύρωση",
     "description": "Label for the dismissing button in the dialog."
   },
-  "deleteConfirmationMsg": {
+  "DELETE_CONFIRMATION_MSG": {
     "message": "Είστε βέβαιοι ότι θέλετε να καταργήσετε το αρχείο $file$;",
     "description": "Confirmation message before removing a selected item from the gallery. Expects a file name to be passed in.",
     "placeholders": {
@@ -189,7 +189,7 @@
       }
     }
   },
-  "deleteMultiConfirmationMsg": {
+  "DELETE_MULTI_CONFIRMATION_MSG": {
     "message": "Είστε βέβαιοι ότι θέλετε να καταργήσετε $count$ στοιχεία;",
     "description": "Confirmation message before removing multiple selected items from the gallery. Expects a file count to be passed in.",
     "placeholders": {
@@ -199,7 +199,7 @@
       }
     }
   },
-  "migratePicturesMsg": {
+  "MIGRATE_PICTURES_MSG": {
     "message": "Οι φωτογραφίες και τα βίντεο που λήφθηκαν με την κάμερα θα μετακινηθούν στον φάκελο \"Λήψεις\". Μπορείτε να τα δείτε στα Αρχεία.\n\nΟι εφαρμογές με άδειες αποθηκευτικού χώρου θα έχουν πρόσβαση στις φωτογραφίες και τα βίντεό σας.",
     "description": "Message shown before moving all photos and videos stored in the Camera App to the Downloads folder."
   }
diff --git a/chrome/browser/resources/chromeos/camera/src/_locales/en/messages.json b/chrome/browser/resources/chromeos/camera/src/_locales/en/messages.json
index 6412f2d61..4e9f00a 100644
--- a/chrome/browser/resources/chromeos/camera/src/_locales/en/messages.json
+++ b/chrome/browser/resources/chromeos/camera/src/_locales/en/messages.json
@@ -1,21 +1,21 @@
 {
-  "name": {
+  "NAME": {
     "message": "Camera",
     "description": "Name of the Camera App."
   },
-  "description": {
+  "DESCRIPTION": {
     "message": "Take photos and record videos with your camera.",
     "description": "Short description of the Camera App."
   },
-  "errorMsgFileSystemFailed": {
+  "ERROR_MSG_FILE_SYSTEM_FAILED": {
     "message": "File system errors.",
     "description": "Error message shown when failing to read or write the file system."
   },
-  "errorMsgNoCamera": {
+  "ERROR_MSG_NO_CAMERA": {
     "message": "Your camera is currently unavailable.\nPlease check if the camera is properly connected.",
     "description": "Error message shown when it was impossible to connect to the camera due to unavailability."
   },
-  "errorMsgGalleryExportFailed": {
+  "ERROR_MSG_GALLERY_EXPORT_FAILED": {
     "message": "Unable to export $file$",
     "description": "Error message shown when exporting to an external directory failed. Expects a file name to be passed in.",
     "placeholders": {
@@ -25,27 +25,27 @@
       }
     }
   },
-  "errorMsgSaveFileFailed": {
+  "ERROR_MSG_SAVE_FILE_FAILED": {
     "message": "Unable to save the file",
     "description": "Error message shown when saving/adding a image or video to the file system failed."
   },
-  "errorMsgTakePhotoFailed": {
+  "ERROR_MSG_TAKE_PHOTO_FAILED": {
     "message": "Unable to take photo",
     "description": "Error message shown when failing to take photo."
   },
-  "errorMsgRecordStartFailed": {
+  "ERROR_MSG_RECORD_START_FAILED": {
     "message": "Unable to start recording",
     "description": "Error message shown when failing to start recording video."
   },
-  "errorMsgEmptyRecording": {
+  "ERROR_MSG_EMPTY_RECORDING": {
     "message": "Nothing recorded",
     "description": "Error message shown when no data is recorded for a recording and it won't be added to the gallery."
   },
-  "statusMsgRecordingStopped": {
+  "STATUS_MSG_RECORDING_STOPPED": {
     "message": "Recording stopped",
     "description": "Status message for spoken feedback when video recording has been stopped."
   },
-  "statusMsgCameraSwitched": {
+  "STATUS_MSG_CAMERA_SWITCHED": {
     "message": "$camera$ active",
     "description": "Status message for spoken feedback when switching over to another camera.",
     "placeholders": {
@@ -55,131 +55,131 @@
       }
     }
   },
-  "galleryButton": {
+  "GALLERY_BUTTON": {
     "message": "Go to gallery",
     "description": "Label for the gallery button."
   },
-  "deleteButton": {
+  "DELETE_BUTTON": {
     "message": "Delete",
     "description": "Label for the delete button."
   },
-  "exportButton": {
+  "EXPORT_BUTTON": {
     "message": "Export to disk",
     "description": "Label for the exporting button."
   },
-  "printButton": {
+  "PRINT_BUTTON": {
     "message": "Print",
     "description": "Label for the printing button."
   },
-  "backButton": {
+  "BACK_BUTTON": {
     "message": "Go back",
     "description": "Label for the back button."
   },
-  "galleryImages": {
+  "GALLERY_IMAGES": {
     "message": "Gallery images",
     "description": "Text to speech label for the gallery list."
   },
-  "settingsButton": {
+  "SETTINGS_BUTTON": {
     "message": "Settings",
     "description": "Label for the settings button."
   },
-  "gridTypeButton": {
+  "GRID_TYPE_BUTTON": {
     "message": "Grid type",
     "description": "Label for the button of grid-type options."
   },
-  "timerDurationButton": {
+  "TIMER_DURATION_BUTTON": {
     "message": "Timer duration",
     "description": "Label for the button of timer-duration options."
   },
-  "feedbackButton": {
+  "FEEDBACK_BUTTON": {
     "message": "Send feedback",
     "description": "Label for the feedback button."
   },
-  "helpButton": {
+  "HELP_BUTTON": {
     "message": "Help",
     "description": "Label for the help button."
   },
-  "labelGrid3x3": {
+  "LABEL_GRID_3X3": {
     "message": "3 x 3",
     "description": "Label for for grid-type: 3x3."
   },
-  "ariaGrid3x3": {
+  "ARIA_GRID_3X3": {
     "message": "3 by 3",
     "description": "Label for spoken feedback to read out grid-type: 3x3."
   },
-  "labelGrid4x4": {
+  "LABEL_GRID_4X4": {
     "message": "4 x 4",
     "description": "Label for for grid-type: 4x4."
   },
-  "ariaGrid4x4": {
+  "ARIA_GRID_4X4": {
     "message": "4 by 4",
     "description": "Label for spoken feedback to read out grid-type: 4x4."
   },
-  "labelGridGolden": {
+  "LABEL_GRID_GOLDEN": {
     "message": "Golden ratio",
     "description": "Label for grid-type: golden ratio."
   },
-  "labelTimer3s": {
+  "LABEL_TIMER_3S": {
     "message": "3 seconds",
     "description": "Label for timer-duration: 3 seconds."
   },
-  "labelTimer10s": {
+  "LABEL_TIMER_10S": {
     "message": "10 seconds",
     "description": "Label for timer-duration: 10 seconds."
   },
-  "takePhotoButton": {
+  "TAKE_PHOTO_BUTTON": {
     "message": "Take photo",
     "description": "Label for the shutter button to take photo."
   },
-  "takePhotoCancelButton": {
+  "TAKE_PHOTO_CANCEL_BUTTON": {
     "message": "Stop taking photo",
     "description": "Label for the shutter button to cancel countdown timer and stop taking photo."
   },
-  "recordVideoStartButton": {
+  "RECORD_VIDEO_START_BUTTON": {
     "message": "Start recording",
     "description": "Label for the shutter button to start recording."
   },
-  "recordVideoStopButton": {
+  "RECORD_VIDEO_STOP_BUTTON": {
     "message": "Stop recording",
     "description": "Label for the shutter button to stop recording."
   },
-  "switchCameraButton": {
+  "SWITCH_CAMERA_BUTTON": {
     "message": "Switch to next camera",
     "description": "Label for the button to switch to next connected camera. Eg. switching from front facing to back facing, or a camera connected via USB. The button is shown only when more than one camera is connected."
   },
-  "switchRecordVideoButton": {
-   "message": "Switch to record video",
-   "description": "Label for the button to switch to record video mode."
+  "SWITCH_RECORD_VIDEO_BUTTON": {
+    "message": "Switch to record video",
+    "description": "Label for the button to switch to record video mode."
   },
-  "switchTakePhotoButton": {
-   "message": "Switch to take photo",
-   "description": "Label for the button to switch to take photo mode."
+  "SWITCH_TAKE_PHOTO_BUTTON": {
+    "message": "Switch to take photo",
+    "description": "Label for the button to switch to take photo mode."
   },
-  "toggleTimerButton": {
+  "TOGGLE_TIMER_BUTTON": {
     "message": "Timer",
     "description": "Label for the checkbox to toggle the countdown timer."
   },
-  "toggleMirrorButton": {
+  "TOGGLE_MIRROR_BUTTON": {
     "message": "Mirroring",
     "description": "Label for the checkbox to toggle the preview mirroring. Eg. if mirroring is toggled on, preview will be flipped horizontally."
   },
-  "toggleGridButton": {
+  "TOGGLE_GRID_BUTTON": {
     "message": "Grid",
     "description": "Label for the checkbox to toggle the grid shown on preview."
   },
-  "toggleMicButton": {
+  "TOGGLE_MIC_BUTTON": {
     "message": "Microphone",
     "description": "Label for the checkbox to toggle the microphone for recording video."
   },
-  "dialogOKButton": {
+  "DIALOG_OK_BUTTON": {
     "message": "OK",
     "description": "Label for the accepting button in the dialog."
   },
-  "dialogCancelButton": {
+  "DIALOG_CANCEL_BUTTON": {
     "message": "Cancel",
     "description": "Label for the dismissing button in the dialog."
   },
-  "deleteConfirmationMsg": {
+  "DELETE_CONFIRMATION_MSG": {
     "message": "Do you really want to remove $file$?",
     "description": "Confirmation message before removing a selected item from the gallery. Expects a file name to be passed in.",
     "placeholders": {
@@ -189,7 +189,7 @@
       }
     }
   },
-  "deleteMultiConfirmationMsg": {
+  "DELETE_MULTI_CONFIRMATION_MSG": {
     "message": "Do you really want to remove $count$ items?",
     "description": "Confirmation message before removing multiple selected items from the gallery. Expects a file count to be passed in.",
     "placeholders": {
@@ -199,8 +199,8 @@
       }
     }
   },
-  "migratePicturesMsg": {
+  "MIGRATE_PICTURES_MSG": {
     "message": "Photos and videos taken with the camera will be moved to the Downloads folder. You can access them in Files.\n\nApps with storage permissions will have access to your photos and videos.",
     "description": "Message shown before moving all photos and videos stored in the Camera App to the Downloads folder."
   }
-}
+}
\ No newline at end of file
diff --git a/chrome/browser/resources/chromeos/camera/src/_locales/en_GB/messages.json b/chrome/browser/resources/chromeos/camera/src/_locales/en_GB/messages.json
index b923a3f..4e9f00a 100644
--- a/chrome/browser/resources/chromeos/camera/src/_locales/en_GB/messages.json
+++ b/chrome/browser/resources/chromeos/camera/src/_locales/en_GB/messages.json
@@ -1,21 +1,21 @@
 {
-  "name": {
+  "NAME": {
     "message": "Camera",
     "description": "Name of the Camera App."
   },
-  "description": {
+  "DESCRIPTION": {
     "message": "Take photos and record videos with your camera.",
     "description": "Short description of the Camera App."
   },
-  "errorMsgFileSystemFailed": {
+  "ERROR_MSG_FILE_SYSTEM_FAILED": {
     "message": "File system errors.",
     "description": "Error message shown when failing to read or write the file system."
   },
-  "errorMsgNoCamera": {
+  "ERROR_MSG_NO_CAMERA": {
     "message": "Your camera is currently unavailable.\nPlease check if the camera is properly connected.",
     "description": "Error message shown when it was impossible to connect to the camera due to unavailability."
   },
-  "errorMsgGalleryExportFailed": {
+  "ERROR_MSG_GALLERY_EXPORT_FAILED": {
     "message": "Unable to export $file$",
     "description": "Error message shown when exporting to an external directory failed. Expects a file name to be passed in.",
     "placeholders": {
@@ -25,27 +25,27 @@
       }
     }
   },
-  "errorMsgSaveFileFailed": {
+  "ERROR_MSG_SAVE_FILE_FAILED": {
     "message": "Unable to save the file",
     "description": "Error message shown when saving/adding a image or video to the file system failed."
   },
-  "errorMsgTakePhotoFailed": {
+  "ERROR_MSG_TAKE_PHOTO_FAILED": {
     "message": "Unable to take photo",
     "description": "Error message shown when failing to take photo."
   },
-  "errorMsgRecordStartFailed": {
+  "ERROR_MSG_RECORD_START_FAILED": {
     "message": "Unable to start recording",
     "description": "Error message shown when failing to start recording video."
   },
-  "errorMsgEmptyRecording": {
+  "ERROR_MSG_EMPTY_RECORDING": {
     "message": "Nothing recorded",
     "description": "Error message shown when no data is recorded for a recording and it won't be added to the gallery."
   },
-  "statusMsgRecordingStopped": {
+  "STATUS_MSG_RECORDING_STOPPED": {
     "message": "Recording stopped",
     "description": "Status message for spoken feedback when video recording has been stopped."
   },
-  "statusMsgCameraSwitched": {
+  "STATUS_MSG_CAMERA_SWITCHED": {
     "message": "$camera$ active",
     "description": "Status message for spoken feedback when switching over to another camera.",
     "placeholders": {
@@ -55,131 +55,131 @@
       }
     }
   },
-  "galleryButton": {
+  "GALLERY_BUTTON": {
     "message": "Go to gallery",
     "description": "Label for the gallery button."
   },
-  "deleteButton": {
+  "DELETE_BUTTON": {
     "message": "Delete",
     "description": "Label for the delete button."
   },
-  "exportButton": {
+  "EXPORT_BUTTON": {
     "message": "Export to disk",
     "description": "Label for the exporting button."
   },
-  "printButton": {
+  "PRINT_BUTTON": {
     "message": "Print",
     "description": "Label for the printing button."
   },
-  "backButton": {
+  "BACK_BUTTON": {
     "message": "Go back",
     "description": "Label for the back button."
   },
-  "galleryImages": {
+  "GALLERY_IMAGES": {
     "message": "Gallery images",
     "description": "Text to speech label for the gallery list."
   },
-  "settingsButton": {
+  "SETTINGS_BUTTON": {
     "message": "Settings",
     "description": "Label for the settings button."
   },
-  "gridTypeButton": {
+  "GRID_TYPE_BUTTON": {
     "message": "Grid type",
     "description": "Label for the button of grid-type options."
   },
-  "timerDurationButton": {
+  "TIMER_DURATION_BUTTON": {
     "message": "Timer duration",
     "description": "Label for the button of timer-duration options."
   },
-  "feedbackButton": {
+  "FEEDBACK_BUTTON": {
     "message": "Send feedback",
     "description": "Label for the feedback button."
   },
-  "helpButton": {
+  "HELP_BUTTON": {
     "message": "Help",
     "description": "Label for the help button."
   },
-  "labelGrid3x3": {
+  "LABEL_GRID_3X3": {
     "message": "3 x 3",
     "description": "Label for for grid-type: 3x3."
   },
-  "ariaGrid3x3": {
+  "ARIA_GRID_3X3": {
     "message": "3 by 3",
     "description": "Label for spoken feedback to read out grid-type: 3x3."
   },
-  "labelGrid4x4": {
+  "LABEL_GRID_4X4": {
     "message": "4 x 4",
     "description": "Label for for grid-type: 4x4."
   },
-  "ariaGrid4x4": {
+  "ARIA_GRID_4X4": {
     "message": "4 by 4",
     "description": "Label for spoken feedback to read out grid-type: 4x4."
   },
-  "labelGridGolden": {
+  "LABEL_GRID_GOLDEN": {
     "message": "Golden ratio",
     "description": "Label for grid-type: golden ratio."
   },
-  "labelTimer3s": {
+  "LABEL_TIMER_3S": {
     "message": "3 seconds",
     "description": "Label for timer-duration: 3 seconds."
   },
-  "labelTimer10s": {
+  "LABEL_TIMER_10S": {
     "message": "10 seconds",
     "description": "Label for timer-duration: 10 seconds."
   },
-  "takePhotoButton": {
+  "TAKE_PHOTO_BUTTON": {
     "message": "Take photo",
     "description": "Label for the shutter button to take photo."
   },
-  "takePhotoCancelButton": {
+  "TAKE_PHOTO_CANCEL_BUTTON": {
     "message": "Stop taking photo",
     "description": "Label for the shutter button to cancel countdown timer and stop taking photo."
   },
-  "recordVideoStartButton": {
+  "RECORD_VIDEO_START_BUTTON": {
     "message": "Start recording",
     "description": "Label for the shutter button to start recording."
   },
-  "recordVideoStopButton": {
+  "RECORD_VIDEO_STOP_BUTTON": {
     "message": "Stop recording",
     "description": "Label for the shutter button to stop recording."
   },
-  "switchCameraButton": {
+  "SWITCH_CAMERA_BUTTON": {
     "message": "Switch to next camera",
     "description": "Label for the button to switch to next connected camera. Eg. switching from front facing to back facing, or a camera connected via USB. The button is shown only when more than one camera is connected."
   },
-  "switchRecordVideoButton": {
+  "SWITCH_RECORD_VIDEO_BUTTON": {
     "message": "Switch to record video",
     "description": "Label for the button to switch to record video mode."
   },
-  "switchTakePhotoButton": {
+  "SWITCH_TAKE_PHOTO_BUTTON": {
     "message": "Switch to take photo",
     "description": "Label for the button to switch to take photo mode."
   },
-  "toggleTimerButton": {
+  "TOGGLE_TIMER_BUTTON": {
     "message": "Timer",
     "description": "Label for the checkbox to toggle the countdown timer."
   },
-  "toggleMirrorButton": {
+  "TOGGLE_MIRROR_BUTTON": {
     "message": "Mirroring",
     "description": "Label for the checkbox to toggle the preview mirroring. Eg. if mirroring is toggled on, preview will be flipped horizontally."
   },
-  "toggleGridButton": {
+  "TOGGLE_GRID_BUTTON": {
     "message": "Grid",
     "description": "Label for the checkbox to toggle the grid shown on preview."
   },
-  "toggleMicButton": {
+  "TOGGLE_MIC_BUTTON": {
     "message": "Microphone",
     "description": "Label for the checkbox to toggle the microphone for recording video."
   },
-  "dialogOKButton": {
+  "DIALOG_OK_BUTTON": {
     "message": "OK",
     "description": "Label for the accepting button in the dialog."
   },
-  "dialogCancelButton": {
+  "DIALOG_CANCEL_BUTTON": {
     "message": "Cancel",
     "description": "Label for the dismissing button in the dialog."
   },
-  "deleteConfirmationMsg": {
+  "DELETE_CONFIRMATION_MSG": {
     "message": "Do you really want to remove $file$?",
     "description": "Confirmation message before removing a selected item from the gallery. Expects a file name to be passed in.",
     "placeholders": {
@@ -189,7 +189,7 @@
       }
     }
   },
-  "deleteMultiConfirmationMsg": {
+  "DELETE_MULTI_CONFIRMATION_MSG": {
     "message": "Do you really want to remove $count$ items?",
     "description": "Confirmation message before removing multiple selected items from the gallery. Expects a file count to be passed in.",
     "placeholders": {
@@ -199,7 +199,7 @@
       }
     }
   },
-  "migratePicturesMsg": {
+  "MIGRATE_PICTURES_MSG": {
     "message": "Photos and videos taken with the camera will be moved to the Downloads folder. You can access them in Files.\n\nApps with storage permissions will have access to your photos and videos.",
     "description": "Message shown before moving all photos and videos stored in the Camera App to the Downloads folder."
   }
diff --git a/chrome/browser/resources/chromeos/camera/src/_locales/es/messages.json b/chrome/browser/resources/chromeos/camera/src/_locales/es/messages.json
index 894ff28..5c5c4b4 100644
--- a/chrome/browser/resources/chromeos/camera/src/_locales/es/messages.json
+++ b/chrome/browser/resources/chromeos/camera/src/_locales/es/messages.json
@@ -1,21 +1,21 @@
 {
-  "name": {
+  "NAME": {
     "message": "Cámara",
     "description": "Name of the Camera App."
   },
-  "description": {
+  "DESCRIPTION": {
     "message": "Haz fotos y graba vídeos con la cámara.",
     "description": "Short description of the Camera App."
   },
-  "errorMsgFileSystemFailed": {
+  "ERROR_MSG_FILE_SYSTEM_FAILED": {
     "message": "Se han producido errores en el sistema de archivos.",
     "description": "Error message shown when failing to read or write the file system."
   },
-  "errorMsgNoCamera": {
+  "ERROR_MSG_NO_CAMERA": {
     "message": "La cámara no está disponible en este momento.\nComprueba si la cámara está conectada correctamente.",
     "description": "Error message shown when it was impossible to connect to the camera due to unavailability."
   },
-  "errorMsgGalleryExportFailed": {
+  "ERROR_MSG_GALLERY_EXPORT_FAILED": {
     "message": "No se ha podido exportar $file$",
     "description": "Error message shown when exporting to an external directory failed. Expects a file name to be passed in.",
     "placeholders": {
@@ -25,27 +25,27 @@
       }
     }
   },
-  "errorMsgSaveFileFailed": {
+  "ERROR_MSG_SAVE_FILE_FAILED": {
     "message": "No se ha podido guardar el archivo",
     "description": "Error message shown when saving/adding a image or video to the file system failed."
   },
-  "errorMsgTakePhotoFailed": {
+  "ERROR_MSG_TAKE_PHOTO_FAILED": {
     "message": "No se ha podido hacer la foto",
     "description": "Error message shown when failing to take photo."
   },
-  "errorMsgRecordStartFailed": {
+  "ERROR_MSG_RECORD_START_FAILED": {
     "message": "No se ha podido iniciar la grabación",
     "description": "Error message shown when failing to start recording video."
   },
-  "errorMsgEmptyRecording": {
+  "ERROR_MSG_EMPTY_RECORDING": {
     "message": "No se ha grabado nada",
     "description": "Error message shown when no data is recorded for a recording and it won't be added to the gallery."
   },
-  "statusMsgRecordingStopped": {
+  "STATUS_MSG_RECORDING_STOPPED": {
     "message": "Se ha detenido la grabación",
     "description": "Status message for spoken feedback when video recording has been stopped."
   },
-  "statusMsgCameraSwitched": {
+  "STATUS_MSG_CAMERA_SWITCHED": {
     "message": "$camera$ activa",
     "description": "Status message for spoken feedback when switching over to another camera.",
     "placeholders": {
@@ -55,131 +55,131 @@
       }
     }
   },
-  "galleryButton": {
+  "GALLERY_BUTTON": {
     "message": "Ir a la galería",
     "description": "Label for the gallery button."
   },
-  "deleteButton": {
+  "DELETE_BUTTON": {
     "message": "Eliminar",
     "description": "Label for the delete button."
   },
-  "exportButton": {
+  "EXPORT_BUTTON": {
     "message": "Exportar a disco",
     "description": "Label for the exporting button."
   },
-  "printButton": {
+  "PRINT_BUTTON": {
     "message": "Imprimir",
     "description": "Label for the printing button."
   },
-  "backButton": {
+  "BACK_BUTTON": {
     "message": "Atrás",
     "description": "Label for the back button."
   },
-  "galleryImages": {
+  "GALLERY_IMAGES": {
     "message": "Imágenes de la galería",
     "description": "Text to speech label for the gallery list."
   },
-  "settingsButton": {
+  "SETTINGS_BUTTON": {
     "message": "Ajustes",
     "description": "Label for the settings button."
   },
-  "gridTypeButton": {
+  "GRID_TYPE_BUTTON": {
     "message": "Tipo de cuadrícula",
     "description": "Label for the button of grid-type options."
   },
-  "timerDurationButton": {
+  "TIMER_DURATION_BUTTON": {
     "message": "Duración del temporizador",
     "description": "Label for the button of timer-duration options."
   },
-  "feedbackButton": {
+  "FEEDBACK_BUTTON": {
     "message": "Enviar comentarios",
     "description": "Label for the feedback button."
   },
-  "helpButton": {
+  "HELP_BUTTON": {
     "message": "Ayuda",
     "description": "Label for the help button."
   },
-  "labelGrid3x3": {
+  "LABEL_GRID_3X3": {
     "message": "3x3",
     "description": "Label for for grid-type: 3x3."
   },
-  "ariaGrid3x3": {
+  "ARIA_GRID_3X3": {
     "message": "Tres por tres",
     "description": "Label for spoken feedback to read out grid-type: 3x3."
   },
-  "labelGrid4x4": {
+  "LABEL_GRID_4X4": {
     "message": "4x4",
     "description": "Label for for grid-type: 4x4."
   },
-  "ariaGrid4x4": {
+  "ARIA_GRID_4X4": {
     "message": "Cuatro por cuatro",
     "description": "Label for spoken feedback to read out grid-type: 4x4."
   },
-  "labelGridGolden": {
+  "LABEL_GRID_GOLDEN": {
     "message": "Proporción áurea",
     "description": "Label for grid-type: golden ratio."
   },
-  "labelTimer3s": {
+  "LABEL_TIMER_3S": {
     "message": "3 segundos",
     "description": "Label for timer-duration: 3 seconds."
   },
-  "labelTimer10s": {
+  "LABEL_TIMER_10S": {
     "message": "10 segundos",
     "description": "Label for timer-duration: 10 seconds."
   },
-  "takePhotoButton": {
+  "TAKE_PHOTO_BUTTON": {
     "message": "Hacer foto",
     "description": "Label for the shutter button to take photo."
   },
-  "takePhotoCancelButton": {
+  "TAKE_PHOTO_CANCEL_BUTTON": {
     "message": "Detener foto",
     "description": "Label for the shutter button to cancel countdown timer and stop taking photo."
   },
-  "recordVideoStartButton": {
+  "RECORD_VIDEO_START_BUTTON": {
     "message": "Iniciar grabación",
     "description": "Label for the shutter button to start recording."
   },
-  "recordVideoStopButton": {
+  "RECORD_VIDEO_STOP_BUTTON": {
     "message": "Detener grabación",
     "description": "Label for the shutter button to stop recording."
   },
-  "switchCameraButton": {
+  "SWITCH_CAMERA_BUTTON": {
     "message": "Cambiar a la siguiente cámara",
     "description": "Label for the button to switch to next connected camera. Eg. switching from front facing to back facing, or a camera connected via USB. The button is shown only when more than one camera is connected."
   },
-  "switchRecordVideoButton": {
+  "SWITCH_RECORD_VIDEO_BUTTON": {
     "message": "Cambiar al modo de cámara de vídeo",
     "description": "Label for the button to switch to record video mode."
   },
-  "switchTakePhotoButton": {
+  "SWITCH_TAKE_PHOTO_BUTTON": {
     "message": "Cambiar al modo de cámara de fotos",
     "description": "Label for the button to switch to take photo mode."
   },
-  "toggleTimerButton": {
+  "TOGGLE_TIMER_BUTTON": {
     "message": "Temporizador",
     "description": "Label for the checkbox to toggle the countdown timer."
   },
-  "toggleMirrorButton": {
+  "TOGGLE_MIRROR_BUTTON": {
     "message": "Efecto espejo",
     "description": "Label for the checkbox to toggle the preview mirroring. Eg. if mirroring is toggled on, preview will be flipped horizontally."
   },
-  "toggleGridButton": {
+  "TOGGLE_GRID_BUTTON": {
     "message": "Cuadrícula",
     "description": "Label for the checkbox to toggle the grid shown on preview."
   },
-  "toggleMicButton": {
+  "TOGGLE_MIC_BUTTON": {
     "message": "Micrófono",
     "description": "Label for the checkbox to toggle the microphone for recording video."
   },
-  "dialogOKButton": {
+  "DIALOG_OK_BUTTON": {
     "message": "Aceptar",
     "description": "Label for the accepting button in the dialog."
   },
-  "dialogCancelButton": {
+  "DIALOG_CANCEL_BUTTON": {
     "message": "Cancelar",
     "description": "Label for the dismissing button in the dialog."
   },
-  "deleteConfirmationMsg": {
+  "DELETE_CONFIRMATION_MSG": {
     "message": "¿Seguro que quieres eliminar $file$?",
     "description": "Confirmation message before removing a selected item from the gallery. Expects a file name to be passed in.",
     "placeholders": {
@@ -189,7 +189,7 @@
       }
     }
   },
-  "deleteMultiConfirmationMsg": {
+  "DELETE_MULTI_CONFIRMATION_MSG": {
     "message": "¿Seguro que quieres quitar estos $count$ elementos?",
     "description": "Confirmation message before removing multiple selected items from the gallery. Expects a file count to be passed in.",
     "placeholders": {
@@ -199,7 +199,7 @@
       }
     }
   },
-  "migratePicturesMsg": {
+  "MIGRATE_PICTURES_MSG": {
     "message": "Las fotos y los vídeos hechos con la cámara se moverán a la carpeta Descargas. Podrás acceder a ellos con la aplicación Archivos.\n\nLas aplicaciones con permiso de almacenamiento podrán acceder a tus fotos y vídeos.",
     "description": "Message shown before moving all photos and videos stored in the Camera App to the Downloads folder."
   }
diff --git a/chrome/browser/resources/chromeos/camera/src/_locales/es_419/messages.json b/chrome/browser/resources/chromeos/camera/src/_locales/es_419/messages.json
index f82f6a6..8b9e030 100644
--- a/chrome/browser/resources/chromeos/camera/src/_locales/es_419/messages.json
+++ b/chrome/browser/resources/chromeos/camera/src/_locales/es_419/messages.json
@@ -1,21 +1,21 @@
 {
-  "name": {
+  "NAME": {
     "message": "Cámara",
     "description": "Name of the Camera App."
   },
-  "description": {
+  "DESCRIPTION": {
     "message": "Toma fotos y graba videos con la cámara.",
     "description": "Short description of the Camera App."
   },
-  "errorMsgFileSystemFailed": {
+  "ERROR_MSG_FILE_SYSTEM_FAILED": {
     "message": "Errores en el sistema de archivos",
     "description": "Error message shown when failing to read or write the file system."
   },
-  "errorMsgNoCamera": {
+  "ERROR_MSG_NO_CAMERA": {
     "message": "La cámara no está disponible en este momento. Revisa si la conectaste correctamente.",
     "description": "Error message shown when it was impossible to connect to the camera due to unavailability."
   },
-  "errorMsgGalleryExportFailed": {
+  "ERROR_MSG_GALLERY_EXPORT_FAILED": {
     "message": "No se puede exportar $file$",
     "description": "Error message shown when exporting to an external directory failed. Expects a file name to be passed in.",
     "placeholders": {
@@ -25,27 +25,27 @@
       }
     }
   },
-  "errorMsgSaveFileFailed": {
+  "ERROR_MSG_SAVE_FILE_FAILED": {
     "message": "No se puede guardar el archivo",
     "description": "Error message shown when saving/adding a image or video to the file system failed."
   },
-  "errorMsgTakePhotoFailed": {
+  "ERROR_MSG_TAKE_PHOTO_FAILED": {
     "message": "No se puede tomar la foto",
     "description": "Error message shown when failing to take photo."
   },
-  "errorMsgRecordStartFailed": {
+  "ERROR_MSG_RECORD_START_FAILED": {
     "message": "No es posible comenzar a grabar",
     "description": "Error message shown when failing to start recording video."
   },
-  "errorMsgEmptyRecording": {
+  "ERROR_MSG_EMPTY_RECORDING": {
     "message": "No se grabaron datos",
     "description": "Error message shown when no data is recorded for a recording and it won't be added to the gallery."
   },
-  "statusMsgRecordingStopped": {
+  "STATUS_MSG_RECORDING_STOPPED": {
     "message": "Se detuvo la grabación",
     "description": "Status message for spoken feedback when video recording has been stopped."
   },
-  "statusMsgCameraSwitched": {
+  "STATUS_MSG_CAMERA_SWITCHED": {
     "message": "$camera$ activada",
     "description": "Status message for spoken feedback when switching over to another camera.",
     "placeholders": {
@@ -55,131 +55,131 @@
       }
     }
   },
-  "galleryButton": {
+  "GALLERY_BUTTON": {
     "message": "Ir a la galería",
     "description": "Label for the gallery button."
   },
-  "deleteButton": {
+  "DELETE_BUTTON": {
     "message": "Borrar",
     "description": "Label for the delete button."
   },
-  "exportButton": {
+  "EXPORT_BUTTON": {
     "message": "Exportar al disco",
     "description": "Label for the exporting button."
   },
-  "printButton": {
+  "PRINT_BUTTON": {
     "message": "Imprimir",
     "description": "Label for the printing button."
   },
-  "backButton": {
+  "BACK_BUTTON": {
     "message": "Volver",
     "description": "Label for the back button."
   },
-  "galleryImages": {
+  "GALLERY_IMAGES": {
     "message": "Imágenes de la galería",
     "description": "Text to speech label for the gallery list."
   },
-  "settingsButton": {
+  "SETTINGS_BUTTON": {
     "message": "Configuración",
     "description": "Label for the settings button."
   },
-  "gridTypeButton": {
+  "GRID_TYPE_BUTTON": {
     "message": "Tipo de cuadrícula",
     "description": "Label for the button of grid-type options."
   },
-  "timerDurationButton": {
+  "TIMER_DURATION_BUTTON": {
     "message": "Duración del temporizador",
     "description": "Label for the button of timer-duration options."
   },
-  "feedbackButton": {
+  "FEEDBACK_BUTTON": {
     "message": "Enviar comentarios",
     "description": "Label for the feedback button."
   },
-  "helpButton": {
+  "HELP_BUTTON": {
     "message": "Ayuda",
     "description": "Label for the help button."
   },
-  "labelGrid3x3": {
+  "LABEL_GRID_3X3": {
     "message": "3 x 3",
     "description": "Label for for grid-type: 3x3."
   },
-  "ariaGrid3x3": {
+  "ARIA_GRID_3X3": {
     "message": "3 por 3",
     "description": "Label for spoken feedback to read out grid-type: 3x3."
   },
-  "labelGrid4x4": {
+  "LABEL_GRID_4X4": {
     "message": "4 x 4",
     "description": "Label for for grid-type: 4x4."
   },
-  "ariaGrid4x4": {
+  "ARIA_GRID_4X4": {
     "message": "4 por 4",
     "description": "Label for spoken feedback to read out grid-type: 4x4."
   },
-  "labelGridGolden": {
+  "LABEL_GRID_GOLDEN": {
     "message": "Proporción áurea",
     "description": "Label for grid-type: golden ratio."
   },
-  "labelTimer3s": {
+  "LABEL_TIMER_3S": {
     "message": "3 segundos",
     "description": "Label for timer-duration: 3 seconds."
   },
-  "labelTimer10s": {
+  "LABEL_TIMER_10S": {
     "message": "10 segundos",
     "description": "Label for timer-duration: 10 seconds."
   },
-  "takePhotoButton": {
+  "TAKE_PHOTO_BUTTON": {
     "message": "Tomar una foto",
     "description": "Label for the shutter button to take photo."
   },
-  "takePhotoCancelButton": {
+  "TAKE_PHOTO_CANCEL_BUTTON": {
     "message": "Detener foto",
     "description": "Label for the shutter button to cancel countdown timer and stop taking photo."
   },
-  "recordVideoStartButton": {
+  "RECORD_VIDEO_START_BUTTON": {
     "message": "Iniciar grabación",
     "description": "Label for the shutter button to start recording."
   },
-  "recordVideoStopButton": {
+  "RECORD_VIDEO_STOP_BUTTON": {
     "message": "Detener grabación",
     "description": "Label for the shutter button to stop recording."
   },
-  "switchCameraButton": {
+  "SWITCH_CAMERA_BUTTON": {
     "message": "Cambiar a la siguiente cámara",
     "description": "Label for the button to switch to next connected camera. Eg. switching from front facing to back facing, or a camera connected via USB. The button is shown only when more than one camera is connected."
   },
-  "switchRecordVideoButton": {
+  "SWITCH_RECORD_VIDEO_BUTTON": {
     "message": "Cambiar al modo para grabar video",
     "description": "Label for the button to switch to record video mode."
   },
-  "switchTakePhotoButton": {
+  "SWITCH_TAKE_PHOTO_BUTTON": {
     "message": "Cambiar al modo para tomar fotos",
     "description": "Label for the button to switch to take photo mode."
   },
-  "toggleTimerButton": {
+  "TOGGLE_TIMER_BUTTON": {
     "message": "Temporizador",
     "description": "Label for the checkbox to toggle the countdown timer."
   },
-  "toggleMirrorButton": {
+  "TOGGLE_MIRROR_BUTTON": {
     "message": "Duplicación",
     "description": "Label for the checkbox to toggle the preview mirroring. Eg. if mirroring is toggled on, preview will be flipped horizontally."
   },
-  "toggleGridButton": {
+  "TOGGLE_GRID_BUTTON": {
     "message": "Cuadrícula",
     "description": "Label for the checkbox to toggle the grid shown on preview."
   },
-  "toggleMicButton": {
+  "TOGGLE_MIC_BUTTON": {
     "message": "Micrófono",
     "description": "Label for the checkbox to toggle the microphone for recording video."
   },
-  "dialogOKButton": {
+  "DIALOG_OK_BUTTON": {
     "message": "Aceptar",
     "description": "Label for the accepting button in the dialog."
   },
-  "dialogCancelButton": {
+  "DIALOG_CANCEL_BUTTON": {
     "message": "Cancelar",
     "description": "Label for the dismissing button in the dialog."
   },
-  "deleteConfirmationMsg": {
+  "DELETE_CONFIRMATION_MSG": {
     "message": "¿Confirmas que deseas quitar $file$?",
     "description": "Confirmation message before removing a selected item from the gallery. Expects a file name to be passed in.",
     "placeholders": {
@@ -189,7 +189,7 @@
       }
     }
   },
-  "deleteMultiConfirmationMsg": {
+  "DELETE_MULTI_CONFIRMATION_MSG": {
     "message": "¿Confirmas que deseas quitar $count$ elementos?",
     "description": "Confirmation message before removing multiple selected items from the gallery. Expects a file count to be passed in.",
     "placeholders": {
@@ -199,7 +199,7 @@
       }
     }
   },
-  "migratePicturesMsg": {
+  "MIGRATE_PICTURES_MSG": {
     "message": "Las fotos y los videos que tomes con la cámara se moverán a la carpeta Descargas, que puedes abrir con la app de Archivos.\n\nLas apps que tengan permiso de almacenamiento podrán acceder a tus fotos y videos.",
     "description": "Message shown before moving all photos and videos stored in the Camera App to the Downloads folder."
   }
diff --git a/chrome/browser/resources/chromeos/camera/src/_locales/et/messages.json b/chrome/browser/resources/chromeos/camera/src/_locales/et/messages.json
index 3c6365e3..337fdb1 100644
--- a/chrome/browser/resources/chromeos/camera/src/_locales/et/messages.json
+++ b/chrome/browser/resources/chromeos/camera/src/_locales/et/messages.json
@@ -1,21 +1,21 @@
 {
-  "name": {
+  "NAME": {
     "message": "Kaamera",
     "description": "Name of the Camera App."
   },
-  "description": {
+  "DESCRIPTION": {
     "message": "Jäädvustage oma kaameraga fotosid ja salvestage videoid.",
     "description": "Short description of the Camera App."
   },
-  "errorMsgFileSystemFailed": {
+  "ERROR_MSG_FILE_SYSTEM_FAILED": {
     "message": "Failisüsteemi vead.",
     "description": "Error message shown when failing to read or write the file system."
   },
-  "errorMsgNoCamera": {
+  "ERROR_MSG_NO_CAMERA": {
     "message": "Kaamera pole praegu saadaval.\nKontrollige, kas kaamera on korralikult ühendatud.",
     "description": "Error message shown when it was impossible to connect to the camera due to unavailability."
   },
-  "errorMsgGalleryExportFailed": {
+  "ERROR_MSG_GALLERY_EXPORT_FAILED": {
     "message": "Faili $file$ eksportimine ebaõnnestus",
     "description": "Error message shown when exporting to an external directory failed. Expects a file name to be passed in.",
     "placeholders": {
@@ -25,27 +25,27 @@
       }
     }
   },
-  "errorMsgSaveFileFailed": {
+  "ERROR_MSG_SAVE_FILE_FAILED": {
     "message": "Faili salvestamine ebaõnnestus",
     "description": "Error message shown when saving/adding a image or video to the file system failed."
   },
-  "errorMsgTakePhotoFailed": {
+  "ERROR_MSG_TAKE_PHOTO_FAILED": {
     "message": "Foto jäädvustamine ebaõnnestus",
     "description": "Error message shown when failing to take photo."
   },
-  "errorMsgRecordStartFailed": {
+  "ERROR_MSG_RECORD_START_FAILED": {
     "message": "Salvestamise alustamine ebaõnnestus",
     "description": "Error message shown when failing to start recording video."
   },
-  "errorMsgEmptyRecording": {
+  "ERROR_MSG_EMPTY_RECORDING": {
     "message": "Midagi pole salvestatud",
     "description": "Error message shown when no data is recorded for a recording and it won't be added to the gallery."
   },
-  "statusMsgRecordingStopped": {
+  "STATUS_MSG_RECORDING_STOPPED": {
     "message": "Salvestamine on peatatud",
     "description": "Status message for spoken feedback when video recording has been stopped."
   },
-  "statusMsgCameraSwitched": {
+  "STATUS_MSG_CAMERA_SWITCHED": {
     "message": "$camera$ on aktiivne",
     "description": "Status message for spoken feedback when switching over to another camera.",
     "placeholders": {
@@ -55,131 +55,131 @@
       }
     }
   },
-  "galleryButton": {
+  "GALLERY_BUTTON": {
     "message": "Ava galerii",
     "description": "Label for the gallery button."
   },
-  "deleteButton": {
+  "DELETE_BUTTON": {
     "message": "Kustuta",
     "description": "Label for the delete button."
   },
-  "exportButton": {
+  "EXPORT_BUTTON": {
     "message": "Ekspordi kettale",
     "description": "Label for the exporting button."
   },
-  "printButton": {
+  "PRINT_BUTTON": {
     "message": "Prindi",
     "description": "Label for the printing button."
   },
-  "backButton": {
+  "BACK_BUTTON": {
     "message": "Mine tagasi",
     "description": "Label for the back button."
   },
-  "galleryImages": {
+  "GALLERY_IMAGES": {
     "message": "Galerii kujutised",
     "description": "Text to speech label for the gallery list."
   },
-  "settingsButton": {
+  "SETTINGS_BUTTON": {
     "message": "Seaded",
     "description": "Label for the settings button."
   },
-  "gridTypeButton": {
+  "GRID_TYPE_BUTTON": {
     "message": "Ruudustiku tüüp",
     "description": "Label for the button of grid-type options."
   },
-  "timerDurationButton": {
+  "TIMER_DURATION_BUTTON": {
     "message": "Taimeri kestus",
     "description": "Label for the button of timer-duration options."
   },
-  "feedbackButton": {
+  "FEEDBACK_BUTTON": {
     "message": "Tagasiside saatmine",
     "description": "Label for the feedback button."
   },
-  "helpButton": {
+  "HELP_BUTTON": {
     "message": "Abi",
     "description": "Label for the help button."
   },
-  "labelGrid3x3": {
+  "LABEL_GRID_3X3": {
     "message": "3 x 3",
     "description": "Label for for grid-type: 3x3."
   },
-  "ariaGrid3x3": {
+  "ARIA_GRID_3X3": {
     "message": "kolm korda kolm",
     "description": "Label for spoken feedback to read out grid-type: 3x3."
   },
-  "labelGrid4x4": {
+  "LABEL_GRID_4X4": {
     "message": "4 x 4",
     "description": "Label for for grid-type: 4x4."
   },
-  "ariaGrid4x4": {
+  "ARIA_GRID_4X4": {
     "message": "neli korda neli",
     "description": "Label for spoken feedback to read out grid-type: 4x4."
   },
-  "labelGridGolden": {
+  "LABEL_GRID_GOLDEN": {
     "message": "Kuldlõige",
     "description": "Label for grid-type: golden ratio."
   },
-  "labelTimer3s": {
+  "LABEL_TIMER_3S": {
     "message": "3 sekundit",
     "description": "Label for timer-duration: 3 seconds."
   },
-  "labelTimer10s": {
+  "LABEL_TIMER_10S": {
     "message": "10 sekundit",
     "description": "Label for timer-duration: 10 seconds."
   },
-  "takePhotoButton": {
+  "TAKE_PHOTO_BUTTON": {
     "message": "Jäädvusta foto",
     "description": "Label for the shutter button to take photo."
   },
-  "takePhotoCancelButton": {
+  "TAKE_PHOTO_CANCEL_BUTTON": {
     "message": "Peata foto jäädvustamine",
     "description": "Label for the shutter button to cancel countdown timer and stop taking photo."
   },
-  "recordVideoStartButton": {
+  "RECORD_VIDEO_START_BUTTON": {
     "message": "Alusta salvestamist",
     "description": "Label for the shutter button to start recording."
   },
-  "recordVideoStopButton": {
+  "RECORD_VIDEO_STOP_BUTTON": {
     "message": "Peata salvestamine",
     "description": "Label for the shutter button to stop recording."
   },
-  "switchCameraButton": {
+  "SWITCH_CAMERA_BUTTON": {
     "message": "Vaheta järgmisele kaamerale",
     "description": "Label for the button to switch to next connected camera. Eg. switching from front facing to back facing, or a camera connected via USB. The button is shown only when more than one camera is connected."
   },
-  "switchRecordVideoButton": {
+  "SWITCH_RECORD_VIDEO_BUTTON": {
     "message": "Vaheta video salvestamise režiimile",
     "description": "Label for the button to switch to record video mode."
   },
-  "switchTakePhotoButton": {
+  "SWITCH_TAKE_PHOTO_BUTTON": {
     "message": "Vaheta foto jäädvustamise režiimile",
     "description": "Label for the button to switch to take photo mode."
   },
-  "toggleTimerButton": {
+  "TOGGLE_TIMER_BUTTON": {
     "message": "Taimer",
     "description": "Label for the checkbox to toggle the countdown timer."
   },
-  "toggleMirrorButton": {
+  "TOGGLE_MIRROR_BUTTON": {
     "message": "Peegeldamine",
     "description": "Label for the checkbox to toggle the preview mirroring. Eg. if mirroring is toggled on, preview will be flipped horizontally."
   },
-  "toggleGridButton": {
+  "TOGGLE_GRID_BUTTON": {
     "message": "Ruudustik",
     "description": "Label for the checkbox to toggle the grid shown on preview."
   },
-  "toggleMicButton": {
+  "TOGGLE_MIC_BUTTON": {
     "message": "Mikrofon",
     "description": "Label for the checkbox to toggle the microphone for recording video."
   },
-  "dialogOKButton": {
+  "DIALOG_OK_BUTTON": {
     "message": "OK",
     "description": "Label for the accepting button in the dialog."
   },
-  "dialogCancelButton": {
+  "DIALOG_CANCEL_BUTTON": {
     "message": "Tühista",
     "description": "Label for the dismissing button in the dialog."
   },
-  "deleteConfirmationMsg": {
+  "DELETE_CONFIRMATION_MSG": {
     "message": "Kas soovite kindlasti eemaldada faili $file$?",
     "description": "Confirmation message before removing a selected item from the gallery. Expects a file name to be passed in.",
     "placeholders": {
@@ -189,7 +189,7 @@
       }
     }
   },
-  "deleteMultiConfirmationMsg": {
+  "DELETE_MULTI_CONFIRMATION_MSG": {
     "message": "Kas soovite kindlasti eemaldada need $count$ üksust?",
     "description": "Confirmation message before removing multiple selected items from the gallery. Expects a file count to be passed in.",
     "placeholders": {
@@ -199,7 +199,7 @@
       }
     }
   },
-  "migratePicturesMsg": {
+  "MIGRATE_PICTURES_MSG": {
     "message": "Kaameraga tehtud fotod ja videod teisaldatakse kausta Allalaadimised. Pääsete neile juurde rakenduses Failid.\n\nSalvestusruumi kasutuse lubadega rakendustel on juurdepääs teie fotodele ja videotele.",
     "description": "Message shown before moving all photos and videos stored in the Camera App to the Downloads folder."
   }
diff --git a/chrome/browser/resources/chromeos/camera/src/_locales/fa/messages.json b/chrome/browser/resources/chromeos/camera/src/_locales/fa/messages.json
index bdf35ad..1fa79039 100644
--- a/chrome/browser/resources/chromeos/camera/src/_locales/fa/messages.json
+++ b/chrome/browser/resources/chromeos/camera/src/_locales/fa/messages.json
@@ -1,21 +1,21 @@
 {
-  "name": {
+  "NAME": {
     "message": "دوربین",
     "description": "Name of the Camera App."
   },
-  "description": {
+  "DESCRIPTION": {
     "message": "با دوربینتان عکس بگیرید و فیلم‌برداری کنید.",
     "description": "Short description of the Camera App."
   },
-  "errorMsgFileSystemFailed": {
+  "ERROR_MSG_FILE_SYSTEM_FAILED": {
     "message": "خطاهایی در سیستم فایل وجود دارد.",
     "description": "Error message shown when failing to read or write the file system."
   },
-  "errorMsgNoCamera": {
+  "ERROR_MSG_NO_CAMERA": {
     "message": "درحال‌حاضر دوربینتان دردسترس نیست.\nلطفاً بررسی کنید که دوربین به‌درستی متصل شده است یا نه.",
     "description": "Error message shown when it was impossible to connect to the camera due to unavailability."
   },
-  "errorMsgGalleryExportFailed": {
+  "ERROR_MSG_GALLERY_EXPORT_FAILED": {
     "message": "صادر کردن $file$ امکان‌پذیر نیست",
     "description": "Error message shown when exporting to an external directory failed. Expects a file name to be passed in.",
     "placeholders": {
@@ -25,27 +25,27 @@
       }
     }
   },
-  "errorMsgSaveFileFailed": {
+  "ERROR_MSG_SAVE_FILE_FAILED": {
     "message": "ذخیره کردن فایل امکان‌پذیر نیست",
     "description": "Error message shown when saving/adding a image or video to the file system failed."
   },
-  "errorMsgTakePhotoFailed": {
+  "ERROR_MSG_TAKE_PHOTO_FAILED": {
     "message": "عکس‌برداری امکان‌پذیر نیست",
     "description": "Error message shown when failing to take photo."
   },
-  "errorMsgRecordStartFailed": {
+  "ERROR_MSG_RECORD_START_FAILED": {
     "message": "شروع ضبط امکان‌پذیر نیست",
     "description": "Error message shown when failing to start recording video."
   },
-  "errorMsgEmptyRecording": {
+  "ERROR_MSG_EMPTY_RECORDING": {
     "message": "چیزی ضبط نشد",
     "description": "Error message shown when no data is recorded for a recording and it won't be added to the gallery."
   },
-  "statusMsgRecordingStopped": {
+  "STATUS_MSG_RECORDING_STOPPED": {
     "message": "ضبط متوقف شد",
     "description": "Status message for spoken feedback when video recording has been stopped."
   },
-  "statusMsgCameraSwitched": {
+  "STATUS_MSG_CAMERA_SWITCHED": {
     "message": "$camera$ فعال است",
     "description": "Status message for spoken feedback when switching over to another camera.",
     "placeholders": {
@@ -55,131 +55,131 @@
       }
     }
   },
-  "galleryButton": {
+  "GALLERY_BUTTON": {
     "message": "رفتن به گالری",
     "description": "Label for the gallery button."
   },
-  "deleteButton": {
+  "DELETE_BUTTON": {
     "message": "حذف",
     "description": "Label for the delete button."
   },
-  "exportButton": {
+  "EXPORT_BUTTON": {
     "message": "صادر کردن به دیسک",
     "description": "Label for the exporting button."
   },
-  "printButton": {
+  "PRINT_BUTTON": {
     "message": "چاپ",
     "description": "Label for the printing button."
   },
-  "backButton": {
+  "BACK_BUTTON": {
     "message": "برگشت",
     "description": "Label for the back button."
   },
-  "galleryImages": {
+  "GALLERY_IMAGES": {
     "message": "تصاویر گالری",
     "description": "Text to speech label for the gallery list."
   },
-  "settingsButton": {
+  "SETTINGS_BUTTON": {
     "message": "تنظیمات",
     "description": "Label for the settings button."
   },
-  "gridTypeButton": {
+  "GRID_TYPE_BUTTON": {
     "message": "نوع شبکه",
     "description": "Label for the button of grid-type options."
   },
-  "timerDurationButton": {
+  "TIMER_DURATION_BUTTON": {
     "message": "مدت تایمر",
     "description": "Label for the button of timer-duration options."
   },
-  "feedbackButton": {
+  "FEEDBACK_BUTTON": {
     "message": "ارسال بازخورد",
     "description": "Label for the feedback button."
   },
-  "helpButton": {
+  "HELP_BUTTON": {
     "message": "راهنما",
     "description": "Label for the help button."
   },
-  "labelGrid3x3": {
+  "LABEL_GRID_3X3": {
     "message": "۳ × ۳",
     "description": "Label for for grid-type: 3x3."
   },
-  "ariaGrid3x3": {
+  "ARIA_GRID_3X3": {
     "message": "۳ در ۳",
     "description": "Label for spoken feedback to read out grid-type: 3x3."
   },
-  "labelGrid4x4": {
+  "LABEL_GRID_4X4": {
     "message": "۴ × ۴",
     "description": "Label for for grid-type: 4x4."
   },
-  "ariaGrid4x4": {
+  "ARIA_GRID_4X4": {
     "message": "۴ در ۴",
     "description": "Label for spoken feedback to read out grid-type: 4x4."
   },
-  "labelGridGolden": {
+  "LABEL_GRID_GOLDEN": {
     "message": "نسبت طلایی",
     "description": "Label for grid-type: golden ratio."
   },
-  "labelTimer3s": {
+  "LABEL_TIMER_3S": {
     "message": "۳ ثانیه",
     "description": "Label for timer-duration: 3 seconds."
   },
-  "labelTimer10s": {
+  "LABEL_TIMER_10S": {
     "message": "۱۰ ثانیه",
     "description": "Label for timer-duration: 10 seconds."
   },
-  "takePhotoButton": {
+  "TAKE_PHOTO_BUTTON": {
     "message": "عکس گرفتن",
     "description": "Label for the shutter button to take photo."
   },
-  "takePhotoCancelButton": {
+  "TAKE_PHOTO_CANCEL_BUTTON": {
     "message": "توقف عکس‌برداری",
     "description": "Label for the shutter button to cancel countdown timer and stop taking photo."
   },
-  "recordVideoStartButton": {
+  "RECORD_VIDEO_START_BUTTON": {
     "message": "شروع ضبط",
     "description": "Label for the shutter button to start recording."
   },
-  "recordVideoStopButton": {
+  "RECORD_VIDEO_STOP_BUTTON": {
     "message": "توقف ضبط",
     "description": "Label for the shutter button to stop recording."
   },
-  "switchCameraButton": {
+  "SWITCH_CAMERA_BUTTON": {
     "message": "جابه‌جایی به دوربین بعدی",
     "description": "Label for the button to switch to next connected camera. Eg. switching from front facing to back facing, or a camera connected via USB. The button is shown only when more than one camera is connected."
   },
-  "switchRecordVideoButton": {
+  "SWITCH_RECORD_VIDEO_BUTTON": {
     "message": "رفتن به حالت فیلم‌برداری",
     "description": "Label for the button to switch to record video mode."
   },
-  "switchTakePhotoButton": {
+  "SWITCH_TAKE_PHOTO_BUTTON": {
     "message": "رفتن به حالت عکس‌برداری",
     "description": "Label for the button to switch to take photo mode."
   },
-  "toggleTimerButton": {
+  "TOGGLE_TIMER_BUTTON": {
     "message": "تایمر",
     "description": "Label for the checkbox to toggle the countdown timer."
   },
-  "toggleMirrorButton": {
+  "TOGGLE_MIRROR_BUTTON": {
     "message": "نمایش صفحه‌نمایش روی دستگاه دیگر",
     "description": "Label for the checkbox to toggle the preview mirroring. Eg. if mirroring is toggled on, preview will be flipped horizontally."
   },
-  "toggleGridButton": {
+  "TOGGLE_GRID_BUTTON": {
     "message": "شطرنجی",
     "description": "Label for the checkbox to toggle the grid shown on preview."
   },
-  "toggleMicButton": {
+  "TOGGLE_MIC_BUTTON": {
     "message": "میکروفون",
     "description": "Label for the checkbox to toggle the microphone for recording video."
   },
-  "dialogOKButton": {
+  "DIALOG_OK_BUTTON": {
     "message": "تأیید",
     "description": "Label for the accepting button in the dialog."
   },
-  "dialogCancelButton": {
+  "DIALOG_CANCEL_BUTTON": {
     "message": "لغو",
     "description": "Label for the dismissing button in the dialog."
   },
-  "deleteConfirmationMsg": {
+  "DELETE_CONFIRMATION_MSG": {
     "message": "واقعاً می‌خواهید $file$ حذف شود؟",
     "description": "Confirmation message before removing a selected item from the gallery. Expects a file name to be passed in.",
     "placeholders": {
@@ -189,7 +189,7 @@
       }
     }
   },
-  "deleteMultiConfirmationMsg": {
+  "DELETE_MULTI_CONFIRMATION_MSG": {
     "message": "واقعاً می‌خواهید $count$ مورد حذف شود؟",
     "description": "Confirmation message before removing multiple selected items from the gallery. Expects a file count to be passed in.",
     "placeholders": {
@@ -199,7 +199,7 @@
       }
     }
   },
-  "migratePicturesMsg": {
+  "MIGRATE_PICTURES_MSG": {
     "message": "عکس‌ها و ویدیوهایی که با دوربین گرفته شده است، به پوشه «بارگیری‌ها» منتقل خواهد شد. می‌توانید در Files به آن‌ها دسترسی داشته باشید.\n\nبرنامه‌هایی که مجوز فضای ذخیره‌سازی دارند، به عکس‌ها و ویدیوهای شما دسترسی خواهند داشت.",
     "description": "Message shown before moving all photos and videos stored in the Camera App to the Downloads folder."
   }
diff --git a/chrome/browser/resources/chromeos/camera/src/_locales/fi/messages.json b/chrome/browser/resources/chromeos/camera/src/_locales/fi/messages.json
index 9c43be12..34ec15504 100644
--- a/chrome/browser/resources/chromeos/camera/src/_locales/fi/messages.json
+++ b/chrome/browser/resources/chromeos/camera/src/_locales/fi/messages.json
@@ -1,21 +1,21 @@
 {
-  "name": {
+  "NAME": {
     "message": "Kamera",
     "description": "Name of the Camera App."
   },
-  "description": {
+  "DESCRIPTION": {
     "message": "Ota kuvia ja videoita kamerallasi.",
     "description": "Short description of the Camera App."
   },
-  "errorMsgFileSystemFailed": {
+  "ERROR_MSG_FILE_SYSTEM_FAILED": {
     "message": "Tiedostojärjestelmän virheitä",
     "description": "Error message shown when failing to read or write the file system."
   },
-  "errorMsgNoCamera": {
+  "ERROR_MSG_NO_CAMERA": {
     "message": "Kamerasi ei ole tällä hetkellä käytettävissä.\nTarkista, onko kamera liitetty oikein.",
     "description": "Error message shown when it was impossible to connect to the camera due to unavailability."
   },
-  "errorMsgGalleryExportFailed": {
+  "ERROR_MSG_GALLERY_EXPORT_FAILED": {
     "message": "Vieminen epäonnistui: $file$.",
     "description": "Error message shown when exporting to an external directory failed. Expects a file name to be passed in.",
     "placeholders": {
@@ -25,27 +25,27 @@
       }
     }
   },
-  "errorMsgSaveFileFailed": {
+  "ERROR_MSG_SAVE_FILE_FAILED": {
     "message": "Tiedoston tallennus epäonnistui.",
     "description": "Error message shown when saving/adding a image or video to the file system failed."
   },
-  "errorMsgTakePhotoFailed": {
+  "ERROR_MSG_TAKE_PHOTO_FAILED": {
     "message": "Kuvan ottaminen epäonnistui.",
     "description": "Error message shown when failing to take photo."
   },
-  "errorMsgRecordStartFailed": {
+  "ERROR_MSG_RECORD_START_FAILED": {
     "message": "Tallennuksen aloittaminen epäonnistui.",
     "description": "Error message shown when failing to start recording video."
   },
-  "errorMsgEmptyRecording": {
+  "ERROR_MSG_EMPTY_RECORDING": {
     "message": "Mitään ei kuvattu.",
     "description": "Error message shown when no data is recorded for a recording and it won't be added to the gallery."
   },
-  "statusMsgRecordingStopped": {
+  "STATUS_MSG_RECORDING_STOPPED": {
     "message": "Tallennus keskeytettiin.",
     "description": "Status message for spoken feedback when video recording has been stopped."
   },
-  "statusMsgCameraSwitched": {
+  "STATUS_MSG_CAMERA_SWITCHED": {
     "message": "$camera$ on aktiivinen.",
     "description": "Status message for spoken feedback when switching over to another camera.",
     "placeholders": {
@@ -55,131 +55,131 @@
       }
     }
   },
-  "galleryButton": {
+  "GALLERY_BUTTON": {
     "message": "Siirry galleriaan",
     "description": "Label for the gallery button."
   },
-  "deleteButton": {
+  "DELETE_BUTTON": {
     "message": "Poista",
     "description": "Label for the delete button."
   },
-  "exportButton": {
+  "EXPORT_BUTTON": {
     "message": "Vie paikalliselle levylle",
     "description": "Label for the exporting button."
   },
-  "printButton": {
+  "PRINT_BUTTON": {
     "message": "Tulosta",
     "description": "Label for the printing button."
   },
-  "backButton": {
+  "BACK_BUTTON": {
     "message": "Takaisin",
     "description": "Label for the back button."
   },
-  "galleryImages": {
+  "GALLERY_IMAGES": {
     "message": "Gallerian kuvat",
     "description": "Text to speech label for the gallery list."
   },
-  "settingsButton": {
+  "SETTINGS_BUTTON": {
     "message": "Asetukset",
     "description": "Label for the settings button."
   },
-  "gridTypeButton": {
+  "GRID_TYPE_BUTTON": {
     "message": "Ruudukkotyyppi",
     "description": "Label for the button of grid-type options."
   },
-  "timerDurationButton": {
+  "TIMER_DURATION_BUTTON": {
     "message": "Ajastimen kesto",
     "description": "Label for the button of timer-duration options."
   },
-  "feedbackButton": {
+  "FEEDBACK_BUTTON": {
     "message": "Lähetä palautetta",
     "description": "Label for the feedback button."
   },
-  "helpButton": {
+  "HELP_BUTTON": {
     "message": "Ohje",
     "description": "Label for the help button."
   },
-  "labelGrid3x3": {
+  "LABEL_GRID_3X3": {
     "message": "3x3",
     "description": "Label for for grid-type: 3x3."
   },
-  "ariaGrid3x3": {
+  "ARIA_GRID_3X3": {
     "message": "3x3",
     "description": "Label for spoken feedback to read out grid-type: 3x3."
   },
-  "labelGrid4x4": {
+  "LABEL_GRID_4X4": {
     "message": "4x4",
     "description": "Label for for grid-type: 4x4."
   },
-  "ariaGrid4x4": {
+  "ARIA_GRID_4X4": {
     "message": "4x4",
     "description": "Label for spoken feedback to read out grid-type: 4x4."
   },
-  "labelGridGolden": {
+  "LABEL_GRID_GOLDEN": {
     "message": "Kultainen leikkaus",
     "description": "Label for grid-type: golden ratio."
   },
-  "labelTimer3s": {
+  "LABEL_TIMER_3S": {
     "message": "3 sekuntia",
     "description": "Label for timer-duration: 3 seconds."
   },
-  "labelTimer10s": {
+  "LABEL_TIMER_10S": {
     "message": "10 sekuntia",
     "description": "Label for timer-duration: 10 seconds."
   },
-  "takePhotoButton": {
+  "TAKE_PHOTO_BUTTON": {
     "message": "Ota valokuva",
     "description": "Label for the shutter button to take photo."
   },
-  "takePhotoCancelButton": {
+  "TAKE_PHOTO_CANCEL_BUTTON": {
     "message": "Lopeta kuvan ottaminen",
     "description": "Label for the shutter button to cancel countdown timer and stop taking photo."
   },
-  "recordVideoStartButton": {
+  "RECORD_VIDEO_START_BUTTON": {
     "message": "Aloita kuvaaminen",
     "description": "Label for the shutter button to start recording."
   },
-  "recordVideoStopButton": {
+  "RECORD_VIDEO_STOP_BUTTON": {
     "message": "Lopeta kuvaaminen",
     "description": "Label for the shutter button to stop recording."
   },
-  "switchCameraButton": {
+  "SWITCH_CAMERA_BUTTON": {
     "message": "Vaihda seuraavaan kameraan",
     "description": "Label for the button to switch to next connected camera. Eg. switching from front facing to back facing, or a camera connected via USB. The button is shown only when more than one camera is connected."
   },
-  "switchRecordVideoButton": {
+  "SWITCH_RECORD_VIDEO_BUTTON": {
     "message": "Vaihda videon kuvaamiseen",
     "description": "Label for the button to switch to record video mode."
   },
-  "switchTakePhotoButton": {
+  "SWITCH_TAKE_PHOTO_BUTTON": {
     "message": "Vaihda kuvan ottamiseen",
     "description": "Label for the button to switch to take photo mode."
   },
-  "toggleTimerButton": {
+  "TOGGLE_TIMER_BUTTON": {
     "message": "Ajastin",
     "description": "Label for the checkbox to toggle the countdown timer."
   },
-  "toggleMirrorButton": {
+  "TOGGLE_MIRROR_BUTTON": {
     "message": "Peilaus",
     "description": "Label for the checkbox to toggle the preview mirroring. Eg. if mirroring is toggled on, preview will be flipped horizontally."
   },
-  "toggleGridButton": {
+  "TOGGLE_GRID_BUTTON": {
     "message": "Ruudukko",
     "description": "Label for the checkbox to toggle the grid shown on preview."
   },
-  "toggleMicButton": {
+  "TOGGLE_MIC_BUTTON": {
     "message": "Mikrofoni",
     "description": "Label for the checkbox to toggle the microphone for recording video."
   },
-  "dialogOKButton": {
+  "DIALOG_OK_BUTTON": {
     "message": "OK",
     "description": "Label for the accepting button in the dialog."
   },
-  "dialogCancelButton": {
+  "DIALOG_CANCEL_BUTTON": {
     "message": "Peruuta",
     "description": "Label for the dismissing button in the dialog."
   },
-  "deleteConfirmationMsg": {
+  "DELETE_CONFIRMATION_MSG": {
     "message": "Haluatko varmasti poistaa tiedoston $file$?",
     "description": "Confirmation message before removing a selected item from the gallery. Expects a file name to be passed in.",
     "placeholders": {
@@ -189,7 +189,7 @@
       }
     }
   },
-  "deleteMultiConfirmationMsg": {
+  "DELETE_MULTI_CONFIRMATION_MSG": {
     "message": "Haluatko varmasti poistaa $count$ kohdetta?",
     "description": "Confirmation message before removing multiple selected items from the gallery. Expects a file count to be passed in.",
     "placeholders": {
@@ -199,7 +199,7 @@
       }
     }
   },
-  "migratePicturesMsg": {
+  "MIGRATE_PICTURES_MSG": {
     "message": "Kameralla otetut kuvat ja videot siirretään Lataukset-kansioon. Voit käyttää niitä avaamalla Tiedostot.\n\nJos sovelluksella on tallennustilan käyttöoikeus, se voi käyttää kuvia ja videoita.",
     "description": "Message shown before moving all photos and videos stored in the Camera App to the Downloads folder."
   }
diff --git a/chrome/browser/resources/chromeos/camera/src/_locales/fil/messages.json b/chrome/browser/resources/chromeos/camera/src/_locales/fil/messages.json
index d1dcb4d..e9fd879 100644
--- a/chrome/browser/resources/chromeos/camera/src/_locales/fil/messages.json
+++ b/chrome/browser/resources/chromeos/camera/src/_locales/fil/messages.json
@@ -1,21 +1,21 @@
 {
-  "name": {
+  "NAME": {
     "message": "Camera",
     "description": "Name of the Camera App."
   },
-  "description": {
+  "DESCRIPTION": {
     "message": "Kumuha ng mga larawan at mag-record ng mga video gamit ang iyong camera.",
     "description": "Short description of the Camera App."
   },
-  "errorMsgFileSystemFailed": {
+  "ERROR_MSG_FILE_SYSTEM_FAILED": {
     "message": "Mga error sa file system.",
     "description": "Error message shown when failing to read or write the file system."
   },
-  "errorMsgNoCamera": {
+  "ERROR_MSG_NO_CAMERA": {
     "message": "Kasalukuyang hindi available ang iyong camera.\nPakitingnan kung nakakonekta nang maayos ang camera.",
     "description": "Error message shown when it was impossible to connect to the camera due to unavailability."
   },
-  "errorMsgGalleryExportFailed": {
+  "ERROR_MSG_GALLERY_EXPORT_FAILED": {
     "message": "Hindi na-export ang $file$",
     "description": "Error message shown when exporting to an external directory failed. Expects a file name to be passed in.",
     "placeholders": {
@@ -25,27 +25,27 @@
       }
     }
   },
-  "errorMsgSaveFileFailed": {
+  "ERROR_MSG_SAVE_FILE_FAILED": {
     "message": "Hindi na-save ang file",
     "description": "Error message shown when saving/adding a image or video to the file system failed."
   },
-  "errorMsgTakePhotoFailed": {
+  "ERROR_MSG_TAKE_PHOTO_FAILED": {
     "message": "Hindi nakakuha ng larawan",
     "description": "Error message shown when failing to take photo."
   },
-  "errorMsgRecordStartFailed": {
+  "ERROR_MSG_RECORD_START_FAILED": {
     "message": "Hindi nasimulan ang pag-record",
     "description": "Error message shown when failing to start recording video."
   },
-  "errorMsgEmptyRecording": {
+  "ERROR_MSG_EMPTY_RECORDING": {
     "message": "Walang na-record",
     "description": "Error message shown when no data is recorded for a recording and it won't be added to the gallery."
   },
-  "statusMsgRecordingStopped": {
+  "STATUS_MSG_RECORDING_STOPPED": {
     "message": "Huminto ang pag-record",
     "description": "Status message for spoken feedback when video recording has been stopped."
   },
-  "statusMsgCameraSwitched": {
+  "STATUS_MSG_CAMERA_SWITCHED": {
     "message": "Aktibo ang $camera$",
     "description": "Status message for spoken feedback when switching over to another camera.",
     "placeholders": {
@@ -55,131 +55,131 @@
       }
     }
   },
-  "galleryButton": {
+  "GALLERY_BUTTON": {
     "message": "Pumunta sa gallery",
     "description": "Label for the gallery button."
   },
-  "deleteButton": {
+  "DELETE_BUTTON": {
     "message": "I-delete",
     "description": "Label for the delete button."
   },
-  "exportButton": {
+  "EXPORT_BUTTON": {
     "message": "I-export sa disk",
     "description": "Label for the exporting button."
   },
-  "printButton": {
+  "PRINT_BUTTON": {
     "message": "I-print",
     "description": "Label for the printing button."
   },
-  "backButton": {
+  "BACK_BUTTON": {
     "message": "Bumalik",
     "description": "Label for the back button."
   },
-  "galleryImages": {
+  "GALLERY_IMAGES": {
     "message": "Mga larawan sa gallery",
     "description": "Text to speech label for the gallery list."
   },
-  "settingsButton": {
+  "SETTINGS_BUTTON": {
     "message": "Mga Setting",
     "description": "Label for the settings button."
   },
-  "gridTypeButton": {
+  "GRID_TYPE_BUTTON": {
     "message": "Uri ng grid",
     "description": "Label for the button of grid-type options."
   },
-  "timerDurationButton": {
+  "TIMER_DURATION_BUTTON": {
     "message": "Tagal ng timer",
     "description": "Label for the button of timer-duration options."
   },
-  "feedbackButton": {
+  "FEEDBACK_BUTTON": {
     "message": "Magpadala ng feedback",
     "description": "Label for the feedback button."
   },
-  "helpButton": {
+  "HELP_BUTTON": {
     "message": "Tulong",
     "description": "Label for the help button."
   },
-  "labelGrid3x3": {
+  "LABEL_GRID_3X3": {
     "message": "3 x 3",
     "description": "Label for for grid-type: 3x3."
   },
-  "ariaGrid3x3": {
+  "ARIA_GRID_3X3": {
     "message": "3 by 3",
     "description": "Label for spoken feedback to read out grid-type: 3x3."
   },
-  "labelGrid4x4": {
+  "LABEL_GRID_4X4": {
     "message": "4 x 4",
     "description": "Label for for grid-type: 4x4."
   },
-  "ariaGrid4x4": {
+  "ARIA_GRID_4X4": {
     "message": "4 by 4",
     "description": "Label for spoken feedback to read out grid-type: 4x4."
   },
-  "labelGridGolden": {
+  "LABEL_GRID_GOLDEN": {
     "message": "Golden ratio",
     "description": "Label for grid-type: golden ratio."
   },
-  "labelTimer3s": {
+  "LABEL_TIMER_3S": {
     "message": "3 segundo",
     "description": "Label for timer-duration: 3 seconds."
   },
-  "labelTimer10s": {
+  "LABEL_TIMER_10S": {
     "message": "10 segundo",
     "description": "Label for timer-duration: 10 seconds."
   },
-  "takePhotoButton": {
+  "TAKE_PHOTO_BUTTON": {
     "message": "Kumuha ng larawan",
     "description": "Label for the shutter button to take photo."
   },
-  "takePhotoCancelButton": {
+  "TAKE_PHOTO_CANCEL_BUTTON": {
     "message": "Ihinto ang pagkuha ng larawan",
     "description": "Label for the shutter button to cancel countdown timer and stop taking photo."
   },
-  "recordVideoStartButton": {
+  "RECORD_VIDEO_START_BUTTON": {
     "message": "Magsimulang mag-record",
     "description": "Label for the shutter button to start recording."
   },
-  "recordVideoStopButton": {
+  "RECORD_VIDEO_STOP_BUTTON": {
     "message": "Ihinto ang pag-record",
     "description": "Label for the shutter button to stop recording."
   },
-  "switchCameraButton": {
+  "SWITCH_CAMERA_BUTTON": {
     "message": "Lumipat sa susunod na camera",
     "description": "Label for the button to switch to next connected camera. Eg. switching from front facing to back facing, or a camera connected via USB. The button is shown only when more than one camera is connected."
   },
-  "switchRecordVideoButton": {
+  "SWITCH_RECORD_VIDEO_BUTTON": {
     "message": "Lumipat sa pag-record ng video",
     "description": "Label for the button to switch to record video mode."
   },
-  "switchTakePhotoButton": {
+  "SWITCH_TAKE_PHOTO_BUTTON": {
     "message": "Lumipat sa pagkuha ng larawan",
     "description": "Label for the button to switch to take photo mode."
   },
-  "toggleTimerButton": {
+  "TOGGLE_TIMER_BUTTON": {
     "message": "Timer",
     "description": "Label for the checkbox to toggle the countdown timer."
   },
-  "toggleMirrorButton": {
+  "TOGGLE_MIRROR_BUTTON": {
     "message": "Pag-mirror",
     "description": "Label for the checkbox to toggle the preview mirroring. Eg. if mirroring is toggled on, preview will be flipped horizontally."
   },
-  "toggleGridButton": {
+  "TOGGLE_GRID_BUTTON": {
     "message": "Grid",
     "description": "Label for the checkbox to toggle the grid shown on preview."
   },
-  "toggleMicButton": {
+  "TOGGLE_MIC_BUTTON": {
     "message": "Mikropono",
     "description": "Label for the checkbox to toggle the microphone for recording video."
   },
-  "dialogOKButton": {
+  "DIALOG_OK_BUTTON": {
     "message": "OK",
     "description": "Label for the accepting button in the dialog."
   },
-  "dialogCancelButton": {
+  "DIALOG_CANCEL_BUTTON": {
     "message": "Kanselahin",
     "description": "Label for the dismissing button in the dialog."
   },
-  "deleteConfirmationMsg": {
+  "DELETE_CONFIRMATION_MSG": {
     "message": "Gusto mo ba talagang alisin ang $file$?",
     "description": "Confirmation message before removing a selected item from the gallery. Expects a file name to be passed in.",
     "placeholders": {
@@ -189,7 +189,7 @@
       }
     }
   },
-  "deleteMultiConfirmationMsg": {
+  "DELETE_MULTI_CONFIRMATION_MSG": {
     "message": "Gusto mo ba talagang alisin ang $count$ (na) item?",
     "description": "Confirmation message before removing multiple selected items from the gallery. Expects a file count to be passed in.",
     "placeholders": {
@@ -199,7 +199,7 @@
       }
     }
   },
-  "migratePicturesMsg": {
+  "MIGRATE_PICTURES_MSG": {
     "message": "Ang mga larawan at video na nakunan gamit ang camera ay ililipat sa folder na Mga Download. Maa-access mo ang mga ito sa Mga File.\n\nAng mga app na may mga pahintulot sa storage ay magkakaroon ng access sa iyong mga larawan at video.",
     "description": "Message shown before moving all photos and videos stored in the Camera App to the Downloads folder."
   }
diff --git a/chrome/browser/resources/chromeos/camera/src/_locales/fr/messages.json b/chrome/browser/resources/chromeos/camera/src/_locales/fr/messages.json
index ce31927f..d5864cfb 100644
--- a/chrome/browser/resources/chromeos/camera/src/_locales/fr/messages.json
+++ b/chrome/browser/resources/chromeos/camera/src/_locales/fr/messages.json
@@ -1,21 +1,21 @@
 {
-  "name": {
+  "NAME": {
     "message": "Appareil photo",
     "description": "Name of the Camera App."
   },
-  "description": {
+  "DESCRIPTION": {
     "message": "Prenez des photos et enregistrez des vidéos avec votre appareil photo.",
     "description": "Short description of the Camera App."
   },
-  "errorMsgFileSystemFailed": {
+  "ERROR_MSG_FILE_SYSTEM_FAILED": {
     "message": "Erreurs du système de fichiers.",
     "description": "Error message shown when failing to read or write the file system."
   },
-  "errorMsgNoCamera": {
+  "ERROR_MSG_NO_CAMERA": {
     "message": "Votre caméra est actuellement indisponible.\nVérifiez qu'elle est bien connectée.",
     "description": "Error message shown when it was impossible to connect to the camera due to unavailability."
   },
-  "errorMsgGalleryExportFailed": {
+  "ERROR_MSG_GALLERY_EXPORT_FAILED": {
     "message": "Impossible d'exporter $file$",
     "description": "Error message shown when exporting to an external directory failed. Expects a file name to be passed in.",
     "placeholders": {
@@ -25,27 +25,27 @@
       }
     }
   },
-  "errorMsgSaveFileFailed": {
+  "ERROR_MSG_SAVE_FILE_FAILED": {
     "message": "Impossible d'enregistrer le fichier",
     "description": "Error message shown when saving/adding a image or video to the file system failed."
   },
-  "errorMsgTakePhotoFailed": {
+  "ERROR_MSG_TAKE_PHOTO_FAILED": {
     "message": "Impossible de prendre la photo",
     "description": "Error message shown when failing to take photo."
   },
-  "errorMsgRecordStartFailed": {
+  "ERROR_MSG_RECORD_START_FAILED": {
     "message": "Impossible de démarrer l'enregistrement",
     "description": "Error message shown when failing to start recording video."
   },
-  "errorMsgEmptyRecording": {
+  "ERROR_MSG_EMPTY_RECORDING": {
     "message": "Aucune donnée enregistrée",
     "description": "Error message shown when no data is recorded for a recording and it won't be added to the gallery."
   },
-  "statusMsgRecordingStopped": {
+  "STATUS_MSG_RECORDING_STOPPED": {
     "message": "Enregistrement interrompu",
     "description": "Status message for spoken feedback when video recording has been stopped."
   },
-  "statusMsgCameraSwitched": {
+  "STATUS_MSG_CAMERA_SWITCHED": {
     "message": "$camera$ active",
     "description": "Status message for spoken feedback when switching over to another camera.",
     "placeholders": {
@@ -55,131 +55,131 @@
       }
     }
   },
-  "galleryButton": {
+  "GALLERY_BUTTON": {
     "message": "Accéder à la galerie",
     "description": "Label for the gallery button."
   },
-  "deleteButton": {
+  "DELETE_BUTTON": {
     "message": "Supprimer",
     "description": "Label for the delete button."
   },
-  "exportButton": {
+  "EXPORT_BUTTON": {
     "message": "Exporter vers le disque",
     "description": "Label for the exporting button."
   },
-  "printButton": {
+  "PRINT_BUTTON": {
     "message": "Imprimer",
     "description": "Label for the printing button."
   },
-  "backButton": {
+  "BACK_BUTTON": {
     "message": "Retour",
     "description": "Label for the back button."
   },
-  "galleryImages": {
+  "GALLERY_IMAGES": {
     "message": "Images de la galerie",
     "description": "Text to speech label for the gallery list."
   },
-  "settingsButton": {
+  "SETTINGS_BUTTON": {
     "message": "Paramètres",
     "description": "Label for the settings button."
   },
-  "gridTypeButton": {
+  "GRID_TYPE_BUTTON": {
     "message": "Type de grille",
     "description": "Label for the button of grid-type options."
   },
-  "timerDurationButton": {
+  "TIMER_DURATION_BUTTON": {
     "message": "Durée du minuteur",
     "description": "Label for the button of timer-duration options."
   },
-  "feedbackButton": {
+  "FEEDBACK_BUTTON": {
     "message": "Envoyer des commentaires",
     "description": "Label for the feedback button."
   },
-  "helpButton": {
+  "HELP_BUTTON": {
     "message": "Aide",
     "description": "Label for the help button."
   },
-  "labelGrid3x3": {
+  "LABEL_GRID_3X3": {
     "message": "3 x 3",
     "description": "Label for for grid-type: 3x3."
   },
-  "ariaGrid3x3": {
+  "ARIA_GRID_3X3": {
     "message": "3 par 3",
     "description": "Label for spoken feedback to read out grid-type: 3x3."
   },
-  "labelGrid4x4": {
+  "LABEL_GRID_4X4": {
     "message": "4 x 4",
     "description": "Label for for grid-type: 4x4."
   },
-  "ariaGrid4x4": {
+  "ARIA_GRID_4X4": {
     "message": "4 par 4",
     "description": "Label for spoken feedback to read out grid-type: 4x4."
   },
-  "labelGridGolden": {
+  "LABEL_GRID_GOLDEN": {
     "message": "Rectangle d'or",
     "description": "Label for grid-type: golden ratio."
   },
-  "labelTimer3s": {
+  "LABEL_TIMER_3S": {
     "message": "3 secondes",
     "description": "Label for timer-duration: 3 seconds."
   },
-  "labelTimer10s": {
+  "LABEL_TIMER_10S": {
     "message": "10 secondes",
     "description": "Label for timer-duration: 10 seconds."
   },
-  "takePhotoButton": {
+  "TAKE_PHOTO_BUTTON": {
     "message": "Prendre une photo",
     "description": "Label for the shutter button to take photo."
   },
-  "takePhotoCancelButton": {
+  "TAKE_PHOTO_CANCEL_BUTTON": {
     "message": "Arrêter de prendre la photo",
     "description": "Label for the shutter button to cancel countdown timer and stop taking photo."
   },
-  "recordVideoStartButton": {
+  "RECORD_VIDEO_START_BUTTON": {
     "message": "Commencer l'enregistrement",
     "description": "Label for the shutter button to start recording."
   },
-  "recordVideoStopButton": {
+  "RECORD_VIDEO_STOP_BUTTON": {
     "message": "Arrêter l'enregistrement",
     "description": "Label for the shutter button to stop recording."
   },
-  "switchCameraButton": {
+  "SWITCH_CAMERA_BUTTON": {
     "message": "Passer à la caméra suivante",
     "description": "Label for the button to switch to next connected camera. Eg. switching from front facing to back facing, or a camera connected via USB. The button is shown only when more than one camera is connected."
   },
-  "switchRecordVideoButton": {
+  "SWITCH_RECORD_VIDEO_BUTTON": {
     "message": "Passer à l'enregistrement de vidéo",
     "description": "Label for the button to switch to record video mode."
   },
-  "switchTakePhotoButton": {
+  "SWITCH_TAKE_PHOTO_BUTTON": {
     "message": "Passer à la prise de photo",
     "description": "Label for the button to switch to take photo mode."
   },
-  "toggleTimerButton": {
+  "TOGGLE_TIMER_BUTTON": {
     "message": "Minuteur",
     "description": "Label for the checkbox to toggle the countdown timer."
   },
-  "toggleMirrorButton": {
+  "TOGGLE_MIRROR_BUTTON": {
     "message": "Duplication d'écran",
     "description": "Label for the checkbox to toggle the preview mirroring. Eg. if mirroring is toggled on, preview will be flipped horizontally."
   },
-  "toggleGridButton": {
+  "TOGGLE_GRID_BUTTON": {
     "message": "Grille",
     "description": "Label for the checkbox to toggle the grid shown on preview."
   },
-  "toggleMicButton": {
+  "TOGGLE_MIC_BUTTON": {
     "message": "Micro",
     "description": "Label for the checkbox to toggle the microphone for recording video."
   },
-  "dialogOKButton": {
+  "DIALOG_OK_BUTTON": {
     "message": "OK",
     "description": "Label for the accepting button in the dialog."
   },
-  "dialogCancelButton": {
+  "DIALOG_CANCEL_BUTTON": {
     "message": "Annuler",
     "description": "Label for the dismissing button in the dialog."
   },
-  "deleteConfirmationMsg": {
+  "DELETE_CONFIRMATION_MSG": {
     "message": "Voulez-vous vraiment supprimer $file$ ?",
     "description": "Confirmation message before removing a selected item from the gallery. Expects a file name to be passed in.",
     "placeholders": {
@@ -189,7 +189,7 @@
       }
     }
   },
-  "deleteMultiConfirmationMsg": {
+  "DELETE_MULTI_CONFIRMATION_MSG": {
     "message": "Voulez-vous vraiment supprimer $count$ éléments ?",
     "description": "Confirmation message before removing multiple selected items from the gallery. Expects a file count to be passed in.",
     "placeholders": {
@@ -199,7 +199,7 @@
       }
     }
   },
-  "migratePicturesMsg": {
+  "MIGRATE_PICTURES_MSG": {
     "message": "Les photos et vidéos prises avec l'appareil photo seront déplacées vers le dossier \"Téléchargements\". Vous pouvez y accéder via l'application Fichiers.\n\nLes applications disposant d'autorisations d'accès à l'espace de stockage pourront accéder à vos photos et vidéos.",
     "description": "Message shown before moving all photos and videos stored in the Camera App to the Downloads folder."
   }
diff --git a/chrome/browser/resources/chromeos/camera/src/_locales/gu/messages.json b/chrome/browser/resources/chromeos/camera/src/_locales/gu/messages.json
index a583dd8..1c34c47 100644
--- a/chrome/browser/resources/chromeos/camera/src/_locales/gu/messages.json
+++ b/chrome/browser/resources/chromeos/camera/src/_locales/gu/messages.json
@@ -1,21 +1,21 @@
 {
-  "name": {
+  "NAME": {
     "message": "કૅમેરા",
     "description": "Name of the Camera App."
   },
-  "description": {
+  "DESCRIPTION": {
     "message": "તમારા કૅમેરા વડે ફોટા લો અને વીડિઓ રેકોર્ડ કરો.",
     "description": "Short description of the Camera App."
   },
-  "errorMsgFileSystemFailed": {
+  "ERROR_MSG_FILE_SYSTEM_FAILED": {
     "message": "ફાઇલ સિસ્ટમની ભૂલો.",
     "description": "Error message shown when failing to read or write the file system."
   },
-  "errorMsgNoCamera": {
+  "ERROR_MSG_NO_CAMERA": {
     "message": "તમારો કૅમેરા હાલમાં અનુપલબ્ધ છે.\nકૃપા કરીને ચેક કરો કે કૅમેરા યોગ્ય રીતે કનેક્ટ થયેલો છે.",
     "description": "Error message shown when it was impossible to connect to the camera due to unavailability."
   },
-  "errorMsgGalleryExportFailed": {
+  "ERROR_MSG_GALLERY_EXPORT_FAILED": {
     "message": "$file$ને નિકાસ કરવામાં નિષ્ફળ રહ્યાં",
     "description": "Error message shown when exporting to an external directory failed. Expects a file name to be passed in.",
     "placeholders": {
@@ -25,27 +25,27 @@
       }
     }
   },
-  "errorMsgSaveFileFailed": {
+  "ERROR_MSG_SAVE_FILE_FAILED": {
     "message": "ફાઇલ સાચવવામાં નિષ્ફળ રહ્યાં",
     "description": "Error message shown when saving/adding a image or video to the file system failed."
   },
-  "errorMsgTakePhotoFailed": {
+  "ERROR_MSG_TAKE_PHOTO_FAILED": {
     "message": "ફોટો લેવામાં નિષ્ફળ રહ્યાં",
     "description": "Error message shown when failing to take photo."
   },
-  "errorMsgRecordStartFailed": {
+  "ERROR_MSG_RECORD_START_FAILED": {
     "message": "રેકોર્ડિંગ શરૂ કરવામાં નિષ્ફળ રહ્યાં",
     "description": "Error message shown when failing to start recording video."
   },
-  "errorMsgEmptyRecording": {
+  "ERROR_MSG_EMPTY_RECORDING": {
     "message": "કંઈ રેકોર્ડ થયું નથી",
     "description": "Error message shown when no data is recorded for a recording and it won't be added to the gallery."
   },
-  "statusMsgRecordingStopped": {
+  "STATUS_MSG_RECORDING_STOPPED": {
     "message": "રેકોર્ડિંગ બંધ કર્યું",
     "description": "Status message for spoken feedback when video recording has been stopped."
   },
-  "statusMsgCameraSwitched": {
+  "STATUS_MSG_CAMERA_SWITCHED": {
     "message": "$camera$ સક્રિય",
     "description": "Status message for spoken feedback when switching over to another camera.",
     "placeholders": {
@@ -55,131 +55,131 @@
       }
     }
   },
-  "galleryButton": {
+  "GALLERY_BUTTON": {
     "message": "ગૅલેરી પર જાઓ",
     "description": "Label for the gallery button."
   },
-  "deleteButton": {
+  "DELETE_BUTTON": {
     "message": "ડિલીટ કરો",
     "description": "Label for the delete button."
   },
-  "exportButton": {
+  "EXPORT_BUTTON": {
     "message": "ડિસ્કમાં નિકાસ કરો",
     "description": "Label for the exporting button."
   },
-  "printButton": {
+  "PRINT_BUTTON": {
     "message": "પ્રિન્ટ કરો",
     "description": "Label for the printing button."
   },
-  "backButton": {
+  "BACK_BUTTON": {
     "message": "પાછા જાઓ",
     "description": "Label for the back button."
   },
-  "galleryImages": {
+  "GALLERY_IMAGES": {
     "message": "ગૅલેરી છબીઓ",
     "description": "Text to speech label for the gallery list."
   },
-  "settingsButton": {
+  "SETTINGS_BUTTON": {
     "message": "સેટિંગ",
     "description": "Label for the settings button."
   },
-  "gridTypeButton": {
+  "GRID_TYPE_BUTTON": {
     "message": "ગ્રિડનો પ્રકાર",
     "description": "Label for the button of grid-type options."
   },
-  "timerDurationButton": {
+  "TIMER_DURATION_BUTTON": {
     "message": "ટાઇમરનો અવધિ",
     "description": "Label for the button of timer-duration options."
   },
-  "feedbackButton": {
+  "FEEDBACK_BUTTON": {
     "message": "પ્રતિસાદ મોકલો",
     "description": "Label for the feedback button."
   },
-  "helpButton": {
+  "HELP_BUTTON": {
     "message": "સહાય",
     "description": "Label for the help button."
   },
-  "labelGrid3x3": {
+  "LABEL_GRID_3X3": {
     "message": "3 x 3",
     "description": "Label for for grid-type: 3x3."
   },
-  "ariaGrid3x3": {
+  "ARIA_GRID_3X3": {
     "message": "3 બાય 3",
     "description": "Label for spoken feedback to read out grid-type: 3x3."
   },
-  "labelGrid4x4": {
+  "LABEL_GRID_4X4": {
     "message": "4 x 4",
     "description": "Label for for grid-type: 4x4."
   },
-  "ariaGrid4x4": {
+  "ARIA_GRID_4X4": {
     "message": "4 બાય 4",
     "description": "Label for spoken feedback to read out grid-type: 4x4."
   },
-  "labelGridGolden": {
+  "LABEL_GRID_GOLDEN": {
     "message": "ગોલ્ડન રેશિયો",
     "description": "Label for grid-type: golden ratio."
   },
-  "labelTimer3s": {
+  "LABEL_TIMER_3S": {
     "message": "3 સેકન્ડ",
     "description": "Label for timer-duration: 3 seconds."
   },
-  "labelTimer10s": {
+  "LABEL_TIMER_10S": {
     "message": "10 સેકન્ડ",
     "description": "Label for timer-duration: 10 seconds."
   },
-  "takePhotoButton": {
+  "TAKE_PHOTO_BUTTON": {
     "message": "ફોટો લો",
     "description": "Label for the shutter button to take photo."
   },
-  "takePhotoCancelButton": {
+  "TAKE_PHOTO_CANCEL_BUTTON": {
     "message": "ફોટા લેવાનું બંધ કરો",
     "description": "Label for the shutter button to cancel countdown timer and stop taking photo."
   },
-  "recordVideoStartButton": {
+  "RECORD_VIDEO_START_BUTTON": {
     "message": "રેકોર્ડિંગ શરૂ કરો",
     "description": "Label for the shutter button to start recording."
   },
-  "recordVideoStopButton": {
+  "RECORD_VIDEO_STOP_BUTTON": {
     "message": "રેકોર્ડિંગ રોકો",
     "description": "Label for the shutter button to stop recording."
   },
-  "switchCameraButton": {
+  "SWITCH_CAMERA_BUTTON": {
     "message": "આગલા કૅમેરા પર સ્વિચ કરો",
     "description": "Label for the button to switch to next connected camera. Eg. switching from front facing to back facing, or a camera connected via USB. The button is shown only when more than one camera is connected."
   },
-  "switchRecordVideoButton": {
+  "SWITCH_RECORD_VIDEO_BUTTON": {
     "message": "વીડિયો રેકોર્ડ કરવા માટે સ્વિચ કરો",
     "description": "Label for the button to switch to record video mode."
   },
-  "switchTakePhotoButton": {
+  "SWITCH_TAKE_PHOTO_BUTTON": {
     "message": "ફોટો લેવા માટે સ્વિચ કરો",
     "description": "Label for the button to switch to take photo mode."
   },
-  "toggleTimerButton": {
+  "TOGGLE_TIMER_BUTTON": {
     "message": "ટાઇમર",
     "description": "Label for the checkbox to toggle the countdown timer."
   },
-  "toggleMirrorButton": {
+  "TOGGLE_MIRROR_BUTTON": {
     "message": "મીરરીંગ",
     "description": "Label for the checkbox to toggle the preview mirroring. Eg. if mirroring is toggled on, preview will be flipped horizontally."
   },
-  "toggleGridButton": {
+  "TOGGLE_GRID_BUTTON": {
     "message": "ગ્રિડ",
     "description": "Label for the checkbox to toggle the grid shown on preview."
   },
-  "toggleMicButton": {
+  "TOGGLE_MIC_BUTTON": {
     "message": "માઇક્રોફોન",
     "description": "Label for the checkbox to toggle the microphone for recording video."
   },
-  "dialogOKButton": {
+  "DIALOG_OK_BUTTON": {
     "message": "ઓકે",
     "description": "Label for the accepting button in the dialog."
   },
-  "dialogCancelButton": {
+  "DIALOG_CANCEL_BUTTON": {
     "message": "રદ કરો",
     "description": "Label for the dismissing button in the dialog."
   },
-  "deleteConfirmationMsg": {
+  "DELETE_CONFIRMATION_MSG": {
     "message": "શું તમે ખરેખર $file$ને કાઢી નાખવા માગો છો?",
     "description": "Confirmation message before removing a selected item from the gallery. Expects a file name to be passed in.",
     "placeholders": {
@@ -189,7 +189,7 @@
       }
     }
   },
-  "deleteMultiConfirmationMsg": {
+  "DELETE_MULTI_CONFIRMATION_MSG": {
     "message": "શું તમે ખરેખર $count$ આઇટમ કાઢી નાખવા માગો છો?",
     "description": "Confirmation message before removing multiple selected items from the gallery. Expects a file count to be passed in.",
     "placeholders": {
@@ -199,7 +199,7 @@
       }
     }
   },
-  "migratePicturesMsg": {
+  "MIGRATE_PICTURES_MSG": {
     "message": "કૅમેરા વડે લીધેલા ફોટા અને વીડિઓ ડાઉનલોડ ફોલ્ડરમાં ખસેડવામાં આવશે. તમે તેઓને ફાઇલોમાં ઍક્સેસ કરી શકશો.\n\nસ્ટોરેજ માટે પરવાનગી ધરાવતી ઍપ તમારા ફોટા તથા વીડિઓને ઍક્સેસ કરી શકશે.",
     "description": "Message shown before moving all photos and videos stored in the Camera App to the Downloads folder."
   }
diff --git a/chrome/browser/resources/chromeos/camera/src/_locales/he/messages.json b/chrome/browser/resources/chromeos/camera/src/_locales/he/messages.json
index eb27e03..954d5ae4 100644
--- a/chrome/browser/resources/chromeos/camera/src/_locales/he/messages.json
+++ b/chrome/browser/resources/chromeos/camera/src/_locales/he/messages.json
@@ -1,21 +1,21 @@
 {
-  "name": {
+  "NAME": {
     "message": "מצלמה",
     "description": "Name of the Camera App."
   },
-  "description": {
+  "DESCRIPTION": {
     "message": "צילום תמונות וסרטונים באמצעות המצלמה.",
     "description": "Short description of the Camera App."
   },
-  "errorMsgFileSystemFailed": {
+  "ERROR_MSG_FILE_SYSTEM_FAILED": {
     "message": "שגיאות במערכת הקבצים.",
     "description": "Error message shown when failing to read or write the file system."
   },
-  "errorMsgNoCamera": {
+  "ERROR_MSG_NO_CAMERA": {
     "message": "המצלמה לא זמינה כרגע.\nיש לבדוק אם היא מחוברת כראוי.",
     "description": "Error message shown when it was impossible to connect to the camera due to unavailability."
   },
-  "errorMsgGalleryExportFailed": {
+  "ERROR_MSG_GALLERY_EXPORT_FAILED": {
     "message": "לא ניתן לייצא את $file$",
     "description": "Error message shown when exporting to an external directory failed. Expects a file name to be passed in.",
     "placeholders": {
@@ -25,27 +25,27 @@
       }
     }
   },
-  "errorMsgSaveFileFailed": {
+  "ERROR_MSG_SAVE_FILE_FAILED": {
     "message": "לא ניתן לשמור את הקובץ",
     "description": "Error message shown when saving/adding a image or video to the file system failed."
   },
-  "errorMsgTakePhotoFailed": {
+  "ERROR_MSG_TAKE_PHOTO_FAILED": {
     "message": "לא ניתן לצלם את התמונה",
     "description": "Error message shown when failing to take photo."
   },
-  "errorMsgRecordStartFailed": {
+  "ERROR_MSG_RECORD_START_FAILED": {
     "message": "לא ניתן להתחיל בצילום סרטון",
     "description": "Error message shown when failing to start recording video."
   },
-  "errorMsgEmptyRecording": {
+  "ERROR_MSG_EMPTY_RECORDING": {
     "message": "לא צולם סרטון",
     "description": "Error message shown when no data is recorded for a recording and it won't be added to the gallery."
   },
-  "statusMsgRecordingStopped": {
+  "STATUS_MSG_RECORDING_STOPPED": {
     "message": "צילום הסרטון הופסק",
     "description": "Status message for spoken feedback when video recording has been stopped."
   },
-  "statusMsgCameraSwitched": {
+  "STATUS_MSG_CAMERA_SWITCHED": {
     "message": "$camera$ פעילה",
     "description": "Status message for spoken feedback when switching over to another camera.",
     "placeholders": {
@@ -55,131 +55,131 @@
       }
     }
   },
-  "galleryButton": {
+  "GALLERY_BUTTON": {
     "message": "מעבר אל הגלריה",
     "description": "Label for the gallery button."
   },
-  "deleteButton": {
+  "DELETE_BUTTON": {
     "message": "מחיקה",
     "description": "Label for the delete button."
   },
-  "exportButton": {
+  "EXPORT_BUTTON": {
     "message": "ייצוא לדיסק",
     "description": "Label for the exporting button."
   },
-  "printButton": {
+  "PRINT_BUTTON": {
     "message": "הדפסה",
     "description": "Label for the printing button."
   },
-  "backButton": {
+  "BACK_BUTTON": {
     "message": "חזרה",
     "description": "Label for the back button."
   },
-  "galleryImages": {
+  "GALLERY_IMAGES": {
     "message": "תמונות בגלריה",
     "description": "Text to speech label for the gallery list."
   },
-  "settingsButton": {
+  "SETTINGS_BUTTON": {
     "message": "הגדרות",
     "description": "Label for the settings button."
   },
-  "gridTypeButton": {
+  "GRID_TYPE_BUTTON": {
     "message": "סוג הרשת",
     "description": "Label for the button of grid-type options."
   },
-  "timerDurationButton": {
+  "TIMER_DURATION_BUTTON": {
     "message": "משך זמן בטיימר",
     "description": "Label for the button of timer-duration options."
   },
-  "feedbackButton": {
+  "FEEDBACK_BUTTON": {
     "message": "שליחת משוב",
     "description": "Label for the feedback button."
   },
-  "helpButton": {
+  "HELP_BUTTON": {
     "message": "עזרה",
     "description": "Label for the help button."
   },
-  "labelGrid3x3": {
+  "LABEL_GRID_3X3": {
     "message": "‎3 x 3",
     "description": "Label for for grid-type: 3x3."
   },
-  "ariaGrid3x3": {
+  "ARIA_GRID_3X3": {
     "message": "3 על 3",
     "description": "Label for spoken feedback to read out grid-type: 3x3."
   },
-  "labelGrid4x4": {
+  "LABEL_GRID_4X4": {
     "message": "‎4 x 4",
     "description": "Label for for grid-type: 4x4."
   },
-  "ariaGrid4x4": {
+  "ARIA_GRID_4X4": {
     "message": "4 על 4",
     "description": "Label for spoken feedback to read out grid-type: 4x4."
   },
-  "labelGridGolden": {
+  "LABEL_GRID_GOLDEN": {
     "message": "יחס הזהב",
     "description": "Label for grid-type: golden ratio."
   },
-  "labelTimer3s": {
+  "LABEL_TIMER_3S": {
     "message": "3 שניות",
     "description": "Label for timer-duration: 3 seconds."
   },
-  "labelTimer10s": {
+  "LABEL_TIMER_10S": {
     "message": "10 שניות",
     "description": "Label for timer-duration: 10 seconds."
   },
-  "takePhotoButton": {
+  "TAKE_PHOTO_BUTTON": {
     "message": "צילום התמונה",
     "description": "Label for the shutter button to take photo."
   },
-  "takePhotoCancelButton": {
+  "TAKE_PHOTO_CANCEL_BUTTON": {
     "message": "הפסקת הצילום",
     "description": "Label for the shutter button to cancel countdown timer and stop taking photo."
   },
-  "recordVideoStartButton": {
+  "RECORD_VIDEO_START_BUTTON": {
     "message": "התחלת צילום סרטון",
     "description": "Label for the shutter button to start recording."
   },
-  "recordVideoStopButton": {
+  "RECORD_VIDEO_STOP_BUTTON": {
     "message": "הפסקת צילום הסרטון",
     "description": "Label for the shutter button to stop recording."
   },
-  "switchCameraButton": {
+  "SWITCH_CAMERA_BUTTON": {
     "message": "מעבר למצלמה הבאה",
     "description": "Label for the button to switch to next connected camera. Eg. switching from front facing to back facing, or a camera connected via USB. The button is shown only when more than one camera is connected."
   },
-  "switchRecordVideoButton": {
+  "SWITCH_RECORD_VIDEO_BUTTON": {
     "message": "מעבר לצילום סרטון",
     "description": "Label for the button to switch to record video mode."
   },
-  "switchTakePhotoButton": {
+  "SWITCH_TAKE_PHOTO_BUTTON": {
     "message": "מעבר לצילום תמונה",
     "description": "Label for the button to switch to take photo mode."
   },
-  "toggleTimerButton": {
+  "TOGGLE_TIMER_BUTTON": {
     "message": "טיימר",
     "description": "Label for the checkbox to toggle the countdown timer."
   },
-  "toggleMirrorButton": {
+  "TOGGLE_MIRROR_BUTTON": {
     "message": "שיקוף",
     "description": "Label for the checkbox to toggle the preview mirroring. Eg. if mirroring is toggled on, preview will be flipped horizontally."
   },
-  "toggleGridButton": {
+  "TOGGLE_GRID_BUTTON": {
     "message": "רשת",
     "description": "Label for the checkbox to toggle the grid shown on preview."
   },
-  "toggleMicButton": {
+  "TOGGLE_MIC_BUTTON": {
     "message": "מיקרופון",
     "description": "Label for the checkbox to toggle the microphone for recording video."
   },
-  "dialogOKButton": {
+  "DIALOG_OK_BUTTON": {
     "message": "אישור",
     "description": "Label for the accepting button in the dialog."
   },
-  "dialogCancelButton": {
+  "DIALOG_CANCEL_BUTTON": {
     "message": "ביטול",
     "description": "Label for the dismissing button in the dialog."
   },
-  "deleteConfirmationMsg": {
+  "DELETE_CONFIRMATION_MSG": {
     "message": "להסיר את $file$?",
     "description": "Confirmation message before removing a selected item from the gallery. Expects a file name to be passed in.",
     "placeholders": {
@@ -189,7 +189,7 @@
       }
     }
   },
-  "deleteMultiConfirmationMsg": {
+  "DELETE_MULTI_CONFIRMATION_MSG": {
     "message": "להסיר את $count$ הפריטים?",
     "description": "Confirmation message before removing multiple selected items from the gallery. Expects a file count to be passed in.",
     "placeholders": {
@@ -199,7 +199,7 @@
       }
     }
   },
-  "migratePicturesMsg": {
+  "MIGRATE_PICTURES_MSG": {
     "message": "תמונות וסרטונים שצולמו באמצעות המצלמה יועברו אל התיקייה 'הורדות'. אפשר לגשת אליהם דרך 'קבצים'.\n\nאפליקציות עם הרשאות אחסון יקבלו גישה אל התמונות והסרטונים.",
     "description": "Message shown before moving all photos and videos stored in the Camera App to the Downloads folder."
   }
diff --git a/chrome/browser/resources/chromeos/camera/src/_locales/hi/messages.json b/chrome/browser/resources/chromeos/camera/src/_locales/hi/messages.json
index 29909b1..d0d1ba2 100644
--- a/chrome/browser/resources/chromeos/camera/src/_locales/hi/messages.json
+++ b/chrome/browser/resources/chromeos/camera/src/_locales/hi/messages.json
@@ -1,21 +1,21 @@
 {
-  "name": {
+  "NAME": {
     "message": "कैमरा",
     "description": "Name of the Camera App."
   },
-  "description": {
+  "DESCRIPTION": {
     "message": "अपने कैमरे से फ़ोटो खींचें और वीडियो रिकॉर्ड करें.",
     "description": "Short description of the Camera App."
   },
-  "errorMsgFileSystemFailed": {
+  "ERROR_MSG_FILE_SYSTEM_FAILED": {
     "message": "फ़ाइल सिस्टम की गड़बड़ियां.",
     "description": "Error message shown when failing to read or write the file system."
   },
-  "errorMsgNoCamera": {
+  "ERROR_MSG_NO_CAMERA": {
     "message": "आपका कैमरा फ़िलहाल उपलब्ध नहीं है.\nकृपया देखें कि कैमरा ठीक तरह से कनेक्ट है या नहीं.",
     "description": "Error message shown when it was impossible to connect to the camera due to unavailability."
   },
-  "errorMsgGalleryExportFailed": {
+  "ERROR_MSG_GALLERY_EXPORT_FAILED": {
     "message": "$file$ एक्सपोर्ट नहीं की जा सकती",
     "description": "Error message shown when exporting to an external directory failed. Expects a file name to be passed in.",
     "placeholders": {
@@ -25,27 +25,27 @@
       }
     }
   },
-  "errorMsgSaveFileFailed": {
+  "ERROR_MSG_SAVE_FILE_FAILED": {
     "message": "फ़ाइल सेव नहीं की जा सकी",
     "description": "Error message shown when saving/adding a image or video to the file system failed."
   },
-  "errorMsgTakePhotoFailed": {
+  "ERROR_MSG_TAKE_PHOTO_FAILED": {
     "message": "फ़ोटो नहीं खींची जा सकी",
     "description": "Error message shown when failing to take photo."
   },
-  "errorMsgRecordStartFailed": {
+  "ERROR_MSG_RECORD_START_FAILED": {
     "message": "रिकॉर्डिंग शुरू नहीं की जा सकी",
     "description": "Error message shown when failing to start recording video."
   },
-  "errorMsgEmptyRecording": {
+  "ERROR_MSG_EMPTY_RECORDING": {
     "message": "कुछ भी रिकॉर्ड नहीं हुआ",
     "description": "Error message shown when no data is recorded for a recording and it won't be added to the gallery."
   },
-  "statusMsgRecordingStopped": {
+  "STATUS_MSG_RECORDING_STOPPED": {
     "message": "रिकॉर्डिंग रूक गई है",
     "description": "Status message for spoken feedback when video recording has been stopped."
   },
-  "statusMsgCameraSwitched": {
+  "STATUS_MSG_CAMERA_SWITCHED": {
     "message": "$camera$ चालू है",
     "description": "Status message for spoken feedback when switching over to another camera.",
     "placeholders": {
@@ -55,131 +55,131 @@
       }
     }
   },
-  "galleryButton": {
+  "GALLERY_BUTTON": {
     "message": "गैलरी में जाएं",
     "description": "Label for the gallery button."
   },
-  "deleteButton": {
+  "DELETE_BUTTON": {
     "message": "मिटाएं",
     "description": "Label for the delete button."
   },
-  "exportButton": {
+  "EXPORT_BUTTON": {
     "message": "डिस्क में ले जाएं",
     "description": "Label for the exporting button."
   },
-  "printButton": {
+  "PRINT_BUTTON": {
     "message": "प्रिंट करें",
     "description": "Label for the printing button."
   },
-  "backButton": {
+  "BACK_BUTTON": {
     "message": "वापस जाएं",
     "description": "Label for the back button."
   },
-  "galleryImages": {
+  "GALLERY_IMAGES": {
     "message": "गैलरी की इमेज",
     "description": "Text to speech label for the gallery list."
   },
-  "settingsButton": {
+  "SETTINGS_BUTTON": {
     "message": "सेटिंग",
     "description": "Label for the settings button."
   },
-  "gridTypeButton": {
+  "GRID_TYPE_BUTTON": {
     "message": "ग्रिड प्रकार",
     "description": "Label for the button of grid-type options."
   },
-  "timerDurationButton": {
+  "TIMER_DURATION_BUTTON": {
     "message": "टाइमर का कुल समय",
     "description": "Label for the button of timer-duration options."
   },
-  "feedbackButton": {
+  "FEEDBACK_BUTTON": {
     "message": "फ़ीडबैक भेजें",
     "description": "Label for the feedback button."
   },
-  "helpButton": {
+  "HELP_BUTTON": {
     "message": "सहायता",
     "description": "Label for the help button."
   },
-  "labelGrid3x3": {
+  "LABEL_GRID_3X3": {
     "message": "3 x 3",
     "description": "Label for for grid-type: 3x3."
   },
-  "ariaGrid3x3": {
+  "ARIA_GRID_3X3": {
     "message": "3 गुणा 3",
     "description": "Label for spoken feedback to read out grid-type: 3x3."
   },
-  "labelGrid4x4": {
+  "LABEL_GRID_4X4": {
     "message": "4 x 4",
     "description": "Label for for grid-type: 4x4."
   },
-  "ariaGrid4x4": {
+  "ARIA_GRID_4X4": {
     "message": "4 गुणा 4",
     "description": "Label for spoken feedback to read out grid-type: 4x4."
   },
-  "labelGridGolden": {
+  "LABEL_GRID_GOLDEN": {
     "message": "स्वर्ण अनुपात",
     "description": "Label for grid-type: golden ratio."
   },
-  "labelTimer3s": {
+  "LABEL_TIMER_3S": {
     "message": "तीन सेकंड",
     "description": "Label for timer-duration: 3 seconds."
   },
-  "labelTimer10s": {
+  "LABEL_TIMER_10S": {
     "message": "10 सेकंड",
     "description": "Label for timer-duration: 10 seconds."
   },
-  "takePhotoButton": {
+  "TAKE_PHOTO_BUTTON": {
     "message": "फ़ोटो लें",
     "description": "Label for the shutter button to take photo."
   },
-  "takePhotoCancelButton": {
+  "TAKE_PHOTO_CANCEL_BUTTON": {
     "message": "फ़ोटो न खींचें",
     "description": "Label for the shutter button to cancel countdown timer and stop taking photo."
   },
-  "recordVideoStartButton": {
+  "RECORD_VIDEO_START_BUTTON": {
     "message": "रिकॉर्ड करना शुरू करें",
     "description": "Label for the shutter button to start recording."
   },
-  "recordVideoStopButton": {
+  "RECORD_VIDEO_STOP_BUTTON": {
     "message": "रिकॉर्ड करना बंद करें",
     "description": "Label for the shutter button to stop recording."
   },
-  "switchCameraButton": {
+  "SWITCH_CAMERA_BUTTON": {
     "message": "अगले कैमरे का इस्तेमाल करें",
     "description": "Label for the button to switch to next connected camera. Eg. switching from front facing to back facing, or a camera connected via USB. The button is shown only when more than one camera is connected."
   },
-  "switchRecordVideoButton": {
+  "SWITCH_RECORD_VIDEO_BUTTON": {
     "message": "वीडियो रिकॉर्डिंग मोड पर जाएं",
     "description": "Label for the button to switch to record video mode."
   },
-  "switchTakePhotoButton": {
+  "SWITCH_TAKE_PHOTO_BUTTON": {
     "message": "फ़ोटो खींचने वाले मोड पर जाएं",
     "description": "Label for the button to switch to take photo mode."
   },
-  "toggleTimerButton": {
+  "TOGGLE_TIMER_BUTTON": {
     "message": "टाइमर",
     "description": "Label for the checkbox to toggle the countdown timer."
   },
-  "toggleMirrorButton": {
+  "TOGGLE_MIRROR_BUTTON": {
     "message": "मिररिंग",
     "description": "Label for the checkbox to toggle the preview mirroring. Eg. if mirroring is toggled on, preview will be flipped horizontally."
   },
-  "toggleGridButton": {
+  "TOGGLE_GRID_BUTTON": {
     "message": "ग्रिड",
     "description": "Label for the checkbox to toggle the grid shown on preview."
   },
-  "toggleMicButton": {
+  "TOGGLE_MIC_BUTTON": {
     "message": "माइक्रोफ़ोन",
     "description": "Label for the checkbox to toggle the microphone for recording video."
   },
-  "dialogOKButton": {
+  "DIALOG_OK_BUTTON": {
     "message": "ठीक",
     "description": "Label for the accepting button in the dialog."
   },
-  "dialogCancelButton": {
+  "DIALOG_CANCEL_BUTTON": {
     "message": "अभी नहीं",
     "description": "Label for the dismissing button in the dialog."
   },
-  "deleteConfirmationMsg": {
+  "DELETE_CONFIRMATION_MSG": {
     "message": "क्या आप वाकई $file$ को हटाना चाहते हैं?",
     "description": "Confirmation message before removing a selected item from the gallery. Expects a file name to be passed in.",
     "placeholders": {
@@ -189,7 +189,7 @@
       }
     }
   },
-  "deleteMultiConfirmationMsg": {
+  "DELETE_MULTI_CONFIRMATION_MSG": {
     "message": "क्या आप वाकई $count$ आइटम हटाना चाहते हैं?",
     "description": "Confirmation message before removing multiple selected items from the gallery. Expects a file count to be passed in.",
     "placeholders": {
@@ -199,7 +199,7 @@
       }
     }
   },
-  "migratePicturesMsg": {
+  "MIGRATE_PICTURES_MSG": {
     "message": "कैमरे से ली गईं फ़ोटो और वीडियो 'डाउनलोड' फ़ोल्डर में ले जाए जाएंगे. आप 'फ़ाइल' में जाकर उन्हें एक्सेस कर सकते हैं.\n\nमेमोरी की अनुमतियों वाले ऐप्लिकेशन आपकी फ़ोटो और वीडियो एक्सेस कर पाएंगे.",
     "description": "Message shown before moving all photos and videos stored in the Camera App to the Downloads folder."
   }
diff --git a/chrome/browser/resources/chromeos/camera/src/_locales/hr/messages.json b/chrome/browser/resources/chromeos/camera/src/_locales/hr/messages.json
index e5b4620..e1f5f47 100644
--- a/chrome/browser/resources/chromeos/camera/src/_locales/hr/messages.json
+++ b/chrome/browser/resources/chromeos/camera/src/_locales/hr/messages.json
@@ -1,21 +1,21 @@
 {
-  "name": {
+  "NAME": {
     "message": "Fotoaparat",
     "description": "Name of the Camera App."
   },
-  "description": {
+  "DESCRIPTION": {
     "message": "Snimajte fotografije i videozapise svojim fotoaparatom.",
     "description": "Short description of the Camera App."
   },
-  "errorMsgFileSystemFailed": {
+  "ERROR_MSG_FILE_SYSTEM_FAILED": {
     "message": "Pogreške datotečnog sustava.",
     "description": "Error message shown when failing to read or write the file system."
   },
-  "errorMsgNoCamera": {
+  "ERROR_MSG_NO_CAMERA": {
     "message": "Fotoaparat trenutačno nije dostupan.\nProvjerite je li fotoaparat pravilno povezan.",
     "description": "Error message shown when it was impossible to connect to the camera due to unavailability."
   },
-  "errorMsgGalleryExportFailed": {
+  "ERROR_MSG_GALLERY_EXPORT_FAILED": {
     "message": "Izvoz datoteke $file$ nije uspio",
     "description": "Error message shown when exporting to an external directory failed. Expects a file name to be passed in.",
     "placeholders": {
@@ -25,27 +25,27 @@
       }
     }
   },
-  "errorMsgSaveFileFailed": {
+  "ERROR_MSG_SAVE_FILE_FAILED": {
     "message": "Spremanje datoteke nije uspjelo",
     "description": "Error message shown when saving/adding a image or video to the file system failed."
   },
-  "errorMsgTakePhotoFailed": {
+  "ERROR_MSG_TAKE_PHOTO_FAILED": {
     "message": "Snimanje fotografije nije uspjelo",
     "description": "Error message shown when failing to take photo."
   },
-  "errorMsgRecordStartFailed": {
+  "ERROR_MSG_RECORD_START_FAILED": {
     "message": "Pokretanje snimanja nije uspjelo",
     "description": "Error message shown when failing to start recording video."
   },
-  "errorMsgEmptyRecording": {
+  "ERROR_MSG_EMPTY_RECORDING": {
     "message": "Nije snimljeno ništa",
     "description": "Error message shown when no data is recorded for a recording and it won't be added to the gallery."
   },
-  "statusMsgRecordingStopped": {
+  "STATUS_MSG_RECORDING_STOPPED": {
     "message": "Snimanje je zaustavljeno",
     "description": "Status message for spoken feedback when video recording has been stopped."
   },
-  "statusMsgCameraSwitched": {
+  "STATUS_MSG_CAMERA_SWITCHED": {
     "message": "Aktivno: $camera$",
     "description": "Status message for spoken feedback when switching over to another camera.",
     "placeholders": {
@@ -55,131 +55,131 @@
       }
     }
   },
-  "galleryButton": {
+  "GALLERY_BUTTON": {
     "message": "Otvori galeriju",
     "description": "Label for the gallery button."
   },
-  "deleteButton": {
+  "DELETE_BUTTON": {
     "message": "Izbriši",
     "description": "Label for the delete button."
   },
-  "exportButton": {
+  "EXPORT_BUTTON": {
     "message": "Izvezi na disk",
     "description": "Label for the exporting button."
   },
-  "printButton": {
+  "PRINT_BUTTON": {
     "message": "Ispiši",
     "description": "Label for the printing button."
   },
-  "backButton": {
+  "BACK_BUTTON": {
     "message": "Natrag",
     "description": "Label for the back button."
   },
-  "galleryImages": {
+  "GALLERY_IMAGES": {
     "message": "Slike iz galerije",
     "description": "Text to speech label for the gallery list."
   },
-  "settingsButton": {
+  "SETTINGS_BUTTON": {
     "message": "Postavke",
     "description": "Label for the settings button."
   },
-  "gridTypeButton": {
+  "GRID_TYPE_BUTTON": {
     "message": "Vrsta rešetke",
     "description": "Label for the button of grid-type options."
   },
-  "timerDurationButton": {
+  "TIMER_DURATION_BUTTON": {
     "message": "Trajanje odbrojavanja",
     "description": "Label for the button of timer-duration options."
   },
-  "feedbackButton": {
+  "FEEDBACK_BUTTON": {
     "message": "Pošaljite povratne informacije",
     "description": "Label for the feedback button."
   },
-  "helpButton": {
+  "HELP_BUTTON": {
     "message": "Pomoć",
     "description": "Label for the help button."
   },
-  "labelGrid3x3": {
+  "LABEL_GRID_3X3": {
     "message": "3 x 3",
     "description": "Label for for grid-type: 3x3."
   },
-  "ariaGrid3x3": {
+  "ARIA_GRID_3X3": {
     "message": "Tri puta tri",
     "description": "Label for spoken feedback to read out grid-type: 3x3."
   },
-  "labelGrid4x4": {
+  "LABEL_GRID_4X4": {
     "message": "4 x 4",
     "description": "Label for for grid-type: 4x4."
   },
-  "ariaGrid4x4": {
+  "ARIA_GRID_4X4": {
     "message": "Četiri puta četiri",
     "description": "Label for spoken feedback to read out grid-type: 4x4."
   },
-  "labelGridGolden": {
+  "LABEL_GRID_GOLDEN": {
     "message": "Zlatni rez",
     "description": "Label for grid-type: golden ratio."
   },
-  "labelTimer3s": {
+  "LABEL_TIMER_3S": {
     "message": "3 sekunde",
     "description": "Label for timer-duration: 3 seconds."
   },
-  "labelTimer10s": {
+  "LABEL_TIMER_10S": {
     "message": "10 sekundi",
     "description": "Label for timer-duration: 10 seconds."
   },
-  "takePhotoButton": {
+  "TAKE_PHOTO_BUTTON": {
     "message": "Snimi fotografiju",
     "description": "Label for the shutter button to take photo."
   },
-  "takePhotoCancelButton": {
+  "TAKE_PHOTO_CANCEL_BUTTON": {
     "message": "Zaustavi snimanje fotografije",
     "description": "Label for the shutter button to cancel countdown timer and stop taking photo."
   },
-  "recordVideoStartButton": {
+  "RECORD_VIDEO_START_BUTTON": {
     "message": "Započni snimanje",
     "description": "Label for the shutter button to start recording."
   },
-  "recordVideoStopButton": {
+  "RECORD_VIDEO_STOP_BUTTON": {
     "message": "Zaustavi snimanje",
     "description": "Label for the shutter button to stop recording."
   },
-  "switchCameraButton": {
+  "SWITCH_CAMERA_BUTTON": {
     "message": "Prijeđi na sljedeći fotoaparat",
     "description": "Label for the button to switch to next connected camera. Eg. switching from front facing to back facing, or a camera connected via USB. The button is shown only when more than one camera is connected."
   },
-  "switchRecordVideoButton": {
+  "SWITCH_RECORD_VIDEO_BUTTON": {
     "message": "Prijeđi na snimanje videozapisa",
     "description": "Label for the button to switch to record video mode."
   },
-  "switchTakePhotoButton": {
+  "SWITCH_TAKE_PHOTO_BUTTON": {
     "message": "Prijeđi na snimanje fotografije",
     "description": "Label for the button to switch to take photo mode."
   },
-  "toggleTimerButton": {
+  "TOGGLE_TIMER_BUTTON": {
     "message": "Odbrojavanje",
     "description": "Label for the checkbox to toggle the countdown timer."
   },
-  "toggleMirrorButton": {
+  "TOGGLE_MIRROR_BUTTON": {
     "message": "Zrcaljenje",
     "description": "Label for the checkbox to toggle the preview mirroring. Eg. if mirroring is toggled on, preview will be flipped horizontally."
   },
-  "toggleGridButton": {
+  "TOGGLE_GRID_BUTTON": {
     "message": "Rešetka",
     "description": "Label for the checkbox to toggle the grid shown on preview."
   },
-  "toggleMicButton": {
+  "TOGGLE_MIC_BUTTON": {
     "message": "Mikrofon",
     "description": "Label for the checkbox to toggle the microphone for recording video."
   },
-  "dialogOKButton": {
+  "DIALOG_OK_BUTTON": {
     "message": "U redu",
     "description": "Label for the accepting button in the dialog."
   },
-  "dialogCancelButton": {
+  "DIALOG_CANCEL_BUTTON": {
     "message": "Odustani",
     "description": "Label for the dismissing button in the dialog."
   },
-  "deleteConfirmationMsg": {
+  "DELETE_CONFIRMATION_MSG": {
     "message": "Želite li doista ukloniti datoteku $file$?",
     "description": "Confirmation message before removing a selected item from the gallery. Expects a file name to be passed in.",
     "placeholders": {
@@ -189,7 +189,7 @@
       }
     }
   },
-  "deleteMultiConfirmationMsg": {
+  "DELETE_MULTI_CONFIRMATION_MSG": {
     "message": "Želite li doista ukloniti te stavke (ukupno $count$)?",
     "description": "Confirmation message before removing multiple selected items from the gallery. Expects a file count to be passed in.",
     "placeholders": {
@@ -199,7 +199,7 @@
       }
     }
   },
-  "migratePicturesMsg": {
+  "MIGRATE_PICTURES_MSG": {
     "message": "Fotografije i videozapisi snimljeni fotoaparatom premjestit će se u mapu Preuzimanja. Možete im pristupiti u Datotekama.\n\nAplikacije s dopuštenjima za pohranu imat će pristup vašim fotografijama i videozapisima.",
     "description": "Message shown before moving all photos and videos stored in the Camera App to the Downloads folder."
   }
diff --git a/chrome/browser/resources/chromeos/camera/src/_locales/hu/messages.json b/chrome/browser/resources/chromeos/camera/src/_locales/hu/messages.json
index 16cf3b6..f93da742 100644
--- a/chrome/browser/resources/chromeos/camera/src/_locales/hu/messages.json
+++ b/chrome/browser/resources/chromeos/camera/src/_locales/hu/messages.json
@@ -1,21 +1,21 @@
 {
-  "name": {
+  "NAME": {
     "message": "Kamera",
     "description": "Name of the Camera App."
   },
-  "description": {
+  "DESCRIPTION": {
     "message": "Fotókat és videókat készíthet a kamerával.",
     "description": "Short description of the Camera App."
   },
-  "errorMsgFileSystemFailed": {
+  "ERROR_MSG_FILE_SYSTEM_FAILED": {
     "message": "Fájlrendszerbeli hibák.",
     "description": "Error message shown when failing to read or write the file system."
   },
-  "errorMsgNoCamera": {
+  "ERROR_MSG_NO_CAMERA": {
     "message": "A kamera jelenleg nem áll rendelkezésre.\nEllenőrizze, hogy megfelelően van-e csatlakoztatva.",
     "description": "Error message shown when it was impossible to connect to the camera due to unavailability."
   },
-  "errorMsgGalleryExportFailed": {
+  "ERROR_MSG_GALLERY_EXPORT_FAILED": {
     "message": "Nem sikerült exportálni a fájlt ($file$).",
     "description": "Error message shown when exporting to an external directory failed. Expects a file name to be passed in.",
     "placeholders": {
@@ -25,27 +25,27 @@
       }
     }
   },
-  "errorMsgSaveFileFailed": {
+  "ERROR_MSG_SAVE_FILE_FAILED": {
     "message": "Nem sikerült menteni a fájlt.",
     "description": "Error message shown when saving/adding a image or video to the file system failed."
   },
-  "errorMsgTakePhotoFailed": {
+  "ERROR_MSG_TAKE_PHOTO_FAILED": {
     "message": "Nem sikerült elkészíteni a fotót.",
     "description": "Error message shown when failing to take photo."
   },
-  "errorMsgRecordStartFailed": {
+  "ERROR_MSG_RECORD_START_FAILED": {
     "message": "Nem sikerült elindítani a rögzítést.",
     "description": "Error message shown when failing to start recording video."
   },
-  "errorMsgEmptyRecording": {
+  "ERROR_MSG_EMPTY_RECORDING": {
     "message": "A rendszer semmit sem rögzített.",
     "description": "Error message shown when no data is recorded for a recording and it won't be added to the gallery."
   },
-  "statusMsgRecordingStopped": {
+  "STATUS_MSG_RECORDING_STOPPED": {
     "message": "A rögzítés leállt",
     "description": "Status message for spoken feedback when video recording has been stopped."
   },
-  "statusMsgCameraSwitched": {
+  "STATUS_MSG_CAMERA_SWITCHED": {
     "message": "$camera$ aktív",
     "description": "Status message for spoken feedback when switching over to another camera.",
     "placeholders": {
@@ -55,131 +55,131 @@
       }
     }
   },
-  "galleryButton": {
+  "GALLERY_BUTTON": {
     "message": "Ugrás a galériába",
     "description": "Label for the gallery button."
   },
-  "deleteButton": {
+  "DELETE_BUTTON": {
     "message": "Törlés",
     "description": "Label for the delete button."
   },
-  "exportButton": {
+  "EXPORT_BUTTON": {
     "message": "Exportálás lemezre",
     "description": "Label for the exporting button."
   },
-  "printButton": {
+  "PRINT_BUTTON": {
     "message": "Nyomtatás",
     "description": "Label for the printing button."
   },
-  "backButton": {
+  "BACK_BUTTON": {
     "message": "Vissza",
     "description": "Label for the back button."
   },
-  "galleryImages": {
+  "GALLERY_IMAGES": {
     "message": "Galériaképek",
     "description": "Text to speech label for the gallery list."
   },
-  "settingsButton": {
+  "SETTINGS_BUTTON": {
     "message": "Beállítások",
     "description": "Label for the settings button."
   },
-  "gridTypeButton": {
+  "GRID_TYPE_BUTTON": {
     "message": "Rács típusa",
     "description": "Label for the button of grid-type options."
   },
-  "timerDurationButton": {
+  "TIMER_DURATION_BUTTON": {
     "message": "Időzítés hossza",
     "description": "Label for the button of timer-duration options."
   },
-  "feedbackButton": {
+  "FEEDBACK_BUTTON": {
     "message": "Visszajelzés küldése",
     "description": "Label for the feedback button."
   },
-  "helpButton": {
+  "HELP_BUTTON": {
     "message": "Súgó",
     "description": "Label for the help button."
   },
-  "labelGrid3x3": {
+  "LABEL_GRID_3X3": {
     "message": "3 × 3",
     "description": "Label for for grid-type: 3x3."
   },
-  "ariaGrid3x3": {
+  "ARIA_GRID_3X3": {
     "message": "Háromszor hármas",
     "description": "Label for spoken feedback to read out grid-type: 3x3."
   },
-  "labelGrid4x4": {
+  "LABEL_GRID_4X4": {
     "message": "4 × 4",
     "description": "Label for for grid-type: 4x4."
   },
-  "ariaGrid4x4": {
+  "ARIA_GRID_4X4": {
     "message": "Négyszer négyes",
     "description": "Label for spoken feedback to read out grid-type: 4x4."
   },
-  "labelGridGolden": {
+  "LABEL_GRID_GOLDEN": {
     "message": "Aranymetszés",
     "description": "Label for grid-type: golden ratio."
   },
-  "labelTimer3s": {
+  "LABEL_TIMER_3S": {
     "message": "3 másodperc",
     "description": "Label for timer-duration: 3 seconds."
   },
-  "labelTimer10s": {
+  "LABEL_TIMER_10S": {
     "message": "10 másodperc",
     "description": "Label for timer-duration: 10 seconds."
   },
-  "takePhotoButton": {
+  "TAKE_PHOTO_BUTTON": {
     "message": "Fotókészítés",
     "description": "Label for the shutter button to take photo."
   },
-  "takePhotoCancelButton": {
+  "TAKE_PHOTO_CANCEL_BUTTON": {
     "message": "Fotókészítés leállítása",
     "description": "Label for the shutter button to cancel countdown timer and stop taking photo."
   },
-  "recordVideoStartButton": {
+  "RECORD_VIDEO_START_BUTTON": {
     "message": "Rögzítés megkezdése",
     "description": "Label for the shutter button to start recording."
   },
-  "recordVideoStopButton": {
+  "RECORD_VIDEO_STOP_BUTTON": {
     "message": "Rögzítés leállítása",
     "description": "Label for the shutter button to stop recording."
   },
-  "switchCameraButton": {
+  "SWITCH_CAMERA_BUTTON": {
     "message": "Váltás a következő kamerára",
     "description": "Label for the button to switch to next connected camera. Eg. switching from front facing to back facing, or a camera connected via USB. The button is shown only when more than one camera is connected."
   },
-  "switchRecordVideoButton": {
+  "SWITCH_RECORD_VIDEO_BUTTON": {
     "message": "Váltás videórögzítésre",
     "description": "Label for the button to switch to record video mode."
   },
-  "switchTakePhotoButton": {
+  "SWITCH_TAKE_PHOTO_BUTTON": {
     "message": "Váltás fotókészítésre",
     "description": "Label for the button to switch to take photo mode."
   },
-  "toggleTimerButton": {
+  "TOGGLE_TIMER_BUTTON": {
     "message": "Időzítő",
     "description": "Label for the checkbox to toggle the countdown timer."
   },
-  "toggleMirrorButton": {
+  "TOGGLE_MIRROR_BUTTON": {
     "message": "Tükrözés",
     "description": "Label for the checkbox to toggle the preview mirroring. Eg. if mirroring is toggled on, preview will be flipped horizontally."
   },
-  "toggleGridButton": {
+  "TOGGLE_GRID_BUTTON": {
     "message": "Rács",
     "description": "Label for the checkbox to toggle the grid shown on preview."
   },
-  "toggleMicButton": {
+  "TOGGLE_MIC_BUTTON": {
     "message": "Mikrofon",
     "description": "Label for the checkbox to toggle the microphone for recording video."
   },
-  "dialogOKButton": {
+  "DIALOG_OK_BUTTON": {
     "message": "OK",
     "description": "Label for the accepting button in the dialog."
   },
-  "dialogCancelButton": {
+  "DIALOG_CANCEL_BUTTON": {
     "message": "Mégse",
     "description": "Label for the dismissing button in the dialog."
   },
-  "deleteConfirmationMsg": {
+  "DELETE_CONFIRMATION_MSG": {
     "message": "Biztosan eltávolítja a következő fájlt: $file$?",
     "description": "Confirmation message before removing a selected item from the gallery. Expects a file name to be passed in.",
     "placeholders": {
@@ -189,7 +189,7 @@
       }
     }
   },
-  "deleteMultiConfirmationMsg": {
+  "DELETE_MULTI_CONFIRMATION_MSG": {
     "message": "Biztosan eltávolít $count$ elemet?",
     "description": "Confirmation message before removing multiple selected items from the gallery. Expects a file count to be passed in.",
     "placeholders": {
@@ -199,7 +199,7 @@
       }
     }
   },
-  "migratePicturesMsg": {
+  "MIGRATE_PICTURES_MSG": {
     "message": "A kamerával készített fotók és videók a Letöltések mappába kerülnek. A Fájlok alkalmazásban érheti el őket.\n\nA tárhelyengedéllyel rendelkező alkalmazások hozzáférnek fotóihoz és videóihoz.",
     "description": "Message shown before moving all photos and videos stored in the Camera App to the Downloads folder."
   }
diff --git a/chrome/browser/resources/chromeos/camera/src/_locales/id/messages.json b/chrome/browser/resources/chromeos/camera/src/_locales/id/messages.json
index 994c6c56..4d4c2a6 100644
--- a/chrome/browser/resources/chromeos/camera/src/_locales/id/messages.json
+++ b/chrome/browser/resources/chromeos/camera/src/_locales/id/messages.json
@@ -1,21 +1,21 @@
 {
-  "name": {
+  "NAME": {
     "message": "Kamera",
     "description": "Name of the Camera App."
   },
-  "description": {
+  "DESCRIPTION": {
     "message": "Ambil foto dan rekam video dengan kamera Anda.",
     "description": "Short description of the Camera App."
   },
-  "errorMsgFileSystemFailed": {
+  "ERROR_MSG_FILE_SYSTEM_FAILED": {
     "message": "Error sistem file.",
     "description": "Error message shown when failing to read or write the file system."
   },
-  "errorMsgNoCamera": {
+  "ERROR_MSG_NO_CAMERA": {
     "message": "Kamera Anda saat ini tidak tersedia.\nHarap periksa apakah kamera terhubung dengan benar.",
     "description": "Error message shown when it was impossible to connect to the camera due to unavailability."
   },
-  "errorMsgGalleryExportFailed": {
+  "ERROR_MSG_GALLERY_EXPORT_FAILED": {
     "message": "Tidak dapat mengekspor $file$",
     "description": "Error message shown when exporting to an external directory failed. Expects a file name to be passed in.",
     "placeholders": {
@@ -25,27 +25,27 @@
       }
     }
   },
-  "errorMsgSaveFileFailed": {
+  "ERROR_MSG_SAVE_FILE_FAILED": {
     "message": "Tidak dapat menyimpan file",
     "description": "Error message shown when saving/adding a image or video to the file system failed."
   },
-  "errorMsgTakePhotoFailed": {
+  "ERROR_MSG_TAKE_PHOTO_FAILED": {
     "message": "Tidak dapat mengambil foto",
     "description": "Error message shown when failing to take photo."
   },
-  "errorMsgRecordStartFailed": {
+  "ERROR_MSG_RECORD_START_FAILED": {
     "message": "Tidak dapat memulai rekaman",
     "description": "Error message shown when failing to start recording video."
   },
-  "errorMsgEmptyRecording": {
+  "ERROR_MSG_EMPTY_RECORDING": {
     "message": "Tidak ada yang direkam",
     "description": "Error message shown when no data is recorded for a recording and it won't be added to the gallery."
   },
-  "statusMsgRecordingStopped": {
+  "STATUS_MSG_RECORDING_STOPPED": {
     "message": "Rekaman dihentikan",
     "description": "Status message for spoken feedback when video recording has been stopped."
   },
-  "statusMsgCameraSwitched": {
+  "STATUS_MSG_CAMERA_SWITCHED": {
     "message": "$camera$ aktif",
     "description": "Status message for spoken feedback when switching over to another camera.",
     "placeholders": {
@@ -55,131 +55,131 @@
       }
     }
   },
-  "galleryButton": {
+  "GALLERY_BUTTON": {
     "message": "Buka galeri",
     "description": "Label for the gallery button."
   },
-  "deleteButton": {
+  "DELETE_BUTTON": {
     "message": "Hapus",
     "description": "Label for the delete button."
   },
-  "exportButton": {
+  "EXPORT_BUTTON": {
     "message": "Ekspor ke disk",
     "description": "Label for the exporting button."
   },
-  "printButton": {
+  "PRINT_BUTTON": {
     "message": "Cetak",
     "description": "Label for the printing button."
   },
-  "backButton": {
+  "BACK_BUTTON": {
     "message": "Kembali",
     "description": "Label for the back button."
   },
-  "galleryImages": {
+  "GALLERY_IMAGES": {
     "message": "Foto galeri",
     "description": "Text to speech label for the gallery list."
   },
-  "settingsButton": {
+  "SETTINGS_BUTTON": {
     "message": "Setelan",
     "description": "Label for the settings button."
   },
-  "gridTypeButton": {
+  "GRID_TYPE_BUTTON": {
     "message": "Jenis petak",
     "description": "Label for the button of grid-type options."
   },
-  "timerDurationButton": {
+  "TIMER_DURATION_BUTTON": {
     "message": "Durasi timer",
     "description": "Label for the button of timer-duration options."
   },
-  "feedbackButton": {
+  "FEEDBACK_BUTTON": {
     "message": "Kirim masukan",
     "description": "Label for the feedback button."
   },
-  "helpButton": {
+  "HELP_BUTTON": {
     "message": "Bantuan",
     "description": "Label for the help button."
   },
-  "labelGrid3x3": {
+  "LABEL_GRID_3X3": {
     "message": "3 x 3",
     "description": "Label for for grid-type: 3x3."
   },
-  "ariaGrid3x3": {
+  "ARIA_GRID_3X3": {
     "message": "3 kali 3",
     "description": "Label for spoken feedback to read out grid-type: 3x3."
   },
-  "labelGrid4x4": {
+  "LABEL_GRID_4X4": {
     "message": "4 x 4",
     "description": "Label for for grid-type: 4x4."
   },
-  "ariaGrid4x4": {
+  "ARIA_GRID_4X4": {
     "message": "4 kali 4",
     "description": "Label for spoken feedback to read out grid-type: 4x4."
   },
-  "labelGridGolden": {
+  "LABEL_GRID_GOLDEN": {
     "message": "Rasio emas",
     "description": "Label for grid-type: golden ratio."
   },
-  "labelTimer3s": {
+  "LABEL_TIMER_3S": {
     "message": "3 detik",
     "description": "Label for timer-duration: 3 seconds."
   },
-  "labelTimer10s": {
+  "LABEL_TIMER_10S": {
     "message": "10 detik",
     "description": "Label for timer-duration: 10 seconds."
   },
-  "takePhotoButton": {
+  "TAKE_PHOTO_BUTTON": {
     "message": "Ambil foto",
     "description": "Label for the shutter button to take photo."
   },
-  "takePhotoCancelButton": {
+  "TAKE_PHOTO_CANCEL_BUTTON": {
     "message": "Berhenti mengambil foto",
     "description": "Label for the shutter button to cancel countdown timer and stop taking photo."
   },
-  "recordVideoStartButton": {
+  "RECORD_VIDEO_START_BUTTON": {
     "message": "Mulai merekam",
     "description": "Label for the shutter button to start recording."
   },
-  "recordVideoStopButton": {
+  "RECORD_VIDEO_STOP_BUTTON": {
     "message": "Hentikan rekaman",
     "description": "Label for the shutter button to stop recording."
   },
-  "switchCameraButton": {
+  "SWITCH_CAMERA_BUTTON": {
     "message": "Beralih ke kamera berikutnya",
     "description": "Label for the button to switch to next connected camera. Eg. switching from front facing to back facing, or a camera connected via USB. The button is shown only when more than one camera is connected."
   },
-  "switchRecordVideoButton": {
+  "SWITCH_RECORD_VIDEO_BUTTON": {
     "message": "Beralih ke mode rekam video",
     "description": "Label for the button to switch to record video mode."
   },
-  "switchTakePhotoButton": {
+  "SWITCH_TAKE_PHOTO_BUTTON": {
     "message": "Beralih ke mode ambil foto",
     "description": "Label for the button to switch to take photo mode."
   },
-  "toggleTimerButton": {
+  "TOGGLE_TIMER_BUTTON": {
     "message": "Timer",
     "description": "Label for the checkbox to toggle the countdown timer."
   },
-  "toggleMirrorButton": {
+  "TOGGLE_MIRROR_BUTTON": {
     "message": "Pencerminan",
     "description": "Label for the checkbox to toggle the preview mirroring. Eg. if mirroring is toggled on, preview will be flipped horizontally."
   },
-  "toggleGridButton": {
+  "TOGGLE_GRID_BUTTON": {
     "message": "Petak",
     "description": "Label for the checkbox to toggle the grid shown on preview."
   },
-  "toggleMicButton": {
+  "TOGGLE_MIC_BUTTON": {
     "message": "Mikrofon",
     "description": "Label for the checkbox to toggle the microphone for recording video."
   },
-  "dialogOKButton": {
+  "DIALOG_OK_BUTTON": {
     "message": "Oke",
     "description": "Label for the accepting button in the dialog."
   },
-  "dialogCancelButton": {
+  "DIALOG_CANCEL_BUTTON": {
     "message": "Batal",
     "description": "Label for the dismissing button in the dialog."
   },
-  "deleteConfirmationMsg": {
+  "DELETE_CONFIRMATION_MSG": {
     "message": "Yakin ingin menghapus $file$?",
     "description": "Confirmation message before removing a selected item from the gallery. Expects a file name to be passed in.",
     "placeholders": {
@@ -189,7 +189,7 @@
       }
     }
   },
-  "deleteMultiConfirmationMsg": {
+  "DELETE_MULTI_CONFIRMATION_MSG": {
     "message": "Yakin ingin menghapus $count$?",
     "description": "Confirmation message before removing multiple selected items from the gallery. Expects a file count to be passed in.",
     "placeholders": {
@@ -199,7 +199,7 @@
       }
     }
   },
-  "migratePicturesMsg": {
+  "MIGRATE_PICTURES_MSG": {
     "message": "Foto dan video yang diambil dengan kamera akan dipindahkan ke folder Download. Anda dapat mengaksesnya di File.\n\nAplikasi yang memiliki izin penyimpanan dapat mengakses foto dan video.",
     "description": "Message shown before moving all photos and videos stored in the Camera App to the Downloads folder."
   }
diff --git a/chrome/browser/resources/chromeos/camera/src/_locales/it/messages.json b/chrome/browser/resources/chromeos/camera/src/_locales/it/messages.json
index 47c9cff..7b4c910c 100644
--- a/chrome/browser/resources/chromeos/camera/src/_locales/it/messages.json
+++ b/chrome/browser/resources/chromeos/camera/src/_locales/it/messages.json
@@ -1,21 +1,21 @@
 {
-  "name": {
+  "NAME": {
     "message": "Fotocamera",
     "description": "Name of the Camera App."
   },
-  "description": {
+  "DESCRIPTION": {
     "message": "Realizza foto e video con la tua fotocamera.",
     "description": "Short description of the Camera App."
   },
-  "errorMsgFileSystemFailed": {
+  "ERROR_MSG_FILE_SYSTEM_FAILED": {
     "message": "Errori del file system.",
     "description": "Error message shown when failing to read or write the file system."
   },
-  "errorMsgNoCamera": {
+  "ERROR_MSG_NO_CAMERA": {
     "message": "La fotocamera non è al momento disponibile.\nControlla se è collegata correttamente.",
     "description": "Error message shown when it was impossible to connect to the camera due to unavailability."
   },
-  "errorMsgGalleryExportFailed": {
+  "ERROR_MSG_GALLERY_EXPORT_FAILED": {
     "message": "Impossibile esportare $file$",
     "description": "Error message shown when exporting to an external directory failed. Expects a file name to be passed in.",
     "placeholders": {
@@ -25,27 +25,27 @@
       }
     }
   },
-  "errorMsgSaveFileFailed": {
+  "ERROR_MSG_SAVE_FILE_FAILED": {
     "message": "Impossibile salvare il file",
     "description": "Error message shown when saving/adding a image or video to the file system failed."
   },
-  "errorMsgTakePhotoFailed": {
+  "ERROR_MSG_TAKE_PHOTO_FAILED": {
     "message": "Impossibile scattare una foto",
     "description": "Error message shown when failing to take photo."
   },
-  "errorMsgRecordStartFailed": {
+  "ERROR_MSG_RECORD_START_FAILED": {
     "message": "Impossibile avviare la registrazione",
     "description": "Error message shown when failing to start recording video."
   },
-  "errorMsgEmptyRecording": {
+  "ERROR_MSG_EMPTY_RECORDING": {
     "message": "Nessun dato registrato",
     "description": "Error message shown when no data is recorded for a recording and it won't be added to the gallery."
   },
-  "statusMsgRecordingStopped": {
+  "STATUS_MSG_RECORDING_STOPPED": {
     "message": "Registrazione interrotta",
     "description": "Status message for spoken feedback when video recording has been stopped."
   },
-  "statusMsgCameraSwitched": {
+  "STATUS_MSG_CAMERA_SWITCHED": {
     "message": "$camera$ attiva",
     "description": "Status message for spoken feedback when switching over to another camera.",
     "placeholders": {
@@ -55,131 +55,131 @@
       }
     }
   },
-  "galleryButton": {
+  "GALLERY_BUTTON": {
     "message": "Vai alla galleria",
     "description": "Label for the gallery button."
   },
-  "deleteButton": {
+  "DELETE_BUTTON": {
     "message": "Elimina",
     "description": "Label for the delete button."
   },
-  "exportButton": {
+  "EXPORT_BUTTON": {
     "message": "Esporta su disco",
     "description": "Label for the exporting button."
   },
-  "printButton": {
+  "PRINT_BUTTON": {
     "message": "Stampa",
     "description": "Label for the printing button."
   },
-  "backButton": {
+  "BACK_BUTTON": {
     "message": "Indietro",
     "description": "Label for the back button."
   },
-  "galleryImages": {
+  "GALLERY_IMAGES": {
     "message": "Immagini della galleria",
     "description": "Text to speech label for the gallery list."
   },
-  "settingsButton": {
+  "SETTINGS_BUTTON": {
     "message": "Impostazioni",
     "description": "Label for the settings button."
   },
-  "gridTypeButton": {
+  "GRID_TYPE_BUTTON": {
     "message": "Tipo di griglia",
     "description": "Label for the button of grid-type options."
   },
-  "timerDurationButton": {
+  "TIMER_DURATION_BUTTON": {
     "message": "Durata del timer",
     "description": "Label for the button of timer-duration options."
   },
-  "feedbackButton": {
+  "FEEDBACK_BUTTON": {
     "message": "Invia feedback",
     "description": "Label for the feedback button."
   },
-  "helpButton": {
+  "HELP_BUTTON": {
     "message": "Guida",
     "description": "Label for the help button."
   },
-  "labelGrid3x3": {
+  "LABEL_GRID_3X3": {
     "message": "3 x 3",
     "description": "Label for for grid-type: 3x3."
   },
-  "ariaGrid3x3": {
+  "ARIA_GRID_3X3": {
     "message": "3 x 3",
     "description": "Label for spoken feedback to read out grid-type: 3x3."
   },
-  "labelGrid4x4": {
+  "LABEL_GRID_4X4": {
     "message": "4 x 4",
     "description": "Label for for grid-type: 4x4."
   },
-  "ariaGrid4x4": {
+  "ARIA_GRID_4X4": {
     "message": "4 x 4",
     "description": "Label for spoken feedback to read out grid-type: 4x4."
   },
-  "labelGridGolden": {
+  "LABEL_GRID_GOLDEN": {
     "message": "Sezione aurea",
     "description": "Label for grid-type: golden ratio."
   },
-  "labelTimer3s": {
+  "LABEL_TIMER_3S": {
     "message": "3 secondi",
     "description": "Label for timer-duration: 3 seconds."
   },
-  "labelTimer10s": {
+  "LABEL_TIMER_10S": {
     "message": "10 secondi",
     "description": "Label for timer-duration: 10 seconds."
   },
-  "takePhotoButton": {
+  "TAKE_PHOTO_BUTTON": {
     "message": "Scatta una foto",
     "description": "Label for the shutter button to take photo."
   },
-  "takePhotoCancelButton": {
+  "TAKE_PHOTO_CANCEL_BUTTON": {
     "message": "Interrompi acquisizione foto",
     "description": "Label for the shutter button to cancel countdown timer and stop taking photo."
   },
-  "recordVideoStartButton": {
+  "RECORD_VIDEO_START_BUTTON": {
     "message": "Avvia registrazione",
     "description": "Label for the shutter button to start recording."
   },
-  "recordVideoStopButton": {
+  "RECORD_VIDEO_STOP_BUTTON": {
     "message": "Interrompi la registrazione",
     "description": "Label for the shutter button to stop recording."
   },
-  "switchCameraButton": {
+  "SWITCH_CAMERA_BUTTON": {
     "message": "Passa alla fotocamera successiva",
     "description": "Label for the button to switch to next connected camera. Eg. switching from front facing to back facing, or a camera connected via USB. The button is shown only when more than one camera is connected."
   },
-  "switchRecordVideoButton": {
+  "SWITCH_RECORD_VIDEO_BUTTON": {
     "message": "Passa alla modalità video",
     "description": "Label for the button to switch to record video mode."
   },
-  "switchTakePhotoButton": {
+  "SWITCH_TAKE_PHOTO_BUTTON": {
     "message": "Passa alla modalità foto",
     "description": "Label for the button to switch to take photo mode."
   },
-  "toggleTimerButton": {
+  "TOGGLE_TIMER_BUTTON": {
     "message": "Timer",
     "description": "Label for the checkbox to toggle the countdown timer."
   },
-  "toggleMirrorButton": {
+  "TOGGLE_MIRROR_BUTTON": {
     "message": "Mirroring",
     "description": "Label for the checkbox to toggle the preview mirroring. Eg. if mirroring is toggled on, preview will be flipped horizontally."
   },
-  "toggleGridButton": {
+  "TOGGLE_GRID_BUTTON": {
     "message": "Griglia",
     "description": "Label for the checkbox to toggle the grid shown on preview."
   },
-  "toggleMicButton": {
+  "TOGGLE_MIC_BUTTON": {
     "message": "Microfono",
     "description": "Label for the checkbox to toggle the microphone for recording video."
   },
-  "dialogOKButton": {
+  "DIALOG_OK_BUTTON": {
     "message": "OK",
     "description": "Label for the accepting button in the dialog."
   },
-  "dialogCancelButton": {
+  "DIALOG_CANCEL_BUTTON": {
     "message": "Annulla",
     "description": "Label for the dismissing button in the dialog."
   },
-  "deleteConfirmationMsg": {
+  "DELETE_CONFIRMATION_MSG": {
     "message": "Vuoi rimuovere il file $file$?",
     "description": "Confirmation message before removing a selected item from the gallery. Expects a file name to be passed in.",
     "placeholders": {
@@ -189,7 +189,7 @@
       }
     }
   },
-  "deleteMultiConfirmationMsg": {
+  "DELETE_MULTI_CONFIRMATION_MSG": {
     "message": "Vuoi rimuovere $count$ elementi?",
     "description": "Confirmation message before removing multiple selected items from the gallery. Expects a file count to be passed in.",
     "placeholders": {
@@ -199,7 +199,7 @@
       }
     }
   },
-  "migratePicturesMsg": {
+  "MIGRATE_PICTURES_MSG": {
     "message": "Le foto e i video acquisiti con la fotocamera verranno spostati nella cartella Download e potrai accedervi dall'app File.\n\nLe app con autorizzazioni di accesso allo spazio di archiviazione potranno accedere alle foto e ai video.",
     "description": "Message shown before moving all photos and videos stored in the Camera App to the Downloads folder."
   }
diff --git a/chrome/browser/resources/chromeos/camera/src/_locales/ja/messages.json b/chrome/browser/resources/chromeos/camera/src/_locales/ja/messages.json
index 7b7945b..2c6eda2 100644
--- a/chrome/browser/resources/chromeos/camera/src/_locales/ja/messages.json
+++ b/chrome/browser/resources/chromeos/camera/src/_locales/ja/messages.json
@@ -1,21 +1,21 @@
 {
-  "name": {
+  "NAME": {
     "message": "カメラ",
     "description": "Name of the Camera App."
   },
-  "description": {
+  "DESCRIPTION": {
     "message": "カメラを使って写真や動画を撮影できます。",
     "description": "Short description of the Camera App."
   },
-  "errorMsgFileSystemFailed": {
+  "ERROR_MSG_FILE_SYSTEM_FAILED": {
     "message": "ファイル システム エラー。",
     "description": "Error message shown when failing to read or write the file system."
   },
-  "errorMsgNoCamera": {
+  "ERROR_MSG_NO_CAMERA": {
     "message": "カメラは現在ご利用いただけません。\n正しく接続されているか確認してください。",
     "description": "Error message shown when it was impossible to connect to the camera due to unavailability."
   },
-  "errorMsgGalleryExportFailed": {
+  "ERROR_MSG_GALLERY_EXPORT_FAILED": {
     "message": "$file$ をエクスポートできません",
     "description": "Error message shown when exporting to an external directory failed. Expects a file name to be passed in.",
     "placeholders": {
@@ -25,27 +25,27 @@
       }
     }
   },
-  "errorMsgSaveFileFailed": {
+  "ERROR_MSG_SAVE_FILE_FAILED": {
     "message": "ファイルを保存できません",
     "description": "Error message shown when saving/adding a image or video to the file system failed."
   },
-  "errorMsgTakePhotoFailed": {
+  "ERROR_MSG_TAKE_PHOTO_FAILED": {
     "message": "写真を撮影できません",
     "description": "Error message shown when failing to take photo."
   },
-  "errorMsgRecordStartFailed": {
+  "ERROR_MSG_RECORD_START_FAILED": {
     "message": "録画を開始できません",
     "description": "Error message shown when failing to start recording video."
   },
-  "errorMsgEmptyRecording": {
+  "ERROR_MSG_EMPTY_RECORDING": {
     "message": "何も記録されていません",
     "description": "Error message shown when no data is recorded for a recording and it won't be added to the gallery."
   },
-  "statusMsgRecordingStopped": {
+  "STATUS_MSG_RECORDING_STOPPED": {
     "message": "録画を停止しました",
     "description": "Status message for spoken feedback when video recording has been stopped."
   },
-  "statusMsgCameraSwitched": {
+  "STATUS_MSG_CAMERA_SWITCHED": {
     "message": "$camera$ に切り替えました",
     "description": "Status message for spoken feedback when switching over to another camera.",
     "placeholders": {
@@ -55,131 +55,131 @@
       }
     }
   },
-  "galleryButton": {
+  "GALLERY_BUTTON": {
     "message": "ギャラリーに移動",
     "description": "Label for the gallery button."
   },
-  "deleteButton": {
+  "DELETE_BUTTON": {
     "message": "削除",
     "description": "Label for the delete button."
   },
-  "exportButton": {
+  "EXPORT_BUTTON": {
     "message": "ディスクにエクスポート",
     "description": "Label for the exporting button."
   },
-  "printButton": {
+  "PRINT_BUTTON": {
     "message": "印刷",
     "description": "Label for the printing button."
   },
-  "backButton": {
+  "BACK_BUTTON": {
     "message": "戻る",
     "description": "Label for the back button."
   },
-  "galleryImages": {
+  "GALLERY_IMAGES": {
     "message": "ギャラリーの画像",
     "description": "Text to speech label for the gallery list."
   },
-  "settingsButton": {
+  "SETTINGS_BUTTON": {
     "message": "設定",
     "description": "Label for the settings button."
   },
-  "gridTypeButton": {
+  "GRID_TYPE_BUTTON": {
     "message": "グリッドの種類",
     "description": "Label for the button of grid-type options."
   },
-  "timerDurationButton": {
+  "TIMER_DURATION_BUTTON": {
     "message": "タイマーの時間",
     "description": "Label for the button of timer-duration options."
   },
-  "feedbackButton": {
+  "FEEDBACK_BUTTON": {
     "message": "フィードバックを送信",
     "description": "Label for the feedback button."
   },
-  "helpButton": {
+  "HELP_BUTTON": {
     "message": "ヘルプ",
     "description": "Label for the help button."
   },
-  "labelGrid3x3": {
+  "LABEL_GRID_3X3": {
     "message": "3 x 3",
     "description": "Label for for grid-type: 3x3."
   },
-  "ariaGrid3x3": {
+  "ARIA_GRID_3X3": {
     "message": "3 x 3",
     "description": "Label for spoken feedback to read out grid-type: 3x3."
   },
-  "labelGrid4x4": {
+  "LABEL_GRID_4X4": {
     "message": "4 x 4",
     "description": "Label for for grid-type: 4x4."
   },
-  "ariaGrid4x4": {
+  "ARIA_GRID_4X4": {
     "message": "4 x 4",
     "description": "Label for spoken feedback to read out grid-type: 4x4."
   },
-  "labelGridGolden": {
+  "LABEL_GRID_GOLDEN": {
     "message": "黄金比",
     "description": "Label for grid-type: golden ratio."
   },
-  "labelTimer3s": {
+  "LABEL_TIMER_3S": {
     "message": "3 秒",
     "description": "Label for timer-duration: 3 seconds."
   },
-  "labelTimer10s": {
+  "LABEL_TIMER_10S": {
     "message": "10 秒",
     "description": "Label for timer-duration: 10 seconds."
   },
-  "takePhotoButton": {
+  "TAKE_PHOTO_BUTTON": {
     "message": "写真を撮影",
     "description": "Label for the shutter button to take photo."
   },
-  "takePhotoCancelButton": {
+  "TAKE_PHOTO_CANCEL_BUTTON": {
     "message": "写真の撮影を停止",
     "description": "Label for the shutter button to cancel countdown timer and stop taking photo."
   },
-  "recordVideoStartButton": {
+  "RECORD_VIDEO_START_BUTTON": {
     "message": "録画を開始",
     "description": "Label for the shutter button to start recording."
   },
-  "recordVideoStopButton": {
+  "RECORD_VIDEO_STOP_BUTTON": {
     "message": "録画を停止",
     "description": "Label for the shutter button to stop recording."
   },
-  "switchCameraButton": {
+  "SWITCH_CAMERA_BUTTON": {
     "message": "次のカメラに切り替える",
     "description": "Label for the button to switch to next connected camera. Eg. switching from front facing to back facing, or a camera connected via USB. The button is shown only when more than one camera is connected."
   },
-  "switchRecordVideoButton": {
+  "SWITCH_RECORD_VIDEO_BUTTON": {
     "message": "動画の撮影に切り替える",
     "description": "Label for the button to switch to record video mode."
   },
-  "switchTakePhotoButton": {
+  "SWITCH_TAKE_PHOTO_BUTTON": {
     "message": "写真の撮影に切り替える",
     "description": "Label for the button to switch to take photo mode."
   },
-  "toggleTimerButton": {
+  "TOGGLE_TIMER_BUTTON": {
     "message": "タイマー",
     "description": "Label for the checkbox to toggle the countdown timer."
   },
-  "toggleMirrorButton": {
+  "TOGGLE_MIRROR_BUTTON": {
     "message": "ミラーリング",
     "description": "Label for the checkbox to toggle the preview mirroring. Eg. if mirroring is toggled on, preview will be flipped horizontally."
   },
-  "toggleGridButton": {
+  "TOGGLE_GRID_BUTTON": {
     "message": "グリッド",
     "description": "Label for the checkbox to toggle the grid shown on preview."
   },
-  "toggleMicButton": {
+  "TOGGLE_MIC_BUTTON": {
     "message": "マイク",
     "description": "Label for the checkbox to toggle the microphone for recording video."
   },
-  "dialogOKButton": {
+  "DIALOG_OK_BUTTON": {
     "message": "OK",
     "description": "Label for the accepting button in the dialog."
   },
-  "dialogCancelButton": {
+  "DIALOG_CANCEL_BUTTON": {
     "message": "キャンセル",
     "description": "Label for the dismissing button in the dialog."
   },
-  "deleteConfirmationMsg": {
+  "DELETE_CONFIRMATION_MSG": {
     "message": "$file$ を削除してもよろしいですか?",
     "description": "Confirmation message before removing a selected item from the gallery. Expects a file name to be passed in.",
     "placeholders": {
@@ -189,7 +189,7 @@
       }
     }
   },
-  "deleteMultiConfirmationMsg": {
+  "DELETE_MULTI_CONFIRMATION_MSG": {
     "message": "$count$ 個のアイテムを削除してもよろしいですか?",
     "description": "Confirmation message before removing multiple selected items from the gallery. Expects a file count to be passed in.",
     "placeholders": {
@@ -199,7 +199,7 @@
       }
     }
   },
-  "migratePicturesMsg": {
+  "MIGRATE_PICTURES_MSG": {
     "message": "カメラで撮影した写真と動画を [ダウンロード] フォルダに移動します。これらの写真や動画には、[ファイル] からアクセスできます。\n\nまた、ストレージへのアクセスが許可されているアプリからも、これらの写真や動画にアクセスできます。",
     "description": "Message shown before moving all photos and videos stored in the Camera App to the Downloads folder."
   }
diff --git a/chrome/browser/resources/chromeos/camera/src/_locales/kn/messages.json b/chrome/browser/resources/chromeos/camera/src/_locales/kn/messages.json
index 681df34..f547c91c 100644
--- a/chrome/browser/resources/chromeos/camera/src/_locales/kn/messages.json
+++ b/chrome/browser/resources/chromeos/camera/src/_locales/kn/messages.json
@@ -1,21 +1,21 @@
 {
-  "name": {
+  "NAME": {
     "message": "ಕ್ಯಾಮರಾ",
     "description": "Name of the Camera App."
   },
-  "description": {
+  "DESCRIPTION": {
     "message": "ನಿಮ್ಮ ಕ್ಯಾಮರಾದ ಮೂಲಕ ಚಿತ್ರಗಳನ್ನು ತೆಗೆಯಿರಿ ಮತ್ತು ವೀಡಿಯೊಗಳನ್ನು ರೆಕಾರ್ಡ್ ಮಾಡಿ.",
     "description": "Short description of the Camera App."
   },
-  "errorMsgFileSystemFailed": {
+  "ERROR_MSG_FILE_SYSTEM_FAILED": {
     "message": "ಫೈಲ್ ಸಿಸ್ಟಮ್ ದೋಷಗಳು.",
     "description": "Error message shown when failing to read or write the file system."
   },
-  "errorMsgNoCamera": {
+  "ERROR_MSG_NO_CAMERA": {
     "message": "ನಿಮ್ಮ ಕ್ಯಾಮರಾ ಪ್ರಸ್ತುತ ಲಭ್ಯವಿಲ್ಲ.\nದಯವಿಟ್ಟು ಕ್ಯಾಮರಾ ಸರಿಯಾಗಿ ಸಂಪರ್ಕಗೊಂಡಿದೆಯೇ ಎಂಬುದನ್ನು ಪರೀಕ್ಷಿಸಿ.",
     "description": "Error message shown when it was impossible to connect to the camera due to unavailability."
   },
-  "errorMsgGalleryExportFailed": {
+  "ERROR_MSG_GALLERY_EXPORT_FAILED": {
     "message": "$file$ ಅನ್ನು ರಫ್ತು ಮಾಡಲು ಸಾಧ್ಯವಾಗುತ್ತಿಲ್ಲ",
     "description": "Error message shown when exporting to an external directory failed. Expects a file name to be passed in.",
     "placeholders": {
@@ -25,27 +25,27 @@
       }
     }
   },
-  "errorMsgSaveFileFailed": {
+  "ERROR_MSG_SAVE_FILE_FAILED": {
     "message": "ಫೈಲ್ ಉಳಿಸಲು ಸಾಧ್ಯವಾಗುತ್ತಿಲ್ಲ",
     "description": "Error message shown when saving/adding a image or video to the file system failed."
   },
-  "errorMsgTakePhotoFailed": {
+  "ERROR_MSG_TAKE_PHOTO_FAILED": {
     "message": "ಫೋಟೋವನ್ನು ತೆಗೆದುಕೊಳ್ಳಲು ಸಾಧ್ಯವಾಗುತ್ತಿಲ್ಲ",
     "description": "Error message shown when failing to take photo."
   },
-  "errorMsgRecordStartFailed": {
+  "ERROR_MSG_RECORD_START_FAILED": {
     "message": "ರೆಕಾರ್ಡ್ ಮಾಡುವುದನ್ನು ಪ್ರಾರಂಭಿಸಲು ಸಾಧ್ಯವಾಗುತ್ತಿಲ್ಲ",
     "description": "Error message shown when failing to start recording video."
   },
-  "errorMsgEmptyRecording": {
+  "ERROR_MSG_EMPTY_RECORDING": {
     "message": "ಏನನ್ನೂ ರೆಕಾರ್ಡ್ ಮಾಡಲಾಗಿಲ್ಲ",
     "description": "Error message shown when no data is recorded for a recording and it won't be added to the gallery."
   },
-  "statusMsgRecordingStopped": {
+  "STATUS_MSG_RECORDING_STOPPED": {
     "message": "ರೆಕಾರ್ಡ್ ಮಾಡುವುದನ್ನು ನಿಲ್ಲಿಸಲಾಗಿದೆ",
     "description": "Status message for spoken feedback when video recording has been stopped."
   },
-  "statusMsgCameraSwitched": {
+  "STATUS_MSG_CAMERA_SWITCHED": {
     "message": "$camera$ ಸಕ್ರಿಯವಾಗಿದೆ",
     "description": "Status message for spoken feedback when switching over to another camera.",
     "placeholders": {
@@ -55,131 +55,131 @@
       }
     }
   },
-  "galleryButton": {
+  "GALLERY_BUTTON": {
     "message": "ಗ್ಯಾಲರಿಗೆ ಹೋಗಿ",
     "description": "Label for the gallery button."
   },
-  "deleteButton": {
+  "DELETE_BUTTON": {
     "message": "ಅಳಿಸಿ",
     "description": "Label for the delete button."
   },
-  "exportButton": {
+  "EXPORT_BUTTON": {
     "message": "ಡಿಸ್ಕ್‌ಗೆ ರಫ್ತು ಮಾಡಿ",
     "description": "Label for the exporting button."
   },
-  "printButton": {
+  "PRINT_BUTTON": {
     "message": "ಮುದ್ರಿಸಿ",
     "description": "Label for the printing button."
   },
-  "backButton": {
+  "BACK_BUTTON": {
     "message": "ಹಿಂದಿರುಗಿ",
     "description": "Label for the back button."
   },
-  "galleryImages": {
+  "GALLERY_IMAGES": {
     "message": "ಗ್ಯಾಲರಿ ಚಿತ್ರಗಳು",
     "description": "Text to speech label for the gallery list."
   },
-  "settingsButton": {
+  "SETTINGS_BUTTON": {
     "message": "ಸೆಟ್ಟಿಂಗ್‌ಗಳು",
     "description": "Label for the settings button."
   },
-  "gridTypeButton": {
+  "GRID_TYPE_BUTTON": {
     "message": "ಗ್ರಿಡ್ ಪ್ರಕಾರ",
     "description": "Label for the button of grid-type options."
   },
-  "timerDurationButton": {
+  "TIMER_DURATION_BUTTON": {
     "message": "ಟೈಮರ್ ಅವಧಿ",
     "description": "Label for the button of timer-duration options."
   },
-  "feedbackButton": {
+  "FEEDBACK_BUTTON": {
     "message": "ಪ್ರತಿಕ್ರಿಯೆ ಕಳುಹಿಸಿ",
     "description": "Label for the feedback button."
   },
-  "helpButton": {
+  "HELP_BUTTON": {
     "message": "ಸಹಾಯ",
     "description": "Label for the help button."
   },
-  "labelGrid3x3": {
+  "LABEL_GRID_3X3": {
     "message": "3 x 3",
     "description": "Label for for grid-type: 3x3."
   },
-  "ariaGrid3x3": {
+  "ARIA_GRID_3X3": {
     "message": "3 x 3",
     "description": "Label for spoken feedback to read out grid-type: 3x3."
   },
-  "labelGrid4x4": {
+  "LABEL_GRID_4X4": {
     "message": "4 x 4",
     "description": "Label for for grid-type: 4x4."
   },
-  "ariaGrid4x4": {
+  "ARIA_GRID_4X4": {
     "message": "4 x 4",
     "description": "Label for spoken feedback to read out grid-type: 4x4."
   },
-  "labelGridGolden": {
+  "LABEL_GRID_GOLDEN": {
     "message": "ಗೋಲ್ಡನ್ ಅನುಪಾತ",
     "description": "Label for grid-type: golden ratio."
   },
-  "labelTimer3s": {
+  "LABEL_TIMER_3S": {
     "message": "3 ಸೆಕೆಂಡುಗಳು",
     "description": "Label for timer-duration: 3 seconds."
   },
-  "labelTimer10s": {
+  "LABEL_TIMER_10S": {
     "message": "10 ಸೆಕೆಂಡುಗಳು",
     "description": "Label for timer-duration: 10 seconds."
   },
-  "takePhotoButton": {
+  "TAKE_PHOTO_BUTTON": {
     "message": "ಫೋಟೋ ತೆಗೆಯಿರಿ",
     "description": "Label for the shutter button to take photo."
   },
-  "takePhotoCancelButton": {
+  "TAKE_PHOTO_CANCEL_BUTTON": {
     "message": "ಫೋಟೋ ತೆಗೆಯುವುದನ್ನು ನಿಲ್ಲಿಸಿ",
     "description": "Label for the shutter button to cancel countdown timer and stop taking photo."
   },
-  "recordVideoStartButton": {
+  "RECORD_VIDEO_START_BUTTON": {
     "message": "ರೆಕಾರ್ಡ್‌ ಮಾಡಲು ಪ್ರಾರಂಭಿಸಿ",
     "description": "Label for the shutter button to start recording."
   },
-  "recordVideoStopButton": {
+  "RECORD_VIDEO_STOP_BUTTON": {
     "message": "ರೆಕಾರ್ಡ್ ಮಾಡುವುದನ್ನು ನಿಲ್ಲಿಸಿ",
     "description": "Label for the shutter button to stop recording."
   },
-  "switchCameraButton": {
+  "SWITCH_CAMERA_BUTTON": {
     "message": "ಮುಂದಿನ ಸಂಪರ್ಕಗೊಂಡಿರುವ ಕ್ಯಾಮೆರಾಗೆ ಬದಲಿಸಿ",
     "description": "Label for the button to switch to next connected camera. Eg. switching from front facing to back facing, or a camera connected via USB. The button is shown only when more than one camera is connected."
   },
-  "switchRecordVideoButton": {
+  "SWITCH_RECORD_VIDEO_BUTTON": {
     "message": "ವೀಡಿಯೊ ರೆಕಾರ್ಡ್ ಮಾಡಿಗೆ ಬದಲಿಸಿ",
     "description": "Label for the button to switch to record video mode."
   },
-  "switchTakePhotoButton": {
+  "SWITCH_TAKE_PHOTO_BUTTON": {
     "message": "ಫೋಟೋ ತೆಗೆದುಕೊಳ್ಳಿಗೆ ಬದಲಿಸಿ",
     "description": "Label for the button to switch to take photo mode."
   },
-  "toggleTimerButton": {
+  "TOGGLE_TIMER_BUTTON": {
     "message": "ಟೈಮರ್",
     "description": "Label for the checkbox to toggle the countdown timer."
   },
-  "toggleMirrorButton": {
+  "TOGGLE_MIRROR_BUTTON": {
     "message": "ಪ್ರತಿಬಿಂಬಿಸುವಿಕೆ",
     "description": "Label for the checkbox to toggle the preview mirroring. Eg. if mirroring is toggled on, preview will be flipped horizontally."
   },
-  "toggleGridButton": {
+  "TOGGLE_GRID_BUTTON": {
     "message": "ಗ್ರಿಡ್",
     "description": "Label for the checkbox to toggle the grid shown on preview."
   },
-  "toggleMicButton": {
+  "TOGGLE_MIC_BUTTON": {
     "message": "ಮೈಕ್ರೊಫೋನ್",
     "description": "Label for the checkbox to toggle the microphone for recording video."
   },
-  "dialogOKButton": {
+  "DIALOG_OK_BUTTON": {
     "message": "ಸರಿ",
     "description": "Label for the accepting button in the dialog."
   },
-  "dialogCancelButton": {
+  "DIALOG_CANCEL_BUTTON": {
     "message": "ರದ್ದುಮಾಡಿ",
     "description": "Label for the dismissing button in the dialog."
   },
-  "deleteConfirmationMsg": {
+  "DELETE_CONFIRMATION_MSG": {
     "message": "ನೀವು ನಿಜವಾಗಿಯೂ $file$ ಅನ್ನು ತೆಗೆದುಹಾಕಲು ಬಯಸುತ್ತೀರಾ?",
     "description": "Confirmation message before removing a selected item from the gallery. Expects a file name to be passed in.",
     "placeholders": {
@@ -189,7 +189,7 @@
       }
     }
   },
-  "deleteMultiConfirmationMsg": {
+  "DELETE_MULTI_CONFIRMATION_MSG": {
     "message": "ನೀವು ನಿಜವಾಗಿಯೂ $count$ ಐಟಂಗಳನ್ನು ತೆಗೆದುಹಾಕಲು ಬಯಸುತ್ತೀರಾ?",
     "description": "Confirmation message before removing multiple selected items from the gallery. Expects a file count to be passed in.",
     "placeholders": {
@@ -199,7 +199,7 @@
       }
     }
   },
-  "migratePicturesMsg": {
+  "MIGRATE_PICTURES_MSG": {
     "message": "ಕ್ಯಾಮರಾದಿಂದ ಸೆರೆಹಿಡಿದ ಫೋಟೋಗಳು ಮತ್ತು ವೀಡಿಯೊಗಳನ್ನು ಡೌನ್‌ಲೋಡ್‌ಗಳ ಫೋಲ್ಡರ್‌ಗೆ ವರ್ಗಾಯಿಸಲಾಗುತ್ತದೆ. ನೀವು ಅವುಗಳನ್ನು ಫೈಲ್‌ಗಳಲ್ಲಿ ಪ್ರವೇಶಿಸಬಹುದು.\n\nಸಂಗ್ರಹಣೆ ಅನುಮತಿಗಳನ್ನು ಹೊಂದಿರುವ ಆ್ಯಪ್‌ಗಳು ನಿಮ್ಮ ಫೋಟೋಗಳು ಮತ್ತು ವೀಡಿಯೊಗಳಿಗೆ ಪ್ರವೇಶವನ್ನು ಹೊಂದಿರುತ್ತವೆ.",
     "description": "Message shown before moving all photos and videos stored in the Camera App to the Downloads folder."
   }
diff --git a/chrome/browser/resources/chromeos/camera/src/_locales/ko/messages.json b/chrome/browser/resources/chromeos/camera/src/_locales/ko/messages.json
index 01c3455..ec4f52b0 100644
--- a/chrome/browser/resources/chromeos/camera/src/_locales/ko/messages.json
+++ b/chrome/browser/resources/chromeos/camera/src/_locales/ko/messages.json
@@ -1,21 +1,21 @@
 {
-  "name": {
+  "NAME": {
     "message": "카메라",
     "description": "Name of the Camera App."
   },
-  "description": {
+  "DESCRIPTION": {
     "message": "카메라로 사진을 찍고 동영상을 녹화합니다.",
     "description": "Short description of the Camera App."
   },
-  "errorMsgFileSystemFailed": {
+  "ERROR_MSG_FILE_SYSTEM_FAILED": {
     "message": "파일 시스템 오류가 발생했습니다.",
     "description": "Error message shown when failing to read or write the file system."
   },
-  "errorMsgNoCamera": {
+  "ERROR_MSG_NO_CAMERA": {
     "message": "현재 카메라를 사용할 수 없습니다.\n카메라가 제대로 연결되어 있는지 확인하세요.",
     "description": "Error message shown when it was impossible to connect to the camera due to unavailability."
   },
-  "errorMsgGalleryExportFailed": {
+  "ERROR_MSG_GALLERY_EXPORT_FAILED": {
     "message": "$file$ 파일을 내보낼 수 없습니다.",
     "description": "Error message shown when exporting to an external directory failed. Expects a file name to be passed in.",
     "placeholders": {
@@ -25,27 +25,27 @@
       }
     }
   },
-  "errorMsgSaveFileFailed": {
+  "ERROR_MSG_SAVE_FILE_FAILED": {
     "message": "파일을 저장할 수 없습니다.",
     "description": "Error message shown when saving/adding a image or video to the file system failed."
   },
-  "errorMsgTakePhotoFailed": {
+  "ERROR_MSG_TAKE_PHOTO_FAILED": {
     "message": "사진을 찍을 수 없습니다.",
     "description": "Error message shown when failing to take photo."
   },
-  "errorMsgRecordStartFailed": {
+  "ERROR_MSG_RECORD_START_FAILED": {
     "message": "녹화를 시작할 수 없습니다.",
     "description": "Error message shown when failing to start recording video."
   },
-  "errorMsgEmptyRecording": {
+  "ERROR_MSG_EMPTY_RECORDING": {
     "message": "녹화된 동영상이 없습니다.",
     "description": "Error message shown when no data is recorded for a recording and it won't be added to the gallery."
   },
-  "statusMsgRecordingStopped": {
+  "STATUS_MSG_RECORDING_STOPPED": {
     "message": "녹화가 중지되었습니다.",
     "description": "Status message for spoken feedback when video recording has been stopped."
   },
-  "statusMsgCameraSwitched": {
+  "STATUS_MSG_CAMERA_SWITCHED": {
     "message": "$camera$ 활성화",
     "description": "Status message for spoken feedback when switching over to another camera.",
     "placeholders": {
@@ -55,131 +55,131 @@
       }
     }
   },
-  "galleryButton": {
+  "GALLERY_BUTTON": {
     "message": "갤러리로 이동",
     "description": "Label for the gallery button."
   },
-  "deleteButton": {
+  "DELETE_BUTTON": {
     "message": "삭제",
     "description": "Label for the delete button."
   },
-  "exportButton": {
+  "EXPORT_BUTTON": {
     "message": "디스크로 내보내기",
     "description": "Label for the exporting button."
   },
-  "printButton": {
+  "PRINT_BUTTON": {
     "message": "인쇄",
     "description": "Label for the printing button."
   },
-  "backButton": {
+  "BACK_BUTTON": {
     "message": "뒤로",
     "description": "Label for the back button."
   },
-  "galleryImages": {
+  "GALLERY_IMAGES": {
     "message": "갤러리 이미지",
     "description": "Text to speech label for the gallery list."
   },
-  "settingsButton": {
+  "SETTINGS_BUTTON": {
     "message": "설정",
     "description": "Label for the settings button."
   },
-  "gridTypeButton": {
+  "GRID_TYPE_BUTTON": {
     "message": "그리드 유형",
     "description": "Label for the button of grid-type options."
   },
-  "timerDurationButton": {
+  "TIMER_DURATION_BUTTON": {
     "message": "타이머 시간",
     "description": "Label for the button of timer-duration options."
   },
-  "feedbackButton": {
+  "FEEDBACK_BUTTON": {
     "message": "의견 보내기",
     "description": "Label for the feedback button."
   },
-  "helpButton": {
+  "HELP_BUTTON": {
     "message": "도움말",
     "description": "Label for the help button."
   },
-  "labelGrid3x3": {
+  "LABEL_GRID_3X3": {
     "message": "3x3",
     "description": "Label for for grid-type: 3x3."
   },
-  "ariaGrid3x3": {
+  "ARIA_GRID_3X3": {
     "message": "3x3",
     "description": "Label for spoken feedback to read out grid-type: 3x3."
   },
-  "labelGrid4x4": {
+  "LABEL_GRID_4X4": {
     "message": "4x4",
     "description": "Label for for grid-type: 4x4."
   },
-  "ariaGrid4x4": {
+  "ARIA_GRID_4X4": {
     "message": "4x4",
     "description": "Label for spoken feedback to read out grid-type: 4x4."
   },
-  "labelGridGolden": {
+  "LABEL_GRID_GOLDEN": {
     "message": "황금 비율",
     "description": "Label for grid-type: golden ratio."
   },
-  "labelTimer3s": {
+  "LABEL_TIMER_3S": {
     "message": "3초",
     "description": "Label for timer-duration: 3 seconds."
   },
-  "labelTimer10s": {
+  "LABEL_TIMER_10S": {
     "message": "10초",
     "description": "Label for timer-duration: 10 seconds."
   },
-  "takePhotoButton": {
+  "TAKE_PHOTO_BUTTON": {
     "message": "사진 촬영",
     "description": "Label for the shutter button to take photo."
   },
-  "takePhotoCancelButton": {
+  "TAKE_PHOTO_CANCEL_BUTTON": {
     "message": "사진 촬영 중지",
     "description": "Label for the shutter button to cancel countdown timer and stop taking photo."
   },
-  "recordVideoStartButton": {
+  "RECORD_VIDEO_START_BUTTON": {
     "message": "녹화 시작",
     "description": "Label for the shutter button to start recording."
   },
-  "recordVideoStopButton": {
+  "RECORD_VIDEO_STOP_BUTTON": {
     "message": "녹화 중지",
     "description": "Label for the shutter button to stop recording."
   },
-  "switchCameraButton": {
+  "SWITCH_CAMERA_BUTTON": {
     "message": "다음 카메라로 전환",
     "description": "Label for the button to switch to next connected camera. Eg. switching from front facing to back facing, or a camera connected via USB. The button is shown only when more than one camera is connected."
   },
-  "switchRecordVideoButton": {
+  "SWITCH_RECORD_VIDEO_BUTTON": {
     "message": "동영상 녹화 모드로 전환",
     "description": "Label for the button to switch to record video mode."
   },
-  "switchTakePhotoButton": {
+  "SWITCH_TAKE_PHOTO_BUTTON": {
     "message": "사진 촬영 모드로 전환",
     "description": "Label for the button to switch to take photo mode."
   },
-  "toggleTimerButton": {
+  "TOGGLE_TIMER_BUTTON": {
     "message": "타이머",
     "description": "Label for the checkbox to toggle the countdown timer."
   },
-  "toggleMirrorButton": {
+  "TOGGLE_MIRROR_BUTTON": {
     "message": "미러링",
     "description": "Label for the checkbox to toggle the preview mirroring. Eg. if mirroring is toggled on, preview will be flipped horizontally."
   },
-  "toggleGridButton": {
+  "TOGGLE_GRID_BUTTON": {
     "message": "그리드",
     "description": "Label for the checkbox to toggle the grid shown on preview."
   },
-  "toggleMicButton": {
+  "TOGGLE_MIC_BUTTON": {
     "message": "마이크",
     "description": "Label for the checkbox to toggle the microphone for recording video."
   },
-  "dialogOKButton": {
+  "DIALOG_OK_BUTTON": {
     "message": "확인",
     "description": "Label for the accepting button in the dialog."
   },
-  "dialogCancelButton": {
+  "DIALOG_CANCEL_BUTTON": {
     "message": "취소",
     "description": "Label for the dismissing button in the dialog."
   },
-  "deleteConfirmationMsg": {
+  "DELETE_CONFIRMATION_MSG": {
     "message": "$file$ 파일을 삭제하시겠습니까?",
     "description": "Confirmation message before removing a selected item from the gallery. Expects a file name to be passed in.",
     "placeholders": {
@@ -189,7 +189,7 @@
       }
     }
   },
-  "deleteMultiConfirmationMsg": {
+  "DELETE_MULTI_CONFIRMATION_MSG": {
     "message": "항목 $count$개를 삭제하시겠습니까?",
     "description": "Confirmation message before removing multiple selected items from the gallery. Expects a file count to be passed in.",
     "placeholders": {
@@ -199,7 +199,7 @@
       }
     }
   },
-  "migratePicturesMsg": {
+  "MIGRATE_PICTURES_MSG": {
     "message": "카메라로 촬영된 사진 및 동영상은 다운로드 폴더로 이동되며, 파일 앱에서 액세스할 수 있습니다.\n\n저장용량 사용 권한이 있는 앱은 사진 및 동영상에 액세스할 수 있습니다.",
     "description": "Message shown before moving all photos and videos stored in the Camera App to the Downloads folder."
   }
diff --git a/chrome/browser/resources/chromeos/camera/src/_locales/lt/messages.json b/chrome/browser/resources/chromeos/camera/src/_locales/lt/messages.json
index 41d5fcc4..e865331 100644
--- a/chrome/browser/resources/chromeos/camera/src/_locales/lt/messages.json
+++ b/chrome/browser/resources/chromeos/camera/src/_locales/lt/messages.json
@@ -1,21 +1,21 @@
 {
-  "name": {
+  "NAME": {
     "message": "Žiniatinklio kamera",
     "description": "Name of the Camera App."
   },
-  "description": {
+  "DESCRIPTION": {
     "message": "Fotografuokite ir filmuokite naudodami žiniatinklio kamerą.",
     "description": "Short description of the Camera App."
   },
-  "errorMsgFileSystemFailed": {
+  "ERROR_MSG_FILE_SYSTEM_FAILED": {
     "message": "Failų sistemos klaidos.",
     "description": "Error message shown when failing to read or write the file system."
   },
-  "errorMsgNoCamera": {
+  "ERROR_MSG_NO_CAMERA": {
     "message": "Jūsų kamera šiuo metu nepasiekiama.\nPatikrinkite, ar kamera tinkamai prijungta.",
     "description": "Error message shown when it was impossible to connect to the camera due to unavailability."
   },
-  "errorMsgGalleryExportFailed": {
+  "ERROR_MSG_GALLERY_EXPORT_FAILED": {
     "message": "Nepavyko eksportuoti failo $file$",
     "description": "Error message shown when exporting to an external directory failed. Expects a file name to be passed in.",
     "placeholders": {
@@ -25,27 +25,27 @@
       }
     }
   },
-  "errorMsgSaveFileFailed": {
+  "ERROR_MSG_SAVE_FILE_FAILED": {
     "message": "Nepavyko išsaugoti failo",
     "description": "Error message shown when saving/adding a image or video to the file system failed."
   },
-  "errorMsgTakePhotoFailed": {
+  "ERROR_MSG_TAKE_PHOTO_FAILED": {
     "message": "Nepavyko nufotografuoti",
     "description": "Error message shown when failing to take photo."
   },
-  "errorMsgRecordStartFailed": {
+  "ERROR_MSG_RECORD_START_FAILED": {
     "message": "Nepavyko pradėti įrašymo",
     "description": "Error message shown when failing to start recording video."
   },
-  "errorMsgEmptyRecording": {
+  "ERROR_MSG_EMPTY_RECORDING": {
     "message": "Nieko neįrašyta",
     "description": "Error message shown when no data is recorded for a recording and it won't be added to the gallery."
   },
-  "statusMsgRecordingStopped": {
+  "STATUS_MSG_RECORDING_STOPPED": {
     "message": "Įrašymas sustabdytas",
     "description": "Status message for spoken feedback when video recording has been stopped."
   },
-  "statusMsgCameraSwitched": {
+  "STATUS_MSG_CAMERA_SWITCHED": {
     "message": "$camera$ veikia",
     "description": "Status message for spoken feedback when switching over to another camera.",
     "placeholders": {
@@ -55,131 +55,131 @@
       }
     }
   },
-  "galleryButton": {
+  "GALLERY_BUTTON": {
     "message": "Eiti į galeriją",
     "description": "Label for the gallery button."
   },
-  "deleteButton": {
+  "DELETE_BUTTON": {
     "message": "Ištrinti",
     "description": "Label for the delete button."
   },
-  "exportButton": {
+  "EXPORT_BUTTON": {
     "message": "Eksportuoti į diską",
     "description": "Label for the exporting button."
   },
-  "printButton": {
+  "PRINT_BUTTON": {
     "message": "Spausdinti",
     "description": "Label for the printing button."
   },
-  "backButton": {
+  "BACK_BUTTON": {
     "message": "Grįžti atgal",
     "description": "Label for the back button."
   },
-  "galleryImages": {
+  "GALLERY_IMAGES": {
     "message": "Galerijos vaizdai",
     "description": "Text to speech label for the gallery list."
   },
-  "settingsButton": {
+  "SETTINGS_BUTTON": {
     "message": "Nustatymai",
     "description": "Label for the settings button."
   },
-  "gridTypeButton": {
+  "GRID_TYPE_BUTTON": {
     "message": "Tinklelio tipas",
     "description": "Label for the button of grid-type options."
   },
-  "timerDurationButton": {
+  "TIMER_DURATION_BUTTON": {
     "message": "Laikmačio trukmė",
     "description": "Label for the button of timer-duration options."
   },
-  "feedbackButton": {
+  "FEEDBACK_BUTTON": {
     "message": "Siųsti atsiliepimą",
     "description": "Label for the feedback button."
   },
-  "helpButton": {
+  "HELP_BUTTON": {
     "message": "Pagalba",
     "description": "Label for the help button."
   },
-  "labelGrid3x3": {
+  "LABEL_GRID_3X3": {
     "message": "3 ir 3",
     "description": "Label for for grid-type: 3x3."
   },
-  "ariaGrid3x3": {
+  "ARIA_GRID_3X3": {
     "message": "3 iš 3",
     "description": "Label for spoken feedback to read out grid-type: 3x3."
   },
-  "labelGrid4x4": {
+  "LABEL_GRID_4X4": {
     "message": "4 ir 4",
     "description": "Label for for grid-type: 4x4."
   },
-  "ariaGrid4x4": {
+  "ARIA_GRID_4X4": {
     "message": "4 iš 4",
     "description": "Label for spoken feedback to read out grid-type: 4x4."
   },
-  "labelGridGolden": {
+  "LABEL_GRID_GOLDEN": {
     "message": "Geriausias įvertinimas",
     "description": "Label for grid-type: golden ratio."
   },
-  "labelTimer3s": {
+  "LABEL_TIMER_3S": {
     "message": "3 sekundės",
     "description": "Label for timer-duration: 3 seconds."
   },
-  "labelTimer10s": {
+  "LABEL_TIMER_10S": {
     "message": "10 sekundžių",
     "description": "Label for timer-duration: 10 seconds."
   },
-  "takePhotoButton": {
+  "TAKE_PHOTO_BUTTON": {
     "message": "Fotografuoti",
     "description": "Label for the shutter button to take photo."
   },
-  "takePhotoCancelButton": {
+  "TAKE_PHOTO_CANCEL_BUTTON": {
     "message": "Sustabdyti fotografavimą",
     "description": "Label for the shutter button to cancel countdown timer and stop taking photo."
   },
-  "recordVideoStartButton": {
+  "RECORD_VIDEO_START_BUTTON": {
     "message": "Pradėti įrašymą",
     "description": "Label for the shutter button to start recording."
   },
-  "recordVideoStopButton": {
+  "RECORD_VIDEO_STOP_BUTTON": {
     "message": "Sustabdyti įrašymą",
     "description": "Label for the shutter button to stop recording."
   },
-  "switchCameraButton": {
+  "SWITCH_CAMERA_BUTTON": {
     "message": "Perjungti į kitą kamerą",
     "description": "Label for the button to switch to next connected camera. Eg. switching from front facing to back facing, or a camera connected via USB. The button is shown only when more than one camera is connected."
   },
-  "switchRecordVideoButton": {
+  "SWITCH_RECORD_VIDEO_BUTTON": {
     "message": "Perjungti į vaizdo įrašymo režimą",
     "description": "Label for the button to switch to record video mode."
   },
-  "switchTakePhotoButton": {
+  "SWITCH_TAKE_PHOTO_BUTTON": {
     "message": "Perjungti į fotografavimo režimą",
     "description": "Label for the button to switch to take photo mode."
   },
-  "toggleTimerButton": {
+  "TOGGLE_TIMER_BUTTON": {
     "message": "Laikmatis",
     "description": "Label for the checkbox to toggle the countdown timer."
   },
-  "toggleMirrorButton": {
+  "TOGGLE_MIRROR_BUTTON": {
     "message": "Atspindėjimas",
     "description": "Label for the checkbox to toggle the preview mirroring. Eg. if mirroring is toggled on, preview will be flipped horizontally."
   },
-  "toggleGridButton": {
+  "TOGGLE_GRID_BUTTON": {
     "message": "Tinklelis",
     "description": "Label for the checkbox to toggle the grid shown on preview."
   },
-  "toggleMicButton": {
+  "TOGGLE_MIC_BUTTON": {
     "message": "Mikrofonas",
     "description": "Label for the checkbox to toggle the microphone for recording video."
   },
-  "dialogOKButton": {
+  "DIALOG_OK_BUTTON": {
     "message": "Gerai",
     "description": "Label for the accepting button in the dialog."
   },
-  "dialogCancelButton": {
+  "DIALOG_CANCEL_BUTTON": {
     "message": "Atšaukti",
     "description": "Label for the dismissing button in the dialog."
   },
-  "deleteConfirmationMsg": {
+  "DELETE_CONFIRMATION_MSG": {
     "message": "Ar tikrai norite pašalinti failą $file$?",
     "description": "Confirmation message before removing a selected item from the gallery. Expects a file name to be passed in.",
     "placeholders": {
@@ -189,7 +189,7 @@
       }
     }
   },
-  "deleteMultiConfirmationMsg": {
+  "DELETE_MULTI_CONFIRMATION_MSG": {
     "message": "Ar tikrai norite pašalinti elementus ($count$)?",
     "description": "Confirmation message before removing multiple selected items from the gallery. Expects a file count to be passed in.",
     "placeholders": {
@@ -199,7 +199,7 @@
       }
     }
   },
-  "migratePicturesMsg": {
+  "MIGRATE_PICTURES_MSG": {
     "message": "Nuotraukos ir vaizdo įrašai, sukurti naudojant fotoaparatą, bus perkelti į aplanką „Atsisiuntimai“. Juos galite pasiekti Failų programoje.\n\nProgramos su saugyklos leidimais turės prieigą prie nuotraukų ir vaizdo įrašų.",
     "description": "Message shown before moving all photos and videos stored in the Camera App to the Downloads folder."
   }
diff --git a/chrome/browser/resources/chromeos/camera/src/_locales/lv/messages.json b/chrome/browser/resources/chromeos/camera/src/_locales/lv/messages.json
index db357ab..a59e899 100644
--- a/chrome/browser/resources/chromeos/camera/src/_locales/lv/messages.json
+++ b/chrome/browser/resources/chromeos/camera/src/_locales/lv/messages.json
@@ -1,21 +1,21 @@
 {
-  "name": {
+  "NAME": {
     "message": "Kamera",
     "description": "Name of the Camera App."
   },
-  "description": {
+  "DESCRIPTION": {
     "message": "Uzņemiet fotoattēlus un ierakstiet videoklipus, izmantojot savu kameru.",
     "description": "Short description of the Camera App."
   },
-  "errorMsgFileSystemFailed": {
+  "ERROR_MSG_FILE_SYSTEM_FAILED": {
     "message": "Failu sistēmas kļūdas.",
     "description": "Error message shown when failing to read or write the file system."
   },
-  "errorMsgNoCamera": {
+  "ERROR_MSG_NO_CAMERA": {
     "message": "Jūsu kamera pašlaik nav pieejama.\nPārbaudiet, vai ir pareizi izveidots savienojums ar kameru.",
     "description": "Error message shown when it was impossible to connect to the camera due to unavailability."
   },
-  "errorMsgGalleryExportFailed": {
+  "ERROR_MSG_GALLERY_EXPORT_FAILED": {
     "message": "Nevar eksportēt failu $file$.",
     "description": "Error message shown when exporting to an external directory failed. Expects a file name to be passed in.",
     "placeholders": {
@@ -25,27 +25,27 @@
       }
     }
   },
-  "errorMsgSaveFileFailed": {
+  "ERROR_MSG_SAVE_FILE_FAILED": {
     "message": "Nevar saglabāt failu.",
     "description": "Error message shown when saving/adding a image or video to the file system failed."
   },
-  "errorMsgTakePhotoFailed": {
+  "ERROR_MSG_TAKE_PHOTO_FAILED": {
     "message": "Nevar uzņemt fotoattēlu.",
     "description": "Error message shown when failing to take photo."
   },
-  "errorMsgRecordStartFailed": {
+  "ERROR_MSG_RECORD_START_FAILED": {
     "message": "Nevar sākt ierakstīšanu.",
     "description": "Error message shown when failing to start recording video."
   },
-  "errorMsgEmptyRecording": {
+  "ERROR_MSG_EMPTY_RECORDING": {
     "message": "Nekas nav ierakstīts.",
     "description": "Error message shown when no data is recorded for a recording and it won't be added to the gallery."
   },
-  "statusMsgRecordingStopped": {
+  "STATUS_MSG_RECORDING_STOPPED": {
     "message": "Ierakstīšana apturēta",
     "description": "Status message for spoken feedback when video recording has been stopped."
   },
-  "statusMsgCameraSwitched": {
+  "STATUS_MSG_CAMERA_SWITCHED": {
     "message": "$camera$ aktīva",
     "description": "Status message for spoken feedback when switching over to another camera.",
     "placeholders": {
@@ -55,131 +55,131 @@
       }
     }
   },
-  "galleryButton": {
+  "GALLERY_BUTTON": {
     "message": "Doties uz galeriju",
     "description": "Label for the gallery button."
   },
-  "deleteButton": {
+  "DELETE_BUTTON": {
     "message": "Dzēst",
     "description": "Label for the delete button."
   },
-  "exportButton": {
+  "EXPORT_BUTTON": {
     "message": "Eksportēt diskā",
     "description": "Label for the exporting button."
   },
-  "printButton": {
+  "PRINT_BUTTON": {
     "message": "Drukāt",
     "description": "Label for the printing button."
   },
-  "backButton": {
+  "BACK_BUTTON": {
     "message": "Atpakaļ",
     "description": "Label for the back button."
   },
-  "galleryImages": {
+  "GALLERY_IMAGES": {
     "message": "Galerijas attēli",
     "description": "Text to speech label for the gallery list."
   },
-  "settingsButton": {
+  "SETTINGS_BUTTON": {
     "message": "Iestatījumi",
     "description": "Label for the settings button."
   },
-  "gridTypeButton": {
+  "GRID_TYPE_BUTTON": {
     "message": "Režģa veids",
     "description": "Label for the button of grid-type options."
   },
-  "timerDurationButton": {
+  "TIMER_DURATION_BUTTON": {
     "message": "Taimera ilgums",
     "description": "Label for the button of timer-duration options."
   },
-  "feedbackButton": {
+  "FEEDBACK_BUTTON": {
     "message": "Sūtīt atsauksmes",
     "description": "Label for the feedback button."
   },
-  "helpButton": {
+  "HELP_BUTTON": {
     "message": "Palīdzība",
     "description": "Label for the help button."
   },
-  "labelGrid3x3": {
+  "LABEL_GRID_3X3": {
     "message": "3 x 3",
     "description": "Label for for grid-type: 3x3."
   },
-  "ariaGrid3x3": {
+  "ARIA_GRID_3X3": {
     "message": "3 reiz 3",
     "description": "Label for spoken feedback to read out grid-type: 3x3."
   },
-  "labelGrid4x4": {
+  "LABEL_GRID_4X4": {
     "message": "4 x 4",
     "description": "Label for for grid-type: 4x4."
   },
-  "ariaGrid4x4": {
+  "ARIA_GRID_4X4": {
     "message": "4 reiz 4",
     "description": "Label for spoken feedback to read out grid-type: 4x4."
   },
-  "labelGridGolden": {
+  "LABEL_GRID_GOLDEN": {
     "message": "Zelta griezums",
     "description": "Label for grid-type: golden ratio."
   },
-  "labelTimer3s": {
+  "LABEL_TIMER_3S": {
     "message": "3 sekundes",
     "description": "Label for timer-duration: 3 seconds."
   },
-  "labelTimer10s": {
+  "LABEL_TIMER_10S": {
     "message": "10 sekundes",
     "description": "Label for timer-duration: 10 seconds."
   },
-  "takePhotoButton": {
+  "TAKE_PHOTO_BUTTON": {
     "message": "Uzņemt fotoattēlu",
     "description": "Label for the shutter button to take photo."
   },
-  "takePhotoCancelButton": {
+  "TAKE_PHOTO_CANCEL_BUTTON": {
     "message": "Apturēt fotoattēla uzņemšanu",
     "description": "Label for the shutter button to cancel countdown timer and stop taking photo."
   },
-  "recordVideoStartButton": {
+  "RECORD_VIDEO_START_BUTTON": {
     "message": "Sākt ierakstīšanu",
     "description": "Label for the shutter button to start recording."
   },
-  "recordVideoStopButton": {
+  "RECORD_VIDEO_STOP_BUTTON": {
     "message": "Apturēt ierakstīšanu",
     "description": "Label for the shutter button to stop recording."
   },
-  "switchCameraButton": {
+  "SWITCH_CAMERA_BUTTON": {
     "message": "Pārslēgties uz nākamo kameru",
     "description": "Label for the button to switch to next connected camera. Eg. switching from front facing to back facing, or a camera connected via USB. The button is shown only when more than one camera is connected."
   },
-  "switchRecordVideoButton": {
+  "SWITCH_RECORD_VIDEO_BUTTON": {
     "message": "Pārslēgties uz videoklipa ierakstīšanu",
     "description": "Label for the button to switch to record video mode."
   },
-  "switchTakePhotoButton": {
+  "SWITCH_TAKE_PHOTO_BUTTON": {
     "message": "Pārslēgties uz fotoattēla uzņemšanu",
     "description": "Label for the button to switch to take photo mode."
   },
-  "toggleTimerButton": {
+  "TOGGLE_TIMER_BUTTON": {
     "message": "Taimeris",
     "description": "Label for the checkbox to toggle the countdown timer."
   },
-  "toggleMirrorButton": {
+  "TOGGLE_MIRROR_BUTTON": {
     "message": "Spoguļošana",
     "description": "Label for the checkbox to toggle the preview mirroring. Eg. if mirroring is toggled on, preview will be flipped horizontally."
   },
-  "toggleGridButton": {
+  "TOGGLE_GRID_BUTTON": {
     "message": "Režģis",
     "description": "Label for the checkbox to toggle the grid shown on preview."
   },
-  "toggleMicButton": {
+  "TOGGLE_MIC_BUTTON": {
     "message": "Mikrofons",
     "description": "Label for the checkbox to toggle the microphone for recording video."
   },
-  "dialogOKButton": {
+  "DIALOG_OK_BUTTON": {
     "message": "Labi",
     "description": "Label for the accepting button in the dialog."
   },
-  "dialogCancelButton": {
+  "DIALOG_CANCEL_BUTTON": {
     "message": "Atcelt",
     "description": "Label for the dismissing button in the dialog."
   },
-  "deleteConfirmationMsg": {
+  "DELETE_CONFIRMATION_MSG": {
     "message": "Vai tiešām vēlaties noņemt failu $file$?",
     "description": "Confirmation message before removing a selected item from the gallery. Expects a file name to be passed in.",
     "placeholders": {
@@ -189,7 +189,7 @@
       }
     }
   },
-  "deleteMultiConfirmationMsg": {
+  "DELETE_MULTI_CONFIRMATION_MSG": {
     "message": "Vai tiešām vēlaties noņemt $count$ failu(-us)?",
     "description": "Confirmation message before removing multiple selected items from the gallery. Expects a file count to be passed in.",
     "placeholders": {
@@ -199,7 +199,7 @@
       }
     }
   },
-  "migratePicturesMsg": {
+  "MIGRATE_PICTURES_MSG": {
     "message": "Ar kameru uzņemtie fotoattēli un videoklipi tiks ievietoti mapē Lejupielādes. Varat tiem piekļūt lietotnē Faili.\n\nJūsu fotoattēliem un videoklipiem varēs piekļūt lietotnes, kam ir krātuves atļaujas.",
     "description": "Message shown before moving all photos and videos stored in the Camera App to the Downloads folder."
   }
diff --git a/chrome/browser/resources/chromeos/camera/src/_locales/ml/messages.json b/chrome/browser/resources/chromeos/camera/src/_locales/ml/messages.json
index 4e8f3a0..454e774 100644
--- a/chrome/browser/resources/chromeos/camera/src/_locales/ml/messages.json
+++ b/chrome/browser/resources/chromeos/camera/src/_locales/ml/messages.json
@@ -1,21 +1,21 @@
 {
-  "name": {
+  "NAME": {
     "message": "ക്യാമറ",
     "description": "Name of the Camera App."
   },
-  "description": {
+  "DESCRIPTION": {
     "message": "നിങ്ങളുടെ ക്യാമറ ഉപയോഗിച്ച് ചിത്രങ്ങൾ എടുക്കുക, വീഡിയോകൾ റെക്കോർഡ് ചെയ്യുക.",
     "description": "Short description of the Camera App."
   },
-  "errorMsgFileSystemFailed": {
+  "ERROR_MSG_FILE_SYSTEM_FAILED": {
     "message": "ഫയൽ സിസ്‌റ്റം പിശകുകൾ.",
     "description": "Error message shown when failing to read or write the file system."
   },
-  "errorMsgNoCamera": {
+  "ERROR_MSG_NO_CAMERA": {
     "message": "ക്യാമറ നിലവിൽ ലഭ്യമല്ല.\nക്യാമറ ശരിയായി കണക്റ്റ് ചെയ്‌തിട്ടുണ്ടോ എന്ന് പരിശോധിക്കുക.",
     "description": "Error message shown when it was impossible to connect to the camera due to unavailability."
   },
-  "errorMsgGalleryExportFailed": {
+  "ERROR_MSG_GALLERY_EXPORT_FAILED": {
     "message": "$file$ എക്‌സ്‌പോർട്ട് ചെയ്യാനായില്ല",
     "description": "Error message shown when exporting to an external directory failed. Expects a file name to be passed in.",
     "placeholders": {
@@ -25,27 +25,27 @@
       }
     }
   },
-  "errorMsgSaveFileFailed": {
+  "ERROR_MSG_SAVE_FILE_FAILED": {
     "message": "ഫയൽ സംരക്ഷിക്കാനായില്ല",
     "description": "Error message shown when saving/adding a image or video to the file system failed."
   },
-  "errorMsgTakePhotoFailed": {
+  "ERROR_MSG_TAKE_PHOTO_FAILED": {
     "message": "ഫോട്ടോ എടുക്കാനായില്ല",
     "description": "Error message shown when failing to take photo."
   },
-  "errorMsgRecordStartFailed": {
+  "ERROR_MSG_RECORD_START_FAILED": {
     "message": "റെക്കോർഡിംഗ് ആരംഭിക്കാനായില്ല",
     "description": "Error message shown when failing to start recording video."
   },
-  "errorMsgEmptyRecording": {
+  "ERROR_MSG_EMPTY_RECORDING": {
     "message": "ഒന്നും റെക്കോർഡ് ചെയ്‌തില്ല",
     "description": "Error message shown when no data is recorded for a recording and it won't be added to the gallery."
   },
-  "statusMsgRecordingStopped": {
+  "STATUS_MSG_RECORDING_STOPPED": {
     "message": "റെക്കോർഡ് ചെയ്യൽ നിർത്തി",
     "description": "Status message for spoken feedback when video recording has been stopped."
   },
-  "statusMsgCameraSwitched": {
+  "STATUS_MSG_CAMERA_SWITCHED": {
     "message": "$camera$ സജീവമാണ്",
     "description": "Status message for spoken feedback when switching over to another camera.",
     "placeholders": {
@@ -55,131 +55,131 @@
       }
     }
   },
-  "galleryButton": {
+  "GALLERY_BUTTON": {
     "message": "ഗാലറിയിലേക്ക് പോവുക",
     "description": "Label for the gallery button."
   },
-  "deleteButton": {
+  "DELETE_BUTTON": {
     "message": "ഇല്ലാതാക്കുക",
     "description": "Label for the delete button."
   },
-  "exportButton": {
+  "EXPORT_BUTTON": {
     "message": "ഡിസ്‌ക്കിലേക്ക് എക്‌സ്‌പോർട്ട് ചെയ്യുക",
     "description": "Label for the exporting button."
   },
-  "printButton": {
+  "PRINT_BUTTON": {
     "message": "പ്രിന്‍റ് ചെയ്യുക",
     "description": "Label for the printing button."
   },
-  "backButton": {
+  "BACK_BUTTON": {
     "message": "തിരികെ പോവുക",
     "description": "Label for the back button."
   },
-  "galleryImages": {
+  "GALLERY_IMAGES": {
     "message": "ഗാലറി ചിത്രങ്ങൾ",
     "description": "Text to speech label for the gallery list."
   },
-  "settingsButton": {
+  "SETTINGS_BUTTON": {
     "message": "ക്രമീകരണം",
     "description": "Label for the settings button."
   },
-  "gridTypeButton": {
+  "GRID_TYPE_BUTTON": {
     "message": "ഗ്രിഡ് തരം",
     "description": "Label for the button of grid-type options."
   },
-  "timerDurationButton": {
+  "TIMER_DURATION_BUTTON": {
     "message": "ടൈമർ ദൈർഘ്യം",
     "description": "Label for the button of timer-duration options."
   },
-  "feedbackButton": {
+  "FEEDBACK_BUTTON": {
     "message": "ഫീഡ്‍ബാക്ക് അയയ്ക്കുക",
     "description": "Label for the feedback button."
   },
-  "helpButton": {
+  "HELP_BUTTON": {
     "message": "സഹായം",
     "description": "Label for the help button."
   },
-  "labelGrid3x3": {
+  "LABEL_GRID_3X3": {
     "message": "3 x 3",
     "description": "Label for for grid-type: 3x3."
   },
-  "ariaGrid3x3": {
+  "ARIA_GRID_3X3": {
     "message": "3 ബൈ 3",
     "description": "Label for spoken feedback to read out grid-type: 3x3."
   },
-  "labelGrid4x4": {
+  "LABEL_GRID_4X4": {
     "message": "4 x 4",
     "description": "Label for for grid-type: 4x4."
   },
-  "ariaGrid4x4": {
+  "ARIA_GRID_4X4": {
     "message": "4 ബൈ 4",
     "description": "Label for spoken feedback to read out grid-type: 4x4."
   },
-  "labelGridGolden": {
+  "LABEL_GRID_GOLDEN": {
     "message": "ഗോൾഡൻ റേഷ്യോ",
     "description": "Label for grid-type: golden ratio."
   },
-  "labelTimer3s": {
+  "LABEL_TIMER_3S": {
     "message": "3 സെക്കൻഡ്",
     "description": "Label for timer-duration: 3 seconds."
   },
-  "labelTimer10s": {
+  "LABEL_TIMER_10S": {
     "message": "10 സെക്കൻഡ്",
     "description": "Label for timer-duration: 10 seconds."
   },
-  "takePhotoButton": {
+  "TAKE_PHOTO_BUTTON": {
     "message": "ഫോട്ടോ എടുക്കുക",
     "description": "Label for the shutter button to take photo."
   },
-  "takePhotoCancelButton": {
+  "TAKE_PHOTO_CANCEL_BUTTON": {
     "message": "ഫോട്ടോ എടുക്കുന്നത് നിർത്തുക",
     "description": "Label for the shutter button to cancel countdown timer and stop taking photo."
   },
-  "recordVideoStartButton": {
+  "RECORD_VIDEO_START_BUTTON": {
     "message": "റെക്കോര്‍ഡിംഗ് ആരംഭിക്കുക",
     "description": "Label for the shutter button to start recording."
   },
-  "recordVideoStopButton": {
+  "RECORD_VIDEO_STOP_BUTTON": {
     "message": "റെക്കോർഡിംഗ് നിർത്തുക",
     "description": "Label for the shutter button to stop recording."
   },
-  "switchCameraButton": {
+  "SWITCH_CAMERA_BUTTON": {
     "message": "അടുത്ത ക്യാമറയിലേക്ക് മാറുക",
     "description": "Label for the button to switch to next connected camera. Eg. switching from front facing to back facing, or a camera connected via USB. The button is shown only when more than one camera is connected."
   },
-  "switchRecordVideoButton": {
+  "SWITCH_RECORD_VIDEO_BUTTON": {
     "message": "വീഡിയോ റെക്കോർഡ് ചെയ്യുന്നതിലേക്ക് മാറുക",
     "description": "Label for the button to switch to record video mode."
   },
-  "switchTakePhotoButton": {
+  "SWITCH_TAKE_PHOTO_BUTTON": {
     "message": "ഫോട്ടോ എടുക്കുന്നതിലേക്ക് മാറുക",
     "description": "Label for the button to switch to take photo mode."
   },
-  "toggleTimerButton": {
+  "TOGGLE_TIMER_BUTTON": {
     "message": "ടൈമർ",
     "description": "Label for the checkbox to toggle the countdown timer."
   },
-  "toggleMirrorButton": {
+  "TOGGLE_MIRROR_BUTTON": {
     "message": "മിററിംഗ്",
     "description": "Label for the checkbox to toggle the preview mirroring. Eg. if mirroring is toggled on, preview will be flipped horizontally."
   },
-  "toggleGridButton": {
+  "TOGGLE_GRID_BUTTON": {
     "message": "ഗ്രിഡ്",
     "description": "Label for the checkbox to toggle the grid shown on preview."
   },
-  "toggleMicButton": {
+  "TOGGLE_MIC_BUTTON": {
     "message": "മൈക്രോഫോൺ",
     "description": "Label for the checkbox to toggle the microphone for recording video."
   },
-  "dialogOKButton": {
+  "DIALOG_OK_BUTTON": {
     "message": "ശരി",
     "description": "Label for the accepting button in the dialog."
   },
-  "dialogCancelButton": {
+  "DIALOG_CANCEL_BUTTON": {
     "message": "റദ്ദാക്കുക",
     "description": "Label for the dismissing button in the dialog."
   },
-  "deleteConfirmationMsg": {
+  "DELETE_CONFIRMATION_MSG": {
     "message": "നിങ്ങൾക്ക് ശരിക്കും $file$ നീക്കം ചെയ്യണോ?",
     "description": "Confirmation message before removing a selected item from the gallery. Expects a file name to be passed in.",
     "placeholders": {
@@ -189,7 +189,7 @@
       }
     }
   },
-  "deleteMultiConfirmationMsg": {
+  "DELETE_MULTI_CONFIRMATION_MSG": {
     "message": "നിങ്ങൾക്ക് ശരിക്കും $count$ ഇനങ്ങൾ നീക്കം ചെയ്യണോ?",
     "description": "Confirmation message before removing multiple selected items from the gallery. Expects a file count to be passed in.",
     "placeholders": {
@@ -199,7 +199,7 @@
       }
     }
   },
-  "migratePicturesMsg": {
+  "MIGRATE_PICTURES_MSG": {
     "message": "ക്യാമറ ഉപയോഗിച്ചെടുത്ത ഫോട്ടോകളും വീഡിയോകളും 'ഡൗൺലോഡുകൾ' ഫോൾഡറിലേക്ക് നീക്കും. നിങ്ങൾക്ക് അവ ഫയലുകളിൽ ആക്‌സസ് ചെയ്യാനാവും.\n\nസ്‌റ്റോറേജ് അനുമതികളുള്ള ആപ്പുകൾക്ക് നിങ്ങളുടെ ഫോട്ടോകളിലേക്കും വീഡിയോകളിലേക്കും ആക്‌സസ് ഉണ്ടായിരിക്കും.",
     "description": "Message shown before moving all photos and videos stored in the Camera App to the Downloads folder."
   }
diff --git a/chrome/browser/resources/chromeos/camera/src/_locales/mr/messages.json b/chrome/browser/resources/chromeos/camera/src/_locales/mr/messages.json
index a1007dce..a1de935b 100644
--- a/chrome/browser/resources/chromeos/camera/src/_locales/mr/messages.json
+++ b/chrome/browser/resources/chromeos/camera/src/_locales/mr/messages.json
@@ -1,21 +1,21 @@
 {
-  "name": {
+  "NAME": {
     "message": "कॅमेरा",
     "description": "Name of the Camera App."
   },
-  "description": {
+  "DESCRIPTION": {
     "message": "तुमच्‍या कॅमेर्‍याने फोटो काढा आणि व्हिडिओ रेकॉर्ड करा.",
     "description": "Short description of the Camera App."
   },
-  "errorMsgFileSystemFailed": {
+  "ERROR_MSG_FILE_SYSTEM_FAILED": {
     "message": "फाइल सिस्टम एरर.",
     "description": "Error message shown when failing to read or write the file system."
   },
-  "errorMsgNoCamera": {
+  "ERROR_MSG_NO_CAMERA": {
     "message": "तुमचा कॅमेरा सध्या उपलब्ध नाही.\nकृपया कॅमेरा योग्यरीत्‍या कनेक्ट केला असल्याचे तपासा.",
     "description": "Error message shown when it was impossible to connect to the camera due to unavailability."
   },
-  "errorMsgGalleryExportFailed": {
+  "ERROR_MSG_GALLERY_EXPORT_FAILED": {
     "message": "$file$ एक्सपोर्ट करता आली नाही",
     "description": "Error message shown when exporting to an external directory failed. Expects a file name to be passed in.",
     "placeholders": {
@@ -25,27 +25,27 @@
       }
     }
   },
-  "errorMsgSaveFileFailed": {
+  "ERROR_MSG_SAVE_FILE_FAILED": {
     "message": "फाइल सेव्‍ह करता आली नाही",
     "description": "Error message shown when saving/adding a image or video to the file system failed."
   },
-  "errorMsgTakePhotoFailed": {
+  "ERROR_MSG_TAKE_PHOTO_FAILED": {
     "message": "फोटो काढता आला नाही",
     "description": "Error message shown when failing to take photo."
   },
-  "errorMsgRecordStartFailed": {
+  "ERROR_MSG_RECORD_START_FAILED": {
     "message": "रेकॉर्डिंग सुरू करता आले नाही",
     "description": "Error message shown when failing to start recording video."
   },
-  "errorMsgEmptyRecording": {
+  "ERROR_MSG_EMPTY_RECORDING": {
     "message": "काहीही रेकॉर्ड केले नाही",
     "description": "Error message shown when no data is recorded for a recording and it won't be added to the gallery."
   },
-  "statusMsgRecordingStopped": {
+  "STATUS_MSG_RECORDING_STOPPED": {
     "message": "रेकॉर्डिंग थांबले आहे",
     "description": "Status message for spoken feedback when video recording has been stopped."
   },
-  "statusMsgCameraSwitched": {
+  "STATUS_MSG_CAMERA_SWITCHED": {
     "message": "$camera$ अ‍ॅक्टिव्ह आहे",
     "description": "Status message for spoken feedback when switching over to another camera.",
     "placeholders": {
@@ -55,131 +55,131 @@
       }
     }
   },
-  "galleryButton": {
+  "GALLERY_BUTTON": {
     "message": "गॅलरीवर जा",
     "description": "Label for the gallery button."
   },
-  "deleteButton": {
+  "DELETE_BUTTON": {
     "message": "हटवा",
     "description": "Label for the delete button."
   },
-  "exportButton": {
+  "EXPORT_BUTTON": {
     "message": "डिस्कवर निर्यात करा",
     "description": "Label for the exporting button."
   },
-  "printButton": {
+  "PRINT_BUTTON": {
     "message": "प्रिंट करा",
     "description": "Label for the printing button."
   },
-  "backButton": {
+  "BACK_BUTTON": {
     "message": "परत जा",
     "description": "Label for the back button."
   },
-  "galleryImages": {
+  "GALLERY_IMAGES": {
     "message": "गॅलरीमधील इमेज",
     "description": "Text to speech label for the gallery list."
   },
-  "settingsButton": {
+  "SETTINGS_BUTTON": {
     "message": "सेटिंग्ज",
     "description": "Label for the settings button."
   },
-  "gridTypeButton": {
+  "GRID_TYPE_BUTTON": {
     "message": "ग्रिडचा प्रकार",
     "description": "Label for the button of grid-type options."
   },
-  "timerDurationButton": {
+  "TIMER_DURATION_BUTTON": {
     "message": "टायमरचा कालावधी",
     "description": "Label for the button of timer-duration options."
   },
-  "feedbackButton": {
+  "FEEDBACK_BUTTON": {
     "message": "फीडबॅक पाठवा",
     "description": "Label for the feedback button."
   },
-  "helpButton": {
+  "HELP_BUTTON": {
     "message": "मदत",
     "description": "Label for the help button."
   },
-  "labelGrid3x3": {
+  "LABEL_GRID_3X3": {
     "message": "३ x ३",
     "description": "Label for for grid-type: 3x3."
   },
-  "ariaGrid3x3": {
+  "ARIA_GRID_3X3": {
     "message": "३ बाय ३",
     "description": "Label for spoken feedback to read out grid-type: 3x3."
   },
-  "labelGrid4x4": {
+  "LABEL_GRID_4X4": {
     "message": "४ x ४",
     "description": "Label for for grid-type: 4x4."
   },
-  "ariaGrid4x4": {
+  "ARIA_GRID_4X4": {
     "message": "४ बाय ४",
     "description": "Label for spoken feedback to read out grid-type: 4x4."
   },
-  "labelGridGolden": {
+  "LABEL_GRID_GOLDEN": {
     "message": "गोल्डन रेशो",
     "description": "Label for grid-type: golden ratio."
   },
-  "labelTimer3s": {
+  "LABEL_TIMER_3S": {
     "message": "तीन सेकंद",
     "description": "Label for timer-duration: 3 seconds."
   },
-  "labelTimer10s": {
+  "LABEL_TIMER_10S": {
     "message": "१० सेकंद",
     "description": "Label for timer-duration: 10 seconds."
   },
-  "takePhotoButton": {
+  "TAKE_PHOTO_BUTTON": {
     "message": "फोटो काढा",
     "description": "Label for the shutter button to take photo."
   },
-  "takePhotoCancelButton": {
+  "TAKE_PHOTO_CANCEL_BUTTON": {
     "message": "फोटो काढणे थांबवा",
     "description": "Label for the shutter button to cancel countdown timer and stop taking photo."
   },
-  "recordVideoStartButton": {
+  "RECORD_VIDEO_START_BUTTON": {
     "message": "रेकॉर्डिंग सुरू करा",
     "description": "Label for the shutter button to start recording."
   },
-  "recordVideoStopButton": {
+  "RECORD_VIDEO_STOP_BUTTON": {
     "message": "रेकॉर्डिंग थांबवा",
     "description": "Label for the shutter button to stop recording."
   },
-  "switchCameraButton": {
+  "SWITCH_CAMERA_BUTTON": {
     "message": "पुढील कॅमेर्‍यावर स्विच करा",
     "description": "Label for the button to switch to next connected camera. Eg. switching from front facing to back facing, or a camera connected via USB. The button is shown only when more than one camera is connected."
   },
-  "switchRecordVideoButton": {
+  "SWITCH_RECORD_VIDEO_BUTTON": {
     "message": "व्हिडिओ रेकॉर्ड करण्‍यासाठी स्विच करा",
     "description": "Label for the button to switch to record video mode."
   },
-  "switchTakePhotoButton": {
+  "SWITCH_TAKE_PHOTO_BUTTON": {
     "message": "फोटो काढण्यासाठी स्विच करा",
     "description": "Label for the button to switch to take photo mode."
   },
-  "toggleTimerButton": {
+  "TOGGLE_TIMER_BUTTON": {
     "message": "टायमर",
     "description": "Label for the checkbox to toggle the countdown timer."
   },
-  "toggleMirrorButton": {
+  "TOGGLE_MIRROR_BUTTON": {
     "message": "मिररिंग",
     "description": "Label for the checkbox to toggle the preview mirroring. Eg. if mirroring is toggled on, preview will be flipped horizontally."
   },
-  "toggleGridButton": {
+  "TOGGLE_GRID_BUTTON": {
     "message": "ग्रिड",
     "description": "Label for the checkbox to toggle the grid shown on preview."
   },
-  "toggleMicButton": {
+  "TOGGLE_MIC_BUTTON": {
     "message": "मायक्रोफोन",
     "description": "Label for the checkbox to toggle the microphone for recording video."
   },
-  "dialogOKButton": {
+  "DIALOG_OK_BUTTON": {
     "message": "ओके",
     "description": "Label for the accepting button in the dialog."
   },
-  "dialogCancelButton": {
+  "DIALOG_CANCEL_BUTTON": {
     "message": "रद्द करा",
     "description": "Label for the dismissing button in the dialog."
   },
-  "deleteConfirmationMsg": {
+  "DELETE_CONFIRMATION_MSG": {
     "message": "तुम्‍हाला $file$ खरोखर काढून टाकायची आहे?",
     "description": "Confirmation message before removing a selected item from the gallery. Expects a file name to be passed in.",
     "placeholders": {
@@ -189,7 +189,7 @@
       }
     }
   },
-  "deleteMultiConfirmationMsg": {
+  "DELETE_MULTI_CONFIRMATION_MSG": {
     "message": "तुम्‍हाला $count$ आयटम खरोखर काढून टाकायचे आहेत?",
     "description": "Confirmation message before removing multiple selected items from the gallery. Expects a file count to be passed in.",
     "placeholders": {
@@ -199,7 +199,7 @@
       }
     }
   },
-  "migratePicturesMsg": {
+  "MIGRATE_PICTURES_MSG": {
     "message": "कॅमेर्‍याने काढलेले फोटो आणि व्हिडिओ डाउनलोड फोल्डरवर हलवले जातील. तुम्ही ते फायलींमध्ये अ‍ॅक्सेस करू शकता.\n\nस्टोरेज परवानग्या असलेल्या अ‍ॅप्सना तुमच्या फोटोचा आणि व्हिडिओचा अ‍ॅक्सेस असेल.",
     "description": "Message shown before moving all photos and videos stored in the Camera App to the Downloads folder."
   }
diff --git a/chrome/browser/resources/chromeos/camera/src/_locales/ms/messages.json b/chrome/browser/resources/chromeos/camera/src/_locales/ms/messages.json
index 73e96b9..edad0aa 100644
--- a/chrome/browser/resources/chromeos/camera/src/_locales/ms/messages.json
+++ b/chrome/browser/resources/chromeos/camera/src/_locales/ms/messages.json
@@ -1,21 +1,21 @@
 {
-  "name": {
+  "NAME": {
     "message": "Kamera",
     "description": "Name of the Camera App."
   },
-  "description": {
+  "DESCRIPTION": {
     "message": "Ambil foto dan rakam video dengan kamera anda.",
     "description": "Short description of the Camera App."
   },
-  "errorMsgFileSystemFailed": {
+  "ERROR_MSG_FILE_SYSTEM_FAILED": {
     "message": "Ralat sistem fail.",
     "description": "Error message shown when failing to read or write the file system."
   },
-  "errorMsgNoCamera": {
+  "ERROR_MSG_NO_CAMERA": {
     "message": "Kamera anda tidak tersedia pada masa ini.\nSila periksa sama ada kamera disambungkan dengan betul.",
     "description": "Error message shown when it was impossible to connect to the camera due to unavailability."
   },
-  "errorMsgGalleryExportFailed": {
+  "ERROR_MSG_GALLERY_EXPORT_FAILED": {
     "message": "Tidak dapat mengeksport $file$",
     "description": "Error message shown when exporting to an external directory failed. Expects a file name to be passed in.",
     "placeholders": {
@@ -25,27 +25,27 @@
       }
     }
   },
-  "errorMsgSaveFileFailed": {
+  "ERROR_MSG_SAVE_FILE_FAILED": {
     "message": "Tidak dapat menyimpan fail",
     "description": "Error message shown when saving/adding a image or video to the file system failed."
   },
-  "errorMsgTakePhotoFailed": {
+  "ERROR_MSG_TAKE_PHOTO_FAILED": {
     "message": "Tidak dapat mengambil foto",
     "description": "Error message shown when failing to take photo."
   },
-  "errorMsgRecordStartFailed": {
+  "ERROR_MSG_RECORD_START_FAILED": {
     "message": "Tidak dapat memulakan rakaman",
     "description": "Error message shown when failing to start recording video."
   },
-  "errorMsgEmptyRecording": {
+  "ERROR_MSG_EMPTY_RECORDING": {
     "message": "Tiada apa-apa yang dirakamkan",
     "description": "Error message shown when no data is recorded for a recording and it won't be added to the gallery."
   },
-  "statusMsgRecordingStopped": {
+  "STATUS_MSG_RECORDING_STOPPED": {
     "message": "Rakaman dihentikan",
     "description": "Status message for spoken feedback when video recording has been stopped."
   },
-  "statusMsgCameraSwitched": {
+  "STATUS_MSG_CAMERA_SWITCHED": {
     "message": "$camera$ aktif",
     "description": "Status message for spoken feedback when switching over to another camera.",
     "placeholders": {
@@ -55,131 +55,131 @@
       }
     }
   },
-  "galleryButton": {
+  "GALLERY_BUTTON": {
     "message": "Pergi ke galeri",
     "description": "Label for the gallery button."
   },
-  "deleteButton": {
+  "DELETE_BUTTON": {
     "message": "Padam",
     "description": "Label for the delete button."
   },
-  "exportButton": {
+  "EXPORT_BUTTON": {
     "message": "Eksport ke cakera",
     "description": "Label for the exporting button."
   },
-  "printButton": {
+  "PRINT_BUTTON": {
     "message": "Cetak",
     "description": "Label for the printing button."
   },
-  "backButton": {
+  "BACK_BUTTON": {
     "message": "Kembali",
     "description": "Label for the back button."
   },
-  "galleryImages": {
+  "GALLERY_IMAGES": {
     "message": "Imej galeri",
     "description": "Text to speech label for the gallery list."
   },
-  "settingsButton": {
+  "SETTINGS_BUTTON": {
     "message": "Tetapan",
     "description": "Label for the settings button."
   },
-  "gridTypeButton": {
+  "GRID_TYPE_BUTTON": {
     "message": "Jenis grid",
     "description": "Label for the button of grid-type options."
   },
-  "timerDurationButton": {
+  "TIMER_DURATION_BUTTON": {
     "message": "Tempoh pemasa",
     "description": "Label for the button of timer-duration options."
   },
-  "feedbackButton": {
+  "FEEDBACK_BUTTON": {
     "message": "Hantar maklum balas",
     "description": "Label for the feedback button."
   },
-  "helpButton": {
+  "HELP_BUTTON": {
     "message": "Bantuan",
     "description": "Label for the help button."
   },
-  "labelGrid3x3": {
+  "LABEL_GRID_3X3": {
     "message": "3 x 3",
     "description": "Label for for grid-type: 3x3."
   },
-  "ariaGrid3x3": {
+  "ARIA_GRID_3X3": {
     "message": "3 kali 3",
     "description": "Label for spoken feedback to read out grid-type: 3x3."
   },
-  "labelGrid4x4": {
+  "LABEL_GRID_4X4": {
     "message": "4 x 4",
     "description": "Label for for grid-type: 4x4."
   },
-  "ariaGrid4x4": {
+  "ARIA_GRID_4X4": {
     "message": "4 kali 4",
     "description": "Label for spoken feedback to read out grid-type: 4x4."
   },
-  "labelGridGolden": {
+  "LABEL_GRID_GOLDEN": {
     "message": "Nisbah keemasan",
     "description": "Label for grid-type: golden ratio."
   },
-  "labelTimer3s": {
+  "LABEL_TIMER_3S": {
     "message": "3 saat",
     "description": "Label for timer-duration: 3 seconds."
   },
-  "labelTimer10s": {
+  "LABEL_TIMER_10S": {
     "message": "10 saat",
     "description": "Label for timer-duration: 10 seconds."
   },
-  "takePhotoButton": {
+  "TAKE_PHOTO_BUTTON": {
     "message": "Ambil foto",
     "description": "Label for the shutter button to take photo."
   },
-  "takePhotoCancelButton": {
+  "TAKE_PHOTO_CANCEL_BUTTON": {
     "message": "Berhenti mengambil foto",
     "description": "Label for the shutter button to cancel countdown timer and stop taking photo."
   },
-  "recordVideoStartButton": {
+  "RECORD_VIDEO_START_BUTTON": {
     "message": "Mulakan rakaman",
     "description": "Label for the shutter button to start recording."
   },
-  "recordVideoStopButton": {
+  "RECORD_VIDEO_STOP_BUTTON": {
     "message": "Hentikan rakaman",
     "description": "Label for the shutter button to stop recording."
   },
-  "switchCameraButton": {
+  "SWITCH_CAMERA_BUTTON": {
     "message": "Beralih kepada kamera seterusnya",
     "description": "Label for the button to switch to next connected camera. Eg. switching from front facing to back facing, or a camera connected via USB. The button is shown only when more than one camera is connected."
   },
-  "switchRecordVideoButton": {
+  "SWITCH_RECORD_VIDEO_BUTTON": {
     "message": "Beralih kepada merakam video",
     "description": "Label for the button to switch to record video mode."
   },
-  "switchTakePhotoButton": {
+  "SWITCH_TAKE_PHOTO_BUTTON": {
     "message": "Beralih kepada mengambil foto",
     "description": "Label for the button to switch to take photo mode."
   },
-  "toggleTimerButton": {
+  "TOGGLE_TIMER_BUTTON": {
     "message": "Pemasa",
     "description": "Label for the checkbox to toggle the countdown timer."
   },
-  "toggleMirrorButton": {
+  "TOGGLE_MIRROR_BUTTON": {
     "message": "Pencerminan",
     "description": "Label for the checkbox to toggle the preview mirroring. Eg. if mirroring is toggled on, preview will be flipped horizontally."
   },
-  "toggleGridButton": {
+  "TOGGLE_GRID_BUTTON": {
     "message": "Grid",
     "description": "Label for the checkbox to toggle the grid shown on preview."
   },
-  "toggleMicButton": {
+  "TOGGLE_MIC_BUTTON": {
     "message": "Mikrofon",
     "description": "Label for the checkbox to toggle the microphone for recording video."
   },
-  "dialogOKButton": {
+  "DIALOG_OK_BUTTON": {
     "message": "OK",
     "description": "Label for the accepting button in the dialog."
   },
-  "dialogCancelButton": {
+  "DIALOG_CANCEL_BUTTON": {
     "message": "Batal",
     "description": "Label for the dismissing button in the dialog."
   },
-  "deleteConfirmationMsg": {
+  "DELETE_CONFIRMATION_MSG": {
     "message": "Adakah anda benar-benar mahu mengalih keluar $file$?",
     "description": "Confirmation message before removing a selected item from the gallery. Expects a file name to be passed in.",
     "placeholders": {
@@ -189,7 +189,7 @@
       }
     }
   },
-  "deleteMultiConfirmationMsg": {
+  "DELETE_MULTI_CONFIRMATION_MSG": {
     "message": "Adakah anda benar-benar mahu mengalih keluar $count$ item?",
     "description": "Confirmation message before removing multiple selected items from the gallery. Expects a file count to be passed in.",
     "placeholders": {
@@ -199,7 +199,7 @@
       }
     }
   },
-  "migratePicturesMsg": {
+  "MIGRATE_PICTURES_MSG": {
     "message": "Foto dan video yang diambil dengan kamera akan dialihkan ke folder Muat turun. Anda boleh mengakses item ini dalam Fail.\n\nApl dengan kebenaran storan akan boleh mengakses foto dan video anda.",
     "description": "Message shown before moving all photos and videos stored in the Camera App to the Downloads folder."
   }
diff --git a/chrome/browser/resources/chromeos/camera/src/_locales/nl/messages.json b/chrome/browser/resources/chromeos/camera/src/_locales/nl/messages.json
index 543b7888..54059af 100644
--- a/chrome/browser/resources/chromeos/camera/src/_locales/nl/messages.json
+++ b/chrome/browser/resources/chromeos/camera/src/_locales/nl/messages.json
@@ -1,21 +1,21 @@
 {
-  "name": {
+  "NAME": {
     "message": "Camera",
     "description": "Name of the Camera App."
   },
-  "description": {
+  "DESCRIPTION": {
     "message": "Maak foto's en neem video's op met je camera.",
     "description": "Short description of the Camera App."
   },
-  "errorMsgFileSystemFailed": {
+  "ERROR_MSG_FILE_SYSTEM_FAILED": {
     "message": "Bestandssysteemfouten.",
     "description": "Error message shown when failing to read or write the file system."
   },
-  "errorMsgNoCamera": {
+  "ERROR_MSG_NO_CAMERA": {
     "message": "Je camera is momenteel niet beschikbaar.\nControleer of de camera correct is aangesloten.",
     "description": "Error message shown when it was impossible to connect to the camera due to unavailability."
   },
-  "errorMsgGalleryExportFailed": {
+  "ERROR_MSG_GALLERY_EXPORT_FAILED": {
     "message": "Kan $file$ niet exporteren",
     "description": "Error message shown when exporting to an external directory failed. Expects a file name to be passed in.",
     "placeholders": {
@@ -25,27 +25,27 @@
       }
     }
   },
-  "errorMsgSaveFileFailed": {
+  "ERROR_MSG_SAVE_FILE_FAILED": {
     "message": "Kan het bestand niet opslaan",
     "description": "Error message shown when saving/adding a image or video to the file system failed."
   },
-  "errorMsgTakePhotoFailed": {
+  "ERROR_MSG_TAKE_PHOTO_FAILED": {
     "message": "Kan geen foto maken",
     "description": "Error message shown when failing to take photo."
   },
-  "errorMsgRecordStartFailed": {
+  "ERROR_MSG_RECORD_START_FAILED": {
     "message": "Kan opname niet starten",
     "description": "Error message shown when failing to start recording video."
   },
-  "errorMsgEmptyRecording": {
+  "ERROR_MSG_EMPTY_RECORDING": {
     "message": "Niets opgenomen",
     "description": "Error message shown when no data is recorded for a recording and it won't be added to the gallery."
   },
-  "statusMsgRecordingStopped": {
+  "STATUS_MSG_RECORDING_STOPPED": {
     "message": "Opname gestopt",
     "description": "Status message for spoken feedback when video recording has been stopped."
   },
-  "statusMsgCameraSwitched": {
+  "STATUS_MSG_CAMERA_SWITCHED": {
     "message": "$camera$ actief",
     "description": "Status message for spoken feedback when switching over to another camera.",
     "placeholders": {
@@ -55,131 +55,131 @@
       }
     }
   },
-  "galleryButton": {
+  "GALLERY_BUTTON": {
     "message": "Ga naar galerij",
     "description": "Label for the gallery button."
   },
-  "deleteButton": {
+  "DELETE_BUTTON": {
     "message": "Verwijderen",
     "description": "Label for the delete button."
   },
-  "exportButton": {
+  "EXPORT_BUTTON": {
     "message": "Exporteren naar schijf",
     "description": "Label for the exporting button."
   },
-  "printButton": {
+  "PRINT_BUTTON": {
     "message": "Afdrukken",
     "description": "Label for the printing button."
   },
-  "backButton": {
+  "BACK_BUTTON": {
     "message": "Terug",
     "description": "Label for the back button."
   },
-  "galleryImages": {
+  "GALLERY_IMAGES": {
     "message": "Galerij-afbeeldingen",
     "description": "Text to speech label for the gallery list."
   },
-  "settingsButton": {
+  "SETTINGS_BUTTON": {
     "message": "Instellingen",
     "description": "Label for the settings button."
   },
-  "gridTypeButton": {
+  "GRID_TYPE_BUTTON": {
     "message": "Rastertype",
     "description": "Label for the button of grid-type options."
   },
-  "timerDurationButton": {
+  "TIMER_DURATION_BUTTON": {
     "message": "Timerduur",
     "description": "Label for the button of timer-duration options."
   },
-  "feedbackButton": {
+  "FEEDBACK_BUTTON": {
     "message": "Feedback verzenden",
     "description": "Label for the feedback button."
   },
-  "helpButton": {
+  "HELP_BUTTON": {
     "message": "Help",
     "description": "Label for the help button."
   },
-  "labelGrid3x3": {
+  "LABEL_GRID_3X3": {
     "message": "3 x 3",
     "description": "Label for for grid-type: 3x3."
   },
-  "ariaGrid3x3": {
+  "ARIA_GRID_3X3": {
     "message": "3 bij 3",
     "description": "Label for spoken feedback to read out grid-type: 3x3."
   },
-  "labelGrid4x4": {
+  "LABEL_GRID_4X4": {
     "message": "4 x 4",
     "description": "Label for for grid-type: 4x4."
   },
-  "ariaGrid4x4": {
+  "ARIA_GRID_4X4": {
     "message": "4 bij 4",
     "description": "Label for spoken feedback to read out grid-type: 4x4."
   },
-  "labelGridGolden": {
+  "LABEL_GRID_GOLDEN": {
     "message": "Gulden snede",
     "description": "Label for grid-type: golden ratio."
   },
-  "labelTimer3s": {
+  "LABEL_TIMER_3S": {
     "message": "3 seconden",
     "description": "Label for timer-duration: 3 seconds."
   },
-  "labelTimer10s": {
+  "LABEL_TIMER_10S": {
     "message": "10 seconden",
     "description": "Label for timer-duration: 10 seconds."
   },
-  "takePhotoButton": {
+  "TAKE_PHOTO_BUTTON": {
     "message": "Foto maken",
     "description": "Label for the shutter button to take photo."
   },
-  "takePhotoCancelButton": {
+  "TAKE_PHOTO_CANCEL_BUTTON": {
     "message": "Foto maken stoppen",
     "description": "Label for the shutter button to cancel countdown timer and stop taking photo."
   },
-  "recordVideoStartButton": {
+  "RECORD_VIDEO_START_BUTTON": {
     "message": "Opname starten",
     "description": "Label for the shutter button to start recording."
   },
-  "recordVideoStopButton": {
+  "RECORD_VIDEO_STOP_BUTTON": {
     "message": "Opname stoppen",
     "description": "Label for the shutter button to stop recording."
   },
-  "switchCameraButton": {
+  "SWITCH_CAMERA_BUTTON": {
     "message": "Naar volgende camera",
     "description": "Label for the button to switch to next connected camera. Eg. switching from front facing to back facing, or a camera connected via USB. The button is shown only when more than one camera is connected."
   },
-  "switchRecordVideoButton": {
+  "SWITCH_RECORD_VIDEO_BUTTON": {
     "message": "Naar video opnemen",
     "description": "Label for the button to switch to record video mode."
   },
-  "switchTakePhotoButton": {
+  "SWITCH_TAKE_PHOTO_BUTTON": {
     "message": "Naar foto maken",
     "description": "Label for the button to switch to take photo mode."
   },
-  "toggleTimerButton": {
+  "TOGGLE_TIMER_BUTTON": {
     "message": "Timer",
     "description": "Label for the checkbox to toggle the countdown timer."
   },
-  "toggleMirrorButton": {
+  "TOGGLE_MIRROR_BUTTON": {
     "message": "Mirroring",
     "description": "Label for the checkbox to toggle the preview mirroring. Eg. if mirroring is toggled on, preview will be flipped horizontally."
   },
-  "toggleGridButton": {
+  "TOGGLE_GRID_BUTTON": {
     "message": "Raster",
     "description": "Label for the checkbox to toggle the grid shown on preview."
   },
-  "toggleMicButton": {
+  "TOGGLE_MIC_BUTTON": {
     "message": "Microfoon",
     "description": "Label for the checkbox to toggle the microphone for recording video."
   },
-  "dialogOKButton": {
+  "DIALOG_OK_BUTTON": {
     "message": "OK",
     "description": "Label for the accepting button in the dialog."
   },
-  "dialogCancelButton": {
+  "DIALOG_CANCEL_BUTTON": {
     "message": "Annuleren",
     "description": "Label for the dismissing button in the dialog."
   },
-  "deleteConfirmationMsg": {
+  "DELETE_CONFIRMATION_MSG": {
     "message": "Weet je zeker dat je $file$ wilt verwijderen?",
     "description": "Confirmation message before removing a selected item from the gallery. Expects a file name to be passed in.",
     "placeholders": {
@@ -189,7 +189,7 @@
       }
     }
   },
-  "deleteMultiConfirmationMsg": {
+  "DELETE_MULTI_CONFIRMATION_MSG": {
     "message": "Weet je zeker dat je $count$ items wilt verwijderen?",
     "description": "Confirmation message before removing multiple selected items from the gallery. Expects a file count to be passed in.",
     "placeholders": {
@@ -199,7 +199,7 @@
       }
     }
   },
-  "migratePicturesMsg": {
+  "MIGRATE_PICTURES_MSG": {
     "message": "Foto's en video's die met de camera zijn gemaakt, worden verplaatst naar de map Downloads. Je kunt ze vinden via Bestanden.\n\nApps met opslagmachtiging hebben toegang tot je foto's en video's.",
     "description": "Message shown before moving all photos and videos stored in the Camera App to the Downloads folder."
   }
diff --git a/chrome/browser/resources/chromeos/camera/src/_locales/no/messages.json b/chrome/browser/resources/chromeos/camera/src/_locales/no/messages.json
index c7b5fe9..142e138c 100644
--- a/chrome/browser/resources/chromeos/camera/src/_locales/no/messages.json
+++ b/chrome/browser/resources/chromeos/camera/src/_locales/no/messages.json
@@ -1,21 +1,21 @@
 {
-  "name": {
+  "NAME": {
     "message": "Kamera",
     "description": "Name of the Camera App."
   },
-  "description": {
+  "DESCRIPTION": {
     "message": "Ta bilder og ta opp video med kameraet ditt.",
     "description": "Short description of the Camera App."
   },
-  "errorMsgFileSystemFailed": {
+  "ERROR_MSG_FILE_SYSTEM_FAILED": {
     "message": "Filsystemfeil.",
     "description": "Error message shown when failing to read or write the file system."
   },
-  "errorMsgNoCamera": {
+  "ERROR_MSG_NO_CAMERA": {
     "message": "Kameraet ditt er utilgjengelig for øyeblikket.\nSjekk om kameraet er koblet til riktig.",
     "description": "Error message shown when it was impossible to connect to the camera due to unavailability."
   },
-  "errorMsgGalleryExportFailed": {
+  "ERROR_MSG_GALLERY_EXPORT_FAILED": {
     "message": "Kan ikke eksportere $file$",
     "description": "Error message shown when exporting to an external directory failed. Expects a file name to be passed in.",
     "placeholders": {
@@ -25,27 +25,27 @@
       }
     }
   },
-  "errorMsgSaveFileFailed": {
+  "ERROR_MSG_SAVE_FILE_FAILED": {
     "message": "Kan ikke lagre filen",
     "description": "Error message shown when saving/adding a image or video to the file system failed."
   },
-  "errorMsgTakePhotoFailed": {
+  "ERROR_MSG_TAKE_PHOTO_FAILED": {
     "message": "Kan ikke ta bilde",
     "description": "Error message shown when failing to take photo."
   },
-  "errorMsgRecordStartFailed": {
+  "ERROR_MSG_RECORD_START_FAILED": {
     "message": "Kan ikke starte opptak",
     "description": "Error message shown when failing to start recording video."
   },
-  "errorMsgEmptyRecording": {
+  "ERROR_MSG_EMPTY_RECORDING": {
     "message": "Ingenting er spilt inn",
     "description": "Error message shown when no data is recorded for a recording and it won't be added to the gallery."
   },
-  "statusMsgRecordingStopped": {
+  "STATUS_MSG_RECORDING_STOPPED": {
     "message": "Opptaket er stoppet",
     "description": "Status message for spoken feedback when video recording has been stopped."
   },
-  "statusMsgCameraSwitched": {
+  "STATUS_MSG_CAMERA_SWITCHED": {
     "message": "$camera$ er aktivt",
     "description": "Status message for spoken feedback when switching over to another camera.",
     "placeholders": {
@@ -55,131 +55,131 @@
       }
     }
   },
-  "galleryButton": {
+  "GALLERY_BUTTON": {
     "message": "Gå til galleriet",
     "description": "Label for the gallery button."
   },
-  "deleteButton": {
+  "DELETE_BUTTON": {
     "message": "Slett",
     "description": "Label for the delete button."
   },
-  "exportButton": {
+  "EXPORT_BUTTON": {
     "message": "Eksportér til disk",
     "description": "Label for the exporting button."
   },
-  "printButton": {
+  "PRINT_BUTTON": {
     "message": "Skriv ut",
     "description": "Label for the printing button."
   },
-  "backButton": {
+  "BACK_BUTTON": {
     "message": "Gå tilbake",
     "description": "Label for the back button."
   },
-  "galleryImages": {
+  "GALLERY_IMAGES": {
     "message": "Galleribilder",
     "description": "Text to speech label for the gallery list."
   },
-  "settingsButton": {
+  "SETTINGS_BUTTON": {
     "message": "Innstillinger",
     "description": "Label for the settings button."
   },
-  "gridTypeButton": {
+  "GRID_TYPE_BUTTON": {
     "message": "Rutenettype",
     "description": "Label for the button of grid-type options."
   },
-  "timerDurationButton": {
+  "TIMER_DURATION_BUTTON": {
     "message": "Nedtellervarighet",
     "description": "Label for the button of timer-duration options."
   },
-  "feedbackButton": {
+  "FEEDBACK_BUTTON": {
     "message": "Send tilbakemelding",
     "description": "Label for the feedback button."
   },
-  "helpButton": {
+  "HELP_BUTTON": {
     "message": "Hjelp",
     "description": "Label for the help button."
   },
-  "labelGrid3x3": {
+  "LABEL_GRID_3X3": {
     "message": "3 x 3",
     "description": "Label for for grid-type: 3x3."
   },
-  "ariaGrid3x3": {
+  "ARIA_GRID_3X3": {
     "message": "3 ganger 3",
     "description": "Label for spoken feedback to read out grid-type: 3x3."
   },
-  "labelGrid4x4": {
+  "LABEL_GRID_4X4": {
     "message": "4 x 4",
     "description": "Label for for grid-type: 4x4."
   },
-  "ariaGrid4x4": {
+  "ARIA_GRID_4X4": {
     "message": "4 ganger 4",
     "description": "Label for spoken feedback to read out grid-type: 4x4."
   },
-  "labelGridGolden": {
+  "LABEL_GRID_GOLDEN": {
     "message": "Det gylne snitt",
     "description": "Label for grid-type: golden ratio."
   },
-  "labelTimer3s": {
+  "LABEL_TIMER_3S": {
     "message": "3 sekunder",
     "description": "Label for timer-duration: 3 seconds."
   },
-  "labelTimer10s": {
+  "LABEL_TIMER_10S": {
     "message": "10 sekunder",
     "description": "Label for timer-duration: 10 seconds."
   },
-  "takePhotoButton": {
+  "TAKE_PHOTO_BUTTON": {
     "message": "Ta bilde",
     "description": "Label for the shutter button to take photo."
   },
-  "takePhotoCancelButton": {
+  "TAKE_PHOTO_CANCEL_BUTTON": {
     "message": "Slutt å ta bilde",
     "description": "Label for the shutter button to cancel countdown timer and stop taking photo."
   },
-  "recordVideoStartButton": {
+  "RECORD_VIDEO_START_BUTTON": {
     "message": "Start opptak",
     "description": "Label for the shutter button to start recording."
   },
-  "recordVideoStopButton": {
+  "RECORD_VIDEO_STOP_BUTTON": {
     "message": "Stopp opptak",
     "description": "Label for the shutter button to stop recording."
   },
-  "switchCameraButton": {
+  "SWITCH_CAMERA_BUTTON": {
     "message": "Bytt til neste kamera",
     "description": "Label for the button to switch to next connected camera. Eg. switching from front facing to back facing, or a camera connected via USB. The button is shown only when more than one camera is connected."
   },
-  "switchRecordVideoButton": {
+  "SWITCH_RECORD_VIDEO_BUTTON": {
     "message": "Bytt til video",
     "description": "Label for the button to switch to record video mode."
   },
-  "switchTakePhotoButton": {
+  "SWITCH_TAKE_PHOTO_BUTTON": {
     "message": "Bytt til foto",
     "description": "Label for the button to switch to take photo mode."
   },
-  "toggleTimerButton": {
+  "TOGGLE_TIMER_BUTTON": {
     "message": "Nedtelling",
     "description": "Label for the checkbox to toggle the countdown timer."
   },
-  "toggleMirrorButton": {
+  "TOGGLE_MIRROR_BUTTON": {
     "message": "Speiling",
     "description": "Label for the checkbox to toggle the preview mirroring. Eg. if mirroring is toggled on, preview will be flipped horizontally."
   },
-  "toggleGridButton": {
+  "TOGGLE_GRID_BUTTON": {
     "message": "Rutenett",
     "description": "Label for the checkbox to toggle the grid shown on preview."
   },
-  "toggleMicButton": {
+  "TOGGLE_MIC_BUTTON": {
     "message": "Mikrofon",
     "description": "Label for the checkbox to toggle the microphone for recording video."
   },
-  "dialogOKButton": {
+  "DIALOG_OK_BUTTON": {
     "message": "OK",
     "description": "Label for the accepting button in the dialog."
   },
-  "dialogCancelButton": {
+  "DIALOG_CANCEL_BUTTON": {
     "message": "Avbryt",
     "description": "Label for the dismissing button in the dialog."
   },
-  "deleteConfirmationMsg": {
+  "DELETE_CONFIRMATION_MSG": {
     "message": "Vil du fjerne $file$?",
     "description": "Confirmation message before removing a selected item from the gallery. Expects a file name to be passed in.",
     "placeholders": {
@@ -189,7 +189,7 @@
       }
     }
   },
-  "deleteMultiConfirmationMsg": {
+  "DELETE_MULTI_CONFIRMATION_MSG": {
     "message": "Vil du fjerne $count$ elementer?",
     "description": "Confirmation message before removing multiple selected items from the gallery. Expects a file count to be passed in.",
     "placeholders": {
@@ -199,7 +199,7 @@
       }
     }
   },
-  "migratePicturesMsg": {
+  "MIGRATE_PICTURES_MSG": {
     "message": "Bilder og videoer som er tatt med kameraet, flyttes til mappen Nedlastinger. Du har tilgang til dem i Filer.\n\nApper med lagringstillatelser har tilgang til bildene og videoene dine.",
     "description": "Message shown before moving all photos and videos stored in the Camera App to the Downloads folder."
   }
diff --git a/chrome/browser/resources/chromeos/camera/src/_locales/pl/messages.json b/chrome/browser/resources/chromeos/camera/src/_locales/pl/messages.json
index 2e1e9a2..97e6fc9a 100644
--- a/chrome/browser/resources/chromeos/camera/src/_locales/pl/messages.json
+++ b/chrome/browser/resources/chromeos/camera/src/_locales/pl/messages.json
@@ -1,21 +1,21 @@
 {
-  "name": {
+  "NAME": {
     "message": "Aparat",
     "description": "Name of the Camera App."
   },
-  "description": {
+  "DESCRIPTION": {
     "message": "Aparatem możesz robić zdjęcia i nagrywać filmy.",
     "description": "Short description of the Camera App."
   },
-  "errorMsgFileSystemFailed": {
+  "ERROR_MSG_FILE_SYSTEM_FAILED": {
     "message": "Błędy systemu plików.",
     "description": "Error message shown when failing to read or write the file system."
   },
-  "errorMsgNoCamera": {
+  "ERROR_MSG_NO_CAMERA": {
     "message": "Kamera jest teraz niedostępna.\nSprawdź, czy jest prawidłowo podłączona.",
     "description": "Error message shown when it was impossible to connect to the camera due to unavailability."
   },
-  "errorMsgGalleryExportFailed": {
+  "ERROR_MSG_GALLERY_EXPORT_FAILED": {
     "message": "Nie udało się wyeksportować pliku $file$",
     "description": "Error message shown when exporting to an external directory failed. Expects a file name to be passed in.",
     "placeholders": {
@@ -25,27 +25,27 @@
       }
     }
   },
-  "errorMsgSaveFileFailed": {
+  "ERROR_MSG_SAVE_FILE_FAILED": {
     "message": "Nie udało się zapisać pliku",
     "description": "Error message shown when saving/adding a image or video to the file system failed."
   },
-  "errorMsgTakePhotoFailed": {
+  "ERROR_MSG_TAKE_PHOTO_FAILED": {
     "message": "Nie udało się zrobić zdjęcia",
     "description": "Error message shown when failing to take photo."
   },
-  "errorMsgRecordStartFailed": {
+  "ERROR_MSG_RECORD_START_FAILED": {
     "message": "Nie udało się rozpocząć nagrywania",
     "description": "Error message shown when failing to start recording video."
   },
-  "errorMsgEmptyRecording": {
+  "ERROR_MSG_EMPTY_RECORDING": {
     "message": "Nic nie zostało nagrane",
     "description": "Error message shown when no data is recorded for a recording and it won't be added to the gallery."
   },
-  "statusMsgRecordingStopped": {
+  "STATUS_MSG_RECORDING_STOPPED": {
     "message": "Nagrywanie zatrzymane",
     "description": "Status message for spoken feedback when video recording has been stopped."
   },
-  "statusMsgCameraSwitched": {
+  "STATUS_MSG_CAMERA_SWITCHED": {
     "message": "Aktywna kamera: $camera$",
     "description": "Status message for spoken feedback when switching over to another camera.",
     "placeholders": {
@@ -55,131 +55,131 @@
       }
     }
   },
-  "galleryButton": {
+  "GALLERY_BUTTON": {
     "message": "Otwórz galerię",
     "description": "Label for the gallery button."
   },
-  "deleteButton": {
+  "DELETE_BUTTON": {
     "message": "Usuń",
     "description": "Label for the delete button."
   },
-  "exportButton": {
+  "EXPORT_BUTTON": {
     "message": "Eksportuj na dysk",
     "description": "Label for the exporting button."
   },
-  "printButton": {
+  "PRINT_BUTTON": {
     "message": "Drukuj",
     "description": "Label for the printing button."
   },
-  "backButton": {
+  "BACK_BUTTON": {
     "message": "Wróć",
     "description": "Label for the back button."
   },
-  "galleryImages": {
+  "GALLERY_IMAGES": {
     "message": "Zdjęcia z galerii",
     "description": "Text to speech label for the gallery list."
   },
-  "settingsButton": {
+  "SETTINGS_BUTTON": {
     "message": "Ustawienia",
     "description": "Label for the settings button."
   },
-  "gridTypeButton": {
+  "GRID_TYPE_BUTTON": {
     "message": "Typ siatki",
     "description": "Label for the button of grid-type options."
   },
-  "timerDurationButton": {
+  "TIMER_DURATION_BUTTON": {
     "message": "Czas samowyzwalacza",
     "description": "Label for the button of timer-duration options."
   },
-  "feedbackButton": {
+  "FEEDBACK_BUTTON": {
     "message": "Prześlij opinię",
     "description": "Label for the feedback button."
   },
-  "helpButton": {
+  "HELP_BUTTON": {
     "message": "Pomoc",
     "description": "Label for the help button."
   },
-  "labelGrid3x3": {
+  "LABEL_GRID_3X3": {
     "message": "3 x 3",
     "description": "Label for for grid-type: 3x3."
   },
-  "ariaGrid3x3": {
+  "ARIA_GRID_3X3": {
     "message": "3 na 3",
     "description": "Label for spoken feedback to read out grid-type: 3x3."
   },
-  "labelGrid4x4": {
+  "LABEL_GRID_4X4": {
     "message": "4 x 4",
     "description": "Label for for grid-type: 4x4."
   },
-  "ariaGrid4x4": {
+  "ARIA_GRID_4X4": {
     "message": "4 na 4",
     "description": "Label for spoken feedback to read out grid-type: 4x4."
   },
-  "labelGridGolden": {
+  "LABEL_GRID_GOLDEN": {
     "message": "Złote proporcje",
     "description": "Label for grid-type: golden ratio."
   },
-  "labelTimer3s": {
+  "LABEL_TIMER_3S": {
     "message": "3 sekundy",
     "description": "Label for timer-duration: 3 seconds."
   },
-  "labelTimer10s": {
+  "LABEL_TIMER_10S": {
     "message": "10 sekund",
     "description": "Label for timer-duration: 10 seconds."
   },
-  "takePhotoButton": {
+  "TAKE_PHOTO_BUTTON": {
     "message": "Zrób zdjęcie",
     "description": "Label for the shutter button to take photo."
   },
-  "takePhotoCancelButton": {
+  "TAKE_PHOTO_CANCEL_BUTTON": {
     "message": "Nie rób zdjęcia",
     "description": "Label for the shutter button to cancel countdown timer and stop taking photo."
   },
-  "recordVideoStartButton": {
+  "RECORD_VIDEO_START_BUTTON": {
     "message": "Rozpocznij nagrywanie",
     "description": "Label for the shutter button to start recording."
   },
-  "recordVideoStopButton": {
+  "RECORD_VIDEO_STOP_BUTTON": {
     "message": "Zatrzymaj nagrywanie",
     "description": "Label for the shutter button to stop recording."
   },
-  "switchCameraButton": {
+  "SWITCH_CAMERA_BUTTON": {
     "message": "Przełącz na następną kamerę",
     "description": "Label for the button to switch to next connected camera. Eg. switching from front facing to back facing, or a camera connected via USB. The button is shown only when more than one camera is connected."
   },
-  "switchRecordVideoButton": {
+  "SWITCH_RECORD_VIDEO_BUTTON": {
     "message": "Przełącz, by nagrać film",
     "description": "Label for the button to switch to record video mode."
   },
-  "switchTakePhotoButton": {
+  "SWITCH_TAKE_PHOTO_BUTTON": {
     "message": "Przełącz, by zrobić zdjęcie",
     "description": "Label for the button to switch to take photo mode."
   },
-  "toggleTimerButton": {
+  "TOGGLE_TIMER_BUTTON": {
     "message": "Samowyzwalacz",
     "description": "Label for the checkbox to toggle the countdown timer."
   },
-  "toggleMirrorButton": {
+  "TOGGLE_MIRROR_BUTTON": {
     "message": "Odbicie lustrzane",
     "description": "Label for the checkbox to toggle the preview mirroring. Eg. if mirroring is toggled on, preview will be flipped horizontally."
   },
-  "toggleGridButton": {
+  "TOGGLE_GRID_BUTTON": {
     "message": "Siatka",
     "description": "Label for the checkbox to toggle the grid shown on preview."
   },
-  "toggleMicButton": {
+  "TOGGLE_MIC_BUTTON": {
     "message": "Mikrofon",
     "description": "Label for the checkbox to toggle the microphone for recording video."
   },
-  "dialogOKButton": {
+  "DIALOG_OK_BUTTON": {
     "message": "OK",
     "description": "Label for the accepting button in the dialog."
   },
-  "dialogCancelButton": {
+  "DIALOG_CANCEL_BUTTON": {
     "message": "Anuluj",
     "description": "Label for the dismissing button in the dialog."
   },
-  "deleteConfirmationMsg": {
+  "DELETE_CONFIRMATION_MSG": {
     "message": "Czy na pewno chcesz usunąć plik $file$?",
     "description": "Confirmation message before removing a selected item from the gallery. Expects a file name to be passed in.",
     "placeholders": {
@@ -189,7 +189,7 @@
       }
     }
   },
-  "deleteMultiConfirmationMsg": {
+  "DELETE_MULTI_CONFIRMATION_MSG": {
     "message": "Czy na pewno chcesz usunąć te elementy ($count$)?",
     "description": "Confirmation message before removing multiple selected items from the gallery. Expects a file count to be passed in.",
     "placeholders": {
@@ -199,7 +199,7 @@
       }
     }
   },
-  "migratePicturesMsg": {
+  "MIGRATE_PICTURES_MSG": {
     "message": "Zdjęcia i filmy pochodzące z aparatu zostaną przeniesione do folderu Pobrane pliki. Będziesz mieć do nich dostęp w aplikacji Pliki.\n\nZ Twoich zdjęć i filmów będą mogły korzystać aplikacje z uprawnieniami dostępu do pamięci.",
     "description": "Message shown before moving all photos and videos stored in the Camera App to the Downloads folder."
   }
diff --git a/chrome/browser/resources/chromeos/camera/src/_locales/pt_BR/messages.json b/chrome/browser/resources/chromeos/camera/src/_locales/pt_BR/messages.json
index 9d8cd63..3a2e4d8 100644
--- a/chrome/browser/resources/chromeos/camera/src/_locales/pt_BR/messages.json
+++ b/chrome/browser/resources/chromeos/camera/src/_locales/pt_BR/messages.json
@@ -1,21 +1,21 @@
 {
-  "name": {
+  "NAME": {
     "message": "Câmera",
     "description": "Name of the Camera App."
   },
-  "description": {
+  "DESCRIPTION": {
     "message": "Tire fotos e grave vídeos com sua câmera.",
     "description": "Short description of the Camera App."
   },
-  "errorMsgFileSystemFailed": {
+  "ERROR_MSG_FILE_SYSTEM_FAILED": {
     "message": "Erros no sistema de arquivos.",
     "description": "Error message shown when failing to read or write the file system."
   },
-  "errorMsgNoCamera": {
+  "ERROR_MSG_NO_CAMERA": {
     "message": "Sua câmera está indisponível no momento.\nVerifique se a câmera está conectada corretamente.",
     "description": "Error message shown when it was impossible to connect to the camera due to unavailability."
   },
-  "errorMsgGalleryExportFailed": {
+  "ERROR_MSG_GALLERY_EXPORT_FAILED": {
     "message": "Não foi possível exportar $file$",
     "description": "Error message shown when exporting to an external directory failed. Expects a file name to be passed in.",
     "placeholders": {
@@ -25,27 +25,27 @@
       }
     }
   },
-  "errorMsgSaveFileFailed": {
+  "ERROR_MSG_SAVE_FILE_FAILED": {
     "message": "Não foi possível salvar o arquivo",
     "description": "Error message shown when saving/adding a image or video to the file system failed."
   },
-  "errorMsgTakePhotoFailed": {
+  "ERROR_MSG_TAKE_PHOTO_FAILED": {
     "message": "Não foi possível tirar a foto",
     "description": "Error message shown when failing to take photo."
   },
-  "errorMsgRecordStartFailed": {
+  "ERROR_MSG_RECORD_START_FAILED": {
     "message": "Não foi possível começar a gravação",
     "description": "Error message shown when failing to start recording video."
   },
-  "errorMsgEmptyRecording": {
+  "ERROR_MSG_EMPTY_RECORDING": {
     "message": "Nenhum dado gravado",
     "description": "Error message shown when no data is recorded for a recording and it won't be added to the gallery."
   },
-  "statusMsgRecordingStopped": {
+  "STATUS_MSG_RECORDING_STOPPED": {
     "message": "A gravação foi interrompida",
     "description": "Status message for spoken feedback when video recording has been stopped."
   },
-  "statusMsgCameraSwitched": {
+  "STATUS_MSG_CAMERA_SWITCHED": {
     "message": "$camera$ ativa",
     "description": "Status message for spoken feedback when switching over to another camera.",
     "placeholders": {
@@ -55,131 +55,131 @@
       }
     }
   },
-  "galleryButton": {
+  "GALLERY_BUTTON": {
     "message": "Ir para a galeria",
     "description": "Label for the gallery button."
   },
-  "deleteButton": {
+  "DELETE_BUTTON": {
     "message": "Excluir",
     "description": "Label for the delete button."
   },
-  "exportButton": {
+  "EXPORT_BUTTON": {
     "message": "Exportar para o disco",
     "description": "Label for the exporting button."
   },
-  "printButton": {
+  "PRINT_BUTTON": {
     "message": "Imprimir",
     "description": "Label for the printing button."
   },
-  "backButton": {
+  "BACK_BUTTON": {
     "message": "Voltar",
     "description": "Label for the back button."
   },
-  "galleryImages": {
+  "GALLERY_IMAGES": {
     "message": "Imagens da galeria",
     "description": "Text to speech label for the gallery list."
   },
-  "settingsButton": {
+  "SETTINGS_BUTTON": {
     "message": "Configurações",
     "description": "Label for the settings button."
   },
-  "gridTypeButton": {
+  "GRID_TYPE_BUTTON": {
     "message": "Tipo de grade",
     "description": "Label for the button of grid-type options."
   },
-  "timerDurationButton": {
+  "TIMER_DURATION_BUTTON": {
     "message": "Duração do timer",
     "description": "Label for the button of timer-duration options."
   },
-  "feedbackButton": {
+  "FEEDBACK_BUTTON": {
     "message": "Enviar feedback",
     "description": "Label for the feedback button."
   },
-  "helpButton": {
+  "HELP_BUTTON": {
     "message": "Ajuda",
     "description": "Label for the help button."
   },
-  "labelGrid3x3": {
+  "LABEL_GRID_3X3": {
     "message": "3 x 3",
     "description": "Label for for grid-type: 3x3."
   },
-  "ariaGrid3x3": {
+  "ARIA_GRID_3X3": {
     "message": "3 por 3",
     "description": "Label for spoken feedback to read out grid-type: 3x3."
   },
-  "labelGrid4x4": {
+  "LABEL_GRID_4X4": {
     "message": "4 x 4",
     "description": "Label for for grid-type: 4x4."
   },
-  "ariaGrid4x4": {
+  "ARIA_GRID_4X4": {
     "message": "4 por 4",
     "description": "Label for spoken feedback to read out grid-type: 4x4."
   },
-  "labelGridGolden": {
+  "LABEL_GRID_GOLDEN": {
     "message": "Proporção de ouro",
     "description": "Label for grid-type: golden ratio."
   },
-  "labelTimer3s": {
+  "LABEL_TIMER_3S": {
     "message": "3 segundos",
     "description": "Label for timer-duration: 3 seconds."
   },
-  "labelTimer10s": {
+  "LABEL_TIMER_10S": {
     "message": "10 segundos",
     "description": "Label for timer-duration: 10 seconds."
   },
-  "takePhotoButton": {
+  "TAKE_PHOTO_BUTTON": {
     "message": "Tirar foto",
     "description": "Label for the shutter button to take photo."
   },
-  "takePhotoCancelButton": {
+  "TAKE_PHOTO_CANCEL_BUTTON": {
     "message": "Parar de tirar foto",
     "description": "Label for the shutter button to cancel countdown timer and stop taking photo."
   },
-  "recordVideoStartButton": {
+  "RECORD_VIDEO_START_BUTTON": {
     "message": "Começar a gravar",
     "description": "Label for the shutter button to start recording."
   },
-  "recordVideoStopButton": {
+  "RECORD_VIDEO_STOP_BUTTON": {
     "message": "Interromper gravação",
     "description": "Label for the shutter button to stop recording."
   },
-  "switchCameraButton": {
+  "SWITCH_CAMERA_BUTTON": {
     "message": "Alternar para a próxima câmera",
     "description": "Label for the button to switch to next connected camera. Eg. switching from front facing to back facing, or a camera connected via USB. The button is shown only when more than one camera is connected."
   },
-  "switchRecordVideoButton": {
+  "SWITCH_RECORD_VIDEO_BUTTON": {
     "message": "Alternar para gravar vídeo",
     "description": "Label for the button to switch to record video mode."
   },
-  "switchTakePhotoButton": {
+  "SWITCH_TAKE_PHOTO_BUTTON": {
     "message": "Alternar para tirar foto",
     "description": "Label for the button to switch to take photo mode."
   },
-  "toggleTimerButton": {
+  "TOGGLE_TIMER_BUTTON": {
     "message": "Timer",
     "description": "Label for the checkbox to toggle the countdown timer."
   },
-  "toggleMirrorButton": {
+  "TOGGLE_MIRROR_BUTTON": {
     "message": "Espelhamento",
     "description": "Label for the checkbox to toggle the preview mirroring. Eg. if mirroring is toggled on, preview will be flipped horizontally."
   },
-  "toggleGridButton": {
+  "TOGGLE_GRID_BUTTON": {
     "message": "Grade",
     "description": "Label for the checkbox to toggle the grid shown on preview."
   },
-  "toggleMicButton": {
+  "TOGGLE_MIC_BUTTON": {
     "message": "Microfone",
     "description": "Label for the checkbox to toggle the microphone for recording video."
   },
-  "dialogOKButton": {
+  "DIALOG_OK_BUTTON": {
     "message": "OK",
     "description": "Label for the accepting button in the dialog."
   },
-  "dialogCancelButton": {
+  "DIALOG_CANCEL_BUTTON": {
     "message": "Cancelar",
     "description": "Label for the dismissing button in the dialog."
   },
-  "deleteConfirmationMsg": {
+  "DELETE_CONFIRMATION_MSG": {
     "message": "Tem certeza de que quer remover o arquivo $file$?",
     "description": "Confirmation message before removing a selected item from the gallery. Expects a file name to be passed in.",
     "placeholders": {
@@ -189,7 +189,7 @@
       }
     }
   },
-  "deleteMultiConfirmationMsg": {
+  "DELETE_MULTI_CONFIRMATION_MSG": {
     "message": "Tem certeza de que quer remover $count$ itens?",
     "description": "Confirmation message before removing multiple selected items from the gallery. Expects a file count to be passed in.",
     "placeholders": {
@@ -199,7 +199,7 @@
       }
     }
   },
-  "migratePicturesMsg": {
+  "MIGRATE_PICTURES_MSG": {
     "message": "As fotos e os vídeos capturados com a câmera serão movidos para a pasta \"Downloads\". Você pode acessá-los no app Arquivos.\n\nOs apps com permissões de armazenamento terão acesso às suas fotos e aos seus vídeos.",
     "description": "Message shown before moving all photos and videos stored in the Camera App to the Downloads folder."
   }
diff --git a/chrome/browser/resources/chromeos/camera/src/_locales/pt_PT/messages.json b/chrome/browser/resources/chromeos/camera/src/_locales/pt_PT/messages.json
index e857a8a3..61bf7a6e 100644
--- a/chrome/browser/resources/chromeos/camera/src/_locales/pt_PT/messages.json
+++ b/chrome/browser/resources/chromeos/camera/src/_locales/pt_PT/messages.json
@@ -1,21 +1,21 @@
 {
-  "name": {
+  "NAME": {
     "message": "Câmara",
     "description": "Name of the Camera App."
   },
-  "description": {
+  "DESCRIPTION": {
     "message": "Tire fotos e grave vídeos com a sua câmara.",
     "description": "Short description of the Camera App."
   },
-  "errorMsgFileSystemFailed": {
+  "ERROR_MSG_FILE_SYSTEM_FAILED": {
     "message": "Erros do sistema de ficheiros.",
     "description": "Error message shown when failing to read or write the file system."
   },
-  "errorMsgNoCamera": {
+  "ERROR_MSG_NO_CAMERA": {
     "message": "De momento, a câmara não está disponível.\nVerifique se a câmara está ligada corretamente.",
     "description": "Error message shown when it was impossible to connect to the camera due to unavailability."
   },
-  "errorMsgGalleryExportFailed": {
+  "ERROR_MSG_GALLERY_EXPORT_FAILED": {
     "message": "Não foi possível exportar o ficheiro $file$.",
     "description": "Error message shown when exporting to an external directory failed. Expects a file name to be passed in.",
     "placeholders": {
@@ -25,27 +25,27 @@
       }
     }
   },
-  "errorMsgSaveFileFailed": {
+  "ERROR_MSG_SAVE_FILE_FAILED": {
     "message": "Não foi possível guardar o ficheiro.",
     "description": "Error message shown when saving/adding a image or video to the file system failed."
   },
-  "errorMsgTakePhotoFailed": {
+  "ERROR_MSG_TAKE_PHOTO_FAILED": {
     "message": "Não é possível tirar a foto.",
     "description": "Error message shown when failing to take photo."
   },
-  "errorMsgRecordStartFailed": {
+  "ERROR_MSG_RECORD_START_FAILED": {
     "message": "Não é possível iniciar a gravação.",
     "description": "Error message shown when failing to start recording video."
   },
-  "errorMsgEmptyRecording": {
+  "ERROR_MSG_EMPTY_RECORDING": {
     "message": "Nada foi gravado.",
     "description": "Error message shown when no data is recorded for a recording and it won't be added to the gallery."
   },
-  "statusMsgRecordingStopped": {
+  "STATUS_MSG_RECORDING_STOPPED": {
     "message": "Gravação interrompida",
     "description": "Status message for spoken feedback when video recording has been stopped."
   },
-  "statusMsgCameraSwitched": {
+  "STATUS_MSG_CAMERA_SWITCHED": {
     "message": "$camera$ ativa",
     "description": "Status message for spoken feedback when switching over to another camera.",
     "placeholders": {
@@ -55,131 +55,131 @@
       }
     }
   },
-  "galleryButton": {
+  "GALLERY_BUTTON": {
     "message": "Ir para a galeria",
     "description": "Label for the gallery button."
   },
-  "deleteButton": {
+  "DELETE_BUTTON": {
     "message": "Eliminar",
     "description": "Label for the delete button."
   },
-  "exportButton": {
+  "EXPORT_BUTTON": {
     "message": "Exportar para o disco",
     "description": "Label for the exporting button."
   },
-  "printButton": {
+  "PRINT_BUTTON": {
     "message": "Imprimir",
     "description": "Label for the printing button."
   },
-  "backButton": {
+  "BACK_BUTTON": {
     "message": "Voltar",
     "description": "Label for the back button."
   },
-  "galleryImages": {
+  "GALLERY_IMAGES": {
     "message": "Imagens da galeria",
     "description": "Text to speech label for the gallery list."
   },
-  "settingsButton": {
+  "SETTINGS_BUTTON": {
     "message": "Definições",
     "description": "Label for the settings button."
   },
-  "gridTypeButton": {
+  "GRID_TYPE_BUTTON": {
     "message": "Tipo de grelha",
     "description": "Label for the button of grid-type options."
   },
-  "timerDurationButton": {
+  "TIMER_DURATION_BUTTON": {
     "message": "Duração do temporizador",
     "description": "Label for the button of timer-duration options."
   },
-  "feedbackButton": {
+  "FEEDBACK_BUTTON": {
     "message": "Enviar comentários",
     "description": "Label for the feedback button."
   },
-  "helpButton": {
+  "HELP_BUTTON": {
     "message": "Ajuda",
     "description": "Label for the help button."
   },
-  "labelGrid3x3": {
+  "LABEL_GRID_3X3": {
     "message": "3 x 3",
     "description": "Label for for grid-type: 3x3."
   },
-  "ariaGrid3x3": {
+  "ARIA_GRID_3X3": {
     "message": "3 por 3",
     "description": "Label for spoken feedback to read out grid-type: 3x3."
   },
-  "labelGrid4x4": {
+  "LABEL_GRID_4X4": {
     "message": "4 x 4",
     "description": "Label for for grid-type: 4x4."
   },
-  "ariaGrid4x4": {
+  "ARIA_GRID_4X4": {
     "message": "4 por 4",
     "description": "Label for spoken feedback to read out grid-type: 4x4."
   },
-  "labelGridGolden": {
+  "LABEL_GRID_GOLDEN": {
     "message": "Número de Ouro",
     "description": "Label for grid-type: golden ratio."
   },
-  "labelTimer3s": {
+  "LABEL_TIMER_3S": {
     "message": "3 segundos",
     "description": "Label for timer-duration: 3 seconds."
   },
-  "labelTimer10s": {
+  "LABEL_TIMER_10S": {
     "message": "10 segundos",
     "description": "Label for timer-duration: 10 seconds."
   },
-  "takePhotoButton": {
+  "TAKE_PHOTO_BUTTON": {
     "message": "Tirar foto",
     "description": "Label for the shutter button to take photo."
   },
-  "takePhotoCancelButton": {
+  "TAKE_PHOTO_CANCEL_BUTTON": {
     "message": "Parar de tirar foto",
     "description": "Label for the shutter button to cancel countdown timer and stop taking photo."
   },
-  "recordVideoStartButton": {
+  "RECORD_VIDEO_START_BUTTON": {
     "message": "Começar a gravar",
     "description": "Label for the shutter button to start recording."
   },
-  "recordVideoStopButton": {
+  "RECORD_VIDEO_STOP_BUTTON": {
     "message": "Parar de gravar",
     "description": "Label for the shutter button to stop recording."
   },
-  "switchCameraButton": {
+  "SWITCH_CAMERA_BUTTON": {
     "message": "Mudar para a câmara seguinte",
     "description": "Label for the button to switch to next connected camera. Eg. switching from front facing to back facing, or a camera connected via USB. The button is shown only when more than one camera is connected."
   },
-  "switchRecordVideoButton": {
+  "SWITCH_RECORD_VIDEO_BUTTON": {
     "message": "Mudar para gravar vídeo",
     "description": "Label for the button to switch to record video mode."
   },
-  "switchTakePhotoButton": {
+  "SWITCH_TAKE_PHOTO_BUTTON": {
     "message": "Mudar para tirar foto",
     "description": "Label for the button to switch to take photo mode."
   },
-  "toggleTimerButton": {
+  "TOGGLE_TIMER_BUTTON": {
     "message": "Temporizador",
     "description": "Label for the checkbox to toggle the countdown timer."
   },
-  "toggleMirrorButton": {
+  "TOGGLE_MIRROR_BUTTON": {
     "message": "Espelhamento",
     "description": "Label for the checkbox to toggle the preview mirroring. Eg. if mirroring is toggled on, preview will be flipped horizontally."
   },
-  "toggleGridButton": {
+  "TOGGLE_GRID_BUTTON": {
     "message": "Grelha",
     "description": "Label for the checkbox to toggle the grid shown on preview."
   },
-  "toggleMicButton": {
+  "TOGGLE_MIC_BUTTON": {
     "message": "Microfone",
     "description": "Label for the checkbox to toggle the microphone for recording video."
   },
-  "dialogOKButton": {
+  "DIALOG_OK_BUTTON": {
     "message": "OK",
     "description": "Label for the accepting button in the dialog."
   },
-  "dialogCancelButton": {
+  "DIALOG_CANCEL_BUTTON": {
     "message": "Cancelar",
     "description": "Label for the dismissing button in the dialog."
   },
-  "deleteConfirmationMsg": {
+  "DELETE_CONFIRMATION_MSG": {
     "message": "Pretende realmente remover o ficheiro $file$?",
     "description": "Confirmation message before removing a selected item from the gallery. Expects a file name to be passed in.",
     "placeholders": {
@@ -189,7 +189,7 @@
       }
     }
   },
-  "deleteMultiConfirmationMsg": {
+  "DELETE_MULTI_CONFIRMATION_MSG": {
     "message": "Pretende realmente remover $count$ itens?",
     "description": "Confirmation message before removing multiple selected items from the gallery. Expects a file count to be passed in.",
     "placeholders": {
@@ -199,7 +199,7 @@
       }
     }
   },
-  "migratePicturesMsg": {
+  "MIGRATE_PICTURES_MSG": {
     "message": "As fotos e os vídeos registados com a câmara serão transferidos para a pasta Transferências. Pode aceder aos mesmos em Ficheiros.\n\nAs aplicações com autorizações de armazenamento terão acesso aos seus vídeos e fotos.",
     "description": "Message shown before moving all photos and videos stored in the Camera App to the Downloads folder."
   }
diff --git a/chrome/browser/resources/chromeos/camera/src/_locales/ro/messages.json b/chrome/browser/resources/chromeos/camera/src/_locales/ro/messages.json
index 9caa1a3..a954f1a 100644
--- a/chrome/browser/resources/chromeos/camera/src/_locales/ro/messages.json
+++ b/chrome/browser/resources/chromeos/camera/src/_locales/ro/messages.json
@@ -1,21 +1,21 @@
 {
-  "name": {
+  "NAME": {
     "message": "Cameră foto",
     "description": "Name of the Camera App."
   },
-  "description": {
+  "DESCRIPTION": {
     "message": "Fotografiați și înregistrați videoclipuri cu camera foto.",
     "description": "Short description of the Camera App."
   },
-  "errorMsgFileSystemFailed": {
+  "ERROR_MSG_FILE_SYSTEM_FAILED": {
     "message": "Erori în sistemul de fișiere.",
     "description": "Error message shown when failing to read or write the file system."
   },
-  "errorMsgNoCamera": {
+  "ERROR_MSG_NO_CAMERA": {
     "message": "Camera dvs. foto este indisponibilă momentan.\nVerificați dacă este conectată corespunzător.",
     "description": "Error message shown when it was impossible to connect to the camera due to unavailability."
   },
-  "errorMsgGalleryExportFailed": {
+  "ERROR_MSG_GALLERY_EXPORT_FAILED": {
     "message": "Nu se poate exporta $file$.",
     "description": "Error message shown when exporting to an external directory failed. Expects a file name to be passed in.",
     "placeholders": {
@@ -25,27 +25,27 @@
       }
     }
   },
-  "errorMsgSaveFileFailed": {
+  "ERROR_MSG_SAVE_FILE_FAILED": {
     "message": "Fișierul nu poate fi salvat.",
     "description": "Error message shown when saving/adding a image or video to the file system failed."
   },
-  "errorMsgTakePhotoFailed": {
+  "ERROR_MSG_TAKE_PHOTO_FAILED": {
     "message": "Nu se pot face fotografii.",
     "description": "Error message shown when failing to take photo."
   },
-  "errorMsgRecordStartFailed": {
+  "ERROR_MSG_RECORD_START_FAILED": {
     "message": "Nu se poate porni înregistrarea.",
     "description": "Error message shown when failing to start recording video."
   },
-  "errorMsgEmptyRecording": {
+  "ERROR_MSG_EMPTY_RECORDING": {
     "message": "Nu s-a înregistrat nimic.",
     "description": "Error message shown when no data is recorded for a recording and it won't be added to the gallery."
   },
-  "statusMsgRecordingStopped": {
+  "STATUS_MSG_RECORDING_STOPPED": {
     "message": "Înregistrarea s-a oprit.",
     "description": "Status message for spoken feedback when video recording has been stopped."
   },
-  "statusMsgCameraSwitched": {
+  "STATUS_MSG_CAMERA_SWITCHED": {
     "message": "$camera$ activă",
     "description": "Status message for spoken feedback when switching over to another camera.",
     "placeholders": {
@@ -55,131 +55,131 @@
       }
     }
   },
-  "galleryButton": {
+  "GALLERY_BUTTON": {
     "message": "Accesați galeria",
     "description": "Label for the gallery button."
   },
-  "deleteButton": {
+  "DELETE_BUTTON": {
     "message": "Ștergeți",
     "description": "Label for the delete button."
   },
-  "exportButton": {
+  "EXPORT_BUTTON": {
     "message": "Exportați pe disc",
     "description": "Label for the exporting button."
   },
-  "printButton": {
+  "PRINT_BUTTON": {
     "message": "Printați",
     "description": "Label for the printing button."
   },
-  "backButton": {
+  "BACK_BUTTON": {
     "message": "Înapoi",
     "description": "Label for the back button."
   },
-  "galleryImages": {
+  "GALLERY_IMAGES": {
     "message": "Imagini din galerie",
     "description": "Text to speech label for the gallery list."
   },
-  "settingsButton": {
+  "SETTINGS_BUTTON": {
     "message": "Setări",
     "description": "Label for the settings button."
   },
-  "gridTypeButton": {
+  "GRID_TYPE_BUTTON": {
     "message": "Tipul grilei",
     "description": "Label for the button of grid-type options."
   },
-  "timerDurationButton": {
+  "TIMER_DURATION_BUTTON": {
     "message": "Durata temporizatorului",
     "description": "Label for the button of timer-duration options."
   },
-  "feedbackButton": {
+  "FEEDBACK_BUTTON": {
     "message": "Trimiteți feedback",
     "description": "Label for the feedback button."
   },
-  "helpButton": {
+  "HELP_BUTTON": {
     "message": "Ajutor",
     "description": "Label for the help button."
   },
-  "labelGrid3x3": {
+  "LABEL_GRID_3X3": {
     "message": "3 x 3",
     "description": "Label for for grid-type: 3x3."
   },
-  "ariaGrid3x3": {
+  "ARIA_GRID_3X3": {
     "message": "3 x 3",
     "description": "Label for spoken feedback to read out grid-type: 3x3."
   },
-  "labelGrid4x4": {
+  "LABEL_GRID_4X4": {
     "message": "4 x 4",
     "description": "Label for for grid-type: 4x4."
   },
-  "ariaGrid4x4": {
+  "ARIA_GRID_4X4": {
     "message": "4 pe 4",
     "description": "Label for spoken feedback to read out grid-type: 4x4."
   },
-  "labelGridGolden": {
+  "LABEL_GRID_GOLDEN": {
     "message": "Raportul de aur",
     "description": "Label for grid-type: golden ratio."
   },
-  "labelTimer3s": {
+  "LABEL_TIMER_3S": {
     "message": "3 secunde",
     "description": "Label for timer-duration: 3 seconds."
   },
-  "labelTimer10s": {
+  "LABEL_TIMER_10S": {
     "message": "10 secunde",
     "description": "Label for timer-duration: 10 seconds."
   },
-  "takePhotoButton": {
+  "TAKE_PHOTO_BUTTON": {
     "message": "Fotografiați",
     "description": "Label for the shutter button to take photo."
   },
-  "takePhotoCancelButton": {
+  "TAKE_PHOTO_CANCEL_BUTTON": {
     "message": "Nu mai fotografiați",
     "description": "Label for the shutter button to cancel countdown timer and stop taking photo."
   },
-  "recordVideoStartButton": {
+  "RECORD_VIDEO_START_BUTTON": {
     "message": "Porniți înregistrarea",
     "description": "Label for the shutter button to start recording."
   },
-  "recordVideoStopButton": {
+  "RECORD_VIDEO_STOP_BUTTON": {
     "message": "Opriți înregistrarea",
     "description": "Label for the shutter button to stop recording."
   },
-  "switchCameraButton": {
+  "SWITCH_CAMERA_BUTTON": {
     "message": "Comutați la următoarea cameră foto",
     "description": "Label for the button to switch to next connected camera. Eg. switching from front facing to back facing, or a camera connected via USB. The button is shown only when more than one camera is connected."
   },
-  "switchRecordVideoButton": {
+  "SWITCH_RECORD_VIDEO_BUTTON": {
     "message": "Comutați pentru a înregistra un videoclip",
     "description": "Label for the button to switch to record video mode."
   },
-  "switchTakePhotoButton": {
+  "SWITCH_TAKE_PHOTO_BUTTON": {
     "message": "Comutați pentru a fotografia",
     "description": "Label for the button to switch to take photo mode."
   },
-  "toggleTimerButton": {
+  "TOGGLE_TIMER_BUTTON": {
     "message": "Temporizator",
     "description": "Label for the checkbox to toggle the countdown timer."
   },
-  "toggleMirrorButton": {
+  "TOGGLE_MIRROR_BUTTON": {
     "message": "Oglindire",
     "description": "Label for the checkbox to toggle the preview mirroring. Eg. if mirroring is toggled on, preview will be flipped horizontally."
   },
-  "toggleGridButton": {
+  "TOGGLE_GRID_BUTTON": {
     "message": "Grilă",
     "description": "Label for the checkbox to toggle the grid shown on preview."
   },
-  "toggleMicButton": {
+  "TOGGLE_MIC_BUTTON": {
     "message": "Microfon",
     "description": "Label for the checkbox to toggle the microphone for recording video."
   },
-  "dialogOKButton": {
+  "DIALOG_OK_BUTTON": {
     "message": "OK",
     "description": "Label for the accepting button in the dialog."
   },
-  "dialogCancelButton": {
+  "DIALOG_CANCEL_BUTTON": {
     "message": "Anulați",
     "description": "Label for the dismissing button in the dialog."
   },
-  "deleteConfirmationMsg": {
+  "DELETE_CONFIRMATION_MSG": {
     "message": "Sigur doriți să eliminați $file$?",
     "description": "Confirmation message before removing a selected item from the gallery. Expects a file name to be passed in.",
     "placeholders": {
@@ -189,7 +189,7 @@
       }
     }
   },
-  "deleteMultiConfirmationMsg": {
+  "DELETE_MULTI_CONFIRMATION_MSG": {
     "message": "Sigur doriți să eliminați $count$ elemente?",
     "description": "Confirmation message before removing multiple selected items from the gallery. Expects a file count to be passed in.",
     "placeholders": {
@@ -199,7 +199,7 @@
       }
     }
   },
-  "migratePicturesMsg": {
+  "MIGRATE_PICTURES_MSG": {
     "message": "Fotografiile și videoclipurile făcute cu camera foto vor fi mutate în dosarul Descărcări. Le puteți accesa în Fișiere.\n\nAplicațiile cu permisiuni de stocare vor avea acces la fotografiile și videoclipurile dvs.",
     "description": "Message shown before moving all photos and videos stored in the Camera App to the Downloads folder."
   }
diff --git a/chrome/browser/resources/chromeos/camera/src/_locales/ru/messages.json b/chrome/browser/resources/chromeos/camera/src/_locales/ru/messages.json
index d40c2c6..f73711b1 100644
--- a/chrome/browser/resources/chromeos/camera/src/_locales/ru/messages.json
+++ b/chrome/browser/resources/chromeos/camera/src/_locales/ru/messages.json
@@ -1,21 +1,21 @@
 {
-  "name": {
+  "NAME": {
     "message": "Камера",
     "description": "Name of the Camera App."
   },
-  "description": {
+  "DESCRIPTION": {
     "message": "Съемка фото и видео при помощи камеры.",
     "description": "Short description of the Camera App."
   },
-  "errorMsgFileSystemFailed": {
+  "ERROR_MSG_FILE_SYSTEM_FAILED": {
     "message": "Ошибки файловой системы",
     "description": "Error message shown when failing to read or write the file system."
   },
-  "errorMsgNoCamera": {
+  "ERROR_MSG_NO_CAMERA": {
     "message": "Камера недоступна.\nПроверьте, правильно ли она подключена.",
     "description": "Error message shown when it was impossible to connect to the camera due to unavailability."
   },
-  "errorMsgGalleryExportFailed": {
+  "ERROR_MSG_GALLERY_EXPORT_FAILED": {
     "message": "Не удалось экспортировать файл $file$",
     "description": "Error message shown when exporting to an external directory failed. Expects a file name to be passed in.",
     "placeholders": {
@@ -25,27 +25,27 @@
       }
     }
   },
-  "errorMsgSaveFileFailed": {
+  "ERROR_MSG_SAVE_FILE_FAILED": {
     "message": "Не удалось сохранить файл",
     "description": "Error message shown when saving/adding a image or video to the file system failed."
   },
-  "errorMsgTakePhotoFailed": {
+  "ERROR_MSG_TAKE_PHOTO_FAILED": {
     "message": "Не удалось сделать снимок",
     "description": "Error message shown when failing to take photo."
   },
-  "errorMsgRecordStartFailed": {
+  "ERROR_MSG_RECORD_START_FAILED": {
     "message": "Не удалось начать запись",
     "description": "Error message shown when failing to start recording video."
   },
-  "errorMsgEmptyRecording": {
+  "ERROR_MSG_EMPTY_RECORDING": {
     "message": "Ничего не записано",
     "description": "Error message shown when no data is recorded for a recording and it won't be added to the gallery."
   },
-  "statusMsgRecordingStopped": {
+  "STATUS_MSG_RECORDING_STOPPED": {
     "message": "Запись прекращена",
     "description": "Status message for spoken feedback when video recording has been stopped."
   },
-  "statusMsgCameraSwitched": {
+  "STATUS_MSG_CAMERA_SWITCHED": {
     "message": "Выбрана $camera$",
     "description": "Status message for spoken feedback when switching over to another camera.",
     "placeholders": {
@@ -55,131 +55,131 @@
       }
     }
   },
-  "galleryButton": {
+  "GALLERY_BUTTON": {
     "message": "Перейти в галерею",
     "description": "Label for the gallery button."
   },
-  "deleteButton": {
+  "DELETE_BUTTON": {
     "message": "Удалить",
     "description": "Label for the delete button."
   },
-  "exportButton": {
+  "EXPORT_BUTTON": {
     "message": "Экспортировать на диск",
     "description": "Label for the exporting button."
   },
-  "printButton": {
+  "PRINT_BUTTON": {
     "message": "Печать",
     "description": "Label for the printing button."
   },
-  "backButton": {
+  "BACK_BUTTON": {
     "message": "Назад",
     "description": "Label for the back button."
   },
-  "galleryImages": {
+  "GALLERY_IMAGES": {
     "message": "Изображения в галерее",
     "description": "Text to speech label for the gallery list."
   },
-  "settingsButton": {
+  "SETTINGS_BUTTON": {
     "message": "Настройки",
     "description": "Label for the settings button."
   },
-  "gridTypeButton": {
+  "GRID_TYPE_BUTTON": {
     "message": "Тип сетки",
     "description": "Label for the button of grid-type options."
   },
-  "timerDurationButton": {
+  "TIMER_DURATION_BUTTON": {
     "message": "Длительность таймера",
     "description": "Label for the button of timer-duration options."
   },
-  "feedbackButton": {
+  "FEEDBACK_BUTTON": {
     "message": "Оставить отзыв",
     "description": "Label for the feedback button."
   },
-  "helpButton": {
+  "HELP_BUTTON": {
     "message": "Справка",
     "description": "Label for the help button."
   },
-  "labelGrid3x3": {
+  "LABEL_GRID_3X3": {
     "message": "3 x 3",
     "description": "Label for for grid-type: 3x3."
   },
-  "ariaGrid3x3": {
+  "ARIA_GRID_3X3": {
     "message": "3 на 3",
     "description": "Label for spoken feedback to read out grid-type: 3x3."
   },
-  "labelGrid4x4": {
+  "LABEL_GRID_4X4": {
     "message": "4 x 4",
     "description": "Label for for grid-type: 4x4."
   },
-  "ariaGrid4x4": {
+  "ARIA_GRID_4X4": {
     "message": "4 на 4",
     "description": "Label for spoken feedback to read out grid-type: 4x4."
   },
-  "labelGridGolden": {
+  "LABEL_GRID_GOLDEN": {
     "message": "Золотое сечение",
     "description": "Label for grid-type: golden ratio."
   },
-  "labelTimer3s": {
+  "LABEL_TIMER_3S": {
     "message": "3 секунды",
     "description": "Label for timer-duration: 3 seconds."
   },
-  "labelTimer10s": {
+  "LABEL_TIMER_10S": {
     "message": "10 секунд",
     "description": "Label for timer-duration: 10 seconds."
   },
-  "takePhotoButton": {
+  "TAKE_PHOTO_BUTTON": {
     "message": "Сделать снимок",
     "description": "Label for the shutter button to take photo."
   },
-  "takePhotoCancelButton": {
+  "TAKE_PHOTO_CANCEL_BUTTON": {
     "message": "Остановить съемку",
     "description": "Label for the shutter button to cancel countdown timer and stop taking photo."
   },
-  "recordVideoStartButton": {
+  "RECORD_VIDEO_START_BUTTON": {
     "message": "Начать запись",
     "description": "Label for the shutter button to start recording."
   },
-  "recordVideoStopButton": {
+  "RECORD_VIDEO_STOP_BUTTON": {
     "message": "Остановить запись",
     "description": "Label for the shutter button to stop recording."
   },
-  "switchCameraButton": {
+  "SWITCH_CAMERA_BUTTON": {
     "message": "Переключиться на следующую камеру",
     "description": "Label for the button to switch to next connected camera. Eg. switching from front facing to back facing, or a camera connected via USB. The button is shown only when more than one camera is connected."
   },
-  "switchRecordVideoButton": {
+  "SWITCH_RECORD_VIDEO_BUTTON": {
     "message": "Переключиться на видеосъемку",
     "description": "Label for the button to switch to record video mode."
   },
-  "switchTakePhotoButton": {
+  "SWITCH_TAKE_PHOTO_BUTTON": {
     "message": "Переключиться на фотосъемку",
     "description": "Label for the button to switch to take photo mode."
   },
-  "toggleTimerButton": {
+  "TOGGLE_TIMER_BUTTON": {
     "message": "Таймер",
     "description": "Label for the checkbox to toggle the countdown timer."
   },
-  "toggleMirrorButton": {
+  "TOGGLE_MIRROR_BUTTON": {
     "message": "Зеркалирование",
     "description": "Label for the checkbox to toggle the preview mirroring. Eg. if mirroring is toggled on, preview will be flipped horizontally."
   },
-  "toggleGridButton": {
+  "TOGGLE_GRID_BUTTON": {
     "message": "Сетка",
     "description": "Label for the checkbox to toggle the grid shown on preview."
   },
-  "toggleMicButton": {
+  "TOGGLE_MIC_BUTTON": {
     "message": "Микрофон",
     "description": "Label for the checkbox to toggle the microphone for recording video."
   },
-  "dialogOKButton": {
+  "DIALOG_OK_BUTTON": {
     "message": "ОК",
     "description": "Label for the accepting button in the dialog."
   },
-  "dialogCancelButton": {
+  "DIALOG_CANCEL_BUTTON": {
     "message": "Отмена",
     "description": "Label for the dismissing button in the dialog."
   },
-  "deleteConfirmationMsg": {
+  "DELETE_CONFIRMATION_MSG": {
     "message": "Удалить файл $file$?",
     "description": "Confirmation message before removing a selected item from the gallery. Expects a file name to be passed in.",
     "placeholders": {
@@ -189,7 +189,7 @@
       }
     }
   },
-  "deleteMultiConfirmationMsg": {
+  "DELETE_MULTI_CONFIRMATION_MSG": {
     "message": "Удалить файлы ($count$)?",
     "description": "Confirmation message before removing multiple selected items from the gallery. Expects a file count to be passed in.",
     "placeholders": {
@@ -199,7 +199,7 @@
       }
     }
   },
-  "migratePicturesMsg": {
+  "MIGRATE_PICTURES_MSG": {
     "message": "Фотографии и видео, полученные с камеры, будут перемещены в папку \"Загрузки\". Вы также сможете найти их в папке \"Файлы\".\n\nПриложения, у которых есть доступ к хранилищу, смогут работать с вашими фотографиями и видео.",
     "description": "Message shown before moving all photos and videos stored in the Camera App to the Downloads folder."
   }
diff --git a/chrome/browser/resources/chromeos/camera/src/_locales/sk/messages.json b/chrome/browser/resources/chromeos/camera/src/_locales/sk/messages.json
index cdf3ba23..3934bb5 100644
--- a/chrome/browser/resources/chromeos/camera/src/_locales/sk/messages.json
+++ b/chrome/browser/resources/chromeos/camera/src/_locales/sk/messages.json
@@ -1,21 +1,21 @@
 {
-  "name": {
+  "NAME": {
     "message": "Fotoaparát",
     "description": "Name of the Camera App."
   },
-  "description": {
+  "DESCRIPTION": {
     "message": "Foťte a nahrávajte videá pomocou fotoaparátu.",
     "description": "Short description of the Camera App."
   },
-  "errorMsgFileSystemFailed": {
+  "ERROR_MSG_FILE_SYSTEM_FAILED": {
     "message": "Chyby systému súborov.",
     "description": "Error message shown when failing to read or write the file system."
   },
-  "errorMsgNoCamera": {
+  "ERROR_MSG_NO_CAMERA": {
     "message": "Váš fotoaparát je momentálne nedostupný.\nSkontrolujte, či je fotoaparát správne pripojený.",
     "description": "Error message shown when it was impossible to connect to the camera due to unavailability."
   },
-  "errorMsgGalleryExportFailed": {
+  "ERROR_MSG_GALLERY_EXPORT_FAILED": {
     "message": "Súbor $file$ sa nepodarilo exportovať",
     "description": "Error message shown when exporting to an external directory failed. Expects a file name to be passed in.",
     "placeholders": {
@@ -25,27 +25,27 @@
       }
     }
   },
-  "errorMsgSaveFileFailed": {
+  "ERROR_MSG_SAVE_FILE_FAILED": {
     "message": "Súbor sa nepodarilo uložiť",
     "description": "Error message shown when saving/adding a image or video to the file system failed."
   },
-  "errorMsgTakePhotoFailed": {
+  "ERROR_MSG_TAKE_PHOTO_FAILED": {
     "message": "Fotku sa nepodarilo nasnímať",
     "description": "Error message shown when failing to take photo."
   },
-  "errorMsgRecordStartFailed": {
+  "ERROR_MSG_RECORD_START_FAILED": {
     "message": "Nahrávanie sa nepodarilo spustiť",
     "description": "Error message shown when failing to start recording video."
   },
-  "errorMsgEmptyRecording": {
+  "ERROR_MSG_EMPTY_RECORDING": {
     "message": "Nič sa nenahralo",
     "description": "Error message shown when no data is recorded for a recording and it won't be added to the gallery."
   },
-  "statusMsgRecordingStopped": {
+  "STATUS_MSG_RECORDING_STOPPED": {
     "message": "Nahrávanie bolo zastavené",
     "description": "Status message for spoken feedback when video recording has been stopped."
   },
-  "statusMsgCameraSwitched": {
+  "STATUS_MSG_CAMERA_SWITCHED": {
     "message": "Kamera $camera$ je aktívna",
     "description": "Status message for spoken feedback when switching over to another camera.",
     "placeholders": {
@@ -55,131 +55,131 @@
       }
     }
   },
-  "galleryButton": {
+  "GALLERY_BUTTON": {
     "message": "Prejsť do galérie",
     "description": "Label for the gallery button."
   },
-  "deleteButton": {
+  "DELETE_BUTTON": {
     "message": "Odstrániť",
     "description": "Label for the delete button."
   },
-  "exportButton": {
+  "EXPORT_BUTTON": {
     "message": "Exportovať na disk",
     "description": "Label for the exporting button."
   },
-  "printButton": {
+  "PRINT_BUTTON": {
     "message": "Tlačiť",
     "description": "Label for the printing button."
   },
-  "backButton": {
+  "BACK_BUTTON": {
     "message": "Späť",
     "description": "Label for the back button."
   },
-  "galleryImages": {
+  "GALLERY_IMAGES": {
     "message": "Obrázky galérie",
     "description": "Text to speech label for the gallery list."
   },
-  "settingsButton": {
+  "SETTINGS_BUTTON": {
     "message": "Nastavenia",
     "description": "Label for the settings button."
   },
-  "gridTypeButton": {
+  "GRID_TYPE_BUTTON": {
     "message": "Typ mriežky",
     "description": "Label for the button of grid-type options."
   },
-  "timerDurationButton": {
+  "TIMER_DURATION_BUTTON": {
     "message": "Trvanie časovača",
     "description": "Label for the button of timer-duration options."
   },
-  "feedbackButton": {
+  "FEEDBACK_BUTTON": {
     "message": "Spätná väzba",
     "description": "Label for the feedback button."
   },
-  "helpButton": {
+  "HELP_BUTTON": {
     "message": "Pomocník",
     "description": "Label for the help button."
   },
-  "labelGrid3x3": {
+  "LABEL_GRID_3X3": {
     "message": "3 x 3",
     "description": "Label for for grid-type: 3x3."
   },
-  "ariaGrid3x3": {
+  "ARIA_GRID_3X3": {
     "message": "3 na 3",
     "description": "Label for spoken feedback to read out grid-type: 3x3."
   },
-  "labelGrid4x4": {
+  "LABEL_GRID_4X4": {
     "message": "4 x 4",
     "description": "Label for for grid-type: 4x4."
   },
-  "ariaGrid4x4": {
+  "ARIA_GRID_4X4": {
     "message": "4 na 4",
     "description": "Label for spoken feedback to read out grid-type: 4x4."
   },
-  "labelGridGolden": {
+  "LABEL_GRID_GOLDEN": {
     "message": "Zlatý pomer",
     "description": "Label for grid-type: golden ratio."
   },
-  "labelTimer3s": {
+  "LABEL_TIMER_3S": {
     "message": "3 sekundy",
     "description": "Label for timer-duration: 3 seconds."
   },
-  "labelTimer10s": {
+  "LABEL_TIMER_10S": {
     "message": "10 sekúnd",
     "description": "Label for timer-duration: 10 seconds."
   },
-  "takePhotoButton": {
+  "TAKE_PHOTO_BUTTON": {
     "message": "Odfotiť",
     "description": "Label for the shutter button to take photo."
   },
-  "takePhotoCancelButton": {
+  "TAKE_PHOTO_CANCEL_BUTTON": {
     "message": "Zastaviť fotenie",
     "description": "Label for the shutter button to cancel countdown timer and stop taking photo."
   },
-  "recordVideoStartButton": {
+  "RECORD_VIDEO_START_BUTTON": {
     "message": "Spustiť nahrávanie",
     "description": "Label for the shutter button to start recording."
   },
-  "recordVideoStopButton": {
+  "RECORD_VIDEO_STOP_BUTTON": {
     "message": "Zastaviť nahrávanie",
     "description": "Label for the shutter button to stop recording."
   },
-  "switchCameraButton": {
+  "SWITCH_CAMERA_BUTTON": {
     "message": "Prepnúť na ďalší fotoaparát",
     "description": "Label for the button to switch to next connected camera. Eg. switching from front facing to back facing, or a camera connected via USB. The button is shown only when more than one camera is connected."
   },
-  "switchRecordVideoButton": {
+  "SWITCH_RECORD_VIDEO_BUTTON": {
     "message": "Prepnúť na nahrávanie videa",
     "description": "Label for the button to switch to record video mode."
   },
-  "switchTakePhotoButton": {
+  "SWITCH_TAKE_PHOTO_BUTTON": {
     "message": "Prepnúť na fotenie",
     "description": "Label for the button to switch to take photo mode."
   },
-  "toggleTimerButton": {
+  "TOGGLE_TIMER_BUTTON": {
     "message": "Časovač",
     "description": "Label for the checkbox to toggle the countdown timer."
   },
-  "toggleMirrorButton": {
+  "TOGGLE_MIRROR_BUTTON": {
     "message": "Zrkadlenie",
     "description": "Label for the checkbox to toggle the preview mirroring. Eg. if mirroring is toggled on, preview will be flipped horizontally."
   },
-  "toggleGridButton": {
+  "TOGGLE_GRID_BUTTON": {
     "message": "Mriežka",
     "description": "Label for the checkbox to toggle the grid shown on preview."
   },
-  "toggleMicButton": {
+  "TOGGLE_MIC_BUTTON": {
     "message": "Mikrofón",
     "description": "Label for the checkbox to toggle the microphone for recording video."
   },
-  "dialogOKButton": {
+  "DIALOG_OK_BUTTON": {
     "message": "OK",
     "description": "Label for the accepting button in the dialog."
   },
-  "dialogCancelButton": {
+  "DIALOG_CANCEL_BUTTON": {
     "message": "Zrušiť",
     "description": "Label for the dismissing button in the dialog."
   },
-  "deleteConfirmationMsg": {
+  "DELETE_CONFIRMATION_MSG": {
     "message": "Naozaj chcete súbor $file$ odstrániť?",
     "description": "Confirmation message before removing a selected item from the gallery. Expects a file name to be passed in.",
     "placeholders": {
@@ -189,7 +189,7 @@
       }
     }
   },
-  "deleteMultiConfirmationMsg": {
+  "DELETE_MULTI_CONFIRMATION_MSG": {
     "message": "Naozaj chcete tieto položky ($count$) odstrániť?",
     "description": "Confirmation message before removing multiple selected items from the gallery. Expects a file count to be passed in.",
     "placeholders": {
@@ -199,7 +199,7 @@
       }
     }
   },
-  "migratePicturesMsg": {
+  "MIGRATE_PICTURES_MSG": {
     "message": "Fotky a videá nasnímané fotoaparátom budú presunuté do priečinka stiahnutých súborov. Prístup k nim získate v priečinku Súbory.\nK fotkám a videám budú mať prístup aplikácie s povoleniami pre úložisko.",
     "description": "Message shown before moving all photos and videos stored in the Camera App to the Downloads folder."
   }
diff --git a/chrome/browser/resources/chromeos/camera/src/_locales/sl/messages.json b/chrome/browser/resources/chromeos/camera/src/_locales/sl/messages.json
index d76e3fe..81ac42e3 100644
--- a/chrome/browser/resources/chromeos/camera/src/_locales/sl/messages.json
+++ b/chrome/browser/resources/chromeos/camera/src/_locales/sl/messages.json
@@ -1,21 +1,21 @@
 {
-  "name": {
+  "NAME": {
     "message": "Fotoaparat",
     "description": "Name of the Camera App."
   },
-  "description": {
+  "DESCRIPTION": {
     "message": "Fotografirajte in snemajte videoposnetke s fotoaparatom.",
     "description": "Short description of the Camera App."
   },
-  "errorMsgFileSystemFailed": {
+  "ERROR_MSG_FILE_SYSTEM_FAILED": {
     "message": "Napake datotečnega sistema.",
     "description": "Error message shown when failing to read or write the file system."
   },
-  "errorMsgNoCamera": {
+  "ERROR_MSG_NO_CAMERA": {
     "message": "Fotoaparat trenutno ni na voljo.\nPreverite, ali je fotoaparat ustrezno povezan.",
     "description": "Error message shown when it was impossible to connect to the camera due to unavailability."
   },
-  "errorMsgGalleryExportFailed": {
+  "ERROR_MSG_GALLERY_EXPORT_FAILED": {
     "message": "Datoteke $file$ ni mogoče izvoziti",
     "description": "Error message shown when exporting to an external directory failed. Expects a file name to be passed in.",
     "placeholders": {
@@ -25,27 +25,27 @@
       }
     }
   },
-  "errorMsgSaveFileFailed": {
+  "ERROR_MSG_SAVE_FILE_FAILED": {
     "message": "Datoteke ni mogoče shraniti",
     "description": "Error message shown when saving/adding a image or video to the file system failed."
   },
-  "errorMsgTakePhotoFailed": {
+  "ERROR_MSG_TAKE_PHOTO_FAILED": {
     "message": "Fotografije ni mogoče posneti",
     "description": "Error message shown when failing to take photo."
   },
-  "errorMsgRecordStartFailed": {
+  "ERROR_MSG_RECORD_START_FAILED": {
     "message": "Snemanja ni mogoče začeti",
     "description": "Error message shown when failing to start recording video."
   },
-  "errorMsgEmptyRecording": {
+  "ERROR_MSG_EMPTY_RECORDING": {
     "message": "Nič ni posneto",
     "description": "Error message shown when no data is recorded for a recording and it won't be added to the gallery."
   },
-  "statusMsgRecordingStopped": {
+  "STATUS_MSG_RECORDING_STOPPED": {
     "message": "Snemanje je ustavljeno",
     "description": "Status message for spoken feedback when video recording has been stopped."
   },
-  "statusMsgCameraSwitched": {
+  "STATUS_MSG_CAMERA_SWITCHED": {
     "message": "Fotoaparat $camera$ je aktiven",
     "description": "Status message for spoken feedback when switching over to another camera.",
     "placeholders": {
@@ -55,131 +55,131 @@
       }
     }
   },
-  "galleryButton": {
+  "GALLERY_BUTTON": {
     "message": "V galerijo",
     "description": "Label for the gallery button."
   },
-  "deleteButton": {
+  "DELETE_BUTTON": {
     "message": "Izbris",
     "description": "Label for the delete button."
   },
-  "exportButton": {
+  "EXPORT_BUTTON": {
     "message": "Izvoz na disk",
     "description": "Label for the exporting button."
   },
-  "printButton": {
+  "PRINT_BUTTON": {
     "message": "Tiskanje",
     "description": "Label for the printing button."
   },
-  "backButton": {
+  "BACK_BUTTON": {
     "message": "Nazaj",
     "description": "Label for the back button."
   },
-  "galleryImages": {
+  "GALLERY_IMAGES": {
     "message": "Slike v galeriji",
     "description": "Text to speech label for the gallery list."
   },
-  "settingsButton": {
+  "SETTINGS_BUTTON": {
     "message": "Nastavitve",
     "description": "Label for the settings button."
   },
-  "gridTypeButton": {
+  "GRID_TYPE_BUTTON": {
     "message": "Vrsta mreže",
     "description": "Label for the button of grid-type options."
   },
-  "timerDurationButton": {
+  "TIMER_DURATION_BUTTON": {
     "message": "Trajanje časovnika",
     "description": "Label for the button of timer-duration options."
   },
-  "feedbackButton": {
+  "FEEDBACK_BUTTON": {
     "message": "Pošlji povratne informacije",
     "description": "Label for the feedback button."
   },
-  "helpButton": {
+  "HELP_BUTTON": {
     "message": "Pomoč",
     "description": "Label for the help button."
   },
-  "labelGrid3x3": {
+  "LABEL_GRID_3X3": {
     "message": "3 x 3",
     "description": "Label for for grid-type: 3x3."
   },
-  "ariaGrid3x3": {
+  "ARIA_GRID_3X3": {
     "message": "3 x 3",
     "description": "Label for spoken feedback to read out grid-type: 3x3."
   },
-  "labelGrid4x4": {
+  "LABEL_GRID_4X4": {
     "message": "4 x 4",
     "description": "Label for for grid-type: 4x4."
   },
-  "ariaGrid4x4": {
+  "ARIA_GRID_4X4": {
     "message": "4 x 4",
     "description": "Label for spoken feedback to read out grid-type: 4x4."
   },
-  "labelGridGolden": {
+  "LABEL_GRID_GOLDEN": {
     "message": "Zlato razmerje",
     "description": "Label for grid-type: golden ratio."
   },
-  "labelTimer3s": {
+  "LABEL_TIMER_3S": {
     "message": "3 sekunde",
     "description": "Label for timer-duration: 3 seconds."
   },
-  "labelTimer10s": {
+  "LABEL_TIMER_10S": {
     "message": "10 sekund",
     "description": "Label for timer-duration: 10 seconds."
   },
-  "takePhotoButton": {
+  "TAKE_PHOTO_BUTTON": {
     "message": "Fotografiranje",
     "description": "Label for the shutter button to take photo."
   },
-  "takePhotoCancelButton": {
+  "TAKE_PHOTO_CANCEL_BUTTON": {
     "message": "Ustavitev fotografiranja",
     "description": "Label for the shutter button to cancel countdown timer and stop taking photo."
   },
-  "recordVideoStartButton": {
+  "RECORD_VIDEO_START_BUTTON": {
     "message": "Začetek snemanja",
     "description": "Label for the shutter button to start recording."
   },
-  "recordVideoStopButton": {
+  "RECORD_VIDEO_STOP_BUTTON": {
     "message": "Ustavitev snemanja",
     "description": "Label for the shutter button to stop recording."
   },
-  "switchCameraButton": {
+  "SWITCH_CAMERA_BUTTON": {
     "message": "Preklop na naslednji fotoaparat",
     "description": "Label for the button to switch to next connected camera. Eg. switching from front facing to back facing, or a camera connected via USB. The button is shown only when more than one camera is connected."
   },
-  "switchRecordVideoButton": {
+  "SWITCH_RECORD_VIDEO_BUTTON": {
     "message": "Preklop na snemanje videa",
     "description": "Label for the button to switch to record video mode."
   },
-  "switchTakePhotoButton": {
+  "SWITCH_TAKE_PHOTO_BUTTON": {
     "message": "Preklop na fotografiranje",
     "description": "Label for the button to switch to take photo mode."
   },
-  "toggleTimerButton": {
+  "TOGGLE_TIMER_BUTTON": {
     "message": "Časovnik",
     "description": "Label for the checkbox to toggle the countdown timer."
   },
-  "toggleMirrorButton": {
+  "TOGGLE_MIRROR_BUTTON": {
     "message": "Zrcaljenje",
     "description": "Label for the checkbox to toggle the preview mirroring. Eg. if mirroring is toggled on, preview will be flipped horizontally."
   },
-  "toggleGridButton": {
+  "TOGGLE_GRID_BUTTON": {
     "message": "Mreža",
     "description": "Label for the checkbox to toggle the grid shown on preview."
   },
-  "toggleMicButton": {
+  "TOGGLE_MIC_BUTTON": {
     "message": "Mikrofon",
     "description": "Label for the checkbox to toggle the microphone for recording video."
   },
-  "dialogOKButton": {
+  "DIALOG_OK_BUTTON": {
     "message": "V redu",
     "description": "Label for the accepting button in the dialog."
   },
-  "dialogCancelButton": {
+  "DIALOG_CANCEL_BUTTON": {
     "message": "Prekliči",
     "description": "Label for the dismissing button in the dialog."
   },
-  "deleteConfirmationMsg": {
+  "DELETE_CONFIRMATION_MSG": {
     "message": "Ali res želite odstraniti datoteko $file$?",
     "description": "Confirmation message before removing a selected item from the gallery. Expects a file name to be passed in.",
     "placeholders": {
@@ -189,7 +189,7 @@
       }
     }
   },
-  "deleteMultiConfirmationMsg": {
+  "DELETE_MULTI_CONFIRMATION_MSG": {
     "message": "Ali res želite odstraniti toliko elementov: $count$?",
     "description": "Confirmation message before removing multiple selected items from the gallery. Expects a file count to be passed in.",
     "placeholders": {
@@ -199,7 +199,7 @@
       }
     }
   },
-  "migratePicturesMsg": {
+  "MIGRATE_PICTURES_MSG": {
     "message": "Fotografije in videoposnetki, ki ste jih posneli s fotoaparatom, bodo premaknjeni v mapo Prenosi. Do njih lahko dostopate v aplikaciji Datoteke.\n\nAplikacije z dovoljenji za shrambo bodo imele dostop do fotografij in videoposnetkov.",
     "description": "Message shown before moving all photos and videos stored in the Camera App to the Downloads folder."
   }
diff --git a/chrome/browser/resources/chromeos/camera/src/_locales/sr/messages.json b/chrome/browser/resources/chromeos/camera/src/_locales/sr/messages.json
index ad1790b..74b3974 100644
--- a/chrome/browser/resources/chromeos/camera/src/_locales/sr/messages.json
+++ b/chrome/browser/resources/chromeos/camera/src/_locales/sr/messages.json
@@ -1,21 +1,21 @@
 {
-  "name": {
+  "NAME": {
     "message": "Камера",
     "description": "Name of the Camera App."
   },
-  "description": {
+  "DESCRIPTION": {
     "message": "Снимајте слике и видео снимке помоћу камере.",
     "description": "Short description of the Camera App."
   },
-  "errorMsgFileSystemFailed": {
+  "ERROR_MSG_FILE_SYSTEM_FAILED": {
     "message": "Грешке система датотека.",
     "description": "Error message shown when failing to read or write the file system."
   },
-  "errorMsgNoCamera": {
+  "ERROR_MSG_NO_CAMERA": {
     "message": "Камера тренутно није доступна.\nПроверите да ли је камера исправно повезана.",
     "description": "Error message shown when it was impossible to connect to the camera due to unavailability."
   },
-  "errorMsgGalleryExportFailed": {
+  "ERROR_MSG_GALLERY_EXPORT_FAILED": {
     "message": "Извоз датотеке $file$ није успео",
     "description": "Error message shown when exporting to an external directory failed. Expects a file name to be passed in.",
     "placeholders": {
@@ -25,27 +25,27 @@
       }
     }
   },
-  "errorMsgSaveFileFailed": {
+  "ERROR_MSG_SAVE_FILE_FAILED": {
     "message": "Чување датотеке није успело",
     "description": "Error message shown when saving/adding a image or video to the file system failed."
   },
-  "errorMsgTakePhotoFailed": {
+  "ERROR_MSG_TAKE_PHOTO_FAILED": {
     "message": "Снимање слике није успело",
     "description": "Error message shown when failing to take photo."
   },
-  "errorMsgRecordStartFailed": {
+  "ERROR_MSG_RECORD_START_FAILED": {
     "message": "Нисмо успели да започнемо снимање",
     "description": "Error message shown when failing to start recording video."
   },
-  "errorMsgEmptyRecording": {
+  "ERROR_MSG_EMPTY_RECORDING": {
     "message": "Ништа није снимљено",
     "description": "Error message shown when no data is recorded for a recording and it won't be added to the gallery."
   },
-  "statusMsgRecordingStopped": {
+  "STATUS_MSG_RECORDING_STOPPED": {
     "message": "Снимање је заустављено",
     "description": "Status message for spoken feedback when video recording has been stopped."
   },
-  "statusMsgCameraSwitched": {
+  "STATUS_MSG_CAMERA_SWITCHED": {
     "message": "Активна је камера $camera$",
     "description": "Status message for spoken feedback when switching over to another camera.",
     "placeholders": {
@@ -55,131 +55,131 @@
       }
     }
   },
-  "galleryButton": {
+  "GALLERY_BUTTON": {
     "message": "Иди у галерију",
     "description": "Label for the gallery button."
   },
-  "deleteButton": {
+  "DELETE_BUTTON": {
     "message": "Избриши",
     "description": "Label for the delete button."
   },
-  "exportButton": {
+  "EXPORT_BUTTON": {
     "message": "Извези на диск",
     "description": "Label for the exporting button."
   },
-  "printButton": {
+  "PRINT_BUTTON": {
     "message": "Штампај",
     "description": "Label for the printing button."
   },
-  "backButton": {
+  "BACK_BUTTON": {
     "message": "Назад",
     "description": "Label for the back button."
   },
-  "galleryImages": {
+  "GALLERY_IMAGES": {
     "message": "Слике у галерији",
     "description": "Text to speech label for the gallery list."
   },
-  "settingsButton": {
+  "SETTINGS_BUTTON": {
     "message": "Подешавања",
     "description": "Label for the settings button."
   },
-  "gridTypeButton": {
+  "GRID_TYPE_BUTTON": {
     "message": "Тип мреже",
     "description": "Label for the button of grid-type options."
   },
-  "timerDurationButton": {
+  "TIMER_DURATION_BUTTON": {
     "message": "Трајање тајмера",
     "description": "Label for the button of timer-duration options."
   },
-  "feedbackButton": {
+  "FEEDBACK_BUTTON": {
     "message": "Пошаљи повратне информације",
     "description": "Label for the feedback button."
   },
-  "helpButton": {
+  "HELP_BUTTON": {
     "message": "Помоћ",
     "description": "Label for the help button."
   },
-  "labelGrid3x3": {
+  "LABEL_GRID_3X3": {
     "message": "3×3",
     "description": "Label for for grid-type: 3x3."
   },
-  "ariaGrid3x3": {
+  "ARIA_GRID_3X3": {
     "message": "3 са 3",
     "description": "Label for spoken feedback to read out grid-type: 3x3."
   },
-  "labelGrid4x4": {
+  "LABEL_GRID_4X4": {
     "message": "4×4",
     "description": "Label for for grid-type: 4x4."
   },
-  "ariaGrid4x4": {
+  "ARIA_GRID_4X4": {
     "message": "4 са 4",
     "description": "Label for spoken feedback to read out grid-type: 4x4."
   },
-  "labelGridGolden": {
+  "LABEL_GRID_GOLDEN": {
     "message": "Златни пресек",
     "description": "Label for grid-type: golden ratio."
   },
-  "labelTimer3s": {
+  "LABEL_TIMER_3S": {
     "message": "3 секунде",
     "description": "Label for timer-duration: 3 seconds."
   },
-  "labelTimer10s": {
+  "LABEL_TIMER_10S": {
     "message": "10 секунди",
     "description": "Label for timer-duration: 10 seconds."
   },
-  "takePhotoButton": {
+  "TAKE_PHOTO_BUTTON": {
     "message": "Сликај",
     "description": "Label for the shutter button to take photo."
   },
-  "takePhotoCancelButton": {
+  "TAKE_PHOTO_CANCEL_BUTTON": {
     "message": "Заустави снимање слике",
     "description": "Label for the shutter button to cancel countdown timer and stop taking photo."
   },
-  "recordVideoStartButton": {
+  "RECORD_VIDEO_START_BUTTON": {
     "message": "Започни снимање",
     "description": "Label for the shutter button to start recording."
   },
-  "recordVideoStopButton": {
+  "RECORD_VIDEO_STOP_BUTTON": {
     "message": "Заустави снимање",
     "description": "Label for the shutter button to stop recording."
   },
-  "switchCameraButton": {
+  "SWITCH_CAMERA_BUTTON": {
     "message": "Пређи на следећу камеру",
     "description": "Label for the button to switch to next connected camera. Eg. switching from front facing to back facing, or a camera connected via USB. The button is shown only when more than one camera is connected."
   },
-  "switchRecordVideoButton": {
+  "SWITCH_RECORD_VIDEO_BUTTON": {
     "message": "Пређи на режим за снимање видеа",
     "description": "Label for the button to switch to record video mode."
   },
-  "switchTakePhotoButton": {
+  "SWITCH_TAKE_PHOTO_BUTTON": {
     "message": "Пређи на режим за снимање слика",
     "description": "Label for the button to switch to take photo mode."
   },
-  "toggleTimerButton": {
+  "TOGGLE_TIMER_BUTTON": {
     "message": "Тајмер",
     "description": "Label for the checkbox to toggle the countdown timer."
   },
-  "toggleMirrorButton": {
+  "TOGGLE_MIRROR_BUTTON": {
     "message": "Пресликавање",
     "description": "Label for the checkbox to toggle the preview mirroring. Eg. if mirroring is toggled on, preview will be flipped horizontally."
   },
-  "toggleGridButton": {
+  "TOGGLE_GRID_BUTTON": {
     "message": "Мрежа",
     "description": "Label for the checkbox to toggle the grid shown on preview."
   },
-  "toggleMicButton": {
+  "TOGGLE_MIC_BUTTON": {
     "message": "Микрофон",
     "description": "Label for the checkbox to toggle the microphone for recording video."
   },
-  "dialogOKButton": {
+  "DIALOG_OK_BUTTON": {
     "message": "Потврди",
     "description": "Label for the accepting button in the dialog."
   },
-  "dialogCancelButton": {
+  "DIALOG_CANCEL_BUTTON": {
     "message": "Откажи",
     "description": "Label for the dismissing button in the dialog."
   },
-  "deleteConfirmationMsg": {
+  "DELETE_CONFIRMATION_MSG": {
     "message": "Желите ли стварно да уклоните датотеку $file$?",
     "description": "Confirmation message before removing a selected item from the gallery. Expects a file name to be passed in.",
     "placeholders": {
@@ -189,7 +189,7 @@
       }
     }
   },
-  "deleteMultiConfirmationMsg": {
+  "DELETE_MULTI_CONFIRMATION_MSG": {
     "message": "Желите ли стварно да уклоните ове ставке ($count$)?",
     "description": "Confirmation message before removing multiple selected items from the gallery. Expects a file count to be passed in.",
     "placeholders": {
@@ -199,7 +199,7 @@
       }
     }
   },
-  "migratePicturesMsg": {
+  "MIGRATE_PICTURES_MSG": {
     "message": "Слике и видео снимци који су снимљени помоћу камере ће се преместити у директоријум Преузимања. Можете да им приступите у Датотекама.\n\nАпликације са дозволама за приступ меморијском простору ће имати приступ сликама и видео снимцима.",
     "description": "Message shown before moving all photos and videos stored in the Camera App to the Downloads folder."
   }
diff --git a/chrome/browser/resources/chromeos/camera/src/_locales/sv/messages.json b/chrome/browser/resources/chromeos/camera/src/_locales/sv/messages.json
index f753f70..430a397 100644
--- a/chrome/browser/resources/chromeos/camera/src/_locales/sv/messages.json
+++ b/chrome/browser/resources/chromeos/camera/src/_locales/sv/messages.json
@@ -1,21 +1,21 @@
 {
-  "name": {
+  "NAME": {
     "message": "Kamera",
     "description": "Name of the Camera App."
   },
-  "description": {
+  "DESCRIPTION": {
     "message": "Ta foton och spela in video med kameran.",
     "description": "Short description of the Camera App."
   },
-  "errorMsgFileSystemFailed": {
+  "ERROR_MSG_FILE_SYSTEM_FAILED": {
     "message": "Fel i filsystemet.",
     "description": "Error message shown when failing to read or write the file system."
   },
-  "errorMsgNoCamera": {
+  "ERROR_MSG_NO_CAMERA": {
     "message": "Kameran är inte tillgänglig.\nKontrollera kameraanslutningen.",
     "description": "Error message shown when it was impossible to connect to the camera due to unavailability."
   },
-  "errorMsgGalleryExportFailed": {
+  "ERROR_MSG_GALLERY_EXPORT_FAILED": {
     "message": "Det gick inte att exportera $file$",
     "description": "Error message shown when exporting to an external directory failed. Expects a file name to be passed in.",
     "placeholders": {
@@ -25,27 +25,27 @@
       }
     }
   },
-  "errorMsgSaveFileFailed": {
+  "ERROR_MSG_SAVE_FILE_FAILED": {
     "message": "Det gick inte att spara filen",
     "description": "Error message shown when saving/adding a image or video to the file system failed."
   },
-  "errorMsgTakePhotoFailed": {
+  "ERROR_MSG_TAKE_PHOTO_FAILED": {
     "message": "Det gick inte att ta ett foto",
     "description": "Error message shown when failing to take photo."
   },
-  "errorMsgRecordStartFailed": {
+  "ERROR_MSG_RECORD_START_FAILED": {
     "message": "Det gick inte att starta inspelningen",
     "description": "Error message shown when failing to start recording video."
   },
-  "errorMsgEmptyRecording": {
+  "ERROR_MSG_EMPTY_RECORDING": {
     "message": "Inget har spelats in",
     "description": "Error message shown when no data is recorded for a recording and it won't be added to the gallery."
   },
-  "statusMsgRecordingStopped": {
+  "STATUS_MSG_RECORDING_STOPPED": {
     "message": "Inspelningen stoppad",
     "description": "Status message for spoken feedback when video recording has been stopped."
   },
-  "statusMsgCameraSwitched": {
+  "STATUS_MSG_CAMERA_SWITCHED": {
     "message": "$camera$ är aktiv",
     "description": "Status message for spoken feedback when switching over to another camera.",
     "placeholders": {
@@ -55,131 +55,131 @@
       }
     }
   },
-  "galleryButton": {
+  "GALLERY_BUTTON": {
     "message": "Besök galleriet",
     "description": "Label for the gallery button."
   },
-  "deleteButton": {
+  "DELETE_BUTTON": {
     "message": "Radera",
     "description": "Label for the delete button."
   },
-  "exportButton": {
+  "EXPORT_BUTTON": {
     "message": "Exportera till disk",
     "description": "Label for the exporting button."
   },
-  "printButton": {
+  "PRINT_BUTTON": {
     "message": "Skriv ut",
     "description": "Label for the printing button."
   },
-  "backButton": {
+  "BACK_BUTTON": {
     "message": "Föregående",
     "description": "Label for the back button."
   },
-  "galleryImages": {
+  "GALLERY_IMAGES": {
     "message": "Bilder i galleriet",
     "description": "Text to speech label for the gallery list."
   },
-  "settingsButton": {
+  "SETTINGS_BUTTON": {
     "message": "Inställningar",
     "description": "Label for the settings button."
   },
-  "gridTypeButton": {
+  "GRID_TYPE_BUTTON": {
     "message": "Typ av rutnät",
     "description": "Label for the button of grid-type options."
   },
-  "timerDurationButton": {
+  "TIMER_DURATION_BUTTON": {
     "message": "Timerns längd",
     "description": "Label for the button of timer-duration options."
   },
-  "feedbackButton": {
+  "FEEDBACK_BUTTON": {
     "message": "Skicka feedback",
     "description": "Label for the feedback button."
   },
-  "helpButton": {
+  "HELP_BUTTON": {
     "message": "Hjälp",
     "description": "Label for the help button."
   },
-  "labelGrid3x3": {
+  "LABEL_GRID_3X3": {
     "message": "3 × 3",
     "description": "Label for for grid-type: 3x3."
   },
-  "ariaGrid3x3": {
+  "ARIA_GRID_3X3": {
     "message": "Tre gånger tre",
     "description": "Label for spoken feedback to read out grid-type: 3x3."
   },
-  "labelGrid4x4": {
+  "LABEL_GRID_4X4": {
     "message": "4 × 4",
     "description": "Label for for grid-type: 4x4."
   },
-  "ariaGrid4x4": {
+  "ARIA_GRID_4X4": {
     "message": "Fyra gånger fyra",
     "description": "Label for spoken feedback to read out grid-type: 4x4."
   },
-  "labelGridGolden": {
+  "LABEL_GRID_GOLDEN": {
     "message": "Gyllene snittet",
     "description": "Label for grid-type: golden ratio."
   },
-  "labelTimer3s": {
+  "LABEL_TIMER_3S": {
     "message": "Tre sekunder",
     "description": "Label for timer-duration: 3 seconds."
   },
-  "labelTimer10s": {
+  "LABEL_TIMER_10S": {
     "message": "Tio sekunder",
     "description": "Label for timer-duration: 10 seconds."
   },
-  "takePhotoButton": {
+  "TAKE_PHOTO_BUTTON": {
     "message": "Ta foto",
     "description": "Label for the shutter button to take photo."
   },
-  "takePhotoCancelButton": {
+  "TAKE_PHOTO_CANCEL_BUTTON": {
     "message": "Sluta ta foton",
     "description": "Label for the shutter button to cancel countdown timer and stop taking photo."
   },
-  "recordVideoStartButton": {
+  "RECORD_VIDEO_START_BUTTON": {
     "message": "Börja spela in",
     "description": "Label for the shutter button to start recording."
   },
-  "recordVideoStopButton": {
+  "RECORD_VIDEO_STOP_BUTTON": {
     "message": "Sluta spela in",
     "description": "Label for the shutter button to stop recording."
   },
-  "switchCameraButton": {
+  "SWITCH_CAMERA_BUTTON": {
     "message": "Byt till nästa kamera",
     "description": "Label for the button to switch to next connected camera. Eg. switching from front facing to back facing, or a camera connected via USB. The button is shown only when more than one camera is connected."
   },
-  "switchRecordVideoButton": {
+  "SWITCH_RECORD_VIDEO_BUTTON": {
     "message": "Byt till videoinspelning",
     "description": "Label for the button to switch to record video mode."
   },
-  "switchTakePhotoButton": {
+  "SWITCH_TAKE_PHOTO_BUTTON": {
     "message": "Byt till fotoläge",
     "description": "Label for the button to switch to take photo mode."
   },
-  "toggleTimerButton": {
+  "TOGGLE_TIMER_BUTTON": {
     "message": "Timer",
     "description": "Label for the checkbox to toggle the countdown timer."
   },
-  "toggleMirrorButton": {
+  "TOGGLE_MIRROR_BUTTON": {
     "message": "Spegling",
     "description": "Label for the checkbox to toggle the preview mirroring. Eg. if mirroring is toggled on, preview will be flipped horizontally."
   },
-  "toggleGridButton": {
+  "TOGGLE_GRID_BUTTON": {
     "message": "Rutnät",
     "description": "Label for the checkbox to toggle the grid shown on preview."
   },
-  "toggleMicButton": {
+  "TOGGLE_MIC_BUTTON": {
     "message": "Mikrofon",
     "description": "Label for the checkbox to toggle the microphone for recording video."
   },
-  "dialogOKButton": {
+  "DIALOG_OK_BUTTON": {
     "message": "OK",
     "description": "Label for the accepting button in the dialog."
   },
-  "dialogCancelButton": {
+  "DIALOG_CANCEL_BUTTON": {
     "message": "Avbryt",
     "description": "Label for the dismissing button in the dialog."
   },
-  "deleteConfirmationMsg": {
+  "DELETE_CONFIRMATION_MSG": {
     "message": "Vill du ta bort $file$?",
     "description": "Confirmation message before removing a selected item from the gallery. Expects a file name to be passed in.",
     "placeholders": {
@@ -189,7 +189,7 @@
       }
     }
   },
-  "deleteMultiConfirmationMsg": {
+  "DELETE_MULTI_CONFIRMATION_MSG": {
     "message": "Vill du ta bort $count$ objekt?",
     "description": "Confirmation message before removing multiple selected items from the gallery. Expects a file count to be passed in.",
     "placeholders": {
@@ -199,7 +199,7 @@
       }
     }
   },
-  "migratePicturesMsg": {
+  "MIGRATE_PICTURES_MSG": {
     "message": "Videor och foton du tagit med kameran flyttas till mappen Nedladdningar. Du kan öppna dem i Filer.\n\nFotona och videorna blir tillgängliga för appar som har åtkomstbehörighet till lagringsutrymmet.",
     "description": "Message shown before moving all photos and videos stored in the Camera App to the Downloads folder."
   }
diff --git a/chrome/browser/resources/chromeos/camera/src/_locales/sw/messages.json b/chrome/browser/resources/chromeos/camera/src/_locales/sw/messages.json
index 651c2b0..79e750b 100644
--- a/chrome/browser/resources/chromeos/camera/src/_locales/sw/messages.json
+++ b/chrome/browser/resources/chromeos/camera/src/_locales/sw/messages.json
@@ -1,21 +1,21 @@
 {
-  "name": {
+  "NAME": {
     "message": "Kamera",
     "description": "Name of the Camera App."
   },
-  "description": {
+  "DESCRIPTION": {
     "message": "Piga picha na urekodi video ukitumia kamera yako.",
     "description": "Short description of the Camera App."
   },
-  "errorMsgFileSystemFailed": {
+  "ERROR_MSG_FILE_SYSTEM_FAILED": {
     "message": "Hitilafu za mfumo wa faili.",
     "description": "Error message shown when failing to read or write the file system."
   },
-  "errorMsgNoCamera": {
+  "ERROR_MSG_NO_CAMERA": {
     "message": "Kamera yako haipatikani kwa sasa.\nTafadhali angalia ikiwa umeunganisha kamera vizuri.",
     "description": "Error message shown when it was impossible to connect to the camera due to unavailability."
   },
-  "errorMsgGalleryExportFailed": {
+  "ERROR_MSG_GALLERY_EXPORT_FAILED": {
     "message": "Imeshindwa kutuma $file$",
     "description": "Error message shown when exporting to an external directory failed. Expects a file name to be passed in.",
     "placeholders": {
@@ -25,27 +25,27 @@
       }
     }
   },
-  "errorMsgSaveFileFailed": {
+  "ERROR_MSG_SAVE_FILE_FAILED": {
     "message": "Imeshindwa kuhifadhi faili",
     "description": "Error message shown when saving/adding a image or video to the file system failed."
   },
-  "errorMsgTakePhotoFailed": {
+  "ERROR_MSG_TAKE_PHOTO_FAILED": {
     "message": "Imeshindwa kupiga picha",
     "description": "Error message shown when failing to take photo."
   },
-  "errorMsgRecordStartFailed": {
+  "ERROR_MSG_RECORD_START_FAILED": {
     "message": "Imeshindwa kuanza kurekodi",
     "description": "Error message shown when failing to start recording video."
   },
-  "errorMsgEmptyRecording": {
+  "ERROR_MSG_EMPTY_RECORDING": {
     "message": "Haijarekodi chochote",
     "description": "Error message shown when no data is recorded for a recording and it won't be added to the gallery."
   },
-  "statusMsgRecordingStopped": {
+  "STATUS_MSG_RECORDING_STOPPED": {
     "message": "Imeacha kurekodi",
     "description": "Status message for spoken feedback when video recording has been stopped."
   },
-  "statusMsgCameraSwitched": {
+  "STATUS_MSG_CAMERA_SWITCHED": {
     "message": "$camera$ inatumika",
     "description": "Status message for spoken feedback when switching over to another camera.",
     "placeholders": {
@@ -55,131 +55,131 @@
       }
     }
   },
-  "galleryButton": {
+  "GALLERY_BUTTON": {
     "message": "Nenda kwenye matunzio",
     "description": "Label for the gallery button."
   },
-  "deleteButton": {
+  "DELETE_BUTTON": {
     "message": "Futa",
     "description": "Label for the delete button."
   },
-  "exportButton": {
+  "EXPORT_BUTTON": {
     "message": "Hamishia kwenye diski",
     "description": "Label for the exporting button."
   },
-  "printButton": {
+  "PRINT_BUTTON": {
     "message": "Chapisha",
     "description": "Label for the printing button."
   },
-  "backButton": {
+  "BACK_BUTTON": {
     "message": "Rudi nyuma",
     "description": "Label for the back button."
   },
-  "galleryImages": {
+  "GALLERY_IMAGES": {
     "message": "Picha za matunzio",
     "description": "Text to speech label for the gallery list."
   },
-  "settingsButton": {
+  "SETTINGS_BUTTON": {
     "message": "Mipangilio",
     "description": "Label for the settings button."
   },
-  "gridTypeButton": {
+  "GRID_TYPE_BUTTON": {
     "message": "Aina ya gridi",
     "description": "Label for the button of grid-type options."
   },
-  "timerDurationButton": {
+  "TIMER_DURATION_BUTTON": {
     "message": "Urefu wa kipima muda",
     "description": "Label for the button of timer-duration options."
   },
-  "feedbackButton": {
+  "FEEDBACK_BUTTON": {
     "message": "Tuma maoni",
     "description": "Label for the feedback button."
   },
-  "helpButton": {
+  "HELP_BUTTON": {
     "message": "Usaidizi",
     "description": "Label for the help button."
   },
-  "labelGrid3x3": {
+  "LABEL_GRID_3X3": {
     "message": "3 x 3",
     "description": "Label for for grid-type: 3x3."
   },
-  "ariaGrid3x3": {
+  "ARIA_GRID_3X3": {
     "message": "3 kwa 3",
     "description": "Label for spoken feedback to read out grid-type: 3x3."
   },
-  "labelGrid4x4": {
+  "LABEL_GRID_4X4": {
     "message": "4 x 4",
     "description": "Label for for grid-type: 4x4."
   },
-  "ariaGrid4x4": {
+  "ARIA_GRID_4X4": {
     "message": "4 kwa 4",
     "description": "Label for spoken feedback to read out grid-type: 4x4."
   },
-  "labelGridGolden": {
+  "LABEL_GRID_GOLDEN": {
     "message": "Uwiano mkuu",
     "description": "Label for grid-type: golden ratio."
   },
-  "labelTimer3s": {
+  "LABEL_TIMER_3S": {
     "message": "Sekunde 3",
     "description": "Label for timer-duration: 3 seconds."
   },
-  "labelTimer10s": {
+  "LABEL_TIMER_10S": {
     "message": "Sekunde 10",
     "description": "Label for timer-duration: 10 seconds."
   },
-  "takePhotoButton": {
+  "TAKE_PHOTO_BUTTON": {
     "message": "Piga picha",
     "description": "Label for the shutter button to take photo."
   },
-  "takePhotoCancelButton": {
+  "TAKE_PHOTO_CANCEL_BUTTON": {
     "message": "Acha kupiga picha",
     "description": "Label for the shutter button to cancel countdown timer and stop taking photo."
   },
-  "recordVideoStartButton": {
+  "RECORD_VIDEO_START_BUTTON": {
     "message": "Anza kurekodi",
     "description": "Label for the shutter button to start recording."
   },
-  "recordVideoStopButton": {
+  "RECORD_VIDEO_STOP_BUTTON": {
     "message": "Acha kurekodi",
     "description": "Label for the shutter button to stop recording."
   },
-  "switchCameraButton": {
+  "SWITCH_CAMERA_BUTTON": {
     "message": "Tumia kamera inayofuata",
     "description": "Label for the button to switch to next connected camera. Eg. switching from front facing to back facing, or a camera connected via USB. The button is shown only when more than one camera is connected."
   },
-  "switchRecordVideoButton": {
+  "SWITCH_RECORD_VIDEO_BUTTON": {
     "message": "Rekodi video",
     "description": "Label for the button to switch to record video mode."
   },
-  "switchTakePhotoButton": {
+  "SWITCH_TAKE_PHOTO_BUTTON": {
     "message": "Piga picha",
     "description": "Label for the button to switch to take photo mode."
   },
-  "toggleTimerButton": {
+  "TOGGLE_TIMER_BUTTON": {
     "message": "Kipima muda",
     "description": "Label for the checkbox to toggle the countdown timer."
   },
-  "toggleMirrorButton": {
+  "TOGGLE_MIRROR_BUTTON": {
     "message": "Uakisi",
     "description": "Label for the checkbox to toggle the preview mirroring. Eg. if mirroring is toggled on, preview will be flipped horizontally."
   },
-  "toggleGridButton": {
+  "TOGGLE_GRID_BUTTON": {
     "message": "Gridi",
     "description": "Label for the checkbox to toggle the grid shown on preview."
   },
-  "toggleMicButton": {
+  "TOGGLE_MIC_BUTTON": {
     "message": "Maikrofoni",
     "description": "Label for the checkbox to toggle the microphone for recording video."
   },
-  "dialogOKButton": {
+  "DIALOG_OK_BUTTON": {
     "message": "Sawa",
     "description": "Label for the accepting button in the dialog."
   },
-  "dialogCancelButton": {
+  "DIALOG_CANCEL_BUTTON": {
     "message": "Ghairi",
     "description": "Label for the dismissing button in the dialog."
   },
-  "deleteConfirmationMsg": {
+  "DELETE_CONFIRMATION_MSG": {
     "message": "Una uhakika ungependa kuondoa $file$ kwenye matunzio?",
     "description": "Confirmation message before removing a selected item from the gallery. Expects a file name to be passed in.",
     "placeholders": {
@@ -189,7 +189,7 @@
       }
     }
   },
-  "deleteMultiConfirmationMsg": {
+  "DELETE_MULTI_CONFIRMATION_MSG": {
     "message": "Una uhakika ungependa kuondoa vipengee $count$?",
     "description": "Confirmation message before removing multiple selected items from the gallery. Expects a file count to be passed in.",
     "placeholders": {
@@ -199,7 +199,7 @@
       }
     }
   },
-  "migratePicturesMsg": {
+  "MIGRATE_PICTURES_MSG": {
     "message": "Picha na video zinazopigwa kwa kamera zitahamishiwa kwenye folda ya Vipakuliwa. Unaweza kuzifikia kwenye Faili.\n\nProgramu zilizo na ruhusa za hifadhi zitaweza kufikia picha na video zako.",
     "description": "Message shown before moving all photos and videos stored in the Camera App to the Downloads folder."
   }
diff --git a/chrome/browser/resources/chromeos/camera/src/_locales/ta/messages.json b/chrome/browser/resources/chromeos/camera/src/_locales/ta/messages.json
index da7a9f0..8c5f161 100644
--- a/chrome/browser/resources/chromeos/camera/src/_locales/ta/messages.json
+++ b/chrome/browser/resources/chromeos/camera/src/_locales/ta/messages.json
@@ -1,21 +1,21 @@
 {
-  "name": {
+  "NAME": {
     "message": "கேமரா",
     "description": "Name of the Camera App."
   },
-  "description": {
+  "DESCRIPTION": {
     "message": "உங்கள் கேமராவைப் பயன்படுத்தி, படங்களை எடுக்கலாம், வீடியோக்களை ரெக்கார்டு செய்யலாம்.",
     "description": "Short description of the Camera App."
   },
-  "errorMsgFileSystemFailed": {
+  "ERROR_MSG_FILE_SYSTEM_FAILED": {
     "message": "கோப்பு அமைப்புப் பிழைகள்.",
     "description": "Error message shown when failing to read or write the file system."
   },
-  "errorMsgNoCamera": {
+  "ERROR_MSG_NO_CAMERA": {
     "message": "உங்கள் கேமரா தற்போது கிடைக்கவில்லை.\nஅது சரியாக இணைக்கப்பட்டுள்ளதா எனச் சரிபார்க்கவும்.",
     "description": "Error message shown when it was impossible to connect to the camera due to unavailability."
   },
-  "errorMsgGalleryExportFailed": {
+  "ERROR_MSG_GALLERY_EXPORT_FAILED": {
     "message": "$file$ஐ இடமாற்ற முடியவில்லை",
     "description": "Error message shown when exporting to an external directory failed. Expects a file name to be passed in.",
     "placeholders": {
@@ -25,27 +25,27 @@
       }
     }
   },
-  "errorMsgSaveFileFailed": {
+  "ERROR_MSG_SAVE_FILE_FAILED": {
     "message": "கோப்பைச் சேமிக்க முடியவில்லை",
     "description": "Error message shown when saving/adding a image or video to the file system failed."
   },
-  "errorMsgTakePhotoFailed": {
+  "ERROR_MSG_TAKE_PHOTO_FAILED": {
     "message": "படம் எடுக்க முடியவில்லை",
     "description": "Error message shown when failing to take photo."
   },
-  "errorMsgRecordStartFailed": {
+  "ERROR_MSG_RECORD_START_FAILED": {
     "message": "ரெக்கார்டு செய்ய முடியவில்லை",
     "description": "Error message shown when failing to start recording video."
   },
-  "errorMsgEmptyRecording": {
+  "ERROR_MSG_EMPTY_RECORDING": {
     "message": "எதுவும் ரெக்கார்டு செய்யப்படவில்லை",
     "description": "Error message shown when no data is recorded for a recording and it won't be added to the gallery."
   },
-  "statusMsgRecordingStopped": {
+  "STATUS_MSG_RECORDING_STOPPED": {
     "message": "ரெக்கார்டு செய்வது நிறுத்தப்பட்டது",
     "description": "Status message for spoken feedback when video recording has been stopped."
   },
-  "statusMsgCameraSwitched": {
+  "STATUS_MSG_CAMERA_SWITCHED": {
     "message": "$camera$ செயலிலுள்ளது",
     "description": "Status message for spoken feedback when switching over to another camera.",
     "placeholders": {
@@ -55,131 +55,131 @@
       }
     }
   },
-  "galleryButton": {
+  "GALLERY_BUTTON": {
     "message": "கேலரிக்குச் செல்",
     "description": "Label for the gallery button."
   },
-  "deleteButton": {
+  "DELETE_BUTTON": {
     "message": "நீக்கு",
     "description": "Label for the delete button."
   },
-  "exportButton": {
+  "EXPORT_BUTTON": {
     "message": "வட்டுக்கு இடமாற்று",
     "description": "Label for the exporting button."
   },
-  "printButton": {
+  "PRINT_BUTTON": {
     "message": "அச்சிடு",
     "description": "Label for the printing button."
   },
-  "backButton": {
+  "BACK_BUTTON": {
     "message": "பின்செல்",
     "description": "Label for the back button."
   },
-  "galleryImages": {
+  "GALLERY_IMAGES": {
     "message": "கேலரியிலுள்ள படங்கள்",
     "description": "Text to speech label for the gallery list."
   },
-  "settingsButton": {
+  "SETTINGS_BUTTON": {
     "message": "அமைப்புகள்",
     "description": "Label for the settings button."
   },
-  "gridTypeButton": {
+  "GRID_TYPE_BUTTON": {
     "message": "கட்ட வகை",
     "description": "Label for the button of grid-type options."
   },
-  "timerDurationButton": {
+  "TIMER_DURATION_BUTTON": {
     "message": "டைமர் காலஅளவு",
     "description": "Label for the button of timer-duration options."
   },
-  "feedbackButton": {
+  "FEEDBACK_BUTTON": {
     "message": "கருத்து அனுப்புக",
     "description": "Label for the feedback button."
   },
-  "helpButton": {
+  "HELP_BUTTON": {
     "message": "உதவி",
     "description": "Label for the help button."
   },
-  "labelGrid3x3": {
+  "LABEL_GRID_3X3": {
     "message": "3 x 3",
     "description": "Label for for grid-type: 3x3."
   },
-  "ariaGrid3x3": {
+  "ARIA_GRID_3X3": {
     "message": "3 x 3",
     "description": "Label for spoken feedback to read out grid-type: 3x3."
   },
-  "labelGrid4x4": {
+  "LABEL_GRID_4X4": {
     "message": "4 x 4",
     "description": "Label for for grid-type: 4x4."
   },
-  "ariaGrid4x4": {
+  "ARIA_GRID_4X4": {
     "message": "4 x 4",
     "description": "Label for spoken feedback to read out grid-type: 4x4."
   },
-  "labelGridGolden": {
+  "LABEL_GRID_GOLDEN": {
     "message": "கோல்டன் ரேஷியோ",
     "description": "Label for grid-type: golden ratio."
   },
-  "labelTimer3s": {
+  "LABEL_TIMER_3S": {
     "message": "3 வினாடிகள்",
     "description": "Label for timer-duration: 3 seconds."
   },
-  "labelTimer10s": {
+  "LABEL_TIMER_10S": {
     "message": "10 வினாடிகள்",
     "description": "Label for timer-duration: 10 seconds."
   },
-  "takePhotoButton": {
+  "TAKE_PHOTO_BUTTON": {
     "message": "படமெடு",
     "description": "Label for the shutter button to take photo."
   },
-  "takePhotoCancelButton": {
+  "TAKE_PHOTO_CANCEL_BUTTON": {
     "message": "படமெடுப்பதை நிறுத்து",
     "description": "Label for the shutter button to cancel countdown timer and stop taking photo."
   },
-  "recordVideoStartButton": {
+  "RECORD_VIDEO_START_BUTTON": {
     "message": "ரெக்கார்டு செய்யத் தொடங்கு",
     "description": "Label for the shutter button to start recording."
   },
-  "recordVideoStopButton": {
+  "RECORD_VIDEO_STOP_BUTTON": {
     "message": "ரெக்கார்டு செய்வதை நிறுத்து",
     "description": "Label for the shutter button to stop recording."
   },
-  "switchCameraButton": {
+  "SWITCH_CAMERA_BUTTON": {
     "message": "அடுத்த கேமராவுக்கு மாறு",
     "description": "Label for the button to switch to next connected camera. Eg. switching from front facing to back facing, or a camera connected via USB. The button is shown only when more than one camera is connected."
   },
-  "switchRecordVideoButton": {
+  "SWITCH_RECORD_VIDEO_BUTTON": {
     "message": "வீடியோவை ரெக்கார்டு செய்யும் பயன்முறைக்கு மாறு",
     "description": "Label for the button to switch to record video mode."
   },
-  "switchTakePhotoButton": {
+  "SWITCH_TAKE_PHOTO_BUTTON": {
     "message": "படமெடுக்கும் பயன்முறைக்கு மாறு",
     "description": "Label for the button to switch to take photo mode."
   },
-  "toggleTimerButton": {
+  "TOGGLE_TIMER_BUTTON": {
     "message": "டைமர்",
     "description": "Label for the checkbox to toggle the countdown timer."
   },
-  "toggleMirrorButton": {
+  "TOGGLE_MIRROR_BUTTON": {
     "message": "பிரதிபலித்தல்",
     "description": "Label for the checkbox to toggle the preview mirroring. Eg. if mirroring is toggled on, preview will be flipped horizontally."
   },
-  "toggleGridButton": {
+  "TOGGLE_GRID_BUTTON": {
     "message": "கட்டம்",
     "description": "Label for the checkbox to toggle the grid shown on preview."
   },
-  "toggleMicButton": {
+  "TOGGLE_MIC_BUTTON": {
     "message": "மைக்ரோஃபோன்",
     "description": "Label for the checkbox to toggle the microphone for recording video."
   },
-  "dialogOKButton": {
+  "DIALOG_OK_BUTTON": {
     "message": "சரி",
     "description": "Label for the accepting button in the dialog."
   },
-  "dialogCancelButton": {
+  "DIALOG_CANCEL_BUTTON": {
     "message": "ரத்துசெய்",
     "description": "Label for the dismissing button in the dialog."
   },
-  "deleteConfirmationMsg": {
+  "DELETE_CONFIRMATION_MSG": {
     "message": "$file$ஐ நிச்சயமாக அகற்ற விரும்புகிறீர்களா?",
     "description": "Confirmation message before removing a selected item from the gallery. Expects a file name to be passed in.",
     "placeholders": {
@@ -189,7 +189,7 @@
       }
     }
   },
-  "deleteMultiConfirmationMsg": {
+  "DELETE_MULTI_CONFIRMATION_MSG": {
     "message": "$count$ உருப்படிகளை நிச்சயமாக அகற்ற விரும்புகிறீர்களா?",
     "description": "Confirmation message before removing multiple selected items from the gallery. Expects a file count to be passed in.",
     "placeholders": {
@@ -199,7 +199,7 @@
       }
     }
   },
-  "migratePicturesMsg": {
+  "MIGRATE_PICTURES_MSG": {
     "message": "கேமராவில் எடுக்கப்படும் படங்களும் வீடியோக்களும் ‘பதிவிறக்கங்கள்’ கோப்புறைக்கு நகர்த்தப்படும். அவற்றை ‘Files’ என்பதில் பார்க்கலாம்.\n\nசேமிப்பக அனுமதிகள் உள்ள ஆப்ஸால் உங்கள் படங்களையும் வீடியோக்களையும் அணுக முடியும்.",
     "description": "Message shown before moving all photos and videos stored in the Camera App to the Downloads folder."
   }
diff --git a/chrome/browser/resources/chromeos/camera/src/_locales/te/messages.json b/chrome/browser/resources/chromeos/camera/src/_locales/te/messages.json
index 8930130..8f780f9 100644
--- a/chrome/browser/resources/chromeos/camera/src/_locales/te/messages.json
+++ b/chrome/browser/resources/chromeos/camera/src/_locales/te/messages.json
@@ -1,21 +1,21 @@
 {
-  "name": {
+  "NAME": {
     "message": "కెమెరా",
     "description": "Name of the Camera App."
   },
-  "description": {
+  "DESCRIPTION": {
     "message": "మీ కెమెరాతో ఫోటోలను తీయండి, వీడియోలను రికార్డ్ చేయండి.",
     "description": "Short description of the Camera App."
   },
-  "errorMsgFileSystemFailed": {
+  "ERROR_MSG_FILE_SYSTEM_FAILED": {
     "message": "ఫైల్ సిస్టమ్ ఎర్రర్‌లు.",
     "description": "Error message shown when failing to read or write the file system."
   },
-  "errorMsgNoCamera": {
+  "ERROR_MSG_NO_CAMERA": {
     "message": "మీ కెమెరా ప్రస్తుతం అందుబాటులో లేదు.\nకెమెరా సరిగ్గా కనెక్ట్ చేయబడిందో లేదో తనిఖీ చేయండి.",
     "description": "Error message shown when it was impossible to connect to the camera due to unavailability."
   },
-  "errorMsgGalleryExportFailed": {
+  "ERROR_MSG_GALLERY_EXPORT_FAILED": {
     "message": "$file$ను ఎగుమతి చేయడం సాధ్యం కాలేదు",
     "description": "Error message shown when exporting to an external directory failed. Expects a file name to be passed in.",
     "placeholders": {
@@ -25,27 +25,27 @@
       }
     }
   },
-  "errorMsgSaveFileFailed": {
+  "ERROR_MSG_SAVE_FILE_FAILED": {
     "message": "ఫైల్‌ను సేవ్ చేయడం సాధ్యం కాలేదు",
     "description": "Error message shown when saving/adding a image or video to the file system failed."
   },
-  "errorMsgTakePhotoFailed": {
+  "ERROR_MSG_TAKE_PHOTO_FAILED": {
     "message": "ఫోటోను తీయడం సాధ్యం కాలేదు",
     "description": "Error message shown when failing to take photo."
   },
-  "errorMsgRecordStartFailed": {
+  "ERROR_MSG_RECORD_START_FAILED": {
     "message": "రికార్డింగ్‌ను ప్రారంభించడం సాధ్యం కాలేదు",
     "description": "Error message shown when failing to start recording video."
   },
-  "errorMsgEmptyRecording": {
+  "ERROR_MSG_EMPTY_RECORDING": {
     "message": "ఏదీ రికార్డ్ చేయబడలేదు",
     "description": "Error message shown when no data is recorded for a recording and it won't be added to the gallery."
   },
-  "statusMsgRecordingStopped": {
+  "STATUS_MSG_RECORDING_STOPPED": {
     "message": "రికార్డింగ్ ఆపివేయబడింది",
     "description": "Status message for spoken feedback when video recording has been stopped."
   },
-  "statusMsgCameraSwitched": {
+  "STATUS_MSG_CAMERA_SWITCHED": {
     "message": "$camera$ యాక్టివ్‌గా ఉంది",
     "description": "Status message for spoken feedback when switching over to another camera.",
     "placeholders": {
@@ -55,131 +55,131 @@
       }
     }
   },
-  "galleryButton": {
+  "GALLERY_BUTTON": {
     "message": "గ్యాలరీకి వెళ్లు",
     "description": "Label for the gallery button."
   },
-  "deleteButton": {
+  "DELETE_BUTTON": {
     "message": "తొలగించు",
     "description": "Label for the delete button."
   },
-  "exportButton": {
+  "EXPORT_BUTTON": {
     "message": "డిస్క్‌కి ఎగుమతి చేయి",
     "description": "Label for the exporting button."
   },
-  "printButton": {
+  "PRINT_BUTTON": {
     "message": "ముద్రించు",
     "description": "Label for the printing button."
   },
-  "backButton": {
+  "BACK_BUTTON": {
     "message": "వెనుకకు వెళ్లు",
     "description": "Label for the back button."
   },
-  "galleryImages": {
+  "GALLERY_IMAGES": {
     "message": "గ్యాలరీ చిత్రాలు",
     "description": "Text to speech label for the gallery list."
   },
-  "settingsButton": {
+  "SETTINGS_BUTTON": {
     "message": "సెట్టింగ్‌లు",
     "description": "Label for the settings button."
   },
-  "gridTypeButton": {
+  "GRID_TYPE_BUTTON": {
     "message": "గ్రిడ్ రకం",
     "description": "Label for the button of grid-type options."
   },
-  "timerDurationButton": {
+  "TIMER_DURATION_BUTTON": {
     "message": "టైమర్ వ్యవధి",
     "description": "Label for the button of timer-duration options."
   },
-  "feedbackButton": {
+  "FEEDBACK_BUTTON": {
     "message": "అభిప్రాయాన్ని పంపు",
     "description": "Label for the feedback button."
   },
-  "helpButton": {
+  "HELP_BUTTON": {
     "message": "సహాయం",
     "description": "Label for the help button."
   },
-  "labelGrid3x3": {
+  "LABEL_GRID_3X3": {
     "message": "3 x 3",
     "description": "Label for for grid-type: 3x3."
   },
-  "ariaGrid3x3": {
+  "ARIA_GRID_3X3": {
     "message": "3 x 3",
     "description": "Label for spoken feedback to read out grid-type: 3x3."
   },
-  "labelGrid4x4": {
+  "LABEL_GRID_4X4": {
     "message": "4 x 4",
     "description": "Label for for grid-type: 4x4."
   },
-  "ariaGrid4x4": {
+  "ARIA_GRID_4X4": {
     "message": "4 x 4",
     "description": "Label for spoken feedback to read out grid-type: 4x4."
   },
-  "labelGridGolden": {
+  "LABEL_GRID_GOLDEN": {
     "message": "గోల్డెన్ రేషియో‌",
     "description": "Label for grid-type: golden ratio."
   },
-  "labelTimer3s": {
+  "LABEL_TIMER_3S": {
     "message": "3 సెకన్లు",
     "description": "Label for timer-duration: 3 seconds."
   },
-  "labelTimer10s": {
+  "LABEL_TIMER_10S": {
     "message": "10 సెకన్లు",
     "description": "Label for timer-duration: 10 seconds."
   },
-  "takePhotoButton": {
+  "TAKE_PHOTO_BUTTON": {
     "message": "ఫోటోను తీయి",
     "description": "Label for the shutter button to take photo."
   },
-  "takePhotoCancelButton": {
+  "TAKE_PHOTO_CANCEL_BUTTON": {
     "message": "ఫోటోను తీయడం ఆపివేయి",
     "description": "Label for the shutter button to cancel countdown timer and stop taking photo."
   },
-  "recordVideoStartButton": {
+  "RECORD_VIDEO_START_BUTTON": {
     "message": "రికార్డింగ్‌ను ప్రారంభించు",
     "description": "Label for the shutter button to start recording."
   },
-  "recordVideoStopButton": {
+  "RECORD_VIDEO_STOP_BUTTON": {
     "message": "రికార్డ్ చేయడం ఆపివేయి",
     "description": "Label for the shutter button to stop recording."
   },
-  "switchCameraButton": {
+  "SWITCH_CAMERA_BUTTON": {
     "message": "తర్వాతి కెమెరాకు మారండి",
     "description": "Label for the button to switch to next connected camera. Eg. switching from front facing to back facing, or a camera connected via USB. The button is shown only when more than one camera is connected."
   },
-  "switchRecordVideoButton": {
+  "SWITCH_RECORD_VIDEO_BUTTON": {
     "message": "వీడియో రికార్డింగ్ మోడ్‌కు మారండి",
     "description": "Label for the button to switch to record video mode."
   },
-  "switchTakePhotoButton": {
+  "SWITCH_TAKE_PHOTO_BUTTON": {
     "message": "ఫోటో మోడ్‌కు మారండి",
     "description": "Label for the button to switch to take photo mode."
   },
-  "toggleTimerButton": {
+  "TOGGLE_TIMER_BUTTON": {
     "message": "టైమర్",
     "description": "Label for the checkbox to toggle the countdown timer."
   },
-  "toggleMirrorButton": {
+  "TOGGLE_MIRROR_BUTTON": {
     "message": "మిర్రరింగ్",
     "description": "Label for the checkbox to toggle the preview mirroring. Eg. if mirroring is toggled on, preview will be flipped horizontally."
   },
-  "toggleGridButton": {
+  "TOGGLE_GRID_BUTTON": {
     "message": "గ్రిడ్",
     "description": "Label for the checkbox to toggle the grid shown on preview."
   },
-  "toggleMicButton": {
+  "TOGGLE_MIC_BUTTON": {
     "message": "మైక్రోఫోన్",
     "description": "Label for the checkbox to toggle the microphone for recording video."
   },
-  "dialogOKButton": {
+  "DIALOG_OK_BUTTON": {
     "message": "సరే",
     "description": "Label for the accepting button in the dialog."
   },
-  "dialogCancelButton": {
+  "DIALOG_CANCEL_BUTTON": {
     "message": "రద్దు చేయి",
     "description": "Label for the dismissing button in the dialog."
   },
-  "deleteConfirmationMsg": {
+  "DELETE_CONFIRMATION_MSG": {
     "message": "మీరు $file$ని నిజంగా తీసివేయాలనుకుంటున్నారా?",
     "description": "Confirmation message before removing a selected item from the gallery. Expects a file name to be passed in.",
     "placeholders": {
@@ -189,7 +189,7 @@
       }
     }
   },
-  "deleteMultiConfirmationMsg": {
+  "DELETE_MULTI_CONFIRMATION_MSG": {
     "message": "మీరు $count$ అంశాలను నిజంగా తీసివేయాలనుకుంటున్నారా?",
     "description": "Confirmation message before removing multiple selected items from the gallery. Expects a file count to be passed in.",
     "placeholders": {
@@ -199,7 +199,7 @@
       }
     }
   },
-  "migratePicturesMsg": {
+  "MIGRATE_PICTURES_MSG": {
     "message": "కెమెరాతో తీసిన ఫోటోలు మరియు వీడియోలు, డౌన్‌లోడ్‌లు ఫోల్డర్‌కు తరలించబడతాయి. మీరు వాటిని ఫైల్స్‌లో యాక్సెస్ చేయవచ్చు. నిల్వ అనుమతులు కలిగిన యాప్‌లు మీ ఫోటోలు మరియు వీడియోలను యాక్సెస్ చేయగలుగుతాయి.",
     "description": "Message shown before moving all photos and videos stored in the Camera App to the Downloads folder."
   }
diff --git a/chrome/browser/resources/chromeos/camera/src/_locales/th/messages.json b/chrome/browser/resources/chromeos/camera/src/_locales/th/messages.json
index 87e4017..72e6885 100644
--- a/chrome/browser/resources/chromeos/camera/src/_locales/th/messages.json
+++ b/chrome/browser/resources/chromeos/camera/src/_locales/th/messages.json
@@ -1,21 +1,21 @@
 {
-  "name": {
+  "NAME": {
     "message": "กล้อง",
     "description": "Name of the Camera App."
   },
-  "description": {
+  "DESCRIPTION": {
     "message": "ถ่ายภาพและบันทึกวิดีโอด้วยกล้อง",
     "description": "Short description of the Camera App."
   },
-  "errorMsgFileSystemFailed": {
+  "ERROR_MSG_FILE_SYSTEM_FAILED": {
     "message": "ข้อผิดพลาดเกี่ยวกับระบบไฟล์",
     "description": "Error message shown when failing to read or write the file system."
   },
-  "errorMsgNoCamera": {
+  "ERROR_MSG_NO_CAMERA": {
     "message": "ขณะนี้กล้องไม่พร้อมใช้งาน\nโปรดตรวจสอบว่ากล้องเชื่อมต่ออย่างถูกต้อง",
     "description": "Error message shown when it was impossible to connect to the camera due to unavailability."
   },
-  "errorMsgGalleryExportFailed": {
+  "ERROR_MSG_GALLERY_EXPORT_FAILED": {
     "message": "ส่งออก $file$ ไม่ได้",
     "description": "Error message shown when exporting to an external directory failed. Expects a file name to be passed in.",
     "placeholders": {
@@ -25,27 +25,27 @@
       }
     }
   },
-  "errorMsgSaveFileFailed": {
+  "ERROR_MSG_SAVE_FILE_FAILED": {
     "message": "บันทึกไฟล์ไม่ได้",
     "description": "Error message shown when saving/adding a image or video to the file system failed."
   },
-  "errorMsgTakePhotoFailed": {
+  "ERROR_MSG_TAKE_PHOTO_FAILED": {
     "message": "ถ่ายภาพไม่ได้",
     "description": "Error message shown when failing to take photo."
   },
-  "errorMsgRecordStartFailed": {
+  "ERROR_MSG_RECORD_START_FAILED": {
     "message": "เริ่มบันทึกวิดีโอไม่ได้",
     "description": "Error message shown when failing to start recording video."
   },
-  "errorMsgEmptyRecording": {
+  "ERROR_MSG_EMPTY_RECORDING": {
     "message": "ไม่ได้บันทึกข้อมูลใด",
     "description": "Error message shown when no data is recorded for a recording and it won't be added to the gallery."
   },
-  "statusMsgRecordingStopped": {
+  "STATUS_MSG_RECORDING_STOPPED": {
     "message": "หยุดบันทึกวิดีโอแล้ว",
     "description": "Status message for spoken feedback when video recording has been stopped."
   },
-  "statusMsgCameraSwitched": {
+  "STATUS_MSG_CAMERA_SWITCHED": {
     "message": "$camera$ ทำงาน",
     "description": "Status message for spoken feedback when switching over to another camera.",
     "placeholders": {
@@ -55,131 +55,131 @@
       }
     }
   },
-  "galleryButton": {
+  "GALLERY_BUTTON": {
     "message": "ไปที่แกลเลอรี",
     "description": "Label for the gallery button."
   },
-  "deleteButton": {
+  "DELETE_BUTTON": {
     "message": "ลบ",
     "description": "Label for the delete button."
   },
-  "exportButton": {
+  "EXPORT_BUTTON": {
     "message": "ส่งออกไปยังดิสก์",
     "description": "Label for the exporting button."
   },
-  "printButton": {
+  "PRINT_BUTTON": {
     "message": "พิมพ์",
     "description": "Label for the printing button."
   },
-  "backButton": {
+  "BACK_BUTTON": {
     "message": "กลับ",
     "description": "Label for the back button."
   },
-  "galleryImages": {
+  "GALLERY_IMAGES": {
     "message": "รูปภาพในแกลเลอรี",
     "description": "Text to speech label for the gallery list."
   },
-  "settingsButton": {
+  "SETTINGS_BUTTON": {
     "message": "การตั้งค่า",
     "description": "Label for the settings button."
   },
-  "gridTypeButton": {
+  "GRID_TYPE_BUTTON": {
     "message": "ประเภทตารางกริด",
     "description": "Label for the button of grid-type options."
   },
-  "timerDurationButton": {
+  "TIMER_DURATION_BUTTON": {
     "message": "ระยะเวลาของตัวจับเวลา",
     "description": "Label for the button of timer-duration options."
   },
-  "feedbackButton": {
+  "FEEDBACK_BUTTON": {
     "message": "ส่งความคิดเห็น",
     "description": "Label for the feedback button."
   },
-  "helpButton": {
+  "HELP_BUTTON": {
     "message": "ความช่วยเหลือ",
     "description": "Label for the help button."
   },
-  "labelGrid3x3": {
+  "LABEL_GRID_3X3": {
     "message": "3 x 3",
     "description": "Label for for grid-type: 3x3."
   },
-  "ariaGrid3x3": {
+  "ARIA_GRID_3X3": {
     "message": "3 x 3",
     "description": "Label for spoken feedback to read out grid-type: 3x3."
   },
-  "labelGrid4x4": {
+  "LABEL_GRID_4X4": {
     "message": "4 x 4",
     "description": "Label for for grid-type: 4x4."
   },
-  "ariaGrid4x4": {
+  "ARIA_GRID_4X4": {
     "message": "4 x 4",
     "description": "Label for spoken feedback to read out grid-type: 4x4."
   },
-  "labelGridGolden": {
+  "LABEL_GRID_GOLDEN": {
     "message": "อัตราส่วนทองคำ",
     "description": "Label for grid-type: golden ratio."
   },
-  "labelTimer3s": {
+  "LABEL_TIMER_3S": {
     "message": "3 วินาที",
     "description": "Label for timer-duration: 3 seconds."
   },
-  "labelTimer10s": {
+  "LABEL_TIMER_10S": {
     "message": "10 วินาที",
     "description": "Label for timer-duration: 10 seconds."
   },
-  "takePhotoButton": {
+  "TAKE_PHOTO_BUTTON": {
     "message": "ถ่ายภาพ",
     "description": "Label for the shutter button to take photo."
   },
-  "takePhotoCancelButton": {
+  "TAKE_PHOTO_CANCEL_BUTTON": {
     "message": "หยุดถ่ายภาพ",
     "description": "Label for the shutter button to cancel countdown timer and stop taking photo."
   },
-  "recordVideoStartButton": {
+  "RECORD_VIDEO_START_BUTTON": {
     "message": "เริ่มบันทึก",
     "description": "Label for the shutter button to start recording."
   },
-  "recordVideoStopButton": {
+  "RECORD_VIDEO_STOP_BUTTON": {
     "message": "หยุดบันทึก",
     "description": "Label for the shutter button to stop recording."
   },
-  "switchCameraButton": {
+  "SWITCH_CAMERA_BUTTON": {
     "message": "เปลี่ยนไปใช้กล้องถัดไป",
     "description": "Label for the button to switch to next connected camera. Eg. switching from front facing to back facing, or a camera connected via USB. The button is shown only when more than one camera is connected."
   },
-  "switchRecordVideoButton": {
+  "SWITCH_RECORD_VIDEO_BUTTON": {
     "message": "เปลี่ยนเป็นโหมดบันทึกวิดีโอ",
     "description": "Label for the button to switch to record video mode."
   },
-  "switchTakePhotoButton": {
+  "SWITCH_TAKE_PHOTO_BUTTON": {
     "message": "เปลี่ยนเป็นโหมดถ่ายภาพ",
     "description": "Label for the button to switch to take photo mode."
   },
-  "toggleTimerButton": {
+  "TOGGLE_TIMER_BUTTON": {
     "message": "ตัวจับเวลา",
     "description": "Label for the checkbox to toggle the countdown timer."
   },
-  "toggleMirrorButton": {
+  "TOGGLE_MIRROR_BUTTON": {
     "message": "การมิเรอร์",
     "description": "Label for the checkbox to toggle the preview mirroring. Eg. if mirroring is toggled on, preview will be flipped horizontally."
   },
-  "toggleGridButton": {
+  "TOGGLE_GRID_BUTTON": {
     "message": "ตารางกริด",
     "description": "Label for the checkbox to toggle the grid shown on preview."
   },
-  "toggleMicButton": {
+  "TOGGLE_MIC_BUTTON": {
     "message": "ไมโครโฟน",
     "description": "Label for the checkbox to toggle the microphone for recording video."
   },
-  "dialogOKButton": {
+  "DIALOG_OK_BUTTON": {
     "message": "ตกลง",
     "description": "Label for the accepting button in the dialog."
   },
-  "dialogCancelButton": {
+  "DIALOG_CANCEL_BUTTON": {
     "message": "ยกเลิก",
     "description": "Label for the dismissing button in the dialog."
   },
-  "deleteConfirmationMsg": {
+  "DELETE_CONFIRMATION_MSG": {
     "message": "คุณต้องการนำ $file$ ออกจริงๆ ใช่ไหม",
     "description": "Confirmation message before removing a selected item from the gallery. Expects a file name to be passed in.",
     "placeholders": {
@@ -189,7 +189,7 @@
       }
     }
   },
-  "deleteMultiConfirmationMsg": {
+  "DELETE_MULTI_CONFIRMATION_MSG": {
     "message": "คุณต้องการนำ $count$ รายการออกจริงๆ ใช่ไหม",
     "description": "Confirmation message before removing multiple selected items from the gallery. Expects a file count to be passed in.",
     "placeholders": {
@@ -199,7 +199,7 @@
       }
     }
   },
-  "migratePicturesMsg": {
+  "MIGRATE_PICTURES_MSG": {
     "message": "รูปภาพและวิดีโอที่ถ่ายจากกล้องจะย้ายไปยังโฟลเดอร์ \"ดาวน์โหลด\" คุณจะเข้าถึงรายการเหล่านี้ได้ในแอป Files\n\nแอปที่มีสิทธิ์ในพื้นที่เก็บข้อมูลจะเข้าถึงรูปภาพและวิดีโอของคุณได้",
     "description": "Message shown before moving all photos and videos stored in the Camera App to the Downloads folder."
   }
diff --git a/chrome/browser/resources/chromeos/camera/src/_locales/tr/messages.json b/chrome/browser/resources/chromeos/camera/src/_locales/tr/messages.json
index fc93ecc..352ab165f 100644
--- a/chrome/browser/resources/chromeos/camera/src/_locales/tr/messages.json
+++ b/chrome/browser/resources/chromeos/camera/src/_locales/tr/messages.json
@@ -1,21 +1,21 @@
 {
-  "name": {
+  "NAME": {
     "message": "Kamera",
     "description": "Name of the Camera App."
   },
-  "description": {
+  "DESCRIPTION": {
     "message": "Kameranızla fotoğraf çekin ve video kaydedin.",
     "description": "Short description of the Camera App."
   },
-  "errorMsgFileSystemFailed": {
+  "ERROR_MSG_FILE_SYSTEM_FAILED": {
     "message": "Dosya sistemi hataları.",
     "description": "Error message shown when failing to read or write the file system."
   },
-  "errorMsgNoCamera": {
+  "ERROR_MSG_NO_CAMERA": {
     "message": "Kameranız şu anda kullanılamıyor.\nLütfen kameranın bağlı olup olmadığını kontrol edin.",
     "description": "Error message shown when it was impossible to connect to the camera due to unavailability."
   },
-  "errorMsgGalleryExportFailed": {
+  "ERROR_MSG_GALLERY_EXPORT_FAILED": {
     "message": "$file$ dışa aktarılamıyor.",
     "description": "Error message shown when exporting to an external directory failed. Expects a file name to be passed in.",
     "placeholders": {
@@ -25,27 +25,27 @@
       }
     }
   },
-  "errorMsgSaveFileFailed": {
+  "ERROR_MSG_SAVE_FILE_FAILED": {
     "message": "Dosya kaydedilemiyor",
     "description": "Error message shown when saving/adding a image or video to the file system failed."
   },
-  "errorMsgTakePhotoFailed": {
+  "ERROR_MSG_TAKE_PHOTO_FAILED": {
     "message": "Fotoğraf çekilemiyor",
     "description": "Error message shown when failing to take photo."
   },
-  "errorMsgRecordStartFailed": {
+  "ERROR_MSG_RECORD_START_FAILED": {
     "message": "Kayıt başlatılamıyor",
     "description": "Error message shown when failing to start recording video."
   },
-  "errorMsgEmptyRecording": {
+  "ERROR_MSG_EMPTY_RECORDING": {
     "message": "Hiçbir şey kaydedilmedi",
     "description": "Error message shown when no data is recorded for a recording and it won't be added to the gallery."
   },
-  "statusMsgRecordingStopped": {
+  "STATUS_MSG_RECORDING_STOPPED": {
     "message": "Kayıt durduruldu",
     "description": "Status message for spoken feedback when video recording has been stopped."
   },
-  "statusMsgCameraSwitched": {
+  "STATUS_MSG_CAMERA_SWITCHED": {
     "message": "$camera$ etkin",
     "description": "Status message for spoken feedback when switching over to another camera.",
     "placeholders": {
@@ -55,131 +55,131 @@
       }
     }
   },
-  "galleryButton": {
+  "GALLERY_BUTTON": {
     "message": "Galeriye git",
     "description": "Label for the gallery button."
   },
-  "deleteButton": {
+  "DELETE_BUTTON": {
     "message": "Sil",
     "description": "Label for the delete button."
   },
-  "exportButton": {
+  "EXPORT_BUTTON": {
     "message": "Diske aktar",
     "description": "Label for the exporting button."
   },
-  "printButton": {
+  "PRINT_BUTTON": {
     "message": "Yazdır",
     "description": "Label for the printing button."
   },
-  "backButton": {
+  "BACK_BUTTON": {
     "message": "Geri dön",
     "description": "Label for the back button."
   },
-  "galleryImages": {
+  "GALLERY_IMAGES": {
     "message": "Galeri resimleri",
     "description": "Text to speech label for the gallery list."
   },
-  "settingsButton": {
+  "SETTINGS_BUTTON": {
     "message": "Ayarlar",
     "description": "Label for the settings button."
   },
-  "gridTypeButton": {
+  "GRID_TYPE_BUTTON": {
     "message": "Kılavuz türü",
     "description": "Label for the button of grid-type options."
   },
-  "timerDurationButton": {
+  "TIMER_DURATION_BUTTON": {
     "message": "Zamanlayıcı süresi",
     "description": "Label for the button of timer-duration options."
   },
-  "feedbackButton": {
+  "FEEDBACK_BUTTON": {
     "message": "Geri bildirim gönder",
     "description": "Label for the feedback button."
   },
-  "helpButton": {
+  "HELP_BUTTON": {
     "message": "Yardım",
     "description": "Label for the help button."
   },
-  "labelGrid3x3": {
+  "LABEL_GRID_3X3": {
     "message": "3 x 3",
     "description": "Label for for grid-type: 3x3."
   },
-  "ariaGrid3x3": {
+  "ARIA_GRID_3X3": {
     "message": "3'e 3",
     "description": "Label for spoken feedback to read out grid-type: 3x3."
   },
-  "labelGrid4x4": {
+  "LABEL_GRID_4X4": {
     "message": "4 x 4",
     "description": "Label for for grid-type: 4x4."
   },
-  "ariaGrid4x4": {
+  "ARIA_GRID_4X4": {
     "message": "4'e 4",
     "description": "Label for spoken feedback to read out grid-type: 4x4."
   },
-  "labelGridGolden": {
+  "LABEL_GRID_GOLDEN": {
     "message": "Altın oran",
     "description": "Label for grid-type: golden ratio."
   },
-  "labelTimer3s": {
+  "LABEL_TIMER_3S": {
     "message": "3 saniye",
     "description": "Label for timer-duration: 3 seconds."
   },
-  "labelTimer10s": {
+  "LABEL_TIMER_10S": {
     "message": "10 saniye",
     "description": "Label for timer-duration: 10 seconds."
   },
-  "takePhotoButton": {
+  "TAKE_PHOTO_BUTTON": {
     "message": "Fotoğraf çek",
     "description": "Label for the shutter button to take photo."
   },
-  "takePhotoCancelButton": {
+  "TAKE_PHOTO_CANCEL_BUTTON": {
     "message": "Fotoğraf çekmeyi durdur",
     "description": "Label for the shutter button to cancel countdown timer and stop taking photo."
   },
-  "recordVideoStartButton": {
+  "RECORD_VIDEO_START_BUTTON": {
     "message": "Kaydı başlat",
     "description": "Label for the shutter button to start recording."
   },
-  "recordVideoStopButton": {
+  "RECORD_VIDEO_STOP_BUTTON": {
     "message": "Kaydı durdur",
     "description": "Label for the shutter button to stop recording."
   },
-  "switchCameraButton": {
+  "SWITCH_CAMERA_BUTTON": {
     "message": "Sonraki kameraya geç",
     "description": "Label for the button to switch to next connected camera. Eg. switching from front facing to back facing, or a camera connected via USB. The button is shown only when more than one camera is connected."
   },
-  "switchRecordVideoButton": {
+  "SWITCH_RECORD_VIDEO_BUTTON": {
     "message": "Video kaydetmeye geç",
     "description": "Label for the button to switch to record video mode."
   },
-  "switchTakePhotoButton": {
+  "SWITCH_TAKE_PHOTO_BUTTON": {
     "message": "Fotoğraf çekmeye geç",
     "description": "Label for the button to switch to take photo mode."
   },
-  "toggleTimerButton": {
+  "TOGGLE_TIMER_BUTTON": {
     "message": "Zamanlayıcı",
     "description": "Label for the checkbox to toggle the countdown timer."
   },
-  "toggleMirrorButton": {
+  "TOGGLE_MIRROR_BUTTON": {
     "message": "Yansıtma",
     "description": "Label for the checkbox to toggle the preview mirroring. Eg. if mirroring is toggled on, preview will be flipped horizontally."
   },
-  "toggleGridButton": {
+  "TOGGLE_GRID_BUTTON": {
     "message": "Kılavuz",
     "description": "Label for the checkbox to toggle the grid shown on preview."
   },
-  "toggleMicButton": {
+  "TOGGLE_MIC_BUTTON": {
     "message": "Mikrofon",
     "description": "Label for the checkbox to toggle the microphone for recording video."
   },
-  "dialogOKButton": {
+  "DIALOG_OK_BUTTON": {
     "message": "Tamam",
     "description": "Label for the accepting button in the dialog."
   },
-  "dialogCancelButton": {
+  "DIALOG_CANCEL_BUTTON": {
     "message": "İptal",
     "description": "Label for the dismissing button in the dialog."
   },
-  "deleteConfirmationMsg": {
+  "DELETE_CONFIRMATION_MSG": {
     "message": "$file$ adlı dosyayı gerçekten kaldırmak istiyor musunuz?",
     "description": "Confirmation message before removing a selected item from the gallery. Expects a file name to be passed in.",
     "placeholders": {
@@ -189,7 +189,7 @@
       }
     }
   },
-  "deleteMultiConfirmationMsg": {
+  "DELETE_MULTI_CONFIRMATION_MSG": {
     "message": "$count$ öğeyi gerçekten kaldırmak istiyor musunuz?",
     "description": "Confirmation message before removing multiple selected items from the gallery. Expects a file count to be passed in.",
     "placeholders": {
@@ -199,7 +199,7 @@
       }
     }
   },
-  "migratePicturesMsg": {
+  "MIGRATE_PICTURES_MSG": {
     "message": "Kamerayla çekilen fotoğraflar ve videolar, İndirilenler klasörüne taşınacaktır. Bunlara Dosyalar uygulamasından erişebilirsiniz.\n\nDepolama iznine sahip uygulamalar fotoğraflarınıza ve videolarınıza erişebilecektir.",
     "description": "Message shown before moving all photos and videos stored in the Camera App to the Downloads folder."
   }
diff --git a/chrome/browser/resources/chromeos/camera/src/_locales/uk/messages.json b/chrome/browser/resources/chromeos/camera/src/_locales/uk/messages.json
index 5b527fee..0e10110 100644
--- a/chrome/browser/resources/chromeos/camera/src/_locales/uk/messages.json
+++ b/chrome/browser/resources/chromeos/camera/src/_locales/uk/messages.json
@@ -1,21 +1,21 @@
 {
-  "name": {
+  "NAME": {
     "message": "Камера",
     "description": "Name of the Camera App."
   },
-  "description": {
+  "DESCRIPTION": {
     "message": "Фотографуйте й записуйте відео камерою.",
     "description": "Short description of the Camera App."
   },
-  "errorMsgFileSystemFailed": {
+  "ERROR_MSG_FILE_SYSTEM_FAILED": {
     "message": "Помилки файлової системи.",
     "description": "Error message shown when failing to read or write the file system."
   },
-  "errorMsgNoCamera": {
+  "ERROR_MSG_NO_CAMERA": {
     "message": "Камера недоступна.\nПеревірте, чи її правильно під’єднано.",
     "description": "Error message shown when it was impossible to connect to the camera due to unavailability."
   },
-  "errorMsgGalleryExportFailed": {
+  "ERROR_MSG_GALLERY_EXPORT_FAILED": {
     "message": "Не вдалось експортувати файл $file$",
     "description": "Error message shown when exporting to an external directory failed. Expects a file name to be passed in.",
     "placeholders": {
@@ -25,27 +25,27 @@
       }
     }
   },
-  "errorMsgSaveFileFailed": {
+  "ERROR_MSG_SAVE_FILE_FAILED": {
     "message": "Не вдалося зберегти файл",
     "description": "Error message shown when saving/adding a image or video to the file system failed."
   },
-  "errorMsgTakePhotoFailed": {
+  "ERROR_MSG_TAKE_PHOTO_FAILED": {
     "message": "Не вдалося сфотографувати",
     "description": "Error message shown when failing to take photo."
   },
-  "errorMsgRecordStartFailed": {
+  "ERROR_MSG_RECORD_START_FAILED": {
     "message": "Не вдалося почати запис",
     "description": "Error message shown when failing to start recording video."
   },
-  "errorMsgEmptyRecording": {
+  "ERROR_MSG_EMPTY_RECORDING": {
     "message": "Нічого не записано",
     "description": "Error message shown when no data is recorded for a recording and it won't be added to the gallery."
   },
-  "statusMsgRecordingStopped": {
+  "STATUS_MSG_RECORDING_STOPPED": {
     "message": "Запис припинено",
     "description": "Status message for spoken feedback when video recording has been stopped."
   },
-  "statusMsgCameraSwitched": {
+  "STATUS_MSG_CAMERA_SWITCHED": {
     "message": "Камера $camera$ активна",
     "description": "Status message for spoken feedback when switching over to another camera.",
     "placeholders": {
@@ -55,131 +55,131 @@
       }
     }
   },
-  "galleryButton": {
+  "GALLERY_BUTTON": {
     "message": "Перейти в галерею",
     "description": "Label for the gallery button."
   },
-  "deleteButton": {
+  "DELETE_BUTTON": {
     "message": "Видалити",
     "description": "Label for the delete button."
   },
-  "exportButton": {
+  "EXPORT_BUTTON": {
     "message": "Експортувати на диск",
     "description": "Label for the exporting button."
   },
-  "printButton": {
+  "PRINT_BUTTON": {
     "message": "Друкувати",
     "description": "Label for the printing button."
   },
-  "backButton": {
+  "BACK_BUTTON": {
     "message": "Назад",
     "description": "Label for the back button."
   },
-  "galleryImages": {
+  "GALLERY_IMAGES": {
     "message": "Зображення в галереї",
     "description": "Text to speech label for the gallery list."
   },
-  "settingsButton": {
+  "SETTINGS_BUTTON": {
     "message": "Налаштування",
     "description": "Label for the settings button."
   },
-  "gridTypeButton": {
+  "GRID_TYPE_BUTTON": {
     "message": "Тип сітки",
     "description": "Label for the button of grid-type options."
   },
-  "timerDurationButton": {
+  "TIMER_DURATION_BUTTON": {
     "message": "Тривалість таймера",
     "description": "Label for the button of timer-duration options."
   },
-  "feedbackButton": {
+  "FEEDBACK_BUTTON": {
     "message": "Надіслати відгук",
     "description": "Label for the feedback button."
   },
-  "helpButton": {
+  "HELP_BUTTON": {
     "message": "Довідка",
     "description": "Label for the help button."
   },
-  "labelGrid3x3": {
+  "LABEL_GRID_3X3": {
     "message": "3 x 3",
     "description": "Label for for grid-type: 3x3."
   },
-  "ariaGrid3x3": {
+  "ARIA_GRID_3X3": {
     "message": "3 на 3",
     "description": "Label for spoken feedback to read out grid-type: 3x3."
   },
-  "labelGrid4x4": {
+  "LABEL_GRID_4X4": {
     "message": "4 x 4",
     "description": "Label for for grid-type: 4x4."
   },
-  "ariaGrid4x4": {
+  "ARIA_GRID_4X4": {
     "message": "4 на 4",
     "description": "Label for spoken feedback to read out grid-type: 4x4."
   },
-  "labelGridGolden": {
+  "LABEL_GRID_GOLDEN": {
     "message": "Золотий перетин",
     "description": "Label for grid-type: golden ratio."
   },
-  "labelTimer3s": {
+  "LABEL_TIMER_3S": {
     "message": "3 секунди",
     "description": "Label for timer-duration: 3 seconds."
   },
-  "labelTimer10s": {
+  "LABEL_TIMER_10S": {
     "message": "10 секунд",
     "description": "Label for timer-duration: 10 seconds."
   },
-  "takePhotoButton": {
+  "TAKE_PHOTO_BUTTON": {
     "message": "Сфотографувати",
     "description": "Label for the shutter button to take photo."
   },
-  "takePhotoCancelButton": {
+  "TAKE_PHOTO_CANCEL_BUTTON": {
     "message": "Припинити фотографувати",
     "description": "Label for the shutter button to cancel countdown timer and stop taking photo."
   },
-  "recordVideoStartButton": {
+  "RECORD_VIDEO_START_BUTTON": {
     "message": "Почати запис",
     "description": "Label for the shutter button to start recording."
   },
-  "recordVideoStopButton": {
+  "RECORD_VIDEO_STOP_BUTTON": {
     "message": "Припинити запис",
     "description": "Label for the shutter button to stop recording."
   },
-  "switchCameraButton": {
+  "SWITCH_CAMERA_BUTTON": {
     "message": "Перемкнутися на наступну камеру",
     "description": "Label for the button to switch to next connected camera. Eg. switching from front facing to back facing, or a camera connected via USB. The button is shown only when more than one camera is connected."
   },
-  "switchRecordVideoButton": {
+  "SWITCH_RECORD_VIDEO_BUTTON": {
     "message": "Перейти в режим запису відео",
     "description": "Label for the button to switch to record video mode."
   },
-  "switchTakePhotoButton": {
+  "SWITCH_TAKE_PHOTO_BUTTON": {
     "message": "Перейти в режим фотозйомки",
     "description": "Label for the button to switch to take photo mode."
   },
-  "toggleTimerButton": {
+  "TOGGLE_TIMER_BUTTON": {
     "message": "Таймер",
     "description": "Label for the checkbox to toggle the countdown timer."
   },
-  "toggleMirrorButton": {
+  "TOGGLE_MIRROR_BUTTON": {
     "message": "Дзеркальне відображення",
     "description": "Label for the checkbox to toggle the preview mirroring. Eg. if mirroring is toggled on, preview will be flipped horizontally."
   },
-  "toggleGridButton": {
+  "TOGGLE_GRID_BUTTON": {
     "message": "Сітка",
     "description": "Label for the checkbox to toggle the grid shown on preview."
   },
-  "toggleMicButton": {
+  "TOGGLE_MIC_BUTTON": {
     "message": "Мікрофон",
     "description": "Label for the checkbox to toggle the microphone for recording video."
   },
-  "dialogOKButton": {
+  "DIALOG_OK_BUTTON": {
     "message": "OK",
     "description": "Label for the accepting button in the dialog."
   },
-  "dialogCancelButton": {
+  "DIALOG_CANCEL_BUTTON": {
     "message": "Скасувати",
     "description": "Label for the dismissing button in the dialog."
   },
-  "deleteConfirmationMsg": {
+  "DELETE_CONFIRMATION_MSG": {
     "message": "Видалити файл $file$?",
     "description": "Confirmation message before removing a selected item from the gallery. Expects a file name to be passed in.",
     "placeholders": {
@@ -189,7 +189,7 @@
       }
     }
   },
-  "deleteMultiConfirmationMsg": {
+  "DELETE_MULTI_CONFIRMATION_MSG": {
     "message": "Видалити елементи ($count$)?",
     "description": "Confirmation message before removing multiple selected items from the gallery. Expects a file count to be passed in.",
     "placeholders": {
@@ -199,7 +199,7 @@
       }
     }
   },
-  "migratePicturesMsg": {
+  "MIGRATE_PICTURES_MSG": {
     "message": "Фото й відео з камери перенесуться в папку \"Завантаження\", і ви зможете відкрити їх у Файлах.\n\nТакож до них матимуть доступ додатки, яким дозволено використовувати пам’ять пристрою.",
     "description": "Message shown before moving all photos and videos stored in the Camera App to the Downloads folder."
   }
diff --git a/chrome/browser/resources/chromeos/camera/src/_locales/vi/messages.json b/chrome/browser/resources/chromeos/camera/src/_locales/vi/messages.json
index 66743d0..b1066fc 100644
--- a/chrome/browser/resources/chromeos/camera/src/_locales/vi/messages.json
+++ b/chrome/browser/resources/chromeos/camera/src/_locales/vi/messages.json
@@ -1,21 +1,21 @@
 {
-  "name": {
+  "NAME": {
     "message": "Máy ảnh",
     "description": "Name of the Camera App."
   },
-  "description": {
+  "DESCRIPTION": {
     "message": "Chụp ảnh và quay video bằng máy ảnh của bạn.",
     "description": "Short description of the Camera App."
   },
-  "errorMsgFileSystemFailed": {
+  "ERROR_MSG_FILE_SYSTEM_FAILED": {
     "message": "Lỗi hệ thống tệp.",
     "description": "Error message shown when failing to read or write the file system."
   },
-  "errorMsgNoCamera": {
+  "ERROR_MSG_NO_CAMERA": {
     "message": "Máy ảnh của bạn hiện không sử dụng được.\nVui lòng kiểm tra xem máy ảnh có được kết nối đúng cách không.",
     "description": "Error message shown when it was impossible to connect to the camera due to unavailability."
   },
-  "errorMsgGalleryExportFailed": {
+  "ERROR_MSG_GALLERY_EXPORT_FAILED": {
     "message": "Không thể xuất $file$",
     "description": "Error message shown when exporting to an external directory failed. Expects a file name to be passed in.",
     "placeholders": {
@@ -25,27 +25,27 @@
       }
     }
   },
-  "errorMsgSaveFileFailed": {
+  "ERROR_MSG_SAVE_FILE_FAILED": {
     "message": "Không thể lưu tệp",
     "description": "Error message shown when saving/adding a image or video to the file system failed."
   },
-  "errorMsgTakePhotoFailed": {
+  "ERROR_MSG_TAKE_PHOTO_FAILED": {
     "message": "Không thể chụp ảnh",
     "description": "Error message shown when failing to take photo."
   },
-  "errorMsgRecordStartFailed": {
+  "ERROR_MSG_RECORD_START_FAILED": {
     "message": "Không thể bắt đầu quay video",
     "description": "Error message shown when failing to start recording video."
   },
-  "errorMsgEmptyRecording": {
+  "ERROR_MSG_EMPTY_RECORDING": {
     "message": "Chưa ghi dữ liệu nào",
     "description": "Error message shown when no data is recorded for a recording and it won't be added to the gallery."
   },
-  "statusMsgRecordingStopped": {
+  "STATUS_MSG_RECORDING_STOPPED": {
     "message": "Đã dừng quay video",
     "description": "Status message for spoken feedback when video recording has been stopped."
   },
-  "statusMsgCameraSwitched": {
+  "STATUS_MSG_CAMERA_SWITCHED": {
     "message": "$camera$ đang hoạt động",
     "description": "Status message for spoken feedback when switching over to another camera.",
     "placeholders": {
@@ -55,131 +55,131 @@
       }
     }
   },
-  "galleryButton": {
+  "GALLERY_BUTTON": {
     "message": "Chuyển đến thư viện",
     "description": "Label for the gallery button."
   },
-  "deleteButton": {
+  "DELETE_BUTTON": {
     "message": "Xóa",
     "description": "Label for the delete button."
   },
-  "exportButton": {
+  "EXPORT_BUTTON": {
     "message": "Xuất ra đĩa",
     "description": "Label for the exporting button."
   },
-  "printButton": {
+  "PRINT_BUTTON": {
     "message": "In",
     "description": "Label for the printing button."
   },
-  "backButton": {
+  "BACK_BUTTON": {
     "message": "Quay lại",
     "description": "Label for the back button."
   },
-  "galleryImages": {
+  "GALLERY_IMAGES": {
     "message": "Ảnh trong thư viện",
     "description": "Text to speech label for the gallery list."
   },
-  "settingsButton": {
+  "SETTINGS_BUTTON": {
     "message": "Cài đặt",
     "description": "Label for the settings button."
   },
-  "gridTypeButton": {
+  "GRID_TYPE_BUTTON": {
     "message": "Loại lưới",
     "description": "Label for the button of grid-type options."
   },
-  "timerDurationButton": {
+  "TIMER_DURATION_BUTTON": {
     "message": "Thời lượng bộ hẹn giờ",
     "description": "Label for the button of timer-duration options."
   },
-  "feedbackButton": {
+  "FEEDBACK_BUTTON": {
     "message": "Gửi phản hồi",
     "description": "Label for the feedback button."
   },
-  "helpButton": {
+  "HELP_BUTTON": {
     "message": "Trợ giúp",
     "description": "Label for the help button."
   },
-  "labelGrid3x3": {
+  "LABEL_GRID_3X3": {
     "message": "3 x 3",
     "description": "Label for for grid-type: 3x3."
   },
-  "ariaGrid3x3": {
+  "ARIA_GRID_3X3": {
     "message": "3 x 3",
     "description": "Label for spoken feedback to read out grid-type: 3x3."
   },
-  "labelGrid4x4": {
+  "LABEL_GRID_4X4": {
     "message": "4 x 4",
     "description": "Label for for grid-type: 4x4."
   },
-  "ariaGrid4x4": {
+  "ARIA_GRID_4X4": {
     "message": "4 x 4",
     "description": "Label for spoken feedback to read out grid-type: 4x4."
   },
-  "labelGridGolden": {
+  "LABEL_GRID_GOLDEN": {
     "message": "Tỷ lệ vàng",
     "description": "Label for grid-type: golden ratio."
   },
-  "labelTimer3s": {
+  "LABEL_TIMER_3S": {
     "message": "3 giây",
     "description": "Label for timer-duration: 3 seconds."
   },
-  "labelTimer10s": {
+  "LABEL_TIMER_10S": {
     "message": "10 giây",
     "description": "Label for timer-duration: 10 seconds."
   },
-  "takePhotoButton": {
+  "TAKE_PHOTO_BUTTON": {
     "message": "Chụp ảnh",
     "description": "Label for the shutter button to take photo."
   },
-  "takePhotoCancelButton": {
+  "TAKE_PHOTO_CANCEL_BUTTON": {
     "message": "Dừng chụp ảnh",
     "description": "Label for the shutter button to cancel countdown timer and stop taking photo."
   },
-  "recordVideoStartButton": {
+  "RECORD_VIDEO_START_BUTTON": {
     "message": "Bắt đầu quay video",
     "description": "Label for the shutter button to start recording."
   },
-  "recordVideoStopButton": {
+  "RECORD_VIDEO_STOP_BUTTON": {
     "message": "Dừng quay video",
     "description": "Label for the shutter button to stop recording."
   },
-  "switchCameraButton": {
+  "SWITCH_CAMERA_BUTTON": {
     "message": "Chuyển sang máy ảnh tiếp theo",
     "description": "Label for the button to switch to next connected camera. Eg. switching from front facing to back facing, or a camera connected via USB. The button is shown only when more than one camera is connected."
   },
-  "switchRecordVideoButton": {
+  "SWITCH_RECORD_VIDEO_BUTTON": {
     "message": "Chuyển sang quay video",
     "description": "Label for the button to switch to record video mode."
   },
-  "switchTakePhotoButton": {
+  "SWITCH_TAKE_PHOTO_BUTTON": {
     "message": "Chuyển sang chụp ảnh",
     "description": "Label for the button to switch to take photo mode."
   },
-  "toggleTimerButton": {
+  "TOGGLE_TIMER_BUTTON": {
     "message": "Bộ hẹn giờ",
     "description": "Label for the checkbox to toggle the countdown timer."
   },
-  "toggleMirrorButton": {
+  "TOGGLE_MIRROR_BUTTON": {
     "message": "Phản chiếu",
     "description": "Label for the checkbox to toggle the preview mirroring. Eg. if mirroring is toggled on, preview will be flipped horizontally."
   },
-  "toggleGridButton": {
+  "TOGGLE_GRID_BUTTON": {
     "message": "Lưới",
     "description": "Label for the checkbox to toggle the grid shown on preview."
   },
-  "toggleMicButton": {
+  "TOGGLE_MIC_BUTTON": {
     "message": "Micrô",
     "description": "Label for the checkbox to toggle the microphone for recording video."
   },
-  "dialogOKButton": {
+  "DIALOG_OK_BUTTON": {
     "message": "OK",
     "description": "Label for the accepting button in the dialog."
   },
-  "dialogCancelButton": {
+  "DIALOG_CANCEL_BUTTON": {
     "message": "Hủy",
     "description": "Label for the dismissing button in the dialog."
   },
-  "deleteConfirmationMsg": {
+  "DELETE_CONFIRMATION_MSG": {
     "message": "Bạn có thực sự muốn xóa $file$ không?",
     "description": "Confirmation message before removing a selected item from the gallery. Expects a file name to be passed in.",
     "placeholders": {
@@ -189,7 +189,7 @@
       }
     }
   },
-  "deleteMultiConfirmationMsg": {
+  "DELETE_MULTI_CONFIRMATION_MSG": {
     "message": "Bạn có thực sự muốn xóa $count$ mục không?",
     "description": "Confirmation message before removing multiple selected items from the gallery. Expects a file count to be passed in.",
     "placeholders": {
@@ -199,7 +199,7 @@
       }
     }
   },
-  "migratePicturesMsg": {
+  "MIGRATE_PICTURES_MSG": {
     "message": "Ảnh và video mà bạn chụp và quay bằng máy ảnh sẽ được chuyển đến thư mục Tài nguyên đã tải xuống. Bạn có thể truy cập vào những nội dung này trong ứng dụng Files.\n\nỨng dụng có quyền truy cập vào bộ nhớ sẽ có quyền truy cập vào ảnh và video của bạn.",
     "description": "Message shown before moving all photos and videos stored in the Camera App to the Downloads folder."
   }
diff --git a/chrome/browser/resources/chromeos/camera/src/_locales/zh_CN/messages.json b/chrome/browser/resources/chromeos/camera/src/_locales/zh_CN/messages.json
index ad6c6ea..4508a1a 100644
--- a/chrome/browser/resources/chromeos/camera/src/_locales/zh_CN/messages.json
+++ b/chrome/browser/resources/chromeos/camera/src/_locales/zh_CN/messages.json
@@ -1,21 +1,21 @@
 {
-  "name": {
+  "NAME": {
     "message": "相机",
     "description": "Name of the Camera App."
   },
-  "description": {
+  "DESCRIPTION": {
     "message": "使用相机拍照和录制视频。",
     "description": "Short description of the Camera App."
   },
-  "errorMsgFileSystemFailed": {
+  "ERROR_MSG_FILE_SYSTEM_FAILED": {
     "message": "文件系统出错。",
     "description": "Error message shown when failing to read or write the file system."
   },
-  "errorMsgNoCamera": {
+  "ERROR_MSG_NO_CAMERA": {
     "message": "您的相机目前不可用。\n请检查此相机是否连接正确。",
     "description": "Error message shown when it was impossible to connect to the camera due to unavailability."
   },
-  "errorMsgGalleryExportFailed": {
+  "ERROR_MSG_GALLERY_EXPORT_FAILED": {
     "message": "无法导出 $file$",
     "description": "Error message shown when exporting to an external directory failed. Expects a file name to be passed in.",
     "placeholders": {
@@ -25,27 +25,27 @@
       }
     }
   },
-  "errorMsgSaveFileFailed": {
+  "ERROR_MSG_SAVE_FILE_FAILED": {
     "message": "无法保存文件",
     "description": "Error message shown when saving/adding a image or video to the file system failed."
   },
-  "errorMsgTakePhotoFailed": {
+  "ERROR_MSG_TAKE_PHOTO_FAILED": {
     "message": "无法拍照",
     "description": "Error message shown when failing to take photo."
   },
-  "errorMsgRecordStartFailed": {
+  "ERROR_MSG_RECORD_START_FAILED": {
     "message": "无法开始录制",
     "description": "Error message shown when failing to start recording video."
   },
-  "errorMsgEmptyRecording": {
+  "ERROR_MSG_EMPTY_RECORDING": {
     "message": "未记录任何数据",
     "description": "Error message shown when no data is recorded for a recording and it won't be added to the gallery."
   },
-  "statusMsgRecordingStopped": {
+  "STATUS_MSG_RECORDING_STOPPED": {
     "message": "已停止录制",
     "description": "Status message for spoken feedback when video recording has been stopped."
   },
-  "statusMsgCameraSwitched": {
+  "STATUS_MSG_CAMERA_SWITCHED": {
     "message": "已切换到$camera$",
     "description": "Status message for spoken feedback when switching over to another camera.",
     "placeholders": {
@@ -55,131 +55,131 @@
       }
     }
   },
-  "galleryButton": {
+  "GALLERY_BUTTON": {
     "message": "打开图库",
     "description": "Label for the gallery button."
   },
-  "deleteButton": {
+  "DELETE_BUTTON": {
     "message": "删除",
     "description": "Label for the delete button."
   },
-  "exportButton": {
+  "EXPORT_BUTTON": {
     "message": "导出到磁盘",
     "description": "Label for the exporting button."
   },
-  "printButton": {
+  "PRINT_BUTTON": {
     "message": "打印",
     "description": "Label for the printing button."
   },
-  "backButton": {
+  "BACK_BUTTON": {
     "message": "返回",
     "description": "Label for the back button."
   },
-  "galleryImages": {
+  "GALLERY_IMAGES": {
     "message": "图库图片",
     "description": "Text to speech label for the gallery list."
   },
-  "settingsButton": {
+  "SETTINGS_BUTTON": {
     "message": "设置",
     "description": "Label for the settings button."
   },
-  "gridTypeButton": {
+  "GRID_TYPE_BUTTON": {
     "message": "网格类型",
     "description": "Label for the button of grid-type options."
   },
-  "timerDurationButton": {
+  "TIMER_DURATION_BUTTON": {
     "message": "定时器时长",
     "description": "Label for the button of timer-duration options."
   },
-  "feedbackButton": {
+  "FEEDBACK_BUTTON": {
     "message": "发送反馈",
     "description": "Label for the feedback button."
   },
-  "helpButton": {
+  "HELP_BUTTON": {
     "message": "帮助",
     "description": "Label for the help button."
   },
-  "labelGrid3x3": {
+  "LABEL_GRID_3X3": {
     "message": "3 x 3",
     "description": "Label for for grid-type: 3x3."
   },
-  "ariaGrid3x3": {
+  "ARIA_GRID_3X3": {
     "message": "3 x 3",
     "description": "Label for spoken feedback to read out grid-type: 3x3."
   },
-  "labelGrid4x4": {
+  "LABEL_GRID_4X4": {
     "message": "4 x 4",
     "description": "Label for for grid-type: 4x4."
   },
-  "ariaGrid4x4": {
+  "ARIA_GRID_4X4": {
     "message": "4 x 4",
     "description": "Label for spoken feedback to read out grid-type: 4x4."
   },
-  "labelGridGolden": {
+  "LABEL_GRID_GOLDEN": {
     "message": "黄金比例",
     "description": "Label for grid-type: golden ratio."
   },
-  "labelTimer3s": {
+  "LABEL_TIMER_3S": {
     "message": "3 秒",
     "description": "Label for timer-duration: 3 seconds."
   },
-  "labelTimer10s": {
+  "LABEL_TIMER_10S": {
     "message": "10 秒",
     "description": "Label for timer-duration: 10 seconds."
   },
-  "takePhotoButton": {
+  "TAKE_PHOTO_BUTTON": {
     "message": "拍照",
     "description": "Label for the shutter button to take photo."
   },
-  "takePhotoCancelButton": {
+  "TAKE_PHOTO_CANCEL_BUTTON": {
     "message": "停止拍照",
     "description": "Label for the shutter button to cancel countdown timer and stop taking photo."
   },
-  "recordVideoStartButton": {
+  "RECORD_VIDEO_START_BUTTON": {
     "message": "开始录制",
     "description": "Label for the shutter button to start recording."
   },
-  "recordVideoStopButton": {
+  "RECORD_VIDEO_STOP_BUTTON": {
     "message": "停止录制",
     "description": "Label for the shutter button to stop recording."
   },
-  "switchCameraButton": {
+  "SWITCH_CAMERA_BUTTON": {
     "message": "切换到下一个相机",
     "description": "Label for the button to switch to next connected camera. Eg. switching from front facing to back facing, or a camera connected via USB. The button is shown only when more than one camera is connected."
   },
-  "switchRecordVideoButton": {
+  "SWITCH_RECORD_VIDEO_BUTTON": {
     "message": "切换到录制视频模式",
     "description": "Label for the button to switch to record video mode."
   },
-  "switchTakePhotoButton": {
+  "SWITCH_TAKE_PHOTO_BUTTON": {
     "message": "切换到拍照模式",
     "description": "Label for the button to switch to take photo mode."
   },
-  "toggleTimerButton": {
+  "TOGGLE_TIMER_BUTTON": {
     "message": "定时器",
     "description": "Label for the checkbox to toggle the countdown timer."
   },
-  "toggleMirrorButton": {
+  "TOGGLE_MIRROR_BUTTON": {
     "message": "镜像",
     "description": "Label for the checkbox to toggle the preview mirroring. Eg. if mirroring is toggled on, preview will be flipped horizontally."
   },
-  "toggleGridButton": {
+  "TOGGLE_GRID_BUTTON": {
     "message": "网格",
     "description": "Label for the checkbox to toggle the grid shown on preview."
   },
-  "toggleMicButton": {
+  "TOGGLE_MIC_BUTTON": {
     "message": "麦克风",
     "description": "Label for the checkbox to toggle the microphone for recording video."
   },
-  "dialogOKButton": {
+  "DIALOG_OK_BUTTON": {
     "message": "确定",
     "description": "Label for the accepting button in the dialog."
   },
-  "dialogCancelButton": {
+  "DIALOG_CANCEL_BUTTON": {
     "message": "取消",
     "description": "Label for the dismissing button in the dialog."
   },
-  "deleteConfirmationMsg": {
+  "DELETE_CONFIRMATION_MSG": {
     "message": "确定要移除 $file$ 吗?",
     "description": "Confirmation message before removing a selected item from the gallery. Expects a file name to be passed in.",
     "placeholders": {
@@ -189,7 +189,7 @@
       }
     }
   },
-  "deleteMultiConfirmationMsg": {
+  "DELETE_MULTI_CONFIRMATION_MSG": {
     "message": "确定要移除这 $count$ 个文件吗?",
     "description": "Confirmation message before removing multiple selected items from the gallery. Expects a file count to be passed in.",
     "placeholders": {
@@ -199,7 +199,7 @@
       }
     }
   },
-  "migratePicturesMsg": {
+  "MIGRATE_PICTURES_MSG": {
     "message": "使用此相机拍摄的照片和视频将被移至“下载内容”文件夹。您可在“文件”中访问它们。\n\n具有存储权限的应用将有权访问您的照片和视频。",
     "description": "Message shown before moving all photos and videos stored in the Camera App to the Downloads folder."
   }
diff --git a/chrome/browser/resources/chromeos/camera/src/_locales/zh_TW/messages.json b/chrome/browser/resources/chromeos/camera/src/_locales/zh_TW/messages.json
index ed48b24..dd4006d 100644
--- a/chrome/browser/resources/chromeos/camera/src/_locales/zh_TW/messages.json
+++ b/chrome/browser/resources/chromeos/camera/src/_locales/zh_TW/messages.json
@@ -1,21 +1,21 @@
 {
-  "name": {
+  "NAME": {
     "message": "相機",
     "description": "Name of the Camera App."
   },
-  "description": {
+  "DESCRIPTION": {
     "message": "使用相機拍攝相片及錄製影片。",
     "description": "Short description of the Camera App."
   },
-  "errorMsgFileSystemFailed": {
+  "ERROR_MSG_FILE_SYSTEM_FAILED": {
     "message": "檔案系統發生錯誤。",
     "description": "Error message shown when failing to read or write the file system."
   },
-  "errorMsgNoCamera": {
+  "ERROR_MSG_NO_CAMERA": {
     "message": "目前無法使用相機。\n請檢查相機是否已正確連接。",
     "description": "Error message shown when it was impossible to connect to the camera due to unavailability."
   },
-  "errorMsgGalleryExportFailed": {
+  "ERROR_MSG_GALLERY_EXPORT_FAILED": {
     "message": "無法匯出「$file$」",
     "description": "Error message shown when exporting to an external directory failed. Expects a file name to be passed in.",
     "placeholders": {
@@ -25,27 +25,27 @@
       }
     }
   },
-  "errorMsgSaveFileFailed": {
+  "ERROR_MSG_SAVE_FILE_FAILED": {
     "message": "無法儲存檔案",
     "description": "Error message shown when saving/adding a image or video to the file system failed."
   },
-  "errorMsgTakePhotoFailed": {
+  "ERROR_MSG_TAKE_PHOTO_FAILED": {
     "message": "無法拍照",
     "description": "Error message shown when failing to take photo."
   },
-  "errorMsgRecordStartFailed": {
+  "ERROR_MSG_RECORD_START_FAILED": {
     "message": "無法開始錄影",
     "description": "Error message shown when failing to start recording video."
   },
-  "errorMsgEmptyRecording": {
+  "ERROR_MSG_EMPTY_RECORDING": {
     "message": "未錄製任何內容",
     "description": "Error message shown when no data is recorded for a recording and it won't be added to the gallery."
   },
-  "statusMsgRecordingStopped": {
+  "STATUS_MSG_RECORDING_STOPPED": {
     "message": "已停止錄影",
     "description": "Status message for spoken feedback when video recording has been stopped."
   },
-  "statusMsgCameraSwitched": {
+  "STATUS_MSG_CAMERA_SWITCHED": {
     "message": "已切換至 $camera$",
     "description": "Status message for spoken feedback when switching over to another camera.",
     "placeholders": {
@@ -55,131 +55,131 @@
       }
     }
   },
-  "galleryButton": {
+  "GALLERY_BUTTON": {
     "message": "前往圖片庫",
     "description": "Label for the gallery button."
   },
-  "deleteButton": {
+  "DELETE_BUTTON": {
     "message": "刪除",
     "description": "Label for the delete button."
   },
-  "exportButton": {
+  "EXPORT_BUTTON": {
     "message": "匯出至磁碟",
     "description": "Label for the exporting button."
   },
-  "printButton": {
+  "PRINT_BUTTON": {
     "message": "列印",
     "description": "Label for the printing button."
   },
-  "backButton": {
+  "BACK_BUTTON": {
     "message": "返回",
     "description": "Label for the back button."
   },
-  "galleryImages": {
+  "GALLERY_IMAGES": {
     "message": "圖片庫圖片",
     "description": "Text to speech label for the gallery list."
   },
-  "settingsButton": {
+  "SETTINGS_BUTTON": {
     "message": "設定",
     "description": "Label for the settings button."
   },
-  "gridTypeButton": {
+  "GRID_TYPE_BUTTON": {
     "message": "格線類型",
     "description": "Label for the button of grid-type options."
   },
-  "timerDurationButton": {
+  "TIMER_DURATION_BUTTON": {
     "message": "計時器倒數時間",
     "description": "Label for the button of timer-duration options."
   },
-  "feedbackButton": {
+  "FEEDBACK_BUTTON": {
     "message": "提供意見",
     "description": "Label for the feedback button."
   },
-  "helpButton": {
+  "HELP_BUTTON": {
     "message": "說明",
     "description": "Label for the help button."
   },
-  "labelGrid3x3": {
+  "LABEL_GRID_3X3": {
     "message": "3 x 3",
     "description": "Label for for grid-type: 3x3."
   },
-  "ariaGrid3x3": {
+  "ARIA_GRID_3X3": {
     "message": "3 乘 3",
     "description": "Label for spoken feedback to read out grid-type: 3x3."
   },
-  "labelGrid4x4": {
+  "LABEL_GRID_4X4": {
     "message": "4 x 4",
     "description": "Label for for grid-type: 4x4."
   },
-  "ariaGrid4x4": {
+  "ARIA_GRID_4X4": {
     "message": "4 乘 4",
     "description": "Label for spoken feedback to read out grid-type: 4x4."
   },
-  "labelGridGolden": {
+  "LABEL_GRID_GOLDEN": {
     "message": "黃金比例",
     "description": "Label for grid-type: golden ratio."
   },
-  "labelTimer3s": {
+  "LABEL_TIMER_3S": {
     "message": "3 秒",
     "description": "Label for timer-duration: 3 seconds."
   },
-  "labelTimer10s": {
+  "LABEL_TIMER_10S": {
     "message": "10 秒",
     "description": "Label for timer-duration: 10 seconds."
   },
-  "takePhotoButton": {
+  "TAKE_PHOTO_BUTTON": {
     "message": "拍照",
     "description": "Label for the shutter button to take photo."
   },
-  "takePhotoCancelButton": {
+  "TAKE_PHOTO_CANCEL_BUTTON": {
     "message": "停止拍照",
     "description": "Label for the shutter button to cancel countdown timer and stop taking photo."
   },
-  "recordVideoStartButton": {
+  "RECORD_VIDEO_START_BUTTON": {
     "message": "開始錄製",
     "description": "Label for the shutter button to start recording."
   },
-  "recordVideoStopButton": {
+  "RECORD_VIDEO_STOP_BUTTON": {
     "message": "停止錄影",
     "description": "Label for the shutter button to stop recording."
   },
-  "switchCameraButton": {
+  "SWITCH_CAMERA_BUTTON": {
     "message": "切換至下一個相機",
     "description": "Label for the button to switch to next connected camera. Eg. switching from front facing to back facing, or a camera connected via USB. The button is shown only when more than one camera is connected."
   },
-  "switchRecordVideoButton": {
+  "SWITCH_RECORD_VIDEO_BUTTON": {
     "message": "切換為錄影模式",
     "description": "Label for the button to switch to record video mode."
   },
-  "switchTakePhotoButton": {
+  "SWITCH_TAKE_PHOTO_BUTTON": {
     "message": "切換為拍照模式",
     "description": "Label for the button to switch to take photo mode."
   },
-  "toggleTimerButton": {
+  "TOGGLE_TIMER_BUTTON": {
     "message": "計時器",
     "description": "Label for the checkbox to toggle the countdown timer."
   },
-  "toggleMirrorButton": {
+  "TOGGLE_MIRROR_BUTTON": {
     "message": "鏡像功能",
     "description": "Label for the checkbox to toggle the preview mirroring. Eg. if mirroring is toggled on, preview will be flipped horizontally."
   },
-  "toggleGridButton": {
+  "TOGGLE_GRID_BUTTON": {
     "message": "格線",
     "description": "Label for the checkbox to toggle the grid shown on preview."
   },
-  "toggleMicButton": {
+  "TOGGLE_MIC_BUTTON": {
     "message": "麥克風",
     "description": "Label for the checkbox to toggle the microphone for recording video."
   },
-  "dialogOKButton": {
+  "DIALOG_OK_BUTTON": {
     "message": "確定",
     "description": "Label for the accepting button in the dialog."
   },
-  "dialogCancelButton": {
+  "DIALOG_CANCEL_BUTTON": {
     "message": "取消",
     "description": "Label for the dismissing button in the dialog."
   },
-  "deleteConfirmationMsg": {
+  "DELETE_CONFIRMATION_MSG": {
     "message": "確定要移除「$file$」嗎?",
     "description": "Confirmation message before removing a selected item from the gallery. Expects a file name to be passed in.",
     "placeholders": {
@@ -189,7 +189,7 @@
       }
     }
   },
-  "deleteMultiConfirmationMsg": {
+  "DELETE_MULTI_CONFIRMATION_MSG": {
     "message": "確定要移除這 $count$ 個項目嗎?",
     "description": "Confirmation message before removing multiple selected items from the gallery. Expects a file count to be passed in.",
     "placeholders": {
@@ -199,7 +199,7 @@
       }
     }
   },
-  "migratePicturesMsg": {
+  "MIGRATE_PICTURES_MSG": {
     "message": "使用相機拍攝的相片和影片將移至「下載內容」資料夾,你可以在「檔案」應用程式中找到這些內容。\n\n具備儲存空間權限的應用程式將可存取你的相片和影片。",
     "description": "Message shown before moving all photos and videos stored in the Camera App to the Downloads folder."
   }
diff --git a/chrome/browser/resources/chromeos/camera/src/css/main.css b/chrome/browser/resources/chromeos/camera/src/css/main.css
index c4c85c6f..41a93b8 100644
--- a/chrome/browser/resources/chromeos/camera/src/css/main.css
+++ b/chrome/browser/resources/chromeos/camera/src/css/main.css
@@ -880,11 +880,11 @@
   display: none;
 }
 
-body._3x3 .description span[i18n-content=labelGrid3x3],
-body._4x4 .description span[i18n-content=labelGrid4x4],
-body.golden .description span[i18n-content=labelGridGolden],
-body._3sec .description span[i18n-content=labelTimer3s],
-body._10sec .description span[i18n-content=labelTimer10s] {
+body._3x3 .description span[i18n-content=label_grid_3x3],
+body._4x4 .description span[i18n-content=label_grid_4x4],
+body.golden .description span[i18n-content=label_grid_golden],
+body._3sec .description span[i18n-content=label_timer_3s],
+body._10sec .description span[i18n-content=label_timer_10s] {
   display: inline;
 }
 
diff --git a/chrome/browser/resources/chromeos/camera/src/js/main.js b/chrome/browser/resources/chromeos/camera/src/js/main.js
index 7a728fc..36457946 100644
--- a/chrome/browser/resources/chromeos/camera/src/js/main.js
+++ b/chrome/browser/resources/chromeos/camera/src/js/main.js
@@ -132,7 +132,7 @@
 cca.App.prototype.start = function() {
   cca.models.FileSystem.initialize(() => {
     // Prompt to migrate pictures if needed.
-    var message = chrome.i18n.getMessage('migratePicturesMsg');
+    var message = chrome.i18n.getMessage('migrate_pictures_msg');
     return cca.nav.open('dialog', message, false).then((acked) => {
       if (!acked) {
         throw new Error('no-migrate');
diff --git a/chrome/browser/resources/chromeos/camera/src/js/views/camera.js b/chrome/browser/resources/chromeos/camera/src/js/views/camera.js
index dd4804c..effcf7c 100644
--- a/chrome/browser/resources/chromeos/camera/src/js/views/camera.js
+++ b/chrome/browser/resources/chromeos/camera/src/js/views/camera.js
@@ -195,7 +195,7 @@
   } catch (e) {
     console.error(e);
     cca.toast.show(this.recordMode ?
-        'errorMsgRecordStartFailed' : 'errorMsgTakePhotoFailed');
+        'error_msg_record_start_failed' : 'error_msg_take_photo_failed');
   }
 };
 
@@ -206,10 +206,10 @@
 cca.views.Camera.prototype.updateShutterLabel_ = function() {
   var label;
   if (this.recordMode) {
-    label = this.taking ? 'recordVideoStopButton' : 'recordVideoStartButton';
+    label = this.taking ? 'record_video_stop_button' : 'record_video_start_button';
   } else {
     label = (this.taking && this.ticks_) ?
-        'takePhotoCancelButton' : 'takePhotoButton';
+        'take_photo_cancel_button' : 'take_photo_button';
   }
   this.shutterButton_.setAttribute('aria-label', chrome.i18n.getMessage(label));
 };
@@ -250,12 +250,12 @@
       if (this.recordMode) {
         // Take of recording will be ended by another shutter click.
         this.take_ = this.createRecordingBlob_().catch((error) => {
-          cca.toast.show('errorMsgEmptyRecording');
+          cca.toast.show('error_msg_empty_recording');
           throw error;
         });
       } else {
         this.take_ = this.createPhotoBlob_().catch((error) => {
-          cca.toast.show('errorMsgTakePhotoFailed');
+          cca.toast.show('error_msg_take_photo_failed');
           throw error;
         });
         this.endTake_();
@@ -291,7 +291,7 @@
           cca.views.camera.Options.Sound.RECORDEND :
           cca.views.camera.Options.Sound.SHUTTER);
       return this.model_.savePicture(blob, recordMode).catch((error) => {
-        cca.toast.show('errorMsgSaveFileFailed');
+        cca.toast.show('error_msg_save_file_failed');
         throw error;
       });
     }
diff --git a/chrome/browser/resources/chromeos/camera/src/js/views/camera/options.js b/chrome/browser/resources/chromeos/camera/src/js/views/camera/options.js
index 3ccb1e50..c1f9ef5 100644
--- a/chrome/browser/resources/chromeos/camera/src/js/views/camera/options.js
+++ b/chrome/browser/resources/chromeos/camera/src/js/views/camera/options.js
@@ -192,7 +192,7 @@
     var found = devices.find((entry) => entry.deviceId == this.videoDeviceId_);
     if (found) {
       cca.toast.speak(chrome.i18n.getMessage(
-          'statusMsgCameraSwitched', found.label));
+          'status_msg_camera_switched', found.label));
     }
   });
 };
diff --git a/chrome/browser/resources/chromeos/camera/src/js/views/camera/recordtime.js b/chrome/browser/resources/chromeos/camera/src/js/views/camera/recordtime.js
index 4dfa7935..dab07149 100644
--- a/chrome/browser/resources/chromeos/camera/src/js/views/camera/recordtime.js
+++ b/chrome/browser/resources/chromeos/camera/src/js/views/camera/recordtime.js
@@ -78,7 +78,7 @@
  * Stops counting and showing the elapsed recording time.
  */
 cca.views.camera.RecordTime.prototype.stop = function() {
-  cca.toast.speak('statusMsgRecordingStopped');
+  cca.toast.speak('status_msg_recording_stopped');
   if (this.tickTimeout_) {
     clearInterval(this.tickTimeout_);
     this.tickTimeout_ = null;
diff --git a/chrome/browser/resources/chromeos/camera/src/js/views/gallery_base.js b/chrome/browser/resources/chromeos/camera/src/js/views/gallery_base.js
index e179ca1..63b5148 100644
--- a/chrome/browser/resources/chromeos/camera/src/js/views/gallery_base.js
+++ b/chrome/browser/resources/chromeos/camera/src/js/views/gallery_base.js
@@ -105,7 +105,7 @@
             this.model_.exportPicture(picture, entry).catch((error) => {
               console.error(error);
               cca.toast.show(chrome.i18n.getMessage(
-                  'errorMsgGalleryExportFailed', entry.name));
+                  'error_msg_gallery_export_failed', entry.name));
             });
           });
     });
@@ -126,7 +126,7 @@
   var param = multi ? selectedIndexes.length.toString() :
       this.lastSelectedPicture().picture.pictureEntry.name;
   var message = chrome.i18n.getMessage(
-      multi ? 'deleteMultiConfirmationMsg' : 'deleteConfirmationMsg', param);
+      multi ? 'delete_multi_confirmation_msg' : 'delete_confirmation_msg', param);
   cca.nav.open('dialog', message, true).then((confirmed) => {
     if (!confirmed) {
       return;
diff --git a/chrome/browser/resources/chromeos/camera/src/js/views/warning.js b/chrome/browser/resources/chromeos/camera/src/js/views/warning.js
index f82e4ce..b588f3e 100644
--- a/chrome/browser/resources/chromeos/camera/src/js/views/warning.js
+++ b/chrome/browser/resources/chromeos/camera/src/js/views/warning.js
@@ -44,10 +44,10 @@
   var message = '';
   switch (this.errorNames_[this.errorNames_.length - 1]) {
     case 'no-camera':
-      message = 'errorMsgNoCamera';
+      message = 'error_msg_no_camera';
       break;
     case 'filesystem-failure':
-      message = 'errorMsgFileSystemFailed';
+      message = 'error_msg_file_system_failed';
       break;
   }
   document.querySelector('#error-msg').textContent =
diff --git a/chrome/browser/resources/chromeos/camera/src/manifest.json b/chrome/browser/resources/chromeos/camera/src/manifest.json
index 221569f..b01339e 100644
--- a/chrome/browser/resources/chromeos/camera/src/manifest.json
+++ b/chrome/browser/resources/chromeos/camera/src/manifest.json
@@ -1,4 +1,5 @@
 {
+  "key": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC3oA1Ox8PiRORjuFDgJeWcwnzZDPHUzuH6fymTrx8KPybhfd6XIYFXvilSsRnsGKPslN+BXke3HWC4/MoB2HM2pNGmsQ+jNyTh2dgk4ISdZYRLfqjxr846/245dkznCJLYAZr72Lk+vRZUyYBcLNNox8jRV5ZF16+8uPPUsUiqbQIDAQAB",
   "manifest_version": 2,
   "name": "__MSG_name__",
   "description": "__MSG_description__",
diff --git a/chrome/browser/resources/chromeos/camera/src/views/main.html b/chrome/browser/resources/chromeos/camera/src/views/main.html
index 5faef4f6..8dc02b6f 100644
--- a/chrome/browser/resources/chromeos/camera/src/views/main.html
+++ b/chrome/browser/resources/chromeos/camera/src/views/main.html
@@ -46,38 +46,38 @@
       </div>
       <div class="actions-group buttons circle">
         <button id="switch-takephoto" tabindex="0"
-                i18n-label="switchTakePhotoButton"></button>
+                i18n-label="switch_take_photo_button"></button>
         <button id="shutter" tabindex="0"
-                i18n-label="takePhotoButton"></button>
+                i18n-label="take_photo_button"></button>
         <button id="switch-recordvideo" tabindex="0"
-                i18n-label="switchRecordVideoButton"></button>
+                i18n-label="switch_record_video_button"></button>
       </div>
       <div class="top-stripe right-stripe buttons">
         <input type="checkbox" id="toggle-mic" tabindex="0"
-               i18n-label="toggleMicButton" data-css="mic" data-key="toggleMic"
+               i18n-label="toggle_mic_button" data-css="mic" data-key="toggleMic"
                checked>
       </div>
       <div class="top-stripe left-stripe buttons">
         <button id="open-settings" tabindex="0"
-                i18n-label="settingsButton" aria-haspopup="true"></button>
+                i18n-label="settings_button" aria-haspopup="true"></button>
       </div>
       <div class="left-stripe options-group buttons">
         <input type="checkbox" id="toggle-mirror" tabindex="0"
-               i18n-label="toggleMirrorButton" data-css="mirror" checked>
+               i18n-label="toggle_mirror_button" data-css="mirror" checked>
         <input type="checkbox" id="toggle-grid" tabindex="0"
-               i18n-label="toggleGridButton" data-css="grid"
+               i18n-label="toggle_grid_button" data-css="grid"
                data-key="toggleGrid">
         <input type="checkbox" id="toggle-timer" tabindex="0"
-               i18n-label="toggleTimerButton" data-css="timer"
+               i18n-label="toggle_timer_button" data-css="timer"
                data-key="toggleTimer">
       </div>
       <div class="bottom-stripe left-stripe buttons circle">
         <button id="switch-device" tabindex="0"
-                i18n-label="switchCameraButton"></button>
+                i18n-label="switch_camera_button"></button>
       </div>
       <div class="bottom-stripe right-stripe buttons circle">
         <button id="gallery-enter" tabindex="0"
-                i18n-label="galleryButton" hidden></button>
+                i18n-label="gallery_button" hidden></button>
       </div>
       <div class="top-stripe" id="record-time" hidden>
         <div class="icon"></div>
@@ -91,18 +91,18 @@
     <div id="settings">
       <div class="menu">
         <div class="menu-header circle">
-          <button class="icon" tabindex="0" i18n-aria="backButton"></button>
-          <div role="menu" i18n-content="settingsButton"></div>
+          <button class="icon" tabindex="0" i18n-aria="back_button"></button>
+          <div role="menu" i18n-content="settings_button"></div>
         </div>
         <button class="menu-item circle" id="settings-gridtype" tabindex="0"
                 aria-describedby="gridtype-desc">
           <div class="icon"></div>
           <div>
-            <div i18n-content="gridTypeButton"></div>
+            <div i18n-content="grid_type_button"></div>
             <div class="description" id="gridtype-desc" aria-hidden="true">
-              <span i18n-content="labelGrid3x3" i18n-aria="ariaGrid3x3"></span>
-              <span i18n-content="labelGrid4x4" i18n-aria="ariaGrid4x4"></span>
-              <span i18n-content="labelGridGolden"></span>
+              <span i18n-content="label_grid_3x3" i18n-aria="aria_grid_3x3"></span>
+              <span i18n-content="label_grid_4x4" i18n-aria="aria_grid_4x4"></span>
+              <span i18n-content="label_grid_golden"></span>
             </div>
           </div>
           <div class="icon end"></div>
@@ -111,80 +111,80 @@
                 aria-describedby="timerdur-desc">
           <div class="icon"></div>
           <div>
-            <div i18n-content="timerDurationButton"></div>
+            <div i18n-content="timer_duration_button"></div>
             <div class="description" id="timerdur-desc" aria-hidden="true">
-              <span i18n-content="labelTimer3s"></span>
-              <span i18n-content="labelTimer10s"></span>
+              <span i18n-content="label_timer_3s"></span>
+              <span i18n-content="label_timer_10s"></span>
             </div>
           </div>
           <div class="icon end"></div>
         </button>
         <button class="menu-item circle" id="settings-feedback" tabindex="0">
           <div class="icon"></div>
-          <div i18n-content="feedbackButton"></div>
+          <div i18n-content="feedback_button"></div>
         </button>
         <button class="menu-item circle" id="settings-help" tabindex="0">
           <div class="icon"></div>
-          <div i18n-content="helpButton"></div>
+          <div i18n-content="help_button"></div>
         </button>
       </div>
     </div>
     <div id="gridsettings">
       <div class="menu">
         <div class="menu-header circle">
-          <button class="icon" tabindex="0" i18n-aria="backButton"></button>
-          <div role="menu" i18n-content="gridTypeButton"></div>
+          <button class="icon" tabindex="0" i18n-aria="back_button"></button>
+          <div role="menu" i18n-content="grid_type_button"></div>
         </div>
         <label class="menu-item circle" for="grid-3x3">
           <input class="icon" id="grid-3x3" type="radio" tabindex="0"
                  name="gridtype" data-css="_3x3" data-key="toggle3x3" checked>
-          <span i18n-content="labelGrid3x3" i18n-aria="ariaGrid3x3"></span>
+          <span i18n-content="label_grid_3x3" i18n-aria="aria_grid_3x3"></span>
         </label>
         <label class="menu-item circle" for="grid-4x4">
           <input class="icon" id="grid-4x4" type="radio" tabindex="0"
                  name="gridtype" data-css="_4x4" data-key="toggle4x4">
-          <span i18n-content="labelGrid4x4" i18n-aria="ariaGrid4x4"></span>
+          <span i18n-content="label_grid_4x4" i18n-aria="aria_grid_4x4"></span>
         </label>
         <label class="menu-item circle" for="grid-golden">
           <input class="icon" id="grid-golden" type="radio" tabindex="0"
                  name="gridtype" data-css="golden" data-key="toggleGolden">
-          <span i18n-content="labelGridGolden"></span>
+          <span i18n-content="label_grid_golden"></span>
         </label>
       </div>
     </div>
     <div id="timersettings">
       <div class="menu">
         <div class="menu-header circle">
-          <button class="icon" tabindex="0" i18n-aria="backButton"></button>
-          <div role="menu" i18n-content="timerDurationButton"></div>
+          <button class="icon" tabindex="0" i18n-aria="back_button"></button>
+          <div role="menu" i18n-content="timer_duration_button"></div>
         </div>
         <label class="menu-item circle" for="timer-3s">
           <input class="icon" id="timer-3s" type="radio" tabindex="0"
                  name="timerdur" data-css="_3sec" data-key="toggle3sec" checked>
-          <span i18n-content="labelTimer3s"></span>
+          <span i18n-content="label_timer_3s"></span>
         </label>
         <label class="menu-item circle" for="timer-10s">
           <input class="icon" id="timer-10s" type="radio" tabindex="0"
                  name="timerdur" data-css="_10sec" data-key="toggle10sec">
-          <span i18n-content="labelTimer10s"></span>
+          <span i18n-content="label_timer_10s"></span>
         </label>
       </div>
     </div>
     <div class="centered-overlay" id="spinner"></div>
-    <div id="browser" role="listbox" i18n-aria="galleryImages">
+    <div id="browser" role="listbox" i18n-aria="gallery_images">
       <div class="padder">
         <div class="bounds-padder"></div>
         <div class="bounds-padder"></div>
       </div>
       <div class="buttons">
         <button id="browser-back" tabindex="0"
-                i18n-label="backButton"></button>
+                i18n-label="back_button"></button>
         <button id="browser-print" disabled tabindex="0"
-                i18n-label="printButton"></button>
+                i18n-label="print_button"></button>
         <button id="browser-export" disabled tabindex="0"
-                i18n-label="exportButton"></button>
+                i18n-label="export_button"></button>
         <button id="browser-delete" disabled tabindex="0"
-                i18n-label="deleteButton"></button>
+                i18n-label="delete_button"></button>
       </div>
     </div>
     <div id="warning">
@@ -195,9 +195,9 @@
         <div id="dialog-msg"></div>
         <div id="dialog-buttons">
           <button id="dialog-negative-button" tabindex="0"
-                  i18n-content="dialogCancelButton"></button>
+                  i18n-content="dialog_cancel_button"></button>
           <button id="dialog-positive-button" tabindex="0"
-                  i18n-content="dialogOKButton"></button>
+                  i18n-content="dialog_ok_button"></button>
         </div>
       </div>
     </div>
diff --git a/chrome/browser/resources/chromeos/chromevox/common/command_store.js b/chrome/browser/resources/chromeos/chromevox/common/command_store.js
index 0d262ae..3129f2a 100644
--- a/chrome/browser/resources/chromeos/chromevox/common/command_store.js
+++ b/chrome/browser/resources/chromeos/chromevox/common/command_store.js
@@ -135,7 +135,6 @@
   'toggleStickyMode': {
     announce: false,
     msgId: 'toggle_sticky_mode',
-    'disallowOOBE': true,
     category: 'modifier_keys'
   },
   'passThroughMode': {
diff --git a/chrome/browser/resources/offline_pages/offline_internals.html b/chrome/browser/resources/offline_pages/offline_internals.html
index df91dab..4f82ada 100644
--- a/chrome/browser/resources/offline_pages/offline_internals.html
+++ b/chrome/browser/resources/offline_pages/offline_internals.html
@@ -125,7 +125,7 @@
       </div>
       <div>
         <input id="operation-name" type="text"
-            placeholder="operations/1234-5678">
+                                   placeholder="operations/1234-5678">
         <button id="get-operation">Get Operation</button>
       </div>
       <div>
@@ -133,6 +133,11 @@
         <button id="download-archive">Download</button>
       </div>
     </div>
+    <div>
+      Limitless prefetching: <span id="limitless-prefetching-status"></span>
+      <button id="limitless-prefetching-on">Enable</button>
+      <button id="limitless-prefetching-off">Disable</button>
+    </div>
     <div id="prefetch-actions-info" class="dump"></div>
   </body>
 </html>
diff --git a/chrome/browser/resources/offline_pages/offline_internals.js b/chrome/browser/resources/offline_pages/offline_internals.js
index b0513bc..e5c919d 100644
--- a/chrome/browser/resources/offline_pages/offline_internals.js
+++ b/chrome/browser/resources/offline_pages/offline_internals.js
@@ -112,6 +112,9 @@
     browserProxy.getNetworkStatus().then(function(networkStatus) {
       $('current-status').textContent = networkStatus;
     });
+    browserProxy.getLimitlessPrefetchingEnabled().then(function(enabled) {
+      $('limitless-prefetching-status').textContent = getTextLabel(enabled);
+    });
     refreshLog();
   }
 
@@ -254,6 +257,14 @@
       $('prefetch-status').textContent = getTextLabel(enabled);
     }
 
+    /**
+     * @param {boolean} enabled Whether to enable limitless prefetching.
+     */
+    function toggleLimitlessPrefetching(enabled) {
+      browserProxy.setLimitlessPrefetchingEnabled(enabled);
+      $('limitless-prefetching-status').textContent = getTextLabel(enabled);
+    }
+
     const incognito = loadTimeData.getBoolean('isIncognito');
     ['delete-selected-pages', 'delete-selected-requests', 'log-model-on',
      'log-model-off', 'log-request-on', 'log-request-off', 'refresh']
@@ -331,6 +342,10 @@
     $('toggle-all-requests').onclick = function() {
       toggleAllCheckboxes($('toggle-all-requests'), 'requests');
     };
+    $('limitless-prefetching-on').onclick =
+        toggleLimitlessPrefetching.bind(null, true);
+    $('limitless-prefetching-off').onclick =
+        toggleLimitlessPrefetching.bind(null, false);
     if (!incognito) {
       refreshAll();
     }
diff --git a/chrome/browser/resources/offline_pages/offline_internals_browser_proxy.js b/chrome/browser/resources/offline_pages/offline_internals_browser_proxy.js
index f6951b1..4be444b 100644
--- a/chrome/browser/resources/offline_pages/offline_internals_browser_proxy.js
+++ b/chrome/browser/resources/offline_pages/offline_internals_browser_proxy.js
@@ -94,6 +94,18 @@
     setRecordPrefetchService: function(shouldLog) {},
 
     /**
+     * Sets whether limitless prefetching is enabled.
+     * @param {boolean} enabled Whether to enable limitless prefetching.
+     */
+    setLimitlessPrefetchingEnabled: function(enabled) {},
+
+    /**
+     * Gets whether limitless prefetching is enabled.
+     * @return {!Promise<boolean>} Whether limitless prefetching is enabled
+     */
+    getLimitlessPrefetchingEnabled: function() {},
+
+    /**
      * Gets the currently recorded logs.
      * @return {!Promise<!Array<string>>} A promise firing when the
      *     logs are retrieved.
@@ -209,6 +221,16 @@
     },
 
     /** @override */
+    setLimitlessPrefetchingEnabled: function(enabled) {
+      chrome.send('setLimitlessPrefetchingEnabled', [enabled]);
+    },
+
+    /** @override */
+    getLimitlessPrefetchingEnabled: function() {
+      return cr.sendWithPromise('getLimitlessPrefetchingEnabled');
+    },
+
+    /** @override */
     getEventLogs: function() {
       return cr.sendWithPromise('getEventLogs');
     },
diff --git a/chrome/browser/resources/settings/bluetooth_page/bluetooth_subpage.js b/chrome/browser/resources/settings/bluetooth_page/bluetooth_subpage.js
index 9cfd44b..ca7038f 100644
--- a/chrome/browser/resources/settings/bluetooth_page/bluetooth_subpage.js
+++ b/chrome/browser/resources/settings/bluetooth_page/bluetooth_subpage.js
@@ -148,6 +148,7 @@
   observers: [
     'adapterStateChanged_(adapterState.*)',
     'deviceListChanged_(deviceList_.*)',
+    'listUpdateFrequencyMsChanged_(listUpdateFrequencyMs)',
   ],
 
   /**
@@ -157,55 +158,13 @@
    */
   updateTimerId_: undefined,
 
-  /**
-   * Listener for chrome.bluetooth.onBluetoothDeviceChanged events.
-   * @type {?function(!chrome.bluetooth.Device)}
-   * @private
-   */
-  bluetoothDeviceUpdatedListener_: null,
-
-  /**
-   * Listener for chrome.bluetooth.onBluetoothDeviceAdded events.
-   * @type {?function(!chrome.bluetooth.Device)}
-   * @private
-   */
-  bluetoothDeviceAddedListener_: null,
-
-  /**
-   * Listener for chrome.bluetooth.onBluetoothDeviceRemoved events.
-   * @type {?function(!chrome.bluetooth.Device)}
-   * @private
-   */
-  bluetoothDeviceRemovedListener_: null,
-
-  /** @override */
-  attached: function() {
-    this.bluetoothDeviceUpdatedListener_ =
-        this.bluetoothDeviceUpdatedListener_ ||
-        this.onBluetoothDeviceUpdated_.bind(this);
-    this.bluetooth.onDeviceChanged.addListener(
-        this.bluetoothDeviceUpdatedListener_);
-
-    this.bluetoothDeviceAddedListener_ = this.bluetoothDeviceAddedListener_ ||
-        this.onBluetoothDeviceAdded_.bind(this);
-    this.bluetooth.onDeviceAdded.addListener(
-        this.bluetoothDeviceAddedListener_);
-
-    this.bluetoothDeviceRemovedListener_ =
-        this.bluetoothDeviceRemovedListener_ ||
-        this.onBluetoothDeviceRemoved_.bind(this);
-    this.bluetooth.onDeviceRemoved.addListener(
-        this.bluetoothDeviceRemovedListener_);
-  },
-
   /** @override */
   detached: function() {
-    this.bluetooth.onDeviceAdded.removeListener(
-        assert(this.bluetoothDeviceAddedListener_));
-    this.bluetooth.onDeviceChanged.removeListener(
-        assert(this.bluetoothDeviceUpdatedListener_));
-    this.bluetooth.onDeviceRemoved.removeListener(
-        assert(this.bluetoothDeviceRemovedListener_));
+    if (this.updateTimerId_ !== undefined) {
+      window.clearInterval(this.updateTimerId_);
+      this.updateTimerId_ = undefined;
+      this.deviceList_ = [];
+    }
   },
 
   /**
@@ -215,6 +174,7 @@
    */
   currentRouteChanged: function(route) {
     this.updateDiscovery_();
+    this.startOrStopRefreshingDeviceList_();
   },
 
   /** @private */
@@ -225,24 +185,62 @@
   /** @private */
   adapterStateChanged_: function() {
     this.updateDiscovery_();
-    this.updateDeviceList_();
+    this.startOrStopRefreshingDeviceList_();
   },
 
   /** @private */
   deviceListChanged_: function() {
     this.saveScroll(this.$.pairedDevices);
     this.saveScroll(this.$.unpairedDevices);
-    this.pairedDeviceList_ = this.deviceList_.filter(function(device) {
-      return !!device.paired || !!device.connecting;
-    });
-    this.unpairedDeviceList_ = this.deviceList_.filter(function(device) {
-      return !device.paired && !device.connecting;
-    });
+
+    this.pairedDeviceList_ = this.getUpdatedDeviceList_(
+      this.pairedDeviceList_,
+      this.deviceList_.filter(d => d.paired || d.connecting));
+    this.unpairedDeviceList_ = this.getUpdatedDeviceList_(
+      this.unpairedDeviceList_,
+      this.deviceList_.filter(d => !(d.paired || d.connecting)));
+
     this.updateScrollableContents();
     this.restoreScroll(this.$.unpairedDevices);
     this.restoreScroll(this.$.pairedDevices);
   },
 
+  /**
+   * Returns a copy of |oldDeviceList| but:
+   *   - Using the corresponding device objects in |newDeviceList|
+   *   - Removing devices not in |newDeviceList|
+   *   - Adding device not in |oldDeviceList| but in |newDeviceList| to the
+   *     end of the list.
+   *
+   * @param {!Array<!chrome.bluetooth.Device>} oldDeviceList
+   * @param {!Array<!chrome.bluetooth.Device>} newDeviceList
+   * @return {!Array<!chrome.bluetooth.Device>}
+   * @private
+   */
+  getUpdatedDeviceList_: function(oldDeviceList, newDeviceList) {
+    const newDeviceMap = new Map(newDeviceList.map(d => [d.address, d]));
+    const updatedDeviceList = [];
+
+    // Add elements of |oldDeviceList| that are in |newDeviceList| to
+    // |updatedDeviceList|.
+    for (const oldDevice of oldDeviceList) {
+      const newDevice = newDeviceMap.get(oldDevice.address);
+      if (newDevice === undefined) {
+        continue;
+      }
+      updatedDeviceList.push(newDevice);
+      newDeviceMap.delete(newDevice.address);
+    }
+
+    // Add all elements of |newDeviceList| that are not in |oldDeviceList| to
+    // |updatedDeviceList|.
+    for (const newDevice of newDeviceMap.values()) {
+      updatedDeviceList.push(newDevice);
+    }
+
+    return updatedDeviceList;
+  },
+
   /** @private */
   selectedPairedItemChanged_: function() {
     if (this.selectedPairedItem_) {
@@ -269,62 +267,6 @@
     }
   },
 
-  /**
-   * If bluetooth is enabled, request the complete list of devices and update
-   * this.deviceList_.
-   * @private
-   */
-  updateDeviceList_: function() {
-    if (!this.adapterState || !this.adapterState.powered) {
-      this.deviceList_ = [];
-      return;
-    }
-    this.requestListUpdate_();
-  },
-
-  /**
-   * Process onDeviceChanged events.
-   * @param {!chrome.bluetooth.Device} device
-   * @private
-   */
-  onBluetoothDeviceUpdated_: function(device) {
-    const address = device.address;
-    if (this.dialogShown_ && this.pairingDevice_ &&
-        this.pairingDevice_.address == address) {
-      this.pairingDevice_ = device;
-    }
-    const index = this.deviceList_.findIndex(function(device) {
-      return device.address == address;
-    });
-    if (index >= 0) {
-      this.set('deviceList_.' + index, device);
-    }
-  },
-
-  /**
-   * Process bluetooth.onDeviceAdded events.
-   * @param {!chrome.bluetooth.Device} device
-   * @private
-   */
-  onBluetoothDeviceAdded_: function(device) {
-    this.requestListUpdate_();
-  },
-
-  /**
-   * Process bluetooth.onDeviceRemoved events.
-   * @param {!chrome.bluetooth.Device} device
-   * @private
-   */
-  onBluetoothDeviceRemoved_: function(device) {
-    const address = device.address;
-    const index = this.deviceList_.findIndex(function(device) {
-      return device.address == address;
-    });
-    if (index >= 0) {
-      this.splice('deviceList_', index, 1);
-    }
-  },
-
   /** @private */
   startDiscovery_: function() {
     if (!this.adapterState || this.adapterState.discovering) {
@@ -484,7 +426,6 @@
             'Error forgetting: ' + device.name + ': ' +
             chrome.runtime.lastError.message);
       }
-      this.updateDeviceList_();
     });
   },
 
@@ -511,45 +452,6 @@
   },
 
   /**
-   * Requests update for bluetooth list.
-   * @private
-   */
-  requestListUpdate_: function() {
-    if (this.deviceList_.length == 0) {
-      // Update immediately for the initial device list.
-      this.refreshBluetoothList_();
-      return;
-    }
-
-    // Return here because an update is already queued.
-    if (this.updateTimerId_ !== undefined) {
-      return;
-    }
-
-    // Call bluetooth.getDevices once per listUpdateFrequencyMs.
-    this.updateTimerId_ = window.setTimeout(() => {
-      if (settings.getCurrentRoute() != settings.routes.BLUETOOTH_DEVICES) {
-        this.stopListUpdate_();
-        return;
-      }
-
-      this.refreshBluetoothList_();
-      this.updateTimerId_ = undefined;
-    }, this.listUpdateFrequencyMs);
-  },
-
-  /**
-   * Stops update for bluetooth list.
-   * @private
-   */
-  stopListUpdate_: function() {
-    if (this.updateTimerId_ !== undefined) {
-      window.clearTimeout(this.updateTimerId_);
-      this.updateTimerId_ = undefined;
-    }
-  },
-
-  /**
    * Requests bluetooth device list from Chrome. Update deviceList_ once the
    * results are returned from chrome.
    * @private
@@ -563,4 +465,37 @@
       this.deviceList_ = devices;
     });
   },
+
+  /** @private */
+  startOrStopRefreshingDeviceList_: function() {
+    if (this.adapterState && this.adapterState.powered) {
+      if (this.updateTimerId_ !== undefined) {
+        return;
+      }
+
+      this.refreshBluetoothList_();
+      this.updateTimerId_ =
+        window.setInterval(this.refreshBluetoothList_.bind(this),
+                           this.listUpdateFrequencyMs);
+      return;
+    }
+    window.clearInterval(this.updateTimerId_);
+    this.updateTimerId_ = undefined;
+    this.deviceList_ = [];
+  },
+
+  /**
+   * Restarts the timer when the frequency changes, which happens
+   * during tests.
+   */
+  listUpdateFrequencyMsChanged_: function() {
+    if (this.updateTimerId_ === undefined) {
+      return;
+    }
+
+    window.clearInterval(this.updateTimerId_);
+    this.updateTimerId_ = undefined;
+
+    this.startOrStopRefreshingDeviceList_();
+  }
 });
diff --git a/chrome/browser/resources/settings/site_settings/all_sites.html b/chrome/browser/resources/settings/site_settings/all_sites.html
index 2b81e9e9..1255663 100644
--- a/chrome/browser/resources/settings/site_settings/all_sites.html
+++ b/chrome/browser/resources/settings/site_settings/all_sites.html
@@ -8,6 +8,7 @@
 <link rel="import" href="../settings_shared_css.html">
 <link rel="import" href="../settings_vars_css.html">
 <link rel="import" href="site_entry.html">
+<link rel="import" href="site_settings_behavior.html">
 
 <dom-module id="all-sites">
   <template>
@@ -66,7 +67,7 @@
           items="[[filteredList_]]"
           scroll-target="[[subpageScrollTarget]]">
         <template>
-          <site-entry site-group="{{item}}" list-index="[[index]]"
+          <site-entry site-group="[[item]]" list-index="[[index]]"
               iron-list-tab-index="[[tabIndex]]"
               tabindex$="[[tabIndex]]"
               last-focused="{{lastFocused_}}"
@@ -75,6 +76,70 @@
         </template>
       </iron-list>
     </div>
+
+    <!-- Overflow menu. -->
+    <cr-lazy-render id="menu">
+      <template>
+        <cr-action-menu>
+          <button class="dropdown-item" role="menuitem"
+              on-click="onConfirmResetSettings_">
+            $i18n{siteSettingsSiteGroupReset}
+          </button>
+          <button class="dropdown-item" role="menuitem"
+              on-click="onConfirmClearData_">
+            $i18n{siteSettingsSiteGroupDelete}
+          </button>
+        </cr-action-menu>
+      </template>
+    </cr-lazy-render>
+
+    <!-- Confirm reset settings dialog. -->
+    <cr-lazy-render id="confirmResetSettings">
+      <template>
+        <cr-dialog close-text="$i18n{close}">
+          <div slot="title">
+            $i18n{siteSettingsSiteGroupResetDialogTitle}
+          </div>
+          <div slot="body">
+            [[getFormatString_(
+                '$i18nPolymer{siteSettingsSiteGroupResetConfirmation}',
+                actionMenuModel_.item.etldPlus1)]]
+          </div>
+          <div slot="button-container">
+            <paper-button class="cancel-button" on-click="onCloseDialog_">
+              $i18n{cancel}
+            </paper-button>
+            <paper-button class="action-button" on-click="onResetSettings_">
+              $i18n{siteSettingsSiteResetAll}
+            </paper-button>
+          </div>
+        </cr-dialog>
+      </template>
+    </cr-lazy-render>
+
+    <!-- Confirm clear data dialog. -->
+    <cr-lazy-render id="confirmClearData">
+      <template>
+        <cr-dialog close-text="$i18n{close}">
+          <div slot="title">
+            $i18n{siteSettingsSiteGroupDeleteDialogTitle}
+          </div>
+          <div slot="body">
+            [[getFormatString_(
+                '$i18nPolymer{siteSettingsSiteGroupDeleteConfirmation}',
+                actionMenuModel_.item.etldPlus1)]]
+          </div>
+          <div slot="button-container">
+            <paper-button class="cancel-button" on-click="onCloseDialog_">
+              $i18n{cancel}
+            </paper-button>
+            <paper-button class="action-button" on-click="onClearData_">
+              $i18n{siteSettingsSiteClearStorage}
+            </paper-button>
+          </div>
+        </cr-dialog>
+      </template>
+    </cr-lazy-render>
   </template>
   <script src="all_sites.js"></script>
 </dom-module>
diff --git a/chrome/browser/resources/settings/site_settings/all_sites.js b/chrome/browser/resources/settings/site_settings/all_sites.js
index c248216..341dc5b 100644
--- a/chrome/browser/resources/settings/site_settings/all_sites.js
+++ b/chrome/browser/resources/settings/site_settings/all_sites.js
@@ -95,6 +95,16 @@
      * focusRowBehavior.
      */
     listBlurred_: Boolean,
+
+    /**
+     * @private {?{
+     *   index: number,
+     *   item: !SiteGroup,
+     *   path: string,
+     *   target: !HTMLElement
+     * }}
+     */
+    actionMenuModel_: Object,
   },
 
   /** @private {?settings.LocalDataBrowserProxy} */
@@ -107,7 +117,7 @@
   },
 
   listeners: {
-    'delete-current-entry': 'onDeleteCurrentEntry_',
+    'open-menu': 'onOpenMenu_',
   },
 
   /** @override */
@@ -258,8 +268,6 @@
   /**
    * Comparator used to sort SiteGroups by the amount of storage they use. Note
    * this sorts in descending order.
-   * TODO(https://crbug.com/835712): Account for website storage in sorting by
-   * storage used.
    * @param {!SiteGroup} siteGroup1
    * @param {!SiteGroup} siteGroup2
    * @private
@@ -340,16 +348,6 @@
   },
 
   /**
-   * Delete an entry from |siteGroupMap| for given etldPlus1.
-   * @param {!CustomEvent<!{etldPlus1: string}>} e
-   * @private
-   */
-  onDeleteCurrentEntry_: function(e) {
-    this.siteGroupMap.delete(e.detail.etldPlus1);
-    this.forceListUpdate_();
-  },
-
-  /**
    * Focus on previously selected entry.
    * @private
    */
@@ -363,5 +361,158 @@
     const index =
         Math.max(0, Math.min(this.selectedItem_.index, this.siteGroupMap.size));
     this.$.allSitesList.focusItem(index);
-  }
-});
+  },
+
+  /**
+   * Open the overflow menu and ensure that the item is visible in the scroll
+   * pane when its menu is opened (it is possible to open off-screen items using
+   * keyboard shortcuts).
+   * @param {!CustomEvent<{
+   *    index: number, item: !SiteGroup,
+   *    path: string, target: !HTMLElement
+   *    }>} e
+   * @private
+   */
+  onOpenMenu_: function(e) {
+    if (this.actionMenuModel_) {
+      return;
+    }
+    const index = e.detail.index;
+    const list = /** @type {IronListElement} */ (this.$['allSitesList']);
+    if (index < list.firstVisibleIndex || index > list.lastVisibleIndex) {
+      list.scrollToIndex(index);
+    }
+    const target = e.detail.target;
+    this.actionMenuModel_ = e.detail;
+    const menu = /** @type {CrActionMenuElement} */ (this.$.menu.get());
+    menu.showAt(target);
+  },
+
+  /**
+   * Confirms the resetting of all content settings for an origin.
+   * @param {!Event} e
+   * @private
+   */
+  onConfirmResetSettings_: function(e) {
+    e.preventDefault();
+    this.$.confirmResetSettings.get().showModal();
+  },
+
+  /**
+   * Confirms the clearing of all storage data for an etld+1.
+   * @param {!Event} e
+   * @private
+   */
+  onConfirmClearData_: function(e) {
+    e.preventDefault();
+    this.$.confirmClearData.get().showModal();
+  },
+
+  /** @private */
+  onCloseDialog_: function(e) {
+    e.target.closest('cr-dialog').close();
+    this.actionMenuModel_ = null;
+    this.$.menu.get().close();
+  },
+
+  /**
+   * Formats the |label| string with |name|, using $<num> as markers.
+   * @param {string} label
+   * @param {string} name
+   * @return {string}
+   * @private
+   */
+  getFormatString_: function(label, name) {
+    return loadTimeData.substituteString(label, name);
+  },
+
+  /**
+   * Resets all permissions for all origins listed in |siteGroup.origins|.
+   * @param {!Event} e
+   * @private
+   */
+  onResetSettings_: function(e) {
+    const contentSettingsTypes = this.getCategoryList();
+    const index = this.actionMenuModel_.index;
+    if (this.actionMenuModel_.item.etldPlus1 !=
+        this.filteredList_[index].etldPlus1) {
+      return;
+    }
+    for (let i = 0; i < this.filteredList_[index].origins.length; ++i) {
+      const origin = this.filteredList_[index].origins[i].origin;
+      this.browserProxy.setOriginPermissions(
+          origin, contentSettingsTypes, settings.ContentSetting.DEFAULT);
+      if (contentSettingsTypes.includes(
+              settings.ContentSettingsTypes.PLUGINS)) {
+        this.browserProxy.clearFlashPref(origin);
+      }
+      this.filteredList_[index].origins[i].hasPermissionSettings = false;
+    }
+    const updatedSiteGroup = {
+      etldPlus1: this.filteredList_[index].etldPlus1,
+      numCookies: this.filteredList_[index].numCookies,
+      origins: []
+    };
+    for (let i = 0; i < this.filteredList_[index].origins.length; ++i) {
+      const updatedOrigin =
+          Object.assign({}, this.filteredList_[index].origins[i]);
+      if (updatedOrigin.numCookies > 0 || updatedOrigin.usage > 0) {
+        updatedOrigin.hasPermissionSettings = false;
+        updatedSiteGroup.origins.push(updatedOrigin);
+      }
+    }
+    if (updatedSiteGroup.origins.length > 0) {
+      this.set('filteredList_.' + index, updatedSiteGroup);
+    } else if (this.filteredList_[index].numCookies > 0) {
+      // If there is no origin for this site group that has any data,
+      // but the ETLD+1 has cookies in use, create a origin placeholder
+      // for display purposes.
+      const originPlaceHolder = {
+        origin: 'http://' + this.filteredList_[index].etldPlus1 + '/',
+        engagement: 0,
+        usage: 0,
+        numCookies: this.filteredList_[index].numCookies,
+        hasPermissionSettings: false
+      };
+      updatedSiteGroup.origins.push(originPlaceHolder);
+      this.set('filteredList_.' + index, updatedSiteGroup);
+    } else {
+      this.splice('filteredList_', index, 1);
+    }
+    this.$.allSitesList.fire('iron-resize');
+    this.onCloseDialog_(e);
+  },
+
+  /**
+   * Clear data and cookies for an etldPlus1.
+   * @param {!Event} e
+   * @private
+   */
+  onClearData_: function(e) {
+    const index = this.actionMenuModel_.index;
+    // Clean up the SiteGroup.
+    this.browserProxy.clearEtldPlus1DataAndCookies(
+        this.filteredList_[index].etldPlus1);
+    const updatedSiteGroup = {
+      etldPlus1: this.filteredList_[index].etldPlus1,
+      numCookies: 0,
+      origins: []
+    };
+    for (let i = 0; i < this.filteredList_[index].origins.length; ++i) {
+      const updatedOrigin =
+          Object.assign({}, this.filteredList_[index].origins[i]);
+      if (updatedOrigin.hasPermissionSettings) {
+        updatedOrigin.numCookies = 0;
+        updatedOrigin.usage = 0;
+        updatedSiteGroup.origins.push(updatedOrigin);
+      }
+    }
+    if (updatedSiteGroup.origins.length > 0) {
+      this.set('filteredList_.' + index, updatedSiteGroup);
+    } else {
+      this.splice('filteredList_', index, 1);
+    }
+    this.$.allSitesList.fire('iron-resize');
+    this.onCloseDialog_(e);
+  },
+});
\ No newline at end of file
diff --git a/chrome/browser/resources/settings/site_settings/site_entry.html b/chrome/browser/resources/settings/site_settings/site_entry.html
index 8fc9bd0..5e543e9 100644
--- a/chrome/browser/resources/settings/site_settings/site_entry.html
+++ b/chrome/browser/resources/settings/site_settings/site_entry.html
@@ -130,62 +130,6 @@
         </div>
       </iron-collapse>
     </div>
-
-    <!-- Overflow menu. -->
-    <cr-lazy-render id="menu">
-      <template>
-        <cr-action-menu>
-          <button class="dropdown-item" role="menuitem"
-              on-click="onConfirmResetSettings_">
-            $i18n{siteSettingsSiteGroupReset}
-          </button>
-          <button class="dropdown-item" role="menuitem"
-              on-click="onConfirmClearData_">
-            $i18n{siteSettingsSiteGroupDelete}
-          </button>
-        </cr-action-menu>
-      </template>
-    </cr-lazy-render>
-
-    <!-- Confirm reset settings dialog. -->
-    <cr-dialog id="confirmResetSettings" close-text="$i18n{close}">
-      <div slot="title">
-        $i18n{siteSettingsSiteGroupResetDialogTitle}
-      </div>
-      <div slot="body">
-        [[getFormatString_(
-            '$i18nPolymer{siteSettingsSiteGroupResetConfirmation}',
-            displayName_)]]
-      </div>
-      <div slot="button-container">
-        <paper-button class="cancel-button" on-click="onCloseDialog_">
-          $i18n{cancel}
-        </paper-button>
-        <paper-button class="action-button" on-click="onResetSettings_">
-          $i18n{siteSettingsSiteResetAll}
-        </paper-button>
-      </div>
-    </cr-dialog>
-
-    <!-- Confirm clear data dialog. -->
-    <cr-dialog id="confirmClearData" close-text="$i18n{close}">
-      <div slot="title">
-        $i18n{siteSettingsSiteGroupDeleteDialogTitle}
-      </div>
-      <div slot="body">
-        [[getFormatString_(
-            '$i18nPolymer{siteSettingsSiteGroupDeleteConfirmation}',
-            displayName_)]]
-      </div>
-      <div slot="button-container">
-        <paper-button class="cancel-button" on-click="onCloseDialog_">
-          $i18n{cancel}
-        </paper-button>
-        <paper-button class="action-button" on-click="onClearData_">
-          $i18n{siteSettingsSiteClearStorage}
-        </paper-button>
-      </div>
-    </cr-dialog>
   </template>
   <script src="site_entry.js"></script>
 </dom-module>
diff --git a/chrome/browser/resources/settings/site_settings/site_entry.js b/chrome/browser/resources/settings/site_settings/site_entry.js
index 6dcf0e7..3cdb71e 100644
--- a/chrome/browser/resources/settings/site_settings/site_entry.js
+++ b/chrome/browser/resources/settings/site_settings/site_entry.js
@@ -75,10 +75,6 @@
     }
   },
 
-  listeners: {
-    'focus': 'onFocus_',
-  },
-
   /** @private {?settings.LocalDataBrowserProxy} */
   localDataBrowserProxy_: null,
 
@@ -345,136 +341,17 @@
   },
 
   /**
-   * Opens the overflow menu at event target.
-   * @param {!{target: !Element}} e
+   * Fires a custom event when the menu button is clicked. Sends the details
+   * of the site entry item and where the menu should appear.
+   * @param {!Event} e
    * @private
    */
   showOverflowMenu_: function(e) {
-    this.$.menu.get().showAt(e.target);
-  },
-
-  /** @private */
-  onCloseDialog_: function(e) {
-    e.target.closest('cr-dialog').close();
-    this.$.menu.get().close();
-  },
-
-  /**
-   * Confirms the resetting of all content settings for an origin.
-   * @param {!Event} e
-   * @private
-   */
-  onConfirmResetSettings_: function(e) {
-    e.preventDefault();
-    this.$.confirmResetSettings.showModal();
-  },
-
-  /**
-   * Confirms the clearing of all storage data for an etld+1.
-   * @param {!Event} e
-   * @private
-   */
-  onConfirmClearData_: function(e) {
-    e.preventDefault();
-    this.$.confirmClearData.showModal();
-  },
-
-  /**
-   * Resets all permissions for all origins listed in |siteGroup.origins|.
-   * @param {!Event} e
-   * @private
-   */
-  onResetSettings_: function(e) {
-    const contentSettingsTypes = this.getCategoryList();
-    for (let i = 0; i < this.siteGroup.origins.length; ++i) {
-      const origin = this.siteGroup.origins[i].origin;
-      this.browserProxy.setOriginPermissions(
-          origin, contentSettingsTypes, settings.ContentSetting.DEFAULT);
-      if (contentSettingsTypes.includes(
-              settings.ContentSettingsTypes.PLUGINS)) {
-        this.browserProxy.clearFlashPref(origin);
-      }
-      this.siteGroup.origins[i].hasPermissionSettings = false;
-    }
-    // Create a new |siteGroup| to make an observable change.
-    const updatedSiteGroup = {
-      etldPlus1: this.siteGroup.etldPlus1,
-      numCookies: this.siteGroup.numCookies,
-      origins: []
-    };
-    for (let i = 0; i < this.siteGroup.origins.length; ++i) {
-      const updatedOrigin = Object.assign({}, this.siteGroup.origins[i]);
-      if (updatedOrigin.numCookies > 0 || updatedOrigin.usage > 0) {
-        updatedOrigin.hasPermissionSettings = false;
-        updatedSiteGroup.origins.push(updatedOrigin);
-      }
-    }
-    if (updatedSiteGroup.origins.length > 0) {
-      this.siteGroup = updatedSiteGroup;
-    } else if (this.siteGroup.numCookies > 0) {
-      // If there is no origin for this site group that has any data,
-      // but the ETLD+1 has cookies in use, create a origin placeholder
-      // for display purposes.
-      const originPlaceHolder = {
-        origin: 'http://' + this.siteGroup.etldPlus1 + '/',
-        engagement: 0,
-        usage: 0,
-        numCookies: this.siteGroup.numCookies,
-        hasPermissionSettings: false
-      };
-      updatedSiteGroup.origins.push(originPlaceHolder);
-      this.siteGroup = updatedSiteGroup;
-    } else {
-      this.fire('delete-current-entry', {
-        etldPlus1: this.siteGroup.etldPlus1,
-      });
-    }
-    this.fire('iron-resize');
-    this.onCloseDialog_(e);
-  },
-
-  /**
-   * Clear data and cookies for an etldPlus1.
-   * @param {!Event} e
-   * @private
-   */
-  onClearData_: function(e) {
-    // Clean up the SiteGroup.
-    this.browserProxy.clearEtldPlus1DataAndCookies(this.siteGroup.etldPlus1);
-    // Create a new |siteGroup| to make an observable change.
-    const updatedSiteGroup = {
-      etldPlus1: this.siteGroup.etldPlus1,
-      numCookies: 0,
-      origins: []
-    };
-    for (let i = 0; i < this.siteGroup.origins.length; ++i) {
-      const updatedOrigin = Object.assign({}, this.siteGroup.origins[i]);
-      if (updatedOrigin.hasPermissionSettings) {
-        updatedOrigin.numCookies = 0;
-        updatedOrigin.usage = 0;
-        updatedSiteGroup.origins.push(updatedOrigin);
-      }
-    }
-    if (updatedSiteGroup.origins.length > 0) {
-      this.siteGroup = updatedSiteGroup;
-    } else {
-      this.fire('delete-current-entry', {
-        etldPlus1: this.siteGroup.etldPlus1,
-      });
-    }
-    this.fire('iron-resize');
-    this.onCloseDialog_(e);
-  },
-
-  /**
-   * Formats the |label| string with |name|, using $<num> as markers.
-   * @param {string} label
-   * @param {string} name
-   * @return {string}
-   * @private
-   */
-  getFormatString_: function(label, name) {
-    return loadTimeData.substituteString(label, name);
+    this.fire('open-menu', {
+      target: Polymer.dom(e).localTarget,
+      index: this.listIndex,
+      item: this.siteGroup,
+    });
   },
 
   /**
@@ -502,12 +379,4 @@
     }
     return '';
   },
-
-  /**
-   * Focuses the first focusable button in this site-entry.
-   * @private
-   */
-  onFocus_: function() {
-    this.button_.focus();
-  },
 });
diff --git a/chrome/browser/resources/settings/site_settings/site_list_entry.html b/chrome/browser/resources/settings/site_settings/site_list_entry.html
index aeb9be89d..8fe5ddbb 100644
--- a/chrome/browser/resources/settings/site_settings/site_list_entry.html
+++ b/chrome/browser/resources/settings/site_settings/site_list_entry.html
@@ -34,7 +34,7 @@
     </style>
     <div class="list-item" focus-row-container>
       <div class="settings-row"
-          actionable$="[[enableSiteSettings_]]" on-click="onOriginTap_">
+          actionable$="[[allowNavigateToSiteDetail_]]" on-click="onOriginTap_">
         <site-favicon url="[[model.origin]]"></site-favicon>
         <div class="middle no-min-width">
           <div class="text-elide">
@@ -45,14 +45,12 @@
           <div class="secondary text-elide"
               id="siteDescription">[[siteDescription_]]</div>
         </div>
-        <template is="dom-if" if="[[enableSiteSettings_]]">
-          <div on-click="onOriginTap_" actionable>
-            <paper-icon-button-light class="subpage-arrow">
-              <button aria-label$="[[model.displayName]]"
-                  aria-describedby="siteDescription" focus-row-control
-                  focus-type="site-details"></button>
-            </paper-icon-button-light>
-          </div>
+        <template is="dom-if" if="[[allowNavigateToSiteDetail_]]">
+          <paper-icon-button-light class="subpage-arrow">
+            <button aria-label$="[[model.displayName]]"
+                aria-describedby="siteDescription" focus-row-control
+                focus-type="site-details"></button>
+          </paper-icon-button-light>
           <div class="separator"></div>
         </template>
       </div>
diff --git a/chrome/browser/resources/settings/site_settings/site_list_entry.js b/chrome/browser/resources/settings/site_settings/site_list_entry.js
index d7f785eb..d6d662e 100644
--- a/chrome/browser/resources/settings/site_settings/site_list_entry.js
+++ b/chrome/browser/resources/settings/site_settings/site_list_entry.js
@@ -37,7 +37,10 @@
      * Site to display in the widget.
      * @type {!SiteException}
      */
-    model: Object,
+    model: {
+      type: Object,
+      observer: 'onModelChanged_',
+    },
 
     /**
      * If the site represented is part of a chooser exception, the chooser type
@@ -70,6 +73,12 @@
       type: Boolean,
       computed: 'computeShowPolicyPrefIndicator_(model)',
     },
+
+    /** @private */
+    allowNavigateToSiteDetail_: {
+      type: Boolean,
+      value: false,
+    },
   },
 
   /** @private */
@@ -113,11 +122,10 @@
 
   /**
    * A handler for selecting a site (by clicking on the origin).
-   * @param {!{model: !{item: !SiteException}}} event
    * @private
    */
-  onOriginTap_: function(event) {
-    if (!this.enableSiteSettings_) {
+  onOriginTap_: function() {
+    if (!this.allowNavigateToSiteDetail_) {
       return;
     }
     settings.navigateTo(
@@ -193,4 +201,15 @@
         'show-action-menu',
         {anchor: this.$.actionMenuButton, model: this.model});
   },
+
+  /** @private */
+  onModelChanged_: function() {
+    if (!this.model) {
+      this.allowNavigateToSiteDetail_ = false;
+      return;
+    }
+    this.browserProxy.isOriginValid(this.model.origin).then((valid) => {
+      this.allowNavigateToSiteDetail_ = valid && this.enableSiteSettings_;
+    });
+  }
 });
diff --git a/chrome/browser/safe_browsing/advanced_protection_status_manager.cc b/chrome/browser/safe_browsing/advanced_protection_status_manager.cc
index 25b269c9..0bce90c 100644
--- a/chrome/browser/safe_browsing/advanced_protection_status_manager.cc
+++ b/chrome/browser/safe_browsing/advanced_protection_status_manager.cc
@@ -97,7 +97,7 @@
   return timer_.IsRunning();
 }
 
-void AdvancedProtectionStatusManager::OnAccountUpdated(
+void AdvancedProtectionStatusManager::OnExtendedAccountInfoUpdated(
     const AccountInfo& info) {
   // Ignore update if |profile_| is in incognito mode, or the updated account
   // is not the primary account.
@@ -113,7 +113,7 @@
   }
 }
 
-void AdvancedProtectionStatusManager::OnAccountRemovedWithInfo(
+void AdvancedProtectionStatusManager::OnExtendedAccountInfoRemoved(
     const AccountInfo& info) {
   if (profile_->IsOffTheRecord())
     return;
diff --git a/chrome/browser/safe_browsing/advanced_protection_status_manager.h b/chrome/browser/safe_browsing/advanced_protection_status_manager.h
index bfc9c7c3..cb61211 100644
--- a/chrome/browser/safe_browsing/advanced_protection_status_manager.h
+++ b/chrome/browser/safe_browsing/advanced_protection_status_manager.h
@@ -84,8 +84,8 @@
   // IdentityManager::Observer implementations.
   void OnPrimaryAccountSet(const CoreAccountInfo& account_info) override;
   void OnPrimaryAccountCleared(const CoreAccountInfo& account_info) override;
-  void OnAccountUpdated(const AccountInfo& info) override;
-  void OnAccountRemovedWithInfo(const AccountInfo& info) override;
+  void OnExtendedAccountInfoUpdated(const AccountInfo& info) override;
+  void OnExtendedAccountInfoRemoved(const AccountInfo& info) override;
 
   void OnAdvancedProtectionEnabled();
 
diff --git a/chrome/browser/supervised_user/child_accounts/child_account_service.cc b/chrome/browser/supervised_user/child_accounts/child_account_service.cc
index 323d2177..99a7586 100644
--- a/chrome/browser/supervised_user/child_accounts/child_account_service.cc
+++ b/chrome/browser/supervised_user/child_accounts/child_account_service.cc
@@ -103,7 +103,7 @@
   // If we're already signed in, check the account immediately just to be sure.
   // (We might have missed an update before registering as an observer.)
   if (identity_manager_->HasPrimaryAccount())
-    OnAccountUpdated(identity_manager_->GetPrimaryAccountInfo());
+    OnExtendedAccountInfoUpdated(identity_manager_->GetPrimaryAccountInfo());
 }
 
 bool ChildAccountService::IsChildAccountStatusKnown() {
@@ -248,7 +248,8 @@
   status_received_callback_list_.clear();
 }
 
-void ChildAccountService::OnAccountUpdated(const AccountInfo& info) {
+void ChildAccountService::OnExtendedAccountInfoUpdated(
+    const AccountInfo& info) {
   // This method may get called when the account info isn't complete yet.
   // We deliberately don't check for that, as we are only interested in the
   // child account status.
@@ -265,7 +266,8 @@
   SetIsChildAccount(info.is_child_account);
 }
 
-void ChildAccountService::OnAccountRemovedWithInfo(const AccountInfo& info) {
+void ChildAccountService::OnExtendedAccountInfoRemoved(
+    const AccountInfo& info) {
   SetIsChildAccount(false);
 }
 
diff --git a/chrome/browser/supervised_user/child_accounts/child_account_service.h b/chrome/browser/supervised_user/child_accounts/child_account_service.h
index 89c0bb9..4d60cdd 100644
--- a/chrome/browser/supervised_user/child_accounts/child_account_service.h
+++ b/chrome/browser/supervised_user/child_accounts/child_account_service.h
@@ -79,8 +79,8 @@
   void SetIsChildAccount(bool is_child_account);
 
   // identity::IdentityManager::Observer implementation.
-  void OnAccountUpdated(const AccountInfo& info) override;
-  void OnAccountRemovedWithInfo(const AccountInfo& info) override;
+  void OnExtendedAccountInfoUpdated(const AccountInfo& info) override;
+  void OnExtendedAccountInfoRemoved(const AccountInfo& info) override;
 
   // FamilyInfoFetcher::Consumer implementation.
   void OnGetFamilyMembersSuccess(
diff --git a/chrome/browser/ui/app_list/search/search_result_ranker/app_launch_predictor_test_util.h b/chrome/browser/ui/app_list/search/search_result_ranker/app_launch_predictor_test_util.h
index 1e3dcbe1f..e7f07f50 100644
--- a/chrome/browser/ui/app_list/search/search_result_ranker/app_launch_predictor_test_util.h
+++ b/chrome/browser/ui/app_list/search/search_result_ranker/app_launch_predictor_test_util.h
@@ -217,8 +217,6 @@
 
 DEFINE_EQUIVTO_PROTO_LITE_1(FakePredictorProto, counts);
 
-DEFINE_EQUIVTO_PROTO_LITE_DEFAULT(FrecencyPredictorProto);
-
 DEFINE_EQUIVTO_PROTO_LITE_5(FrecencyStoreProto,
                             values,
                             value_limit,
@@ -240,12 +238,9 @@
 
 DEFINE_EQUIVTO_PROTO_LITE_2(RecurrencePredictorProto,
                             fake_predictor,
-                            frecency_predictor);
+                            zero_state_frecency_predictor);
 
-DEFINE_EQUIVTO_PROTO_LITE_3(RecurrenceRankerProto,
-                            config_hash,
-                            predictor,
-                            targets);
+DEFINE_EQUIVTO_PROTO_LITE_2(RecurrenceRankerProto, config_hash, predictor);
 
 DEFINE_EQUIVTO_PROTO_LITE_2(SerializedMrfuAppLaunchPredictorProto,
                             num_of_trains,
@@ -254,6 +249,9 @@
 DEFINE_EQUIVTO_PROTO_LITE_2(SerializedMrfuAppLaunchPredictorProto_Score,
                             num_of_trains_at_last_update,
                             last_score);
+
+DEFINE_EQUIVTO_PROTO_LITE_1(ZeroStateFrecencyPredictorProto, targets);
+
 }  // namespace internal
 
 template <typename Proto>
diff --git a/chrome/browser/ui/app_list/search/search_result_ranker/frecency_store.cc b/chrome/browser/ui/app_list/search/search_result_ranker/frecency_store.cc
index 101aa786..d2e9352 100644
--- a/chrome/browser/ui/app_list/search/search_result_ranker/frecency_store.cc
+++ b/chrome/browser/ui/app_list/search/search_result_ranker/frecency_store.cc
@@ -22,7 +22,13 @@
 }  // namespace
 
 FrecencyStore::FrecencyStore(int value_limit, float decay_coeff)
-    : value_limit_(value_limit), decay_coeff_(decay_coeff) {}
+    : value_limit_(value_limit), decay_coeff_(decay_coeff) {
+  if (decay_coeff <= 0.0f || decay_coeff >= 1.0f) {
+    LOG(ERROR) << "FrecencyStore decay_coeff has invalid value: " << decay_coeff
+               << ", resetting to default.";
+    decay_coeff_ = 0.75f;
+  }
+}
 
 FrecencyStore::~FrecencyStore() {}
 
diff --git a/chrome/browser/ui/app_list/search/search_result_ranker/recurrence_predictor.cc b/chrome/browser/ui/app_list/search/search_result_ranker/recurrence_predictor.cc
index efc748f..bd564168f 100644
--- a/chrome/browser/ui/app_list/search/search_result_ranker/recurrence_predictor.cc
+++ b/chrome/browser/ui/app_list/search/search_result_ranker/recurrence_predictor.cc
@@ -7,26 +7,44 @@
 #include <cmath>
 
 #include "base/logging.h"
+#include "chrome/browser/ui/app_list/search/search_result_ranker/frecency_store.h"
+#include "chrome/browser/ui/app_list/search/search_result_ranker/frecency_store.pb.h"
 #include "chrome/browser/ui/app_list/search/search_result_ranker/recurrence_predictor.pb.h"
 
 namespace app_list {
 
-FakePredictor::FakePredictor() = default;
+FakePredictor::FakePredictor(FakePredictorConfig config) {}
 FakePredictor::~FakePredictor() = default;
 
-void FakePredictor::Train(unsigned int target) {
-  counts_[target] += 1.0f;
-}
-
-base::flat_map<unsigned int, float> FakePredictor::Rank() {
-  return counts_;
-}
-
 const char FakePredictor::kPredictorName[] = "FakePredictor";
 const char* FakePredictor::GetPredictorName() const {
   return kPredictorName;
 }
 
+void FakePredictor::Train(const std::string& target, const std::string& query) {
+  counts_[target] += 1.0f;
+}
+
+base::flat_map<std::string, float> FakePredictor::Rank(
+    const std::string& query) {
+  return counts_;
+}
+
+void FakePredictor::Rename(const std::string& target,
+                           const std::string& new_target) {
+  auto it = counts_.find(target);
+  if (it != counts_.end()) {
+    counts_[new_target] = it->second;
+    counts_.erase(it);
+  }
+}
+
+void FakePredictor::Remove(const std::string& target) {
+  auto it = counts_.find(target);
+  if (it != counts_.end())
+    counts_.erase(it);
+}
+
 void FakePredictor::ToProto(RecurrencePredictorProto* proto) const {
   auto* counts = proto->mutable_fake_predictor()->mutable_counts();
   for (auto& pair : counts_)
@@ -37,36 +55,72 @@
   if (!proto.has_fake_predictor())
     return;
 
-  auto fake_predictor_proto = proto.fake_predictor();
-  for (const auto& pair : fake_predictor_proto.counts()) {
+  auto predictor = proto.fake_predictor();
+  for (const auto& pair : predictor.counts())
     counts_[pair.first] = pair.second;
-  }
 }
 
-// |FrecencyPredictor| uses the |RecurrenceRanker|'s store of targets for
-// ranking, which is updated on calls to |RecurrenceRanker::Record|. So, there
-// is no training work for the predictor itself to do.
-void FrecencyPredictor::Train(unsigned int target) {}
+ZeroStateFrecencyPredictor::ZeroStateFrecencyPredictor(
+    ZeroStateFrecencyPredictorConfig config)
+    : targets_(std::make_unique<FrecencyStore>(config.target_limit(),
+                                               config.decay_coeff())) {}
+ZeroStateFrecencyPredictor::~ZeroStateFrecencyPredictor() = default;
 
-// |FrecencyPredictor::Rank| is special-cased inside |RecurrenceRanker::Record|
-// for efficiency reasons, so as not to do uneccessary conversion of targets to
-// ids and back.
-base::flat_map<unsigned int, float> FrecencyPredictor::Rank() {
-  NOTREACHED();
-  return {};
-}
-
-const char FrecencyPredictor::kPredictorName[] = "FrecencyPredictor";
-const char* FrecencyPredictor::GetPredictorName() const {
+const char ZeroStateFrecencyPredictor::kPredictorName[] =
+    "ZeroStateFrecencyPredictor";
+const char* ZeroStateFrecencyPredictor::GetPredictorName() const {
   return kPredictorName;
 }
 
-// Empty as all data used by the frecency predictor is serialised with
-// |RecurrenceRanker|.
-void FrecencyPredictor::ToProto(RecurrencePredictorProto* proto) const {}
+void ZeroStateFrecencyPredictor::Train(const std::string& target,
+                                       const std::string& query) {
+  if (!query.empty()) {
+    NOTREACHED();
+    LOG(ERROR) << "ZeroStateFrecencyPredictor was passed a query.";
+    return;
+  }
 
-// Empty as all data used by the frecency predictor is serialised with
-// |RecurrenceRanker|.
-void FrecencyPredictor::FromProto(const RecurrencePredictorProto& proto) {}
+  targets_->Update(target);
+}
+
+base::flat_map<std::string, float> ZeroStateFrecencyPredictor::Rank(
+    const std::string& query) {
+  if (!query.empty()) {
+    NOTREACHED();
+    LOG(ERROR) << "ZeroStateFrecencyPredictor was passed a query.";
+    return {};
+  }
+
+  base::flat_map<std::string, float> ranks;
+  for (const auto& target : targets_->GetAll())
+    ranks[target.first] = target.second.last_score;
+  return ranks;
+}
+
+void ZeroStateFrecencyPredictor::Rename(const std::string& target,
+                                        const std::string& new_target) {
+  targets_->Rename(target, new_target);
+}
+
+void ZeroStateFrecencyPredictor::Remove(const std::string& target) {
+  targets_->Remove(target);
+}
+
+void ZeroStateFrecencyPredictor::ToProto(
+    RecurrencePredictorProto* proto) const {
+  auto* targets =
+      proto->mutable_zero_state_frecency_predictor()->mutable_targets();
+  targets_->ToProto(targets);
+}
+
+void ZeroStateFrecencyPredictor::FromProto(
+    const RecurrencePredictorProto& proto) {
+  if (!proto.has_zero_state_frecency_predictor())
+    return;
+
+  const auto& predictor = proto.zero_state_frecency_predictor();
+  if (predictor.has_targets())
+    targets_->FromProto(predictor.targets());
+}
 
 }  // namespace app_list
diff --git a/chrome/browser/ui/app_list/search/search_result_ranker/recurrence_predictor.h b/chrome/browser/ui/app_list/search/search_result_ranker/recurrence_predictor.h
index c23306e..17a47740f 100644
--- a/chrome/browser/ui/app_list/search/search_result_ranker/recurrence_predictor.h
+++ b/chrome/browser/ui/app_list/search/search_result_ranker/recurrence_predictor.h
@@ -5,15 +5,23 @@
 #ifndef CHROME_BROWSER_UI_APP_LIST_SEARCH_SEARCH_RESULT_RANKER_RECURRENCE_PREDICTOR_H_
 #define CHROME_BROWSER_UI_APP_LIST_SEARCH_SEARCH_RESULT_RANKER_RECURRENCE_PREDICTOR_H_
 
+#include <memory>
 #include <string>
 #include <vector>
 
 #include "base/containers/flat_map.h"
 #include "base/macros.h"
 #include "chrome/browser/ui/app_list/search/search_result_ranker/recurrence_predictor.pb.h"
+#include "chrome/browser/ui/app_list/search/search_result_ranker/recurrence_ranker_config.pb.h"
 
 namespace app_list {
 
+using FakePredictorConfig = RecurrenceRankerConfigProto::FakePredictorConfig;
+using ZeroStateFrecencyPredictorConfig =
+    RecurrenceRankerConfigProto::ZeroStateFrecencyPredictorConfig;
+
+class FrecencyStore;
+
 // |RecurrencePredictor| is the interface for all predictors used by
 // |RecurrenceRanker| to drive rankings. If a predictor has some form of
 // serialisation, it should have a corresponding proto in
@@ -22,13 +30,21 @@
  public:
   virtual ~RecurrencePredictor() = default;
 
-  // Train the predictor on an occurrence of |target|. The predictor will
-  // collect its own contextual information, eg. time of day, as part of
-  // training.
-  virtual void Train(unsigned int target) = 0;
-  // Return a map of all known targets to their scores under this predictor.
-  // Scores must be within the range [0,1].
-  virtual base::flat_map<unsigned int, float> Rank() = 0;
+  // Train the predictor on an occurrence of |target| coinciding with |query|.
+  // The predictor will collect its own contextual information, eg. time of day,
+  // as part of training. Zero-state scenarios should use an empty string for
+  // |query|.
+  virtual void Train(const std::string& target, const std::string& query) = 0;
+  // Return a map of all known targets to their scores for the given query
+  // under this predictor. Scores must be within the range [0,1]. Zero-state
+  // scenarios should use an empty string for |query|.
+  virtual base::flat_map<std::string, float> Rank(const std::string& query) = 0;
+
+  // Rename a target, while keeping learned information on it.
+  virtual void Rename(const std::string& target,
+                      const std::string& new_target) = 0;
+  // Remove a target entirely.
+  virtual void Remove(const std::string& target) = 0;
 
   virtual void ToProto(RecurrencePredictorProto* proto) const = 0;
   virtual void FromProto(const RecurrencePredictorProto& proto) = 0;
@@ -36,51 +52,57 @@
 };
 
 // |FakePredictor| is a simple 'predictor' used for testing. |Rank| returns the
-// numbers of times each target has been trained on.
+// numbers of times each target has been trained on, and ignores the query
+// altogether.
 //
 // WARNING: this breaks the guarantees on the range of values a score can take,
 // so should not be used for anything except testing.
 class FakePredictor : public RecurrencePredictor {
  public:
-  FakePredictor();
+  explicit FakePredictor(FakePredictorConfig config);
   ~FakePredictor() override;
 
-  // RecurrencePredictor overrides:
-  void Train(unsigned int target) override;
-  base::flat_map<unsigned int, float> Rank() override;
-  const char* GetPredictorName() const override;
+  // RecurrencePredictor:
+  void Train(const std::string& target, const std::string& query) override;
+  base::flat_map<std::string, float> Rank(const std::string& query) override;
+  void Rename(const std::string& target,
+              const std::string& new_target) override;
+  void Remove(const std::string& target) override;
   void ToProto(RecurrencePredictorProto* proto) const override;
   void FromProto(const RecurrencePredictorProto& proto) override;
+  const char* GetPredictorName() const override;
 
   static const char kPredictorName[];
 
  private:
-  base::flat_map<unsigned int, float> counts_;
+  base::flat_map<std::string, float> counts_;
 
   DISALLOW_COPY_AND_ASSIGN(FakePredictor);
 };
 
-// |FrecencyPredictor| simply returns targets in frecency order. To do this, it
-// piggybacks off the existing targets FrecencyStore used in |RecurrenceRanker|.
-// For efficiency reasons the ranker itself has a special case that handles the
-// logic of |FrecencyPredictor::Rank|. This leaves |FrecencyPredictor| as a
-// mostly empty class.
-class FrecencyPredictor : public RecurrencePredictor {
+// |ZeroStateFrecencyPredictor| ranks targets according to their frecency, and
+// can only be used for zero-state predictions, that is, an empty query string.
+class ZeroStateFrecencyPredictor : public RecurrencePredictor {
  public:
-  FrecencyPredictor() = default;
-  ~FrecencyPredictor() override = default;
+  explicit ZeroStateFrecencyPredictor(ZeroStateFrecencyPredictorConfig config);
+  ~ZeroStateFrecencyPredictor() override;
 
-  // RecurrencePredictor overrides:
-  void Train(unsigned int target) override;
-  base::flat_map<unsigned int, float> Rank() override;
-  const char* GetPredictorName() const override;
+  // RecurrencePredictor:
+  void Train(const std::string& target, const std::string& query) override;
+  base::flat_map<std::string, float> Rank(const std::string& query) override;
+  void Rename(const std::string& target,
+              const std::string& new_target) override;
+  void Remove(const std::string& target) override;
   void ToProto(RecurrencePredictorProto* proto) const override;
   void FromProto(const RecurrencePredictorProto& proto) override;
+  const char* GetPredictorName() const override;
 
   static const char kPredictorName[];
 
  private:
-  DISALLOW_COPY_AND_ASSIGN(FrecencyPredictor);
+  std::unique_ptr<FrecencyStore> targets_;
+
+  DISALLOW_COPY_AND_ASSIGN(ZeroStateFrecencyPredictor);
 };
 
 }  // namespace app_list
diff --git a/chrome/browser/ui/app_list/search/search_result_ranker/recurrence_predictor.proto b/chrome/browser/ui/app_list/search/search_result_ranker/recurrence_predictor.proto
index 0ee47e0..c352a78 100644
--- a/chrome/browser/ui/app_list/search/search_result_ranker/recurrence_predictor.proto
+++ b/chrome/browser/ui/app_list/search/search_result_ranker/recurrence_predictor.proto
@@ -4,23 +4,27 @@
 
 syntax = "proto2";
 
+import "frecency_store.proto";
+
 option optimize_for = LITE_RUNTIME;
 
 package app_list;
 
 // Fake predictor used for testing.
 message FakePredictorProto {
-  map<uint32, float> counts = 1;
+  // Maps targets to their score.
+  map<string, float> counts = 1;
 }
 
-// Frecency predictor. Uses the targets stored in the ranker, so serialises
-// nothing of its own.
-message FrecencyPredictorProto {}
+// Zero-state frecency predictor.
+message ZeroStateFrecencyPredictorProto {
+  optional FrecencyStoreProto targets = 1;
+}
 
 // Represents the serialisation of one particular predictor.
 message RecurrencePredictorProto {
   oneof predictor {
     FakePredictorProto fake_predictor = 1;
-    FrecencyPredictorProto frecency_predictor = 2;
+    ZeroStateFrecencyPredictorProto zero_state_frecency_predictor = 2;
   }
 }
diff --git a/chrome/browser/ui/app_list/search/search_result_ranker/recurrence_predictor_unittest.cc b/chrome/browser/ui/app_list/search/search_result_ranker/recurrence_predictor_unittest.cc
new file mode 100644
index 0000000..5601698e
--- /dev/null
+++ b/chrome/browser/ui/app_list/search/search_result_ranker/recurrence_predictor_unittest.cc
@@ -0,0 +1,134 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/app_list/search/search_result_ranker/recurrence_predictor.h"
+
+#include <memory>
+#include <vector>
+
+#include "ash/public/cpp/app_list/app_list_features.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/hash.h"
+#include "base/test/scoped_feature_list.h"
+#include "base/test/scoped_task_environment.h"
+#include "chrome/browser/ui/app_list/search/search_result_ranker/app_launch_predictor_test_util.h"
+#include "chrome/browser/ui/app_list/search/search_result_ranker/frecency_store.h"
+#include "chrome/browser/ui/app_list/search/search_result_ranker/recurrence_ranker_config.pb.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using testing::_;
+using testing::ElementsAre;
+using testing::FloatEq;
+using testing::IsSupersetOf;
+using testing::NiceMock;
+using testing::Pair;
+using testing::Return;
+using testing::StrEq;
+using testing::UnorderedElementsAre;
+
+namespace app_list {
+
+class ZeroStateFrecencyPredictorTest : public testing::Test {
+ protected:
+  void SetUp() override {
+    Test::SetUp();
+
+    config_.set_target_limit(100u);
+    config_.set_decay_coeff(0.5f);
+    predictor_ = std::make_unique<ZeroStateFrecencyPredictor>(config_);
+  }
+
+  ZeroStateFrecencyPredictorConfig config_;
+  std::unique_ptr<ZeroStateFrecencyPredictor> predictor_;
+};
+
+TEST_F(ZeroStateFrecencyPredictorTest, RankWithNoTargets) {
+  EXPECT_TRUE(predictor_->Rank("").empty());
+}
+
+TEST_F(ZeroStateFrecencyPredictorTest, RecordAndRank) {
+  predictor_->Train("A", "");
+  predictor_->Train("B", "");
+  predictor_->Train("C", "");
+
+  EXPECT_THAT(predictor_->Rank(""),
+              UnorderedElementsAre(Pair("A", FloatEq(0.125f)),
+                                   Pair("B", FloatEq(0.25f)),
+                                   Pair("C", FloatEq(0.5f))));
+}
+
+TEST_F(ZeroStateFrecencyPredictorTest, Rename) {
+  predictor_->Train("A", "");
+  predictor_->Train("B", "");
+  predictor_->Train("B", "");
+  predictor_->Rename("B", "A");
+
+  EXPECT_THAT(predictor_->Rank(""),
+              UnorderedElementsAre(Pair("A", FloatEq(0.75f))));
+}
+
+TEST_F(ZeroStateFrecencyPredictorTest, RenameNonexistentTarget) {
+  predictor_->Train("A", "");
+  predictor_->Rename("B", "C");
+
+  EXPECT_THAT(predictor_->Rank(""),
+              UnorderedElementsAre(Pair("A", FloatEq(0.5f))));
+}
+
+TEST_F(ZeroStateFrecencyPredictorTest, Remove) {
+  predictor_->Train("A", "");
+  predictor_->Train("B", "");
+  predictor_->Remove("B");
+
+  EXPECT_THAT(predictor_->Rank(""),
+              UnorderedElementsAre(Pair("A", FloatEq(0.25f))));
+}
+
+TEST_F(ZeroStateFrecencyPredictorTest, RemoveNonexistentTarget) {
+  predictor_->Train("A", "");
+  predictor_->Remove("B");
+
+  EXPECT_THAT(predictor_->Rank(""),
+              UnorderedElementsAre(Pair("A", FloatEq(0.5f))));
+}
+
+TEST_F(ZeroStateFrecencyPredictorTest, TargetLimitExceeded) {
+  ZeroStateFrecencyPredictorConfig config;
+  config.set_target_limit(5u);
+  config.set_decay_coeff(0.9999f);
+  ZeroStateFrecencyPredictor predictor(config);
+
+  // Insert many more targets than the target limit.
+  for (int i = 0; i < 50; i++) {
+    predictor.Train(std::to_string(i), "");
+  }
+
+  // Check that some of the values have been deleted, and the most recent ones
+  // remain. We check loose bounds on these requirements, to prevent the test
+  // from being tied to implementation details of the |FrecencyStore| cleanup
+  // logic. See |FrecencyStoreTest::CleanupOnOverflow| for a corresponding, more
+  // precise test.
+  auto ranks = predictor.Rank("");
+  EXPECT_LE(ranks.size(), 10ul);
+  EXPECT_THAT(
+      ranks, testing::IsSupersetOf({Pair("45", _), Pair("46", _), Pair("47", _),
+                                    Pair("48", _), Pair("49", _)}));
+}
+
+TEST_F(ZeroStateFrecencyPredictorTest, ToAndFromProto) {
+  predictor_->Train("A", "");
+  predictor_->Train("B", "");
+  predictor_->Train("C", "");
+
+  const auto ranks = predictor_->Rank("");
+
+  RecurrencePredictorProto proto;
+  predictor_->ToProto(&proto);
+  predictor_->FromProto(proto);
+
+  EXPECT_EQ(ranks, predictor_->Rank(""));
+}
+
+}  // namespace app_list
diff --git a/chrome/browser/ui/app_list/search/search_result_ranker/recurrence_ranker.cc b/chrome/browser/ui/app_list/search/search_result_ranker/recurrence_ranker.cc
index b5e83a8..4e5b385 100644
--- a/chrome/browser/ui/app_list/search/search_result_ranker/recurrence_ranker.cc
+++ b/chrome/browser/ui/app_list/search/search_result_ranker/recurrence_ranker.cc
@@ -74,11 +74,12 @@
 
 // Returns a new, configured instance of the predictor defined in |config|.
 std::unique_ptr<RecurrencePredictor> MakePredictor(
-    RecurrenceRankerConfigProto config) {
-  if (config.has_frecency_predictor())
-    return std::make_unique<FrecencyPredictor>();
+    const RecurrenceRankerConfigProto& config) {
   if (config.has_fake_predictor())
-    return std::make_unique<FakePredictor>();
+    return std::make_unique<FakePredictor>(config.fake_predictor());
+  if (config.has_zero_state_frecency_predictor())
+    return std::make_unique<ZeroStateFrecencyPredictor>(
+        config.zero_state_frecency_predictor());
 
   NOTREACHED();
   return nullptr;
@@ -100,13 +101,12 @@
       {base::TaskPriority::BEST_EFFORT, base::MayBlock(),
        base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN});
 
-  targets_ = std::make_unique<FrecencyStore>(config.target_limit(),
-                                             config.target_decay_coeff());
   if (is_ephemeral_user_) {
     // Ephemeral users have no persistent storage, so we don't try and load the
     // proto from disk. Instead, we fall back on using a frecency predictor,
     // which is still useful with only data from the current session.
-    predictor_ = std::make_unique<FrecencyPredictor>();
+    predictor_ = std::make_unique<ZeroStateFrecencyPredictor>(
+        config.fallback_predictor());
   } else {
     predictor_ = MakePredictor(config);
 
@@ -132,25 +132,21 @@
     return;
   }
 
-  if (proto->has_targets())
-    targets_->FromProto(proto->targets());
   if (proto->has_predictor())
     predictor_->FromProto(proto->predictor());
-
   load_from_disk_completed_ = true;
 }
 
 void RecurrenceRanker::Record(const std::string& target) {
+  Record(target, "");
+}
+
+void RecurrenceRanker::Record(const std::string& target,
+                              const std::string& query) {
   if (!load_from_disk_completed_)
     return;
 
-  targets_->Update(target);
-
-  // It might be possible that, despite just being updated, the target was
-  // removed from the store. Only train if the target is still valid.
-  Optional<unsigned int> id = targets_->GetId(target);
-  if (id.has_value())
-    predictor_->Train(id.value());
+  predictor_->Train(target, query);
   MaybeSave();
 }
 
@@ -159,7 +155,7 @@
   if (!load_from_disk_completed_)
     return;
 
-  targets_->Rename(target, new_target);
+  predictor_->Rename(target, new_target);
   MaybeSave();
 }
 
@@ -167,44 +163,33 @@
   if (!load_from_disk_completed_)
     return;
 
-  targets_->Remove(target);
+  predictor_->Remove(target);
   MaybeSave();
 }
 
 base::flat_map<std::string, float> RecurrenceRanker::Rank() {
+  return Rank("");
+}
+
+base::flat_map<std::string, float> RecurrenceRanker::Rank(
+    const std::string& query) {
   if (!load_from_disk_completed_)
     return {};
 
-  // Special case for a frecency predictor. Because this is simply a wrapper
-  // around the |RecurrenceRanker|'s targets store, we can directly return the
-  // contents of the store and avoid an uneccessary iteration through targets.
-  if (predictor_->GetPredictorName() == FrecencyPredictor::kPredictorName) {
-    base::flat_map<std::string, float> ranks;
-    for (const auto& pair : targets_->GetAll())
-      ranks[pair.first] = pair.second.last_score;
-    return ranks;
-  }
-
-  const base::flat_map<unsigned int, float> id_ranks = predictor_->Rank();
-  const base::flat_map<std::string, FrecencyStore::ValueData>& targets =
-      targets_->GetAll();
-
-  base::flat_map<std::string, float> ranks;
-  for (const auto& pair : targets) {
-    const auto& data = pair.second;
-    const auto it = id_ranks.find(data.id);
-    if (it == id_ranks.end())
-      continue;
-    ranks[pair.first] = it->second;
-  }
-  return ranks;
+  return predictor_->Rank(query);
 }
 
 std::vector<std::pair<std::string, float>> RecurrenceRanker::RankTopN(int n) {
+  return RankTopN(n, "");
+}
+
+std::vector<std::pair<std::string, float>> RecurrenceRanker::RankTopN(
+    int n,
+    const std::string& query) {
   if (!load_from_disk_completed_)
     return {};
 
-  base::flat_map<std::string, float> ranks = Rank();
+  base::flat_map<std::string, float> ranks = Rank(query);
   std::vector<std::pair<std::string, float>> sorted_ranks(ranks.begin(),
                                                           ranks.end());
   std::sort(sorted_ranks.begin(), sorted_ranks.end(),
@@ -236,7 +221,6 @@
 void RecurrenceRanker::ToProto(RecurrenceRankerProto* proto) {
   proto->set_config_hash(config_hash_);
   predictor_->ToProto(proto->mutable_predictor());
-  targets_->ToProto(proto->mutable_targets());
 }
 
 void RecurrenceRanker::ForceSaveOnNextUpdateForTesting() {
diff --git a/chrome/browser/ui/app_list/search/search_result_ranker/recurrence_ranker.h b/chrome/browser/ui/app_list/search/search_result_ranker/recurrence_ranker.h
index 6ea9cf2c..d3eefa7 100644
--- a/chrome/browser/ui/app_list/search/search_result_ranker/recurrence_ranker.h
+++ b/chrome/browser/ui/app_list/search/search_result_ranker/recurrence_ranker.h
@@ -21,7 +21,6 @@
 
 namespace app_list {
 
-class FrecencyStore;
 class RecurrencePredictor;
 class RecurrenceRankerProto;
 
@@ -40,8 +39,11 @@
 
   ~RecurrenceRanker();
 
-  // Record the use of a given target, and train the predictor on it.
+  // Record the use of a given target, and train the predictor on it. The one
+  // argument version is a shortcut for an empty query string, useful for
+  // zero-state scenarios.
   void Record(const std::string& target);
+  void Record(const std::string& target, const std::string& query);
   // Rename a target, while keeping learned information on it.
   void Rename(const std::string& target, const std::string& new_target);
   // Remove a target entirely.
@@ -50,14 +52,19 @@
   // Returns a map of target to score.
   //  - Higher scores are better.
   //  - Score are guaranteed to be in the range [0,1].
+  // The zero-argument version is a shortcut for an empty query string.
   base::flat_map<std::string, float> Rank();
+  base::flat_map<std::string, float> Rank(const std::string& query);
 
   // Returns a sorted vector of <target, score> pairs.
   //  - Higher scores are better.
   //  - Score are guaranteed to be in the range [0,1].
   //  - Pairs are sorted in descending order of score.
   //  - At most n results will be returned.
+  // The one-argument version is a shortcut for an empty query string.
   std::vector<std::pair<std::string, float>> RankTopN(int n);
+  std::vector<std::pair<std::string, float>> RankTopN(int n,
+                                                      const std::string& query);
 
  private:
   FRIEND_TEST_ALL_PREFIXES(RecurrenceRankerTest,
@@ -82,8 +89,6 @@
 
   // Internal predictor that drives ranking.
   std::unique_ptr<RecurrencePredictor> predictor_;
-  // A store of all possible targets to return.
-  std::unique_ptr<FrecencyStore> targets_;
 
   // Where to save the ranker.
   const base::FilePath proto_filepath_;
diff --git a/chrome/browser/ui/app_list/search/search_result_ranker/recurrence_ranker.proto b/chrome/browser/ui/app_list/search/search_result_ranker/recurrence_ranker.proto
index 6797e3fc..763fd145 100644
--- a/chrome/browser/ui/app_list/search/search_result_ranker/recurrence_ranker.proto
+++ b/chrome/browser/ui/app_list/search/search_result_ranker/recurrence_ranker.proto
@@ -4,7 +4,6 @@
 
 syntax = "proto2";
 
-import "frecency_store.proto";
 import "recurrence_predictor.proto";
 
 option optimize_for = LITE_RUNTIME;
@@ -18,6 +17,4 @@
   optional uint32 config_hash = 1;
   // Serialisation of the predictor used by the ranker.
   optional RecurrencePredictorProto predictor = 2;
-  // Serialisation of the store of targets.
-  optional FrecencyStoreProto targets = 3;
 }
diff --git a/chrome/browser/ui/app_list/search/search_result_ranker/recurrence_ranker_config.proto b/chrome/browser/ui/app_list/search/search_result_ranker/recurrence_ranker_config.proto
index 1030cea03..6fd46e0 100644
--- a/chrome/browser/ui/app_list/search/search_result_ranker/recurrence_ranker_config.proto
+++ b/chrome/browser/ui/app_list/search/search_result_ranker/recurrence_ranker_config.proto
@@ -13,23 +13,33 @@
 // Warning: this cannot contain any map fields, as they cannot be relied upon
 // for a consistent hash.
 message RecurrenceRankerConfigProto {
-  // The soft-maximum number of targets that are stored within the ranker.
-  required uint32 target_limit = 1;
-  // The frecency parameter used to control the frequency-recency tradeoff that
-  // determines when targets are removed. Must be in [0.5, 1.0], with 0.5
-  // meaning only-recency and 1.0 meaning only-frequency.
-  required float target_decay_coeff = 2;
+  // Fields with IDs 1 (target_limit) and 2 (target_decay_coeff) have been
+  // deleted.
+  reserved 1;
+  reserved 2;
 
   required uint32 min_seconds_between_saves = 3;
 
   // Config for a fake predictor, used for testing.
   message FakePredictorConfig {}
+
   // Config for a frecency predictor.
-  message FrecencyPredictorConfig {}
+  message ZeroStateFrecencyPredictorConfig {
+    // The soft-maximum number of targets that are stored within the predictor.
+    required uint32 target_limit = 201;
+    // The frecency parameter used to control the frequency-recency tradeoff
+    // that determines when targets are removed. Must be in [0.5, 1.0], with 0.5
+    // meaning only-recency and 1.0 meaning only-frequency.
+    required float decay_coeff = 202;
+  }
 
   // The choice of which kind of predictor to use, and its configuration.
   oneof predictor_config {
-    FakePredictorConfig fake_predictor = 4;
-    FrecencyPredictorConfig frecency_predictor = 5;
+    FakePredictorConfig fake_predictor = 10001;
+    ZeroStateFrecencyPredictorConfig zero_state_frecency_predictor = 10002;
   }
+
+  // Configuration for a frecency predictor used as a fallback if the user is
+  // ephemeral.
+  required ZeroStateFrecencyPredictorConfig fallback_predictor = 11000;
 }
diff --git a/chrome/browser/ui/app_list/search/search_result_ranker/recurrence_ranker_unittest.cc b/chrome/browser/ui/app_list/search/search_result_ranker/recurrence_ranker_unittest.cc
index a1d7998..61be71d 100644
--- a/chrome/browser/ui/app_list/search/search_result_ranker/recurrence_ranker_unittest.cc
+++ b/chrome/browser/ui/app_list/search/search_result_ranker/recurrence_ranker_unittest.cc
@@ -36,13 +36,14 @@
     ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
     ranker_filepath_ = temp_dir_.GetPath().AppendASCII("recurrence_ranker");
 
-    config_.set_target_limit(1000u);
-    config_.set_target_decay_coeff(0.75f);
-    config_.set_min_seconds_between_saves(120);
+    auto* fallback = config_.mutable_fallback_predictor();
+    fallback->set_target_limit(0u);
+    fallback->set_decay_coeff(0.0f);
     // Even if empty, the setting of the oneof |predictor_config| in
     // |RecurrenceRankerConfigProto| is used to determine which predictor is
     // constructed.
     config_.mutable_fake_predictor();
+    config_.set_min_seconds_between_saves(5);
 
     ranker_ =
         std::make_unique<RecurrenceRanker>(ranker_filepath_, config_, false);
@@ -57,17 +58,9 @@
 
     auto* counts =
         proto.mutable_predictor()->mutable_fake_predictor()->mutable_counts();
-    (*counts)[0u] = 1.0f;
-    (*counts)[1u] = 2.0f;
-    (*counts)[2u] = 1.0f;
-
-    FrecencyStore store(1000, 0.75f);
-    store.Update("A");
-    store.Update("B");
-    store.Update("B");
-    store.Update("C");
-    FrecencyStoreProto targets_proto;
-    store.ToProto(proto.mutable_targets());
+    (*counts)["A"] = 1.0f;
+    (*counts)["B"] = 2.0f;
+    (*counts)["C"] = 1.0f;
 
     return proto;
   }
@@ -81,7 +74,7 @@
   base::FilePath ranker_filepath_;
 };
 
-TEST_F(RecurrenceRankerTest, CheckRecord) {
+TEST_F(RecurrenceRankerTest, Record) {
   ranker_->Record("A");
   ranker_->Record("B");
   ranker_->Record("B");
@@ -90,7 +83,7 @@
                                                     Pair("B", FloatEq(2.0f))));
 }
 
-TEST_F(RecurrenceRankerTest, CheckRename) {
+TEST_F(RecurrenceRankerTest, Rename) {
   ranker_->Record("A");
   ranker_->Record("B");
   ranker_->Record("B");
@@ -99,7 +92,7 @@
   EXPECT_THAT(ranker_->Rank(), ElementsAre(Pair("A", FloatEq(2.0f))));
 }
 
-TEST_F(RecurrenceRankerTest, CheckRemove) {
+TEST_F(RecurrenceRankerTest, Remove) {
   ranker_->Record("A");
   ranker_->Record("B");
   ranker_->Record("B");
@@ -213,10 +206,14 @@
 
   // Construct a second ranker with a slightly different config.
   RecurrenceRankerConfigProto other_config;
-  other_config.set_target_limit(1000u);
-  other_config.set_target_decay_coeff(0.76f);
-  other_config.set_min_seconds_between_saves(120);
+  auto* fallback = other_config.mutable_fallback_predictor();
+  fallback->set_target_limit(0u);
+  fallback->set_decay_coeff(0.0f);
   other_config.mutable_fake_predictor();
+  // This is different.
+  other_config.set_min_seconds_between_saves(
+      config_.min_seconds_between_saves() + 1);
+
   RecurrenceRanker other_ranker(ranker_filepath_, other_config, false);
   Wait();
 
@@ -229,31 +226,36 @@
 }
 
 TEST_F(RecurrenceRankerTest, EphemeralUsersUseFrecencyPredictor) {
-  auto ephemeral_ranker =
-      std::make_unique<RecurrenceRanker>(ranker_filepath_, config_, true);
+  RecurrenceRanker ephemeral_ranker(ranker_filepath_, config_, true);
   Wait();
-  EXPECT_THAT(ephemeral_ranker->GetPredictorNameForTesting(),
-              StrEq(FrecencyPredictor().GetPredictorName()));
+  EXPECT_THAT(ephemeral_ranker.GetPredictorNameForTesting(),
+              StrEq(ZeroStateFrecencyPredictor::kPredictorName));
 }
 
-TEST_F(RecurrenceRankerTest, CheckFrecencyPredictor) {
+TEST_F(RecurrenceRankerTest, IntegrationWithZeroStateFrecencyPredictor) {
   RecurrenceRankerConfigProto config;
-  config.set_target_limit(1000u);
-  config.set_target_decay_coeff(0.5f);
-  config.set_min_seconds_between_saves(120);
-  config.mutable_frecency_predictor();
+  config.set_min_seconds_between_saves(5);
+  auto* predictor = config.mutable_zero_state_frecency_predictor();
+  predictor->set_target_limit(100u);
+  predictor->set_decay_coeff(0.5f);
+  auto* fallback = config.mutable_fallback_predictor();
+  fallback->set_target_limit(100u);
+  fallback->set_decay_coeff(0.5f);
 
-  RecurrenceRanker frecency_ranker(ranker_filepath_, config, false);
+  RecurrenceRanker ranker(ranker_filepath_, config, false);
   Wait();
 
-  frecency_ranker.Record("A");
-  frecency_ranker.Record("B");
-  frecency_ranker.Record("C");
+  ranker.Record("A");
+  ranker.Record("D");
+  ranker.Record("C");
+  ranker.Record("E");
+  ranker.Rename("D", "B");
+  ranker.Remove("E");
+  ranker.Rename("E", "A");
 
-  EXPECT_THAT(frecency_ranker.Rank(),
-              UnorderedElementsAre(Pair("A", FloatEq(0.125f)),
-                                   Pair("B", FloatEq(0.25f)),
-                                   Pair("C", FloatEq(0.5f))));
+  EXPECT_THAT(ranker.Rank(), UnorderedElementsAre(Pair("A", FloatEq(0.0625f)),
+                                                  Pair("B", FloatEq(0.125f)),
+                                                  Pair("C", FloatEq(0.25f))));
 }
 
 }  // namespace app_list
diff --git a/chrome/browser/ui/views/profiles/avatar_toolbar_button.cc b/chrome/browser/ui/views/profiles/avatar_toolbar_button.cc
index d4a1199b..7c2d6c10 100644
--- a/chrome/browser/ui/views/profiles/avatar_toolbar_button.cc
+++ b/chrome/browser/ui/views/profiles/avatar_toolbar_button.cc
@@ -99,10 +99,6 @@
   SetEnabled(!IsIncognito() || IsIncognitoCounterActive());
 #endif  // !defined(OS_CHROMEOS)
 
-  // The incognito window counter uses left-aligned text.
-  if (IsIncognitoCounterActive())
-    SetHorizontalAlignment(gfx::ALIGN_LEFT);
-
   // Set initial text and tooltip. UpdateIcon() needs to be called from the
   // outside as GetThemeProvider() is not available until the button is added to
   // ToolbarView's hierarchy.
@@ -131,13 +127,13 @@
     SetTextColor(STATE_DISABLED, *color);
   }
 
-  if (IsIncognitoCounterActive()) {
-    const int incognito_window_count =
+  if (IsIncognito()) {
+    int incognito_window_count =
         BrowserList::GetIncognitoSessionsActiveForProfile(profile_);
-    if (incognito_window_count > 1)
-      text = base::NumberToString16(incognito_window_count);
-  } else if (IsIncognito()) {
-    text = l10n_util::GetStringUTF16(IDS_AVATAR_BUTTON_INCOGNITO);
+    if (!IsIncognitoCounterActive())
+      incognito_window_count = 1;
+    text = l10n_util::GetPluralStringFUTF16(IDS_AVATAR_BUTTON_INCOGNITO,
+                                            incognito_window_count);
   } else if (sync_state == SyncState::kError) {
     color =
         AdjustHighlightColorForContrast(gfx::kGoogleRed300, gfx::kGoogleRed600,
@@ -235,11 +231,13 @@
   UpdateIcon();
 }
 
-void AvatarToolbarButton::OnAccountUpdated(const AccountInfo& info) {
+void AvatarToolbarButton::OnExtendedAccountInfoUpdated(
+    const AccountInfo& info) {
   UpdateIcon();
 }
 
-void AvatarToolbarButton::OnAccountRemovedWithInfo(const AccountInfo& info) {
+void AvatarToolbarButton::OnExtendedAccountInfoRemoved(
+    const AccountInfo& info) {
   UpdateIcon();
 }
 
@@ -393,21 +391,6 @@
   // is hard to read for user avatars, so we need to set corresponding insets.
   gfx::Insets layout_insets(ui::MaterialDesignController::touch_ui() ? 0 : -2);
 
-  // When the incognito counter is displaying, we need to add additional insets
-  // to the icon side because the existing ones don't look balanced.
-  if (IsIncognitoCounterActive()) {
-    const int incognito_window_count =
-        BrowserList::GetIncognitoSessionsActiveForProfile(profile_);
-    if (incognito_window_count > 1) {
-      const int highlight_radius =
-          ChromeLayoutProvider::Get()->GetCornerRadiusMetric(
-              views::EMPHASIS_MAXIMUM, size());
-      // These additional insets have been chosen to look reasonably well and
-      // scale with the (touchable or not) UI.
-      layout_insets.set_left(layout_insets.left() + highlight_radius / 4);
-    }
-  }
-
   SetLayoutInsetDelta(layout_insets);
 }
 
diff --git a/chrome/browser/ui/views/profiles/avatar_toolbar_button.h b/chrome/browser/ui/views/profiles/avatar_toolbar_button.h
index 80bdd67..778ae58 100644
--- a/chrome/browser/ui/views/profiles/avatar_toolbar_button.h
+++ b/chrome/browser/ui/views/profiles/avatar_toolbar_button.h
@@ -65,8 +65,8 @@
   void OnAccountsInCookieUpdated(
       const identity::AccountsInCookieJarInfo& accounts_in_cookie_jar_info,
       const GoogleServiceAuthError& error) override;
-  void OnAccountUpdated(const AccountInfo& info) override;
-  void OnAccountRemovedWithInfo(const AccountInfo& info) override;
+  void OnExtendedAccountInfoUpdated(const AccountInfo& info) override;
+  void OnExtendedAccountInfoRemoved(const AccountInfo& info) override;
 
   // ui::MaterialDesignControllerObserver:
   void OnTouchUiChanged() override;
diff --git a/chrome/browser/ui/views/profiles/incognito_window_count_view.cc b/chrome/browser/ui/views/profiles/incognito_window_count_view.cc
index 07717ddc..380689a 100644
--- a/chrome/browser/ui/views/profiles/incognito_window_count_view.cc
+++ b/chrome/browser/ui/views/profiles/incognito_window_count_view.cc
@@ -7,15 +7,15 @@
 #include "base/bind_helpers.h"
 #include "chrome/app/vector_icons/vector_icons.h"
 #include "chrome/browser/platform_util.h"
+#include "chrome/browser/themes/theme_properties.h"
+#include "chrome/browser/themes/theme_service.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_list.h"
 #include "chrome/browser/ui/browser_window.h"
-#include "chrome/browser/ui/views/chrome_typography.h"
 #include "chrome/browser/ui/views/hover_button.h"
 #include "chrome/grit/generated_resources.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/gfx/paint_vector_icon.h"
-#include "ui/native_theme/native_theme.h"
 #include "ui/views/controls/separator.h"
 #include "ui/views/layout/box_layout.h"
 
@@ -64,11 +64,10 @@
       views::BoxLayout::Orientation::kVertical));
 
   auto incognito_icon = std::make_unique<views::ImageView>();
-  // TODO(https://crbug.com/896235): Color to be updated after incognito
-  // redesign is finalized. Text color is chosen to have maximum contrast with
-  // background color.
-  const SkColor icon_color = views::style::GetColor(
-      *this, views::style::CONTEXT_TEXTFIELD, STYLE_PRIMARY_MONOSPACED);
+  const ui::ThemeProvider& theme_provider =
+      ThemeService::GetThemeProviderForProfile(browser_->profile());
+  const SkColor icon_color =
+      theme_provider.GetColor(ThemeProperties::COLOR_NTP_BACKGROUND);
   incognito_icon->SetImage(
       gfx::CreateVectorIcon(kIncognitoIcon, 40, icon_color));
 
diff --git a/chrome/browser/ui/webui/local_discovery/local_discovery_ui_browsertest.cc b/chrome/browser/ui/webui/local_discovery/local_discovery_ui_browsertest.cc
index 081eb01..35788b8 100644
--- a/chrome/browser/ui/webui/local_discovery/local_discovery_ui_browsertest.cc
+++ b/chrome/browser/ui/webui/local_discovery/local_discovery_ui_browsertest.cc
@@ -26,7 +26,6 @@
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/signin/chrome_signin_client_factory.h"
 #include "chrome/browser/signin/identity_manager_factory.h"
-#include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/webui/local_discovery/local_discovery_ui_handler.h"
 #include "chrome/common/chrome_constants.h"
diff --git a/chrome/browser/ui/webui/offline/offline_internals_ui_message_handler.cc b/chrome/browser/ui/webui/offline/offline_internals_ui_message_handler.cc
index 7d3fd2a..a74cad5b 100644
--- a/chrome/browser/ui/webui/offline/offline_internals_ui_message_handler.cc
+++ b/chrome/browser/ui/webui/offline/offline_internals_ui_message_handler.cc
@@ -34,6 +34,7 @@
 #include "components/offline_pages/core/prefetch/prefetch_background_task_handler.h"
 #include "components/offline_pages/core/prefetch/prefetch_dispatcher.h"
 #include "components/offline_pages/core/prefetch/prefetch_downloader.h"
+#include "components/offline_pages/core/prefetch/prefetch_prefs.h"
 #include "components/offline_pages/core/prefetch/prefetch_service.h"
 #include "components/offline_pages/core/prefetch/prefetch_types.h"
 #include "content/public/browser/web_ui.h"
@@ -402,6 +403,29 @@
     prefetch_service_->GetLogger()->SetIsLogging(should_record);
 }
 
+void OfflineInternalsUIMessageHandler::HandleSetLimitlessPrefetchingEnabled(
+    const base::ListValue* args) {
+  AllowJavascript();
+  PrefService* prefs = Profile::FromWebUI(web_ui())->GetPrefs();
+  DCHECK(!args->GetList().empty());
+  bool enabled = args->GetList()[0].GetBool();
+  offline_pages::prefetch_prefs::SetLimitlessPrefetchingEnabled(prefs, enabled);
+}
+
+void OfflineInternalsUIMessageHandler::HandleGetLimitlessPrefetchingEnabled(
+    const base::ListValue* args) {
+  AllowJavascript();
+  const base::Value* callback_id;
+  bool got_callback_id = args->Get(0, &callback_id);
+  DCHECK(got_callback_id);
+
+  PrefService* prefs = Profile::FromWebUI(web_ui())->GetPrefs();
+  bool enabled =
+      offline_pages::prefetch_prefs::IsLimitlessPrefetchingEnabled(prefs);
+
+  ResolveJavascriptCallback(*callback_id, base::Value(enabled));
+}
+
 void OfflineInternalsUIMessageHandler::HandleGetLoggingState(
     const base::ListValue* args) {
   AllowJavascript();
@@ -523,6 +547,16 @@
           &OfflineInternalsUIMessageHandler::HandleSetRecordPrefetchService,
           base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
+      "setLimitlessPrefetchingEnabled",
+      base::BindRepeating(&OfflineInternalsUIMessageHandler::
+                              HandleSetLimitlessPrefetchingEnabled,
+                          base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "getLimitlessPrefetchingEnabled",
+      base::BindRepeating(&OfflineInternalsUIMessageHandler::
+                              HandleGetLimitlessPrefetchingEnabled,
+                          base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
       "getLoggingState",
       base::BindRepeating(
           &OfflineInternalsUIMessageHandler::HandleGetLoggingState,
diff --git a/chrome/browser/ui/webui/offline/offline_internals_ui_message_handler.h b/chrome/browser/ui/webui/offline/offline_internals_ui_message_handler.h
index 9450df7..e7234fdc 100644
--- a/chrome/browser/ui/webui/offline/offline_internals_ui_message_handler.h
+++ b/chrome/browser/ui/webui/offline/offline_internals_ui_message_handler.h
@@ -57,6 +57,12 @@
   // Set whether to record prefetch service events.
   void HandleSetRecordPrefetchService(const base::ListValue* args);
 
+  // Set whether to enable limitless prefetching.
+  void HandleSetLimitlessPrefetchingEnabled(const base::ListValue* args);
+
+  // Get whether limitless prefetching is enabled.
+  void HandleGetLimitlessPrefetchingEnabled(const base::ListValue* args);
+
   // Load all offline services' event logs.
   void HandleGetEventLogs(const base::ListValue* args);
 
diff --git a/chrome/browser/ui/webui/settings/chromeos/account_manager_handler.cc b/chrome/browser/ui/webui/settings/chromeos/account_manager_handler.cc
index e0f827c..aef28520 100644
--- a/chrome/browser/ui/webui/settings/chromeos/account_manager_handler.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/account_manager_handler.cc
@@ -245,7 +245,8 @@
 // this new set of information. Note that we may be listening to
 // |identity::IdentityManager| but we still consider |AccountManager| to be the
 // source of truth for account list.
-void AccountManagerUIHandler::OnAccountUpdated(const AccountInfo& info) {
+void AccountManagerUIHandler::OnExtendedAccountInfoUpdated(
+    const AccountInfo& info) {
   RefreshUI();
 }
 
diff --git a/chrome/browser/ui/webui/settings/chromeos/account_manager_handler.h b/chrome/browser/ui/webui/settings/chromeos/account_manager_handler.h
index 054424bf..dff4731 100644
--- a/chrome/browser/ui/webui/settings/chromeos/account_manager_handler.h
+++ b/chrome/browser/ui/webui/settings/chromeos/account_manager_handler.h
@@ -44,7 +44,7 @@
   void OnAccountRemoved(const AccountManager::AccountKey& account_key) override;
 
   // |identity::IdentityManager::Observer| overrides.
-  void OnAccountUpdated(const AccountInfo& info) override;
+  void OnExtendedAccountInfoUpdated(const AccountInfo& info) override;
 
  private:
   // WebUI "getAccounts" message callback.
diff --git a/chrome/browser/ui/webui/settings/people_handler.cc b/chrome/browser/ui/webui/settings/people_handler.cc
index 711b5dbb..94b2f6f 100644
--- a/chrome/browser/ui/webui/settings/people_handler.cc
+++ b/chrome/browser/ui/webui/settings/people_handler.cc
@@ -463,11 +463,11 @@
   ResolveJavascriptCallback(*callback_id, GetStoredAccountsList());
 }
 
-void PeopleHandler::OnAccountUpdated(const AccountInfo& info) {
+void PeopleHandler::OnExtendedAccountInfoUpdated(const AccountInfo& info) {
   FireWebUIListener("stored-accounts-updated", GetStoredAccountsList());
 }
 
-void PeopleHandler::OnAccountRemovedWithInfo(const AccountInfo& info) {
+void PeopleHandler::OnExtendedAccountInfoRemoved(const AccountInfo& info) {
   FireWebUIListener("stored-accounts-updated", GetStoredAccountsList());
 }
 
diff --git a/chrome/browser/ui/webui/settings/people_handler.h b/chrome/browser/ui/webui/settings/people_handler.h
index 1708043..f80bc5d 100644
--- a/chrome/browser/ui/webui/settings/people_handler.h
+++ b/chrome/browser/ui/webui/settings/people_handler.h
@@ -131,8 +131,8 @@
   void OnPrimaryAccountCleared(
       const CoreAccountInfo& previous_primary_account_info) override;
 #if BUILDFLAG(ENABLE_DICE_SUPPORT)
-  void OnAccountUpdated(const AccountInfo& info) override;
-  void OnAccountRemovedWithInfo(const AccountInfo& info) override;
+  void OnExtendedAccountInfoUpdated(const AccountInfo& info) override;
+  void OnExtendedAccountInfoRemoved(const AccountInfo& info) override;
 #endif
 
   // syncer::SyncServiceObserver implementation.
diff --git a/chrome/browser/ui/webui/signin/sync_confirmation_handler.cc b/chrome/browser/ui/webui/signin/sync_confirmation_handler.cc
index 23b7fff..e64c4eac 100644
--- a/chrome/browser/ui/webui/signin/sync_confirmation_handler.cc
+++ b/chrome/browser/ui/webui/signin/sync_confirmation_handler.cc
@@ -183,7 +183,8 @@
   }
 }
 
-void SyncConfirmationHandler::OnAccountUpdated(const AccountInfo& info) {
+void SyncConfirmationHandler::OnExtendedAccountInfoUpdated(
+    const AccountInfo& info) {
   if (!info.IsValid())
     return;
 
diff --git a/chrome/browser/ui/webui/signin/sync_confirmation_handler.h b/chrome/browser/ui/webui/signin/sync_confirmation_handler.h
index d4e6017..5407c208 100644
--- a/chrome/browser/ui/webui/signin/sync_confirmation_handler.h
+++ b/chrome/browser/ui/webui/signin/sync_confirmation_handler.h
@@ -40,7 +40,7 @@
   void RegisterMessages() override;
 
   // identity::IdentityManager::Observer:
-  void OnAccountUpdated(const AccountInfo& info) override;
+  void OnExtendedAccountInfoUpdated(const AccountInfo& info) override;
 
   // BrowserListObserver:
   void OnBrowserRemoved(Browser* browser) override;
diff --git a/chrome/browser/web_applications/extensions/bookmark_app_util.cc b/chrome/browser/web_applications/extensions/bookmark_app_util.cc
index 93715fb..ebf56ac 100644
--- a/chrome/browser/web_applications/extensions/bookmark_app_util.cc
+++ b/chrome/browser/web_applications/extensions/bookmark_app_util.cc
@@ -16,6 +16,7 @@
 #include "extensions/browser/extension_registry.h"
 #include "extensions/browser/extension_system.h"
 #include "extensions/common/extension.h"
+#include "extensions/common/url_pattern.h"
 #include "extensions/common/url_pattern_set.h"
 #include "url/gurl.h"
 
@@ -129,4 +130,10 @@
   return num_user_installed;
 }
 
+bool IsValidBookmarkAppUrl(const GURL& url) {
+  URLPattern origin_only_pattern(Extension::kValidBookmarkAppSchemes);
+  origin_only_pattern.SetMatchAllURLs(true);
+  return url.is_valid() && origin_only_pattern.MatchesURL(url);
+}
+
 }  // namespace extensions
diff --git a/chrome/browser/web_applications/extensions/bookmark_app_util.h b/chrome/browser/web_applications/extensions/bookmark_app_util.h
index af9c20a..6d539db 100644
--- a/chrome/browser/web_applications/extensions/bookmark_app_util.h
+++ b/chrome/browser/web_applications/extensions/bookmark_app_util.h
@@ -53,6 +53,9 @@
 // (non default-installed apps).
 int CountUserInstalledBookmarkApps(content::BrowserContext* browser_context);
 
+// Returns whether the given |url| is a valid user bookmark app url.
+bool IsValidBookmarkAppUrl(const GURL& url);
+
 }  // namespace extensions
 
 #endif  // CHROME_BROWSER_WEB_APPLICATIONS_EXTENSIONS_BOOKMARK_APP_UTIL_H_
diff --git a/chrome/browser/web_applications/extensions/bookmark_app_util_unittest.cc b/chrome/browser/web_applications/extensions/bookmark_app_util_unittest.cc
index 51d53313..ce2d565 100644
--- a/chrome/browser/web_applications/extensions/bookmark_app_util_unittest.cc
+++ b/chrome/browser/web_applications/extensions/bookmark_app_util_unittest.cc
@@ -95,4 +95,24 @@
       GURL("chrome-extension://nkoccljplnhpfnfiajclkommnmllphnl/html/path")));
 }
 
+TEST(BookmarkAppUtil, IsValidBookmarkAppUrl) {
+  EXPECT_TRUE(IsValidBookmarkAppUrl(GURL("https://chromium.org")));
+  EXPECT_TRUE(IsValidBookmarkAppUrl(GURL("https://www.chromium.org")));
+  EXPECT_TRUE(IsValidBookmarkAppUrl(
+      GURL("https://www.chromium.org/path/to/page.html")));
+  EXPECT_TRUE(IsValidBookmarkAppUrl(GURL("http://chromium.org")));
+  EXPECT_TRUE(IsValidBookmarkAppUrl(GURL("http://www.chromium.org")));
+  EXPECT_TRUE(
+      IsValidBookmarkAppUrl(GURL("http://www.chromium.org/path/to/page.html")));
+  EXPECT_TRUE(IsValidBookmarkAppUrl(
+      GURL("chrome-extension://oafaagfgbdpldilgjjfjocjglfbolmac")));
+
+  EXPECT_FALSE(IsValidBookmarkAppUrl(GURL("ftp://www.chromium.org")));
+  EXPECT_FALSE(IsValidBookmarkAppUrl(GURL("chrome://flags")));
+  EXPECT_FALSE(IsValidBookmarkAppUrl(GURL("about:blank")));
+  EXPECT_FALSE(
+      IsValidBookmarkAppUrl(GURL("file://mhjfbmdgcfjbbpaeojofohoefgiehjai")));
+  EXPECT_FALSE(IsValidBookmarkAppUrl(GURL("chrome://extensions")));
+}
+
 }  // namespace extensions
diff --git a/chrome/browser/web_applications/external_web_apps.cc b/chrome/browser/web_applications/external_web_apps.cc
index 88ebfc2..529ec306 100644
--- a/chrome/browser/web_applications/external_web_apps.cc
+++ b/chrome/browser/web_applications/external_web_apps.cc
@@ -88,7 +88,7 @@
 
 std::vector<web_app::PendingAppManager::AppInfo> ScanDir(
     const base::FilePath& dir,
-    Profile* profile) {
+    const std::string& user_type) {
   base::ScopedBlockingCall scoped_blocking_call(base::BlockingType::MAY_BLOCK);
   base::FilePath::StringType extension(FILE_PATH_LITERAL(".json"));
   base::FileEnumerator json_files(dir,
@@ -116,8 +116,8 @@
       continue;
     }
 
-    if (!apps::ProfileMatchJsonUserType(
-            profile, file.MaybeAsASCII() /* app_id */, dict.get(),
+    if (!apps::UserTypeMatchesJsonUserType(
+            user_type, file.MaybeAsASCII() /* app_id */, dict.get(),
             nullptr /* default_user_types */)) {
       // Already logged.
       continue;
@@ -214,7 +214,7 @@
 std::vector<web_app::PendingAppManager::AppInfo>
 ScanDirForExternalWebAppsForTesting(const base::FilePath& dir,
                                     Profile* profile) {
-  return ScanDir(dir, profile);
+  return ScanDir(dir, apps::DetermineUserType(profile));
 }
 
 void ScanForExternalWebApps(Profile* profile,
@@ -238,7 +238,8 @@
       FROM_HERE,
       {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
        base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN},
-      base::BindOnce(&ScanDir, dir, profile), std::move(callback));
+      base::BindOnce(&ScanDir, dir, apps::DetermineUserType(profile)),
+      std::move(callback));
 }
 
 }  //  namespace web_app
diff --git a/chrome/common/chrome_features.cc b/chrome/common/chrome_features.cc
index 1c3e78c0..fe70300 100644
--- a/chrome/common/chrome_features.cc
+++ b/chrome/common/chrome_features.cc
@@ -553,7 +553,7 @@
 
 // The site settings all sites list page in the Chrome settings UI.
 const base::Feature kSiteSettings{"SiteSettings",
-                                  base::FEATURE_DISABLED_BY_DEFAULT};
+                                  base::FEATURE_ENABLED_BY_DEFAULT};
 
 // Enables committed error pages instead of transient navigation entries for
 // SSL interstitial error pages (i.e. certificate errors).
diff --git a/chrome/common/extensions/extension_constants.cc b/chrome/common/extensions/extension_constants.cc
index b3c65002..94d72fe 100644
--- a/chrome/common/extensions/extension_constants.cc
+++ b/chrome/common/extensions/extension_constants.cc
@@ -71,6 +71,7 @@
 const char kZipArchiverExtensionId[] = "dmboannefpncccogfdikhmhpmdnddgoe";
 const char kZipArchiverExtensionPath[] = "chromeos/zip_archiver";
 const char kChromeCameraAppId[] = "hfhhnacclhffhdffklopdkcgdhifgngh";
+const char kChromeCameraAppPath[] = "chromeos/camera";
 const char kContainedHomeAppId[] = "nbaolgedfgoedkjbfmpediclncanmpbc";
 #endif
 
diff --git a/chrome/common/extensions/extension_constants.h b/chrome/common/extensions/extension_constants.h
index 48de342..4ae3582b 100644
--- a/chrome/common/extensions/extension_constants.h
+++ b/chrome/common/extensions/extension_constants.h
@@ -231,6 +231,8 @@
 extern const char kZipArchiverExtensionPath[];
 // The app ID of Chrome camera app.
 extern const char kChromeCameraAppId[];
+// Path to preinstalled Chrome camera app.
+extern const char kChromeCameraAppPath[];
 // The app ID of the contained home app.
 extern const char kContainedHomeAppId[];
 #endif
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index 1de1264..e03f039 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -4633,6 +4633,7 @@
       "../browser/ui/app_list/search/search_result_ranker/app_launch_predictor_unittest.cc",
       "../browser/ui/app_list/search/search_result_ranker/app_search_result_ranker_unittest.cc",
       "../browser/ui/app_list/search/search_result_ranker/frecency_store_unittest.cc",
+      "../browser/ui/app_list/search/search_result_ranker/recurrence_predictor_unittest.cc",
       "../browser/ui/app_list/search/search_result_ranker/recurrence_ranker_unittest.cc",
       "../browser/ui/app_list/search/settings_shortcut/settings_shortcut_provider_unittest.cc",
       "../browser/ui/app_list/search/settings_shortcut/settings_shortcut_result_unittest.cc",
diff --git a/chrome/test/data/webui/settings/all_sites_tests.js b/chrome/test/data/webui/settings/all_sites_tests.js
index 38e40ea..32392296 100644
--- a/chrome/test/data/webui/settings/all_sites_tests.js
+++ b/chrome/test/data/webui/settings/all_sites_tests.js
@@ -16,6 +16,16 @@
   };
 
   /**
+   * An example eTLD+1 Object with multiple origins grouped under it.
+   * @type {!SiteGroup}
+   */
+  const TEST_MULTIPLE_SITE_GROUP = test_util.createSiteGroup('example.com', [
+    'http://example.com',
+    'https://www.example.com',
+    'https://login.example.com',
+  ]);
+
+  /**
    * An example pref with multiple categories and multiple allow/block
    * state.
    * @type {SiteSettingsPref}
@@ -332,4 +342,190 @@
       assertEquals(addOrigin, siteEntries[3].siteGroup.origins[0].origin);
     });
   });
+
+  function resetSettingsViaOverflowMenu(buttonType) {
+    assertTrue(buttonType == 'cancel-button' || buttonType == 'action-button');
+    Polymer.dom.flush();
+    siteEntries = testElement.$.listContainer.querySelectorAll('site-entry');
+    assertEquals(1, siteEntries.length);
+    const overflowMenuButton = siteEntries[0].$.overflowMenuButton;
+    assertFalse(overflowMenuButton.closest('.row-aligned').hidden);
+    // Open the reset settings dialog.
+    const overflowMenu = testElement.$.menu.get();
+    const menuItems = overflowMenu.querySelectorAll('.dropdown-item');
+
+    // Test clicking on the overflow menu button opens the menu.
+    assertFalse(overflowMenu.open);
+    overflowMenuButton.click();
+    assertTrue(overflowMenu.open);
+
+    // Open the reset settings dialog and tap the |buttonType| button.
+    assertFalse(testElement.$.confirmResetSettings.get().open);
+    menuItems[0].click();
+    assertTrue(testElement.$.confirmResetSettings.get().open);
+    const actionButtonList =
+        testElement.$.confirmResetSettings.get().getElementsByClassName(
+            buttonType);
+    assertEquals(1, actionButtonList.length);
+    actionButtonList[0].click();
+    testElement.actionMenuModel_ = {
+      index: 0,
+      item: testElement.filteredList_[0],
+    };
+
+    // Check the dialog and overflow menu are now both closed.
+    assertFalse(testElement.$.confirmResetSettings.get().open);
+    assertFalse(overflowMenu.open);
+  }
+
+  test('cancelling the confirm dialog on resetting settings works', function() {
+    testElement.siteGroupMap.set(
+        TEST_MULTIPLE_SITE_GROUP.etldPlus1,
+        JSON.parse(JSON.stringify(TEST_MULTIPLE_SITE_GROUP)));
+    testElement.forceListUpdate_();
+    resetSettingsViaOverflowMenu('cancel-button');
+  });
+
+  test('reset settings via overflow menu (no data or cookies)', function() {
+    // Test when entire siteGroup has no data or cookies.
+    // Clone this object to avoid propagating changes made in this test.
+    testElement.siteGroupMap.set(
+        TEST_MULTIPLE_SITE_GROUP.etldPlus1,
+        JSON.parse(JSON.stringify(TEST_MULTIPLE_SITE_GROUP)));
+    testElement.forceListUpdate_();
+    resetSettingsViaOverflowMenu('action-button');
+    // Ensure a call was made to setOriginPermissions for each origin.
+    assertEquals(
+        TEST_MULTIPLE_SITE_GROUP.origins.length,
+        browserProxy.getCallCount('setOriginPermissions'));
+    assertEquals(testElement.filteredList_.length, 0);
+  });
+
+  test(
+      'reset settings via overflow menu (one has data and cookies)',
+      function() {
+        // Test when one origin has data and cookies.
+        // Clone this object to avoid propagating changes made in this test.
+        let siteGroup = JSON.parse(JSON.stringify(TEST_MULTIPLE_SITE_GROUP));
+        siteGroup.origins[0].hasPermissionSettings = true;
+        siteGroup.origins[0].usage = 100;
+        siteGroup.origins[0].numCookies = 2;
+        testElement.siteGroupMap.set(
+            siteGroup.etldPlus1, JSON.parse(JSON.stringify(siteGroup)));
+        testElement.forceListUpdate_();
+        resetSettingsViaOverflowMenu('action-button');
+        assertEquals(testElement.filteredList_.length, 1);
+        assertEquals(1, testElement.filteredList_[0].origins.length);
+        assertFalse(
+            testElement.filteredList_[0].origins[0].hasPermissionSettings);
+        assertEquals(testElement.filteredList_[0].origins[0].usage, 100);
+        assertEquals(testElement.filteredList_[0].origins[0].numCookies, 2);
+      });
+
+  test('reset settings via overflow menu (etld+1 has cookies)', function() {
+    // Test when none of origin have data or cookies, but etld+1 has
+    // cookies. In this case, a placeholder origin will be created with the
+    // Etld+1 cookies number. Clone this object to avoid propagating changes
+    // made in this test.
+    let siteGroup = JSON.parse(JSON.stringify(TEST_MULTIPLE_SITE_GROUP));
+    siteGroup.numCookies = 5;
+    testElement.siteGroupMap.set(
+        siteGroup.etldPlus1, JSON.parse(JSON.stringify(siteGroup)));
+    testElement.forceListUpdate_();
+    resetSettingsViaOverflowMenu('action-button');
+    assertEquals(testElement.filteredList_.length, 1);
+    assertEquals(1, testElement.filteredList_[0].origins.length);
+    assertFalse(testElement.filteredList_[0].origins[0].hasPermissionSettings);
+    assertEquals(testElement.filteredList_[0].origins[0].usage, 0);
+    assertEquals(testElement.filteredList_[0].origins[0].numCookies, 5);
+  });
+
+  function clearDataViaOverflowMenu(buttonType) {
+    assertTrue(buttonType == 'cancel-button' || buttonType == 'action-button');
+    Polymer.dom.flush();
+    siteEntries = testElement.$.listContainer.querySelectorAll('site-entry');
+    assertEquals(1, siteEntries.length);
+    const overflowMenuButton = siteEntries[0].$.overflowMenuButton;
+    assertFalse(overflowMenuButton.closest('.row-aligned').hidden);
+
+    // Open the clear data dialog.
+    const overflowMenu = testElement.$.menu.get();
+    const menuItems = overflowMenu.querySelectorAll('.dropdown-item');
+    // Test clicking on the overflow menu button opens the menu.
+    assertFalse(overflowMenu.open);
+    overflowMenuButton.click();
+    assertTrue(overflowMenu.open);
+
+    // Open the clear data dialog and tap the |buttonType| button.
+    assertFalse(testElement.$.confirmClearData.get().open);
+    menuItems[1].click();
+    assertTrue(testElement.$.confirmClearData.get().open);
+    const actionButtonList =
+        testElement.$.confirmClearData.get().getElementsByClassName(buttonType);
+    assertEquals(1, actionButtonList.length);
+    testElement.actionMenuModel_ = {
+      index: 0,
+      item: testElement.filteredList_[0],
+    };
+    actionButtonList[0].click();
+
+    // Check the dialog and overflow menu are now both closed.
+    assertFalse(testElement.$.confirmClearData.get().open);
+    assertFalse(overflowMenu.open);
+  }
+
+  test('cancelling the confirm dialog on clear data works', function() {
+    testElement.siteGroupMap.set(
+        TEST_MULTIPLE_SITE_GROUP.etldPlus1,
+        JSON.parse(JSON.stringify(TEST_MULTIPLE_SITE_GROUP)));
+    testElement.forceListUpdate_();
+    clearDataViaOverflowMenu('cancel-button');
+  });
+
+  test('clear data via overflow menu (no permission and no data)', function() {
+    // Test when all origins has no permission settings and no data.
+    // Clone this object to avoid propagating changes made in this test.
+    testElement.siteGroupMap.set(
+        TEST_MULTIPLE_SITE_GROUP.etldPlus1,
+        JSON.parse(JSON.stringify(TEST_MULTIPLE_SITE_GROUP)));
+    testElement.forceListUpdate_();
+    clearDataViaOverflowMenu('action-button');
+    // Ensure a call was made to clearEtldPlus1DataAndCookies.
+    assertEquals(1, browserProxy.getCallCount('clearEtldPlus1DataAndCookies'));
+    assertEquals(testElement.filteredList_.length, 0);
+  });
+
+  test('clear data via overflow menu (one origin has permission)', function() {
+    // Test when there is one origin has permissions settings.
+    // Clone this object to avoid propagating changes made in this test.
+    let siteGroup = JSON.parse(JSON.stringify(TEST_MULTIPLE_SITE_GROUP));
+    siteGroup.origins[0].hasPermissionSettings = true;
+    testElement.siteGroupMap.set(
+        siteGroup.etldPlus1, JSON.parse(JSON.stringify(siteGroup)));
+    testElement.forceListUpdate_();
+    clearDataViaOverflowMenu('action-button');
+    assertEquals(testElement.filteredList_.length, 1);
+    assertEquals(testElement.filteredList_[0].origins.length, 1);
+  });
+
+  test(
+      'clear data via overflow menu (one origin has permission and data)',
+      function() {
+        // Test when one origin has permission settings and data, clear data
+        // only clears the data and cookies.
+        siteGroup = JSON.parse(JSON.stringify(TEST_MULTIPLE_SITE_GROUP));
+        siteGroup.origins[0].hasPermissionSettings = true;
+        siteGroup.origins[0].usage = 100;
+        siteGroup.origins[0].numCookies = 3;
+        testElement.siteGroupMap.set(
+            siteGroup.etldPlus1, JSON.parse(JSON.stringify(siteGroup)));
+        testElement.forceListUpdate_();
+        clearDataViaOverflowMenu('action-button');
+        assertEquals(testElement.filteredList_.length, 1);
+        assertEquals(testElement.filteredList_[0].origins.length, 1);
+        assertTrue(
+            testElement.filteredList_[0].origins[0].hasPermissionSettings);
+        assertEquals(testElement.filteredList_[0].origins[0].usage, 0);
+        assertEquals(testElement.filteredList_[0].origins[0].numCookies, 0);
+      });
 });
diff --git a/chrome/test/data/webui/settings/bluetooth_page_tests.js b/chrome/test/data/webui/settings/bluetooth_page_tests.js
index 831c4eb..da9a6bc7 100644
--- a/chrome/test/data/webui/settings/bluetooth_page_tests.js
+++ b/chrome/test/data/webui/settings/bluetooth_page_tests.js
@@ -176,9 +176,10 @@
         fakeUnpairedDevice1, fakeUnpairedDevice2, fakePairedDevice1,
         fakePairedDevice2
       ]);
-      await waitForListUpdateTimeout();
 
+      await waitForListUpdateTimeout();
       Polymer.dom.flush();
+
       assertEquals(4, subpage.deviceList_.length);
       assertEquals(2, subpage.pairedDeviceList_.length);
       assertEquals(2, subpage.unpairedDeviceList_.length);
@@ -187,7 +188,9 @@
       await new Promise(
           resolve => bluetoothPrivateApi.connect(address, resolve));
 
+      await waitForListUpdateTimeout();
       Polymer.dom.flush();
+
       assertEquals(3, subpage.pairedDeviceList_.length);
       assertEquals(1, subpage.unpairedDeviceList_.length);
     });
@@ -286,9 +289,8 @@
         assertEquals(
             unpairedDeviceList()[0].address, fakeUnpairedDevice2.address);
 
-        // Add the first device again. Since the devices are always sorted by
-        // address, the new device will be added at the beginning of the list.
-        // TODO(ortuno): Devices should always be added at the end of the list.
+        // Add the first device again; it should be added at the end of the
+        // list.
         bluetoothApi.simulateDevicesAddedForTest([fakeUnpairedDevice1]);
 
         await waitForListUpdateTimeout();
@@ -301,9 +303,9 @@
         assertFalse(subpage.$.noPairedDevices.hidden);
 
         assertEquals(
-            unpairedDeviceList()[0].address, fakeUnpairedDevice1.address);
+            unpairedDeviceList()[0].address, fakeUnpairedDevice2.address);
         assertEquals(
-            unpairedDeviceList()[1].address, fakeUnpairedDevice2.address);
+            unpairedDeviceList()[1].address, fakeUnpairedDevice1.address);
 
         // Remove both devices.
         bluetoothApi.simulateDevicesRemovedForTest(
@@ -391,9 +393,8 @@
 
         assertEquals(pairedDeviceList()[0].address, fakePairedDevice2.address);
 
-        // Add the first device again. Since the devices are always sorted by
-        // address, the new device will be added at the beginning of the list.
-        // TODO(ortuno): Devices should always be added at the end of the list.
+        // Add the first device again; it should be added at the end of the
+        // list.
         bluetoothApi.simulateDevicesAddedForTest([fakePairedDevice1]);
 
         await waitForListUpdateTimeout();
@@ -405,8 +406,8 @@
         assertFalse(subpage.$.noUnpairedDevices.hidden);
         assertTrue(subpage.$.noPairedDevices.hidden);
 
-        assertEquals(pairedDeviceList()[0].address, fakePairedDevice1.address);
-        assertEquals(pairedDeviceList()[1].address, fakePairedDevice2.address);
+        assertEquals(pairedDeviceList()[0].address, fakePairedDevice2.address);
+        assertEquals(pairedDeviceList()[1].address, fakePairedDevice1.address);
 
         // Remove both devices.
         bluetoothApi.simulateDevicesRemovedForTest(
diff --git a/chrome/test/data/webui/settings/cr_settings_browsertest.js b/chrome/test/data/webui/settings/cr_settings_browsertest.js
index e8b64862..176c2efa 100644
--- a/chrome/test/data/webui/settings/cr_settings_browsertest.js
+++ b/chrome/test/data/webui/settings/cr_settings_browsertest.js
@@ -1373,8 +1373,10 @@
   /** @override */
   extraLibraries: CrSettingsBrowserTest.prototype.extraLibraries.concat([
     '../cr_elements/cr_policy_strings.js',
+    '../test_browser_proxy.js',
     'site_list_entry_tests.js',
     'test_util.js',
+    'test_site_settings_prefs_browser_proxy.js',
   ]),
 };
 
diff --git a/chrome/test/data/webui/settings/site_entry_tests.js b/chrome/test/data/webui/settings/site_entry_tests.js
index c558d4dc..9a7cab8a 100644
--- a/chrome/test/data/webui/settings/site_entry_tests.js
+++ b/chrome/test/data/webui/settings/site_entry_tests.js
@@ -140,89 +140,6 @@
     assertTrue(overflowMenuButton.closest('.row-aligned').hidden);
   });
 
-  function resetSettingsViaOverflowMenu(buttonType) {
-    assertTrue(buttonType == 'cancel-button' || buttonType == 'action-button');
-    Polymer.dom.flush();
-    const overflowMenuButton = testElement.$.overflowMenuButton;
-    assertFalse(overflowMenuButton.closest('.row-aligned').hidden);
-    // Open the reset settings dialog and make sure both cancelling the
-    // action and resetting all permissions work.
-    const overflowMenu = testElement.$.menu.get();
-    const menuItems = overflowMenu.querySelectorAll('.dropdown-item');
-
-    // Test clicking on the overflow menu button opens the menu.
-    assertFalse(overflowMenu.open);
-    overflowMenuButton.click();
-    assertTrue(overflowMenu.open);
-
-    // Open the reset settings dialog and tap the |buttonType| button.
-    assertFalse(testElement.$.confirmResetSettings.open);
-    menuItems[0].click();
-    assertTrue(testElement.$.confirmResetSettings.open);
-    const actionButtonList =
-        testElement.$.confirmResetSettings.getElementsByClassName(buttonType);
-    assertEquals(1, actionButtonList.length);
-    actionButtonList[0].click();
-
-    // Check the dialog and overflow menu are now both closed.
-    assertFalse(testElement.$.confirmResetSettings.open);
-    assertFalse(overflowMenu.open);
-  }
-
-  test('cancelling the confirm dialog on resetting settings works', function() {
-    testElement.siteGroup = TEST_MULTIPLE_SITE_GROUP;
-    resetSettingsViaOverflowMenu('cancel-button');
-  });
-
-  test(
-      'with multiple origins can reset settings via overflow menu', function() {
-        let deleteCurrentEntryCalled = false;
-        testElement.addEventListener('delete-current-entry', function() {
-          deleteCurrentEntryCalled = true;
-        });
-
-        // Test when entire siteGroup has no data or cookies.
-        // Clone this object to avoid propagating changes made in this test.
-        testElement.siteGroup =
-            JSON.parse(JSON.stringify(TEST_MULTIPLE_SITE_GROUP));
-        resetSettingsViaOverflowMenu('action-button');
-        // Ensure a call was made to setOriginPermissions for each origin.
-        assertEquals(
-            TEST_MULTIPLE_SITE_GROUP.origins.length,
-            browserProxy.getCallCount('setOriginPermissions'));
-        assertTrue(deleteCurrentEntryCalled);
-
-        // Test when one origin has data and cookies.
-        // Clone this object to avoid propagating changes made in this test.
-        testElement.siteGroup =
-            JSON.parse(JSON.stringify(TEST_MULTIPLE_SITE_GROUP));
-        testElement.siteGroup.origins[0].hasPermissionSettings = true;
-        testElement.siteGroup.origins[0].usage = 100;
-        testElement.siteGroup.origins[0].numCookies = 2;
-        deleteCurrentEntryCalled = false;
-        resetSettingsViaOverflowMenu('action-button');
-        assertFalse(deleteCurrentEntryCalled);
-        assertEquals(1, testElement.siteGroup.origins.length);
-        assertFalse(testElement.siteGroup.origins[0].hasPermissionSettings);
-        assertEquals(testElement.siteGroup.origins[0].usage, 100);
-        assertEquals(testElement.siteGroup.origins[0].numCookies, 2);
-
-        // Test when none of origin have data or cookies, but etld+1 has
-        // cookies. In this case, a placeholder origin will be created with the
-        // Etld+1 cookies number. Clone this object to avoid propagating changes
-        // made in this test.
-        testElement.siteGroup =
-            JSON.parse(JSON.stringify(TEST_MULTIPLE_SITE_GROUP));
-        testElement.siteGroup.numCookies = 5;
-        deleteCurrentEntryCalled = false;
-        resetSettingsViaOverflowMenu('action-button');
-        assertFalse(deleteCurrentEntryCalled);
-        assertEquals(1, testElement.siteGroup.origins.length);
-        assertFalse(testElement.siteGroup.origins[0].hasPermissionSettings);
-        assertEquals(testElement.siteGroup.origins[0].usage, 0);
-        assertEquals(testElement.siteGroup.origins[0].numCookies, 5);
-      });
-
   test(
       'moving from grouped to ungrouped does not get stuck in opened state',
       function() {
@@ -321,78 +238,4 @@
 
     });
   });
-
-  function clearDataViaOverflowMenu(buttonType) {
-    assertTrue(buttonType == 'cancel-button' || buttonType == 'action-button');
-    Polymer.dom.flush();
-    const overflowMenuButton = testElement.$.overflowMenuButton;
-    assertFalse(overflowMenuButton.closest('.row-aligned').hidden);
-
-    // Open the clear data dialog and make sure both cancelling the
-    // action and resetting all permissions work.
-    const overflowMenu = testElement.$.menu.get();
-    const menuItems = overflowMenu.querySelectorAll('.dropdown-item');
-    // Test clicking on the overflow menu button opens the menu.
-    assertFalse(overflowMenu.open);
-    overflowMenuButton.click();
-    assertTrue(overflowMenu.open);
-
-    // Open the clear data dialog and tap the |buttonType| button.
-    assertFalse(testElement.$.confirmClearData.open);
-    menuItems[1].click();
-    assertTrue(testElement.$.confirmClearData.open);
-    const actionButtonList =
-        testElement.$.confirmClearData.getElementsByClassName(buttonType);
-    assertEquals(1, actionButtonList.length);
-    actionButtonList[0].click();
-
-    // Check the dialog and overflow menu are now both closed.
-    assertFalse(testElement.$.confirmClearData.open);
-    assertFalse(overflowMenu.open);
-  }
-
-  test('cancelling the confirm dialog on clear data works', function() {
-    testElement.siteGroup = TEST_MULTIPLE_SITE_GROUP;
-    clearDataViaOverflowMenu('cancel-button');
-  });
-
-  test('with multiple origins can clear data via overflow menu', function() {
-    let deleteCurrentEntryCalled = false;
-    testElement.addEventListener('delete-current-entry', function() {
-      deleteCurrentEntryCalled = true;
-    });
-    // Test when all origins has no permission settings and no data.
-    // Clone this object to avoid propagating changes made in this test.
-    testElement.siteGroup =
-        JSON.parse(JSON.stringify(TEST_MULTIPLE_SITE_GROUP));
-    clearDataViaOverflowMenu('action-button');
-    // Ensure a call was made to clearEtldPlus1DataAndCookies.
-    assertEquals(1, browserProxy.getCallCount('clearEtldPlus1DataAndCookies'));
-    assertTrue(deleteCurrentEntryCalled);
-
-    // Test when there is one origin has permissions settings.
-    // Clone this object to avoid propagating changes made in this test.
-    testElement.siteGroup =
-        JSON.parse(JSON.stringify(TEST_MULTIPLE_SITE_GROUP));
-    deleteCurrentEntryCalled = false;
-    testElement.siteGroup.origins[0].hasPermissionSettings = true;
-    clearDataViaOverflowMenu('action-button');
-    assertFalse(deleteCurrentEntryCalled);
-    assertEquals(testElement.siteGroup.origins.length, 1);
-
-    // Test when one origin has permission settings and data, clear data only
-    // clears the data and cookies.
-    testElement.siteGroup =
-        JSON.parse(JSON.stringify(TEST_MULTIPLE_SITE_GROUP));
-    deleteCurrentEntryCalled = false;
-    testElement.siteGroup.origins[0].hasPermissionSettings = true;
-    testElement.siteGroup.origins[0].usage = 100;
-    testElement.siteGroup.origins[0].numCookies = 3;
-    clearDataViaOverflowMenu('action-button');
-    assertFalse(deleteCurrentEntryCalled);
-    assertEquals(testElement.siteGroup.origins.length, 1);
-    assertTrue(testElement.siteGroup.origins[0].hasPermissionSettings);
-    assertEquals(testElement.siteGroup.origins[0].usage, 0);
-    assertEquals(testElement.siteGroup.origins[0].numCookies, 0);
-  });
 });
diff --git a/chrome/test/data/webui/settings/site_list_entry_tests.js b/chrome/test/data/webui/settings/site_list_entry_tests.js
index 66640a34..27bb9f6 100644
--- a/chrome/test/data/webui/settings/site_list_entry_tests.js
+++ b/chrome/test/data/webui/settings/site_list_entry_tests.js
@@ -6,7 +6,16 @@
 
 suite('SiteListEntry', function() {
   let testElement;
+
+  /**
+   * The mock proxy object to use during test.
+   * @type {TestSiteSettingsPrefsBrowserProxy}
+   */
+  let browserProxy;
+
   setup(function() {
+    browserProxy = new TestSiteSettingsPrefsBrowserProxy();
+    settings.SiteSettingsPrefsBrowserProxyImpl.instance_ = browserProxy;
     PolymerTest.clearBody();
     testElement = document.createElement('site-list-entry');
     document.body.appendChild(testElement);
@@ -50,4 +59,53 @@
           siteDescription.textContent);
     });
   }
+
+  test('not valid origin does not go to site details page', function() {
+    loadTimeData.overrideValues({enableSiteSettings: true});
+    browserProxy.setIsOriginValid(false);
+    testElement.model = {
+      controlledBy: chrome.settingsPrivate.ControlledBy.USER_POLICY,
+      enforcement: chrome.settingsPrivate.Enforcement.ENFORCED,
+      origin: 'example.com',
+    };
+    settings.navigateTo(settings.routes.SITE_SETTINGS);
+    return browserProxy.whenCalled('isOriginValid').then((args) => {
+      assertEquals('example.com', args);
+      Polymer.dom.flush();
+      const settingsRow = testElement.root.querySelector('.settings-row');
+      assertFalse(settingsRow.hasAttribute('actionable'));
+      const subpageArrow = settingsRow.querySelector('.subpage-arrow');
+      assertTrue(!subpageArrow);
+      const separator = settingsRow.querySelector('.separator');
+      assertTrue(!separator);
+      settingsRow.click();
+      assertEquals(
+          settings.routes.SITE_SETTINGS.path, settings.getCurrentRoute().path);
+    });
+  });
+
+  test('valid origin goes to site details page', function() {
+    loadTimeData.overrideValues({enableSiteSettings: true});
+    browserProxy.setIsOriginValid(true);
+    testElement.model = {
+      controlledBy: chrome.settingsPrivate.ControlledBy.USER_POLICY,
+      enforcement: chrome.settingsPrivate.Enforcement.ENFORCED,
+      origin: 'http://example.com',
+    };
+    settings.navigateTo(settings.routes.SITE_SETTINGS);
+    return browserProxy.whenCalled('isOriginValid').then((args) => {
+      assertEquals('http://example.com', args);
+      Polymer.dom.flush();
+      settingsRow = testElement.root.querySelector('.settings-row');
+      assertTrue(settingsRow.hasAttribute('actionable'));
+      const subpageArrow = settingsRow.querySelector('.subpage-arrow');
+      assertFalse(!subpageArrow);
+      const separator = settingsRow.querySelector('.separator');
+      assertFalse(!separator);
+      settingsRow.click();
+      assertEquals(
+          settings.routes.SITE_SETTINGS_SITE_DETAILS.path,
+          settings.getCurrentRoute().path);
+    });
+  });
 });
diff --git a/chromecast/browser/cast_content_browser_client.cc b/chromecast/browser/cast_content_browser_client.cc
index 7093cedeb..c99d783 100644
--- a/chromecast/browser/cast_content_browser_client.cc
+++ b/chromecast/browser/cast_content_browser_client.cc
@@ -6,6 +6,7 @@
 
 #include <stddef.h>
 
+#include <memory>
 #include <string>
 #include <utility>
 
@@ -627,7 +628,8 @@
     content::StoragePartition* partition,
     storage::OptionalQuotaSettingsCallback callback) {
   storage::GetNominalDynamicSettings(
-      partition->GetPath(), context->IsOffTheRecord(), std::move(callback));
+      partition->GetPath(), context->IsOffTheRecord(),
+      storage::GetDefaultDiskInfoHelper(), std::move(callback));
 }
 
 void CastContentBrowserClient::AllowCertificateError(
diff --git a/chromeos/components/drivefs/BUILD.gn b/chromeos/components/drivefs/BUILD.gn
index 1344deb..00a04b8 100644
--- a/chromeos/components/drivefs/BUILD.gn
+++ b/chromeos/components/drivefs/BUILD.gn
@@ -15,6 +15,8 @@
     "drivefs_host_observer.h",
     "drivefs_search.cc",
     "drivefs_search.h",
+    "drivefs_session.cc",
+    "drivefs_session.h",
     "fake_drivefs_launcher_client.cc",
     "fake_drivefs_launcher_client.h",
     "pending_connection_manager.cc",
@@ -61,6 +63,7 @@
     "drivefs_bootstrap_unittest.cc",
     "drivefs_host_unittest.cc",
     "drivefs_search_unittest.cc",
+    "drivefs_session_unittest.cc",
     "pending_connection_manager_unittest.cc",
   ]
 
diff --git a/chromeos/components/drivefs/drivefs_auth.cc b/chromeos/components/drivefs/drivefs_auth.cc
index 02a908f..6fb88a14 100644
--- a/chromeos/components/drivefs/drivefs_auth.cc
+++ b/chromeos/components/drivefs/drivefs_auth.cc
@@ -23,8 +23,8 @@
 
 DriveFsAuth::~DriveFsAuth() {}
 
-base::Optional<std::string> DriveFsAuth::TakeCachedAccessToken() {
-  const auto& token = MaybeGetCachedToken(true);
+base::Optional<std::string> DriveFsAuth::GetCachedAccessToken() {
+  const auto& token = GetOrResetCachedToken(true);
   if (token.empty()) {
     return base::nullopt;
   }
@@ -40,7 +40,7 @@
     return;
   }
 
-  const std::string& token = MaybeGetCachedToken(use_cached);
+  const std::string& token = GetOrResetCachedToken(use_cached);
   if (!token.empty()) {
     std::move(callback).Run(mojom::AccessTokenStatus::kSuccess, token);
     return;
@@ -78,8 +78,7 @@
       .Run(mojom::AccessTokenStatus::kSuccess, *access_token);
 }
 
-const std::string& DriveFsAuth::MaybeGetCachedToken(bool use_cached) {
-  // Return value from cache at most once per mount.
+const std::string& DriveFsAuth::GetOrResetCachedToken(bool use_cached) {
   if (!use_cached || clock_->Now() >= last_token_expiry_) {
     last_token_.clear();
   }
diff --git a/chromeos/components/drivefs/drivefs_auth.h b/chromeos/components/drivefs/drivefs_auth.h
index c84e0bd6..90e9ebc 100644
--- a/chromeos/components/drivefs/drivefs_auth.h
+++ b/chromeos/components/drivefs/drivefs_auth.h
@@ -57,7 +57,7 @@
     return delegate_->GetObfuscatedAccountId();
   }
 
-  base::Optional<std::string> TakeCachedAccessToken();
+  base::Optional<std::string> GetCachedAccessToken();
 
   virtual void GetAccessToken(
       bool use_cached,
@@ -71,7 +71,7 @@
                             base::Time expiration_time,
                             const GoogleServiceAuthError& error);
 
-  const std::string& MaybeGetCachedToken(bool use_cached);
+  const std::string& GetOrResetCachedToken(bool use_cached);
 
   void UpdateCachedToken(const std::string& token, base::Time expiry);
 
diff --git a/chromeos/components/drivefs/drivefs_bootstrap.cc b/chromeos/components/drivefs/drivefs_bootstrap.cc
index a847aea..a2b1fab3 100644
--- a/chromeos/components/drivefs/drivefs_bootstrap.cc
+++ b/chromeos/components/drivefs/drivefs_bootstrap.cc
@@ -4,6 +4,8 @@
 
 #include "chromeos/components/drivefs/drivefs_bootstrap.h"
 
+#include <utility>
+
 #include "base/bind.h"
 #include "chromeos/components/drivefs/pending_connection_manager.h"
 #include "mojo/public/cpp/platform/platform_channel_endpoint.h"
@@ -47,34 +49,66 @@
       mojo::PlatformChannelEndpoint(mojo::PlatformHandle(std::move(handle))));
 }
 
-DriveFsConnection::DriveFsConnection(
-    std::unique_ptr<DriveFsBootstrapListener> bootstrap_listener,
-    mojom::DriveFsConfigurationPtr config,
-    mojom::DriveFsDelegate* delegate,
-    base::OnceClosure on_disconnected)
-    : bootstrap_listener_(std::move(bootstrap_listener)),
-      delegate_binding_(delegate),
-      on_disconnected_(std::move(on_disconnected)) {
-  auto bootstrap = bootstrap_listener_->bootstrap();
+class DriveFsConnectionImpl : public DriveFsConnection {
+ public:
+  DriveFsConnectionImpl(
+      std::unique_ptr<DriveFsBootstrapListener> bootstrap_listener,
+      mojom::DriveFsConfigurationPtr config)
+      : bootstrap_listener_(std::move(bootstrap_listener)),
+        config_(std::move(config)) {}
 
-  mojom::DriveFsDelegatePtr delegate_ptr;
-  delegate_binding_.Bind(mojo::MakeRequest(&delegate_ptr));
-  delegate_binding_.set_connection_error_handler(base::BindOnce(
-      &DriveFsConnection::OnMojoConnectionError, base::Unretained(this)));
+  ~DriveFsConnectionImpl() override = default;
 
-  bootstrap->Init(std::move(config), mojo::MakeRequest(&drivefs_),
-                  std::move(delegate_ptr));
+  base::UnguessableToken Connect(mojom::DriveFsDelegate* delegate,
+                                 base::OnceClosure on_disconnected) override {
+    delegate_binding_ =
+        std::make_unique<mojo::Binding<mojom::DriveFsDelegate>>(delegate);
+    on_disconnected_ = std::move(on_disconnected);
 
-  drivefs_.set_connection_error_handler(base::BindOnce(
-      &DriveFsConnection::OnMojoConnectionError, base::Unretained(this)));
-}
+    auto bootstrap = bootstrap_listener_->bootstrap();
+    auto token = bootstrap_listener_->pending_token();
 
-DriveFsConnection::~DriveFsConnection() = default;
+    mojom::DriveFsDelegatePtr delegate_ptr;
+    delegate_binding_->Bind(mojo::MakeRequest(&delegate_ptr));
+    delegate_binding_->set_connection_error_handler(base::BindOnce(
+        &DriveFsConnectionImpl::OnMojoConnectionError, base::Unretained(this)));
 
-void DriveFsConnection::OnMojoConnectionError() {
-  if (on_disconnected_ && bootstrap_listener_->is_connected()) {
-    std::move(on_disconnected_).Run();
+    bootstrap->Init(std::move(config_), mojo::MakeRequest(&drivefs_),
+                    std::move(delegate_ptr));
+
+    drivefs_.set_connection_error_handler(base::BindOnce(
+        &DriveFsConnectionImpl::OnMojoConnectionError, base::Unretained(this)));
+
+    return token;
   }
-}
 
+  mojom::DriveFs& GetDriveFs() override {
+    CHECK(drivefs_);
+    return *drivefs_;
+  }
+
+ private:
+  void OnMojoConnectionError() {
+    if (on_disconnected_ && bootstrap_listener_->is_connected()) {
+      std::move(on_disconnected_).Run();
+    }
+  }
+
+  const std::unique_ptr<DriveFsBootstrapListener> bootstrap_listener_;
+  mojom::DriveFsConfigurationPtr config_;
+
+  std::unique_ptr<mojo::Binding<mojom::DriveFsDelegate>> delegate_binding_;
+  mojom::DriveFsPtr drivefs_;
+
+  base::OnceClosure on_disconnected_;
+
+  DISALLOW_COPY_AND_ASSIGN(DriveFsConnectionImpl);
+};
+
+std::unique_ptr<DriveFsConnection> DriveFsConnection::Create(
+    std::unique_ptr<DriveFsBootstrapListener> bootstrap_listener,
+    mojom::DriveFsConfigurationPtr config) {
+  return std::make_unique<DriveFsConnectionImpl>(std::move(bootstrap_listener),
+                                                 std::move(config));
+}
 }  // namespace drivefs
diff --git a/chromeos/components/drivefs/drivefs_bootstrap.h b/chromeos/components/drivefs/drivefs_bootstrap.h
index 2cf511f..6673390e 100644
--- a/chromeos/components/drivefs/drivefs_bootstrap.h
+++ b/chromeos/components/drivefs/drivefs_bootstrap.h
@@ -49,29 +49,17 @@
 // Establishes and holds mojo connection to DriveFS.
 class COMPONENT_EXPORT(DRIVEFS) DriveFsConnection {
  public:
-  DriveFsConnection(
-      std::unique_ptr<DriveFsBootstrapListener> bootstrap_listener,
-      mojom::DriveFsConfigurationPtr config,
-      mojom::DriveFsDelegate* delegate,
-      base::OnceClosure on_disconnected);
-  virtual ~DriveFsConnection();
+  DriveFsConnection() = default;
+  virtual ~DriveFsConnection() = default;
+  virtual base::UnguessableToken Connect(mojom::DriveFsDelegate* delegate,
+                                         base::OnceClosure on_disconnected) = 0;
+  virtual mojom::DriveFs& GetDriveFs() = 0;
 
-  const base::UnguessableToken& pending_token() const {
-    return bootstrap_listener_ ? bootstrap_listener_->pending_token()
-                               : base::UnguessableToken::Null();
-  }
-  mojom::DriveFs* drivefs_interface() const { return drivefs_.get(); }
+  static std::unique_ptr<DriveFsConnection> Create(
+      std::unique_ptr<DriveFsBootstrapListener> bootstrap_listener,
+      mojom::DriveFsConfigurationPtr config);
 
  private:
-  void OnMojoConnectionError();
-
-  std::unique_ptr<DriveFsBootstrapListener> bootstrap_listener_;
-
-  mojo::Binding<mojom::DriveFsDelegate> delegate_binding_;
-  mojom::DriveFsPtr drivefs_;
-
-  base::OnceClosure on_disconnected_;
-
   DISALLOW_COPY_AND_ASSIGN(DriveFsConnection);
 };
 
diff --git a/chromeos/components/drivefs/drivefs_bootstrap_unittest.cc b/chromeos/components/drivefs/drivefs_bootstrap_unittest.cc
index 62c2ff5..c450667c 100644
--- a/chromeos/components/drivefs/drivefs_bootstrap_unittest.cc
+++ b/chromeos/components/drivefs/drivefs_bootstrap_unittest.cc
@@ -80,11 +80,11 @@
   }
 
   base::UnguessableToken ListenForConnection() {
-    connection_ = std::make_unique<DriveFsConnection>(
-        CreateListener(), mojom::DriveFsConfiguration::New(), &mock_delegate_,
-        base::BindOnce(&DriveFsBootstrapTest::OnDisconnect,
-                       base::Unretained(this)));
-    return connection_->pending_token();
+    connection_ = DriveFsConnection::Create(CreateListener(),
+                                            mojom::DriveFsConfiguration::New());
+    return connection_->Connect(
+        &mock_delegate_, base::BindOnce(&DriveFsBootstrapTest::OnDisconnect,
+                                        base::Unretained(this)));
   }
 
   void WaitForConnection(const base::UnguessableToken& token) {
diff --git a/chromeos/components/drivefs/drivefs_host.cc b/chromeos/components/drivefs/drivefs_host.cc
index 32e7fce..158b70c 100644
--- a/chromeos/components/drivefs/drivefs_host.cc
+++ b/chromeos/components/drivefs/drivefs_host.cc
@@ -28,9 +28,7 @@
 
 namespace {
 
-constexpr char kMountScheme[] = "drivefs://";
 constexpr char kDataPath[] = "GCache/v2";
-constexpr base::TimeDelta kMountTimeout = base::TimeDelta::FromSeconds(20);
 
 }  // namespace
 
@@ -41,64 +39,43 @@
 
 // A container of state tied to a particular mounting of DriveFS. None of this
 // should be shared between mounts.
-class DriveFsHost::MountState
-    : public mojom::DriveFsDelegate,
-      public chromeos::disks::DiskMountManager::Observer,
-      public drive::DriveNotificationObserver {
+class DriveFsHost::MountState : public DriveFsSession,
+                                public drive::DriveNotificationObserver {
  public:
   explicit MountState(DriveFsHost* host)
-      : host_(host), weak_ptr_factory_(this) {
-    host_->disk_mount_manager_->AddObserver(this);
-
-    auto access_token = host_->account_token_delegate_->TakeCachedAccessToken();
-    token_fetch_attempted_ = bool{access_token};
-
-    mojo_connection_ = CreateMojoConnection(
-        {base::in_place, host_->delegate_->GetAccountId().GetUserEmail(),
-         std::move(access_token)});
-
-    auto pending_token = mojo_connection_->pending_token();
-    CHECK(pending_token);
-    source_path_ = base::StrCat({kMountScheme, pending_token.ToString()});
-    std::string datadir_option =
-        base::StrCat({"datadir=", host_->GetDataPath().value()});
-
-    host_->disk_mount_manager_->MountPath(
-        source_path_, "",
-        base::StrCat({"drivefs-", host_->delegate_->GetObfuscatedAccountId()}),
-        {datadir_option}, chromeos::MOUNT_TYPE_NETWORK_STORAGE,
-        chromeos::MOUNT_ACCESS_MODE_READ_WRITE);
-
-    host_->timer_->Start(
-        FROM_HERE, kMountTimeout,
-        base::BindOnce(&MountState::OnTimedOut, base::Unretained(this)));
-
+      : DriveFsSession(host->timer_.get(),
+                       DiskMounter::Create(host->disk_mount_manager_),
+                       CreateMojoConnection(host->account_token_delegate_.get(),
+                                            host->delegate_),
+                       host->GetDataPath(),
+                       host->GetDefaultMountDirName(),
+                       host->mount_observer_),
+        host_(host) {
+    token_fetch_attempted_ =
+        bool{host->account_token_delegate_->GetCachedAccessToken()};
     search_ = std::make_unique<DriveFsSearch>(
-        GetDriveFsInterface(), host_->network_connection_tracker_,
-        host_->clock_);
+        drivefs_interface(), host_->network_connection_tracker_, host_->clock_);
   }
 
   ~MountState() override {
     DCHECK_CALLED_ON_VALID_SEQUENCE(host_->sequence_checker_);
-    host_->disk_mount_manager_->RemoveObserver(this);
     host_->delegate_->GetDriveNotificationManager().RemoveObserver(this);
-    host_->timer_->Stop();
-    if (!mount_path_.empty()) {
-      host_->disk_mount_manager_->UnmountPath(
-          mount_path_.value(), chromeos::UNMOUNT_OPTIONS_NONE, {});
-    }
-    if (mounted()) {
+    if (is_mounted()) {
       for (auto& observer : host_->observers_) {
         observer.OnUnmounted();
       }
     }
   }
 
-  bool mounted() const { return drivefs_has_mounted_ && !mount_path_.empty(); }
-  const base::FilePath& mount_path() const { return mount_path_; }
-
-  mojom::DriveFs* GetDriveFsInterface() const {
-    return mojo_connection_->drivefs_interface();
+  static std::unique_ptr<DriveFsConnection> CreateMojoConnection(
+      DriveFsAuth* auth_delegate,
+      DriveFsHost::Delegate* delegate) {
+    auto access_token = auth_delegate->GetCachedAccessToken();
+    mojom::DriveFsConfigurationPtr config = {
+        base::in_place, auth_delegate->GetAccountId().GetUserEmail(),
+        std::move(access_token)};
+    return DriveFsConnection::Create(delegate->CreateMojoListener(),
+                                     std::move(config));
   }
 
   mojom::QueryParameters::QuerySource SearchDriveFs(
@@ -119,38 +96,6 @@
     token_fetch_attempted_ = true;
   }
 
-  void OnHeartbeat() override {
-    DCHECK_CALLED_ON_VALID_SEQUENCE(host_->sequence_checker_);
-    if (host_->timer_->IsRunning()) {
-      host_->timer_->Reset();
-    }
-  }
-
-  void OnMounted() override {
-    DCHECK_CALLED_ON_VALID_SEQUENCE(host_->sequence_checker_);
-    DCHECK(!drivefs_has_mounted_);
-    drivefs_has_mounted_ = true;
-    MaybeNotifyDelegateOnMounted();
-  }
-
-  void OnMountFailed(base::Optional<base::TimeDelta> remount_delay) override {
-    DCHECK_CALLED_ON_VALID_SEQUENCE(host_->sequence_checker_);
-    drivefs_has_mounted_ = false;
-    drivefs_has_terminated_ = true;
-    bool needs_restart = remount_delay.has_value();
-    host_->mount_observer_->OnMountFailed(
-        needs_restart ? MountObserver::MountFailure::kNeedsRestart
-                      : MountObserver::MountFailure::kUnknown,
-        std::move(remount_delay));
-  }
-
-  void OnUnmounted(base::Optional<base::TimeDelta> remount_delay) override {
-    DCHECK_CALLED_ON_VALID_SEQUENCE(host_->sequence_checker_);
-    drivefs_has_mounted_ = false;
-    drivefs_has_terminated_ = true;
-    host_->mount_observer_->OnUnmounted(std::move(remount_delay));
-  }
-
   void OnSyncingStatusUpdate(mojom::SyncingStatusPtr status) override {
     for (auto& observer : host_->observers_) {
       observer.OnSyncingStatusUpdate(*status);
@@ -198,60 +143,6 @@
         additions, removals);
   }
 
-  void OnConnectionError() {
-    DCHECK_CALLED_ON_VALID_SEQUENCE(host_->sequence_checker_);
-    if (!drivefs_has_terminated_) {
-      if (mounted()) {
-        host_->mount_observer_->OnUnmounted({});
-      } else {
-        host_->mount_observer_->OnMountFailed(
-            MountObserver::MountFailure::kIpcDisconnect, {});
-      }
-      drivefs_has_terminated_ = true;
-    }
-  }
-
-  void OnTimedOut() {
-    DCHECK_CALLED_ON_VALID_SEQUENCE(host_->sequence_checker_);
-    host_->timer_->Stop();
-    drivefs_has_mounted_ = false;
-    drivefs_has_terminated_ = true;
-    host_->mount_observer_->OnMountFailed(MountObserver::MountFailure::kTimeout,
-                                          {});
-  }
-
-  void MaybeNotifyDelegateOnMounted() {
-    if (mounted()) {
-      host_->timer_->Stop();
-      host_->mount_observer_->OnMounted(mount_path());
-    }
-  }
-
-  // DiskMountManager::Observer:
-  void OnMountEvent(chromeos::disks::DiskMountManager::MountEvent event,
-                    chromeos::MountError error_code,
-                    const chromeos::disks::DiskMountManager::MountPointInfo&
-                        mount_info) override {
-    DCHECK_CALLED_ON_VALID_SEQUENCE(host_->sequence_checker_);
-    if (mount_info.mount_type != chromeos::MOUNT_TYPE_NETWORK_STORAGE ||
-        mount_info.source_path != source_path_ ||
-        event != chromeos::disks::DiskMountManager::MOUNTING) {
-      return;
-    }
-    if (error_code != chromeos::MOUNT_ERROR_NONE) {
-      auto* observer = host_->mount_observer_;
-
-      // Deletes |this|.
-      host_->Unmount();
-      observer->OnMountFailed(MountObserver::MountFailure::kInvocation, {});
-      return;
-    }
-    DCHECK(!mount_info.mount_path.empty());
-    mount_path_ = base::FilePath(mount_info.mount_path);
-    host_->disk_mount_manager_->RemoveObserver(this);
-    MaybeNotifyDelegateOnMounted();
-  }
-
   // DriveNotificationObserver overrides:
   void OnNotificationReceived(
       const std::map<std::string, int64_t>& invalidations) override {
@@ -261,41 +152,20 @@
       options.emplace_back(base::in_place, invalidation.second,
                            invalidation.first);
     }
-    GetDriveFsInterface()->FetchChangeLog(std::move(options));
+    drivefs_interface()->FetchChangeLog(std::move(options));
   }
 
   void OnNotificationTimerFired() override {
-    GetDriveFsInterface()->FetchAllChangeLogs();
-  }
-
-  std::unique_ptr<DriveFsConnection> CreateMojoConnection(
-      mojom::DriveFsConfigurationPtr config) {
-    return std::make_unique<DriveFsConnection>(
-        host_->delegate_->CreateMojoListener(), std::move(config), this,
-        base::BindOnce(&MountState::OnConnectionError, base::Unretained(this)));
+    drivefs_interface()->FetchAllChangeLogs();
   }
 
   // Owns |this|.
   DriveFsHost* const host_;
 
-  std::unique_ptr<DriveFsConnection> mojo_connection_;
-
-  // The path passed to cros-disks to mount.
-  std::string source_path_;
-
-  // The path where DriveFS is mounted.
-  base::FilePath mount_path_;
-
   std::unique_ptr<DriveFsSearch> search_;
 
-  bool drivefs_has_mounted_ = false;
-  bool drivefs_has_terminated_ = false;
   bool token_fetch_attempted_ = false;
 
-  base::Time last_shared_with_me_response_;
-
-  base::WeakPtrFactory<MountState> weak_ptr_factory_;
-
   DISALLOW_COPY_AND_ASSIGN(MountState);
 };
 
@@ -351,15 +221,13 @@
 }
 
 bool DriveFsHost::IsMounted() const {
-  return mount_state_ && mount_state_->mounted();
+  return mount_state_ && mount_state_->is_mounted();
 }
 
 base::FilePath DriveFsHost::GetMountPath() const {
-  return mount_state_ && mount_state_->mounted()
+  return mount_state_ && mount_state_->is_mounted()
              ? mount_state_->mount_path()
-             : base::FilePath("/media/fuse")
-                   .Append(base::StrCat(
-                       {"drivefs-", delegate_->GetObfuscatedAccountId()}));
+             : base::FilePath("/media/fuse").Append(GetDefaultMountDirName());
 }
 
 base::FilePath DriveFsHost::GetDataPath() const {
@@ -368,10 +236,10 @@
 }
 
 mojom::DriveFs* DriveFsHost::GetDriveFsInterface() const {
-  if (!mount_state_ || !mount_state_->mounted()) {
+  if (!mount_state_ || !mount_state_->is_mounted()) {
     return nullptr;
   }
-  return mount_state_->GetDriveFsInterface();
+  return mount_state_->drivefs_interface();
 }
 
 mojom::QueryParameters::QuerySource DriveFsHost::PerformSearch(
@@ -380,4 +248,8 @@
   return mount_state_->SearchDriveFs(std::move(query), std::move(callback));
 }
 
+std::string DriveFsHost::GetDefaultMountDirName() const {
+  return base::StrCat({"drivefs-", delegate_->GetObfuscatedAccountId()});
+}
+
 }  // namespace drivefs
diff --git a/chromeos/components/drivefs/drivefs_host.h b/chromeos/components/drivefs/drivefs_host.h
index afd01f49..ab92a88 100644
--- a/chromeos/components/drivefs/drivefs_host.h
+++ b/chromeos/components/drivefs/drivefs_host.h
@@ -16,6 +16,7 @@
 #include "base/time/clock.h"
 #include "base/timer/timer.h"
 #include "chromeos/components/drivefs/drivefs_auth.h"
+#include "chromeos/components/drivefs/drivefs_session.h"
 #include "chromeos/components/drivefs/mojom/drivefs.mojom.h"
 #include "chromeos/disks/disk_mount_manager.h"
 #include "components/account_id/account_id.h"
@@ -45,27 +46,7 @@
 // file manager.
 class COMPONENT_EXPORT(DRIVEFS) DriveFsHost {
  public:
-  class MountObserver {
-   public:
-    enum class MountFailure {
-      kUnknown,
-      kNeedsRestart,
-      kIpcDisconnect,
-      kInvocation,
-      kTimeout,
-    };
-
-    MountObserver() = default;
-    virtual ~MountObserver() = default;
-    virtual void OnMounted(const base::FilePath& mount_path) = 0;
-    virtual void OnUnmounted(base::Optional<base::TimeDelta> remount_delay) = 0;
-    virtual void OnMountFailed(
-        MountFailure failure,
-        base::Optional<base::TimeDelta> remount_delay) = 0;
-
-   private:
-    DISALLOW_COPY_AND_ASSIGN(MountObserver);
-  };
+  using MountObserver = DriveFsSession::MountObserver;
 
   class Delegate : public DriveFsAuth::Delegate {
    public:
@@ -118,6 +99,8 @@
   class AccountTokenDelegate;
   class MountState;
 
+  std::string GetDefaultMountDirName() const;
+
   SEQUENCE_CHECKER(sequence_checker_);
 
   // The path to the user's profile.
diff --git a/chromeos/components/drivefs/drivefs_session.cc b/chromeos/components/drivefs/drivefs_session.cc
new file mode 100644
index 0000000..581cbd8
--- /dev/null
+++ b/chromeos/components/drivefs/drivefs_session.cc
@@ -0,0 +1,236 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chromeos/components/drivefs/drivefs_session.h"
+
+#include <utility>
+
+#include "base/strings/strcat.h"
+#include "chromeos/components/drivefs/drivefs_bootstrap.h"
+
+namespace drivefs {
+
+namespace {
+
+using MountFailure = DriveFsSession::MountObserver::MountFailure;
+constexpr char kDataDirOption[] = "datadir=";
+constexpr char kMountScheme[] = "drivefs://";
+constexpr base::TimeDelta kMountTimeout = base::TimeDelta::FromSeconds(20);
+
+class DiskMounterImpl : public DiskMounter,
+                        public chromeos::disks::DiskMountManager::Observer {
+ public:
+  explicit DiskMounterImpl(
+      chromeos::disks::DiskMountManager* disk_mount_manager)
+      : disk_mount_manager_(disk_mount_manager) {}
+
+  ~DiskMounterImpl() override {
+    disk_mount_manager_->RemoveObserver(this);
+    if (!mount_path_.empty()) {
+      Unmount();
+    }
+  }
+
+  void Mount(const base::UnguessableToken& token,
+             const base::FilePath& data_path,
+             const std::string& desired_mount_dir_name,
+             base::OnceCallback<void(base::FilePath)> callback) override {
+    DCHECK(mount_path_.empty());
+    DCHECK(callback_.is_null());
+    callback_ = std::move(callback);
+
+    disk_mount_manager_->AddObserver(this);
+    source_path_ = base::StrCat({kMountScheme, token.ToString()});
+    std::string datadir_option =
+        base::StrCat({kDataDirOption, data_path.value()});
+    disk_mount_manager_->MountPath(source_path_, "", desired_mount_dir_name,
+                                   {datadir_option},
+                                   chromeos::MOUNT_TYPE_NETWORK_STORAGE,
+                                   chromeos::MOUNT_ACCESS_MODE_READ_WRITE);
+  }
+
+ private:
+  void Unmount() {
+    disk_mount_manager_->RemoveObserver(this);
+    if (!mount_path_.empty()) {
+      disk_mount_manager_->UnmountPath(mount_path_.value(),
+                                       chromeos::UNMOUNT_OPTIONS_NONE, {});
+      mount_path_.clear();
+    }
+  }
+
+  // DiskMountManager::Observer:
+  void OnMountEvent(chromeos::disks::DiskMountManager::MountEvent event,
+                    chromeos::MountError error_code,
+                    const chromeos::disks::DiskMountManager::MountPointInfo&
+                        mount_info) override {
+    if (mount_info.mount_type != chromeos::MOUNT_TYPE_NETWORK_STORAGE ||
+        mount_info.source_path != source_path_ ||
+        event != chromeos::disks::DiskMountManager::MOUNTING) {
+      return;
+    }
+    DCHECK(mount_path_.empty());
+    DCHECK(!callback_.is_null());
+    if (error_code == chromeos::MOUNT_ERROR_NONE) {
+      disk_mount_manager_->RemoveObserver(this);
+      DCHECK(!mount_info.mount_path.empty());
+      mount_path_ = base::FilePath(mount_info.mount_path);
+    }
+    std::move(callback_).Run(mount_path_);
+  }
+
+  chromeos::disks::DiskMountManager* const disk_mount_manager_;
+  base::OnceCallback<void(base::FilePath)> callback_;
+  // The path passed to cros-disks to mount.
+  std::string source_path_;
+  base::FilePath mount_path_;
+
+  DISALLOW_COPY_AND_ASSIGN(DiskMounterImpl);
+};
+
+}  // namespace
+
+std::unique_ptr<DiskMounter> DiskMounter::Create(
+    chromeos::disks::DiskMountManager* disk_mount_manager) {
+  return std::make_unique<DiskMounterImpl>(disk_mount_manager);
+}
+
+DriveFsSession::DriveFsSession(base::OneShotTimer* timer,
+                               std::unique_ptr<DiskMounter> disk_mounter,
+                               std::unique_ptr<DriveFsConnection> connection,
+                               const base::FilePath& data_path,
+                               const std::string& desired_mount_dir_name,
+                               MountObserver* observer)
+    : timer_(timer),
+      disk_mounter_(std::move(disk_mounter)),
+      connection_(std::move(connection)),
+      observer_(observer) {
+  auto token = connection_->Connect(
+      this, base::BindOnce(&DriveFsSession::OnMojoConnectionError,
+                           base::Unretained(this)));
+  CHECK(token);
+  drivefs_ = &connection_->GetDriveFs();
+  disk_mounter_->Mount(token, data_path, desired_mount_dir_name,
+                       base::BindOnce(&DriveFsSession::OnDiskMountCompleted,
+                                      base::Unretained(this)));
+  timer_->Start(
+      FROM_HERE, kMountTimeout,
+      base::BindOnce(&DriveFsSession::OnMountTimedOut, base::Unretained(this)));
+}
+
+DriveFsSession::~DriveFsSession() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  timer_->Stop();
+  is_mounted_ = false;
+  drivefs_has_terminated_ = true;
+  disk_mounter_.reset();
+}
+
+void DriveFsSession::OnDiskMountCompleted(base::FilePath mount_path) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  if (!mount_path.empty()) {
+    mount_path_ = mount_path;
+    MaybeNotifyOnMounted();
+  } else {
+    NotifyFailed(MountFailure::kInvocation, {});
+  }
+}
+
+void DriveFsSession::OnMojoConnectionError() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  if (!drivefs_has_terminated_) {
+    bool was_mounted = is_mounted_;
+    is_mounted_ = false;
+    drivefs_has_terminated_ = true;
+    if (was_mounted) {
+      NotifyUnmounted({});
+    } else {
+      NotifyFailed(MountFailure::kIpcDisconnect, {});
+    }
+  }
+}
+
+void DriveFsSession::OnMountTimedOut() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  DCHECK(!is_mounted_);
+  DCHECK(!drivefs_has_terminated_);
+  timer_->Stop();
+  drivefs_has_terminated_ = true;
+  NotifyFailed(MountFailure::kTimeout, {});
+}
+
+void DriveFsSession::MaybeNotifyOnMounted() {
+  is_mounted_ =
+      drivefs_has_started_ && !drivefs_has_terminated_ && !mount_path_.empty();
+  if (is_mounted_) {
+    timer_->Stop();
+    observer_->OnMounted(mount_path());
+  }
+}
+
+void DriveFsSession::NotifyFailed(
+    MountFailure failure,
+    base::Optional<base::TimeDelta> remount_delay) {
+  // May delete |this|.
+  auto connection = std::move(connection_);
+  if (connection) {
+    observer_->OnMountFailed(failure, remount_delay);
+  }
+}
+
+void DriveFsSession::NotifyUnmounted(
+    base::Optional<base::TimeDelta> remount_delay) {
+  // May delete |this|.
+  auto connection = std::move(connection_);
+  if (connection) {
+    observer_->OnUnmounted(remount_delay);
+  }
+}
+
+void DriveFsSession::OnMounted() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  DCHECK(!drivefs_has_started_);
+  DCHECK(!is_mounted_);
+  if (!drivefs_has_terminated_) {
+    drivefs_has_started_ = true;
+    MaybeNotifyOnMounted();
+  }
+}
+
+void DriveFsSession::OnMountFailed(
+    base::Optional<base::TimeDelta> remount_delay) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  DCHECK(!drivefs_has_started_);
+  DCHECK(!is_mounted_);
+  if (!drivefs_has_terminated_) {
+    drivefs_has_terminated_ = true;
+    bool needs_restart = remount_delay.has_value();
+    NotifyFailed(
+        needs_restart ? MountFailure::kNeedsRestart : MountFailure::kUnknown,
+        std::move(remount_delay));
+  }
+}
+
+void DriveFsSession::OnUnmounted(
+    base::Optional<base::TimeDelta> remount_delay) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  DCHECK(drivefs_has_started_);
+  DCHECK(!drivefs_has_terminated_);
+  DCHECK(is_mounted_);
+  bool was_mounted = is_mounted_;
+  drivefs_has_terminated_ = true;
+  is_mounted_ = false;
+  if (was_mounted) {
+    NotifyUnmounted(std::move(remount_delay));
+  }
+}
+
+void DriveFsSession::OnHeartbeat() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  if (timer_->IsRunning()) {
+    timer_->Reset();
+  }
+}
+
+}  // namespace drivefs
diff --git a/chromeos/components/drivefs/drivefs_session.h b/chromeos/components/drivefs/drivefs_session.h
new file mode 100644
index 0000000..6ca7081f
--- /dev/null
+++ b/chromeos/components/drivefs/drivefs_session.h
@@ -0,0 +1,120 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROMEOS_COMPONENTS_DRIVEFS_DRIVEFS_SESSION_H_
+#define CHROMEOS_COMPONENTS_DRIVEFS_DRIVEFS_SESSION_H_
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "base/component_export.h"
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "base/timer/timer.h"
+#include "base/unguessable_token.h"
+#include "chromeos/components/drivefs/mojom/drivefs.mojom.h"
+#include "chromeos/disks/disk_mount_manager.h"
+
+namespace drivefs {
+
+// Utility class to simplify mounting with DiskMountManager.
+class COMPONENT_EXPORT(DRIVEFS) DiskMounter {
+ public:
+  DiskMounter() = default;
+  virtual ~DiskMounter() = default;
+  virtual void Mount(const base::UnguessableToken& token,
+                     const base::FilePath& data_path,
+                     const std::string& desired_mount_dir_name,
+                     base::OnceCallback<void(base::FilePath)> callback) = 0;
+
+  static std::unique_ptr<DiskMounter> Create(
+      chromeos::disks::DiskMountManager* disk_mount_manager);
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(DiskMounter);
+};
+
+class DriveFsConnection;
+
+// Represents single Drive mount session. Hides the complexity
+// of determining whether DriveFs is mounted or not.
+class COMPONENT_EXPORT(DRIVEFS) DriveFsSession : public mojom::DriveFsDelegate {
+ public:
+  class MountObserver {
+   public:
+    enum class MountFailure {
+      kUnknown,
+      kNeedsRestart,
+      kIpcDisconnect,
+      kInvocation,
+      kTimeout,
+    };
+
+    MountObserver() = default;
+    virtual ~MountObserver() = default;
+    virtual void OnMounted(const base::FilePath& mount_path) = 0;
+    virtual void OnUnmounted(base::Optional<base::TimeDelta> remount_delay) = 0;
+    virtual void OnMountFailed(
+        MountFailure failure,
+        base::Optional<base::TimeDelta> remount_delay) = 0;
+
+   private:
+    DISALLOW_COPY_AND_ASSIGN(MountObserver);
+  };
+
+  DriveFsSession(base::OneShotTimer* timer,
+                 std::unique_ptr<DiskMounter> disk_mounter,
+                 std::unique_ptr<DriveFsConnection> connection,
+                 const base::FilePath& data_path,
+                 const std::string& desired_mount_dir_name,
+                 MountObserver* observer);
+  ~DriveFsSession() override;
+
+  // Returns whether DriveFS is mounted.
+  bool is_mounted() const { return is_mounted_; }
+
+  // Returns the path where DriveFS is mounted.
+  const base::FilePath& mount_path() const { return mount_path_; }
+
+  mojom::DriveFs* drivefs_interface() { return drivefs_; }
+
+ private:
+  // mojom::DriveFsDelegate:
+  void OnMounted() final;
+  void OnMountFailed(base::Optional<base::TimeDelta> remount_delay) final;
+  void OnUnmounted(base::Optional<base::TimeDelta> remount_delay) final;
+  void OnHeartbeat() final;
+
+  void OnDiskMountCompleted(base::FilePath mount_path);
+  void OnMojoConnectionError();
+  void OnMountTimedOut();
+  void MaybeNotifyOnMounted();
+  void NotifyFailed(MountObserver::MountFailure failure,
+                    base::Optional<base::TimeDelta> remount_delay);
+  void NotifyUnmounted(base::Optional<base::TimeDelta> remount_delay);
+
+  SEQUENCE_CHECKER(sequence_checker_);
+
+  base::OneShotTimer* const timer_;
+  std::unique_ptr<DiskMounter> disk_mounter_;
+  std::unique_ptr<DriveFsConnection> connection_;
+  MountObserver* const observer_;
+
+  // The path where DriveFS is mounted.
+  base::FilePath mount_path_;
+
+  // Mojo interface to the DriveFS process.
+  mojom::DriveFs* drivefs_ = nullptr;
+
+  bool drivefs_has_started_ = false;
+  bool drivefs_has_terminated_ = false;
+  bool is_mounted_ = false;
+
+  DISALLOW_COPY_AND_ASSIGN(DriveFsSession);
+};
+
+}  // namespace drivefs
+
+#endif  // CHROMEOS_COMPONENTS_DRIVEFS_DRIVEFS_SESSION_H_
diff --git a/chromeos/components/drivefs/drivefs_session_unittest.cc b/chromeos/components/drivefs/drivefs_session_unittest.cc
new file mode 100644
index 0000000..c69d32aa
--- /dev/null
+++ b/chromeos/components/drivefs/drivefs_session_unittest.cc
@@ -0,0 +1,486 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chromeos/components/drivefs/drivefs_session.h"
+
+#include <utility>
+
+#include "base/run_loop.h"
+#include "base/strings/strcat.h"
+#include "base/test/bind_test_util.h"
+#include "base/test/scoped_task_environment.h"
+#include "base/test/simple_test_clock.h"
+#include "base/timer/mock_timer.h"
+#include "chromeos/components/drivefs/fake_drivefs.h"
+#include "chromeos/components/drivefs/mojom/drivefs.mojom-test-utils.h"
+#include "chromeos/disks/mock_disk_mount_manager.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace drivefs {
+namespace {
+
+constexpr char kExpectedMountDir[] = "drivefs-salt-g-ID";
+constexpr char kExpectedMountPath[] = "/media/drivefsroot/mountdir";
+constexpr char kExpectedDataDir[] = "/path/to/profile/GCache/v2/salt-g-ID";
+
+static const base::Optional<base::TimeDelta> kEmptyDelay;
+static const base::Optional<base::TimeDelta> kDefaultDelay =
+    base::TimeDelta::FromSeconds(5);
+
+using testing::_;
+using testing::Invoke;
+using testing::InvokeWithoutArgs;
+using MountFailure = DriveFsSession::MountObserver::MountFailure;
+
+class DriveFsDiskMounterTest : public testing::Test {
+ protected:
+  std::string StartMount(DiskMounter* mounter) {
+    auto token = base::UnguessableToken::Create();
+    std::string source;
+    EXPECT_CALL(
+        disk_manager_,
+        MountPath(
+            testing::StartsWith("drivefs://"), "", kExpectedMountDir,
+            testing::Contains("datadir=/path/to/profile/GCache/v2/salt-g-ID"),
+            _, chromeos::MOUNT_ACCESS_MODE_READ_WRITE))
+        .WillOnce(testing::SaveArg<0>(&source));
+
+    mounter->Mount(token, base::FilePath(kExpectedDataDir), kExpectedMountDir,
+                   base::BindOnce(&DriveFsDiskMounterTest::OnCompleted,
+                                  base::Unretained(this)));
+    testing::Mock::VerifyAndClear(&disk_manager_);
+    return source.substr(strlen("drivefs://"));
+  }
+
+  void DispatchMountEvent(
+      chromeos::disks::DiskMountManager::MountEvent event,
+      chromeos::MountError error_code,
+      const chromeos::disks::DiskMountManager::MountPointInfo& mount_info) {
+    disk_manager_.NotifyMountEvent(event, error_code, mount_info);
+  }
+
+  MOCK_METHOD1(OnCompleted, void(base::FilePath));
+  chromeos::disks::MockDiskMountManager disk_manager_;
+};
+
+TEST_F(DriveFsDiskMounterTest, MountUnmount) {
+  auto mounter = DiskMounter::Create(&disk_manager_);
+  auto token = StartMount(mounter.get());
+  EXPECT_CALL(*this, OnCompleted(base::FilePath(kExpectedMountPath)));
+  DispatchMountEvent(chromeos::disks::DiskMountManager::MOUNTING,
+                     chromeos::MOUNT_ERROR_NONE,
+                     {base::StrCat({"drivefs://", token}),
+                      kExpectedMountPath,
+                      chromeos::MOUNT_TYPE_NETWORK_STORAGE,
+                      {}});
+  EXPECT_CALL(disk_manager_, UnmountPath(kExpectedMountPath,
+                                         chromeos::UNMOUNT_OPTIONS_NONE, _));
+  mounter.reset();
+}
+
+TEST_F(DriveFsDiskMounterTest, DestroyAfterMounted) {
+  auto mounter = DiskMounter::Create(&disk_manager_);
+  auto token = StartMount(mounter.get());
+  EXPECT_CALL(*this, OnCompleted(base::FilePath(kExpectedMountPath)));
+  DispatchMountEvent(chromeos::disks::DiskMountManager::MOUNTING,
+                     chromeos::MOUNT_ERROR_NONE,
+                     {base::StrCat({"drivefs://", token}),
+                      kExpectedMountPath,
+                      chromeos::MOUNT_TYPE_NETWORK_STORAGE,
+                      {}});
+  EXPECT_CALL(disk_manager_, UnmountPath(kExpectedMountPath,
+                                         chromeos::UNMOUNT_OPTIONS_NONE, _));
+}
+
+TEST_F(DriveFsDiskMounterTest, DestroyBeforeMounted) {
+  EXPECT_CALL(disk_manager_, UnmountPath(_, _, _)).Times(0);
+  auto mounter = DiskMounter::Create(&disk_manager_);
+  StartMount(mounter.get());
+}
+
+TEST_F(DriveFsDiskMounterTest, ObserveOtherEvents) {
+  EXPECT_CALL(*this, OnCompleted(_)).Times(0);
+  EXPECT_CALL(disk_manager_, UnmountPath(_, _, _)).Times(0);
+
+  auto mounter = DiskMounter::Create(&disk_manager_);
+  auto token = StartMount(mounter.get());
+
+  DispatchMountEvent(chromeos::disks::DiskMountManager::MOUNTING,
+                     chromeos::MOUNT_ERROR_DIRECTORY_CREATION_FAILED,
+                     {"some/other/mount/event",
+                      "/some/other/mount/point",
+                      chromeos::MOUNT_TYPE_DEVICE,
+                      {}});
+  DispatchMountEvent(chromeos::disks::DiskMountManager::UNMOUNTING,
+                     chromeos::MOUNT_ERROR_NONE,
+                     {base::StrCat({"drivefs://", token}),
+                      kExpectedMountPath,
+                      chromeos::MOUNT_TYPE_NETWORK_STORAGE,
+                      {}});
+}
+
+TEST_F(DriveFsDiskMounterTest, MountError) {
+  EXPECT_CALL(disk_manager_, UnmountPath(_, _, _)).Times(0);
+
+  auto mounter = DiskMounter::Create(&disk_manager_);
+  auto token = StartMount(mounter.get());
+  EXPECT_CALL(*this, OnCompleted(base::FilePath()));
+  DispatchMountEvent(chromeos::disks::DiskMountManager::MOUNTING,
+                     chromeos::MOUNT_ERROR_INVALID_MOUNT_OPTIONS,
+                     {base::StrCat({"drivefs://", token}),
+                      kExpectedMountPath,
+                      chromeos::MOUNT_TYPE_NETWORK_STORAGE,
+                      {}});
+}
+
+// DiskMountManager sometimes sends mount events for all existing mount points.
+// Mount events beyond the first should be ignored.
+TEST_F(DriveFsDiskMounterTest, MultipleMountNotifications) {
+  auto mounter = DiskMounter::Create(&disk_manager_);
+  auto token = StartMount(mounter.get());
+  EXPECT_CALL(*this, OnCompleted(base::FilePath(kExpectedMountPath))).Times(1);
+  DispatchMountEvent(chromeos::disks::DiskMountManager::MOUNTING,
+                     chromeos::MOUNT_ERROR_NONE,
+                     {base::StrCat({"drivefs://", token}),
+                      kExpectedMountPath,
+                      chromeos::MOUNT_TYPE_NETWORK_STORAGE,
+                      {}});
+  DispatchMountEvent(chromeos::disks::DiskMountManager::MOUNTING,
+                     chromeos::MOUNT_ERROR_NONE,
+                     {base::StrCat({"drivefs://", token}),
+                      kExpectedMountPath,
+                      chromeos::MOUNT_TYPE_NETWORK_STORAGE,
+                      {}});
+  DispatchMountEvent(chromeos::disks::DiskMountManager::MOUNTING,
+                     chromeos::MOUNT_ERROR_NONE,
+                     {base::StrCat({"drivefs://", token}),
+                      kExpectedMountPath,
+                      chromeos::MOUNT_TYPE_NETWORK_STORAGE,
+                      {}});
+}
+
+class MockDiskMounter : public DiskMounter {
+ public:
+  MockDiskMounter() { ++gInstanceCounter; }
+  ~MockDiskMounter() override { --gInstanceCounter; }
+
+  void Mount(const base::UnguessableToken& token,
+             const base::FilePath& data_path,
+             const std::string& desired_mount_dir_name,
+             base::OnceCallback<void(base::FilePath)> callback) override {
+    callback_ = std::move(callback);
+    OnMountCalled(token, data_path, desired_mount_dir_name);
+  }
+
+  MOCK_METHOD3(OnMountCalled,
+               void(const base::UnguessableToken& token,
+                    const base::FilePath& data_path,
+                    const std::string& desired_mount_dir_name));
+
+  void CompleteMount(const base::FilePath& mount_path) {
+    CHECK(callback_);
+    std::move(callback_).Run(mount_path);
+  }
+
+  static void AssertNotMounted() { ASSERT_EQ(0, gInstanceCounter); }
+
+ private:
+  static int gInstanceCounter;
+  base::OnceCallback<void(base::FilePath)> callback_;
+  DISALLOW_COPY_AND_ASSIGN(MockDiskMounter);
+};
+
+int MockDiskMounter::gInstanceCounter = 0;
+
+class MockDriveFsConnection : public DriveFsConnection,
+                              public mojom::DriveFsInterceptorForTesting {
+ public:
+  MockDriveFsConnection() = default;
+  ~MockDriveFsConnection() override = default;
+
+  base::UnguessableToken Connect(mojom::DriveFsDelegate* delegate,
+                                 base::OnceClosure on_disconnected) override {
+    CHECK(!delegate_);
+    on_disconnected_ = std::move(on_disconnected);
+    delegate_ = delegate;
+    OnConnected(delegate);
+    return base::UnguessableToken::Create();
+  }
+
+  mojom::DriveFs& GetDriveFs() override { return *this; }
+
+  MOCK_METHOD1(OnConnected, void(mojom::DriveFsDelegate* delegate));
+
+  void ForceDisconnect() {
+    if (on_disconnected_) {
+      std::move(on_disconnected_).Run();
+    }
+  }
+
+ private:
+  mojom::DriveFs* GetForwardingInterface() override {
+    NOTREACHED();
+    return nullptr;
+  }
+
+  mojom::DriveFsDelegate* delegate_ = nullptr;
+  base::OnceClosure on_disconnected_;
+
+  DISALLOW_COPY_AND_ASSIGN(MockDriveFsConnection);
+};
+
+class DriveFsSessionForTest : public DriveFsSession {
+ public:
+  DriveFsSessionForTest(base::OneShotTimer* timer,
+                        std::unique_ptr<DiskMounter> disk_mounter,
+                        std::unique_ptr<DriveFsConnection> connection,
+                        const base::FilePath& data_path,
+                        const std::string& desired_mount_dir_name,
+                        MountObserver* observer)
+      : DriveFsSession(timer,
+                       std::move(disk_mounter),
+                       std::move(connection),
+                       data_path,
+                       desired_mount_dir_name,
+                       observer) {}
+  ~DriveFsSessionForTest() override = default;
+
+ private:
+  void GetAccessToken(const std::string& client_id,
+                      const std::string& app_id,
+                      const std::vector<std::string>& scopes,
+                      GetAccessTokenCallback callback) override {}
+  void OnSyncingStatusUpdate(mojom::SyncingStatusPtr status) override {}
+  void OnFilesChanged(std::vector<mojom::FileChangePtr> changes) override {}
+  void OnError(mojom::DriveErrorPtr error) override {}
+  void OnTeamDrivesListReady(
+      const std::vector<std::string>& team_drive_ids) override {}
+  void OnTeamDriveChanged(
+      const std::string& team_drive_id,
+      mojom::DriveFsDelegate::CreateOrDelete change_type) override {}
+  DISALLOW_COPY_AND_ASSIGN(DriveFsSessionForTest);
+};
+
+class DriveFsSessionTest : public ::testing::Test,
+                           public DriveFsSession::MountObserver {
+ public:
+  DriveFsSessionTest() {}
+
+ protected:
+  MOCK_METHOD1(OnMounted, void(const base::FilePath& path));
+  MOCK_METHOD1(OnUnmounted, void(base::Optional<base::TimeDelta> delay));
+  MOCK_METHOD2(OnMountFailed,
+               void(MountFailure failure,
+                    base::Optional<base::TimeDelta> delay));
+
+  void StartMounting() {
+    DCHECK(!holder_);
+    DCHECK(!session_);
+    auto mounter = std::make_unique<MockDiskMounter>();
+    auto connection = std::make_unique<MockDriveFsConnection>();
+    holder_ = std::make_unique<PointerHolder>();
+    holder_->mounter = mounter.get();
+    holder_->connection = connection.get();
+
+    base::FilePath data_path(kExpectedDataDir);
+
+    EXPECT_CALL(*holder_->connection, OnConnected(_));
+    EXPECT_CALL(*holder_->mounter,
+                OnMountCalled(_, data_path, kExpectedMountDir));
+    session_ = std::make_unique<DriveFsSessionForTest>(
+        &timer_, std::move(mounter), std::move(connection), data_path,
+        kExpectedMountDir, this);
+    holder_->delegate = session_.get();
+    ASSERT_FALSE(session_->is_mounted());
+  }
+
+  void CompleteDiskMount() {
+    holder_->mounter->CompleteMount(base::FilePath(kExpectedMountPath));
+  }
+
+  void ConfirmDriveFsMounted() { holder_->delegate->OnMounted(); }
+
+  void FinishMounting() {
+    CompleteDiskMount();
+    ASSERT_FALSE(session_->is_mounted());
+    EXPECT_CALL(*this, OnMounted(base::FilePath(kExpectedMountPath)));
+    ConfirmDriveFsMounted();
+    ASSERT_TRUE(session_->is_mounted());
+  }
+
+  void DoUnmount() {
+    session_.reset();
+    MockDiskMounter::AssertNotMounted();
+    holder_.reset();
+  }
+
+  base::test::ScopedTaskEnvironment task_environment_;
+
+  struct PointerHolder {
+    MockDiskMounter* mounter = nullptr;
+    MockDriveFsConnection* connection = nullptr;
+    mojom::DriveFsDelegate* delegate = nullptr;
+  };
+  base::MockOneShotTimer timer_;
+  std::unique_ptr<PointerHolder> holder_;
+  std::unique_ptr<DriveFsSession> session_;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(DriveFsSessionTest);
+};
+
+}  // namespace
+
+TEST_F(DriveFsSessionTest, OnMounted_DisksThenDriveFs) {
+  EXPECT_CALL(*this, OnMountFailed(_, _)).Times(0);
+  EXPECT_CALL(*this, OnUnmounted(_)).Times(0);
+  ASSERT_NO_FATAL_FAILURE(StartMounting());
+
+  CompleteDiskMount();
+  ASSERT_FALSE(session_->is_mounted());
+  EXPECT_CALL(*this, OnMounted(base::FilePath(kExpectedMountPath)));
+  ConfirmDriveFsMounted();
+  ASSERT_TRUE(session_->is_mounted());
+
+  EXPECT_EQ(base::FilePath(kExpectedMountPath), session_->mount_path());
+  ASSERT_NO_FATAL_FAILURE(DoUnmount());
+}
+
+TEST_F(DriveFsSessionTest, OnMounted_DriveFsThenDisks) {
+  EXPECT_CALL(*this, OnMountFailed(_, _)).Times(0);
+  EXPECT_CALL(*this, OnUnmounted(_)).Times(0);
+  ASSERT_NO_FATAL_FAILURE(StartMounting());
+
+  ConfirmDriveFsMounted();
+  ASSERT_FALSE(session_->is_mounted());
+  EXPECT_CALL(*this, OnMounted(base::FilePath(kExpectedMountPath)));
+  CompleteDiskMount();
+  ASSERT_TRUE(session_->is_mounted());
+
+  EXPECT_EQ(base::FilePath(kExpectedMountPath), session_->mount_path());
+  ASSERT_NO_FATAL_FAILURE(DoUnmount());
+}
+
+TEST_F(DriveFsSessionTest, OnMountFailed_InDriveFs) {
+  EXPECT_CALL(*this, OnMounted(_)).Times(0);
+  EXPECT_CALL(*this, OnUnmounted(_)).Times(0);
+
+  ASSERT_NO_FATAL_FAILURE(StartMounting());
+  CompleteDiskMount();
+
+  EXPECT_CALL(*this, OnMountFailed(MountFailure::kUnknown, kEmptyDelay));
+  holder_->delegate->OnMountFailed(kEmptyDelay);
+  ASSERT_FALSE(session_->is_mounted());
+}
+
+TEST_F(DriveFsSessionTest, OnMountFailed_InDisks) {
+  EXPECT_CALL(*this, OnMounted(_)).Times(0);
+  EXPECT_CALL(*this, OnUnmounted(_)).Times(0);
+
+  ASSERT_NO_FATAL_FAILURE(StartMounting());
+
+  EXPECT_CALL(*this, OnMountFailed(MountFailure::kInvocation, kEmptyDelay));
+  holder_->mounter->CompleteMount({});
+  ASSERT_FALSE(session_->is_mounted());
+}
+
+TEST_F(DriveFsSessionTest, OnMountFailed_DriveFsNeedsRestart) {
+  EXPECT_CALL(*this, OnMounted(_)).Times(0);
+  EXPECT_CALL(*this, OnUnmounted(_)).Times(0);
+
+  ASSERT_NO_FATAL_FAILURE(StartMounting());
+  CompleteDiskMount();
+
+  EXPECT_CALL(*this, OnMountFailed(MountFailure::kNeedsRestart, kDefaultDelay));
+  holder_->delegate->OnMountFailed(kDefaultDelay);
+  ASSERT_FALSE(session_->is_mounted());
+}
+
+TEST_F(DriveFsSessionTest, OnMountFailed_UnmountInObserver) {
+  EXPECT_CALL(*this, OnMounted(_)).Times(0);
+  EXPECT_CALL(*this, OnUnmounted(_)).Times(0);
+
+  ASSERT_NO_FATAL_FAILURE(StartMounting());
+  EXPECT_CALL(*this, OnMountFailed(MountFailure::kInvocation, kEmptyDelay))
+      .WillOnce(testing::InvokeWithoutArgs([&]() { session_.reset(); }));
+  holder_->mounter->CompleteMount({});
+  ASSERT_FALSE(session_);
+}
+
+TEST_F(DriveFsSessionTest, DestroyBeforeMojoConnection) {
+  EXPECT_CALL(*this, OnMounted(_)).Times(0);
+  EXPECT_CALL(*this, OnUnmounted(_)).Times(0);
+
+  ASSERT_NO_FATAL_FAILURE(StartMounting());
+  CompleteDiskMount();
+
+  session_.reset();
+}
+
+TEST_F(DriveFsSessionTest, DestroyBeforeMountEvent) {
+  EXPECT_CALL(*this, OnMounted(_)).Times(0);
+  EXPECT_CALL(*this, OnUnmounted(_)).Times(0);
+
+  ASSERT_NO_FATAL_FAILURE(StartMounting());
+  ConfirmDriveFsMounted();
+
+  session_.reset();
+}
+
+TEST_F(DriveFsSessionTest, UnmountByRemote) {
+  EXPECT_CALL(*this, OnMountFailed(_, _)).Times(0);
+
+  ASSERT_NO_FATAL_FAILURE(StartMounting());
+  ASSERT_NO_FATAL_FAILURE(FinishMounting());
+
+  EXPECT_CALL(*this, OnUnmounted(kDefaultDelay));
+  holder_->delegate->OnUnmounted(kDefaultDelay);
+}
+
+TEST_F(DriveFsSessionTest, BreakConnectionAfterMount) {
+  EXPECT_CALL(*this, OnMountFailed(_, _)).Times(0);
+
+  ASSERT_NO_FATAL_FAILURE(StartMounting());
+  ASSERT_NO_FATAL_FAILURE(FinishMounting());
+
+  EXPECT_CALL(*this, OnUnmounted(kEmptyDelay));
+  holder_->connection->ForceDisconnect();
+}
+
+TEST_F(DriveFsSessionTest, BreakConnectionBeforeMount) {
+  EXPECT_CALL(*this, OnMounted(_)).Times(0);
+  EXPECT_CALL(*this, OnUnmounted(_)).Times(0);
+
+  ASSERT_NO_FATAL_FAILURE(StartMounting());
+  CompleteDiskMount();
+
+  EXPECT_CALL(*this, OnMountFailed(MountFailure::kIpcDisconnect, kEmptyDelay));
+  holder_->connection->ForceDisconnect();
+}
+
+TEST_F(DriveFsSessionTest, BreakConnectionOnUnmount) {
+  EXPECT_CALL(*this, OnMountFailed(_, _)).Times(0);
+  ASSERT_NO_FATAL_FAILURE(StartMounting());
+  ASSERT_NO_FATAL_FAILURE(FinishMounting());
+
+  EXPECT_CALL(*this, OnUnmounted(kDefaultDelay))
+      .WillOnce(testing::InvokeWithoutArgs(
+          [&]() { holder_->connection->ForceDisconnect(); }));
+  holder_->delegate->OnUnmounted(kDefaultDelay);
+  ASSERT_NO_FATAL_FAILURE(DoUnmount());
+}
+
+TEST_F(DriveFsSessionTest, MountTimeout) {
+  EXPECT_CALL(*this, OnMounted(_)).Times(0);
+  EXPECT_CALL(*this, OnUnmounted(_)).Times(0);
+
+  ASSERT_NO_FATAL_FAILURE(StartMounting());
+  CompleteDiskMount();
+
+  EXPECT_CALL(*this, OnMountFailed(MountFailure::kTimeout, kEmptyDelay));
+  timer_.Fire();
+}
+
+}  // namespace drivefs
diff --git a/chromeos/dbus/cicerone_client.cc b/chromeos/dbus/cicerone_client.cc
index cff917be..15a12de76 100644
--- a/chromeos/dbus/cicerone_client.cc
+++ b/chromeos/dbus/cicerone_client.cc
@@ -62,6 +62,10 @@
     return is_lxd_container_created_signal_connected_;
   }
 
+  bool IsLxdContainerDeletedSignalConnected() override {
+    return is_lxd_container_deleted_signal_connected_;
+  }
+
   bool IsLxdContainerDownloadingSignalConnected() override {
     return is_lxd_container_downloading_signal_connected_;
   }
@@ -223,6 +227,28 @@
                        weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
   }
 
+  void DeleteLxdContainer(
+      const vm_tools::cicerone::DeleteLxdContainerRequest& request,
+      DBusMethodCallback<vm_tools::cicerone::DeleteLxdContainerResponse>
+          callback) override {
+    dbus::MethodCall method_call(vm_tools::cicerone::kVmCiceroneInterface,
+                                 vm_tools::cicerone::kDeleteLxdContainerMethod);
+    dbus::MessageWriter writer(&method_call);
+
+    if (!writer.AppendProtoAsArrayOfBytes(request)) {
+      LOG(ERROR) << "Failed to encode DeleteLxdContainerRequest protobuf";
+      base::ThreadTaskRunnerHandle::Get()->PostTask(
+          FROM_HERE, base::BindOnce(std::move(callback), base::nullopt));
+      return;
+    }
+
+    cicerone_proxy_->CallMethod(
+        &method_call, kDefaultTimeout.InMilliseconds(),
+        base::BindOnce(&CiceroneClientImpl::OnDBusProtoResponse<
+                           vm_tools::cicerone::DeleteLxdContainerResponse>,
+                       weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
+  }
+
   void StartLxdContainer(
       const vm_tools::cicerone::StartLxdContainerRequest& request,
       DBusMethodCallback<vm_tools::cicerone::StartLxdContainerResponse>
@@ -410,6 +436,13 @@
                        weak_ptr_factory_.GetWeakPtr()));
     cicerone_proxy_->ConnectToSignal(
         vm_tools::cicerone::kVmCiceroneInterface,
+        vm_tools::cicerone::kLxdContainerDeletedSignal,
+        base::BindRepeating(&CiceroneClientImpl::OnLxdContainerDeletedSignal,
+                            weak_ptr_factory_.GetWeakPtr()),
+        base::BindOnce(&CiceroneClientImpl::OnSignalConnected,
+                       weak_ptr_factory_.GetWeakPtr()));
+    cicerone_proxy_->ConnectToSignal(
+        vm_tools::cicerone::kVmCiceroneInterface,
         vm_tools::cicerone::kLxdContainerDownloadingSignal,
         base::BindRepeating(
             &CiceroneClientImpl::OnLxdContainerDownloadingSignal,
@@ -526,6 +559,18 @@
     }
   }
 
+  void OnLxdContainerDeletedSignal(dbus::Signal* signal) {
+    vm_tools::cicerone::LxdContainerDeletedSignal proto;
+    dbus::MessageReader reader(signal);
+    if (!reader.PopArrayOfBytesAsProto(&proto)) {
+      LOG(ERROR) << "Failed to parse proto from DBus Signal";
+      return;
+    }
+    for (auto& observer : observer_list_) {
+      observer.OnLxdContainerDeleted(proto);
+    }
+  }
+
   void OnLxdContainerDownloadingSignal(dbus::Signal* signal) {
     vm_tools::cicerone::LxdContainerDownloadingSignal proto;
     dbus::MessageReader reader(signal);
@@ -606,6 +651,8 @@
       is_uninstall_package_progress_signal_connected_ = is_connected;
     } else if (signal_name == vm_tools::cicerone::kLxdContainerCreatedSignal) {
       is_lxd_container_created_signal_connected_ = is_connected;
+    } else if (signal_name == vm_tools::cicerone::kLxdContainerDeletedSignal) {
+      is_lxd_container_deleted_signal_connected_ = is_connected;
     } else if (signal_name ==
                vm_tools::cicerone::kLxdContainerDownloadingSignal) {
       is_lxd_container_downloading_signal_connected_ = is_connected;
@@ -633,6 +680,7 @@
   bool is_install_linux_package_progress_signal_connected_ = false;
   bool is_uninstall_package_progress_signal_connected_ = false;
   bool is_lxd_container_created_signal_connected_ = false;
+  bool is_lxd_container_deleted_signal_connected_ = false;
   bool is_lxd_container_downloading_signal_connected_ = false;
   bool is_tremplin_started_signal_connected_ = false;
   bool is_lxd_container_starting_signal_connected_ = false;
diff --git a/chromeos/dbus/cicerone_client.h b/chromeos/dbus/cicerone_client.h
index 7fd0721..19ee0e1 100644
--- a/chromeos/dbus/cicerone_client.h
+++ b/chromeos/dbus/cicerone_client.h
@@ -46,6 +46,11 @@
     virtual void OnLxdContainerCreated(
         const vm_tools::cicerone::LxdContainerCreatedSignal& signal) = 0;
 
+    // OnLxdContainerDeleted is signaled from Cicerone when the long running
+    // deletion of an Lxd container is complete.
+    virtual void OnLxdContainerDeleted(
+        const vm_tools::cicerone::LxdContainerDeletedSignal& signal) = 0;
+
     // OnLxdContainerDownloading is signaled from Cicerone giving download
     // progress on the container.
     virtual void OnLxdContainerDownloading(
@@ -103,6 +108,9 @@
   // StartLxdContainer.
   virtual bool IsLxdContainerCreatedSignalConnected() = 0;
 
+  // This should be true prior to calling DeleteLxdContainer.
+  virtual bool IsLxdContainerDeletedSignalConnected() = 0;
+
   // This should be true prior to calling CreateLxdContainer or
   // StartLxdContainer.
   virtual bool IsLxdContainerDownloadingSignalConnected() = 0;
@@ -164,6 +172,14 @@
       DBusMethodCallback<vm_tools::cicerone::CreateLxdContainerResponse>
           callback) = 0;
 
+  // Deletes an Lxd Container.
+  // |callback| is called to indicate deletion status.
+  // |Observer::OnLxdContainerDeleted| will be called on completion.
+  virtual void DeleteLxdContainer(
+      const vm_tools::cicerone::DeleteLxdContainerRequest& request,
+      DBusMethodCallback<vm_tools::cicerone::DeleteLxdContainerResponse>
+          callback) = 0;
+
   // Starts a new Lxd Container.
   // |callback| is called when the method completes.
   virtual void StartLxdContainer(
diff --git a/chromeos/dbus/fake_cicerone_client.cc b/chromeos/dbus/fake_cicerone_client.cc
index 7e8dc9c..98939d7 100644
--- a/chromeos/dbus/fake_cicerone_client.cc
+++ b/chromeos/dbus/fake_cicerone_client.cc
@@ -66,6 +66,10 @@
   return is_lxd_container_created_signal_connected_;
 }
 
+bool FakeCiceroneClient::IsLxdContainerDeletedSignalConnected() {
+  return is_lxd_container_deleted_signal_connected_;
+}
+
 bool FakeCiceroneClient::IsLxdContainerDownloadingSignalConnected() {
   return is_lxd_container_downloading_signal_connected_;
 }
@@ -173,6 +177,15 @@
                                 base::Unretained(this), std::move(signal)));
 }
 
+void FakeCiceroneClient::DeleteLxdContainer(
+    const vm_tools::cicerone::DeleteLxdContainerRequest& request,
+    DBusMethodCallback<vm_tools::cicerone::DeleteLxdContainerResponse>
+        callback) {
+  base::ThreadTaskRunnerHandle::Get()->PostTask(
+      FROM_HERE,
+      base::BindOnce(std::move(callback), delete_lxd_container_response_));
+}
+
 void FakeCiceroneClient::StartLxdContainer(
     const vm_tools::cicerone::StartLxdContainerRequest& request,
     DBusMethodCallback<vm_tools::cicerone::StartLxdContainerResponse>
diff --git a/chromeos/dbus/fake_cicerone_client.h b/chromeos/dbus/fake_cicerone_client.h
index 2b6cc20..f7b2140 100644
--- a/chromeos/dbus/fake_cicerone_client.h
+++ b/chromeos/dbus/fake_cicerone_client.h
@@ -44,6 +44,9 @@
   // StartLxdContainer.
   bool IsLxdContainerCreatedSignalConnected() override;
 
+  // This should be true prior to calling DeleteLxdContainer.
+  bool IsLxdContainerDeletedSignalConnected() override;
+
   // This should be true prior to calling CreateLxdContainer or
   // StartLxdContainer.
   bool IsLxdContainerDownloadingSignalConnected() override;
@@ -111,6 +114,11 @@
       DBusMethodCallback<vm_tools::cicerone::CreateLxdContainerResponse>
           callback) override;
 
+  void DeleteLxdContainer(
+      const vm_tools::cicerone::DeleteLxdContainerRequest& request,
+      DBusMethodCallback<vm_tools::cicerone::DeleteLxdContainerResponse>
+          callback) override;
+
   // Fake version of the method that starts a new Container.
   // |callback| is called when the method completes.
   void StartLxdContainer(
@@ -188,6 +196,17 @@
     lxd_container_created_signal_status_ = status;
   }
 
+  // Set LxdContainerDeletedSignalConnected state
+  void set_lxd_container_deleted_signal_connected(bool connected) {
+    is_lxd_container_deleted_signal_connected_ = connected;
+  }
+
+  // Set LxdContainerDeletedSignalConnected response status
+  void set_lxd_container_deleted_signal_status(
+      vm_tools::cicerone::LxdContainerDeletedSignal_Status status) {
+    lxd_container_deleted_signal_status_ = status;
+  }
+
   // Set LxdContainerDownloadingSignalConnected state
   void set_lxd_container_downloading_signal_connected(bool connected) {
     is_lxd_container_downloading_signal_connected_ = connected;
@@ -261,6 +280,12 @@
     create_lxd_container_response_ = create_lxd_container_response;
   }
 
+  void set_delete_lxd_container_response_(
+      const vm_tools::cicerone::DeleteLxdContainerResponse&
+          delete_lxd_container_response) {
+    delete_lxd_container_response_ = delete_lxd_container_response;
+  }
+
   void set_start_lxd_container_response(
       const vm_tools::cicerone::StartLxdContainerResponse&
           start_lxd_container_response) {
@@ -294,6 +319,8 @@
   // Additional functions to allow tests to trigger Signals.
   void NotifyLxdContainerCreated(
       const vm_tools::cicerone::LxdContainerCreatedSignal& signal);
+  void NotifyLxdContainerDeleted(
+      const vm_tools::cicerone::LxdContainerDeletedSignal& signal);
   void NotifyContainerStarted(
       const vm_tools::cicerone::ContainerStartedSignal& signal);
   void NotifyTremplinStarted(
@@ -318,6 +345,7 @@
   bool is_install_linux_package_progress_signal_connected_ = true;
   bool is_uninstall_package_progress_signal_connected_ = true;
   bool is_lxd_container_created_signal_connected_ = true;
+  bool is_lxd_container_deleted_signal_connected_ = true;
   bool is_lxd_container_downloading_signal_connected_ = true;
   bool is_tremplin_started_signal_connected_ = true;
   bool is_lxd_container_starting_signal_connected_ = true;
@@ -327,6 +355,9 @@
   vm_tools::cicerone::LxdContainerCreatedSignal_Status
       lxd_container_created_signal_status_ =
           vm_tools::cicerone::LxdContainerCreatedSignal::CREATED;
+  vm_tools::cicerone::LxdContainerDeletedSignal_Status
+      lxd_container_deleted_signal_status_ =
+          vm_tools::cicerone::LxdContainerDeletedSignal::DELETED;
   vm_tools::cicerone::LxdContainerStartingSignal_Status
       lxd_container_starting_signal_status_ =
           vm_tools::cicerone::LxdContainerStartingSignal::STARTED;
@@ -344,6 +375,7 @@
   vm_tools::cicerone::UninstallPackageOwningFileResponse
       uninstall_package_owning_file_response_;
   vm_tools::cicerone::CreateLxdContainerResponse create_lxd_container_response_;
+  vm_tools::cicerone::DeleteLxdContainerResponse delete_lxd_container_response_;
   vm_tools::cicerone::StartLxdContainerResponse start_lxd_container_response_;
   vm_tools::cicerone::GetLxdContainerUsernameResponse
       get_lxd_container_username_response_;
diff --git a/components/cronet/native/test_instructions.md b/components/cronet/native/test_instructions.md
index 28918de77..5654983 100644
--- a/components/cronet/native/test_instructions.md
+++ b/components/cronet/native/test_instructions.md
@@ -41,5 +41,5 @@
 You can use the -b flag to test against just one of those, like this:
 
 ```shell
-$ git cl try -b linux_chromium_rel_ng
+$ git cl try -b linux-rel
 ```
diff --git a/components/download/internal/background_service/config.cc b/components/download/internal/background_service/config.cc
index 800185c..f876e62 100644
--- a/components/download/internal/background_service/config.cc
+++ b/components/download/internal/background_service/config.cc
@@ -60,6 +60,11 @@
 
 // Default value for start up delay to wait for network stack ready.
 const base::TimeDelta kDefaultNetworkStartupDelay =
+    base::TimeDelta::FromSeconds(25);
+
+// Default value for start up delay to wait for network stack ready when
+// triggered from a background task.
+const base::TimeDelta kDefaultNetworkStartupDelayBackgroundTask =
     base::TimeDelta::FromSeconds(5);
 
 // The default delay to notify the observer when network changes from
@@ -137,6 +142,12 @@
       base::TimeDelta::FromMilliseconds(base::saturated_cast<int>(
           GetFinchConfigUInt(kNetworkStartupDelayMsConfig,
                              kDefaultNetworkStartupDelay.InMilliseconds())));
+  config->network_startup_delay_backgroud_task =
+      base::TimeDelta::FromMilliseconds(
+          base::saturated_cast<int>(GetFinchConfigUInt(
+              kNetworkStartupDelayBackgroundTaskMsConfig,
+              kDefaultNetworkStartupDelayBackgroundTask.InMilliseconds())));
+
   config->network_change_delay =
       base::TimeDelta::FromMilliseconds(base::saturated_cast<int>(
           GetFinchConfigUInt(kNetworkChangeDelayMsConfig,
diff --git a/components/download/internal/background_service/config.h b/components/download/internal/background_service/config.h
index 26af2e0..47a1e1b 100644
--- a/components/download/internal/background_service/config.h
+++ b/components/download/internal/background_service/config.h
@@ -54,6 +54,11 @@
 // Configuration name for start up delay, measured in milliseconds.
 constexpr char kNetworkStartupDelayMsConfig[] = "start_up_delay_ms";
 
+// Configuration name for start up delay when triggered from a background task,
+// measured in milliseconds.
+constexpr char kNetworkStartupDelayBackgroundTaskMsConfig[] =
+    "start_up_delay_background_task_ms";
+
 // Configuration name for the delay to notify network status change, measured in
 // milliseconds.
 constexpr char kNetworkChangeDelayMsConfig[] = "network_change_delay_ms";
@@ -139,6 +144,10 @@
   // ready.
   base::TimeDelta network_startup_delay;
 
+  // The delay to initialize internal components to wait for network stack
+  // ready when triggered from a background task.
+  base::TimeDelta network_startup_delay_backgroud_task;
+
   // The delay to notify network status changes.
   base::TimeDelta network_change_delay;
 
diff --git a/components/download/internal/background_service/controller_impl.cc b/components/download/internal/background_service/controller_impl.cc
index eae2dc6..18de3f0 100644
--- a/components/download/internal/background_service/controller_impl.cc
+++ b/components/download/internal/background_service/controller_impl.cc
@@ -305,6 +305,7 @@
 
 void ControllerImpl::OnStartScheduledTask(DownloadTaskType task_type,
                                           TaskFinishedCallback callback) {
+  device_status_listener_->Start(config_->network_startup_delay_backgroud_task);
   task_finished_callbacks_[task_type] = std::move(callback);
 
   switch (controller_state_) {
@@ -678,7 +679,8 @@
     return;
   }
 
-  device_status_listener_->Start(this);
+  device_status_listener_->SetObserver(this);
+  device_status_listener_->Start(config_->network_startup_delay);
   PollActiveDriverDownloads();
   CancelOrphanedRequests();
   CleanupUnknownFiles();
diff --git a/components/download/internal/background_service/scheduler/device_status_listener.cc b/components/download/internal/background_service/scheduler/device_status_listener.cc
index 9e9380e0..76f11e5d 100644
--- a/components/download/internal/background_service/scheduler/device_status_listener.cc
+++ b/components/download/internal/background_service/scheduler/device_status_listener.cc
@@ -45,7 +45,6 @@
       observer_(nullptr),
       listening_(false),
       is_valid_state_(false),
-      startup_delay_(startup_delay),
       online_delay_(online_delay),
       battery_listener_(std::move(battery_listener)) {}
 
@@ -59,21 +58,27 @@
   return status_;
 }
 
-void DeviceStatusListener::Start(DeviceStatusListener::Observer* observer) {
-  if (listening_)
-    return;
-
+void DeviceStatusListener::SetObserver(
+    DeviceStatusListener::Observer* observer) {
   DCHECK(observer);
   observer_ = observer;
+}
+
+void DeviceStatusListener::Start(const base::TimeDelta& start_delay) {
+  if (listening_ || !observer_)
+    return;
 
   // Network stack may shake off all connections after getting the IP address,
   // use a delay to wait for potential network setup.
-  timer_.Start(FROM_HERE, startup_delay_,
+  timer_.Start(FROM_HERE, start_delay,
                base::BindOnce(&DeviceStatusListener::StartAfterDelay,
                               base::Unretained(this)));
 }
 
 void DeviceStatusListener::StartAfterDelay() {
+  if (listening_ || !observer_)
+    return;
+
   // Listen to battery status changes.
   DCHECK(battery_listener_);
   battery_listener_->Start(this);
diff --git a/components/download/internal/background_service/scheduler/device_status_listener.h b/components/download/internal/background_service/scheduler/device_status_listener.h
index 54dc4c45c..be56b71 100644
--- a/components/download/internal/background_service/scheduler/device_status_listener.h
+++ b/components/download/internal/background_service/scheduler/device_status_listener.h
@@ -38,9 +38,12 @@
   // internal device status when called.
   const DeviceStatus& CurrentDeviceStatus();
 
+  void SetObserver(DeviceStatusListener::Observer* observer);
+
   // Starts/stops to listen network and battery change events, virtual for
   // testing.
-  virtual void Start(DeviceStatusListener::Observer* observer);
+  virtual void Start(const base::TimeDelta& start_delay);
+
   virtual void Stop();
 
  protected:
@@ -77,9 +80,6 @@
   // Used to start the device listener or notify network change after a delay.
   base::OneShotTimer timer_;
 
-  // The delay used on start up.
-  base::TimeDelta startup_delay_;
-
   // The delay used when network status becomes online.
   base::TimeDelta online_delay_;
 
diff --git a/components/download/internal/background_service/scheduler/device_status_listener_unittest.cc b/components/download/internal/background_service/scheduler/device_status_listener_unittest.cc
index 070ebe8..0397a442 100644
--- a/components/download/internal/background_service/scheduler/device_status_listener_unittest.cc
+++ b/components/download/internal/background_service/scheduler/device_status_listener_unittest.cc
@@ -63,8 +63,19 @@
                              std::move(battery_listener),
                              std::move(network_listener)) {}
 
+  // DeviceStatusListener implementation.
+  void Start(const base::TimeDelta& start_delay) override {
+    // Cache the start delay for verification.
+    start_delay_ = start_delay;
+    DeviceStatusListener::Start(start_delay);
+  }
+
+  base::TimeDelta start_delay() const { return start_delay_; }
+
  private:
   friend class DeviceStatusListenerTest;
+  base::TimeDelta start_delay_;
+
   DISALLOW_COPY_AND_ASSIGN(TestDeviceStatusListener);
 };
 
@@ -86,6 +97,7 @@
 
     listener_ = std::make_unique<TestDeviceStatusListener>(
         std::move(battery_listener), std::move(network_listener));
+    listener_->SetObserver(&mock_observer_);
   }
 
   void TearDown() override { listener_.reset(); }
@@ -100,7 +112,7 @@
     EXPECT_CALL(mock_observer_, OnDeviceStatusChanged(_))
         .Times(1)
         .RetiresOnSaturation();
-    listener_->Start(&mock_observer_);
+    listener_->Start(base::TimeDelta());
     base::RunLoop().RunUntilIdle();
   }
 
@@ -145,7 +157,8 @@
   EXPECT_EQ(DeviceStatus(), listener_->CurrentDeviceStatus());
 
   const int kInitialBatteryPercentage = 45;
-  listener_->Start(&mock_observer_);
+  listener_->Start(base::TimeDelta());
+
   ChangeBatteryPercentage(kInitialBatteryPercentage);
 
   // We are in no opt state, notify the observer.
@@ -157,6 +170,20 @@
   EXPECT_EQ(NetworkStatus::DISCONNECTED, status.network_status);
 }
 
+// Verifies two Start() call will only do initialization for once, and the start
+// delay should be refreshed based on a later Start() call.
+TEST_F(DeviceStatusListenerTest, DuplicateStart) {
+  ChangeNetworkType(ConnectionType::CONNECTION_NONE);
+  SimulateBatteryChange(true); /* Not charging. */
+  EXPECT_EQ(DeviceStatus(), listener_->CurrentDeviceStatus());
+  const auto acutual_delay = base::TimeDelta::FromSeconds(0);
+  listener_->Start(base::TimeDelta::FromSeconds(1));
+  listener_->Start(acutual_delay);
+  EXPECT_CALL(mock_observer_, OnDeviceStatusChanged(_)).Times(1);
+  base::RunLoop().RunUntilIdle();
+  EXPECT_EQ(listener_->start_delay(), acutual_delay);
+}
+
 TEST_F(DeviceStatusListenerTest, TestValidStateChecks) {
   ChangeNetworkType(ConnectionType::CONNECTION_NONE);
   SimulateBatteryChange(true);
@@ -164,7 +191,7 @@
 
   {
     EXPECT_CALL(mock_observer_, OnDeviceStatusChanged(_)).Times(0);
-    listener_->Start(&mock_observer_);
+    listener_->Start(base::TimeDelta());
     EXPECT_FALSE(listener_->is_valid_state());
   }
 
@@ -196,7 +223,7 @@
 
 // Ensures the observer is notified when network condition changes.
 TEST_F(DeviceStatusListenerTest, NotifyObserverNetworkChange) {
-  listener_->Start(&mock_observer_);
+  listener_->Start(base::TimeDelta());
 
   // Initial states check.
   EXPECT_EQ(NetworkStatus::DISCONNECTED,
@@ -240,7 +267,7 @@
   SimulateBatteryChange(false); /* Charging. */
   EXPECT_EQ(DeviceStatus(), listener_->CurrentDeviceStatus());
 
-  listener_->Start(&mock_observer_);
+  listener_->Start(base::TimeDelta());
 
   EXPECT_CALL(mock_observer_, OnDeviceStatusChanged(
                                   BatteryStatusEqual(BatteryStatus::CHARGING)))
diff --git a/components/download/internal/background_service/test/test_device_status_listener.cc b/components/download/internal/background_service/test/test_device_status_listener.cc
index ebea337..44b70208 100644
--- a/components/download/internal/background_service/test/test_device_status_listener.cc
+++ b/components/download/internal/background_service/test/test_device_status_listener.cc
@@ -52,9 +52,11 @@
   status_ = status;
 }
 
-void TestDeviceStatusListener::Start(DeviceStatusListener::Observer* observer) {
+void TestDeviceStatusListener::Start(const base::TimeDelta& start_delay) {
+  if (listening_ || !observer_)
+    return;
+
   listening_ = true;
-  observer_ = observer;
 
   // Simulates the delay after start up.
   base::ThreadTaskRunnerHandle::Get()->PostTask(
diff --git a/components/download/internal/background_service/test/test_device_status_listener.h b/components/download/internal/background_service/test/test_device_status_listener.h
index aa717cc..ef9ec8e 100644
--- a/components/download/internal/background_service/test/test_device_status_listener.h
+++ b/components/download/internal/background_service/test/test_device_status_listener.h
@@ -26,7 +26,7 @@
   void SetDeviceStatus(const DeviceStatus& status);
 
   // DeviceStatusListener implementation.
-  void Start(DeviceStatusListener::Observer* observer) override;
+  void Start(const base::TimeDelta& start_delay) override;
   void Stop() override;
 
  private:
diff --git a/components/exo/client_controlled_shell_surface_unittest.cc b/components/exo/client_controlled_shell_surface_unittest.cc
index b4a7157..c1600938 100644
--- a/components/exo/client_controlled_shell_surface_unittest.cc
+++ b/components/exo/client_controlled_shell_surface_unittest.cc
@@ -1837,9 +1837,11 @@
   ui::ScopedAnimationDurationScaleMode animation_scale_mode(
       ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
   aura::Window* window = shell_surface->GetWidget()->GetNativeWindow();
+  EXPECT_EQ(gfx::Rect(8, 8, 256, 256), window->layer()->GetTargetBounds());
+  EXPECT_EQ(gfx::Rect(8, 8, 256, 256), window->layer()->bounds());
   window->SetBounds(gfx::Rect(10, 10, 256, 256));
   EXPECT_EQ(gfx::Rect(10, 10, 256, 256), window->layer()->GetTargetBounds());
-  EXPECT_EQ(gfx::Rect(0, 0, 256, 256), window->layer()->bounds());
+  EXPECT_EQ(gfx::Rect(8, 8, 256, 256), window->layer()->bounds());
 }
 
 TEST_F(ClientControlledShellSurfaceTest, PipWindowDragDoesNotAnimate) {
@@ -1857,13 +1859,15 @@
   shell_surface->GetWidget()->Show();
 
   aura::Window* window = shell_surface->GetWidget()->GetNativeWindow();
+  EXPECT_EQ(gfx::Rect(8, 8, 256, 256), window->layer()->GetTargetBounds());
+  EXPECT_EQ(gfx::Rect(8, 8, 256, 256), window->layer()->bounds());
   ui::ScopedAnimationDurationScaleMode animation_scale_mode(
       ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
   std::unique_ptr<ash::WindowResizer> resizer(ash::CreateWindowResizer(
       window, gfx::Point(), HTCAPTION, ::wm::WINDOW_MOVE_SOURCE_MOUSE));
   resizer->Drag(gfx::Point(10, 10), 0);
-  EXPECT_EQ(gfx::Rect(10, 10, 256, 256), window->layer()->GetTargetBounds());
-  EXPECT_EQ(gfx::Rect(10, 10, 256, 256), window->layer()->bounds());
+  EXPECT_EQ(gfx::Rect(18, 18, 256, 256), window->layer()->GetTargetBounds());
+  EXPECT_EQ(gfx::Rect(18, 18, 256, 256), window->layer()->bounds());
   resizer->CompleteDrag();
 }
 
diff --git a/components/feature_engagement/internal/tracker_impl_unittest.cc b/components/feature_engagement/internal/tracker_impl_unittest.cc
index 197a10e..6c422e6 100644
--- a/components/feature_engagement/internal/tracker_impl_unittest.cc
+++ b/components/feature_engagement/internal/tracker_impl_unittest.cc
@@ -117,7 +117,7 @@
                   uint32_t event_day,
                   uint32_t current_day) const override {
     return true;
-  };
+  }
 
  private:
   DISALLOW_COPY_AND_ASSIGN(StoreEverythingEventStorageValidator);
@@ -129,7 +129,7 @@
   ~TestTimeProvider() override = default;
 
   // TimeProvider implementation.
-  uint32_t GetCurrentDay() const override { return 1u; };
+  uint32_t GetCurrentDay() const override { return 1u; }
 
  private:
   DISALLOW_COPY_AND_ASSIGN(TestTimeProvider);
diff --git a/components/sync/device_info/DEPS b/components/sync/device_info/DEPS
index 26784b6b7..3c48053e 100644
--- a/components/sync/device_info/DEPS
+++ b/components/sync/device_info/DEPS
@@ -2,8 +2,6 @@
   "+components/keyed_service",
   "+components/metrics",
   "+components/sync/base",
-  # TODO(crbug.com/922971): The dependency to driver/ is only needed for
-  # MakeUserAgentForSync() which can be moved elsewhere.
   "+components/sync/driver",
   "+components/sync/model",
   "+components/sync/model_impl",
diff --git a/components/sync/device_info/local_device_info_provider_impl.h b/components/sync/device_info/local_device_info_provider_impl.h
index 92688a5..ef1e5d9 100644
--- a/components/sync/device_info/local_device_info_provider_impl.h
+++ b/components/sync/device_info/local_device_info_provider_impl.h
@@ -20,7 +20,6 @@
 
 class LocalDeviceInfoProviderImpl : public LocalDeviceInfoProvider {
  public:
-  // TODO(crbug.com/922971): This could be moved to DeviceInfoSyncService.
   using SigninScopedDeviceIdCallback = base::RepeatingCallback<std::string()>;
 
   LocalDeviceInfoProviderImpl(
diff --git a/components/test/DEPS b/components/test/DEPS
index 8971108..3350f447 100644
--- a/components/test/DEPS
+++ b/components/test/DEPS
@@ -6,7 +6,6 @@
   "+jni",
   "+media",
   "+net",
-  "+services/catalog",
   "+ui",
 ]
 
diff --git a/components/viz/service/display_embedder/direct_context_provider.cc b/components/viz/service/display_embedder/direct_context_provider.cc
index e315b82..b7517fc7 100644
--- a/components/viz/service/display_embedder/direct_context_provider.cc
+++ b/components/viz/service/display_embedder/direct_context_provider.cc
@@ -21,7 +21,6 @@
 #include "gpu/command_buffer/service/command_buffer_direct.h"
 #include "gpu/command_buffer/service/gles2_cmd_decoder.h"
 #include "gpu/command_buffer/service/memory_tracking.h"
-#include "gpu/command_buffer/service/transfer_buffer_manager.h"
 #include "gpu/config/gpu_feature_info.h"
 #include "ui/gl/gl_context.h"
 #include "ui/gl/gl_surface.h"
@@ -45,10 +44,7 @@
       /*progress_reporter=*/nullptr, gpu_feature_info_, &discardable_manager_,
       &passthrough_discardable_manager_, &shared_image_manager_);
 
-  transfer_buffer_manager_ =
-      std::make_unique<gpu::TransferBufferManager>(nullptr);
-  auto command_buffer = std::make_unique<gpu::CommandBufferDirect>(
-      transfer_buffer_manager_.get());
+  auto command_buffer = std::make_unique<gpu::CommandBufferDirect>();
 
   std::unique_ptr<gpu::gles2::GLES2Decoder> decoder(
       gpu::gles2::GLES2Decoder::Create(command_buffer.get(),
diff --git a/components/viz/service/display_embedder/direct_context_provider.h b/components/viz/service/display_embedder/direct_context_provider.h
index 77ece27..9078b87 100644
--- a/components/viz/service/display_embedder/direct_context_provider.h
+++ b/components/viz/service/display_embedder/direct_context_provider.h
@@ -133,7 +133,6 @@
   gpu::ContextResult context_result_ = gpu::ContextResult::kSuccess;
 
   // Only non-null if BindToCurrentThread() == ContextResult::kSuccess.
-  std::unique_ptr<gpu::TransferBufferManager> transfer_buffer_manager_;
   std::unique_ptr<gpu::CommandBufferDirect> command_buffer_;
   std::unique_ptr<gpu::gles2::GLES2CmdHelper> gles2_cmd_helper_;
   std::unique_ptr<gpu::gles2::GLES2Decoder> decoder_;
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn
index 078e20d..4358ef3 100644
--- a/content/browser/BUILD.gn
+++ b/content/browser/BUILD.gn
@@ -129,9 +129,6 @@
     "//services/audio:lib",
     "//services/audio/public/cpp",
     "//services/audio/public/mojom",
-    "//services/catalog:constants",
-    "//services/catalog/public/cpp",
-    "//services/catalog/public/mojom:constants",
     "//services/content:impl",
     "//services/content/public/cpp",
     "//services/content/public/mojom",
@@ -1848,6 +1845,8 @@
     "web_package/signed_exchange_prefetch_metric_recorder.h",
     "web_package/signed_exchange_prologue.cc",
     "web_package/signed_exchange_prologue.h",
+    "web_package/signed_exchange_reporter.cc",
+    "web_package/signed_exchange_reporter.h",
     "web_package/signed_exchange_request_handler.cc",
     "web_package/signed_exchange_request_handler.h",
     "web_package/signed_exchange_request_matcher.cc",
diff --git a/content/browser/appcache/appcache_request_handler_unittest.cc b/content/browser/appcache/appcache_request_handler_unittest.cc
index 00fc790..37996ee3 100644
--- a/content/browser/appcache/appcache_request_handler_unittest.cc
+++ b/content/browser/appcache/appcache_request_handler_unittest.cc
@@ -193,7 +193,7 @@
 
     bool IsHandledProtocol(const std::string& scheme) const override {
       return scheme == "http";
-    };
+    }
 
     bool IsSafeRedirectTarget(const GURL& location) const override {
       return false;
diff --git a/content/browser/appcache/appcache_url_request_job_unittest.cc b/content/browser/appcache/appcache_url_request_job_unittest.cc
index bffbb1fa7..1165e4c0c 100644
--- a/content/browser/appcache/appcache_url_request_job_unittest.cc
+++ b/content/browser/appcache/appcache_url_request_job_unittest.cc
@@ -109,7 +109,7 @@
 
   bool IsHandledProtocol(const std::string& scheme) const override {
     return scheme == "http";
-  };
+  }
 
   bool IsSafeRedirectTarget(const GURL& location) const override {
     return false;
diff --git a/content/browser/blob_storage/chrome_blob_storage_context.cc b/content/browser/blob_storage/chrome_blob_storage_context.cc
index 944324e..8c5b2fc 100644
--- a/content/browser/blob_storage/chrome_blob_storage_context.cc
+++ b/content/browser/blob_storage/chrome_blob_storage_context.cc
@@ -88,6 +88,7 @@
 
 ChromeBlobStorageContext::ChromeBlobStorageContext() {}
 
+// static
 ChromeBlobStorageContext* ChromeBlobStorageContext::GetFor(
     BrowserContext* context) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
diff --git a/content/browser/devtools/devtools_manager_unittest.cc b/content/browser/devtools/devtools_manager_unittest.cc
index 886c0b2..89eb5d2 100644
--- a/content/browser/devtools/devtools_manager_unittest.cc
+++ b/content/browser/devtools/devtools_manager_unittest.cc
@@ -203,11 +203,11 @@
 
   void Attach(DevToolsExternalAgentProxy* proxy) override {
     recordEvent("Attach");
-  };
+  }
 
   void Detach(DevToolsExternalAgentProxy* proxy) override {
     recordEvent("Detach");
-  };
+  }
 
   std::string GetType() override { return std::string(); }
   std::string GetTitle() override { return std::string(); }
@@ -215,15 +215,15 @@
   GURL GetURL() override { return GURL(); }
   GURL GetFaviconURL() override { return GURL(); }
   std::string GetFrontendURL() override { return std::string(); }
-  bool Activate() override { return false; };
-  void Reload() override { };
-  bool Close() override { return false; };
+  bool Activate() override { return false; }
+  void Reload() override {}
+  bool Close() override { return false; }
   base::TimeTicks GetLastActivityTime() override { return base::TimeTicks(); }
 
   void SendMessageToBackend(DevToolsExternalAgentProxy* proxy,
                             const std::string& message) override {
     recordEvent(std::string("SendMessageToBackend.") + message);
-  };
+  }
 };
 
 TEST_F(DevToolsManagerTest, TestExternalProxy) {
diff --git a/content/browser/devtools/protocol/devtools_protocol_browsertest.cc b/content/browser/devtools/protocol/devtools_protocol_browsertest.cc
index 2b62753..d190bab 100644
--- a/content/browser/devtools/protocol/devtools_protocol_browsertest.cc
+++ b/content/browser/devtools/protocol/devtools_protocol_browsertest.cc
@@ -140,7 +140,7 @@
     } else {
       callback_ = std::move(callback);
     }
-  };
+  }
 
   void RunBeforeUnloadDialog(WebContents* web_contents,
                              RenderFrameHost* render_frame_host,
@@ -1631,7 +1631,7 @@
   void SetUpCommandLine(base::CommandLine* command_line) override {
     DevToolsProtocolTest::SetUpCommandLine(command_line);
     IsolateAllSitesForTesting(command_line);
-  };
+  }
 
   void SetUpOnMainThread() override {
     DevToolsProtocolTest::SetUpOnMainThread();
diff --git a/content/browser/frame_host/navigation_request.cc b/content/browser/frame_host/navigation_request.cc
index e5cacf8..11bcbee 100644
--- a/content/browser/frame_host/navigation_request.cc
+++ b/content/browser/frame_host/navigation_request.cc
@@ -611,6 +611,11 @@
     devtools_instrumentation::OnNavigationRequestFailed(
         *this, network::URLLoaderCompletionStatus(net::ERR_ABORTED));
   }
+  // This is done manually here because the NavigationHandle destructor
+  // calls into WebContentsObserver::DidFinishNavigation, some of which need to
+  // then access navigation_request(). This is only possible if the handle is
+  // destroyed before the NavigationRequest.
+  navigation_handle_.reset();
 }
 
 void NavigationRequest::BeginNavigation() {
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc
index 66ce76d..1d63f90 100644
--- a/content/browser/frame_host/render_frame_host_impl.cc
+++ b/content/browser/frame_host/render_frame_host_impl.cc
@@ -2254,8 +2254,8 @@
     same_document_navigation_request_ = std::move(navigation_request);
     return;
   }
-  navigation_requests_[navigation_request->navigation_handle()
-                           ->GetNavigationId()] = std::move(navigation_request);
+  navigation_requests_[navigation_request.get()] =
+      std::move(navigation_request);
 }
 
 void RenderFrameHostImpl::SwapOut(
@@ -5363,9 +5363,8 @@
 
 void RenderFrameHostImpl::NavigationRequestCancelled(
     NavigationRequest* navigation_request) {
-  OnCrossDocumentCommitProcessed(
-      navigation_request->navigation_handle()->GetNavigationId(),
-      blink::mojom::CommitResult::Aborted);
+  OnCrossDocumentCommitProcessed(navigation_request,
+                                 blink::mojom::CommitResult::Aborted);
 }
 
 bool RenderFrameHostImpl::CreateNetworkServiceDefaultFactoryAndObserve(
@@ -6200,8 +6199,7 @@
   std::unique_ptr<NavigationRequest> committed_request;
   // |navigation_request| is committed, we pass full ownership to the Navigator.
   if (navigation_request) {
-    auto it = navigation_requests_.find(
-        navigation_request->navigation_handle()->GetNavigationId());
+    auto it = navigation_requests_.find(navigation_request);
     // If we provided a navigation_request and it committed, it should always
     // be in the map.
     CHECK(it != navigation_requests_.end());
@@ -6276,13 +6274,13 @@
 }
 
 void RenderFrameHostImpl::OnCrossDocumentCommitProcessed(
-    int64_t navigation_id,
+    NavigationRequest* navigation_request,
     blink::mojom::CommitResult result) {
   DCHECK_NE(blink::mojom::CommitResult::RestartCrossDocument, result);
   if (result == blink::mojom::CommitResult::Ok) {
     // The navigation will soon be committed. Move it out of the map to the
     // NavigationRequest that is about to commit.
-    auto find_request = navigation_requests_.find(navigation_id);
+    auto find_request = navigation_requests_.find(navigation_request);
     if (find_request != navigation_requests_.end()) {
       navigation_request_ = std::move(find_request->second);
     } else {
@@ -6292,7 +6290,7 @@
     }
   }
   // Remove the requests from the list of NavigationRequests waiting to commit.
-  navigation_requests_.erase(navigation_id);
+  navigation_requests_.erase(navigation_request);
 }
 
 std::unique_ptr<base::trace_event::TracedValue>
@@ -6561,20 +6559,16 @@
   if (!navigation_request)
     return content::mojom::FrameNavigationControl::CommitNavigationCallback();
 
-  return base::BindOnce(
-      &RenderFrameHostImpl::OnCrossDocumentCommitProcessed,
-      base::Unretained(this),
-      navigation_request->navigation_handle()->GetNavigationId());
+  return base::BindOnce(&RenderFrameHostImpl::OnCrossDocumentCommitProcessed,
+                        base::Unretained(this), navigation_request);
 }
 
 mojom::FrameNavigationControl::CommitFailedNavigationCallback
 RenderFrameHostImpl::BuildCommitFailedNavigationCallback(
     NavigationRequest* navigation_request) {
   DCHECK(navigation_request);
-  return base::BindOnce(
-      &RenderFrameHostImpl::OnCrossDocumentCommitProcessed,
-      base::Unretained(this),
-      navigation_request->navigation_handle()->GetNavigationId());
+  return base::BindOnce(&RenderFrameHostImpl::OnCrossDocumentCommitProcessed,
+                        base::Unretained(this), navigation_request);
 }
 
 mojom::NavigationClient::CommitNavigationCallback
diff --git a/content/browser/frame_host/render_frame_host_impl.h b/content/browser/frame_host/render_frame_host_impl.h
index 5c720af..f01777e 100644
--- a/content/browser/frame_host/render_frame_host_impl.h
+++ b/content/browser/frame_host/render_frame_host_impl.h
@@ -1455,7 +1455,7 @@
 
   // Called by the renderer process when it is done processing a cross-document
   // commit request.
-  void OnCrossDocumentCommitProcessed(int64_t navigation_id,
+  void OnCrossDocumentCommitProcessed(NavigationRequest* navigation_request,
                                       blink::mojom::CommitResult result);
 
   // Creates a TracedValue object containing the details of a committed
@@ -1731,7 +1731,8 @@
   // When the flag is always on, rework the structure to simply store an
   // unindexed bunch of ongoing navigations and modify
   // DidCommitNavigationInternal.
-  std::map<int64_t, std::unique_ptr<NavigationRequest>> navigation_requests_;
+  std::map<NavigationRequest*, std::unique_ptr<NavigationRequest>>
+      navigation_requests_;
 
   // Holds a same-document NavigationRequest while waiting for the navigation it
   // is tracking to commit.
diff --git a/content/browser/indexed_db/database_impl.cc b/content/browser/indexed_db/database_impl.cc
index 0ea1b31..ca2d0e4 100644
--- a/content/browser/indexed_db/database_impl.cc
+++ b/content/browser/indexed_db/database_impl.cc
@@ -282,6 +282,12 @@
     blink::mojom::IDBPutMode mode,
     const std::vector<IndexedDBIndexKeys>& index_keys,
     blink::mojom::IDBCallbacksAssociatedPtrInfo callbacks_info) {
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+  CHECK(dispatcher_host_);
+  if (!dispatcher_host_->blob_storage_context()) {
+    return;
+  }
+
   ChildProcessSecurityPolicyImpl* policy =
       ChildProcessSecurityPolicyImpl::GetInstance();
 
diff --git a/content/browser/indexed_db/indexed_db_callbacks.cc b/content/browser/indexed_db/indexed_db_callbacks.cc
index d2c7b73..08cfb24 100644
--- a/content/browser/indexed_db/indexed_db_callbacks.cc
+++ b/content/browser/indexed_db/indexed_db_callbacks.cc
@@ -94,7 +94,7 @@
 };
 
 std::unique_ptr<storage::BlobDataHandle> CreateBlobData(
-    storage::BlobStorageContext* blob_context,
+    base::WeakPtr<storage::BlobStorageContext> blob_context,
     IndexedDBContextImpl* indexed_db_context,
     const IndexedDBBlobInfo& blob_info) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
@@ -180,7 +180,7 @@
 
 // static
 bool IndexedDBCallbacks::CreateAllBlobs(
-    storage::BlobStorageContext* blob_context,
+    base::WeakPtr<storage::BlobStorageContext> blob_context,
     IndexedDBContextImpl* indexed_db_context,
     const std::vector<IndexedDBBlobInfo>& blob_info,
     std::vector<blink::mojom::IDBBlobInfoPtr>* blob_or_file_info) {
@@ -504,7 +504,7 @@
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
   if (!callbacks_)
     return;
-  if (!dispatcher_host_) {
+  if (!dispatcher_host_ || !dispatcher_host_->blob_storage_context()) {
     OnConnectionError();
     return;
   }
@@ -516,7 +516,7 @@
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
   if (!callbacks_)
     return;
-  if (!dispatcher_host_) {
+  if (!dispatcher_host_ || !dispatcher_host_->blob_storage_context()) {
     OnConnectionError();
     return;
   }
@@ -528,7 +528,7 @@
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
   if (!callbacks_)
     return;
-  if (!dispatcher_host_) {
+  if (!dispatcher_host_ || !dispatcher_host_->blob_storage_context()) {
     OnConnectionError();
     return;
   }
@@ -537,7 +537,7 @@
 
 void IndexedDBCallbacks::IOThreadHelper::SendBlocked(int64_t existing_version) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
-  if (!dispatcher_host_) {
+  if (!dispatcher_host_ || !dispatcher_host_->blob_storage_context()) {
     OnConnectionError();
     return;
   }
@@ -554,7 +554,7 @@
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
   if (!callbacks_)
     return;
-  if (!dispatcher_host_) {
+  if (!dispatcher_host_ || !dispatcher_host_->blob_storage_context()) {
     OnConnectionError();
     return;
   }
@@ -577,7 +577,7 @@
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
   if (!callbacks_)
     return;
-  if (!dispatcher_host_) {
+  if (!dispatcher_host_ || !dispatcher_host_->blob_storage_context()) {
     OnConnectionError();
     return;
   }
@@ -603,7 +603,7 @@
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
   if (!callbacks_)
     return;
-  if (!dispatcher_host_) {
+  if (!dispatcher_host_ || !dispatcher_host_->blob_storage_context()) {
     OnConnectionError();
     return;
   }
@@ -629,7 +629,7 @@
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
   if (!callbacks_)
     return;
-  if (!dispatcher_host_) {
+  if (!dispatcher_host_ || !dispatcher_host_->blob_storage_context()) {
     OnConnectionError();
     return;
   }
@@ -649,7 +649,7 @@
 
   if (!callbacks_)
     return;
-  if (!dispatcher_host_) {
+  if (!dispatcher_host_ || !dispatcher_host_->blob_storage_context()) {
     OnConnectionError();
     return;
   }
@@ -672,7 +672,7 @@
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
   if (!callbacks_)
     return;
-  if (!dispatcher_host_) {
+  if (!dispatcher_host_ || !dispatcher_host_->blob_storage_context()) {
     OnConnectionError();
     return;
   }
@@ -694,7 +694,7 @@
 
   if (!callbacks_)
     return;
-  if (!dispatcher_host_) {
+  if (!dispatcher_host_ || !dispatcher_host_->blob_storage_context()) {
     OnConnectionError();
     return;
   }
@@ -716,7 +716,7 @@
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
   if (!callbacks_)
     return;
-  if (!dispatcher_host_) {
+  if (!dispatcher_host_ || !dispatcher_host_->blob_storage_context()) {
     OnConnectionError();
     return;
   }
@@ -727,7 +727,7 @@
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
   if (!callbacks_)
     return;
-  if (!dispatcher_host_) {
+  if (!dispatcher_host_ || !dispatcher_host_->blob_storage_context()) {
     OnConnectionError();
     return;
   }
@@ -738,7 +738,7 @@
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
   if (!callbacks_)
     return;
-  if (!dispatcher_host_) {
+  if (!dispatcher_host_ || !dispatcher_host_->blob_storage_context()) {
     OnConnectionError();
     return;
   }
diff --git a/content/browser/indexed_db/indexed_db_callbacks.h b/content/browser/indexed_db/indexed_db_callbacks.h
index 8b85f76..bb1048f2 100644
--- a/content/browser/indexed_db/indexed_db_callbacks.h
+++ b/content/browser/indexed_db/indexed_db_callbacks.h
@@ -47,7 +47,7 @@
     : public base::RefCounted<IndexedDBCallbacks> {
  public:
   static bool CreateAllBlobs(
-      storage::BlobStorageContext* blob_context,
+      base::WeakPtr<storage::BlobStorageContext> blob_context,
       IndexedDBContextImpl* indexed_db_context,
       const std::vector<IndexedDBBlobInfo>& blob_info,
       std::vector<blink::mojom::IDBBlobInfoPtr>* blob_or_file_info);
diff --git a/content/browser/indexed_db/indexed_db_cursor.cc b/content/browser/indexed_db/indexed_db_cursor.cc
index 7f1ad84..20f1dac 100644
--- a/content/browser/indexed_db/indexed_db_cursor.cc
+++ b/content/browser/indexed_db/indexed_db_cursor.cc
@@ -174,7 +174,7 @@
              blink::mojom::IDBCursor::AdvanceCallback callback,
              IndexedDBKey key, IndexedDBKey primary_key,
              IndexedDBValue* value) {
-            if (!dispatcher_host)
+            if (!dispatcher_host || !dispatcher_host->blob_storage_context())
               return;
 
             blink::mojom::IDBValuePtr mojo_value;
diff --git a/content/browser/indexed_db/indexed_db_dispatcher_host.cc b/content/browser/indexed_db/indexed_db_dispatcher_host.cc
index 3a21012..06e85cc 100644
--- a/content/browser/indexed_db/indexed_db_dispatcher_host.cc
+++ b/content/browser/indexed_db/indexed_db_dispatcher_host.cc
@@ -125,8 +125,7 @@
     : indexed_db_context_(std::move(indexed_db_context)),
       blob_storage_context_(std::move(blob_storage_context)),
       ipc_process_id_(ipc_process_id),
-      idb_helper_(new IDBSequenceHelper(ipc_process_id_,
-                                        indexed_db_context_)),
+      idb_helper_(new IDBSequenceHelper(ipc_process_id_, indexed_db_context_)),
       weak_factory_(this) {
   DCHECK(indexed_db_context_.get());
 }
@@ -138,6 +137,12 @@
 void IndexedDBDispatcherHost::AddBinding(
     blink::mojom::IDBFactoryRequest request,
     const url::Origin& origin) {
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+  if (blob_storage_context_) {
+    io_weak_blob_storage_context_ =
+        blob_storage_context_->context()->AsWeakPtr();
+    blob_storage_context_.reset();
+  }
   bindings_.AddBinding(this, std::move(request), {origin});
 }
 
diff --git a/content/browser/indexed_db/indexed_db_dispatcher_host.h b/content/browser/indexed_db/indexed_db_dispatcher_host.h
index f147d36..27e7ce8 100644
--- a/content/browser/indexed_db/indexed_db_dispatcher_host.h
+++ b/content/browser/indexed_db/indexed_db_dispatcher_host.h
@@ -58,8 +58,8 @@
 
   // A shortcut for accessing our context.
   IndexedDBContextImpl* context() const { return indexed_db_context_.get(); }
-  storage::BlobStorageContext* blob_storage_context() const {
-    return blob_storage_context_->context();
+  base::WeakPtr<storage::BlobStorageContext> blob_storage_context() const {
+    return io_weak_blob_storage_context_;
   }
   int ipc_process_id() const { return ipc_process_id_; }
 
@@ -107,7 +107,9 @@
   base::SequencedTaskRunner* IDBTaskRunner() const;
 
   scoped_refptr<IndexedDBContextImpl> indexed_db_context_;
+
   scoped_refptr<ChromeBlobStorageContext> blob_storage_context_;
+  base::WeakPtr<storage::BlobStorageContext> io_weak_blob_storage_context_;
 
   // Used to set file permissions for blob storage.
   const int ipc_process_id_;
diff --git a/content/browser/indexed_db/indexed_db_dispatcher_host_unittest.cc b/content/browser/indexed_db/indexed_db_dispatcher_host_unittest.cc
index 6e25235f..a2e21656 100644
--- a/content/browser/indexed_db/indexed_db_dispatcher_host_unittest.cc
+++ b/content/browser/indexed_db/indexed_db_dispatcher_host_unittest.cc
@@ -193,6 +193,11 @@
   }
 
   void SetUp() override {
+    // ChromeBlobStorageContext::GetFor() issues PostTask() calls to the IO
+    // thread.  Let those run before calling AddBinding().
+    base::RunLoop loop;
+    loop.RunUntilIdle();
+
     host_->AddBinding(::mojo::MakeRequest(&idb_mojo_factory_),
                       {url::Origin::Create(GURL(kOrigin))});
   }
diff --git a/content/browser/media/browser_feature_provider.cc b/content/browser/media/browser_feature_provider.cc
index c6d006c..713a98c 100644
--- a/content/browser/media/browser_feature_provider.cc
+++ b/content/browser/media/browser_feature_provider.cc
@@ -13,7 +13,7 @@
 using ::media::learning::FeatureLibrary;
 using ::media::learning::FeatureProviderFactoryCB;
 using ::media::learning::FeatureValue;
-using ::media::learning::LabelledExample;
+using ::media::learning::FeatureVector;
 using ::media::learning::LearningTask;
 using ::media::learning::SequenceBoundFeatureProvider;
 
@@ -36,24 +36,22 @@
   return base::BindRepeating(&BrowserFeatureProvider::Create);
 }
 
-void BrowserFeatureProvider::AddFeatures(const LabelledExample& example,
-                                         LabelledExampleCB cb) {
-  LabelledExample new_example = example;
-
+void BrowserFeatureProvider::AddFeatures(FeatureVector features,
+                                         FeatureVectorCB cb) {
   const size_t size = task_.feature_descriptions.size();
-  if (new_example.features.size() < size)
-    new_example.features.resize(size);
+  if (features.size() < size)
+    features.resize(size);
 
   // Find any features that we're supposed to fill in.
   for (size_t i = 0; i < size; i++) {
     const auto& desc = task_.feature_descriptions[i];
     if (desc.name == FeatureLibrary::NetworkType().name) {
-      new_example.features[i] = FeatureValue(
+      features[i] = FeatureValue(
           static_cast<int>(net::NetworkChangeNotifier::GetConnectionType()));
     }
   }
 
-  std::move(cb).Run(std::move(new_example));
+  std::move(cb).Run(std::move(features));
 }
 
 }  // namespace content
diff --git a/content/browser/media/browser_feature_provider.h b/content/browser/media/browser_feature_provider.h
index dbcd9cf..8619bc1 100644
--- a/content/browser/media/browser_feature_provider.h
+++ b/content/browser/media/browser_feature_provider.h
@@ -28,8 +28,8 @@
   static ::media::learning::FeatureProviderFactoryCB GetFactoryCB();
 
   // FeatureProvider
-  void AddFeatures(const ::media::learning::LabelledExample& example,
-                   LabelledExampleCB cb) override;
+  void AddFeatures(::media::learning::FeatureVector features,
+                   FeatureVectorCB cb) override;
 
  private:
   ::media::learning::LearningTask task_;
diff --git a/content/browser/renderer_host/compositor_impl_android.cc b/content/browser/renderer_host/compositor_impl_android.cc
index 6a8d619..4172fb9 100644
--- a/content/browser/renderer_host/compositor_impl_android.cc
+++ b/content/browser/renderer_host/compositor_impl_android.cc
@@ -865,6 +865,16 @@
   host_->SetNeedsAnimate();
 }
 
+void CompositorImpl::DidUpdateLayers() {
+  // Dump property trees and layers if run with:
+  //   --vmodule=compositor_impl_android=3
+  VLOG(3) << "After updating layers:\n"
+          << "property trees:\n"
+          << host_->property_trees()->ToString() << "\n"
+          << "cc::Layers:\n"
+          << host_->LayersAsString();
+}
+
 void CompositorImpl::UpdateLayerTreeHost() {
   client_->UpdateLayerTreeHost();
   if (needs_animate_) {
diff --git a/content/browser/renderer_host/compositor_impl_android.h b/content/browser/renderer_host/compositor_impl_android.h
index cce753d..8c7fac418 100644
--- a/content/browser/renderer_host/compositor_impl_android.h
+++ b/content/browser/renderer_host/compositor_impl_android.h
@@ -110,6 +110,7 @@
   // LayerTreeHostClient implementation.
   void WillBeginMainFrame() override {}
   void DidBeginMainFrame() override {}
+  void DidUpdateLayers() override;
   void BeginMainFrame(const viz::BeginFrameArgs& args) override {}
   void BeginMainFrameNotExpectedSoon() override {}
   void BeginMainFrameNotExpectedUntil(base::TimeTicks time) override {}
diff --git a/content/browser/service_worker/service_worker_browsertest.cc b/content/browser/service_worker/service_worker_browsertest.cc
index c7f31a4..2d67a2101 100644
--- a/content/browser/service_worker/service_worker_browsertest.cc
+++ b/content/browser/service_worker/service_worker_browsertest.cc
@@ -3114,7 +3114,7 @@
     // OnCachedMetadataUpdated() is called.
     run_loop.Run();
   }
-  size_t metadata_size() { return metadata_size_; };
+  size_t metadata_size() { return metadata_size_; }
 
  protected:
   // ServiceWorkerVersion::Observer overrides
diff --git a/content/browser/service_worker/service_worker_context_watcher_unittest.cc b/content/browser/service_worker/service_worker_context_watcher_unittest.cc
index b6ebed9..feb3989 100644
--- a/content/browser/service_worker/service_worker_context_watcher_unittest.cc
+++ b/content/browser/service_worker/service_worker_context_watcher_unittest.cc
@@ -71,7 +71,7 @@
     return errors_;
   }
 
-  int callback_count() const { return callback_count_; };
+  int callback_count() const { return callback_count_; }
 
  private:
   void OnRegistrationUpdated(
diff --git a/content/browser/service_worker/service_worker_provider_host_unittest.cc b/content/browser/service_worker/service_worker_provider_host_unittest.cc
index 58d394c..5b1abf6 100644
--- a/content/browser/service_worker/service_worker_provider_host_unittest.cc
+++ b/content/browser/service_worker/service_worker_provider_host_unittest.cc
@@ -436,7 +436,7 @@
   }
 
  protected:
-  ~MockServiceWorkerRegistration() override{};
+  ~MockServiceWorkerRegistration() override {}
 
  private:
   std::set<ServiceWorkerRegistration::Listener*> listeners_;
diff --git a/content/browser/service_worker/service_worker_registration_unittest.cc b/content/browser/service_worker/service_worker_registration_unittest.cc
index f38ee06..ac051996 100644
--- a/content/browser/service_worker/service_worker_registration_unittest.cc
+++ b/content/browser/service_worker/service_worker_registration_unittest.cc
@@ -77,10 +77,10 @@
   }
   ~MockServiceWorkerRegistrationObject() override = default;
 
-  int update_found_called_count() const { return update_found_called_count_; };
+  int update_found_called_count() const { return update_found_called_count_; }
   int set_version_attributes_called_count() const {
     return set_version_attributes_called_count_;
-  };
+  }
   int set_update_via_cache_called_count() const {
     return set_update_via_cache_called_count_;
   }
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc
index ea87008..4c68f6e 100644
--- a/content/browser/web_contents/web_contents_impl.cc
+++ b/content/browser/web_contents/web_contents_impl.cc
@@ -2798,6 +2798,7 @@
   // Track the delegate on which WebContentsCreated may be called.
   // TODO(ericrk): Remove this once debugging complete. https://crbug.com/758186
   web_contents_created_delegate_ = delegate_;
+  web_contents_added_to_delegate_ = false;
   if (delegate_) {
     delegate_->WebContentsCreated(this, render_process_id,
                                   opener->GetRoutingID(), params.frame_name,
@@ -2936,6 +2937,10 @@
                     "WebContentsCreated. "
                  << delegate_ << " vs " << web_contents_created_delegate_;
     }
+    if (web_contents_added_to_delegate_) {
+      LOG(ERROR) << "WebContents added to delegate twice";
+    }
+    web_contents_added_to_delegate_ = true;
 
     // Mark the web contents as pending resume, then immediately do
     // the resume if the delegate wants it.
diff --git a/content/browser/web_contents/web_contents_impl.h b/content/browser/web_contents/web_contents_impl.h
index ca355f6..e535c16 100644
--- a/content/browser/web_contents/web_contents_impl.h
+++ b/content/browser/web_contents/web_contents_impl.h
@@ -1853,6 +1853,7 @@
   // TODO(ericrk): Variable to debug https://crbug.com/758186. Remove when
   // debugging concluded.
   WebContentsDelegate* web_contents_created_delegate_ = nullptr;
+  bool web_contents_added_to_delegate_ = false;
 
   base::WeakPtrFactory<WebContentsImpl> loading_weak_factory_;
   base::WeakPtrFactory<WebContentsImpl> weak_factory_;
diff --git a/content/browser/web_package/signed_exchange_cert_fetcher.cc b/content/browser/web_package/signed_exchange_cert_fetcher.cc
index 792d111..a4f67e2 100644
--- a/content/browser/web_package/signed_exchange_cert_fetcher.cc
+++ b/content/browser/web_package/signed_exchange_cert_fetcher.cc
@@ -14,6 +14,7 @@
 #include "content/browser/loader/resource_dispatcher_host_impl.h"
 #include "content/browser/web_package/signed_exchange_consts.h"
 #include "content/browser/web_package/signed_exchange_devtools_proxy.h"
+#include "content/browser/web_package/signed_exchange_reporter.h"
 #include "content/browser/web_package/signed_exchange_utils.h"
 #include "content/common/throttling_url_loader.h"
 #include "content/public/common/resource_type.h"
@@ -76,6 +77,7 @@
     bool force_fetch,
     CertificateCallback callback,
     SignedExchangeDevToolsProxy* devtools_proxy,
+    SignedExchangeReporter* reporter,
     const base::Optional<base::UnguessableToken>& throttling_profile_id) {
   TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("loading"),
                "SignedExchangeCertFetcher::CreateAndStart");
@@ -83,7 +85,7 @@
       new SignedExchangeCertFetcher(std::move(shared_url_loader_factory),
                                     std::move(throttles), cert_url, force_fetch,
                                     std::move(callback), devtools_proxy,
-                                    throttling_profile_id));
+                                    reporter, throttling_profile_id));
   cert_fetcher->Start();
   return cert_fetcher;
 }
@@ -96,12 +98,14 @@
     bool force_fetch,
     CertificateCallback callback,
     SignedExchangeDevToolsProxy* devtools_proxy,
+    SignedExchangeReporter* reporter,
     const base::Optional<base::UnguessableToken>& throttling_profile_id)
     : shared_url_loader_factory_(std::move(shared_url_loader_factory)),
       throttles_(std::move(throttles)),
       resource_request_(std::make_unique<network::ResourceRequest>()),
       callback_(std::move(callback)),
-      devtools_proxy_(devtools_proxy) {
+      devtools_proxy_(devtools_proxy),
+      reporter_(reporter) {
   // TODO(https://crbug.com/803774): Revisit more ResourceRequest flags.
   resource_request_->url = cert_url;
   // |request_initiator| is used for cookie checks, but cert requests don't use
@@ -214,6 +218,10 @@
                                                  resource_request_->url, head);
   }
 
+  if (reporter_) {
+    reporter_->set_cert_server_ip(head.socket_address.host());
+  }
+
   // |headers| is null when loading data URL.
   if (head.headers && head.headers->response_code() != net::HTTP_OK) {
     signed_exchange_utils::ReportErrorAndTraceEvent(
diff --git a/content/browser/web_package/signed_exchange_cert_fetcher.h b/content/browser/web_package/signed_exchange_cert_fetcher.h
index 880fba2..283e81e7 100644
--- a/content/browser/web_package/signed_exchange_cert_fetcher.h
+++ b/content/browser/web_package/signed_exchange_cert_fetcher.h
@@ -29,6 +29,7 @@
 namespace content {
 
 class SignedExchangeDevToolsProxy;
+class SignedExchangeReporter;
 class ThrottlingURLLoader;
 class URLLoaderThrottle;
 
@@ -54,6 +55,7 @@
       bool force_fetch,
       CertificateCallback callback,
       SignedExchangeDevToolsProxy* devtools_proxy,
+      SignedExchangeReporter* reporter,
       const base::Optional<base::UnguessableToken>& throttling_profile_id);
 
   ~SignedExchangeCertFetcher() override;
@@ -75,6 +77,7 @@
       bool force_fetch,
       CertificateCallback callback,
       SignedExchangeDevToolsProxy* devtools_proxy,
+      SignedExchangeReporter* reporter,
       const base::Optional<base::UnguessableToken>& throttling_profile_id);
   void Start();
   void Abort();
@@ -106,6 +109,9 @@
 
   // This is owned by SignedExchangeHandler which is the owner of |this|.
   SignedExchangeDevToolsProxy* devtools_proxy_;
+  // This is owned by SignedExchangeLoader which owns SignedExchangeHandler
+  // that is the owner of |this|.
+  SignedExchangeReporter* reporter_;
   base::Optional<base::UnguessableToken> cert_request_id_;
 
   DISALLOW_COPY_AND_ASSIGN(SignedExchangeCertFetcher);
diff --git a/content/browser/web_package/signed_exchange_cert_fetcher_factory.cc b/content/browser/web_package/signed_exchange_cert_fetcher_factory.cc
index 17b8c18..db373b626 100644
--- a/content/browser/web_package/signed_exchange_cert_fetcher_factory.cc
+++ b/content/browser/web_package/signed_exchange_cert_fetcher_factory.cc
@@ -30,7 +30,8 @@
       const GURL& cert_url,
       bool force_fetch,
       SignedExchangeCertFetcher::CertificateCallback callback,
-      SignedExchangeDevToolsProxy* devtools_proxy) override;
+      SignedExchangeDevToolsProxy* devtools_proxy,
+      SignedExchangeReporter* reporter) override;
 
  private:
   scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
@@ -43,14 +44,16 @@
     const GURL& cert_url,
     bool force_fetch,
     SignedExchangeCertFetcher::CertificateCallback callback,
-    SignedExchangeDevToolsProxy* devtools_proxy) {
+    SignedExchangeDevToolsProxy* devtools_proxy,
+    SignedExchangeReporter* reporter) {
   DCHECK(url_loader_factory_);
   DCHECK(url_loader_throttles_getter_);
   std::vector<std::unique_ptr<URLLoaderThrottle>> throttles =
       std::move(url_loader_throttles_getter_).Run();
   return SignedExchangeCertFetcher::CreateAndStart(
       std::move(url_loader_factory_), std::move(throttles), cert_url,
-      force_fetch, std::move(callback), devtools_proxy, throttling_profile_id_);
+      force_fetch, std::move(callback), devtools_proxy, reporter,
+      throttling_profile_id_);
 }
 
 // static
diff --git a/content/browser/web_package/signed_exchange_cert_fetcher_factory.h b/content/browser/web_package/signed_exchange_cert_fetcher_factory.h
index a15c456..850252bb 100644
--- a/content/browser/web_package/signed_exchange_cert_fetcher_factory.h
+++ b/content/browser/web_package/signed_exchange_cert_fetcher_factory.h
@@ -22,6 +22,7 @@
 
 class SignedExchangeDevToolsProxy;
 class SignedExchangeCertFetcher;
+class SignedExchangeReporter;
 class URLLoaderThrottle;
 
 // An interface for creating SignedExchangeCertFetcher object.
@@ -34,7 +35,8 @@
       const GURL& cert_url,
       bool force_fetch,
       SignedExchangeCertFetcher::CertificateCallback callback,
-      SignedExchangeDevToolsProxy* devtools_proxy) = 0;
+      SignedExchangeDevToolsProxy* devtools_proxy,
+      SignedExchangeReporter* reporter) = 0;
 
   using URLLoaderThrottlesGetter = base::RepeatingCallback<
       std::vector<std::unique_ptr<content::URLLoaderThrottle>>()>;
diff --git a/content/browser/web_package/signed_exchange_cert_fetcher_unittest.cc b/content/browser/web_package/signed_exchange_cert_fetcher_unittest.cc
index 3ea96f7..5895294 100644
--- a/content/browser/web_package/signed_exchange_cert_fetcher_unittest.cc
+++ b/content/browser/web_package/signed_exchange_cert_fetcher_unittest.cc
@@ -215,7 +215,7 @@
         base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
             &mock_loader_factory_),
         std::move(throttles_), url, force_fetch, std::move(callback),
-        nullptr /* devtools_proxy */,
+        nullptr /* devtools_proxy */, nullptr /* reporter */,
         base::nullopt /* throttling_profile_id */);
   }
 
diff --git a/content/browser/web_package/signed_exchange_error.h b/content/browser/web_package/signed_exchange_error.h
index 408f476..de84ce2 100644
--- a/content/browser/web_package/signed_exchange_error.h
+++ b/content/browser/web_package/signed_exchange_error.h
@@ -43,7 +43,9 @@
   kCertRequirementsNotMet,
   // SXG was served without "X-Content-Type-Options: nosniff" header.
   kSXGServedWithoutNosniff,
-  kMaxValue = kSXGServedWithoutNosniff
+  // Merkle integrity error.
+  kMerkleIntegrityError,
+  kMaxValue = kMerkleIntegrityError
 };
 
 struct SignedExchangeError {
diff --git a/content/browser/web_package/signed_exchange_handler.cc b/content/browser/web_package/signed_exchange_handler.cc
index 851e79d..a49cde4 100644
--- a/content/browser/web_package/signed_exchange_handler.cc
+++ b/content/browser/web_package/signed_exchange_handler.cc
@@ -22,6 +22,7 @@
 #include "content/browser/web_package/signed_exchange_devtools_proxy.h"
 #include "content/browser/web_package/signed_exchange_envelope.h"
 #include "content/browser/web_package/signed_exchange_prologue.h"
+#include "content/browser/web_package/signed_exchange_reporter.h"
 #include "content/browser/web_package/signed_exchange_signature_verifier.h"
 #include "content/browser/web_package/signed_exchange_utils.h"
 #include "content/public/browser/browser_task_traits.h"
@@ -185,6 +186,7 @@
     std::unique_ptr<SignedExchangeCertFetcherFactory> cert_fetcher_factory,
     int load_flags,
     std::unique_ptr<SignedExchangeDevToolsProxy> devtools_proxy,
+    SignedExchangeReporter* reporter,
     base::RepeatingCallback<int(void)> frame_tree_node_id_getter)
     : is_secure_transport_(is_secure_transport),
       has_nosniff_(has_nosniff),
@@ -193,6 +195,7 @@
       cert_fetcher_factory_(std::move(cert_fetcher_factory)),
       load_flags_(load_flags),
       devtools_proxy_(std::move(devtools_proxy)),
+      reporter_(reporter),
       frame_tree_node_id_getter_(frame_tree_node_id_getter),
       weak_factory_(this) {
   DCHECK(signed_exchange_utils::IsSignedExchangeHandlingEnabled());
@@ -426,6 +429,11 @@
     return SignedExchangeLoadResult::kHeaderParseError;
   }
 
+  if (reporter_) {
+    reporter_->set_inner_url(envelope_->request_url().url);
+    reporter_->set_cert_url(envelope_->signature().cert_url);
+  }
+
   const GURL cert_url = envelope_->signature().cert_url;
   // TODO(https://crbug.com/819467): When we will support ed25519Key, |cert_url|
   // may be empty.
@@ -441,7 +449,7 @@
                           cert_url, force_fetch,
                           base::BindOnce(&SignedExchangeHandler::OnCertReceived,
                                          base::Unretained(this)),
-                          devtools_proxy_.get());
+                          devtools_proxy_.get(), reporter_);
 
   state_ = State::kFetchingCertificate;
   return SignedExchangeLoadResult::kSuccess;
diff --git a/content/browser/web_package/signed_exchange_handler.h b/content/browser/web_package/signed_exchange_handler.h
index fc9dcade..93b4da7b 100644
--- a/content/browser/web_package/signed_exchange_handler.h
+++ b/content/browser/web_package/signed_exchange_handler.h
@@ -44,6 +44,7 @@
 class SignedExchangeCertFetcherFactory;
 class SignedExchangeCertificateChain;
 class SignedExchangeDevToolsProxy;
+class SignedExchangeReporter;
 
 // SignedExchangeHandler reads "application/signed-exchange" format from a
 // net::SourceStream, parses and verifies the signed exchange, and reports
@@ -92,6 +93,7 @@
       std::unique_ptr<SignedExchangeCertFetcherFactory> cert_fetcher_factory,
       int load_flags,
       std::unique_ptr<SignedExchangeDevToolsProxy> devtools_proxy,
+      SignedExchangeReporter* reporter,
       base::RepeatingCallback<int(void)> frame_tree_node_id_getter);
   ~SignedExchangeHandler();
 
@@ -152,6 +154,9 @@
 
   std::unique_ptr<SignedExchangeDevToolsProxy> devtools_proxy_;
 
+  // This is owned by SignedExchangeLoader which is the owner of |this|.
+  SignedExchangeReporter* reporter_;
+
   base::RepeatingCallback<int(void)> frame_tree_node_id_getter_;
 
   base::TimeTicks cert_fetch_start_time_;
diff --git a/content/browser/web_package/signed_exchange_handler_unittest.cc b/content/browser/web_package/signed_exchange_handler_unittest.cc
index f2b83405..b7b7df4d 100644
--- a/content/browser/web_package/signed_exchange_handler_unittest.cc
+++ b/content/browser/web_package/signed_exchange_handler_unittest.cc
@@ -93,7 +93,8 @@
       const GURL& cert_url,
       bool force_fetch,
       SignedExchangeCertFetcher::CertificateCallback callback,
-      SignedExchangeDevToolsProxy* devtools_proxy) override {
+      SignedExchangeDevToolsProxy* devtools_proxy,
+      SignedExchangeReporter* reporter) override {
     EXPECT_EQ(cert_url, expected_cert_url_);
 
     auto cert_chain = SignedExchangeCertificateChain::Parse(
@@ -270,7 +271,8 @@
         base::BindOnce(&SignedExchangeHandlerTest::OnHeaderFound,
                        base::Unretained(this)),
         std::move(cert_fetcher_factory_), net::LOAD_NORMAL,
-        nullptr /* devtools_proxy */, base::RepeatingCallback<int(void)>());
+        nullptr /* devtools_proxy */, nullptr /* reporter */,
+        base::RepeatingCallback<int(void)>());
   }
 
   void WaitForHeader() {
diff --git a/content/browser/web_package/signed_exchange_loader.cc b/content/browser/web_package/signed_exchange_loader.cc
index a6f9be0..1ef0ab54 100644
--- a/content/browser/web_package/signed_exchange_loader.cc
+++ b/content/browser/web_package/signed_exchange_loader.cc
@@ -17,6 +17,7 @@
 #include "content/browser/web_package/signed_exchange_devtools_proxy.h"
 #include "content/browser/web_package/signed_exchange_handler.h"
 #include "content/browser/web_package/signed_exchange_prefetch_metric_recorder.h"
+#include "content/browser/web_package/signed_exchange_reporter.h"
 #include "content/browser/web_package/signed_exchange_utils.h"
 #include "content/public/common/content_features.h"
 #include "content/public/common/origin_util.h"
@@ -116,6 +117,7 @@
     uint32_t url_loader_options,
     bool should_redirect_on_failure,
     std::unique_ptr<SignedExchangeDevToolsProxy> devtools_proxy,
+    std::unique_ptr<SignedExchangeReporter> reporter,
     scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
     URLLoaderThrottlesGetter url_loader_throttles_getter,
     base::RepeatingCallback<int(void)> frame_tree_node_id_getter,
@@ -129,6 +131,7 @@
       url_loader_options_(url_loader_options),
       should_redirect_on_failure_(should_redirect_on_failure),
       devtools_proxy_(std::move(devtools_proxy)),
+      reporter_(std::move(reporter)),
       url_loader_factory_(std::move(url_loader_factory)),
       url_loader_throttles_getter_(std::move(url_loader_throttles_getter)),
       frame_tree_node_id_getter_(frame_tree_node_id_getter),
@@ -224,7 +227,7 @@
       base::BindOnce(&SignedExchangeLoader::OnHTTPExchangeFound,
                      weak_factory_.GetWeakPtr()),
       std::move(cert_fetcher_factory), outer_request_.load_flags,
-      std::move(devtools_proxy_), frame_tree_node_id_getter_);
+      std::move(devtools_proxy_), reporter_.get(), frame_tree_node_id_getter_);
 }
 
 void SignedExchangeLoader::OnComplete(
@@ -284,6 +287,9 @@
   }
 
   if (error) {
+    DCHECK_NE(result, SignedExchangeLoadResult::kSuccess);
+    if (reporter_)
+      reporter_->ReportResult(result);
     if (error != net::ERR_INVALID_SIGNED_EXCHANGE ||
         !should_redirect_on_failure_ || !request_url.is_valid()) {
       // Let the request fail.
@@ -302,6 +308,7 @@
     forwarding_client_.reset();
     return;
   }
+  DCHECK_EQ(result, SignedExchangeLoadResult::kSuccess);
   inner_request_url_ = request_url;
 
   DCHECK(outer_response_timing_info_);
@@ -365,6 +372,13 @@
   if (!encoded_data_length_ || !decoded_body_read_result_)
     return;
 
+  if (reporter_) {
+    reporter_->ReportResult(
+        *decoded_body_read_result_ == net::OK
+            ? SignedExchangeLoadResult::kSuccess
+            : SignedExchangeLoadResult::kMerkleIntegrityError);
+  }
+
   // TODO(https://crbug.com/803774): Fill the data length information (
   // encoded_body_length, decoded_body_length) too.
   network::URLLoaderCompletionStatus status;
diff --git a/content/browser/web_package/signed_exchange_loader.h b/content/browser/web_package/signed_exchange_loader.h
index 475750e4..6611a9b 100644
--- a/content/browser/web_package/signed_exchange_loader.h
+++ b/content/browser/web_package/signed_exchange_loader.h
@@ -5,6 +5,9 @@
 #ifndef CONTENT_BROWSER_WEB_PACKAGE_SIGNED_EXCHANGE_LOADER_H_
 #define CONTENT_BROWSER_WEB_PACKAGE_SIGNED_EXCHANGE_LOADER_H_
 
+#include <memory>
+#include <string>
+
 #include "base/callback.h"
 #include "base/optional.h"
 #include "base/unguessable_token.h"
@@ -32,6 +35,7 @@
 class SignedExchangeHandler;
 class SignedExchangeHandlerFactory;
 class SignedExchangePrefetchMetricRecorder;
+class SignedExchangeReporter;
 class URLLoaderThrottle;
 class SourceStreamToDataPipe;
 
@@ -57,6 +61,7 @@
       uint32_t url_loader_options,
       bool should_redirect_on_failure,
       std::unique_ptr<SignedExchangeDevToolsProxy> devtools_proxy,
+      std::unique_ptr<SignedExchangeReporter> reporter,
       scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
       URLLoaderThrottlesGetter url_loader_throttles_getter,
       base::RepeatingCallback<int(void)> frame_tree_node_id_getter,
@@ -149,6 +154,7 @@
   const uint32_t url_loader_options_;
   const bool should_redirect_on_failure_;
   std::unique_ptr<SignedExchangeDevToolsProxy> devtools_proxy_;
+  std::unique_ptr<SignedExchangeReporter> reporter_;
   scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
   URLLoaderThrottlesGetter url_loader_throttles_getter_;
   base::RepeatingCallback<int(void)> frame_tree_node_id_getter_;
diff --git a/content/browser/web_package/signed_exchange_loader_unittest.cc b/content/browser/web_package/signed_exchange_loader_unittest.cc
index 0d90bd74..beb530d 100644
--- a/content/browser/web_package/signed_exchange_loader_unittest.cc
+++ b/content/browser/web_package/signed_exchange_loader_unittest.cc
@@ -13,6 +13,7 @@
 #include "content/browser/web_package/mock_signed_exchange_handler.h"
 #include "content/browser/web_package/signed_exchange_devtools_proxy.h"
 #include "content/browser/web_package/signed_exchange_prefetch_metric_recorder.h"
+#include "content/browser/web_package/signed_exchange_reporter.h"
 #include "mojo/public/cpp/bindings/binding.h"
 #include "mojo/public/cpp/system/string_data_pipe_producer.h"
 #include "net/http/http_status_code.h"
@@ -115,7 +116,7 @@
           resource_request, response, std::move(client), std::move(endpoints),
           network::mojom::kURLLoadOptionNone,
           false /* should_redirect_to_fallback */, nullptr /* devtools_proxy */,
-          nullptr /* url_loader_factory */,
+          nullptr /* reporter */, nullptr /* url_loader_factory */,
           SignedExchangeLoader::URLLoaderThrottlesGetter(),
           base::RepeatingCallback<int(void)>(), nullptr /* metric_recorder */);
 
diff --git a/content/browser/web_package/signed_exchange_prefetch_handler.cc b/content/browser/web_package/signed_exchange_prefetch_handler.cc
index 8682c8d..74e7de7 100644
--- a/content/browser/web_package/signed_exchange_prefetch_handler.cc
+++ b/content/browser/web_package/signed_exchange_prefetch_handler.cc
@@ -9,6 +9,7 @@
 #include "content/browser/web_package/signed_exchange_devtools_proxy.h"
 #include "content/browser/web_package/signed_exchange_loader.h"
 #include "content/browser/web_package/signed_exchange_prefetch_metric_recorder.h"
+#include "content/browser/web_package/signed_exchange_reporter.h"
 #include "content/browser/web_package/signed_exchange_url_loader_factory_for_non_network_service.h"
 #include "content/public/common/content_features.h"
 #include "mojo/public/cpp/bindings/strong_binding.h"
@@ -54,6 +55,9 @@
           resource_request.url, response, frame_tree_node_id_getter,
           base::nullopt /* devtools_navigation_token */,
           resource_request.report_raw_headers),
+      SignedExchangeReporter::MaybeCreate(resource_request.url,
+                                          resource_request.referrer.spec(),
+                                          response, frame_tree_node_id_getter),
       std::move(url_loader_factory), loader_throttles_getter,
       frame_tree_node_id_getter, std::move(metric_recorder));
 }
diff --git a/content/browser/web_package/signed_exchange_reporter.cc b/content/browser/web_package/signed_exchange_reporter.cc
new file mode 100644
index 0000000..f49859f
--- /dev/null
+++ b/content/browser/web_package/signed_exchange_reporter.cc
@@ -0,0 +1,65 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/web_package/signed_exchange_reporter.h"
+
+#include <string>
+#include <utility>
+
+#include "base/callback.h"
+#include "base/feature_list.h"
+#include "base/memory/ptr_util.h"
+#include "content/public/common/content_features.h"
+#include "services/network/public/cpp/features.h"
+#include "services/network/public/cpp/resource_response.h"
+
+namespace content {
+
+// static
+std::unique_ptr<SignedExchangeReporter> SignedExchangeReporter::MaybeCreate(
+    const GURL& outer_url,
+    const std::string& referrer,
+    const network::ResourceResponseHead& response,
+    base::OnceCallback<int(void)> frame_tree_node_id_getter) {
+  if (!base::FeatureList::IsEnabled(network::features::kReporting) ||
+      !base::FeatureList::IsEnabled(
+          features::kSignedExchangeReportingForDistributors)) {
+    return nullptr;
+  }
+  return base::WrapUnique(new SignedExchangeReporter(
+      outer_url, referrer, response, std::move(frame_tree_node_id_getter)));
+}
+
+SignedExchangeReporter::SignedExchangeReporter(
+    const GURL& outer_url,
+    const std::string& referrer,
+    const network::ResourceResponseHead& response,
+    base::OnceCallback<int(void)> frame_tree_node_id_getter)
+    : outer_url_(outer_url),
+      referrer_(referrer),
+      server_ip_(response.socket_address.host()),
+      status_code_(response.headers ? response.headers->response_code() : 0),
+      frame_tree_node_id_getter_(std::move(frame_tree_node_id_getter)) {}
+
+SignedExchangeReporter::~SignedExchangeReporter() = default;
+
+void SignedExchangeReporter::set_cert_server_ip(
+    const std::string& cert_server_ip) {
+  cert_server_ip_ = cert_server_ip;
+}
+
+void SignedExchangeReporter::set_inner_url(const GURL& inner_url) {
+  inner_url_ = inner_url;
+}
+
+void SignedExchangeReporter::set_cert_url(const GURL& cert_url) {
+  cert_url_ = cert_url;
+}
+
+void SignedExchangeReporter::ReportResult(SignedExchangeLoadResult result) {
+  // TODO(910516):Implement this. |frame_tree_node_id_getter_| will be used
+  // to get mojom::NetworkContext and call a method to queue the report.
+}
+
+}  // namespace content
diff --git a/content/browser/web_package/signed_exchange_reporter.h b/content/browser/web_package/signed_exchange_reporter.h
new file mode 100644
index 0000000..4373e4e
--- /dev/null
+++ b/content/browser/web_package/signed_exchange_reporter.h
@@ -0,0 +1,60 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_WEB_PACKAGE_SIGNED_EXCHANGE_REPORTER_H_
+#define CONTENT_BROWSER_WEB_PACKAGE_SIGNED_EXCHANGE_REPORTER_H_
+
+#include <memory>
+#include <string>
+
+#include "base/callback.h"
+#include "base/macros.h"
+#include "content/browser/web_package/signed_exchange_error.h"
+#include "content/common/content_export.h"
+#include "url/gurl.h"
+
+namespace network {
+struct ResourceResponseHead;
+}  // namespace network
+
+namespace content {
+
+class CONTENT_EXPORT SignedExchangeReporter {
+ public:
+  static std::unique_ptr<SignedExchangeReporter> MaybeCreate(
+      const GURL& outer_url,
+      const std::string& referrer,
+      const network::ResourceResponseHead& response,
+      base::OnceCallback<int(void)> frame_tree_node_id_getter);
+
+  ~SignedExchangeReporter();
+
+  void set_cert_server_ip(const std::string& cert_server_ip);
+  void set_inner_url(const GURL& inner_url);
+  void set_cert_url(const GURL& cert_url);
+
+  void ReportResult(SignedExchangeLoadResult result);
+
+ private:
+  SignedExchangeReporter(
+      const GURL& outer_url,
+      const std::string& referrer,
+      const network::ResourceResponseHead& response,
+      base::OnceCallback<int(void)> frame_tree_node_id_getter);
+
+  const GURL outer_url_;
+  const std::string referrer_;
+  const std::string server_ip_;
+  const int status_code_;
+  base::OnceCallback<int(void)> frame_tree_node_id_getter_;
+  std::string cert_server_ip_;
+  GURL inner_url_;
+  GURL cert_url_;
+
+  DISALLOW_COPY_AND_ASSIGN(SignedExchangeReporter);
+};
+
+}  // namespace content
+
+#endif  // CONTENT_BROWSER_WEB_PACKAGE_SIGNED_EXCHANGE_REPORTER_H_
diff --git a/content/browser/web_package/signed_exchange_request_handler.cc b/content/browser/web_package/signed_exchange_request_handler.cc
index 6e50dee..1705b36 100644
--- a/content/browser/web_package/signed_exchange_request_handler.cc
+++ b/content/browser/web_package/signed_exchange_request_handler.cc
@@ -11,6 +11,7 @@
 #include "content/browser/web_package/signed_exchange_devtools_proxy.h"
 #include "content/browser/web_package/signed_exchange_loader.h"
 #include "content/browser/web_package/signed_exchange_prefetch_metric_recorder.h"
+#include "content/browser/web_package/signed_exchange_reporter.h"
 #include "content/browser/web_package/signed_exchange_utils.h"
 #include "content/common/throttling_url_loader.h"
 #include "content/public/common/content_features.h"
@@ -90,6 +91,9 @@
   network::mojom::URLLoaderClientPtr client;
   *client_request = mojo::MakeRequest(&client);
 
+  base::RepeatingCallback<int(void)> frame_tree_node_id_getter =
+      base::BindRepeating([](int id) { return id; }, frame_tree_node_id_);
+
   // This lets the SignedExchangeLoader directly returns an artificial redirect
   // to the downstream client without going through ThrottlingURLLoader, which
   // means some checks like SafeBrowsing may not see the redirect. Given that
@@ -99,12 +103,12 @@
       request, response, std::move(client), url_loader->Unbind(),
       url_loader_options_, true /* should_redirect_to_fallback */,
       std::make_unique<SignedExchangeDevToolsProxy>(
-          request.url, response,
-          base::BindRepeating([](int id) { return id; }, frame_tree_node_id_),
+          request.url, response, frame_tree_node_id_getter,
           devtools_navigation_token_, request.report_raw_headers),
+      SignedExchangeReporter::MaybeCreate(request.url, request.referrer.spec(),
+                                          response, frame_tree_node_id_getter),
       url_loader_factory_, url_loader_throttles_getter_,
-      base::BindRepeating([](int id) { return id; }, frame_tree_node_id_),
-      metric_recorder_);
+      frame_tree_node_id_getter, metric_recorder_);
 
   *skip_other_interceptors = true;
   return true;
diff --git a/content/renderer/BUILD.gn b/content/renderer/BUILD.gn
index 14f9f2e2..cb92cfa 100644
--- a/content/renderer/BUILD.gn
+++ b/content/renderer/BUILD.gn
@@ -560,6 +560,8 @@
     "web_ui_extension_data.h",
     "webgraphicscontext3d_provider_impl.cc",
     "webgraphicscontext3d_provider_impl.h",
+    "worker/dedicated_worker_host_factory_client.cc",
+    "worker/dedicated_worker_host_factory_client.h",
     "worker/embedded_shared_worker_stub.cc",
     "worker/embedded_shared_worker_stub.h",
     "worker/shared_worker_factory_impl.cc",
diff --git a/content/renderer/compositor/layer_tree_view.cc b/content/renderer/compositor/layer_tree_view.cc
index d55fa923..8192b7f7 100644
--- a/content/renderer/compositor/layer_tree_view.cc
+++ b/content/renderer/compositor/layer_tree_view.cc
@@ -573,6 +573,16 @@
 
 void LayerTreeView::DidBeginMainFrame() {}
 
+void LayerTreeView::DidUpdateLayers() {
+  // Dump property trees and layers if run with:
+  //   --vmodule=layer_tree_view=3
+  VLOG(3) << "After updating layers:\n"
+          << "property trees:\n"
+          << layer_tree_host_->property_trees()->ToString() << "\n"
+          << "cc::Layers:\n"
+          << layer_tree_host_->LayersAsString();
+}
+
 void LayerTreeView::BeginMainFrame(const viz::BeginFrameArgs& args) {
   web_main_thread_scheduler_->WillBeginFrame(args);
   delegate_->BeginMainFrame(args.frame_time);
diff --git a/content/renderer/compositor/layer_tree_view.h b/content/renderer/compositor/layer_tree_view.h
index fbadffa..417e073 100644
--- a/content/renderer/compositor/layer_tree_view.h
+++ b/content/renderer/compositor/layer_tree_view.h
@@ -185,6 +185,7 @@
   // cc::LayerTreeHostClient implementation.
   void WillBeginMainFrame() override;
   void DidBeginMainFrame() override;
+  void DidUpdateLayers() override;
   void BeginMainFrame(const viz::BeginFrameArgs& args) override;
   void BeginMainFrameNotExpectedSoon() override;
   void BeginMainFrameNotExpectedUntil(base::TimeTicks time) override;
diff --git a/content/renderer/renderer_blink_platform_impl.cc b/content/renderer/renderer_blink_platform_impl.cc
index e258a9b..0456ed1 100644
--- a/content/renderer/renderer_blink_platform_impl.cc
+++ b/content/renderer/renderer_blink_platform_impl.cc
@@ -66,6 +66,7 @@
 #include "content/renderer/storage_util.h"
 #include "content/renderer/web_database_observer_impl.h"
 #include "content/renderer/webgraphicscontext3d_provider_impl.h"
+#include "content/renderer/worker/dedicated_worker_host_factory_client.h"
 #include "content/renderer/worker/worker_thread_registry.h"
 #include "device/gamepad/public/cpp/gamepads.h"
 #include "gpu/command_buffer/client/gles2_interface.h"
@@ -1037,6 +1038,14 @@
 
 //------------------------------------------------------------------------------
 
+std::unique_ptr<blink::WebDedicatedWorkerHostFactoryClient>
+RendererBlinkPlatformImpl::CreateDedicatedWorkerHostFactoryClient(
+    blink::WebDedicatedWorker* worker,
+    service_manager::InterfaceProvider* interface_provider) {
+  return std::make_unique<DedicatedWorkerHostFactoryClient>(worker,
+                                                            interface_provider);
+}
+
 void RendererBlinkPlatformImpl::DidStartWorkerThread() {
   WorkerThreadRegistry::Instance()->DidStartCurrentWorkerThread();
 }
diff --git a/content/renderer/renderer_blink_platform_impl.h b/content/renderer/renderer_blink_platform_impl.h
index a65c2138..02a9681 100644
--- a/content/renderer/renderer_blink_platform_impl.h
+++ b/content/renderer/renderer_blink_platform_impl.h
@@ -201,6 +201,10 @@
                     const blink::WebString& sample) override;
   void RecordRapporURL(const char* metric, const blink::WebURL& url) override;
   blink::WebPushProvider* PushProvider() override;
+  std::unique_ptr<blink::WebDedicatedWorkerHostFactoryClient>
+  CreateDedicatedWorkerHostFactoryClient(
+      blink::WebDedicatedWorker*,
+      service_manager::InterfaceProvider*) override;
   void DidStartWorkerThread() override;
   void WillStopWorkerThread() override;
   void WorkerContextCreated(const v8::Local<v8::Context>& worker) override;
diff --git a/content/renderer/service_worker/service_worker_network_provider_for_service_worker.cc b/content/renderer/service_worker/service_worker_network_provider_for_service_worker.cc
index 689f771..c2ff0feb 100644
--- a/content/renderer/service_worker/service_worker_network_provider_for_service_worker.cc
+++ b/content/renderer/service_worker/service_worker_network_provider_for_service_worker.cc
@@ -6,7 +6,6 @@
 
 #include <utility>
 
-#include "base/debug/alias.h"
 #include "content/public/common/resource_type.h"
 #include "content/public/renderer/url_loader_throttle_provider.h"
 #include "content/renderer/loader/request_extra_data.h"
@@ -18,23 +17,9 @@
 #include "third_party/blink/public/common/service_worker/service_worker_utils.h"
 #include "third_party/blink/public/platform/web_url.h"
 #include "third_party/blink/public/platform/web_url_request.h"
-#include "url/gurl.h"
 
 namespace content {
 
-namespace {
-
-// TODO(https://crbug.com/929042): Remove this after the linked bug is fixed.
-void CrashBecauseNotMainScriptRequest(const blink::WebURLRequest& request) {
-  GURL url(request.Url());
-  DEBUG_ALIAS_FOR_GURL(url_buf, url);
-  blink::mojom::RequestContextType context = request.GetRequestContext();
-  base::debug::Alias(&context);
-  CHECK(false);
-}
-
-}  // namespace
-
 ServiceWorkerNetworkProviderForServiceWorker::
     ServiceWorkerNetworkProviderForServiceWorker(
         int provider_id,
@@ -48,9 +33,6 @@
 
 void ServiceWorkerNetworkProviderForServiceWorker::WillSendRequest(
     blink::WebURLRequest& request) {
-  ResourceType resource_type = WebURLRequestToResourceType(request);
-  DCHECK_EQ(resource_type, ResourceType::RESOURCE_TYPE_SERVICE_WORKER);
-
   auto extra_data = std::make_unique<RequestExtraData>();
   extra_data->set_service_worker_provider_id(provider_id_);
   extra_data->set_originated_from_service_worker(true);
@@ -64,7 +46,7 @@
   if (render_thread && render_thread->url_loader_throttle_provider()) {
     extra_data->set_url_loader_throttles(
         render_thread->url_loader_throttle_provider()->CreateThrottles(
-            MSG_ROUTING_NONE, request, resource_type));
+            MSG_ROUTING_NONE, request, WebURLRequestToResourceType(request)));
   }
 
   request.SetExtraData(std::move(extra_data));
@@ -75,16 +57,15 @@
     const blink::WebURLRequest& request,
     std::unique_ptr<blink::scheduler::WebResourceLoadingTaskRunnerHandle>
         task_runner_handle) {
-  // We only get here for the main script request from the shadow page.
-  // importScripts() and other subresource fetches are handled on the worker
-  // thread by ServiceWorkerFetchContextImpl.
   if (request.GetRequestContext() !=
       blink::mojom::RequestContextType::SERVICE_WORKER) {
-    CrashBecauseNotMainScriptRequest(request);
+    // This provider is only used for requests from the shadow page, which is
+    // created to load the service worker's main script. But shadow pages
+    // sometimes request strange things like CSS resources because consumers
+    // think it's a real frame. Just return nullptr to use the default loader
+    // instead of the script loader.
     return nullptr;
   }
-  DCHECK_EQ(blink::mojom::RequestContextType::SERVICE_WORKER,
-            request.GetRequestContext());
 
   RenderThreadImpl* render_thread = RenderThreadImpl::current();
   // RenderThreadImpl may be null in some tests.
diff --git a/content/renderer/worker/dedicated_worker_host_factory_client.cc b/content/renderer/worker/dedicated_worker_host_factory_client.cc
new file mode 100644
index 0000000..052018e0
--- /dev/null
+++ b/content/renderer/worker/dedicated_worker_host_factory_client.cc
@@ -0,0 +1,68 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/renderer/worker/dedicated_worker_host_factory_client.h"
+
+#include <utility>
+#include "content/renderer/loader/navigation_response_override_parameters.h"
+#include "third_party/blink/public/common/features.h"
+#include "third_party/blink/public/mojom/blob/blob_url_store.mojom.h"
+#include "third_party/blink/public/mojom/service_worker/controller_service_worker.mojom.h"
+#include "third_party/blink/public/mojom/service_worker/service_worker_provider.mojom.h"
+#include "third_party/blink/public/mojom/worker/worker_main_script_load_params.mojom.h"
+#include "third_party/blink/public/platform/web_dedicated_worker.h"
+
+namespace content {
+
+DedicatedWorkerHostFactoryClient::DedicatedWorkerHostFactoryClient(
+    blink::WebDedicatedWorker* worker,
+    service_manager::InterfaceProvider* interface_provider)
+    : worker_(worker), binding_(this) {
+  DCHECK(blink::features::IsPlzDedicatedWorkerEnabled());
+  DCHECK(interface_provider);
+  interface_provider->GetInterface(mojo::MakeRequest(&factory_));
+}
+
+DedicatedWorkerHostFactoryClient::~DedicatedWorkerHostFactoryClient() = default;
+
+void DedicatedWorkerHostFactoryClient::CreateWorkerHost(
+    const blink::WebURL& script_url,
+    const blink::WebSecurityOrigin& script_origin,
+    mojo::ScopedMessagePipeHandle blob_url_token) {
+  DCHECK(blink::features::IsPlzDedicatedWorkerEnabled());
+  blink::mojom::DedicatedWorkerHostFactoryClientPtr client_ptr;
+  binding_.Bind(mojo::MakeRequest(&client_ptr));
+
+  factory_->CreateAndStartLoad(
+      script_url, script_origin,
+      blink::mojom::BlobURLTokenPtr(blink::mojom::BlobURLTokenPtrInfo(
+          std::move(blob_url_token), blink::mojom::BlobURLToken::Version_)),
+      std::move(client_ptr));
+}
+
+void DedicatedWorkerHostFactoryClient::OnWorkerHostCreated(
+    service_manager::mojom::InterfaceProviderPtr interface_provider) {
+  worker_->OnWorkerHostCreated(interface_provider.PassInterface().PassHandle());
+}
+
+void DedicatedWorkerHostFactoryClient::OnScriptLoaded(
+    blink::mojom::ServiceWorkerProviderInfoForWorkerPtr
+        service_worker_provider_info,
+    blink::mojom::WorkerMainScriptLoadParamsPtr main_script_load_params,
+    std::unique_ptr<blink::URLLoaderFactoryBundleInfo>
+        subresource_loader_factory_bundle_info,
+    blink::mojom::ControllerServiceWorkerInfoPtr controller_info) {
+  DCHECK(blink::features::IsPlzDedicatedWorkerEnabled());
+  // TODO(nhiroki): Keep the given values for creating
+  // WebWorkerFetchContextImpl.
+  worker_->OnScriptLoaded();
+}
+
+void DedicatedWorkerHostFactoryClient::OnScriptLoadFailed() {
+  DCHECK(blink::features::IsPlzDedicatedWorkerEnabled());
+  worker_->OnScriptLoadFailed();
+  // |this| may be destroyed at this point.
+}
+
+}  // namespace content
diff --git a/content/renderer/worker/dedicated_worker_host_factory_client.h b/content/renderer/worker/dedicated_worker_host_factory_client.h
new file mode 100644
index 0000000..74330b6
--- /dev/null
+++ b/content/renderer/worker/dedicated_worker_host_factory_client.h
@@ -0,0 +1,62 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_RENDERER_WORKER_DEDICATED_WORKER_HOST_FACTORY_CLIENT_H_
+#define CONTENT_RENDERER_WORKER_DEDICATED_WORKER_HOST_FACTORY_CLIENT_H_
+
+#include <memory>
+#include "mojo/public/cpp/bindings/binding.h"
+#include "services/service_manager/public/cpp/interface_provider.h"
+#include "third_party/blink/public/mojom/worker/dedicated_worker_host_factory.mojom.h"
+#include "third_party/blink/public/platform/web_dedicated_worker_host_factory_client.h"
+
+namespace blink {
+class WebDedicatedWorker;
+}  // namespace blink
+
+namespace content {
+
+// PlzDedicatedWorker:
+// DedicatedWorkerHostFactoryClient intermediates between
+// blink::(Web)DedicatedWorker and content::DedicatedWorkerHostFactory. This
+// is bound with the thread where the execution context creating this worker
+// lives (i.e., the main thread or a worker thread for nested workers). This is
+// owned by blink::(Web)DedicatedWorker.
+class DedicatedWorkerHostFactoryClient final
+    : public blink::WebDedicatedWorkerHostFactoryClient,
+      public blink::mojom::DedicatedWorkerHostFactoryClient {
+ public:
+  DedicatedWorkerHostFactoryClient(
+      blink::WebDedicatedWorker* worker,
+      service_manager::InterfaceProvider* interface_provider);
+  ~DedicatedWorkerHostFactoryClient() override;
+
+  // Implements blink::WebDedicatedWorkerHostFactoryClient.
+  void CreateWorkerHost(const blink::WebURL& script_url,
+                        const blink::WebSecurityOrigin& script_origin,
+                        mojo::ScopedMessagePipeHandle blob_url_token) override;
+
+ private:
+  // Implements blink::mojom::DedicatedWorkerHostFactoryClient.
+  void OnWorkerHostCreated(
+      service_manager::mojom::InterfaceProviderPtr interface_provider) override;
+  void OnScriptLoaded(
+      blink::mojom::ServiceWorkerProviderInfoForWorkerPtr
+          service_worker_provider_info,
+      blink::mojom::WorkerMainScriptLoadParamsPtr main_script_load_params,
+      std::unique_ptr<blink::URLLoaderFactoryBundleInfo>
+          subresource_loader_factory_bundle_info,
+      blink::mojom::ControllerServiceWorkerInfoPtr controller_info) override;
+  void OnScriptLoadFailed() override;
+
+  // |worker_| owns |this|.
+  blink::WebDedicatedWorker* worker_;
+
+  blink::mojom::DedicatedWorkerHostFactoryPtr factory_;
+  mojo::Binding<blink::mojom::DedicatedWorkerHostFactoryClient> binding_;
+};
+
+}  // namespace content
+
+#endif  // CONTENT_RENDERER_WORKER_DEDICATED_WORKER_HOST_FACTORY_CLIENT_H_
diff --git a/content/renderer/worker/web_service_worker_network_provider_impl_for_worker.cc b/content/renderer/worker/web_service_worker_network_provider_impl_for_worker.cc
index 539de29..be31986 100644
--- a/content/renderer/worker/web_service_worker_network_provider_impl_for_worker.cc
+++ b/content/renderer/worker/web_service_worker_network_provider_impl_for_worker.cc
@@ -87,8 +87,6 @@
 
 void WebServiceWorkerNetworkProviderImplForWorker::WillSendRequest(
     blink::WebURLRequest& request) {
-  DCHECK_EQ(blink::mojom::RequestContextType::SHARED_WORKER,
-            request.GetRequestContext());
   auto extra_data = std::make_unique<RequestExtraData>();
   extra_data->set_service_worker_provider_id(provider_id());
   extra_data->set_initiated_in_secure_context(is_secure_context_);
@@ -118,11 +116,15 @@
     const blink::WebURLRequest& request,
     std::unique_ptr<blink::scheduler::WebResourceLoadingTaskRunnerHandle>
         task_runner_handle) {
-  // We only get here for the main script request from the shadow page.
-  // importScripts() and other subresource fetches are handled on the worker
-  // thread by WebWorkerFetchContextImpl.
-  DCHECK_EQ(blink::mojom::RequestContextType::SHARED_WORKER,
-            request.GetRequestContext());
+  if (request.GetRequestContext() !=
+      blink::mojom::RequestContextType::SHARED_WORKER) {
+    // This provider is only used for requests from the shadow page, which is
+    // created to load the shared worker's main script. But shadow pages
+    // sometimes request strange things like CSS resources because consumers
+    // think it's a real frame. Just return nullptr to use the default loader
+    // instead of the script loader.
+    return nullptr;
+  }
 
   // S13nServiceWorker:
   // We only install our own URLLoader if Servicification is enabled.
diff --git a/content/test/data/gpu/pixel_video_mp4_fullsize.html b/content/test/data/gpu/pixel_video_mp4_fullsize.html
new file mode 100644
index 0000000..d052a811
--- /dev/null
+++ b/content/test/data/gpu/pixel_video_mp4_fullsize.html
@@ -0,0 +1,26 @@
+<!DOCTYPE HTML>
+
+<!-- READ BEFORE UPDATING:
+If this test is updated make sure to increment the "revision" value of the
+associated test in content/test/gpu/page_sets/pixel_tests.py. This will ensure
+that the baseline images are regenerated on the next run.
+-->
+
+<html>
+<head>
+<title>MP4 Video test</title>
+<style type="text/css">
+.nomargin {
+  margin: 0px auto;
+}
+</style>
+<script src="pixel_video_test.js"></script>
+</head>
+<body onload="main()">
+<div id="container" style="position:absolute; top:0px; left:0px">
+<video class="nomargin" id="video" width="960" height="540">
+<source src="/media/test/data/four-colors.mp4" type="video/mp4">
+</video>
+</div>
+</body>
+</html>
diff --git a/content/test/data/gpu/pixel_video_test.js b/content/test/data/gpu/pixel_video_test.js
index 0026a858..1ffc1e90 100644
--- a/content/test/data/gpu/pixel_video_test.js
+++ b/content/test/data/gpu/pixel_video_test.js
@@ -4,20 +4,31 @@
 
 var video;
 
+// Some videos are less than 60 fps, so actual video frame presentations
+// could be much less than 30.
+var g_swaps_before_success = 30
+
 function main() {
   video = document.getElementById("video");
   video.loop = true;
-  video.addEventListener('timeupdate', waitForSwapToComplete);
+  video.addEventListener('timeupdate', waitForVideoToPlay);
   video.play();
 }
 
-function waitForSwapToComplete() {
+function waitForVideoToPlay() {
   if (video.currentTime > 0) {
-    video.removeEventListener('timeupdate', waitForSwapToComplete);
-    chrome.gpuBenchmarking.addSwapCompletionEventListener(sendSuccess);
+    video.removeEventListener('timeupdate', waitForVideoToPlay);
+    chrome.gpuBenchmarking.addSwapCompletionEventListener(
+        waitForSwapsToComplete);
   }
 }
 
-function sendSuccess() {
-  domAutomationController.send("SUCCESS");
+function waitForSwapsToComplete() {
+  g_swaps_before_success--;
+  if (g_swaps_before_success > 0) {
+    chrome.gpuBenchmarking.addSwapCompletionEventListener(
+        waitForSwapsToComplete);
+  } else {
+    domAutomationController.send("SUCCESS");
+  }
 }
diff --git a/content/test/data/gpu/pixel_video_underlay_fullsize.html b/content/test/data/gpu/pixel_video_underlay_fullsize.html
new file mode 100644
index 0000000..aec6a577
--- /dev/null
+++ b/content/test/data/gpu/pixel_video_underlay_fullsize.html
@@ -0,0 +1,28 @@
+<!DOCTYPE HTML>
+
+<!-- READ BEFORE UPDATING:
+If this test is updated make sure to increment the "revision" value of the
+associated test in content/test/gpu/page_sets/pixel_tests.py. This will ensure
+that the baseline images are regenerated on the next run.
+-->
+
+<html>
+<head>
+<title>Underlay Video test</title>
+<style type="text/css">
+.nomargin {
+  margin: 0px auto;
+}
+</style>
+<script src="pixel_video_test.js"></script>
+</head>
+<body onload="main()">
+<div id="container" style="position:absolute; top:0px; left:0px">
+<video class="nomargin" id="video" width="960" height="540">
+<source src="/media/test/data/four-colors.mp4" type="video/mp4">
+</video>
+</div>
+<div id="container" class="nomargin" style="position:absolute; top:0px; left:0px; width:30px; height:30px; background-color:black;">
+</div>
+</body>
+</html>
diff --git a/content/test/data/gpu/pixel_video_vp9_fullsize.html b/content/test/data/gpu/pixel_video_vp9_fullsize.html
new file mode 100644
index 0000000..7b4ecde
--- /dev/null
+++ b/content/test/data/gpu/pixel_video_vp9_fullsize.html
@@ -0,0 +1,26 @@
+<!DOCTYPE HTML>
+
+<!-- READ BEFORE UPDATING:
+If this test is updated make sure to increment the "revision" value of the
+associated test in content/test/gpu/page_sets/pixel_tests.py. This will ensure
+that the baseline images are regenerated on the next run.
+-->
+
+<html>
+<head>
+<title>VP9 Video test</title>
+<style type="text/css">
+.nomargin {
+  margin: 0px auto;
+}
+</style>
+<script src="pixel_video_test.js"></script>
+</head>
+<body onload="main()">
+<div id="container" style="position:absolute; top:0px; left:0px">
+<video class="nomargin" id="video" width="960" height="540">
+<source src="/media/test/data/four-colors-vp9.webm" type="video/webm">
+</video>
+</div>
+</body>
+</html>
diff --git a/content/test/gpu/gpu_tests/pixel_test_pages.py b/content/test/gpu/gpu_tests/pixel_test_pages.py
index 7dbb7c3..4f5e41b1 100644
--- a/content/test/gpu/gpu_tests/pixel_test_pages.py
+++ b/content/test/gpu/gpu_tests/pixel_test_pages.py
@@ -1208,6 +1208,11 @@
     'DirectCompositionUnderlays']
   browser_args_YUY2 = browser_args + [
     '--disable-features=DirectCompositionPreferNV12Overlays']
+  browser_args_DXVA = browser_args + [
+    '--disable-features=D3D11VideoDecoder']
+  browser_args_Underlay_DXVA = browser_args + [
+    '--enable-features=DirectCompositionUnderlays',
+    '--disable-features=D3D11VideoDecoder']
 
   tolerance_dc = 3
 
@@ -1251,6 +1256,81 @@
 
     PixelTestPage(
       'pixel_video_mp4.html',
+      base_name + '_DirectComposition_Video_MP4_DXVA',
+      browser_args=browser_args_DXVA,
+      test_rect=[0, 0, 240, 135],
+      revision=0, # Golden image revision is not used
+      expected_colors=[
+        {
+          'comment': 'top left video, yellow',
+          'location': [5, 5],
+          'size': [110, 57],
+          'color': [255, 255, 15],
+          'tolerance': tolerance_dc
+        },
+        {
+          'comment': 'top right video, red',
+          'location': [125, 5],
+          'size': [110, 57],
+          'color': [255, 17, 24],
+          'tolerance': tolerance_dc
+        },
+        {
+          'comment': 'bottom left video, blue',
+          'location': [5, 72],
+          'size': [110, 57],
+          'color': [12, 12, 255],
+          'tolerance': tolerance_dc
+        },
+        {
+          'comment': 'bottom right video, green',
+          'location': [125, 72],
+          'size': [110, 57],
+          'color': [44, 255, 16],
+          'tolerance': tolerance_dc
+        }
+      ]),
+
+    PixelTestPage(
+      'pixel_video_mp4_fullsize.html',
+      base_name + '_DirectComposition_Video_MP4_Fullsize',
+      browser_args=browser_args,
+      test_rect=[0, 0, 960, 540],
+      revision=0, # Golden image revision is not used
+      other_args={'zero_copy': True},
+      expected_colors=[
+        {
+          'comment': 'top left video, yellow',
+          'location': [10, 10],
+          'size': [460, 250],
+          'color': [255, 255, 15],
+          'tolerance': tolerance_dc
+        },
+        {
+          'comment': 'top right video, red',
+          'location': [490, 10],
+          'size': [460, 250],
+          'color': [255, 17, 24],
+          'tolerance': tolerance_dc
+        },
+        {
+          'comment': 'bottom left video, blue',
+          'location': [10, 280],
+          'size': [460, 250],
+          'color': [12, 12, 255],
+          'tolerance': tolerance_dc
+        },
+        {
+          'comment': 'bottom right video, green',
+          'location': [490, 280],
+          'size': [460, 250],
+          'color': [44, 255, 16],
+          'tolerance': tolerance_dc
+        }
+      ]),
+
+    PixelTestPage(
+      'pixel_video_mp4.html',
       base_name + '_DirectComposition_Video_MP4_YUY2',
       test_rect=[0, 0, 240, 135],
       revision=0, # Golden image revision is not used
@@ -1344,6 +1424,7 @@
       test_rect=[0, 0, 427, 240],
       revision=0, # Golden image revision is not used
       browser_args=browser_args,
+      other_args={'video_is_rotated': True},
       expected_colors=[
         {
           'comment': 'outside video content, left side, white',
@@ -1386,8 +1467,7 @@
           'size': [55, 110],
           'color': [12, 12, 255],
           'tolerance': tolerance_dc
-        }],
-      other_args={'video_is_rotated': True}),
+        }]),
 
     PixelTestPage(
       'pixel_video_mp4_four_colors_rot_180.html',
@@ -1395,6 +1475,7 @@
       test_rect=[0, 0, 240, 135],
       revision=0, # Golden image revision is not used
       browser_args=browser_args,
+      other_args={'video_is_rotated': True},
       expected_colors=[
         {
           'comment': 'top left video, green',
@@ -1423,8 +1504,7 @@
           'size': [110, 57],
           'color': [255, 255, 15],
           'tolerance': tolerance_dc
-        }],
-      other_args={'video_is_rotated': True}),
+        }]),
 
     PixelTestPage(
       'pixel_video_mp4_four_colors_rot_270.html',
@@ -1432,6 +1512,7 @@
       test_rect=[0, 0, 427, 240],
       revision=0, # Golden image revision is not used
       browser_args=browser_args,
+      other_args={'video_is_rotated': True},
       expected_colors=[
         {
           'comment': 'outside video content, left side, white',
@@ -1474,8 +1555,7 @@
           'size': [55, 110],
           'color': [255, 17, 24],
           'tolerance': tolerance_dc
-        }],
-      other_args={'video_is_rotated': True}),
+        }]),
 
     PixelTestPage(
       'pixel_video_vp9.html',
@@ -1516,6 +1596,81 @@
 
     PixelTestPage(
       'pixel_video_vp9.html',
+      base_name + '_DirectComposition_Video_VP9_DXVA',
+      browser_args=browser_args_DXVA,
+      test_rect=[0, 0, 240, 135],
+      revision=0, # Golden image revision is not used
+      expected_colors=[
+        {
+          'comment': 'top left video, yellow',
+          'location': [5, 5],
+          'size': [110, 57],
+          'color': [255, 255, 15],
+          'tolerance': tolerance_dc
+        },
+        {
+          'comment': 'top right video, red',
+          'location': [125, 5],
+          'size': [110, 57],
+          'color': [255, 17, 24],
+          'tolerance': tolerance_dc
+        },
+        {
+          'comment': 'bottom left video, blue',
+          'location': [5, 72],
+          'size': [110, 57],
+          'color': [12, 12, 255],
+          'tolerance': tolerance_dc
+        },
+        {
+          'comment': 'bottom right video, green',
+          'location': [125, 72],
+          'size': [110, 57],
+          'color': [44, 255, 16],
+          'tolerance': tolerance_dc
+        }
+      ]),
+
+    PixelTestPage(
+      'pixel_video_vp9_fullsize.html',
+      base_name + '_DirectComposition_Video_VP9_Fullsize',
+      test_rect=[0, 0, 960, 540],
+      revision=0, # Golden image revision is not used
+      browser_args=browser_args,
+      other_args={'zero_copy': True},
+      expected_colors=[
+        {
+          'comment': 'top left video, yellow',
+          'location': [10, 10],
+          'size': [460, 250],
+          'color': [255, 255, 15],
+          'tolerance': tolerance_dc
+        },
+        {
+          'comment': 'top right video, red',
+          'location': [490, 10],
+          'size': [460, 250],
+          'color': [255, 17, 24],
+          'tolerance': tolerance_dc
+        },
+        {
+          'comment': 'bottom left video, blue',
+          'location': [10, 280],
+          'size': [460, 250],
+          'color': [12, 12, 255],
+          'tolerance': tolerance_dc
+        },
+        {
+          'comment': 'bottom right video, green',
+          'location': [490, 280],
+          'size': [460, 250],
+          'color': [44, 255, 16],
+          'tolerance': tolerance_dc
+        }
+      ]),
+
+    PixelTestPage(
+      'pixel_video_vp9.html',
       base_name + '_DirectComposition_Video_VP9_YUY2',
       test_rect=[0, 0, 240, 135],
       revision=0, # Golden image revision is not used
@@ -1597,6 +1752,95 @@
       ]),
 
     PixelTestPage(
+      'pixel_video_underlay.html',
+      base_name + '_DirectComposition_Underlay_DXVA',
+      test_rect=[0, 0, 240, 136],
+      revision=0, # Golden image revision is not used
+      browser_args=browser_args_Underlay_DXVA,
+      expected_colors=[
+        {
+          'comment': 'black top left',
+          'location': [4, 4],
+          'size': [20, 20],
+          'color': [0, 0, 0],
+          'tolerance': tolerance_dc
+        },
+        {
+          'comment': 'yellow top left quadrant',
+          'location': [4, 34],
+          'size': [110, 30],
+          'color': [255, 255, 15],
+          'tolerance': tolerance_dc
+        },
+        {
+          'comment': 'red top right quadrant',
+          'location': [124, 4],
+          'size': [110, 60],
+          'color': [255, 17, 24],
+          'tolerance': tolerance_dc
+        },
+        {
+          'comment': 'blue bottom left quadrant',
+          'location': [4, 72],
+          'size': [110, 60],
+          'color': [12, 12, 255],
+          'tolerance': tolerance_dc
+        },
+        {
+          'comment': 'green bottom right quadrant',
+          'location': [124, 72],
+          'size': [110, 60],
+          'color': [44, 255, 16],
+          'tolerance': tolerance_dc
+        }
+      ]),
+
+    PixelTestPage(
+      'pixel_video_underlay_fullsize.html',
+      base_name + '_DirectComposition_Underlay_Fullsize',
+      test_rect=[0, 0, 960, 540],
+      revision=0, # Golden image revision is not used
+      browser_args=browser_args_Underlay,
+      other_args={'zero_copy': True},
+      expected_colors=[
+        {
+          'comment': 'black top left',
+          'location': [4, 4],
+          'size': [20, 20],
+          'color': [0, 0, 0],
+          'tolerance': tolerance_dc
+        },
+        {
+          'comment': 'yellow top left quadrant',
+          'location': [10, 35],
+          'size': [460, 225],
+          'color': [255, 255, 15],
+          'tolerance': tolerance_dc
+        },
+        {
+          'comment': 'red top right quadrant',
+          'location': [490, 10],
+          'size': [460, 250],
+          'color': [255, 17, 24],
+          'tolerance': tolerance_dc
+        },
+        {
+          'comment': 'blue bottom left quadrant',
+          'location': [10, 280],
+          'size': [460, 250],
+          'color': [12, 12, 255],
+          'tolerance': tolerance_dc
+        },
+        {
+          'comment': 'green bottom right quadrant',
+          'location': [490, 290],
+          'size': [460, 250],
+          'color': [44, 255, 16],
+          'tolerance': tolerance_dc
+        }
+      ]),
+
+    PixelTestPage(
       'pixel_video_nonroot.html',
       base_name + '_DirectComposition_Nonroot',
       test_rect=[0, 0, 240, 136],
@@ -1646,6 +1890,7 @@
       test_rect=[0, 0, 240, 136],
       revision=0, # Golden image revision is not used
       browser_args=browser_args_Complex,
+      other_args={'video_is_rotated': True},
       expected_colors=[
         {
           'comment': 'black top left',
@@ -1681,6 +1926,5 @@
           'size': [65, 30],
           'color': [44, 255, 16],
           'tolerance': tolerance_dc
-        }],
-      other_args={'video_is_rotated': True}),
+        }]),
     ]
diff --git a/content/test/gpu/gpu_tests/screenshot_sync_integration_test.py b/content/test/gpu/gpu_tests/screenshot_sync_integration_test.py
index d088ee6d..ddc8941 100644
--- a/content/test/gpu/gpu_tests/screenshot_sync_integration_test.py
+++ b/content/test/gpu/gpu_tests/screenshot_sync_integration_test.py
@@ -128,7 +128,7 @@
     # It seems that we should be able to set start_x to 2 * inset (one to
     # account for the inner div having left=1 and one to avoid sampling the
     # aa edge). For reasons not fully understood this is insufficent on
-    # several bots (N9, 6P, mac_chromium_rel_ng).
+    # several bots (N9, 6P, mac-rel).
     start_x = 10
     start_y = inset
     outer_size = 256 - inset
diff --git a/content/test/gpu/gpu_tests/trace_integration_test.py b/content/test/gpu/gpu_tests/trace_integration_test.py
index cbf2b5b..fbb3440 100644
--- a/content/test/gpu/gpu_tests/trace_integration_test.py
+++ b/content/test/gpu/gpu_tests/trace_integration_test.py
@@ -80,16 +80,17 @@
 _SWAP_CHAIN_PRESENTATION_MODE_OVERLAY = 1
 _SWAP_CHAIN_PRESENTATION_MODE_NONE = 2
 _SWAP_CHAIN_PRESENTATION_MODE_COMPOSITION_FAILURE = 3
+# The following is defined for Chromium testing internal use.
+_SWAP_CHAIN_GET_FRAME_STATISTICS_MEDIA_FAILED = -1
 
 # Pixel format enums match OverlayFormat in config/gpu/gpu_info.h
 _SWAP_CHAIN_PIXEL_FORMAT_BGRA = 0
 _SWAP_CHAIN_PIXEL_FORMAT_YUY2 = 1
 _SWAP_CHAIN_PIXEL_FORMAT_NV12 = 2
 
-_TEST_MAX_REPEATS = 30
+_GET_STATISTICS_EVENT_NAME = 'GetFrameStatisticsMedia'
+_SWAP_CHAIN_PRESENT_EVENT_NAME = 'SwapChain::Present'
 
-_TEST_DONE = 0 # Test finished, either failed or succeeded
-_TEST_REPEAT = 1 # Test failed, but it's flaky and should run again.
 
 class TraceIntegrationTest(gpu_integration_test.GpuIntegrationTest):
   """Tests GPU traces are plumbed through properly.
@@ -119,20 +120,26 @@
               'test_harness_script': webgl_test_harness_script,
               'finish_js_condition': 'domAutomationController._finished',
               'success_eval_func': 'CheckGLCategory'})
-    for p in pixel_test_pages.DirectCompositionPages('VideoTraceTest'):
-      success_eval_func = 'CheckVideoMode'
-      if (p.other_args is not None and
-          p.other_args.get('video_is_rotated', False)):
-        # On several Intel GPUs we tested that support hardware overlays,
-        # none of them promote a swap chain to hardware overlay if there is
-        # rotation.
-        success_eval_func = 'CheckVideoModeNoOverlay'
+    for p in pixel_test_pages.DirectCompositionPages('VideoPathTraceTest'):
       yield (p.name, gpu_relative_path + p.url,
              {'browser_args': p.browser_args,
               'category': cls._DisabledByDefaultTraceCategory('gpu.service'),
               'test_harness_script': basic_test_harness_script,
               'finish_js_condition': 'domAutomationController._finished',
-              'success_eval_func': success_eval_func})
+              'success_eval_func': 'CheckVideoPath',
+              'other_args': p.other_args})
+    for p in pixel_test_pages.DirectCompositionPages('OverlayModeTraceTest'):
+      if p.other_args and p.other_args.get('video_is_rotated', False):
+        # For all drivers we tested, when a video is rotated, frames won't
+        # be promoted to hardware overlays.
+        continue
+      yield (p.name, gpu_relative_path + p.url,
+             {'browser_args': p.browser_args,
+              'category': cls._DisabledByDefaultTraceCategory('gpu.service'),
+              'test_harness_script': basic_test_harness_script,
+              'finish_js_condition': 'domAutomationController._finished',
+              'success_eval_func': 'CheckOverlayMode',
+              'other_args': p.other_args})
 
   def RunActualGpuTest(self, test_path, *args):
     test_params = args[0]
@@ -145,46 +152,37 @@
     test_harness_script = test_params['test_harness_script']
     finish_js_condition = test_params['finish_js_condition']
     success_eval_func = test_params['success_eval_func']
+    other_args = test_params.get('other_args', None)
 
-    # Maximum repeat a flaky test 30 times
-    for ii in range(_TEST_MAX_REPEATS):
-      if ii > 0:
-        logging.info('Try the test again: #%d', ii + 1)
-      # The version of this test in the old GPU test harness restarted
-      # the browser after each test, so continue to do that to match its
-      # behavior.
-      self.RestartBrowserWithArgs(self._AddDefaultArgs(browser_args))
+    # The version of this test in the old GPU test harness restarted
+    # the browser after each test, so continue to do that to match its
+    # behavior.
+    self.RestartBrowserWithArgs(self._AddDefaultArgs(browser_args))
 
-      # Set up tracing.
-      config = tracing_config.TracingConfig()
-      config.chrome_trace_config.category_filter.AddExcludedCategory('*')
-      config.chrome_trace_config.category_filter.AddDisabledByDefault(category)
-      config.enable_chrome_trace = True
-      tab = self.tab
-      tab.browser.platform.tracing_controller.StartTracing(config, 60)
+    # Set up tracing.
+    config = tracing_config.TracingConfig()
+    config.chrome_trace_config.category_filter.AddExcludedCategory('*')
+    config.chrome_trace_config.category_filter.AddDisabledByDefault(category)
+    config.enable_chrome_trace = True
+    tab = self.tab
+    tab.browser.platform.tracing_controller.StartTracing(config, 60)
 
-      # Perform page navigation.
-      url = self.UrlOfStaticFilePath(test_path)
-      tab.Navigate(url, script_to_evaluate_on_commit=test_harness_script)
-      tab.action_runner.WaitForJavaScriptCondition(
-          finish_js_condition, timeout=30)
+    # Perform page navigation.
+    url = self.UrlOfStaticFilePath(test_path)
+    tab.Navigate(url, script_to_evaluate_on_commit=test_harness_script)
+    tab.action_runner.WaitForJavaScriptCondition(
+        finish_js_condition, timeout=30)
 
-      # Stop tracing.
-      timeline_data = tab.browser.platform.tracing_controller.StopTracing()[0]
+    # Stop tracing.
+    timeline_data = tab.browser.platform.tracing_controller.StopTracing()[0]
 
-      # Evaluate success.
+    # Evaluate success.
+    if success_eval_func:
       timeline_model = model_module.TimelineModel(timeline_data)
       event_iter = timeline_model.IterAllEvents(
           event_type_predicate=timeline_model.IsSliceOrAsyncSlice)
-      test_result = _TEST_DONE
-      if success_eval_func:
-        prefixed_func_name = '_EvaluateSuccess_' + success_eval_func
-        test_result = getattr(self, prefixed_func_name)(category, event_iter)
-        assert test_result in [_TEST_DONE, _TEST_REPEAT]
-      if test_result == _TEST_DONE:
-        break
-    else:
-      self.fail('Test failed all %d tries' % _TEST_MAX_REPEATS)
+      prefixed_func_name = '_EvaluateSuccess_' + success_eval_func
+      getattr(self, prefixed_func_name)(category, event_iter, other_args)
 
   @classmethod
   def _CreateExpectations(cls):
@@ -227,18 +225,6 @@
     return str(pixel_format)
 
   @staticmethod
-  def _SwapChainPixelFormatListToStr(pixel_format_list):
-    assert len(pixel_format_list) > 0
-    list_str = None
-    for pixel_format in pixel_format_list:
-      format_str = TraceIntegrationTest._SwapChainPixelFormatToStr(pixel_format)
-      if list_str is not None:
-        list_str = '%s, %s' % (list_str, format_str)
-      else:
-        list_str = format_str
-    return '[%s]' % list_str
-
-  @staticmethod
   def _SwapChainPresentationModeToStr(presentation_mode):
     if presentation_mode == _SWAP_CHAIN_PRESENTATION_MODE_COMPOSED:
       return 'COMPOSED'
@@ -248,18 +234,19 @@
       return 'NONE'
     if presentation_mode == _SWAP_CHAIN_PRESENTATION_MODE_COMPOSITION_FAILURE:
       return 'COMPOSITION_FAILURE'
+    if presentation_mode == _SWAP_CHAIN_GET_FRAME_STATISTICS_MEDIA_FAILED:
+      return 'GET_STATISTICS_FAILED'
     return str(presentation_mode)
 
   @staticmethod
   def _SwapChainPresentationModeListToStr(presentation_mode_list):
-    assert len(presentation_mode_list) > 0
     list_str = None
     for mode in presentation_mode_list:
       mode_str = TraceIntegrationTest._SwapChainPresentationModeToStr(mode)
-      if list_str is not None:
-        list_str = '%s, %s' % (list_str, mode_str)
-      else:
+      if list_str is None:
         list_str = mode_str
+      else:
+        list_str = '%s,%s' % (list_str, mode_str)
     return '[%s]' % list_str
 
   @staticmethod
@@ -269,27 +256,83 @@
   #########################################
   # The test success evaluation functions
 
-  def _EvaluateSuccess_CheckGLCategory(self, category, event_iterator):
+  def _EvaluateSuccess_CheckGLCategory(self, category, event_iterator,
+                                       other_args):
     for event in event_iterator:
       if (event.category == category and
           event.args.get('gl_category', None) == 'gpu_toplevel'):
         break
     else:
       self.fail('Trace markers for GPU category %s were not found' % category)
-    return _TEST_DONE
 
-  def _EvaluateSuccess_CheckVideoModeYUY2(self, category, event_iterator):
-    return self._CheckVideoModeHelper(category, event_iterator,
-                                      expect_yuy2=True)
+  def _EvaluateSuccess_CheckVideoPath(self, category, event_iterator,
+                                      other_args):
+    """Verifies Chrome goes down the code path as expected.
 
-  def _EvaluateSuccess_CheckVideoModeNoOverlay(self, category, event_iterator):
-    return self._CheckVideoModeHelper(category, event_iterator, no_overlay=True)
+    Depending on whether hardware overlays are supported or not, which formats
+    are supported in overlays, whether video is downscaled or not, whether
+    video is rotated or not, Chrome's video presentation code path can be
+    different.
+    """
+    os_name = self.browser.platform.GetOSName()
+    assert os_name and os_name.lower() == 'win'
 
-  def _EvaluateSuccess_CheckVideoMode(self, category, event_iterator):
-    return self._CheckVideoModeHelper(category, event_iterator)
+    # Calculate expectations.
+    if other_args is None:
+      other_args = {}
+    expect_yuy2 = other_args.get('expect_yuy2', False)
+    zero_copy = other_args.get('zero_copy', False)
 
-  def _CheckVideoModeHelper(self, category, event_iterator, no_overlay=False,
-                            expect_yuy2=False):
+    overlay_bot_config = self.GetOverlayBotConfig()
+    if overlay_bot_config is None:
+      self.fail('Overlay bot config can not be determined')
+    assert overlay_bot_config.get('direct_composition', False)
+
+    expected_pixel_format = _SWAP_CHAIN_PIXEL_FORMAT_NV12
+    supports_nv12_overlays = False
+    if overlay_bot_config.get('supports_overlays', False):
+      supports_yuy2_overlays = False
+      if overlay_bot_config.get('overlay_cap_yuy2', 'NONE') != 'NONE':
+        supports_yuy2_overlays = True
+      if overlay_bot_config.get('overlay_cap_nv12', 'NONE') != 'NONE':
+        supports_nv12_overlays = True
+      assert supports_yuy2_overlays or supports_nv12_overlays
+      if expect_yuy2 or not supports_nv12_overlays:
+        expected_pixel_format = _SWAP_CHAIN_PIXEL_FORMAT_YUY2
+    if not supports_nv12_overlays:
+      zero_copy = False
+
+    # Verify expectations through captured trace events.
+    for event in event_iterator:
+      if event.category != category:
+        continue
+      if event.name != _SWAP_CHAIN_PRESENT_EVENT_NAME:
+        continue
+      detected_pixel_format = event.args.get('PixelFormat', None)
+      if detected_pixel_format is None:
+        self.fail('PixelFormat is missing from event %s' %
+                  _SWAP_CHAIN_PRESENT_EVENT_NAME)
+      if expected_pixel_format != detected_pixel_format:
+        self.fail('SwapChain pixel format mismatch, expected %s got %s' %
+            (TraceIntegrationTest._SwapChainPixelFormatToStr(
+                 expected_pixel_format),
+             TraceIntegrationTest._SwapChainPixelFormatToStr(
+                 detected_pixel_format)))
+      detected_zero_copy = event.args.get('ZeroCopy', None)
+      if detected_zero_copy is None:
+        self.fail('ZeroCopy is missing from event %s' %
+                  _SWAP_CHAIN_PRESENT_EVENT_NAME)
+      if zero_copy != detected_zero_copy:
+        self.fail('ZeroCopy mismatch, expected %s got %s' %
+                  (zero_copy, detected_zero_copy))
+      break
+    else:
+      self.fail('Events with name %s were not found' %
+                _SWAP_CHAIN_PRESENT_EVENT_NAME)
+
+  def _EvaluateSuccess_CheckOverlayMode(self, category, event_iterator,
+                                        other_args):
+    """Verifies video frames are promoted to overlays when supported."""
     os_name = self.browser.platform.GetOSName()
     assert os_name and os_name.lower() == 'win'
 
@@ -298,71 +341,38 @@
       self.fail('Overlay bot config can not be determined')
     assert overlay_bot_config.get('direct_composition', False)
 
-    expected_pixel_format = _SWAP_CHAIN_PIXEL_FORMAT_NV12
     expected_presentation_mode = _SWAP_CHAIN_PRESENTATION_MODE_COMPOSED
     if overlay_bot_config.get('supports_overlays', False):
-      supports_yuy2 = False
-      supports_nv12 = False
-      if overlay_bot_config.get('overlay_cap_yuy2', 'NONE') != 'NONE':
-        supports_yuy2 = True
-      if overlay_bot_config.get('overlay_cap_nv12', 'NONE') != 'NONE':
-        supports_nv12 = True
-      assert supports_yuy2 or supports_nv12
-      if not no_overlay:
-        expected_presentation_mode = _SWAP_CHAIN_PRESENTATION_MODE_OVERLAY
-      if expect_yuy2 or not supports_nv12:
-        expected_pixel_format = _SWAP_CHAIN_PIXEL_FORMAT_YUY2
+      expected_presentation_mode = _SWAP_CHAIN_PRESENTATION_MODE_OVERLAY
 
-    pixel_format_history = []
     presentation_mode_history = []
-    previous_time = None
-    invalid_info_encountered = False
     for event in event_iterator:
       if event.category != category:
         continue
-      if event.name == 'SwapChainFrameInfoInvalid':
-        error_code = event.args.get('ErrorCode', None)
-        if error_code is None:
-          self.fail('ErrorCode is missing from SwapChainFrameInfoInvalid event')
-        invalid_info_encountered = True
-        logging.info('Swap chain presentation stats collection failed: %s',
-                     hex(error_code))
+      if event.name != _GET_STATISTICS_EVENT_NAME:
         continue
-      if event.name != 'SwapChainFrameInfo':
+      detected_presentation_mode = event.args.get('CompositionMode', None)
+      if detected_presentation_mode is None:
+        self.fail('PresentationMode is missing from event %s' %
+                  _GET_STATISTICS_EVENT_NAME)
+      presentation_mode_history.append(detected_presentation_mode)
+    valid_entry_found = False
+    for mode in presentation_mode_history:
+      if (mode == _SWAP_CHAIN_PRESENTATION_MODE_NONE or
+          mode == _SWAP_CHAIN_GET_FRAME_STATISTICS_MEDIA_FAILED):
+        # Be more tolerant to avoid test flakiness
         continue
-      if previous_time is not None:
-        # Sanity check that events are chronically sorted
-        assert previous_time < event.start
-      pixel_format = event.args.get('SwapChain.PixelFormat', None)
-      presentation_mode = event.args.get('SwapChain.PresentationMode', None)
-      if pixel_format is None or presentation_mode is None:
-        self.fail('PixelFormat or PresentationMode is missing from event')
-      pixel_format_history.append(pixel_format)
-      presentation_mode_history.append(presentation_mode)
-      previous_time = event.start
-
-    if len(pixel_format_history) == 0 or len(presentation_mode_history) == 0:
-      # In theory 'supports_overlays' needs to be true to trigger a fail, but
-      # all DirectComposition test pages run with commandline switch
-      # --enable-direct-composition-layers.
-      if invalid_info_encountered:
-        return _TEST_REPEAT
-      self.fail('Trace markers of name SwapChainFrameInfo were not found')
-
-    # The last relevant event is selected.
-    if expected_pixel_format != pixel_format_history[-1]:
-      self.fail('SwapChain pixel format mismatch, expected %s got %s' %
-          (TraceIntegrationTest._SwapChainPixelFormatToStr(
-               expected_pixel_format),
-           TraceIntegrationTest._SwapChainPixelFormatListToStr(
-               pixel_format_history)))
-    if expected_presentation_mode != presentation_mode_history[-1]:
-      self.fail('SwapChain presentation mode mismatch, expected %s got %s' %
-          (TraceIntegrationTest._SwapChainPresentationModeToStr(
-               expected_presentation_mode),
-           TraceIntegrationTest._SwapChainPresentationModeListToStr(
-               presentation_mode_history)))
-    return _TEST_DONE
+      if mode != expected_presentation_mode:
+        self.fail('SwapChain presentation mode mismatch, expected %s got %s' %
+            (TraceIntegrationTest._SwapChainPresentationModeToStr(
+                 expected_presentation_mode),
+             TraceIntegrationTest._SwapChainPresentationModeListToStr(
+                 presentation_mode_history)))
+      valid_entry_found = True
+    if not valid_entry_found:
+      logging.warning('No valid frame statistics being collected: %s',
+          TraceIntegrationTest._SwapChainPresentationModeListToStr(
+              presentation_mode_history))
 
 
 def load_tests(loader, tests, pattern):
diff --git a/content/test/gpu/gpu_tests/trace_test_expectations.py b/content/test/gpu/gpu_tests/trace_test_expectations.py
index 7159b1f3..f0e8943 100644
--- a/content/test/gpu/gpu_tests/trace_test_expectations.py
+++ b/content/test/gpu/gpu_tests/trace_test_expectations.py
@@ -22,8 +22,11 @@
     self.Skip('*_Video_Context_Loss_MP4', ['android'], bug=580386)
 
     # Skip on platforms where DirectComposition isn't supported
-    self.Skip('VideoTraceTest_*',
+    self.Skip('VideoPathTraceTest_*',
+        ['mac', 'linux', 'android', 'chromeos', 'win7'], bug=867136)
+    self.Skip('OverlayModeTraceTest_*',
         ['mac', 'linux', 'android', 'chromeos', 'win7'], bug=867136)
 
-    # Skip until flakiness is resolved.
-    self.Skip('VideoTraceTest_DirectComposition*', ['win10'], bug=928166)
+    # VP9 videos fail to trigger zero copy video presentation path.
+    self.Fail('VideoPathTraceTest_DirectComposition_Video_VP9_Fullsize',
+        ['win', 'intel'], bug=930343)
diff --git a/content/test/navigation_simulator_impl.cc b/content/test/navigation_simulator_impl.cc
index 1b0022c..f0cf1afb 100644
--- a/content/test/navigation_simulator_impl.cc
+++ b/content/test/navigation_simulator_impl.cc
@@ -586,7 +586,7 @@
   auto params = BuildDidCommitProvisionalLoadParams(
       false /* same_document */, false /* failed_navigation */);
   render_frame_host_->SimulateCommitProcessed(
-      handle_->GetNavigationId(), std::move(params),
+      handle_->navigation_request(), std::move(params),
       std::move(interface_provider_request_),
       std::move(document_interface_broker_content_request_),
       std::move(document_interface_broker_blink_request_), same_document_);
@@ -618,7 +618,7 @@
   CHECK(render_frame_host_)
       << "NavigationSimulatorImpl::AbortCommit can only be "
          "called for navigations that commit.";
-  render_frame_host_->AbortCommit(handle_->GetNavigationId());
+  render_frame_host_->AbortCommit(handle_->navigation_request());
 
   state_ = FINISHED;
   CHECK_EQ(1, num_did_finish_navigation_called_);
@@ -704,7 +704,7 @@
   auto params = BuildDidCommitProvisionalLoadParams(
       false /* same_document */, true /* failed_navigation */);
   render_frame_host_->SimulateCommitProcessed(
-      handle_->GetNavigationId(), std::move(params),
+      handle_->navigation_request(), std::move(params),
       std::move(interface_provider_request_),
       std::move(document_interface_broker_content_request_),
       std::move(document_interface_broker_blink_request_),
@@ -740,7 +740,7 @@
   document_interface_broker_blink_request_ = nullptr;
 
   render_frame_host_->SimulateCommitProcessed(
-      handle_ ? handle_->GetNavigationId() : -1, std::move(params),
+      handle_ ? handle_->navigation_request() : nullptr, std::move(params),
       nullptr /* interface_provider_request_ */,
       nullptr /* document_interface_broker_content_handle */,
       nullptr /* document_interface_broker_blink_handle */,
diff --git a/content/test/test_render_frame_host.cc b/content/test/test_render_frame_host.cc
index fdb8d648..1be633a 100644
--- a/content/test/test_render_frame_host.cc
+++ b/content/test/test_render_frame_host.cc
@@ -432,7 +432,7 @@
 }
 
 void TestRenderFrameHost::SimulateCommitProcessed(
-    int64_t navigation_id,
+    NavigationRequest* navigation_request,
     std::unique_ptr<FrameHostMsg_DidCommitProvisionalLoad_Params> params,
     service_manager::mojom::InterfaceProviderRequest interface_provider_request,
     blink::mojom::DocumentInterfaceBrokerRequest
@@ -449,12 +449,13 @@
     // callbacks, no more than 1 callback will ever run, because navigation_id
     // is unique across all callback storages.
     {
-      auto callback_it = commit_callback_.find(navigation_id);
+      auto callback_it = commit_callback_.find(navigation_request);
       if (callback_it != commit_callback_.end())
         std::move(callback_it->second).Run(result);
     }
     {
-      auto callback_it = navigation_client_commit_callback_.find(navigation_id);
+      auto callback_it =
+          navigation_client_commit_callback_.find(navigation_request);
       if (callback_it != navigation_client_commit_callback_.end()) {
         std::move(callback_it->second)
             .Run(std::move(params),
@@ -466,13 +467,13 @@
       }
     }
     {
-      auto callback_it = commit_failed_callback_.find(navigation_id);
+      auto callback_it = commit_failed_callback_.find(navigation_request);
       if (callback_it != commit_failed_callback_.end())
         std::move(callback_it->second).Run(result);
     }
     {
       auto callback_it =
-          navigation_client_commit_failed_callback_.find(navigation_id);
+          navigation_client_commit_failed_callback_.find(navigation_request);
       if (callback_it != navigation_client_commit_failed_callback_.end()) {
         std::move(callback_it->second)
             .Run(std::move(params),
@@ -526,13 +527,11 @@
     const base::UnguessableToken& devtools_navigation_token) {
   if (!navigation_request)
     return;
-  int64_t navigation_id =
-      navigation_request->navigation_handle()->GetNavigationId();
   if (navigation_client) {
-    navigation_client_commit_callback_[navigation_id] =
+    navigation_client_commit_callback_[navigation_request] =
         BuildNavigationClientCommitNavigationCallback(navigation_request);
   } else {
-    commit_callback_[navigation_id] =
+    commit_callback_[navigation_request] =
         BuildCommitNavigationCallback(navigation_request);
   }
 }
@@ -547,15 +546,11 @@
     const base::Optional<std::string>& error_page_content,
     std::unique_ptr<blink::URLLoaderFactoryBundleInfo>
         subresource_loader_factories) {
-  if (!navigation_request)
-    return;
-  int64_t navigation_id =
-      navigation_request->navigation_handle()->GetNavigationId();
   if (navigation_client) {
-    navigation_client_commit_failed_callback_[navigation_id] =
+    navigation_client_commit_failed_callback_[navigation_request] =
         BuildNavigationClientCommitFailedNavigationCallback(navigation_request);
   } else {
-    commit_failed_callback_[navigation_id] =
+    commit_failed_callback_[navigation_request] =
         BuildCommitFailedNavigationCallback(navigation_request);
   }
 }
@@ -648,8 +643,8 @@
   return interface_params;
 }
 
-void TestRenderFrameHost::AbortCommit(int64_t navigation_id) {
-  OnCrossDocumentCommitProcessed(navigation_id,
+void TestRenderFrameHost::AbortCommit(NavigationRequest* navigation_request) {
+  OnCrossDocumentCommitProcessed(navigation_request,
                                  blink::mojom::CommitResult::Aborted);
 }
 
diff --git a/content/test/test_render_frame_host.h b/content/test/test_render_frame_host.h
index 3087b95..73a0a2d 100644
--- a/content/test/test_render_frame_host.h
+++ b/content/test/test_render_frame_host.h
@@ -7,6 +7,7 @@
 
 #include <stdint.h>
 
+#include <map>
 #include <string>
 #include <vector>
 
@@ -165,7 +166,7 @@
   // renderer. If parameters required to commit are not provided, they will be
   // set to default null values.
   void SimulateCommitProcessed(
-      int64_t navigation_id,
+      NavigationRequest* navigation_request,
       std::unique_ptr<FrameHostMsg_DidCommitProvisionalLoad_Params> params,
       service_manager::mojom::InterfaceProviderRequest
           interface_provider_request,
@@ -201,10 +202,10 @@
 
   // This simulates aborting a cross document navigation.
   // Will abort the navigation with the given |navigation_id|.
-  void AbortCommit(int64_t navigation_id);
+  void AbortCommit(NavigationRequest* navigation_request);
 
   // Returns the navigations that are trying to commit.
-  const std::map<int64_t, std::unique_ptr<NavigationRequest>>&
+  const std::map<NavigationRequest*, std::unique_ptr<NavigationRequest>>&
   navigation_requests() {
     return navigation_requests_;
   }
@@ -274,14 +275,17 @@
   // The last commit was for an error page.
   bool last_commit_was_error_page_;
 
-  std::map<int64_t, mojom::FrameNavigationControl::CommitNavigationCallback>
+  std::map<NavigationRequest*,
+           mojom::FrameNavigationControl::CommitNavigationCallback>
       commit_callback_;
-  std::map<int64_t, mojom::NavigationClient::CommitNavigationCallback>
+  std::map<NavigationRequest*,
+           mojom::NavigationClient::CommitNavigationCallback>
       navigation_client_commit_callback_;
-  std::map<int64_t,
+  std::map<NavigationRequest*,
            mojom::FrameNavigationControl::CommitFailedNavigationCallback>
       commit_failed_callback_;
-  std::map<int64_t, mojom::NavigationClient::CommitFailedNavigationCallback>
+  std::map<NavigationRequest*,
+           mojom::NavigationClient::CommitFailedNavigationCallback>
       navigation_client_commit_failed_callback_;
 
   DISALLOW_COPY_AND_ASSIGN(TestRenderFrameHost);
diff --git a/device/bluetooth/bluetooth_adapter_mac.h b/device/bluetooth/bluetooth_adapter_mac.h
index 96e06ee..3c78793 100644
--- a/device/bluetooth/bluetooth_adapter_mac.h
+++ b/device/bluetooth/bluetooth_adapter_mac.h
@@ -106,8 +106,8 @@
   void DeviceConnected(IOBluetoothDevice* device);
 
   // We only use CoreBluetooth when OS X >= 10.10. This because the
-  // CBCentralManager destructor was found to crash on the mac_chromium_rel_ng
-  // builder running 10.9.5. May also cause blued to crash on OS X 10.9.5
+  // CBCentralManager destructor was found to crash on the mac-rel builder
+  // running 10.9.5. May also cause blued to crash on OS X 10.9.5
   // (crbug.com/506287).
   static bool IsLowEnergyAvailable();
 
diff --git a/device/bluetooth/test/fake_peripheral.cc b/device/bluetooth/test/fake_peripheral.cc
index 7e52f80..d9305f3 100644
--- a/device/bluetooth/test/fake_peripheral.cc
+++ b/device/bluetooth/test/fake_peripheral.cc
@@ -45,7 +45,7 @@
   // GattServiceMap even though it only uses the UUIDs.
   int count = 0;
   for (const auto& uuid : service_uuids) {
-    std::string id = base::IntToString(count++);
+    std::string id = base::NumberToString(count++);
     std::tie(std::ignore, inserted) =
         gatt_services.emplace(id, std::make_unique<FakeRemoteGattService>(
                                       id, uuid, /*is_primary=*/true, this));
diff --git a/docs/closure_compilation.md b/docs/closure_compilation.md
index 4ae3688..2cfd9e8 100644
--- a/docs/closure_compilation.md
+++ b/docs/closure_compilation.md
@@ -170,7 +170,7 @@
 From the command line, you try your change with:
 
 ```shell
-git cl try -b linux_chromium_rel_ng
+git cl try -b linux-rel
 ```
 
 ## Integrating with the continuous build
diff --git a/docs/gpu/gpu_testing.md b/docs/gpu/gpu_testing.md
index 69eac24f..86adc8e 100644
--- a/docs/gpu/gpu_testing.md
+++ b/docs/gpu/gpu_testing.md
@@ -110,13 +110,13 @@
 The GPU tests are part of the default set for Chromium CLs, and are run as part
 of the following tryservers' jobs:
 
-*   [linux_chromium_rel_ng], formerly on the `tryserver.chromium.linux` waterfall
-*   [mac_chromium_rel_ng], formerly on the `tryserver.chromium.mac` waterfall
-*   [win_chromium_rel_ng], formerly on the `tryserver.chromium.win` waterfall
+*   [linux-rel], formerly on the `tryserver.chromium.linux` waterfall
+*   [mac-rel], formerly on the `tryserver.chromium.mac` waterfall
+*   [win7-rel], formerly on the `tryserver.chromium.win` waterfall
 
-[linux_chromium_rel_ng]:    https://ci.chromium.org/p/chromium/builders/luci.chromium.try/linux_chromium_rel_ng?limit=100
-[mac_chromium_rel_ng]:      https://ci.chromium.org/p/chromium/builders/luci.chromium.try/mac_chromium_rel_ng?limit=100
-[win7_chromium_rel_ng]:     https://ci.chromium.org/p/chromium/builders/luci.chromium.try/win7_chromium_rel_ng?limit=100
+[linux-rel]:    https://ci.chromium.org/p/chromium/builders/luci.chromium.try/linux-rel?limit=100
+[mac-rel]:      https://ci.chromium.org/p/chromium/builders/luci.chromium.try/mac-rel?limit=100
+[win7-rel]:     https://ci.chromium.org/p/chromium/builders/luci.chromium.try/win7-rel?limit=100
 
 Scan down through the steps looking for the text "GPU"; that identifies those
 tests run on the GPU bots. For each test the "trigger" step can be ignored; the
@@ -127,9 +127,9 @@
 tryserver master you want to reference, for example:
 
 ```sh
-git cl try -b linux_chromium_rel_ng
-git cl try -b mac_chromium_rel_ng
-git cl try -b win7_chromium_rel_ng
+git cl try -b linux-rel
+git cl try -b mac-rel
+git cl try -b win7-rel
 ```
 
 Alternatively, the Gerrit UI can be used to send a patch set to these try
@@ -476,9 +476,9 @@
 currently have the capacity to absorb large new test suites. It is safer to get
 new tests running on the chromium.gpu.fyi waterfall first, and expand from there
 to the chromium.gpu waterfall (which will also make them run against every
-Chromium CL by virtue of the `linux_chromium_rel_ng`, `mac_chromium_rel_ng`,
-`win7_chromium_rel_ng` and `android-marshmallow-arm64-rel` tryservers' mirroring
-of the bots on this waterfall – so be careful!).
+Chromium CL by virtue of the `linux-rel`, `mac-rel`, `win7-rel` and
+`android-marshmallow-arm64-rel` tryservers' mirroring of the bots on this
+waterfall – so be careful!).
 
 Tryjobs which add new test steps to the chromium.gpu.json file will run those
 new steps during the tryjob, which helps ensure that the new test won't break
diff --git a/docs/gpu/gpu_testing_bot_details.md b/docs/gpu/gpu_testing_bot_details.md
index a1c46751..0e4a25e 100644
--- a/docs/gpu/gpu_testing_bot_details.md
+++ b/docs/gpu/gpu_testing_bot_details.md
@@ -167,10 +167,9 @@
             and then break on the waterfall.
         *   This file defines the behavior of the following GPU-related try
             bots:
-            *   `linux_chromium_rel_ng`, `mac_chromium_rel_ng`, and
-                `win_chromium_rel_ng`, which run against every Chromium CL, and
-                which mirror the behavior of bots on the chromium.gpu
-                waterfall.
+            *   `linux-rel`, `mac-rel`, and `win7-rel`, which run against every
+                Chromium CL, and which mirror the behavior of bots on the
+                chromium.gpu waterfall.
             *   The ANGLE try bots, which run against ANGLE CLs, and mirror the
                 behavior of the chromium.gpu.fyi waterfall (including using
                 top-of-tree ANGLE, and running additional tests not run by the
diff --git a/docs/gpu/pixel_wrangling.md b/docs/gpu/pixel_wrangling.md
index b04c333..68630aed 100644
--- a/docs/gpu/pixel_wrangling.md
+++ b/docs/gpu/pixel_wrangling.md
@@ -179,19 +179,15 @@
         waterfall, but instead run as part of the regular tryjobs on the
         Chromium waterfalls. The GPU tests run as part of the following
         tryservers' jobs:
-        1.  <code>[linux_chromium_rel_ng]</code> on the [luci.chromium.try]
-            waterfall
-        1.  <code>[mac_chromium_rel_ng]</code> on the [luci.chromium.try]
-            waterfall
-        1.  <code>[win7_chromium_rel_ng]</code> on the [luci.chromium.try]
-            waterfall
+        1.  `[linux-rel]` on the [luci.chromium.try] waterfall
+        1.  `[mac-rel]` on the [luci.chromium.try] waterfall
+        1.  `[win7-rel]` on the [luci.chromium.try] waterfall
     1.  The best tool to use to quickly find flakiness on the tryservers is the
         new [Chromium Try Flakes] tool. Look for the names of GPU tests (like
-        maps_pixel_test) as well as the test machines (e.g.
-        mac_chromium_rel_ng). If you see a flaky test, file a bug like [this
-        one](http://crbug.com/444430). Also look for compile flakes that may
-        indicate that a bot needs to be clobbered. Contact the Chromium
-        sheriffs or troopers if so.
+        maps_pixel_test) as well as the test machines (e.g. mac-rel). If you
+        see a flaky test, file a bug like [this one](http://crbug.com/444430).
+        Also look for compile flakes that may indicate that a bot needs to be
+        clobbered. Contact the Chromium sheriffs or troopers if so.
     1.  Glance at these trybots from time to time and see if any GPU tests are
         failing frequently. **Note** that test failures are **expected** on
         these bots: individuals' patches may fail to apply, fail to compile, or
@@ -257,11 +253,12 @@
 [Sheriff-O-Matic now has support for the chromium.gpu.fyi waterfall]: https://sheriff-o-matic.appspot.com/chromium.gpu.fyi
 [Chromium tab]: https://sheriff-o-matic.appspot.com/chromium
 [tree sheriffing page]: https://sites.google.com/a/chromium.org/dev/developers/tree-sheriffs
-[linux_chromium_rel_ng]: https://ci.chromium.org/p/chromium/builders/luci.chromium.try/linux_chromium_rel_ng
+[linux-rel]: https://ci.chromium.org/p/chromium/builders/luci.chromium.try/linux-rel
 [luci.chromium.try]: https://ci.chromium.org/p/chromium/g/luci.chromium.try/builders
-[mac_chromium_rel_ng]: https://ci.chromium.org/p/chromium/builders/luci.chromium.try/mac_chromium_rel_ng
+[mac-rel]: https://ci.chromium.org/p/chromium/builders/luci.chromium.try/mac-rel
 [tryserver.chromium.mac]: https://ci.chromium.org/p/chromium/g/tryserver.chromium.mac/builders
-[win7_chromium_rel_ng]: https://ci.chromium.org/p/chromium/builders/luci.chromium.try/win7_chromium_rel_ng
+[win7-rel]:
+https://ci.chromium.org/p/chromium/builders/luci.chromium.try/win7-rel
 [tryserver.chromium.win]: https://ci.chromium.org/p/chromium/g/tryserver.chromium.win/builders
 [Chromium Try Flakes]: http://chromium-try-flakes.appspot.com/
 <!-- TODO(kainino): link doesn't work, but is still included from chromium-swarm homepage so not removing it now -->
diff --git a/docs/infra/trybot_usage.md b/docs/infra/trybot_usage.md
index 4d7a70b..3f55b83 100644
--- a/docs/infra/trybot_usage.md
+++ b/docs/infra/trybot_usage.md
@@ -43,7 +43,7 @@
 Launching a particular trybot:
 
 ```bash
-$ git cl try -B luci.chromium.try -b linux_chromium_rel_ng
+$ git cl try -B luci.chromium.try -b linux-rel
 ```
 
 Launching multiple trybots:
diff --git a/docs/parsing_test_results.md b/docs/parsing_test_results.md
index 909877f..462a05d 100644
--- a/docs/parsing_test_results.md
+++ b/docs/parsing_test_results.md
@@ -19,16 +19,16 @@
   Android, using the *debug* configuration.
 * *android-kitkat-arm-rel* builds and runs tests for Chromium for Android,
   using the *release* configuration on a kitkat device.
-* *win7_chromium_rel_ng* builds and runs tests for Chromium on Windows, using
+* *win7-rel* builds and runs tests for Chromium on Windows, using
   the release configuration on a Windows 7 device. *ng* stands for next
   generation, but this has no meaning as the previous generation was already
   phased out.
 
 Green boxes refer to builds that passed. Red boxes refer to builds that failed.
 Some failed builds get automatically retried by the CQ. In this example,
-*linux_chromium_rel_ng* and *mac_chromium_rel_ng* were automatically retried
-[hence the two **X**s], but *win7_chromium_rel_ng* was not. The **X** on the
-left is the first build, and the **X** on the right is the second build.
+*linux-rel* and *mac-rel* were automatically retried [hence the two **X**s], but
+*win7-rel* was not. The **X** on the left is the first build, and the **X** on the right
+is the second build.
 
 Each of these boxes is a link that provides more information about the build
 failure.
diff --git a/extensions/shell/browser/shell_content_browser_client.cc b/extensions/shell/browser/shell_content_browser_client.cc
index fbe35364..7fed38d 100644
--- a/extensions/shell/browser/shell_content_browser_client.cc
+++ b/extensions/shell/browser/shell_content_browser_client.cc
@@ -137,7 +137,8 @@
     content::StoragePartition* partition,
     storage::OptionalQuotaSettingsCallback callback) {
   storage::GetNominalDynamicSettings(
-      partition->GetPath(), context->IsOffTheRecord(), std::move(callback));
+      partition->GetPath(), context->IsOffTheRecord(),
+      storage::GetDefaultDiskInfoHelper(), std::move(callback));
 }
 
 bool ShellContentBrowserClient::IsHandledURL(const GURL& url) {
diff --git a/fuchsia/BUILD.gn b/fuchsia/BUILD.gn
index 8944eddd..fe0b95e 100644
--- a/fuchsia/BUILD.gn
+++ b/fuchsia/BUILD.gn
@@ -7,22 +7,6 @@
 import("//build/config/fuchsia/fidl_library.gni")
 import("//build/util/process_version.gni")
 
-config("webrunner_implementation") {
-  defines = [ "WEBRUNNER_IMPLEMENTATION" ]
-}
-
-source_set("mem_buffer_common") {
-  sources = [
-    "common/fuchsia_export.h",
-    "common/mem_buffer_util.cc",
-    "common/mem_buffer_util.h",
-  ]
-  deps = [
-    "//base",
-    "//third_party/fuchsia-sdk/sdk:mem",
-  ]
-}
-
 fidl_library("web_fidl") {
   library_name = "web"
   namespace = "chromium"
@@ -134,11 +118,11 @@
 group("gn_all") {
   testonly = true
   deps = [
+    "base:cr_fuchsia_base_unittests",
     "engine:web_engine",
     "engine:web_engine_browsertests",
     "engine:web_engine_unittests",
     "http:http_service_tests",
-    "modular:modular_unittests",
     "runners:cast_runner",
     "runners:cast_runner_browsertests",
     "runners:cast_runner_integration_tests",
diff --git a/fuchsia/base/BUILD.gn b/fuchsia/base/BUILD.gn
new file mode 100644
index 0000000..131f3c34
--- /dev/null
+++ b/fuchsia/base/BUILD.gn
@@ -0,0 +1,63 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+assert(is_fuchsia)
+
+import("//build/config/fuchsia/fidl_library.gni")
+import("//build/config/fuchsia/rules.gni")
+import("//testing/test.gni")
+
+# Integration helpers for commonly used fuchsia.* APIs.
+source_set("base") {
+  sources = [
+    "mem_buffer_util.cc",
+  ]
+  public = [
+    "mem_buffer_util.h",
+  ]
+  deps = [
+    "//base",
+    "//third_party/fuchsia-sdk/sdk:mem",
+  ]
+}
+
+# Integration helpers for fuchsia.modular.
+source_set("modular") {
+  sources = [
+    "agent_impl.cc",
+    "agent_impl.h",
+  ]
+  deps = [
+    "//base",
+  ]
+  public_deps = [
+    "//third_party/fuchsia-sdk/sdk:modular",
+  ]
+}
+
+source_set("test_support") {
+  testonly = true
+  public = [
+    "fit_adapter.h",
+    "result_receiver.h",
+  ]
+  public_deps = [
+    "//base",
+  ]
+}
+
+# Unit-tests for all //fuchsia/base utilities.
+test("cr_fuchsia_base_unittests") {
+  sources = [
+    "agent_impl_unittests.cc",
+  ]
+  deps = [
+    ":modular",
+    ":test_support",
+    "//base",
+    "//base:testfidl",
+    "//base/test:run_all_unittests",
+    "//testing/gtest",
+  ]
+}
diff --git a/fuchsia/modular/agent_impl.cc b/fuchsia/base/agent_impl.cc
similarity index 96%
rename from fuchsia/modular/agent_impl.cc
rename to fuchsia/base/agent_impl.cc
index 1a958d6..77b4f57 100644
--- a/fuchsia/modular/agent_impl.cc
+++ b/fuchsia/base/agent_impl.cc
@@ -2,11 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "fuchsia/modular/agent_impl.h"
+#include "fuchsia/base/agent_impl.h"
 
 #include "base/bind.h"
 
-namespace modular {
+namespace cr_fuchsia {
 
 AgentImpl::ComponentStateBase::~ComponentStateBase() = default;
 
@@ -80,4 +80,4 @@
   std::move(on_last_client_callback_).Run();
 }
 
-}  // namespace modular
+}  // namespace cr_fuchsia
diff --git a/fuchsia/modular/agent_impl.h b/fuchsia/base/agent_impl.h
similarity index 95%
rename from fuchsia/modular/agent_impl.h
rename to fuchsia/base/agent_impl.h
index 07013b5..9b578ff 100644
--- a/fuchsia/modular/agent_impl.h
+++ b/fuchsia/base/agent_impl.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef FUCHSIA_MODULAR_AGENT_IMPL_H_
-#define FUCHSIA_MODULAR_AGENT_IMPL_H_
+#ifndef FUCHSIA_BASE_AGENT_IMPL_H_
+#define FUCHSIA_BASE_AGENT_IMPL_H_
 
 #include <fuchsia/modular/cpp/fidl.h>
 #include <lib/fidl/cpp/binding_set.h>
@@ -19,7 +19,7 @@
 #include "base/macros.h"
 #include "base/strings/string_piece.h"
 
-namespace modular {
+namespace cr_fuchsia {
 
 // AgentImpl allows the set of services published to each component to be
 // configured via a caller-supplied factory function for per-component state.
@@ -52,7 +52,7 @@
     virtual ~ComponentStateBase();
 
    protected:
-    ComponentStateBase(base::StringPiece component_id);
+    explicit ComponentStateBase(base::StringPiece component_id);
 
     // Returns the identity of the component served by this instance.
     const base::StringPiece component_id() const { return component_id_; }
@@ -124,6 +124,6 @@
   DISALLOW_COPY_AND_ASSIGN(AgentImpl);
 };
 
-}  // namespace modular
+}  // namespace cr_fuchsia
 
-#endif  // FUCHSIA_MODULAR_AGENT_IMPL_H_
+#endif  // FUCHSIA_BASE_AGENT_IMPL_H_
diff --git a/fuchsia/modular/agent_impl_unittests.cc b/fuchsia/base/agent_impl_unittests.cc
similarity index 95%
rename from fuchsia/modular/agent_impl_unittests.cc
rename to fuchsia/base/agent_impl_unittests.cc
index 3c227469..acc12892 100644
--- a/fuchsia/modular/agent_impl_unittests.cc
+++ b/fuchsia/base/agent_impl_unittests.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "fuchsia/modular/agent_impl.h"
+#include "fuchsia/base/agent_impl.h"
 
 #include "base/fuchsia/fuchsia_logging.h"
 #include "base/fuchsia/service_directory.h"
@@ -10,10 +10,11 @@
 #include "base/fuchsia/testfidl/cpp/fidl.h"
 #include "base/logging.h"
 #include "base/message_loop/message_loop.h"
-#include "fuchsia/engine/test/promise.h"
+#include "fuchsia/base/fit_adapter.h"
+#include "fuchsia/base/result_receiver.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-namespace modular {
+namespace cr_fuchsia {
 
 namespace {
 
@@ -105,9 +106,9 @@
 
 // Verify that the Agent can publish and unpublish itself.
 TEST_F(AgentImplTest, PublishAndUnpublish) {
-  cr_fuchsia::test::Promise<zx_status_t> client_disconnect_status1;
+  cr_fuchsia::ResultReceiver<zx_status_t> client_disconnect_status1;
   fuchsia::modular::AgentPtr agent = CreateAgentAndConnect();
-  agent.set_error_handler(cr_fuchsia::test::ConvertToFitFunction(
+  agent.set_error_handler(cr_fuchsia::CallbackToFitFunction(
       client_disconnect_status1.GetReceiveCallback()));
 
   base::RunLoop().RunUntilIdle();
@@ -121,9 +122,9 @@
   EXPECT_EQ(*client_disconnect_status1, ZX_ERR_PEER_CLOSED);
 
   // Verify that the Agent service is no longer available.
-  cr_fuchsia::test::Promise<zx_status_t> client_disconnect_status2;
+  cr_fuchsia::ResultReceiver<zx_status_t> client_disconnect_status2;
   services_client_->ConnectToService(agent.NewRequest());
-  agent.set_error_handler(cr_fuchsia::test::ConvertToFitFunction(
+  agent.set_error_handler(cr_fuchsia::CallbackToFitFunction(
       client_disconnect_status2.GetReceiveCallback()));
 
   base::RunLoop().RunUntilIdle();
@@ -284,4 +285,4 @@
   test_interface2.set_error_handler(nullptr);
 }
 
-}  // namespace modular
+}  // namespace cr_fuchsia
diff --git a/fuchsia/base/fit_adapter.h b/fuchsia/base/fit_adapter.h
new file mode 100644
index 0000000..4f8d632
--- /dev/null
+++ b/fuchsia/base/fit_adapter.h
@@ -0,0 +1,26 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef FUCHSIA_BASE_FIT_ADAPTER_H_
+#define FUCHSIA_BASE_FIT_ADAPTER_H_
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/optional.h"
+
+namespace cr_fuchsia {
+
+// Adapts a base::OnceCallback<> to a fit::function<>, to allow //base callbacks
+// to be used directly as FIDL result callbacks.
+template <typename ReturnType, typename... ArgumentTypes>
+fit::function<ReturnType(ArgumentTypes...)> CallbackToFitFunction(
+    base::OnceCallback<ReturnType(ArgumentTypes...)> callback) {
+  return [callback = std::move(callback)](ArgumentTypes... args) mutable {
+    std::move(callback).Run(std::forward<ArgumentTypes>(args)...);
+  };
+}
+
+}  // namespace cr_fuchsia
+
+#endif  // FUCHSIA_BASE_FIT_ADAPTER_H_
diff --git a/fuchsia/common/mem_buffer_util.cc b/fuchsia/base/mem_buffer_util.cc
similarity index 96%
rename from fuchsia/common/mem_buffer_util.cc
rename to fuchsia/base/mem_buffer_util.cc
index 837e4c2c..575fa589 100644
--- a/fuchsia/common/mem_buffer_util.cc
+++ b/fuchsia/base/mem_buffer_util.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "fuchsia/common/mem_buffer_util.h"
+#include "fuchsia/base/mem_buffer_util.h"
 
 #include <lib/fdio/io.h>
 
@@ -16,7 +16,7 @@
 #include "base/stl_util.h"
 #include "base/threading/thread_restrictions.h"
 
-namespace webrunner {
+namespace cr_fuchsia {
 
 bool ReadUTF8FromVMOAsUTF16(const fuchsia::mem::Buffer& buffer,
                             base::string16* output) {
@@ -85,4 +85,4 @@
   return output;
 }
 
-}  // namespace webrunner
+}  // namespace cr_fuchsia
diff --git a/fuchsia/common/mem_buffer_util.h b/fuchsia/base/mem_buffer_util.h
similarity index 88%
rename from fuchsia/common/mem_buffer_util.h
rename to fuchsia/base/mem_buffer_util.h
index c320fcb..cf20419 100644
--- a/fuchsia/common/mem_buffer_util.h
+++ b/fuchsia/base/mem_buffer_util.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef FUCHSIA_COMMON_MEM_BUFFER_UTIL_H_
-#define FUCHSIA_COMMON_MEM_BUFFER_UTIL_H_
+#ifndef FUCHSIA_BASE_MEM_BUFFER_UTIL_H_
+#define FUCHSIA_BASE_MEM_BUFFER_UTIL_H_
 
 #include <fuchsia/mem/cpp/fidl.h>
 #include <lib/zx/channel.h>
@@ -12,7 +12,7 @@
 #include "base/files/file.h"
 #include "base/strings/utf_string_conversions.h"
 
-namespace webrunner {
+namespace cr_fuchsia {
 
 // Reads the contents of |buffer|, encoded in UTF-8, to a UTF-16 string.
 // Returns |false| if |buffer| is not valid UTF-8.
@@ -37,6 +37,6 @@
 // Creates a non-resizeable, copy-on-write shared memory clone of |buffer|.
 fuchsia::mem::Buffer CloneBuffer(const fuchsia::mem::Buffer& buffer);
 
-}  // namespace webrunner
+}  // namespace cr_fuchsia
 
-#endif  // FUCHSIA_COMMON_MEM_BUFFER_UTIL_H_
+#endif  // FUCHSIA_BASE_MEM_BUFFER_UTIL_H_
diff --git a/fuchsia/base/result_receiver.h b/fuchsia/base/result_receiver.h
new file mode 100644
index 0000000..26ed6a6
--- /dev/null
+++ b/fuchsia/base/result_receiver.h
@@ -0,0 +1,64 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef FUCHSIA_BASE_RESULT_RECEIVER_H_
+#define FUCHSIA_BASE_RESULT_RECEIVER_H_
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/optional.h"
+
+namespace cr_fuchsia {
+
+// Helper for capturing a "result" of an asynchronous operation that is passed
+// via a Callback<ResultType>, for later retrieval. An optional Closure may also
+// be configured, to be called when the result is captured.
+//
+// This is primarily useful for tests, which use a ResultReceiver<> configured
+// with a RunLoop::QuitClosure() to pump a message-loop until an asynchronous
+// operation has completed.
+template <typename T>
+class ResultReceiver {
+ public:
+  ResultReceiver() : on_result_received_() {}
+  explicit ResultReceiver(base::RepeatingClosure on_result_received)
+      : on_result_received_(std::move(on_result_received)) {}
+
+  ~ResultReceiver() = default;
+
+  // Returns a OnceCallback which will receive and store a result value.
+  base::OnceCallback<void(T)> GetReceiveCallback() {
+    return base::BindOnce(&ResultReceiver<T>::ReceiveResult,
+                          base::Unretained(this));
+  }
+
+  void ReceiveResult(T result) {
+    DCHECK(!result_.has_value());
+    result_ = std::move(result);
+    if (on_result_received_)
+      on_result_received_.Run();
+  }
+
+  bool has_value() const { return result_.has_value(); }
+
+  T& operator*() {
+    DCHECK(result_.has_value());
+    return *result_;
+  }
+
+  T* operator->() {
+    DCHECK(result_.has_value());
+    return &*result_;
+  }
+
+ private:
+  base::Optional<T> result_;
+  const base::RepeatingClosure on_result_received_;
+
+  DISALLOW_COPY_AND_ASSIGN(ResultReceiver<T>);
+};
+
+}  // namespace cr_fuchsia
+
+#endif  // FUCHSIA_BASE_RESULT_RECEIVER_H_
diff --git a/fuchsia/common/fuchsia_export.h b/fuchsia/common/fuchsia_export.h
deleted file mode 100644
index 3a7f4761..0000000
--- a/fuchsia/common/fuchsia_export.h
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef FUCHSIA_COMMON_FUCHSIA_EXPORT_H_
-#define FUCHSIA_COMMON_FUCHSIA_EXPORT_H_
-
-#if defined(COMPONENT_BUILD)
-
-#if defined(WEBRUNNER_IMPLEMENTATION)
-#define FUCHSIA_EXPORT __attribute__((visibility("default")))
-#else
-#define FUCHSIA_EXPORT
-#endif
-
-#else  // defined(COMPONENT_BUILD)
-#define FUCHSIA_EXPORT
-#endif
-
-#endif  // FUCHSIA_COMMON_FUCHSIA_EXPORT_H_
diff --git a/fuchsia/engine/BUILD.gn b/fuchsia/engine/BUILD.gn
index f56205d..f379f86 100644
--- a/fuchsia/engine/BUILD.gn
+++ b/fuchsia/engine/BUILD.gn
@@ -9,12 +9,15 @@
 import("//testing/test.gni")
 import("//tools/grit/repack.gni")
 
+config("web_engine_implementation") {
+  defines = [ "WEB_ENGINE_IMPLEMENTATION" ]
+}
+
 source_set("test_support") {
   testonly = true
   sources = [
     "test/fake_context.cc",
     "test/fake_context.h",
-    "test/promise.h",
     "test/test_common.cc",
     "test/test_common.h",
   ]
@@ -22,7 +25,7 @@
     "//base",
     "//base/test:test_config",
     "//content/test:test_support",
-    "//fuchsia:mem_buffer_common",
+    "//fuchsia/base",
   ]
   public_deps = [
     "//fuchsia:web_fidl",
@@ -87,7 +90,7 @@
     "//content/public/child",
     "//content/public/common",
     "//content/public/renderer",
-    "//fuchsia:mem_buffer_common",
+    "//fuchsia/base",
     "//mojo/public/cpp/bindings",
     "//services/network/public/cpp",
     "//services/service_manager/sandbox",
@@ -110,7 +113,7 @@
   public_deps = [
     "//fuchsia:web_fidl",
   ]
-  configs += [ "//fuchsia:webrunner_implementation" ]
+  configs += [ ":web_engine_implementation" ]
   sources = [
     "browser/context_impl.cc",
     "browser/context_impl.h",
@@ -142,6 +145,7 @@
     "renderer/on_load_script_injector.h",
     "renderer/webrunner_content_renderer_client.cc",
     "renderer/webrunner_content_renderer_client.h",
+    "web_engine_export.h",
     "webrunner_content_client.cc",
     "webrunner_content_client.h",
     "webrunner_main_delegate.cc",
@@ -212,7 +216,8 @@
     ":web_engine_core",
     "//base/test:test_support",
     "//content/public/browser",
-    "//fuchsia:mem_buffer_common",
+    "//fuchsia/base",
+    "//fuchsia/base:test_support",
     "//net:test_support",
     "//testing/gmock",
     "//testing/gtest",
diff --git a/fuchsia/engine/browser/context_impl.h b/fuchsia/engine/browser/context_impl.h
index dfa9f16..4e68f91 100644
--- a/fuchsia/engine/browser/context_impl.h
+++ b/fuchsia/engine/browser/context_impl.h
@@ -11,7 +11,7 @@
 
 #include "base/containers/unique_ptr_adapters.h"
 #include "base/macros.h"
-#include "fuchsia/common/fuchsia_export.h"
+#include "fuchsia/engine/web_engine_export.h"
 #include "fuchsia/fidl/chromium/web/cpp/fidl.h"
 
 namespace content {
@@ -23,7 +23,7 @@
 // Implementation of Context from //fuchsia/fidl/context.fidl.
 // Owns a BrowserContext instance and uses it to create new WebContents/Frames.
 // All created Frames are owned by this object.
-class FUCHSIA_EXPORT ContextImpl : public chromium::web::Context {
+class WEB_ENGINE_EXPORT ContextImpl : public chromium::web::Context {
  public:
   // |browser_context| must outlive ContextImpl.
   explicit ContextImpl(content::BrowserContext* browser_context);
diff --git a/fuchsia/engine/browser/frame_impl.cc b/fuchsia/engine/browser/frame_impl.cc
index a9d00701..142ece9 100644
--- a/fuchsia/engine/browser/frame_impl.cc
+++ b/fuchsia/engine/browser/frame_impl.cc
@@ -19,7 +19,7 @@
 #include "content/public/browser/web_contents.h"
 #include "content/public/common/renderer_preferences_util.h"
 #include "content/public/common/was_activated_option.h"
-#include "fuchsia/common/mem_buffer_util.h"
+#include "fuchsia/base/mem_buffer_util.h"
 #include "fuchsia/engine/browser/context_impl.h"
 #include "fuchsia/engine/browser/message_port_impl.h"
 #include "mojo/public/cpp/system/platform_handle.h"
@@ -314,7 +314,7 @@
     origins_strings.push_back(origin);
 
   base::string16 script_utf16;
-  if (!webrunner::ReadUTF8FromVMOAsUTF16(script, &script_utf16)) {
+  if (!cr_fuchsia::ReadUTF8FromVMOAsUTF16(script, &script_utf16)) {
     callback(false);
     return;
   }
@@ -333,7 +333,7 @@
 
     // Create a read-only VMO from |script|.
     fuchsia::mem::Buffer script_buffer =
-        webrunner::MemBufferFromString16(script_utf16);
+        cr_fuchsia::MemBufferFromString16(script_utf16);
     if (!script_buffer.vmo) {
       LOG(WARNING) << "Couldn't read script contents from VMO.";
       callback(false);
@@ -370,7 +370,7 @@
     target_origin_utf16 = base::UTF8ToUTF16(target_origin);
 
   base::string16 data_utf16;
-  if (!webrunner::ReadUTF8FromVMOAsUTF16(message.data, &data_utf16)) {
+  if (!cr_fuchsia::ReadUTF8FromVMOAsUTF16(message.data, &data_utf16)) {
     DLOG(WARNING) << "PostMessage() rejected non-UTF8 |message.data|.";
     callback(false);
     return;
diff --git a/fuchsia/engine/browser/frame_impl_browsertest.cc b/fuchsia/engine/browser/frame_impl_browsertest.cc
index b7c3279b9..a6d70ea 100644
--- a/fuchsia/engine/browser/frame_impl_browsertest.cc
+++ b/fuchsia/engine/browser/frame_impl_browsertest.cc
@@ -11,10 +11,11 @@
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/browser/web_contents_observer.h"
-#include "fuchsia/common/mem_buffer_util.h"
+#include "fuchsia/base/fit_adapter.h"
+#include "fuchsia/base/mem_buffer_util.h"
+#include "fuchsia/base/result_receiver.h"
 #include "fuchsia/engine/browser/frame_impl.h"
 #include "fuchsia/engine/common.h"
-#include "fuchsia/engine/test/promise.h"
 #include "fuchsia/engine/test/test_common.h"
 #include "fuchsia/engine/test/webrunner_browser_test.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
@@ -399,8 +400,8 @@
 
   frame->ExecuteJavaScript(
       std::move(origins),
-      webrunner::MemBufferFromString("window.location.href = \"" +
-                                     title2.spec() + "\";"),
+      cr_fuchsia::MemBufferFromString("window.location.href = \"" +
+                                      title2.spec() + "\";"),
       chromium::web::ExecuteMode::IMMEDIATE_ONCE,
       [](bool success) { EXPECT_TRUE(success); });
 
@@ -422,7 +423,7 @@
 
   frame->ExecuteJavaScript(
       std::move(origins),
-      webrunner::MemBufferFromString("stashed_title = 'hello';"),
+      cr_fuchsia::MemBufferFromString("stashed_title = 'hello';"),
       chromium::web::ExecuteMode::ON_PAGE_LOAD,
       [](bool success) { EXPECT_TRUE(success); });
 
@@ -440,7 +441,7 @@
 
   frame->ExecuteJavaScript(
       std::move(origins),
-      webrunner::MemBufferFromString("stashed_title = 'hello';"),
+      cr_fuchsia::MemBufferFromString("stashed_title = 'hello';"),
       chromium::web::ExecuteMode::ON_PAGE_LOAD,
       [](bool success) { EXPECT_TRUE(success); });
 
@@ -458,7 +459,7 @@
 
   frame->ExecuteJavaScript(
       std::move(origins),
-      webrunner::MemBufferFromString("stashed_title = 'hello';"),
+      cr_fuchsia::MemBufferFromString("stashed_title = 'hello';"),
       chromium::web::ExecuteMode::ON_PAGE_LOAD,
       [](bool success) { EXPECT_TRUE(success); });
 
@@ -480,7 +481,7 @@
 
   frame->ExecuteJavaScript(
       std::move(origins),
-      webrunner::MemBufferFromString("stashed_title = 'hello';"),
+      cr_fuchsia::MemBufferFromString("stashed_title = 'hello';"),
       chromium::web::ExecuteMode::ON_PAGE_LOAD,
       [](bool success) { EXPECT_TRUE(success); });
 
@@ -507,12 +508,12 @@
 
   std::vector<std::string> origins = {url.GetOrigin().spec()};
   frame->ExecuteJavaScript(
-      origins, webrunner::MemBufferFromString("stashed_title = 'hello';"),
+      origins, cr_fuchsia::MemBufferFromString("stashed_title = 'hello';"),
       chromium::web::ExecuteMode::ON_PAGE_LOAD,
       [](bool success) { EXPECT_TRUE(success); });
   frame->ExecuteJavaScript(
       std::move(origins),
-      webrunner::MemBufferFromString("stashed_title += ' there';"),
+      cr_fuchsia::MemBufferFromString("stashed_title += ' there';"),
       chromium::web::ExecuteMode::ON_PAGE_LOAD,
       [](bool success) { EXPECT_TRUE(success); });
 
@@ -530,7 +531,7 @@
   std::vector<std::string> origins = {url.GetOrigin().spec()};
 
   frame->ExecuteJavaScript(
-      origins, webrunner::MemBufferFromString("stashed_title = 'hello';"),
+      origins, cr_fuchsia::MemBufferFromString("stashed_title = 'hello';"),
       chromium::web::ExecuteMode::ON_PAGE_LOAD,
       [](bool success) { EXPECT_TRUE(success); });
 
@@ -540,7 +541,7 @@
 
   frame->ExecuteJavaScript(
       std::move(origins),
-      webrunner::MemBufferFromString("stashed_title += ' there';"),
+      cr_fuchsia::MemBufferFromString("stashed_title += ' there';"),
       chromium::web::ExecuteMode::ON_PAGE_LOAD,
       [](bool success) { EXPECT_TRUE(success); });
 
@@ -567,7 +568,7 @@
   // 0xFE is an illegal UTF-8 byte; it should cause UTF-8 conversion to fail.
   std::vector<std::string> origins = {url.host()};
   frame->ExecuteJavaScript(
-      std::move(origins), webrunner::MemBufferFromString("true;\xfe"),
+      std::move(origins), cr_fuchsia::MemBufferFromString("true;\xfe"),
       chromium::web::ExecuteMode::IMMEDIATE_ONCE, [&run_loop](bool success) {
         EXPECT_FALSE(success);
         run_loop.Quit();
@@ -740,11 +741,11 @@
                controller.get());
 
   chromium::web::WebMessage message;
-  message.data = webrunner::MemBufferFromString(kPage1Path);
-  cr_fuchsia::test::Promise<bool> post_result;
+  message.data = cr_fuchsia::MemBufferFromString(kPage1Path);
+  cr_fuchsia::ResultReceiver<bool> post_result;
   frame->PostMessage(
       std::move(message), post_message_url.GetOrigin().spec(),
-      cr_fuchsia::test::ConvertToFitFunction(post_result.GetReceiveCallback()));
+      cr_fuchsia::CallbackToFitFunction(post_result.GetReceiveCallback()));
   base::RunLoop run_loop;
   EXPECT_CALL(navigation_observer_,
               MockableOnNavigationStateChanged(
@@ -774,33 +775,33 @@
     msg.outgoing_transfer =
         std::make_unique<chromium::web::OutgoingTransferable>();
     msg.outgoing_transfer->set_message_port(message_port.NewRequest());
-    msg.data = webrunner::MemBufferFromString("hi");
-    cr_fuchsia::test::Promise<bool> post_result;
-    frame->PostMessage(std::move(msg), post_message_url.GetOrigin().spec(),
-                       cr_fuchsia::test::ConvertToFitFunction(
-                           post_result.GetReceiveCallback()));
+    msg.data = cr_fuchsia::MemBufferFromString("hi");
+    cr_fuchsia::ResultReceiver<bool> post_result;
+    frame->PostMessage(
+        std::move(msg), post_message_url.GetOrigin().spec(),
+        cr_fuchsia::CallbackToFitFunction(post_result.GetReceiveCallback()));
 
     base::RunLoop run_loop;
-    cr_fuchsia::test::Promise<chromium::web::WebMessage> receiver(
+    cr_fuchsia::ResultReceiver<chromium::web::WebMessage> receiver(
         run_loop.QuitClosure());
     message_port->ReceiveMessage(
-        cr_fuchsia::test::ConvertToFitFunction(receiver.GetReceiveCallback()));
+        cr_fuchsia::CallbackToFitFunction(receiver.GetReceiveCallback()));
     run_loop.Run();
     EXPECT_EQ("got_port",
               cr_fuchsia::test::StringFromMemBufferOrDie(receiver->data));
   }
 
   {
-    msg.data = webrunner::MemBufferFromString("ping");
-    cr_fuchsia::test::Promise<bool> post_result;
-    message_port->PostMessage(std::move(msg),
-                              cr_fuchsia::test::ConvertToFitFunction(
-                                  post_result.GetReceiveCallback()));
+    msg.data = cr_fuchsia::MemBufferFromString("ping");
+    cr_fuchsia::ResultReceiver<bool> post_result;
+    message_port->PostMessage(
+        std::move(msg),
+        cr_fuchsia::CallbackToFitFunction(post_result.GetReceiveCallback()));
     base::RunLoop run_loop;
-    cr_fuchsia::test::Promise<chromium::web::WebMessage> receiver(
+    cr_fuchsia::ResultReceiver<chromium::web::WebMessage> receiver(
         run_loop.QuitClosure());
     message_port->ReceiveMessage(
-        cr_fuchsia::test::ConvertToFitFunction(receiver.GetReceiveCallback()));
+        cr_fuchsia::CallbackToFitFunction(receiver.GetReceiveCallback()));
     run_loop.Run();
     EXPECT_EQ("ack ping",
               cr_fuchsia::test::StringFromMemBufferOrDie(receiver->data));
@@ -827,17 +828,17 @@
     msg.outgoing_transfer =
         std::make_unique<chromium::web::OutgoingTransferable>();
     msg.outgoing_transfer->set_message_port(message_port.NewRequest());
-    msg.data = webrunner::MemBufferFromString("hi");
-    cr_fuchsia::test::Promise<bool> post_result;
-    frame->PostMessage(std::move(msg), post_message_url.GetOrigin().spec(),
-                       cr_fuchsia::test::ConvertToFitFunction(
-                           post_result.GetReceiveCallback()));
+    msg.data = cr_fuchsia::MemBufferFromString("hi");
+    cr_fuchsia::ResultReceiver<bool> post_result;
+    frame->PostMessage(
+        std::move(msg), post_message_url.GetOrigin().spec(),
+        cr_fuchsia::CallbackToFitFunction(post_result.GetReceiveCallback()));
 
     base::RunLoop run_loop;
-    cr_fuchsia::test::Promise<chromium::web::WebMessage> receiver(
+    cr_fuchsia::ResultReceiver<chromium::web::WebMessage> receiver(
         run_loop.QuitClosure());
     message_port->ReceiveMessage(
-        cr_fuchsia::test::ConvertToFitFunction(receiver.GetReceiveCallback()));
+        cr_fuchsia::CallbackToFitFunction(receiver.GetReceiveCallback()));
     run_loop.Run();
     EXPECT_EQ("got_port",
               cr_fuchsia::test::StringFromMemBufferOrDie(receiver->data));
@@ -876,17 +877,17 @@
     msg.outgoing_transfer =
         std::make_unique<chromium::web::OutgoingTransferable>();
     msg.outgoing_transfer->set_message_port(message_port.NewRequest());
-    msg.data = webrunner::MemBufferFromString("hi");
-    cr_fuchsia::test::Promise<bool> post_result;
-    frame->PostMessage(std::move(msg), "*",
-                       cr_fuchsia::test::ConvertToFitFunction(
-                           post_result.GetReceiveCallback()));
+    msg.data = cr_fuchsia::MemBufferFromString("hi");
+    cr_fuchsia::ResultReceiver<bool> post_result;
+    frame->PostMessage(
+        std::move(msg), "*",
+        cr_fuchsia::CallbackToFitFunction(post_result.GetReceiveCallback()));
 
     base::RunLoop run_loop;
-    cr_fuchsia::test::Promise<chromium::web::WebMessage> receiver(
+    cr_fuchsia::ResultReceiver<chromium::web::WebMessage> receiver(
         run_loop.QuitClosure());
     message_port->ReceiveMessage(
-        cr_fuchsia::test::ConvertToFitFunction(receiver.GetReceiveCallback()));
+        cr_fuchsia::CallbackToFitFunction(receiver.GetReceiveCallback()));
     run_loop.Run();
     EXPECT_EQ("got_port",
               cr_fuchsia::test::StringFromMemBufferOrDie(receiver->data));
@@ -898,11 +899,11 @@
   // the MessagePortImpl buffer.
   for (int i = 0; i < 3; ++i) {
     base::RunLoop run_loop;
-    cr_fuchsia::test::Promise<bool> post_result(run_loop.QuitClosure());
-    msg.data = webrunner::MemBufferFromString("ping");
-    incoming_message_port->PostMessage(std::move(msg),
-                                       cr_fuchsia::test::ConvertToFitFunction(
-                                           post_result.GetReceiveCallback()));
+    cr_fuchsia::ResultReceiver<bool> post_result(run_loop.QuitClosure());
+    msg.data = cr_fuchsia::MemBufferFromString("ping");
+    incoming_message_port->PostMessage(
+        std::move(msg),
+        cr_fuchsia::CallbackToFitFunction(post_result.GetReceiveCallback()));
     run_loop.Run();
     EXPECT_TRUE(*post_result);
   }
@@ -915,19 +916,19 @@
     msg.outgoing_transfer =
         std::make_unique<chromium::web::OutgoingTransferable>();
     msg.outgoing_transfer->set_message_port(ack_message_port.NewRequest());
-    msg.data = webrunner::MemBufferFromString("hi");
+    msg.data = cr_fuchsia::MemBufferFromString("hi");
 
     // Quit the runloop only after we've received a WebMessage AND a PostMessage
     // result.
-    cr_fuchsia::test::Promise<bool> post_result;
-    frame->PostMessage(std::move(msg), "*",
-                       cr_fuchsia::test::ConvertToFitFunction(
-                           post_result.GetReceiveCallback()));
+    cr_fuchsia::ResultReceiver<bool> post_result;
+    frame->PostMessage(
+        std::move(msg), "*",
+        cr_fuchsia::CallbackToFitFunction(post_result.GetReceiveCallback()));
     base::RunLoop run_loop;
-    cr_fuchsia::test::Promise<chromium::web::WebMessage> receiver(
+    cr_fuchsia::ResultReceiver<chromium::web::WebMessage> receiver(
         run_loop.QuitClosure());
     ack_message_port->ReceiveMessage(
-        cr_fuchsia::test::ConvertToFitFunction(receiver.GetReceiveCallback()));
+        cr_fuchsia::CallbackToFitFunction(receiver.GetReceiveCallback()));
     run_loop.Run();
     EXPECT_EQ("got_port",
               cr_fuchsia::test::StringFromMemBufferOrDie(receiver->data));
@@ -937,10 +938,10 @@
   // Pull the three 'ack ping's from the buffer.
   for (int i = 0; i < 3; ++i) {
     base::RunLoop run_loop;
-    cr_fuchsia::test::Promise<chromium::web::WebMessage> receiver(
+    cr_fuchsia::ResultReceiver<chromium::web::WebMessage> receiver(
         run_loop.QuitClosure());
     incoming_message_port->ReceiveMessage(
-        cr_fuchsia::test::ConvertToFitFunction(receiver.GetReceiveCallback()));
+        cr_fuchsia::CallbackToFitFunction(receiver.GetReceiveCallback()));
     run_loop.Run();
     EXPECT_EQ("ack ping",
               cr_fuchsia::test::StringFromMemBufferOrDie(receiver->data));
@@ -967,14 +968,14 @@
   msg.outgoing_transfer =
       std::make_unique<chromium::web::OutgoingTransferable>();
   msg.outgoing_transfer->set_message_port(unused_message_port.NewRequest());
-  msg.data = webrunner::MemBufferFromString("bad origin, bad!");
-  cr_fuchsia::test::Promise<bool> unused_post_result;
+  msg.data = cr_fuchsia::MemBufferFromString("bad origin, bad!");
+  cr_fuchsia::ResultReceiver<bool> unused_post_result;
   frame->PostMessage(std::move(msg), "https://example.com",
-                     cr_fuchsia::test::ConvertToFitFunction(
+                     cr_fuchsia::CallbackToFitFunction(
                          unused_post_result.GetReceiveCallback()));
-  cr_fuchsia::test::Promise<chromium::web::WebMessage> unused_message_read;
+  cr_fuchsia::ResultReceiver<chromium::web::WebMessage> unused_message_read;
   bad_origin_incoming_message_port->ReceiveMessage(
-      cr_fuchsia::test::ConvertToFitFunction(
+      cr_fuchsia::CallbackToFitFunction(
           unused_message_read.GetReceiveCallback()));
 
   // PostMessage() with a valid origin should succeed.
@@ -987,16 +988,16 @@
   msg.outgoing_transfer =
       std::make_unique<chromium::web::OutgoingTransferable>();
   msg.outgoing_transfer->set_message_port(message_port.NewRequest());
-  msg.data = webrunner::MemBufferFromString("good origin");
-  cr_fuchsia::test::Promise<bool> post_result;
+  msg.data = cr_fuchsia::MemBufferFromString("good origin");
+  cr_fuchsia::ResultReceiver<bool> post_result;
   frame->PostMessage(
       std::move(msg), "*",
-      cr_fuchsia::test::ConvertToFitFunction(post_result.GetReceiveCallback()));
+      cr_fuchsia::CallbackToFitFunction(post_result.GetReceiveCallback()));
   base::RunLoop run_loop;
-  cr_fuchsia::test::Promise<chromium::web::WebMessage> receiver(
+  cr_fuchsia::ResultReceiver<chromium::web::WebMessage> receiver(
       run_loop.QuitClosure());
   message_port->ReceiveMessage(
-      cr_fuchsia::test::ConvertToFitFunction(receiver.GetReceiveCallback()));
+      cr_fuchsia::CallbackToFitFunction(receiver.GetReceiveCallback()));
   run_loop.Run();
   EXPECT_EQ("got_port",
             cr_fuchsia::test::StringFromMemBufferOrDie(receiver->data));
diff --git a/fuchsia/engine/browser/message_port_impl.cc b/fuchsia/engine/browser/message_port_impl.cc
index 838299c..277e13d 100644
--- a/fuchsia/engine/browser/message_port_impl.cc
+++ b/fuchsia/engine/browser/message_port_impl.cc
@@ -15,7 +15,7 @@
 #include "base/bind.h"
 #include "base/fuchsia/fuchsia_logging.h"
 #include "base/macros.h"
-#include "fuchsia/common/mem_buffer_util.h"
+#include "fuchsia/base/mem_buffer_util.h"
 #include "fuchsia/fidl/chromium/web/cpp/fidl.h"
 #include "mojo/public/cpp/system/message_pipe.h"
 #include "third_party/blink/public/common/messaging/message_port_channel.h"
@@ -83,7 +83,7 @@
 // Returns a null mojo::Message if |message| was invalid.
 mojo::Message FromFidlMessage(chromium::web::WebMessage message) {
   base::string16 data_utf16;
-  if (!webrunner::ReadUTF8FromVMOAsUTF16(message.data, &data_utf16))
+  if (!cr_fuchsia::ReadUTF8FromVMOAsUTF16(message.data, &data_utf16))
     return mojo::Message();
 
   // TODO(crbug.com/893236): support >1 transferable when fidlc cycle detection
diff --git a/fuchsia/engine/common.h b/fuchsia/engine/common.h
index 9903ce48..350067c 100644
--- a/fuchsia/engine/common.h
+++ b/fuchsia/engine/common.h
@@ -7,11 +7,11 @@
 
 #include <zircon/processargs.h>
 
-#include "fuchsia/common/fuchsia_export.h"
+#include "fuchsia/engine/web_engine_export.h"
 
 // Switch passed to content process when running in incognito mode, i.e. when
 // there is no kWebContextDataPath.
-FUCHSIA_EXPORT extern const char kIncognitoSwitch[];
+WEB_ENGINE_EXPORT extern const char kIncognitoSwitch[];
 
 // This file contains constants and functions shared between Context and
 // ContextProvider processes.
diff --git a/fuchsia/engine/context_provider_impl.h b/fuchsia/engine/context_provider_impl.h
index 878d510..bc7bbb8 100644
--- a/fuchsia/engine/context_provider_impl.h
+++ b/fuchsia/engine/context_provider_impl.h
@@ -11,7 +11,7 @@
 #include "base/callback.h"
 #include "base/macros.h"
 #include "chromium/web/cpp/fidl.h"
-#include "fuchsia/common/fuchsia_export.h"
+#include "fuchsia/engine/web_engine_export.h"
 
 namespace base {
 class CommandLine;
@@ -19,7 +19,7 @@
 class Process;
 }  // namespace base
 
-class FUCHSIA_EXPORT ContextProviderImpl
+class WEB_ENGINE_EXPORT ContextProviderImpl
     : public chromium::web::ContextProvider {
  public:
   ContextProviderImpl();
diff --git a/fuchsia/engine/context_provider_main.h b/fuchsia/engine/context_provider_main.h
index ec1ec64..bfafcd9 100644
--- a/fuchsia/engine/context_provider_main.h
+++ b/fuchsia/engine/context_provider_main.h
@@ -5,11 +5,11 @@
 #ifndef FUCHSIA_ENGINE_CONTEXT_PROVIDER_MAIN_H_
 #define FUCHSIA_ENGINE_CONTEXT_PROVIDER_MAIN_H_
 
-#include "fuchsia/common/fuchsia_export.h"
+#include "fuchsia/engine/web_engine_export.h"
 
 // Main function for the process that implements web::ContextProvider interface.
 // Called by WebRunnerMainDelegate when the process is started without --type
 // argument.
-FUCHSIA_EXPORT int ContextProviderMain();
+WEB_ENGINE_EXPORT int ContextProviderMain();
 
-#endif  // FUCHSIA_ENGINE_CONTEXT_PROVIDER_MAIN_H_
\ No newline at end of file
+#endif  // FUCHSIA_ENGINE_CONTEXT_PROVIDER_MAIN_H_
diff --git a/fuchsia/engine/test/promise.h b/fuchsia/engine/test/promise.h
deleted file mode 100644
index 06c3e92..0000000
--- a/fuchsia/engine/test/promise.h
+++ /dev/null
@@ -1,72 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef FUCHSIA_ENGINE_TEST_PROMISE_H_
-#define FUCHSIA_ENGINE_TEST_PROMISE_H_
-
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/optional.h"
-
-namespace cr_fuchsia {
-namespace test {
-
-// Stores an asynchronously generated value for later retrieval, optionally
-// invoking a callback on value receipt for controlling test flow.
-//
-// The value can be read by using the dereference (*) or arrow (->) operators.
-// Values must first be received before they can be accessed. Dereferencing a
-// value before it is set will produce a CHECK violation.
-template <typename T>
-class Promise {
- public:
-  explicit Promise(base::RepeatingClosure on_capture = base::DoNothing())
-      : on_capture_(std::move(on_capture)) {}
-
-  Promise(Promise&& other) = default;
-
-  ~Promise() = default;
-
-  // Returns a OnceCallback which will receive and store a value T.
-  base::OnceCallback<void(T)> GetReceiveCallback() {
-    return base::BindOnce(&Promise<T>::ReceiveValue, base::Unretained(this));
-  }
-
-  void ReceiveValue(T value) {
-    captured_ = std::move(value);
-    on_capture_.Run();
-  }
-
-  bool has_value() const { return captured_.has_value(); }
-
-  T& operator*() {
-    CHECK(captured_.has_value());
-    return *captured_;
-  }
-
-  T* operator->() {
-    CHECK(captured_.has_value());
-    return &*captured_;
-  }
-
- private:
-  base::Optional<T> captured_;
-  base::RepeatingClosure on_capture_;
-
-  DISALLOW_COPY_AND_ASSIGN(Promise<T>);
-};
-
-// Converts a Chromium OnceCallback to a fit::function.
-template <typename TRet, typename... TArgs>
-fit::function<TRet(TArgs...)> ConvertToFitFunction(
-    base::OnceCallback<TRet(TArgs...)> callback) {
-  return [callback = std::move(callback)](TArgs... args) mutable {
-    std::move(callback).Run(std::forward<TArgs>(args)...);
-  };
-}
-
-}  // namespace test
-}  // namespace cr_fuchsia
-
-#endif  // FUCHSIA_ENGINE_TEST_PROMISE_H_
diff --git a/fuchsia/engine/test/test_common.cc b/fuchsia/engine/test/test_common.cc
index 799425a..ce19897 100644
--- a/fuchsia/engine/test/test_common.cc
+++ b/fuchsia/engine/test/test_common.cc
@@ -9,7 +9,7 @@
 
 #include "base/fuchsia/fuchsia_logging.h"
 #include "base/run_loop.h"
-#include "fuchsia/common/mem_buffer_util.h"
+#include "fuchsia/base/mem_buffer_util.h"
 
 namespace cr_fuchsia {
 namespace test {
@@ -35,7 +35,7 @@
 
 std::string StringFromMemBufferOrDie(const fuchsia::mem::Buffer& buffer) {
   std::string output;
-  CHECK(webrunner::StringFromMemBuffer(buffer, &output));
+  CHECK(cr_fuchsia::StringFromMemBuffer(buffer, &output));
   return output;
 }
 
diff --git a/fuchsia/engine/web_engine_export.h b/fuchsia/engine/web_engine_export.h
new file mode 100644
index 0000000..9ca98b5
--- /dev/null
+++ b/fuchsia/engine/web_engine_export.h
@@ -0,0 +1,20 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef FUCHSIA_ENGINE_WEB_ENGINE_EXPORT_H_
+#define FUCHSIA_ENGINE_WEB_ENGINE_EXPORT_H_
+
+#if defined(COMPONENT_BUILD)
+
+#if defined(WEB_ENGINE_IMPLEMENTATION)
+#define WEB_ENGINE_EXPORT __attribute__((visibility("default")))
+#else
+#define WEB_ENGINE_EXPORT
+#endif
+
+#else  // defined(COMPONENT_BUILD)
+#define WEB_ENGINE_EXPORT
+#endif
+
+#endif  // FUCHSIA_ENGINE_WEB_ENGINE_EXPORT_H_
diff --git a/fuchsia/engine/webrunner_main_delegate.h b/fuchsia/engine/webrunner_main_delegate.h
index 5479aa74..e336901c 100644
--- a/fuchsia/engine/webrunner_main_delegate.h
+++ b/fuchsia/engine/webrunner_main_delegate.h
@@ -11,7 +11,7 @@
 
 #include "base/macros.h"
 #include "content/public/app/content_main_delegate.h"
-#include "fuchsia/common/fuchsia_export.h"
+#include "fuchsia/engine/web_engine_export.h"
 
 namespace content {
 class ContentClient;
@@ -20,7 +20,7 @@
 class WebRunnerContentBrowserClient;
 class WebRunnerContentRendererClient;
 
-class FUCHSIA_EXPORT WebRunnerMainDelegate
+class WEB_ENGINE_EXPORT WebRunnerMainDelegate
     : public content::ContentMainDelegate {
  public:
   explicit WebRunnerMainDelegate(zx::channel context_channel);
diff --git a/fuchsia/modular/BUILD.gn b/fuchsia/modular/BUILD.gn
deleted file mode 100644
index f7d6cd6..0000000
--- a/fuchsia/modular/BUILD.gn
+++ /dev/null
@@ -1,36 +0,0 @@
-# Copyright 2019 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-assert(is_fuchsia)
-
-import("//build/config/fuchsia/fidl_library.gni")
-import("//build/config/fuchsia/rules.gni")
-import("//testing/test.gni")
-
-source_set("modular") {
-  sources = [
-    "agent_impl.cc",
-    "agent_impl.h",
-  ]
-  deps = [
-    "//base",
-  ]
-  public_deps = [
-    "//third_party/fuchsia-sdk/sdk:modular",
-  ]
-}
-
-test("modular_unittests") {
-  sources = [
-    "agent_impl_unittests.cc",
-  ]
-  deps = [
-    ":modular",
-    "//base",
-    "//base:testfidl",
-    "//base/test:run_all_unittests",
-    "//fuchsia/engine:test_support",
-    "//testing/gtest",
-  ]
-}
diff --git a/fuchsia/runners/BUILD.gn b/fuchsia/runners/BUILD.gn
index 4ff1698c..e103204 100644
--- a/fuchsia/runners/BUILD.gn
+++ b/fuchsia/runners/BUILD.gn
@@ -45,7 +45,7 @@
   ]
   deps = [
     "//base",
-    "//fuchsia:mem_buffer_common",
+    "//fuchsia/base",
     "//url",
   ]
   public_deps = [
@@ -53,7 +53,6 @@
     "//fuchsia:cast_fidl",
     "//fuchsia:web_fidl",
   ]
-  configs += [ "//fuchsia:webrunner_implementation" ]
   visibility = [ ":*" ]
 }
 
@@ -114,6 +113,7 @@
     ":cast_runner_test_core",
     "//base/test:run_all_unittests",
     "//base/test:test_support",
+    "//fuchsia/base:test_support",
     "//fuchsia/engine:test_support",
     "//net:test_support",
     "//testing/gtest",
@@ -137,7 +137,8 @@
     ":cast_runner_core",
     "//base/test:test_support",
     "//content/public/browser",
-    "//fuchsia:mem_buffer_common",
+    "//fuchsia/base",
+    "//fuchsia/base:test_support",
     "//fuchsia/engine:browsertest_core",
     "//fuchsia/engine:test_support",
     "//testing/gmock",
diff --git a/fuchsia/runners/cast/cast_channel_bindings.cc b/fuchsia/runners/cast/cast_channel_bindings.cc
index 3dc589a..a46e5bf 100644
--- a/fuchsia/runners/cast/cast_channel_bindings.cc
+++ b/fuchsia/runners/cast/cast_channel_bindings.cc
@@ -15,7 +15,7 @@
 #include "base/macros.h"
 #include "base/path_service.h"
 #include "base/threading/thread_task_runner_handle.h"
-#include "fuchsia/common/mem_buffer_util.h"
+#include "fuchsia/base/mem_buffer_util.h"
 #include "fuchsia/runners/cast/named_message_port_connector.h"
 
 // Unique identifier of the Cast Channel message port, used by the JavaScript
@@ -49,7 +49,7 @@
   // mem::Buffer.
   base::FilePath assets_path;
   CHECK(base::PathService::Get(base::DIR_ASSETS, &assets_path));
-  fuchsia::mem::Buffer bindings_buf = webrunner::MemBufferFromFile(base::File(
+  fuchsia::mem::Buffer bindings_buf = cr_fuchsia::MemBufferFromFile(base::File(
       assets_path.AppendASCII("fuchsia/runners/cast/cast_channel_bindings.js"),
       base::File::FLAG_OPEN | base::File::FLAG_READ));
   CHECK(bindings_buf.vmo);
diff --git a/fuchsia/runners/cast/cast_channel_bindings.h b/fuchsia/runners/cast/cast_channel_bindings.h
index e259140..a0199f03 100644
--- a/fuchsia/runners/cast/cast_channel_bindings.h
+++ b/fuchsia/runners/cast/cast_channel_bindings.h
@@ -11,14 +11,13 @@
 #include "base/callback.h"
 #include "base/macros.h"
 #include "base/strings/string_piece.h"
-#include "fuchsia/common/fuchsia_export.h"
 #include "fuchsia/fidl/chromium/cast/cpp/fidl.h"
 #include "fuchsia/runners/cast/named_message_port_connector.h"
 
 // Handles the injection of cast.__platform__.channel bindings into pages'
 // scripting context, and establishes a bidirectional message pipe over
 // which the two communicate.
-class FUCHSIA_EXPORT CastChannelBindings {
+class CastChannelBindings {
  public:
   // Attaches CastChannel bindings and port to a |frame|.
   // |frame|: The frame to be provided with a CastChannel.
diff --git a/fuchsia/runners/cast/cast_channel_bindings_browsertest.cc b/fuchsia/runners/cast/cast_channel_bindings_browsertest.cc
index ba272dd..98124036 100644
--- a/fuchsia/runners/cast/cast_channel_bindings_browsertest.cc
+++ b/fuchsia/runners/cast/cast_channel_bindings_browsertest.cc
@@ -12,8 +12,9 @@
 #include "base/test/bind_test_util.h"
 #include "base/test/test_timeouts.h"
 #include "base/threading/thread_restrictions.h"
-#include "fuchsia/common/mem_buffer_util.h"
-#include "fuchsia/engine/test/promise.h"
+#include "fuchsia/base/fit_adapter.h"
+#include "fuchsia/base/mem_buffer_util.h"
+#include "fuchsia/base/result_receiver.h"
 #include "fuchsia/engine/test/test_common.h"
 #include "fuchsia/engine/test/webrunner_browser_test.h"
 #include "fuchsia/runners/cast/cast_channel_bindings.h"
@@ -92,10 +93,10 @@
 
   std::string ReadStringFromChannel() {
     base::RunLoop run_loop;
-    cr_fuchsia::test::Promise<chromium::web::WebMessage> message(
+    cr_fuchsia::ResultReceiver<chromium::web::WebMessage> message(
         run_loop.QuitClosure());
     connected_channel_->ReceiveMessage(
-        cr_fuchsia::test::ConvertToFitFunction(message.GetReceiveCallback()));
+        cr_fuchsia::CallbackToFitFunction(message.GetReceiveCallback()));
     run_loop.Run();
     return cr_fuchsia::test::StringFromMemBufferOrDie(message->data);
   }
@@ -187,13 +188,13 @@
     // Send a message to the channel.
     {
       chromium::web::WebMessage message;
-      message.data = webrunner::MemBufferFromString("hello");
+      message.data = cr_fuchsia::MemBufferFromString("hello");
 
       base::RunLoop run_loop;
-      cr_fuchsia::test::Promise<bool> post_result(run_loop.QuitClosure());
-      connected_channel_->PostMessage(std::move(message),
-                                      cr_fuchsia::test::ConvertToFitFunction(
-                                          post_result.GetReceiveCallback()));
+      cr_fuchsia::ResultReceiver<bool> post_result(run_loop.QuitClosure());
+      connected_channel_->PostMessage(
+          std::move(message),
+          cr_fuchsia::CallbackToFitFunction(post_result.GetReceiveCallback()));
       run_loop.Run();
       EXPECT_EQ(true, *post_result);
     }
diff --git a/fuchsia/runners/cast/cast_runner_integration_test.cc b/fuchsia/runners/cast/cast_runner_integration_test.cc
index ebb27f9..90e6eb9 100644
--- a/fuchsia/runners/cast/cast_runner_integration_test.cc
+++ b/fuchsia/runners/cast/cast_runner_integration_test.cc
@@ -11,7 +11,8 @@
 #include "base/message_loop/message_loop.h"
 #include "base/strings/stringprintf.h"
 #include "base/test/test_timeouts.h"
-#include "fuchsia/engine/test/promise.h"
+#include "fuchsia/base/fit_adapter.h"
+#include "fuchsia/base/result_receiver.h"
 #include "fuchsia/engine/test/test_common.h"
 #include "fuchsia/fidl/chromium/web/cpp/fidl.h"
 #include "fuchsia/runners/cast/cast_runner.h"
@@ -157,7 +158,7 @@
   chromium::web::NavigationControllerPtr nav_controller;
   {
     base::RunLoop run_loop;
-    cr_fuchsia::test::Promise<WebComponent*> web_component(
+    cr_fuchsia::ResultReceiver<WebComponent*> web_component(
         run_loop.QuitClosure());
     cast_runner_->GetWebComponentForTest(web_component.GetReceiveCallback());
     run_loop.Run();
@@ -170,10 +171,10 @@
   // Ensure the NavigationEntry has the expected URL.
   {
     base::RunLoop run_loop;
-    cr_fuchsia::test::Promise<std::unique_ptr<chromium::web::NavigationEntry>>
+    cr_fuchsia::ResultReceiver<std::unique_ptr<chromium::web::NavigationEntry>>
         nav_entry(run_loop.QuitClosure());
     nav_controller->GetVisibleEntry(
-        cr_fuchsia::test::ConvertToFitFunction(nav_entry.GetReceiveCallback()));
+        cr_fuchsia::CallbackToFitFunction(nav_entry.GetReceiveCallback()));
     run_loop.Run();
     EXPECT_EQ(nav_entry->get()->url, test_server_.GetURL(kBlankAppPath).spec());
   }
@@ -197,7 +198,7 @@
 
   // Ensure no WebComponent was created.
   base::RunLoop run_loop;
-  cr_fuchsia::test::Promise<WebComponent*> web_component(
+  cr_fuchsia::ResultReceiver<WebComponent*> web_component(
       run_loop.QuitClosure());
   cast_runner_->GetWebComponentForTest(web_component.GetReceiveCallback());
   run_loop.Run();
@@ -222,7 +223,7 @@
   chromium::web::NavigationControllerPtr nav_controller;
   {
     base::RunLoop run_loop;
-    cr_fuchsia::test::Promise<WebComponent*> web_component(
+    cr_fuchsia::ResultReceiver<WebComponent*> web_component(
         run_loop.QuitClosure());
     cast_runner_->GetWebComponentForTest(web_component.GetReceiveCallback());
     run_loop.Run();
@@ -235,10 +236,10 @@
   // Ensure the NavigationEntry has the expected URL.
   {
     base::RunLoop run_loop;
-    cr_fuchsia::test::Promise<std::unique_ptr<chromium::web::NavigationEntry>>
+    cr_fuchsia::ResultReceiver<std::unique_ptr<chromium::web::NavigationEntry>>
         nav_entry(run_loop.QuitClosure());
     nav_controller->GetVisibleEntry(
-        cr_fuchsia::test::ConvertToFitFunction(nav_entry.GetReceiveCallback()));
+        cr_fuchsia::CallbackToFitFunction(nav_entry.GetReceiveCallback()));
     run_loop.Run();
     EXPECT_EQ(nav_entry->get()->url,
               test_server_.GetURL(kCastChannelAppPath).spec());
@@ -249,10 +250,10 @@
   auto expected_list = {"this", "is", "a", "test"};
   for (const std::string& expected : expected_list) {
     base::RunLoop run_loop;
-    cr_fuchsia::test::Promise<chromium::web::WebMessage> message(
+    cr_fuchsia::ResultReceiver<chromium::web::WebMessage> message(
         run_loop.QuitClosure());
     connected_channel_->ReceiveMessage(
-        cr_fuchsia::test::ConvertToFitFunction(message.GetReceiveCallback()));
+        cr_fuchsia::CallbackToFitFunction(message.GetReceiveCallback()));
     run_loop.Run();
 
     EXPECT_EQ(cr_fuchsia::test::StringFromMemBufferOrDie(message->data),
diff --git a/fuchsia/runners/cast/named_message_port_connector.cc b/fuchsia/runners/cast/named_message_port_connector.cc
index aba175e8..5ab9fe9 100644
--- a/fuchsia/runners/cast/named_message_port_connector.cc
+++ b/fuchsia/runners/cast/named_message_port_connector.cc
@@ -13,7 +13,7 @@
 #include "base/macros.h"
 #include "base/path_service.h"
 #include "base/threading/thread_restrictions.h"
-#include "fuchsia/common/mem_buffer_util.h"
+#include "fuchsia/base/mem_buffer_util.h"
 #include "fuchsia/fidl/chromium/web/cpp/fidl.h"
 
 namespace {
@@ -27,7 +27,7 @@
 NamedMessagePortConnector::NamedMessagePortConnector() {
   base::FilePath assets_path;
   CHECK(base::PathService::Get(base::DIR_ASSETS, &assets_path));
-  bindings_script_ = webrunner::MemBufferFromFile(
+  bindings_script_ = cr_fuchsia::MemBufferFromFile(
       base::File(assets_path.AppendASCII(kBindingsJsPath),
                  base::File::FLAG_OPEN | base::File::FLAG_READ));
 }
@@ -71,7 +71,8 @@
     const RegistrationEntry& registration = it->second;
 
     chromium::web::WebMessage message;
-    message.data = webrunner::MemBufferFromString("connect " + registration.id);
+    message.data =
+        cr_fuchsia::MemBufferFromString("connect " + registration.id);
 
     // Call the handler callback, with the MessagePort client object.
     message.outgoing_transfer =
@@ -87,7 +88,7 @@
          handler =
              registration.handler](chromium::web::WebMessage message) mutable {
           std::string message_str;
-          if (!webrunner::StringFromMemBuffer(message.data, &message_str)) {
+          if (!cr_fuchsia::StringFromMemBuffer(message.data, &message_str)) {
             LOG(ERROR) << "Couldn't read from message VMO.";
             return;
           }
@@ -111,7 +112,7 @@
 
   std::vector<std::string> origins = {"*"};
   frame->ExecuteJavaScript(
-      std::move(origins), webrunner::CloneBuffer(bindings_script_),
+      std::move(origins), cr_fuchsia::CloneBuffer(bindings_script_),
       chromium::web::ExecuteMode::ON_PAGE_LOAD,
       [](bool success) { CHECK(success) << "Couldn't inject bindings."; });
 }
diff --git a/fuchsia/runners/cast/named_message_port_connector.h b/fuchsia/runners/cast/named_message_port_connector.h
index b7d5bcd..e41d04a 100644
--- a/fuchsia/runners/cast/named_message_port_connector.h
+++ b/fuchsia/runners/cast/named_message_port_connector.h
@@ -12,14 +12,13 @@
 #include "base/callback.h"
 #include "base/files/file_path.h"
 #include "base/macros.h"
-#include "fuchsia/common/fuchsia_export.h"
 #include "fuchsia/fidl/chromium/web/cpp/fidl.h"
 
 // The implementation actively creates a MessagePort for each registered Id,
 // passing them all to the web container every time a page-load occurs. It then
 // waits for the page to acknowledge each MessagePort, before invoking its
 // registered |handler| to notify the called that it is ready for use.
-class FUCHSIA_EXPORT NamedMessagePortConnector {
+class NamedMessagePortConnector {
  public:
   using PortConnectedCallback =
       base::RepeatingCallback<void(chromium::web::MessagePortPtr)>;
diff --git a/fuchsia/runners/cast/named_message_port_connector_browsertest.cc b/fuchsia/runners/cast/named_message_port_connector_browsertest.cc
index a3c8ba8..ede205e2 100644
--- a/fuchsia/runners/cast/named_message_port_connector_browsertest.cc
+++ b/fuchsia/runners/cast/named_message_port_connector_browsertest.cc
@@ -10,8 +10,9 @@
 #include "base/macros.h"
 #include "base/path_service.h"
 #include "base/test/test_timeouts.h"
-#include "fuchsia/common/mem_buffer_util.h"
-#include "fuchsia/engine/test/promise.h"
+#include "fuchsia/base/fit_adapter.h"
+#include "fuchsia/base/mem_buffer_util.h"
+#include "fuchsia/base/result_receiver.h"
 #include "fuchsia/engine/test/test_common.h"
 #include "fuchsia/engine/test/webrunner_browser_test.h"
 #include "fuchsia/runners/cast/named_message_port_connector.h"
@@ -77,12 +78,12 @@
   frame_->GetNavigationController(controller.NewRequest());
 
   base::RunLoop receive_port_run_loop;
-  cr_fuchsia::test::Promise<chromium::web::MessagePortPtr> message_port(
+  cr_fuchsia::ResultReceiver<chromium::web::MessagePortPtr> message_port(
       receive_port_run_loop.QuitClosure());
   connector_.Register(
       "hello",
-      base::BindRepeating(&cr_fuchsia::test::Promise<
-                              chromium::web::MessagePortPtr>::ReceiveValue,
+      base::BindRepeating(&cr_fuchsia::ResultReceiver<
+                              chromium::web::MessagePortPtr>::ReceiveResult,
                           base::Unretained(&message_port)),
       frame_.get());
   CheckLoadUrl(test_url.spec(), controller.get());
@@ -90,19 +91,19 @@
   receive_port_run_loop.Run();
 
   chromium::web::WebMessage msg;
-  msg.data = webrunner::MemBufferFromString("ping");
-  cr_fuchsia::test::Promise<bool> post_result;
+  msg.data = cr_fuchsia::MemBufferFromString("ping");
+  cr_fuchsia::ResultReceiver<bool> post_result;
   (*message_port)
-      ->PostMessage(std::move(msg), cr_fuchsia::test::ConvertToFitFunction(
+      ->PostMessage(std::move(msg), cr_fuchsia::CallbackToFitFunction(
                                         post_result.GetReceiveCallback()));
 
   std::vector<std::string> test_messages = {"early 1", "early 2", "ack ping"};
   for (std::string expected_msg : test_messages) {
     base::RunLoop run_loop;
-    cr_fuchsia::test::Promise<chromium::web::WebMessage> message_receiver(
+    cr_fuchsia::ResultReceiver<chromium::web::WebMessage> message_receiver(
         run_loop.QuitClosure());
     (*message_port)
-        ->ReceiveMessage(cr_fuchsia::test::ConvertToFitFunction(
+        ->ReceiveMessage(cr_fuchsia::CallbackToFitFunction(
             message_receiver.GetReceiveCallback()));
     run_loop.Run();
     EXPECT_EQ(
diff --git a/google_apis/gaia/fake_oauth2_token_service.h b/google_apis/gaia/fake_oauth2_token_service.h
index 9cd4bcb..032a709 100644
--- a/google_apis/gaia/fake_oauth2_token_service.h
+++ b/google_apis/gaia/fake_oauth2_token_service.h
@@ -33,7 +33,7 @@
       const GoogleServiceAuthError& auth_error);
 
   void InvalidateTokenForMultilogin(const std::string& account_id,
-                                    const std::string& token) override{};
+                                    const std::string& token) override {}
 
   FakeOAuth2TokenServiceDelegate* GetFakeOAuth2TokenServiceDelegate();
 
diff --git a/google_apis/gaia/gaia_oauth_client_unittest.cc b/google_apis/gaia/gaia_oauth_client_unittest.cc
index d7b370a9..0d42eac 100644
--- a/google_apis/gaia/gaia_oauth_client_unittest.cc
+++ b/google_apis/gaia/gaia_oauth_client_unittest.cc
@@ -175,7 +175,7 @@
     client_info_.client_id = "test_client_id";
     client_info_.client_secret = "test_client_secret";
     client_info_.redirect_uri = "test_redirect_uri";
-  };
+  }
 
   scoped_refptr<network::SharedURLLoaderFactory> GetSharedURLLoaderFactory() {
     return base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
diff --git a/gpu/command_buffer/client/cmd_buffer_helper_test.cc b/gpu/command_buffer/client/cmd_buffer_helper_test.cc
index 5687d247..8e2755df 100644
--- a/gpu/command_buffer/client/cmd_buffer_helper_test.cc
+++ b/gpu/command_buffer/client/cmd_buffer_helper_test.cc
@@ -18,7 +18,6 @@
 #include "gpu/command_buffer/client/cmd_buffer_helper.h"
 #include "gpu/command_buffer/client/command_buffer_direct_locked.h"
 #include "gpu/command_buffer/service/mocks.h"
-#include "gpu/command_buffer/service/transfer_buffer_manager.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace gpu {
@@ -42,9 +41,7 @@
 class CommandBufferHelperTest : public testing::Test {
  protected:
   void SetUp() override {
-    transfer_buffer_manager_ = std::make_unique<TransferBufferManager>(nullptr);
-    command_buffer_.reset(
-        new CommandBufferDirectLocked(transfer_buffer_manager_.get()));
+    command_buffer_.reset(new CommandBufferDirectLocked());
     api_mock_.reset(new AsyncAPIMock(true, command_buffer_->service()));
     command_buffer_->set_handler(api_mock_.get());
 
@@ -199,7 +196,6 @@
     helper_->WaitForGetOffsetInRange(start, end);
   }
 
-  std::unique_ptr<TransferBufferManager> transfer_buffer_manager_;
   std::unique_ptr<CommandBufferDirectLocked> command_buffer_;
   std::unique_ptr<AsyncAPIMock> api_mock_;
   std::unique_ptr<CommandBufferHelper> helper_;
diff --git a/gpu/command_buffer/client/command_buffer_direct_locked.h b/gpu/command_buffer/client/command_buffer_direct_locked.h
index c7d32cdf..fc9d8d65 100644
--- a/gpu/command_buffer/client/command_buffer_direct_locked.h
+++ b/gpu/command_buffer/client/command_buffer_direct_locked.h
@@ -13,9 +13,7 @@
 // until either it gets unlocked or the client waits for progress.
 class CommandBufferDirectLocked : public CommandBufferDirect {
  public:
-  explicit CommandBufferDirectLocked(
-      TransferBufferManager* transfer_buffer_manager)
-      : CommandBufferDirect(transfer_buffer_manager) {}
+  CommandBufferDirectLocked() = default;
   ~CommandBufferDirectLocked() override = default;
 
   // Overridden from CommandBufferDirect
diff --git a/gpu/command_buffer/client/fenced_allocator_test.cc b/gpu/command_buffer/client/fenced_allocator_test.cc
index 4dc7898..be304f1 100644
--- a/gpu/command_buffer/client/fenced_allocator_test.cc
+++ b/gpu/command_buffer/client/fenced_allocator_test.cc
@@ -17,7 +17,6 @@
 #include "gpu/command_buffer/client/fenced_allocator.h"
 #include "gpu/command_buffer/service/command_buffer_direct.h"
 #include "gpu/command_buffer/service/mocks.h"
-#include "gpu/command_buffer/service/transfer_buffer_manager.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace gpu {
@@ -37,9 +36,7 @@
   static const int kAllocAlignment = 16;
 
   void SetUp() override {
-    transfer_buffer_manager_ = std::make_unique<TransferBufferManager>(nullptr);
-    command_buffer_.reset(
-        new CommandBufferDirect(transfer_buffer_manager_.get()));
+    command_buffer_.reset(new CommandBufferDirect());
     api_mock_.reset(new AsyncAPIMock(true, command_buffer_->service()));
     command_buffer_->set_handler(api_mock_.get());
 
@@ -58,7 +55,6 @@
 
   int32_t GetToken() { return command_buffer_->GetLastState().token; }
 
-  std::unique_ptr<TransferBufferManager> transfer_buffer_manager_;
   std::unique_ptr<CommandBufferDirect> command_buffer_;
   std::unique_ptr<AsyncAPIMock> api_mock_;
   std::unique_ptr<CommandBufferHelper> helper_;
diff --git a/gpu/command_buffer/client/mapped_memory_unittest.cc b/gpu/command_buffer/client/mapped_memory_unittest.cc
index affe2335..d1844a0 100644
--- a/gpu/command_buffer/client/mapped_memory_unittest.cc
+++ b/gpu/command_buffer/client/mapped_memory_unittest.cc
@@ -16,7 +16,6 @@
 #include "gpu/command_buffer/client/cmd_buffer_helper.h"
 #include "gpu/command_buffer/client/command_buffer_direct_locked.h"
 #include "gpu/command_buffer/service/mocks.h"
-#include "gpu/command_buffer/service/transfer_buffer_manager.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace gpu {
@@ -34,9 +33,7 @@
   static const unsigned int kBufferSize = 1024;
 
   void SetUp() override {
-    transfer_buffer_manager_ = std::make_unique<TransferBufferManager>(nullptr);
-    command_buffer_.reset(
-        new CommandBufferDirectLocked(transfer_buffer_manager_.get()));
+    command_buffer_.reset(new CommandBufferDirectLocked());
     api_mock_.reset(new AsyncAPIMock(true, command_buffer_->service()));
     command_buffer_->set_handler(api_mock_.get());
 
@@ -55,7 +52,6 @@
 
   int32_t GetToken() { return command_buffer_->GetLastState().token; }
 
-  std::unique_ptr<TransferBufferManager> transfer_buffer_manager_;
   std::unique_ptr<CommandBufferDirectLocked> command_buffer_;
   std::unique_ptr<AsyncAPIMock> api_mock_;
   std::unique_ptr<CommandBufferHelper> helper_;
diff --git a/gpu/command_buffer/client/ring_buffer_test.cc b/gpu/command_buffer/client/ring_buffer_test.cc
index 3b334e40..4dd4f68 100644
--- a/gpu/command_buffer/client/ring_buffer_test.cc
+++ b/gpu/command_buffer/client/ring_buffer_test.cc
@@ -17,7 +17,6 @@
 #include "gpu/command_buffer/client/cmd_buffer_helper.h"
 #include "gpu/command_buffer/service/command_buffer_direct.h"
 #include "gpu/command_buffer/service/mocks.h"
-#include "gpu/command_buffer/service/transfer_buffer_manager.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace gpu {
@@ -59,9 +58,7 @@
 
   void SetUp() override {
     delay_set_token_ = false;
-    transfer_buffer_manager_ = std::make_unique<TransferBufferManager>(nullptr);
-    command_buffer_.reset(
-        new CommandBufferDirect(transfer_buffer_manager_.get()));
+    command_buffer_.reset(new CommandBufferDirect());
     api_mock_.reset(new AsyncAPIMock(true, command_buffer_->service()));
     command_buffer_->set_handler(api_mock_.get());
 
@@ -80,7 +77,6 @@
 
   int32_t GetToken() { return command_buffer_->GetLastState().token; }
 
-  std::unique_ptr<TransferBufferManager> transfer_buffer_manager_;
   std::unique_ptr<CommandBufferDirect> command_buffer_;
   std::unique_ptr<AsyncAPIMock> api_mock_;
   std::unique_ptr<CommandBufferHelper> helper_;
diff --git a/gpu/command_buffer/service/command_buffer_direct.cc b/gpu/command_buffer/service/command_buffer_direct.cc
index 45439dc..6e407cf 100644
--- a/gpu/command_buffer/service/command_buffer_direct.cc
+++ b/gpu/command_buffer/service/command_buffer_direct.cc
@@ -16,9 +16,8 @@
 
 }  // anonymous namespace
 
-CommandBufferDirect::CommandBufferDirect(
-    TransferBufferManager* transfer_buffer_manager)
-    : service_(this, transfer_buffer_manager),
+CommandBufferDirect::CommandBufferDirect()
+    : service_(this, nullptr),
       command_buffer_id_(
           CommandBufferId::FromUnsafeValue(g_next_command_buffer_id++)) {}
 
diff --git a/gpu/command_buffer/service/command_buffer_direct.h b/gpu/command_buffer/service/command_buffer_direct.h
index d12b11f8..3fe8847 100644
--- a/gpu/command_buffer/service/command_buffer_direct.h
+++ b/gpu/command_buffer/service/command_buffer_direct.h
@@ -15,17 +15,16 @@
 namespace gpu {
 
 class AsyncAPIInterface;
-class TransferBufferManager;
 
 class GPU_EXPORT CommandBufferDirect : public CommandBuffer,
                                        public CommandBufferServiceClient,
                                        public DecoderClient {
  public:
-  explicit CommandBufferDirect(TransferBufferManager* transfer_buffer_manager);
+  CommandBufferDirect();
   ~CommandBufferDirect() override;
 
   void set_handler(AsyncAPIInterface* handler) { handler_ = handler; }
-  CommandBufferServiceBase* service() { return &service_; }
+  CommandBufferService* service() { return &service_; }
 
   // CommandBuffer implementation:
   CommandBuffer::State GetLastState() override;
@@ -40,7 +39,7 @@
                                              int32_t* id) override;
   void DestroyTransferBuffer(int32_t id) override;
 
-  // CommandBufferServiceBase implementation:
+  // CommandBufferServiceClient implementation:
   CommandBatchProcessedResult OnCommandBatchProcessed() override;
   void OnParseError() override;
 
diff --git a/gpu/command_buffer/service/command_buffer_service.cc b/gpu/command_buffer/service/command_buffer_service.cc
index 89b0e1b..04407cd 100644
--- a/gpu/command_buffer/service/command_buffer_service.cc
+++ b/gpu/command_buffer/service/command_buffer_service.cc
@@ -18,12 +18,12 @@
 
 namespace gpu {
 
-CommandBufferService::CommandBufferService(
-    CommandBufferServiceClient* client,
-    TransferBufferManager* transfer_buffer_manager)
-    : client_(client), transfer_buffer_manager_(transfer_buffer_manager) {
+CommandBufferService::CommandBufferService(CommandBufferServiceClient* client,
+                                           MemoryTracker* memory_tracker)
+    : client_(client),
+      transfer_buffer_manager_(
+          std::make_unique<TransferBufferManager>(memory_tracker)) {
   DCHECK(client_);
-  DCHECK(transfer_buffer_manager_);
   state_.token = 0;
 }
 
@@ -204,4 +204,8 @@
   scheduled_ = scheduled;
 }
 
+size_t CommandBufferService::GetSharedMemoryBytesAllocated() const {
+  return transfer_buffer_manager_->shared_memory_bytes_allocated();
+}
+
 }  // namespace gpu
diff --git a/gpu/command_buffer/service/command_buffer_service.h b/gpu/command_buffer/service/command_buffer_service.h
index 42e1716..3e52c3d0 100644
--- a/gpu/command_buffer/service/command_buffer_service.h
+++ b/gpu/command_buffer/service/command_buffer_service.h
@@ -18,6 +18,7 @@
 
 namespace gpu {
 
+class MemoryTracker;
 class TransferBufferManager;
 
 class GPU_EXPORT CommandBufferServiceBase {
@@ -73,7 +74,7 @@
   static const int kParseCommandsSlice = 20;
 
   CommandBufferService(CommandBufferServiceClient* client,
-                       TransferBufferManager* transfer_buffer_manager);
+                       MemoryTracker* memory_tracker);
   ~CommandBufferService() override;
 
   // CommandBufferServiceBase implementation:
@@ -123,9 +124,11 @@
     state_.get_offset = get_offset;
   }
 
+  size_t GetSharedMemoryBytesAllocated() const;
+
  private:
   CommandBufferServiceClient* client_;
-  TransferBufferManager* transfer_buffer_manager_;
+  std::unique_ptr<TransferBufferManager> transfer_buffer_manager_;
 
   CommandBuffer::State state_;
   int32_t put_offset_ = 0;
diff --git a/gpu/command_buffer/service/command_buffer_service_unittest.cc b/gpu/command_buffer/service/command_buffer_service_unittest.cc
index 52c9e7d..9237e0b 100644
--- a/gpu/command_buffer/service/command_buffer_service_unittest.cc
+++ b/gpu/command_buffer/service/command_buffer_service_unittest.cc
@@ -12,7 +12,6 @@
 #include "gpu/command_buffer/client/client_test_helper.h"
 #include "gpu/command_buffer/service/command_buffer_service.h"
 #include "gpu/command_buffer/service/mocks.h"
-#include "gpu/command_buffer/service/transfer_buffer_manager.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace gpu {
@@ -43,9 +42,8 @@
   // Creates a CommandBufferService, with a buffer of the specified size (in
   // entries).
   void MakeService(unsigned int entry_count) {
-    transfer_buffer_manager_ = std::make_unique<TransferBufferManager>(nullptr);
-    command_buffer_service_ = std::make_unique<CommandBufferService>(
-        this, transfer_buffer_manager_.get());
+    command_buffer_service_ =
+        std::make_unique<CommandBufferService>(this, nullptr);
     api_mock_.reset(new AsyncAPIMock(false, command_buffer_service_.get()));
     SetNewGetBuffer(entry_count * sizeof(CommandBufferEntry));
   }
@@ -95,7 +93,6 @@
   MOCK_METHOD0(OnParseError, void());
 
  private:
-  std::unique_ptr<TransferBufferManager> transfer_buffer_manager_;
   std::unique_ptr<CommandBufferService> command_buffer_service_;
   std::unique_ptr<AsyncAPIMock> api_mock_;
   scoped_refptr<Buffer> buffer_;
diff --git a/gpu/command_buffer/service/context_group.cc b/gpu/command_buffer/service/context_group.cc
index a79f6394..8df7bf38 100644
--- a/gpu/command_buffer/service/context_group.cc
+++ b/gpu/command_buffer/service/context_group.cc
@@ -24,7 +24,6 @@
 #include "gpu/command_buffer/service/shader_manager.h"
 #include "gpu/command_buffer/service/shared_image_factory.h"
 #include "gpu/command_buffer/service/texture_manager.h"
-#include "gpu/command_buffer/service/transfer_buffer_manager.h"
 #include "gpu/config/gpu_preferences.h"
 #include "ui/gl/gl_bindings.h"
 #include "ui/gl/gl_version_info.h"
@@ -128,8 +127,6 @@
   DCHECK(discardable_manager);
   DCHECK(feature_info_);
   DCHECK(mailbox_manager_);
-  transfer_buffer_manager_ =
-      std::make_unique<TransferBufferManager>(memory_tracker_.get());
   use_passthrough_cmd_decoder_ = supports_passthrough_command_decoders &&
                                  gpu_preferences_.use_passthrough_cmd_decoder;
 }
diff --git a/gpu/command_buffer/service/context_group.h b/gpu/command_buffer/service/context_group.h
index 3b3cacba..7ff6e3d82 100644
--- a/gpu/command_buffer/service/context_group.h
+++ b/gpu/command_buffer/service/context_group.h
@@ -33,7 +33,6 @@
 class ImageFactory;
 struct GpuPreferences;
 class MailboxManager;
-class TransferBufferManager;
 class SharedImageManager;
 class SharedImageRepresentationFactory;
 class ServiceDiscardableManager;
@@ -199,10 +198,6 @@
     return shader_manager_.get();
   }
 
-  TransferBufferManager* transfer_buffer_manager() const {
-    return transfer_buffer_manager_.get();
-  }
-
   SamplerManager* sampler_manager() const {
     return sampler_manager_.get();
   }
@@ -274,7 +269,6 @@
   std::unique_ptr<MemoryTracker> memory_tracker_;
   ShaderTranslatorCache* shader_translator_cache_;
   FramebufferCompletenessCache* framebuffer_completeness_cache_;
-  std::unique_ptr<TransferBufferManager> transfer_buffer_manager_;
 
   bool enforce_gl_minimums_;
   bool bind_generates_resource_;
diff --git a/gpu/command_buffer/tests/decoder_perftest.cc b/gpu/command_buffer/tests/decoder_perftest.cc
index 35592b75..3a1e5e26 100644
--- a/gpu/command_buffer/tests/decoder_perftest.cc
+++ b/gpu/command_buffer/tests/decoder_perftest.cc
@@ -56,10 +56,7 @@
  public:
   enum Mode { kDirect, kRecord, kReplay };
 
-  explicit RecordReplayCommandBuffer(
-      TransferBufferManager* transfer_buffer_manager)
-      : CommandBufferDirect(transfer_buffer_manager) {}
-
+  RecordReplayCommandBuffer() = default;
   ~RecordReplayCommandBuffer() override = default;
 
   void AdvanceMode() {
@@ -183,8 +180,7 @@
         nullptr /* progress_reporter */, GpuFeatureInfo(),
         &discardable_manager_, &passthrough_discardable_manager_,
         &shared_image_manager_);
-    command_buffer_.reset(new RecordReplayCommandBuffer(
-        context_group->transfer_buffer_manager()));
+    command_buffer_.reset(new RecordReplayCommandBuffer());
 
     decoder_.reset(gles2::GLES2Decoder::Create(
         command_buffer_.get(), command_buffer_->service(), &outputter_,
diff --git a/gpu/command_buffer/tests/fuzzer_main.cc b/gpu/command_buffer/tests/fuzzer_main.cc
index c4a6446..cd6eb35 100644
--- a/gpu/command_buffer/tests/fuzzer_main.cc
+++ b/gpu/command_buffer/tests/fuzzer_main.cc
@@ -363,8 +363,7 @@
         nullptr /* image_factory */, nullptr /* progress_reporter */,
         gpu_feature_info, discardable_manager_.get(),
         passthrough_discardable_manager_.get(), &shared_image_manager_);
-    command_buffer_.reset(
-        new CommandBufferDirect(context_group->transfer_buffer_manager()));
+    command_buffer_.reset(new CommandBufferDirect());
 
 #if defined(GPU_FUZZER_USE_RASTER_DECODER)
     CHECK(feature_info->feature_flags().chromium_raster_transport);
diff --git a/gpu/command_buffer/tests/gl_manager.cc b/gpu/command_buffer/tests/gl_manager.cc
index bbe571b..bbf2962 100644
--- a/gpu/command_buffer/tests/gl_manager.cc
+++ b/gpu/command_buffer/tests/gl_manager.cc
@@ -195,10 +195,8 @@
 
 class CommandBufferCheckLostContext : public CommandBufferDirect {
  public:
-  CommandBufferCheckLostContext(TransferBufferManager* transfer_buffer_manager,
-                                bool context_lost_allowed)
-      : CommandBufferDirect(transfer_buffer_manager),
-        context_lost_allowed_(context_lost_allowed) {}
+  explicit CommandBufferCheckLostContext(bool context_lost_allowed)
+      : context_lost_allowed_(context_lost_allowed) {}
 
   ~CommandBufferCheckLostContext() override = default;
 
@@ -356,8 +354,8 @@
         &shared_image_manager_);
   }
 
-  command_buffer_.reset(new CommandBufferCheckLostContext(
-      context_group->transfer_buffer_manager(), options.context_lost_allowed));
+  command_buffer_.reset(
+      new CommandBufferCheckLostContext(options.context_lost_allowed));
 
   decoder_.reset(::gpu::gles2::GLES2Decoder::Create(
       command_buffer_.get(), command_buffer_->service(), &outputter_,
@@ -427,9 +425,7 @@
 }
 
 size_t GLManager::GetSharedMemoryBytesAllocated() const {
-  return decoder_->GetContextGroup()
-      ->transfer_buffer_manager()
-      ->shared_memory_bytes_allocated();
+  return command_buffer_->service()->GetSharedMemoryBytesAllocated();
 }
 
 void GLManager::SetupBaseContext() {
diff --git a/gpu/gles2_conform_support/egl/context.cc b/gpu/gles2_conform_support/egl/context.cc
index 06f61d4c..0101e17 100644
--- a/gpu/gles2_conform_support/egl/context.cc
+++ b/gpu/gles2_conform_support/egl/context.cc
@@ -16,7 +16,6 @@
 #include "gpu/command_buffer/service/memory_tracking.h"
 #include "gpu/command_buffer/service/service_discardable_manager.h"
 #include "gpu/command_buffer/service/shared_image_manager.h"
-#include "gpu/command_buffer/service/transfer_buffer_manager.h"
 #include "gpu/gles2_conform_support/egl/config.h"
 #include "gpu/gles2_conform_support/egl/display.h"
 #include "gpu/gles2_conform_support/egl/surface.h"
@@ -267,10 +266,7 @@
       nullptr /* progress_reporter */, gpu_feature_info, &discardable_manager_,
       &passthrough_discardable_manager_, &shared_image_manager_));
 
-  transfer_buffer_manager_ =
-      std::make_unique<gpu::TransferBufferManager>(nullptr);
-  std::unique_ptr<gpu::CommandBufferDirect> command_buffer(
-      new gpu::CommandBufferDirect(transfer_buffer_manager_.get()));
+  auto command_buffer = std::make_unique<gpu::CommandBufferDirect>();
 
   std::unique_ptr<gpu::gles2::GLES2Decoder> decoder(
       gpu::gles2::GLES2Decoder::Create(command_buffer.get(),
diff --git a/gpu/gles2_conform_support/egl/context.h b/gpu/gles2_conform_support/egl/context.h
index 914d3bd0..9a99d9fd 100644
--- a/gpu/gles2_conform_support/egl/context.h
+++ b/gpu/gles2_conform_support/egl/context.h
@@ -111,7 +111,6 @@
   bool is_current_in_some_thread_;
   bool is_destroyed_;
   const gpu::GpuDriverBugWorkarounds gpu_driver_bug_workarounds_;
-  std::unique_ptr<gpu::TransferBufferManager> transfer_buffer_manager_;
   std::unique_ptr<gpu::CommandBufferDirect> command_buffer_;
   std::unique_ptr<gpu::gles2::GLES2CmdHelper> gles2_cmd_helper_;
 
diff --git a/gpu/ipc/in_process_command_buffer.cc b/gpu/ipc/in_process_command_buffer.cc
index 43b28996..9a35f65 100644
--- a/gpu/ipc/in_process_command_buffer.cc
+++ b/gpu/ipc/in_process_command_buffer.cc
@@ -54,7 +54,6 @@
 #include "gpu/command_buffer/service/shared_context_state.h"
 #include "gpu/command_buffer/service/shared_image_factory.h"
 #include "gpu/command_buffer/service/sync_point_manager.h"
-#include "gpu/command_buffer/service/transfer_buffer_manager.h"
 #include "gpu/command_buffer/service/webgpu_decoder.h"
 #include "gpu/config/gpu_crash_keys.h"
 #include "gpu/config/gpu_feature_info.h"
@@ -389,10 +388,6 @@
     return gpu::ContextResult::kTransientFailure;
   }
 
-  // TODO(crbug.com/832243): This could use the TransferBufferManager owned by
-  // |context_group_| instead.
-  transfer_buffer_manager_ = std::make_unique<TransferBufferManager>(nullptr);
-
   GpuDriverBugWorkarounds workarounds(
       task_executor_->gpu_feature_info().enabled_gpu_driver_bug_workarounds);
 
@@ -448,7 +443,7 @@
                                                                         : "0");
 
   command_buffer_ = std::make_unique<CommandBufferService>(
-      this, transfer_buffer_manager_.get());
+      this, context_group_->memory_tracker());
 
   if (!surface_) {
     if (params.is_offscreen) {
@@ -729,7 +724,6 @@
     decoder_.reset();
   }
   command_buffer_.reset();
-  transfer_buffer_manager_.reset();
   surface_ = nullptr;
 
   context_ = nullptr;
diff --git a/gpu/ipc/in_process_command_buffer.h b/gpu/ipc/in_process_command_buffer.h
index a2ac2361..02884084 100644
--- a/gpu/ipc/in_process_command_buffer.h
+++ b/gpu/ipc/in_process_command_buffer.h
@@ -64,7 +64,6 @@
 class SharedImageFactory;
 class SharedImageInterface;
 class SyncPointClientState;
-class TransferBufferManager;
 struct ContextCreationAttribs;
 struct SwapBuffersCompleteParams;
 
@@ -316,7 +315,6 @@
   bool use_virtualized_gl_context_ = false;
   raster::GrShaderCache* gr_shader_cache_ = nullptr;
   scoped_refptr<base::SingleThreadTaskRunner> origin_task_runner_;
-  std::unique_ptr<TransferBufferManager> transfer_buffer_manager_;
   std::unique_ptr<CommandBufferService> command_buffer_;
   std::unique_ptr<DecoderContext> decoder_;
   base::Optional<raster::GrCacheController> gr_cache_controller_;
diff --git a/gpu/ipc/service/command_buffer_stub.cc b/gpu/ipc/service/command_buffer_stub.cc
index de1ea8c..7ac4bed 100644
--- a/gpu/ipc/service/command_buffer_stub.cc
+++ b/gpu/ipc/service/command_buffer_stub.cc
@@ -804,6 +804,16 @@
   return context_group_->memory_tracker();
 }
 
+scoped_refptr<Buffer> CommandBufferStub::GetTransferBuffer(int32_t id) {
+  return command_buffer_->GetTransferBuffer(id);
+}
+
+void CommandBufferStub::RegisterTransferBufferForTest(
+    int32_t id,
+    scoped_refptr<Buffer> buffer) {
+  command_buffer_->RegisterTransferBuffer(id, std::move(buffer));
+}
+
 bool CommandBufferStub::CheckContextLost() {
   DCHECK(command_buffer_);
   CommandBuffer::State state = command_buffer_->GetState();
diff --git a/gpu/ipc/service/command_buffer_stub.h b/gpu/ipc/service/command_buffer_stub.h
index 69fa89e..2b2b8e8d 100644
--- a/gpu/ipc/service/command_buffer_stub.h
+++ b/gpu/ipc/service/command_buffer_stub.h
@@ -113,6 +113,8 @@
   static void SetMemoryTrackerFactoryForTesting(MemoryTrackerFactory factory);
 
   MemoryTracker* GetMemoryTracker() const;
+  scoped_refptr<Buffer> GetTransferBuffer(int32_t id);
+  void RegisterTransferBufferForTest(int32_t id, scoped_refptr<Buffer> buffer);
 
   // Whether this command buffer can currently handle IPC messages.
   bool IsScheduled();
diff --git a/gpu/ipc/service/direct_composition_surface_win.cc b/gpu/ipc/service/direct_composition_surface_win.cc
index f2f7691..4a45504 100644
--- a/gpu/ipc/service/direct_composition_surface_win.cc
+++ b/gpu/ipc/service/direct_composition_surface_win.cc
@@ -1274,7 +1274,10 @@
       is_yuv_swapchain_ ? g_overlay_format_used : OverlayFormat::kBGRA;
   UMA_HISTOGRAM_ENUMERATION("GPU.DirectComposition.SwapChainFormat2",
                             swap_chain_format);
-
+  TRACE_EVENT_INSTANT2(TRACE_DISABLED_BY_DEFAULT("gpu.service"),
+                       "SwapChain::Present", TRACE_EVENT_SCOPE_THREAD,
+                       "PixelFormat", swap_chain_format, "ZeroCopy",
+                       !!decode_swap_chain_);
   HRESULT hr = 0;
   Microsoft::WRL::ComPtr<IDXGISwapChainMedia> swap_chain_media;
   if (decode_swap_chain_) {
@@ -1283,7 +1286,6 @@
     DCHECK(swap_chain_);
     hr = swap_chain_.As(&swap_chain_media);
   }
-
   if (SUCCEEDED(hr)) {
     DCHECK(swap_chain_media);
     DXGI_FRAME_STATISTICS_MEDIA stats = {};
@@ -1294,19 +1296,17 @@
     // Waiting for the DXGI adapter to finish presenting before calling the
     // function doesn't get rid of the failure.
     HRESULT hr = swap_chain_media->GetFrameStatisticsMedia(&stats);
+    int mode = -1;
     if (SUCCEEDED(hr)) {
       base::UmaHistogramSparse("GPU.DirectComposition.CompositionMode",
                                stats.CompositionMode);
       presentation_history_.AddSample(stats.CompositionMode);
-      TRACE_EVENT_INSTANT2(TRACE_DISABLED_BY_DEFAULT("gpu.service"),
-                           "SwapChainFrameInfo", TRACE_EVENT_SCOPE_THREAD,
-                           "SwapChain.PresentationMode", stats.CompositionMode,
-                           "SwapChain.PixelFormat", swap_chain_format);
-    } else {
-      TRACE_EVENT_INSTANT1(
-          TRACE_DISABLED_BY_DEFAULT("gpu.service"), "SwapChainFrameInfoInvalid",
-          TRACE_EVENT_SCOPE_THREAD, "ErrorCode", static_cast<uint32_t>(hr));
+      mode = stats.CompositionMode;
     }
+    // Record CompositionMode as -1 if GetFrameStatisticsMedia() fails.
+    TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("gpu.service"),
+                         "GetFrameStatisticsMedia", TRACE_EVENT_SCOPE_THREAD,
+                         "CompositionMode", mode);
   }
 }
 
diff --git a/gpu/ipc/service/gles2_command_buffer_stub.cc b/gpu/ipc/service/gles2_command_buffer_stub.cc
index d1f37958d..fccec34 100644
--- a/gpu/ipc/service/gles2_command_buffer_stub.cc
+++ b/gpu/ipc/service/gles2_command_buffer_stub.cc
@@ -157,7 +157,7 @@
 #endif
 
   command_buffer_ = std::make_unique<CommandBufferService>(
-      this, context_group_->transfer_buffer_manager());
+      this, context_group_->memory_tracker());
   gles2_decoder_ = gles2::GLES2Decoder::Create(
       this, command_buffer_.get(), manager->outputter(), context_group_.get());
   set_decoder_context(std::unique_ptr<DecoderContext>(gles2_decoder_));
diff --git a/gpu/ipc/service/image_decode_accelerator_stub.cc b/gpu/ipc/service/image_decode_accelerator_stub.cc
index c46fd8f4..eee16ead 100644
--- a/gpu/ipc/service/image_decode_accelerator_stub.cc
+++ b/gpu/ipc/service/image_decode_accelerator_stub.cc
@@ -23,7 +23,6 @@
 #include "gpu/command_buffer/service/service_transfer_cache.h"
 #include "gpu/command_buffer/service/shared_context_state.h"
 #include "gpu/command_buffer/service/sync_point_manager.h"
-#include "gpu/command_buffer/service/transfer_buffer_manager.h"
 #include "gpu/config/gpu_finch_features.h"
 #include "gpu/ipc/common/command_buffer_id.h"
 #include "gpu/ipc/service/command_buffer_stub.h"
@@ -176,12 +175,8 @@
     OnError();
     return;
   }
-  DCHECK(command_buffer->context_group());
-  DCHECK(command_buffer->context_group()->transfer_buffer_manager());
   scoped_refptr<Buffer> handle_buffer =
-      command_buffer->context_group()
-          ->transfer_buffer_manager()
-          ->GetTransferBuffer(params.discardable_handle_shm_id);
+      command_buffer->GetTransferBuffer(params.discardable_handle_shm_id);
   if (!DiscardableHandleBase::ValidateParameters(
           handle_buffer.get(), params.discardable_handle_shm_offset)) {
     DLOG(ERROR) << "Could not validate the discardable handle parameters";
diff --git a/gpu/ipc/service/image_decode_accelerator_stub_unittest.cc b/gpu/ipc/service/image_decode_accelerator_stub_unittest.cc
index 9a80565..292fb5f 100644
--- a/gpu/ipc/service/image_decode_accelerator_stub_unittest.cc
+++ b/gpu/ipc/service/image_decode_accelerator_stub_unittest.cc
@@ -240,22 +240,15 @@
 
     // We need a buffer to make sure that the ImageDecodeAcceleratorStub can
     // create a ServiceDiscardableHandle.
-    scoped_refptr<Buffer> handle_buffer = MakeBufferForTesting();
     CommandBufferStub* command_buffer =
         channel->LookupCommandBuffer(kCommandBufferRouteId);
     if (!command_buffer)
       return SyncToken();
-    scoped_refptr<gles2::ContextGroup> context_group =
-        command_buffer->context_group();
-    if (!context_group)
-      return SyncToken();
-    TransferBufferManager* transfer_buffer_manager =
-        context_group->transfer_buffer_manager();
-    if (!transfer_buffer_manager)
-      return SyncToken();
+
     int32_t buffer_shm_id = GetNextBufferId();
-    transfer_buffer_manager->RegisterTransferBuffer(buffer_shm_id,
-                                                    std::move(handle_buffer));
+    scoped_refptr<Buffer> handle_buffer = MakeBufferForTesting();
+    command_buffer->RegisterTransferBufferForTest(buffer_shm_id,
+                                                  std::move(handle_buffer));
 
     // Send the IPC decode request.
     GpuChannelMsg_ScheduleImageDecode_Params decode_params;
diff --git a/gpu/ipc/service/raster_command_buffer_stub.cc b/gpu/ipc/service/raster_command_buffer_stub.cc
index f673526d..3b856eb 100644
--- a/gpu/ipc/service/raster_command_buffer_stub.cc
+++ b/gpu/ipc/service/raster_command_buffer_stub.cc
@@ -135,7 +135,7 @@
       shared_context_state->use_virtualized_gl_contexts();
 
   command_buffer_ = std::make_unique<CommandBufferService>(
-      this, context_group_->transfer_buffer_manager());
+      this, context_group_->memory_tracker());
   std::unique_ptr<raster::RasterDecoder> decoder(raster::RasterDecoder::Create(
       this, command_buffer_.get(), manager->outputter(), context_group_.get(),
       shared_context_state));
diff --git a/gpu/ipc/service/webgpu_command_buffer_stub.cc b/gpu/ipc/service/webgpu_command_buffer_stub.cc
index 5d5ad50c..1dcc0c0 100644
--- a/gpu/ipc/service/webgpu_command_buffer_stub.cc
+++ b/gpu/ipc/service/webgpu_command_buffer_stub.cc
@@ -101,7 +101,6 @@
   share_group_ = manager->share_group();
   use_virtualized_gl_context_ = false;
 
-  TransferBufferManager* transfer_buffer_manager;
   // TODO: all of this is necessary to get a transfer buffer manager - we would
   // prefer to create a standalone one instead.
   {
@@ -120,12 +119,10 @@
         manager->gpu_feature_info(), manager->discardable_manager(),
         manager->passthrough_discardable_manager(),
         manager->shared_image_manager());
-
-    transfer_buffer_manager = context_group_->transfer_buffer_manager();
   }
 
-  command_buffer_ =
-      std::make_unique<CommandBufferService>(this, transfer_buffer_manager);
+  command_buffer_ = std::make_unique<CommandBufferService>(
+      this, context_group_->memory_tracker());
   std::unique_ptr<webgpu::WebGPUDecoder> decoder(webgpu::WebGPUDecoder::Create(
       this, command_buffer_.get(), manager->outputter()));
 
diff --git a/headless/lib/browser/headless_content_browser_client.cc b/headless/lib/browser/headless_content_browser_client.cc
index 7061fb8b..92da092c 100644
--- a/headless/lib/browser/headless_content_browser_client.cc
+++ b/headless/lib/browser/headless_content_browser_client.cc
@@ -176,7 +176,8 @@
     content::StoragePartition* partition,
     ::storage::OptionalQuotaSettingsCallback callback) {
   ::storage::GetNominalDynamicSettings(
-      partition->GetPath(), context->IsOffTheRecord(), std::move(callback));
+      partition->GetPath(), context->IsOffTheRecord(),
+      ::storage::GetDefaultDiskInfoHelper(), std::move(callback));
 }
 
 content::GeneratedCodeCacheSettings
diff --git a/infra/config/global/cr-buildbucket.cfg b/infra/config/global/cr-buildbucket.cfg
index 69b82ca1..35704bc 100644
--- a/infra/config/global/cr-buildbucket.cfg
+++ b/infra/config/global/cr-buildbucket.cfg
@@ -362,6 +362,14 @@
 }
 
 builder_mixins {
+  name: "linux-debug-cache"
+  caches: {
+    name: "builder"
+    path: "linux_debug"
+  }
+}
+
+builder_mixins {
   name: "linux-optional-gpu-try"
   mixins: "linux"
   mixins: "gpu-optional-try"
@@ -3278,12 +3286,17 @@
     builders { mixins: "linux-try" name: "linux_chromium_compile_dbg_32_ng" }
     builders {
       mixins: "linux-try"
+      mixins: "linux-debug-cache"
       mixins: "goma-j150"
       name: "linux_chromium_compile_dbg_ng"
     }
     builders { mixins: "linux-try" name: "linux_chromium_compile_rel_ng" }
     builders { mixins: "linux-try" name: "linux_chromium_dbg_32_ng" }
-    builders { mixins: "linux-try" name: "linux_chromium_dbg_ng" }
+    builders {
+      mixins: "linux-try"
+      mixins: "linux-debug-cache"
+      name: "linux_chromium_dbg_ng"
+    }
     builders {
       mixins: "linux-try"
       mixins: "goma-j150"
diff --git a/ios/chrome/browser/ui/tab_grid/tab_grid_bottom_toolbar.mm b/ios/chrome/browser/ui/tab_grid/tab_grid_bottom_toolbar.mm
index dcf6cee..1200936 100644
--- a/ios/chrome/browser/ui/tab_grid/tab_grid_bottom_toolbar.mm
+++ b/ios/chrome/browser/ui/tab_grid/tab_grid_bottom_toolbar.mm
@@ -55,8 +55,13 @@
 #pragma mark - Public
 
 - (void)setPage:(TabGridPage)page {
-  if (page == _page)
-    return;
+  // TODO(crbug.com/929981): "traitCollectionDidChange:" method won't get called
+  // when the view is not displayed, and in that case the only chance
+  // TabGridBottomToolbar can update its layout is when the TabGrid sets its
+  // "page" property in the
+  // "viewWillTransitionToSize:withTransitionCoordinator:" method. An early
+  // return for "self.page == page" can be added here once UIKit fixes its
+  // issue or TabGridBottomToolbar is turned into a view controller.
   _page = page;
   self.newTabButton.page = page;
   [self updateLayout];
@@ -130,10 +135,16 @@
 
 // Returns YES if should use compact bottom toolbar layout.
 - (BOOL)shouldUseCompactLayout {
-  return self.traitCollection.verticalSizeClass ==
-             UIUserInterfaceSizeClassRegular &&
-         self.traitCollection.horizontalSizeClass ==
-             UIUserInterfaceSizeClassCompact;
+  // TODO(crbug.com/929981): UIView's |traitCollection| can be wrong and
+  // contradict the keyWindow's |traitCollection| because UIView's
+  // |-traitCollectionDidChange:| is not properly called when the view rotates
+  // while it is in a ViewController deeper in the ViewController hierarchy. Use
+  // self.traitCollection once this is fixed by UIKit, or remove this function
+  // if TabGridBottomToolbar is turned into a view controller.
+  return UIApplication.sharedApplication.keyWindow.traitCollection
+                 .verticalSizeClass == UIUserInterfaceSizeClassRegular &&
+         UIApplication.sharedApplication.keyWindow.traitCollection
+                 .horizontalSizeClass == UIUserInterfaceSizeClassCompact;
 }
 
 @end
diff --git a/ios/chrome/test/earl_grey/BUILD.gn b/ios/chrome/test/earl_grey/BUILD.gn
index 54f38a1..93a8c08 100644
--- a/ios/chrome/test/earl_grey/BUILD.gn
+++ b/ios/chrome/test/earl_grey/BUILD.gn
@@ -221,6 +221,8 @@
     "chrome_earl_grey_ui.mm",
     "chrome_matchers.h",
     "chrome_matchers.mm",
+    "chrome_matchers_shorthand.h",
+    "chrome_matchers_shorthand.mm",
     "chrome_test_case.h",
     "chrome_test_case.mm",
   ]
diff --git a/ios/chrome/test/earl_grey/chrome_matchers.h b/ios/chrome/test/earl_grey/chrome_matchers.h
index 6173d1b..ba879f7c 100644
--- a/ios/chrome/test/earl_grey/chrome_matchers.h
+++ b/ios/chrome/test/earl_grey/chrome_matchers.h
@@ -9,259 +9,262 @@
 
 #include <string>
 
+#import "ios/chrome/test/earl_grey/chrome_matchers_shorthand.h"
+
 @protocol GREYMatcher;
 
-namespace chrome_test_util {
-
-// Matcher for element with accessibility label corresponding to |message_id|
-// and accessibility trait UIAccessibilityTraitButton.
-id<GREYMatcher> ButtonWithAccessibilityLabelId(int message_id);
+@interface ChromeMatchers : NSObject
 
 // Matcher for element with accessibility label corresponding to |label| and
 // accessibility trait UIAccessibilityTraitButton.
-id<GREYMatcher> ButtonWithAccessibilityLabel(NSString* label);
++ (id<GREYMatcher>)buttonWithAccessibilityLabel:(NSString*)label;
 
-// Matcher for element with an image corresponding to |image_id|.
-id<GREYMatcher> ImageViewWithImage(int image_id);
+// Matcher for element with accessibility label corresponding to |messageId|
+// and accessibility trait UIAccessibilityTraitButton.
++ (id<GREYMatcher>)buttonWithAccessibilityLabelId:(int)messageId;
+
+// Matcher for element with an image corresponding to |imageId|.
++ (id<GREYMatcher>)imageViewWithImage:(int)imageId;
 
 // Matcher for element with an image defined by its name in the main bundle.
-id<GREYMatcher> ImageViewWithImageNamed(NSString* imageName);
++ (id<GREYMatcher>)imageViewWithImageNamed:(NSString*)imageName;
 
-// Matcher for element with an image corresponding to |image_id| and
+// Matcher for element with an image corresponding to |imageId| and
 // accessibility trait UIAccessibilityTraitButton.
-id<GREYMatcher> ButtonWithImage(int image_id);
++ (id<GREYMatcher>)buttonWithImage:(int)imageId;
 
-// Matcher for element with accessibility label corresponding to |message_id|
+// Matcher for element with accessibility label corresponding to |messageId|
 // and accessibility trait UIAccessibilityTraitStaticText.
-id<GREYMatcher> StaticTextWithAccessibilityLabelId(int message_id);
++ (id<GREYMatcher>)staticTextWithAccessibilityLabelId:(int)messageId;
 
 // Matcher for element with accessibility label corresponding to |label| and
 // accessibility trait UIAccessibilityTraitStaticText.
-id<GREYMatcher> StaticTextWithAccessibilityLabel(NSString* label);
++ (id<GREYMatcher>)staticTextWithAccessibilityLabel:(NSString*)label;
 
-// Matcher for element with accessibility label corresponding to |message_id|
+// Matcher for element with accessibility label corresponding to |messageId|
 // and accessibility trait UIAccessibilityTraitHeader.
-id<GREYMatcher> HeaderWithAccessibilityLabelId(int message_id);
++ (id<GREYMatcher>)headerWithAccessibilityLabelId:(int)messageId;
 
 // Matcher for element with accessibility label corresponding to |label| and
 // accessibility trait UIAccessibilityTraitHeader.
-id<GREYMatcher> HeaderWithAccessibilityLabel(NSString* label);
++ (id<GREYMatcher>)headerWithAccessibilityLabel:(NSString*)label;
 
 // Returns matcher for a cancel button.
-id<GREYMatcher> CancelButton();
++ (id<GREYMatcher>)cancelButton;
 
 // Returns matcher for a close button.
-id<GREYMatcher> CloseButton();
++ (id<GREYMatcher>)closeButton;
 
 // Matcher for the navigate forward button.
-id<GREYMatcher> ForwardButton();
++ (id<GREYMatcher>)forwardButton;
 
 // Matcher for the navigate backward button.
-id<GREYMatcher> BackButton();
++ (id<GREYMatcher>)backButton;
 
 // Matcher for the reload button.
-id<GREYMatcher> ReloadButton();
++ (id<GREYMatcher>)reloadButton;
 
 // Matcher for the stop loading button.
-id<GREYMatcher> StopButton();
++ (id<GREYMatcher>)stopButton;
 
 // Returns a matcher for the omnibox.
-id<GREYMatcher> Omnibox();
++ (id<GREYMatcher>)omnibox;
 
 // Returns a matcher for the location view.
-id<GREYMatcher> DefocusedLocationView();
++ (id<GREYMatcher>)defocusedLocationView;
 
 // Returns a matcher for the page security info button.
-id<GREYMatcher> PageSecurityInfoButton();
++ (id<GREYMatcher>)pageSecurityInfoButton;
+
 // Returns a matcher for the page security info indicator.
-id<GREYMatcher> PageSecurityInfoIndicator();
++ (id<GREYMatcher>)pageSecurityInfoIndicator;
 
 // Returns matcher for omnibox containing |text|. Performs an exact match of the
 // omnibox contents.
-id<GREYMatcher> OmniboxText(std::string text);
++ (id<GREYMatcher>)omniboxText:(std::string)text;
 
 // Returns matcher for |text| being a substring of the text in the omnibox.
-id<GREYMatcher> OmniboxContainingText(std::string text);
++ (id<GREYMatcher>)omniboxContainingText:(std::string)text;
 
 // Returns matcher for |text| being a substring of the text in the location
 // view.
-id<GREYMatcher> LocationViewContainingText(std::string text);
++ (id<GREYMatcher>)locationViewContainingText:(std::string)text;
 
 // Matcher for Tools menu button.
-id<GREYMatcher> ToolsMenuButton();
++ (id<GREYMatcher>)toolsMenuButton;
 
 // Matcher for the Share menu button.
-id<GREYMatcher> ShareButton();
++ (id<GREYMatcher>)shareButton;
 
 // Returns the GREYMatcher for the button that opens the tab switcher.
-id<GREYMatcher> TabletTabSwitcherOpenButton();
++ (id<GREYMatcher>)tabletTabSwitcherOpenButton;
 
 // Matcher for show tabs button.
-id<GREYMatcher> ShowTabsButton();
++ (id<GREYMatcher>)showTabsButton;
 
 // Matcher for SettingsSwitchCell.
-id<GREYMatcher> SettingsSwitchCell(NSString* accessibility_identifier,
-                                   BOOL is_toggled_on);
++ (id<GREYMatcher>)settingsSwitchCell:(NSString*)accessibilityIdentifier
+                          isToggledOn:(BOOL)isToggledOn;
 
 // Matcher for SettingsSwitchCell.
-id<GREYMatcher> SettingsSwitchCell(NSString* accessibility_identifier,
-                                   BOOL is_toggled_on,
-                                   BOOL is_enabled);
++ (id<GREYMatcher>)settingsSwitchCell:(NSString*)accessibilityIdentifier
+                          isToggledOn:(BOOL)isToggledOn
+                            isEnabled:(BOOL)isEnabled;
 
 // Matcher for SyncSwitchCell.
-id<GREYMatcher> SyncSwitchCell(NSString* accessibility_label,
-                               BOOL is_toggled_on);
++ (id<GREYMatcher>)syncSwitchCell:(NSString*)accessibilityLabel
+                      isToggledOn:(BOOL)isToggledOn;
 
 // Matcher for the Open in New Tab option in the context menu when long pressing
 // a link.
-id<GREYMatcher> OpenLinkInNewTabButton();
++ (id<GREYMatcher>)openLinkInNewTabButton;
 
 // Matcher for the done button on the navigation bar.
-id<GREYMatcher> NavigationBarDoneButton();
++ (id<GREYMatcher>)navigationBarDoneButton;
 
 // Matcher for the done button on the Bookmarks navigation bar.
-id<GREYMatcher> BookmarksNavigationBarDoneButton();
++ (id<GREYMatcher>)bookmarksNavigationBarDoneButton;
 
 // Returns matcher for the account consistency setup signin button.
-id<GREYMatcher> AccountConsistencySetupSigninButton();
++ (id<GREYMatcher>)accountConsistencySetupSigninButton;
 
 // Returns matcher for the account consistency confirmation button.
-id<GREYMatcher> AccountConsistencyConfirmationOkButton();
++ (id<GREYMatcher>)accountConsistencyConfirmationOkButton;
 
 // Returns matcher for the add account accounts button.
-id<GREYMatcher> AddAccountButton();
++ (id<GREYMatcher>)addAccountButton;
 
 // Returns matcher for the sign out accounts button.
-id<GREYMatcher> SignOutAccountsButton();
++ (id<GREYMatcher>)signOutAccountsButton;
 
 // Returns matcher for the Clear Browsing Data cell on the Privacy screen.
-id<GREYMatcher> ClearBrowsingDataCell();
++ (id<GREYMatcher>)clearBrowsingDataCell;
 
 // Returns matcher for the clear browsing data button on the clear browsing data
 // panel.
-id<GREYMatcher> ClearBrowsingDataButton();
++ (id<GREYMatcher>)clearBrowsingDataButton;
 
 // Returns matcher for the clear browsing data collection view.
-id<GREYMatcher> ClearBrowsingDataCollectionView();
++ (id<GREYMatcher>)clearBrowsingDataCollectionView;
 
 // Matcher for the clear browsing data action sheet item.
-id<GREYMatcher> ConfirmClearBrowsingDataButton();
++ (id<GREYMatcher>)confirmClearBrowsingDataButton;
 
 // Returns matcher for the settings button in the tools menu.
-id<GREYMatcher> SettingsMenuButton();
++ (id<GREYMatcher>)settingsMenuButton;
 
 // Returns matcher for the "Done" button in the settings' navigation bar.
-id<GREYMatcher> SettingsDoneButton();
++ (id<GREYMatcher>)settingsDoneButton;
 
 // Returns matcher for the tools menu table view.
-id<GREYMatcher> ToolsMenuView();
++ (id<GREYMatcher>)toolsMenuView;
 
 // Returns matcher for the OK button.
-id<GREYMatcher> OKButton();
++ (id<GREYMatcher>)okButton;
 
 // Returns matcher for the primary button in the sign-in promo view. This is
 // "Sign in into Chrome" button for a cold state, or "Continue as John Doe" for
 // a warm state.
-id<GREYMatcher> PrimarySignInButton();
++ (id<GREYMatcher>)primarySignInButton;
 
 // Returns matcher for the secondary button in the sign-in promo view. This is
 // "Not johndoe@example.com" button.
-id<GREYMatcher> SecondarySignInButton();
++ (id<GREYMatcher>)secondarySignInButton;
 
 // Returns matcher for the button for the currently signed in account in the
 // settings menu.
-id<GREYMatcher> SettingsAccountButton();
++ (id<GREYMatcher>)settingsAccountButton;
 
 // Returns matcher for the accounts collection view.
-id<GREYMatcher> SettingsAccountsCollectionView();
++ (id<GREYMatcher>)settingsAccountsCollectionView;
 
 // Returns matcher for the Import Data cell in switch sync account view.
-id<GREYMatcher> SettingsImportDataImportButton();
++ (id<GREYMatcher>)settingsImportDataImportButton;
 
 // Returns matcher for the Keep Data Separate cell in switch sync account view.
-id<GREYMatcher> SettingsImportDataKeepSeparateButton();
++ (id<GREYMatcher>)settingsImportDataKeepSeparateButton;
 
 // Returns matcher for the Manage Synced Data button in sync setting view.
-id<GREYMatcher> SettingsSyncManageSyncedDataButton();
++ (id<GREYMatcher>)settingsSyncManageSyncedDataButton;
 
 // Returns matcher for the menu button to sync accounts.
-id<GREYMatcher> AccountsSyncButton();
++ (id<GREYMatcher>)accountsSyncButton;
 
 // Returns matcher for the Content Settings button on the main Settings screen.
-id<GREYMatcher> ContentSettingsButton();
++ (id<GREYMatcher>)contentSettingsButton;
 
 // Returns matcher for the Google Services Settings button on the main Settings
 // screen.
-id<GREYMatcher> GoogleServicesSettingsButton();
++ (id<GREYMatcher>)googleServicesSettingsButton;
 
 // Returns matcher for the back button on a settings menu.
-id<GREYMatcher> SettingsMenuBackButton();
++ (id<GREYMatcher>)settingsMenuBackButton;
 
 // Returns matcher for the Privacy cell on the main Settings screen.
-id<GREYMatcher> SettingsMenuPrivacyButton();
++ (id<GREYMatcher>)settingsMenuPrivacyButton;
 
 // Returns matcher for the Save passwords cell on the main Settings screen.
-id<GREYMatcher> SettingsMenuPasswordsButton();
++ (id<GREYMatcher>)settingsMenuPasswordsButton;
 
 // Returns matcher for the payment request collection view.
-id<GREYMatcher> PaymentRequestView();
++ (id<GREYMatcher>)paymentRequestView;
 
 // Returns matcher for the error confirmation view for payment request.
-id<GREYMatcher> PaymentRequestErrorView();
++ (id<GREYMatcher>)paymentRequestErrorView;
 
 // Returns matcher for the voice search button on the main Settings screen.
-id<GREYMatcher> VoiceSearchButton();
++ (id<GREYMatcher>)voiceSearchButton;
 
 // Returns matcher for the settings main menu view.
-id<GREYMatcher> SettingsCollectionView();
++ (id<GREYMatcher>)settingsCollectionView;
 
 // Returns matcher for the clear browsing history cell on the clear browsing
 // data panel.
-id<GREYMatcher> ClearBrowsingHistoryButton();
++ (id<GREYMatcher>)clearBrowsingHistoryButton;
 
 // Returns matcher for the clear cookies cell on the clear browsing data panel.
-id<GREYMatcher> ClearCookiesButton();
++ (id<GREYMatcher>)clearCookiesButton;
 
 // Returns matcher for the clear cache cell on the clear browsing data panel.
-id<GREYMatcher> ClearCacheButton();
++ (id<GREYMatcher>)clearCacheButton;
 
 // Returns matcher for the clear saved passwords cell on the clear browsing data
 // panel.
-id<GREYMatcher> ClearSavedPasswordsButton();
++ (id<GREYMatcher>)clearSavedPasswordsButton;
 
 // Returns matcher for the collection view of content suggestion.
-id<GREYMatcher> ContentSuggestionCollectionView();
++ (id<GREYMatcher>)contentSuggestionCollectionView;
 
 // Returns matcher for the warning message while filling in payment requests.
-id<GREYMatcher> WarningMessageView();
++ (id<GREYMatcher>)warningMessageView;
 
 // Returns matcher for the payment picker cell.
-id<GREYMatcher> PaymentRequestPickerRow();
++ (id<GREYMatcher>)paymentRequestPickerRow;
 
 // Returns matcher for the payment request search bar.
-id<GREYMatcher> PaymentRequestPickerSearchBar();
++ (id<GREYMatcher>)paymentRequestPickerSearchBar;
 
 // Returns matcher for the bookmarks button on the Tools menu.
-id<GREYMatcher> BookmarksMenuButton();
++ (id<GREYMatcher>)bookmarksMenuButton;
 
 // Returns matcher for the recent tabs button on the Tools menu.
-id<GREYMatcher> RecentTabsMenuButton();
++ (id<GREYMatcher>)recentTabsMenuButton;
 
 // Returns matcher for the system selection callout.
-id<GREYMatcher> SystemSelectionCallout();
++ (id<GREYMatcher>)systemSelectionCallout;
 
 // Returns matcher for the copy button on the system selection callout.
-id<GREYMatcher> SystemSelectionCalloutCopyButton();
++ (id<GREYMatcher>)systemSelectionCalloutCopyButton;
 
 // Returns matcher for the Copy item on the context menu.
-id<GREYMatcher> ContextMenuCopyButton();
++ (id<GREYMatcher>)contextMenuCopyButton;
 
 // Returns matcher for defoucesed omnibox on a new tab.
-id<GREYMatcher> NewTabPageOmnibox();
++ (id<GREYMatcher>)NTPOmnibox;
 
 // Returns a matcher for the current WebView.
-id<GREYMatcher> WebViewMatcher();
++ (id<GREYMatcher>)webViewMatcher;
 
-}  // namespace chrome_test_util
+@end
 
 #endif  // IOS_CHROME_TEST_EARL_GREY_CHROME_MATCHERS_H_
diff --git a/ios/chrome/test/earl_grey/chrome_matchers.mm b/ios/chrome/test/earl_grey/chrome_matchers.mm
index 46b2e3c..264f4f60 100644
--- a/ios/chrome/test/earl_grey/chrome_matchers.mm
+++ b/ios/chrome/test/earl_grey/chrome_matchers.mm
@@ -47,36 +47,35 @@
 
 namespace {
 
-id<GREYMatcher> SettingsSwitchIsToggledOn(BOOL is_toggled_on) {
+id<GREYMatcher> SettingsSwitchIsToggledOn(BOOL isToggledOn) {
   MatchesBlock matches = ^BOOL(id element) {
     SettingsSwitchCell* switch_cell =
         base::mac::ObjCCastStrict<SettingsSwitchCell>(element);
     UISwitch* switch_view = switch_cell.switchView;
-    return (switch_view.on && is_toggled_on) ||
-           (!switch_view.on && !is_toggled_on);
+    return (switch_view.on && isToggledOn) || (!switch_view.on && !isToggledOn);
   };
   DescribeToBlock describe = ^void(id<GREYDescription> description) {
     NSString* name =
         [NSString stringWithFormat:@"settingsSwitchToggledState(%@)",
-                                   is_toggled_on ? @"ON" : @"OFF"];
+                                   isToggledOn ? @"ON" : @"OFF"];
     [description appendText:name];
   };
   return [[GREYElementMatcherBlock alloc] initWithMatchesBlock:matches
                                               descriptionBlock:describe];
 }
 
-id<GREYMatcher> SettingsSwitchIsEnabled(BOOL is_enabled) {
+id<GREYMatcher> SettingsSwitchIsEnabled(BOOL isEnabled) {
   MatchesBlock matches = ^BOOL(id element) {
     SettingsSwitchCell* switch_cell =
         base::mac::ObjCCastStrict<SettingsSwitchCell>(element);
     UISwitch* switch_view = switch_cell.switchView;
-    return (switch_view.enabled && is_enabled) ||
-           (!switch_view.enabled && !is_enabled);
+    return (switch_view.enabled && isEnabled) ||
+           (!switch_view.enabled && !isEnabled);
   };
   DescribeToBlock describe = ^void(id<GREYDescription> description) {
     NSString* name =
         [NSString stringWithFormat:@"settingsSwitchEnabledState(%@)",
-                                   is_enabled ? @"YES" : @"NO"];
+                                   isEnabled ? @"YES" : @"NO"];
     [description appendText:name];
   };
   return [[GREYElementMatcherBlock alloc] initWithMatchesBlock:matches
@@ -101,132 +100,135 @@
 
 }  // namespace
 
-namespace chrome_test_util {
+@implementation ChromeMatchers
 
-id<GREYMatcher> ButtonWithAccessibilityLabel(NSString* label) {
++ (id<GREYMatcher>)buttonWithAccessibilityLabel:(NSString*)label {
   return grey_allOf(grey_accessibilityLabel(label),
                     grey_accessibilityTrait(UIAccessibilityTraitButton), nil);
 }
 
-id<GREYMatcher> ButtonWithAccessibilityLabelId(int message_id) {
-  return ButtonWithAccessibilityLabel(
-      l10n_util::GetNSStringWithFixup(message_id));
++ (id<GREYMatcher>)buttonWithAccessibilityLabelId:(int)messageId {
+  return [ChromeMatchers
+      buttonWithAccessibilityLabel:l10n_util::GetNSStringWithFixup(messageId)];
 }
 
-id<GREYMatcher> ImageViewWithImageNamed(NSString* imageName) {
-  UIImage* expected_image = [UIImage imageNamed:imageName];
++ (id<GREYMatcher>)imageViewWithImageNamed:(NSString*)imageName {
+  UIImage* expectedImage = [UIImage imageNamed:imageName];
   MatchesBlock matches = ^BOOL(UIImageView* imageView) {
-    return ui::test::uiimage_utils::UIImagesAreEqual(expected_image,
+    return ui::test::uiimage_utils::UIImagesAreEqual(expectedImage,
                                                      imageView.image);
   };
-  NSString* description_string =
+  NSString* descriptionString =
       [NSString stringWithFormat:@"Images matching image named %@", imageName];
   DescribeToBlock describe = ^(id<GREYDescription> description) {
-    [description appendText:description_string];
+    [description appendText:descriptionString];
   };
-  id<GREYMatcher> image_matcher =
+  id<GREYMatcher> imageMatcher =
       [[GREYElementMatcherBlock alloc] initWithMatchesBlock:matches
                                            descriptionBlock:describe];
-  return image_matcher;
+  return imageMatcher;
 }
 
-id<GREYMatcher> ImageViewWithImage(int image_id) {
-  UIImage* expected_image = NativeImage(image_id);
++ (id<GREYMatcher>)imageViewWithImage:(int)imageId {
+  UIImage* expectedImage = NativeImage(imageId);
   MatchesBlock matches = ^BOOL(UIImageView* imageView) {
-    return ui::test::uiimage_utils::UIImagesAreEqual(expected_image,
+    return ui::test::uiimage_utils::UIImagesAreEqual(expectedImage,
                                                      imageView.image);
   };
-  NSString* description_string =
-      [NSString stringWithFormat:@"Images matching %i", image_id];
+  NSString* descriptionString =
+      [NSString stringWithFormat:@"Images matching %i", imageId];
   DescribeToBlock describe = ^(id<GREYDescription> description) {
-    [description appendText:description_string];
+    [description appendText:descriptionString];
   };
-  id<GREYMatcher> image_matcher =
+  id<GREYMatcher> imageMatcher =
       [[GREYElementMatcherBlock alloc] initWithMatchesBlock:matches
                                            descriptionBlock:describe];
-  return image_matcher;
+  return imageMatcher;
 }
 
-id<GREYMatcher> ButtonWithImage(int image_id) {
-  UIImage* expected_image = NativeImage(image_id);
++ (id<GREYMatcher>)buttonWithImage:(int)imageId {
+  UIImage* expectedImage = NativeImage(imageId);
   MatchesBlock matches = ^BOOL(UIButton* button) {
-    return ui::test::uiimage_utils::UIImagesAreEqual(expected_image,
+    return ui::test::uiimage_utils::UIImagesAreEqual(expectedImage,
                                                      [button currentImage]);
   };
-  NSString* description_string =
-      [NSString stringWithFormat:@"Images matching %i", image_id];
+  NSString* descriptionString =
+      [NSString stringWithFormat:@"Images matching %i", imageId];
   DescribeToBlock describe = ^(id<GREYDescription> description) {
-    [description appendText:description_string];
+    [description appendText:descriptionString];
   };
-  id<GREYMatcher> image_matcher =
+  id<GREYMatcher> imageMatcher =
       [[GREYElementMatcherBlock alloc] initWithMatchesBlock:matches
                                            descriptionBlock:describe];
   return grey_allOf(grey_accessibilityTrait(UIAccessibilityTraitButton),
-                    image_matcher, nil);
+                    imageMatcher, nil);
 }
 
-id<GREYMatcher> StaticTextWithAccessibilityLabelId(int message_id) {
-  return StaticTextWithAccessibilityLabel(
-      l10n_util::GetNSStringWithFixup(message_id));
++ (id<GREYMatcher>)staticTextWithAccessibilityLabelId:(int)messageId {
+  return [ChromeMatchers
+      staticTextWithAccessibilityLabel:(l10n_util::GetNSStringWithFixup(
+                                           messageId))];
 }
 
-id<GREYMatcher> StaticTextWithAccessibilityLabel(NSString* label) {
++ (id<GREYMatcher>)staticTextWithAccessibilityLabel:(NSString*)label {
   return grey_allOf(grey_accessibilityLabel(label),
                     grey_accessibilityTrait(UIAccessibilityTraitStaticText),
                     nil);
 }
 
-id<GREYMatcher> HeaderWithAccessibilityLabelId(int message_id) {
-  return HeaderWithAccessibilityLabel(
-      l10n_util::GetNSStringWithFixup(message_id));
++ (id<GREYMatcher>)headerWithAccessibilityLabelId:(int)messageId {
+  return [ChromeMatchers
+      headerWithAccessibilityLabel:(l10n_util::GetNSStringWithFixup(
+                                       messageId))];
 }
 
-id<GREYMatcher> HeaderWithAccessibilityLabel(NSString* label) {
++ (id<GREYMatcher>)headerWithAccessibilityLabel:(NSString*)label {
   return grey_allOf(grey_accessibilityLabel(label),
                     grey_accessibilityTrait(UIAccessibilityTraitHeader), nil);
 }
 
-id<GREYMatcher> CancelButton() {
-  return ButtonWithAccessibilityLabelId(IDS_CANCEL);
++ (id<GREYMatcher>)cancelButton {
+  return [ChromeMatchers buttonWithAccessibilityLabelId:(IDS_CANCEL)];
 }
 
-id<GREYMatcher> CloseButton() {
-  return ButtonWithAccessibilityLabelId(IDS_CLOSE);
++ (id<GREYMatcher>)closeButton {
+  return [ChromeMatchers buttonWithAccessibilityLabelId:(IDS_CLOSE)];
 }
 
-id<GREYMatcher> ForwardButton() {
-  return ButtonWithAccessibilityLabelId(IDS_ACCNAME_FORWARD);
++ (id<GREYMatcher>)forwardButton {
+  return [ChromeMatchers buttonWithAccessibilityLabelId:(IDS_ACCNAME_FORWARD)];
 }
 
-id<GREYMatcher> BackButton() {
-  return ButtonWithAccessibilityLabelId(IDS_ACCNAME_BACK);
++ (id<GREYMatcher>)backButton {
+  return [ChromeMatchers buttonWithAccessibilityLabelId:(IDS_ACCNAME_BACK)];
 }
 
-id<GREYMatcher> ReloadButton() {
-  return ButtonWithAccessibilityLabelId(IDS_IOS_ACCNAME_RELOAD);
++ (id<GREYMatcher>)reloadButton {
+  return
+      [ChromeMatchers buttonWithAccessibilityLabelId:(IDS_IOS_ACCNAME_RELOAD)];
 }
 
-id<GREYMatcher> StopButton() {
-  return ButtonWithAccessibilityLabelId(IDS_IOS_ACCNAME_STOP);
++ (id<GREYMatcher>)stopButton {
+  return [ChromeMatchers buttonWithAccessibilityLabelId:(IDS_IOS_ACCNAME_STOP)];
 }
 
-id<GREYMatcher> Omnibox() {
++ (id<GREYMatcher>)omnibox {
   return grey_kindOfClass([OmniboxTextFieldIOS class]);
 }
 
-id<GREYMatcher> DefocusedLocationView() {
++ (id<GREYMatcher>)defocusedLocationView {
   return grey_kindOfClass([LocationBarSteadyView class]);
 }
 
-id<GREYMatcher> PageSecurityInfoButton() {
++ (id<GREYMatcher>)pageSecurityInfoButton {
   return grey_accessibilityLabel(@"Page Security Info");
 }
 
-id<GREYMatcher> PageSecurityInfoIndicator() {
++ (id<GREYMatcher>)pageSecurityInfoIndicator {
   return grey_accessibilityLabel(@"Page Security Info");
 }
 
-id<GREYMatcher> OmniboxText(std::string text) {
++ (id<GREYMatcher>)omniboxText:(std::string)text {
   GREYElementMatcherBlock* matcher = [GREYElementMatcherBlock
       matcherWithMatchesBlock:^BOOL(id element) {
         OmniboxTextFieldIOS* omnibox =
@@ -242,7 +244,7 @@
   return matcher;
 }
 
-id<GREYMatcher> OmniboxContainingText(std::string text) {
++ (id<GREYMatcher>)omniboxContainingText:(std::string)text {
   GREYElementMatcherBlock* matcher = [GREYElementMatcherBlock
       matcherWithMatchesBlock:^BOOL(UITextField* element) {
         return [element.text containsString:base::SysUTF8ToNSString(text)];
@@ -256,7 +258,7 @@
   return matcher;
 }
 
-id<GREYMatcher> LocationViewContainingText(std::string text) {
++ (id<GREYMatcher>)locationViewContainingText:(std::string)text {
   GREYElementMatcherBlock* matcher = [GREYElementMatcherBlock
       matcherWithMatchesBlock:^BOOL(LocationBarSteadyView* element) {
         return [element.locationLabel.text
@@ -272,161 +274,171 @@
   return matcher;
 }
 
-id<GREYMatcher> ToolsMenuButton() {
++ (id<GREYMatcher>)toolsMenuButton {
   return grey_allOf(grey_accessibilityID(kToolbarToolsMenuButtonIdentifier),
                     grey_sufficientlyVisible(), nil);
 }
 
-id<GREYMatcher> ShareButton() {
-  return grey_allOf(ButtonWithAccessibilityLabelId(IDS_IOS_TOOLS_MENU_SHARE),
-                    grey_sufficientlyVisible(), nil);
++ (id<GREYMatcher>)shareButton {
+  return grey_allOf(
+      [ChromeMatchers
+          buttonWithAccessibilityLabelId:(IDS_IOS_TOOLS_MENU_SHARE)],
+      grey_sufficientlyVisible(), nil);
 }
 
-id<GREYMatcher> TabletTabSwitcherOpenButton() {
-  return ButtonWithAccessibilityLabelId(IDS_IOS_TAB_STRIP_ENTER_TAB_SWITCHER);
++ (id<GREYMatcher>)tabletTabSwitcherOpenButton {
+  return [ChromeMatchers
+      buttonWithAccessibilityLabelId:(IDS_IOS_TAB_STRIP_ENTER_TAB_SWITCHER)];
 }
 
-id<GREYMatcher> ShowTabsButton() {
++ (id<GREYMatcher>)showTabsButton {
   return grey_allOf(grey_accessibilityID(kToolbarStackButtonIdentifier),
                     grey_sufficientlyVisible(), nil);
 }
 
-id<GREYMatcher> SettingsSwitchCell(NSString* accessibility_identifier,
-                                   BOOL is_toggled_on) {
-  return SettingsSwitchCell(accessibility_identifier, is_toggled_on, YES);
++ (id<GREYMatcher>)settingsSwitchCell:(NSString*)accessibilityIdentifier
+                          isToggledOn:(BOOL)isToggledOn {
+  return [ChromeMatchers settingsSwitchCell:accessibilityIdentifier
+                                isToggledOn:isToggledOn
+                                  isEnabled:YES];
 }
 
-id<GREYMatcher> SettingsSwitchCell(NSString* accessibility_identifier,
-                                   BOOL is_toggled_on,
-                                   BOOL is_enabled) {
-  return grey_allOf(grey_accessibilityID(accessibility_identifier),
-                    SettingsSwitchIsToggledOn(is_toggled_on),
-                    SettingsSwitchIsEnabled(is_enabled),
++ (id<GREYMatcher>)settingsSwitchCell:(NSString*)accessibilityIdentifier
+                          isToggledOn:(BOOL)isToggledOn
+                            isEnabled:(BOOL)isEnabled {
+  return grey_allOf(grey_accessibilityID(accessibilityIdentifier),
+                    SettingsSwitchIsToggledOn(isToggledOn),
+                    SettingsSwitchIsEnabled(isEnabled),
                     grey_sufficientlyVisible(), nil);
 }
 
-id<GREYMatcher> SyncSwitchCell(NSString* accessibility_label,
-                               BOOL is_toggled_on) {
++ (id<GREYMatcher>)syncSwitchCell:(NSString*)accessibilityLabel
+                      isToggledOn:(BOOL)isToggledOn {
   return grey_allOf(
-      grey_accessibilityLabel(accessibility_label),
+      grey_accessibilityLabel(accessibilityLabel),
       grey_accessibilityValue(
-          is_toggled_on ? l10n_util::GetNSString(IDS_IOS_SETTING_ON)
-                        : l10n_util::GetNSString(IDS_IOS_SETTING_OFF)),
+          isToggledOn ? l10n_util::GetNSString(IDS_IOS_SETTING_ON)
+                      : l10n_util::GetNSString(IDS_IOS_SETTING_OFF)),
       grey_sufficientlyVisible(), nil);
 }
 
-id<GREYMatcher> OpenLinkInNewTabButton() {
-  return ButtonWithAccessibilityLabelId(IDS_IOS_CONTENT_CONTEXT_OPENLINKNEWTAB);
++ (id<GREYMatcher>)openLinkInNewTabButton {
+  return [ChromeMatchers
+      buttonWithAccessibilityLabelId:(IDS_IOS_CONTENT_CONTEXT_OPENLINKNEWTAB)];
 }
 
-id<GREYMatcher> NavigationBarDoneButton() {
++ (id<GREYMatcher>)navigationBarDoneButton {
   return grey_allOf(
-      ButtonWithAccessibilityLabelId(IDS_IOS_NAVIGATION_BAR_DONE_BUTTON),
+      [ChromeMatchers
+          buttonWithAccessibilityLabelId:(IDS_IOS_NAVIGATION_BAR_DONE_BUTTON)],
       grey_userInteractionEnabled(), nil);
 }
 
-id<GREYMatcher> BookmarksNavigationBarDoneButton() {
++ (id<GREYMatcher>)bookmarksNavigationBarDoneButton {
   return grey_accessibilityID(kBookmarkHomeNavigationBarDoneButtonIdentifier);
 }
 
-id<GREYMatcher> AccountConsistencySetupSigninButton() {
-  return ButtonWithAccessibilityLabelId(
-      IDS_IOS_ACCOUNT_CONSISTENCY_SETUP_SIGNIN_BUTTON);
++ (id<GREYMatcher>)accountConsistencySetupSigninButton {
+  return [ChromeMatchers buttonWithAccessibilityLabelId:
+                             (IDS_IOS_ACCOUNT_CONSISTENCY_SETUP_SIGNIN_BUTTON)];
 }
 
-id<GREYMatcher> AccountConsistencyConfirmationOkButton() {
++ (id<GREYMatcher>)accountConsistencyConfirmationOkButton {
   int labelID = base::FeatureList::IsEnabled(unified_consent::kUnifiedConsent)
                     ? IDS_IOS_ACCOUNT_UNIFIED_CONSENT_OK_BUTTON
                     : IDS_IOS_ACCOUNT_CONSISTENCY_CONFIRMATION_OK_BUTTON;
-  return ButtonWithAccessibilityLabelId(labelID);
+  return [ChromeMatchers buttonWithAccessibilityLabelId:(labelID)];
 }
 
-id<GREYMatcher> AddAccountButton() {
++ (id<GREYMatcher>)addAccountButton {
   return grey_accessibilityID(kSettingsAccountsTableViewAddAccountCellId);
 }
 
-id<GREYMatcher> SignOutAccountsButton() {
++ (id<GREYMatcher>)signOutAccountsButton {
   return grey_accessibilityID(kSettingsAccountsTableViewSignoutCellId);
 }
 
-id<GREYMatcher> ClearBrowsingDataCell() {
-  return ButtonWithAccessibilityLabelId(IDS_IOS_CLEAR_BROWSING_DATA_TITLE);
++ (id<GREYMatcher>)clearBrowsingDataCell {
+  return [ChromeMatchers
+      buttonWithAccessibilityLabelId:(IDS_IOS_CLEAR_BROWSING_DATA_TITLE)];
 }
 
-id<GREYMatcher> ClearBrowsingDataButton() {
-  return ButtonWithAccessibilityLabelId(IDS_IOS_CLEAR_BUTTON);
++ (id<GREYMatcher>)clearBrowsingDataButton {
+  return [ChromeMatchers buttonWithAccessibilityLabelId:(IDS_IOS_CLEAR_BUTTON)];
 }
 
-id<GREYMatcher> ClearBrowsingDataCollectionView() {
++ (id<GREYMatcher>)clearBrowsingDataCollectionView {
   return grey_accessibilityID(
       kClearBrowsingDataCollectionViewAccessibilityIdentifier);
 }
 
-id<GREYMatcher> ConfirmClearBrowsingDataButton() {
++ (id<GREYMatcher>)confirmClearBrowsingDataButton {
   return grey_allOf(
       grey_accessibilityLabel(l10n_util::GetNSString(IDS_IOS_CLEAR_BUTTON)),
       grey_accessibilityTrait(UIAccessibilityTraitButton),
       grey_not(grey_accessibilityID(kClearBrowsingDataButtonIdentifier)), nil);
 }
 
-id<GREYMatcher> SettingsMenuButton() {
++ (id<GREYMatcher>)settingsMenuButton {
   return grey_accessibilityID(kToolsMenuSettingsId);
 }
 
-id<GREYMatcher> SettingsDoneButton() {
++ (id<GREYMatcher>)settingsDoneButton {
   return grey_accessibilityID(kSettingsDoneButtonId);
 }
 
-id<GREYMatcher> ToolsMenuView() {
++ (id<GREYMatcher>)toolsMenuView {
   return grey_accessibilityID(kPopupMenuToolsMenuTableViewId);
 }
 
-id<GREYMatcher> OKButton() {
-  return ButtonWithAccessibilityLabelId(IDS_OK);
++ (id<GREYMatcher>)okButton {
+  return [ChromeMatchers buttonWithAccessibilityLabelId:(IDS_OK)];
 }
 
-id<GREYMatcher> PrimarySignInButton() {
++ (id<GREYMatcher>)primarySignInButton {
   return grey_accessibilityID(kSigninPromoPrimaryButtonId);
 }
 
-id<GREYMatcher> SecondarySignInButton() {
++ (id<GREYMatcher>)secondarySignInButton {
   return grey_accessibilityID(kSigninPromoSecondaryButtonId);
 }
 
-id<GREYMatcher> SettingsAccountButton() {
++ (id<GREYMatcher>)settingsAccountButton {
   return grey_accessibilityID(kSettingsAccountCellId);
 }
 
-id<GREYMatcher> SettingsAccountsCollectionView() {
++ (id<GREYMatcher>)settingsAccountsCollectionView {
   return grey_accessibilityID(kSettingsAccountsTableViewId);
 }
 
-id<GREYMatcher> SettingsImportDataImportButton() {
++ (id<GREYMatcher>)settingsImportDataImportButton {
   return grey_accessibilityID(kImportDataImportCellId);
 }
 
-id<GREYMatcher> SettingsImportDataKeepSeparateButton() {
++ (id<GREYMatcher>)settingsImportDataKeepSeparateButton {
   return grey_accessibilityID(kImportDataKeepSeparateCellId);
 }
 
-id<GREYMatcher> SettingsSyncManageSyncedDataButton() {
++ (id<GREYMatcher>)settingsSyncManageSyncedDataButton {
   return grey_accessibilityID(kSettingsSyncId);
 }
 
-id<GREYMatcher> AccountsSyncButton() {
++ (id<GREYMatcher>)accountsSyncButton {
   return grey_allOf(grey_accessibilityID(kSettingsAccountsTableViewSyncCellId),
                     grey_sufficientlyVisible(), nil);
 }
 
-id<GREYMatcher> ContentSettingsButton() {
-  return ButtonWithAccessibilityLabelId(IDS_IOS_CONTENT_SETTINGS_TITLE);
++ (id<GREYMatcher>)contentSettingsButton {
+  return [ChromeMatchers
+      buttonWithAccessibilityLabelId:(IDS_IOS_CONTENT_SETTINGS_TITLE)];
 }
 
-id<GREYMatcher> GoogleServicesSettingsButton() {
-  return ButtonWithAccessibilityLabelId(IDS_IOS_GOOGLE_SERVICES_SETTINGS_TITLE);
++ (id<GREYMatcher>)googleServicesSettingsButton {
+  return [ChromeMatchers
+      buttonWithAccessibilityLabelId:(IDS_IOS_GOOGLE_SERVICES_SETTINGS_TITLE)];
 }
 
-id<GREYMatcher> SettingsMenuBackButton() {
++ (id<GREYMatcher>)settingsMenuBackButton {
   UINavigationBar* navBar = base::mac::ObjCCastStrict<UINavigationBar>(
       SubviewWithAccessibilityIdentifier(
           @"SettingNavigationBar",
@@ -438,94 +450,95 @@
                     nil);
 }
 
-id<GREYMatcher> SettingsMenuPrivacyButton() {
-  return ButtonWithAccessibilityLabelId(
-      IDS_OPTIONS_ADVANCED_SECTION_TITLE_PRIVACY);
++ (id<GREYMatcher>)settingsMenuPrivacyButton {
+  return [ChromeMatchers buttonWithAccessibilityLabelId:
+                             (IDS_OPTIONS_ADVANCED_SECTION_TITLE_PRIVACY)];
 }
 
-id<GREYMatcher> SettingsMenuPasswordsButton() {
-  return ButtonWithAccessibilityLabelId(IDS_IOS_PASSWORDS);
++ (id<GREYMatcher>)settingsMenuPasswordsButton {
+  return [ChromeMatchers buttonWithAccessibilityLabelId:(IDS_IOS_PASSWORDS)];
 }
 
-id<GREYMatcher> PaymentRequestView() {
++ (id<GREYMatcher>)paymentRequestView {
   return grey_accessibilityID(kPaymentRequestCollectionViewID);
 }
 
 // Returns matcher for the error confirmation view for payment request.
-id<GREYMatcher> PaymentRequestErrorView() {
++ (id<GREYMatcher>)paymentRequestErrorView {
   return grey_accessibilityID(kPaymentRequestErrorCollectionViewID);
 }
 
-id<GREYMatcher> VoiceSearchButton() {
++ (id<GREYMatcher>)voiceSearchButton {
   return grey_allOf(grey_accessibilityID(kSettingsVoiceSearchCellId),
                     grey_accessibilityTrait(UIAccessibilityTraitButton), nil);
 }
 
-id<GREYMatcher> SettingsCollectionView() {
++ (id<GREYMatcher>)settingsCollectionView {
   return grey_accessibilityID(kSettingsTableViewId);
 }
 
-id<GREYMatcher> ClearBrowsingHistoryButton() {
++ (id<GREYMatcher>)clearBrowsingHistoryButton {
   return grey_accessibilityID(kClearBrowsingHistoryCellAccessibilityIdentifier);
 }
 
-id<GREYMatcher> ClearCookiesButton() {
++ (id<GREYMatcher>)clearCookiesButton {
   return grey_accessibilityID(kClearCookiesCellAccessibilityIdentifier);
 }
 
-id<GREYMatcher> ClearCacheButton() {
++ (id<GREYMatcher>)clearCacheButton {
   return grey_accessibilityID(kClearCacheCellAccessibilityIdentifier);
 }
 
-id<GREYMatcher> ClearSavedPasswordsButton() {
++ (id<GREYMatcher>)clearSavedPasswordsButton {
   return grey_accessibilityID(kClearSavedPasswordsCellAccessibilityIdentifier);
 }
 
-id<GREYMatcher> ContentSuggestionCollectionView() {
++ (id<GREYMatcher>)contentSuggestionCollectionView {
   return grey_accessibilityID(
       [ContentSuggestionsViewController collectionAccessibilityIdentifier]);
 }
 
-id<GREYMatcher> WarningMessageView() {
++ (id<GREYMatcher>)warningMessageView {
   return grey_accessibilityID(kWarningMessageAccessibilityID);
 }
 
-id<GREYMatcher> PaymentRequestPickerRow() {
++ (id<GREYMatcher>)paymentRequestPickerRow {
   return grey_accessibilityID(kPaymentRequestPickerRowAccessibilityID);
 }
 
-id<GREYMatcher> PaymentRequestPickerSearchBar() {
++ (id<GREYMatcher>)paymentRequestPickerSearchBar {
   return grey_accessibilityID(kPaymentRequestPickerSearchBarAccessibilityID);
 }
 
-id<GREYMatcher> BookmarksMenuButton() {
++ (id<GREYMatcher>)bookmarksMenuButton {
   return grey_accessibilityID(kToolsMenuBookmarksId);
 }
 
-id<GREYMatcher> RecentTabsMenuButton() {
++ (id<GREYMatcher>)recentTabsMenuButton {
   return grey_accessibilityID(kToolsMenuOtherDevicesId);
 }
 
-id<GREYMatcher> SystemSelectionCallout() {
++ (id<GREYMatcher>)systemSelectionCallout {
   return grey_kindOfClass(NSClassFromString(@"UICalloutBarButton"));
 }
 
-id<GREYMatcher> SystemSelectionCalloutCopyButton() {
++ (id<GREYMatcher>)systemSelectionCalloutCopyButton {
   return grey_accessibilityLabel(@"Copy");
 }
 
-id<GREYMatcher> ContextMenuCopyButton() {
-  return ButtonWithAccessibilityLabelId(IDS_IOS_CONTENT_CONTEXT_COPY);
++ (id<GREYMatcher>)contextMenuCopyButton {
+  return [ChromeMatchers
+      buttonWithAccessibilityLabelId:(IDS_IOS_CONTENT_CONTEXT_COPY)];
 }
 
-id<GREYMatcher> NewTabPageOmnibox() {
++ (id<GREYMatcher>)NTPOmnibox {
   return grey_allOf(
       grey_accessibilityLabel(l10n_util::GetNSString(IDS_OMNIBOX_EMPTY_HINT)),
       grey_minimumVisiblePercent(0.2), nil);
 }
 
-id<GREYMatcher> WebViewMatcher() {
++ (id<GREYMatcher>)webViewMatcher {
   return web::WebViewInWebState(chrome_test_util::GetCurrentWebState());
 }
 
-}  // namespace chrome_test_util
+@end
diff --git a/ios/chrome/test/earl_grey/chrome_matchers_shorthand.h b/ios/chrome/test/earl_grey/chrome_matchers_shorthand.h
new file mode 100644
index 0000000..eeb40eb3
--- /dev/null
+++ b/ios/chrome/test/earl_grey/chrome_matchers_shorthand.h
@@ -0,0 +1,267 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef IOS_CHROME_TEST_EARL_GREY_CHROME_MATCHERS_SHORTHAND_H_
+#define IOS_CHROME_TEST_EARL_GREY_CHROME_MATCHERS_SHORTHAND_H_
+
+#import <Foundation/Foundation.h>
+
+#include <string>
+
+@protocol GREYMatcher;
+
+namespace chrome_test_util {
+
+// Matcher for element with accessibility label corresponding to |message_id|
+// and accessibility trait UIAccessibilityTraitButton.
+id<GREYMatcher> ButtonWithAccessibilityLabelId(int message_id);
+
+// Matcher for element with accessibility label corresponding to |label| and
+// accessibility trait UIAccessibilityTraitButton.
+id<GREYMatcher> ButtonWithAccessibilityLabel(NSString* label);
+
+// Matcher for element with an image corresponding to |image_id|.
+id<GREYMatcher> ImageViewWithImage(int image_id);
+
+// Matcher for element with an image defined by its name in the main bundle.
+id<GREYMatcher> ImageViewWithImageNamed(NSString* imageName);
+
+// Matcher for element with an image corresponding to |image_id| and
+// accessibility trait UIAccessibilityTraitButton.
+id<GREYMatcher> ButtonWithImage(int image_id);
+
+// Matcher for element with accessibility label corresponding to |message_id|
+// and accessibility trait UIAccessibilityTraitStaticText.
+id<GREYMatcher> StaticTextWithAccessibilityLabelId(int message_id);
+
+// Matcher for element with accessibility label corresponding to |label| and
+// accessibility trait UIAccessibilityTraitStaticText.
+id<GREYMatcher> StaticTextWithAccessibilityLabel(NSString* label);
+
+// Matcher for element with accessibility label corresponding to |message_id|
+// and accessibility trait UIAccessibilityTraitHeader.
+id<GREYMatcher> HeaderWithAccessibilityLabelId(int message_id);
+
+// Matcher for element with accessibility label corresponding to |label| and
+// accessibility trait UIAccessibilityTraitHeader.
+id<GREYMatcher> HeaderWithAccessibilityLabel(NSString* label);
+
+// Returns matcher for a cancel button.
+id<GREYMatcher> CancelButton();
+
+// Returns matcher for a close button.
+id<GREYMatcher> CloseButton();
+
+// Matcher for the navigate forward button.
+id<GREYMatcher> ForwardButton();
+
+// Matcher for the navigate backward button.
+id<GREYMatcher> BackButton();
+
+// Matcher for the reload button.
+id<GREYMatcher> ReloadButton();
+
+// Matcher for the stop loading button.
+id<GREYMatcher> StopButton();
+
+// Returns a matcher for the omnibox.
+id<GREYMatcher> Omnibox();
+
+// Returns a matcher for the location view.
+id<GREYMatcher> DefocusedLocationView();
+
+// Returns a matcher for the page security info button.
+id<GREYMatcher> PageSecurityInfoButton();
+// Returns a matcher for the page security info indicator.
+id<GREYMatcher> PageSecurityInfoIndicator();
+
+// Returns matcher for omnibox containing |text|. Performs an exact match of the
+// omnibox contents.
+id<GREYMatcher> OmniboxText(std::string text);
+
+// Returns matcher for |text| being a substring of the text in the omnibox.
+id<GREYMatcher> OmniboxContainingText(std::string text);
+
+// Returns matcher for |text| being a substring of the text in the location
+// view.
+id<GREYMatcher> LocationViewContainingText(std::string text);
+
+// Matcher for Tools menu button.
+id<GREYMatcher> ToolsMenuButton();
+
+// Matcher for the Share menu button.
+id<GREYMatcher> ShareButton();
+
+// Returns the GREYMatcher for the button that opens the tab switcher.
+id<GREYMatcher> TabletTabSwitcherOpenButton();
+
+// Matcher for show tabs button.
+id<GREYMatcher> ShowTabsButton();
+
+// Matcher for SettingsSwitchCell.
+id<GREYMatcher> SettingsSwitchCell(NSString* accessibility_identifier,
+                                   BOOL is_toggled_on);
+
+// Matcher for SettingsSwitchCell.
+id<GREYMatcher> SettingsSwitchCell(NSString* accessibility_identifier,
+                                   BOOL is_toggled_on,
+                                   BOOL is_enabled);
+
+// Matcher for LegacySyncSwitchCell.
+id<GREYMatcher> SyncSwitchCell(NSString* accessibility_label,
+                               BOOL is_toggled_on);
+
+// Matcher for the Open in New Tab option in the context menu when long pressing
+// a link.
+id<GREYMatcher> OpenLinkInNewTabButton();
+
+// Matcher for the done button on the navigation bar.
+id<GREYMatcher> NavigationBarDoneButton();
+
+// Matcher for the done button on the Bookmarks navigation bar.
+id<GREYMatcher> BookmarksNavigationBarDoneButton();
+
+// Returns matcher for the account consistency setup signin button.
+id<GREYMatcher> AccountConsistencySetupSigninButton();
+
+// Returns matcher for the account consistency confirmation button.
+id<GREYMatcher> AccountConsistencyConfirmationOkButton();
+
+// Returns matcher for the add account accounts button.
+id<GREYMatcher> AddAccountButton();
+
+// Returns matcher for the sign out accounts button.
+id<GREYMatcher> SignOutAccountsButton();
+
+// Returns matcher for the Clear Browsing Data cell on the Privacy screen.
+id<GREYMatcher> ClearBrowsingDataCell();
+
+// Returns matcher for the clear browsing data button on the clear browsing data
+// panel.
+id<GREYMatcher> ClearBrowsingDataButton();
+
+// Returns matcher for the clear browsing data collection view.
+id<GREYMatcher> ClearBrowsingDataCollectionView();
+
+// Matcher for the clear browsing data action sheet item.
+id<GREYMatcher> ConfirmClearBrowsingDataButton();
+
+// Returns matcher for the settings button in the tools menu.
+id<GREYMatcher> SettingsMenuButton();
+
+// Returns matcher for the "Done" button in the settings' navigation bar.
+id<GREYMatcher> SettingsDoneButton();
+
+// Returns matcher for the tools menu table view.
+id<GREYMatcher> ToolsMenuView();
+
+// Returns matcher for the OK button.
+id<GREYMatcher> OKButton();
+
+// Returns matcher for the primary button in the sign-in promo view. This is
+// "Sign in into Chrome" button for a cold state, or "Continue as John Doe" for
+// a warm state.
+id<GREYMatcher> PrimarySignInButton();
+
+// Returns matcher for the secondary button in the sign-in promo view. This is
+// "Not johndoe@example.com" button.
+id<GREYMatcher> SecondarySignInButton();
+
+// Returns matcher for the button for the currently signed in account in the
+// settings menu.
+id<GREYMatcher> SettingsAccountButton();
+
+// Returns matcher for the accounts collection view.
+id<GREYMatcher> SettingsAccountsCollectionView();
+
+// Returns matcher for the Import Data cell in switch sync account view.
+id<GREYMatcher> SettingsImportDataImportButton();
+
+// Returns matcher for the Keep Data Separate cell in switch sync account view.
+id<GREYMatcher> SettingsImportDataKeepSeparateButton();
+
+// Returns matcher for the Manage Synced Data button in sync setting view.
+id<GREYMatcher> SettingsSyncManageSyncedDataButton();
+
+// Returns matcher for the menu button to sync accounts.
+id<GREYMatcher> AccountsSyncButton();
+
+// Returns matcher for the Content Settings button on the main Settings screen.
+id<GREYMatcher> ContentSettingsButton();
+
+// Returns matcher for the Google Services Settings button on the main Settings
+// screen.
+id<GREYMatcher> GoogleServicesSettingsButton();
+
+// Returns matcher for the back button on a settings menu.
+id<GREYMatcher> SettingsMenuBackButton();
+
+// Returns matcher for the Privacy cell on the main Settings screen.
+id<GREYMatcher> SettingsMenuPrivacyButton();
+
+// Returns matcher for the Save passwords cell on the main Settings screen.
+id<GREYMatcher> SettingsMenuPasswordsButton();
+
+// Returns matcher for the payment request collection view.
+id<GREYMatcher> PaymentRequestView();
+
+// Returns matcher for the error confirmation view for payment request.
+id<GREYMatcher> PaymentRequestErrorView();
+
+// Returns matcher for the voice search button on the main Settings screen.
+id<GREYMatcher> VoiceSearchButton();
+
+// Returns matcher for the settings main menu view.
+id<GREYMatcher> SettingsCollectionView();
+
+// Returns matcher for the clear browsing history cell on the clear browsing
+// data panel.
+id<GREYMatcher> ClearBrowsingHistoryButton();
+
+// Returns matcher for the clear cookies cell on the clear browsing data panel.
+id<GREYMatcher> ClearCookiesButton();
+
+// Returns matcher for the clear cache cell on the clear browsing data panel.
+id<GREYMatcher> ClearCacheButton();
+
+// Returns matcher for the clear saved passwords cell on the clear browsing data
+// panel.
+id<GREYMatcher> ClearSavedPasswordsButton();
+
+// Returns matcher for the collection view of content suggestion.
+id<GREYMatcher> ContentSuggestionCollectionView();
+
+// Returns matcher for the warning message while filling in payment requests.
+id<GREYMatcher> WarningMessageView();
+
+// Returns matcher for the payment picker cell.
+id<GREYMatcher> PaymentRequestPickerRow();
+
+// Returns matcher for the payment request search bar.
+id<GREYMatcher> PaymentRequestPickerSearchBar();
+
+// Returns matcher for the bookmarks button on the Tools menu.
+id<GREYMatcher> BookmarksMenuButton();
+
+// Returns matcher for the recent tabs button on the Tools menu.
+id<GREYMatcher> RecentTabsMenuButton();
+
+// Returns matcher for the system selection callout.
+id<GREYMatcher> SystemSelectionCallout();
+
+// Returns matcher for the copy button on the system selection callout.
+id<GREYMatcher> SystemSelectionCalloutCopyButton();
+
+// Returns matcher for the Copy item on the context menu.
+id<GREYMatcher> ContextMenuCopyButton();
+
+// Returns matcher for defoucesed omnibox on a new tab.
+id<GREYMatcher> NewTabPageOmnibox();
+
+// Returns a matcher for the current WebView.
+id<GREYMatcher> WebViewMatcher();
+
+}
+
+#endif  // IOS_CHROME_TEST_EARL_GREY_CHROME_MATCHERS_SHORTHAND_H_
diff --git a/ios/chrome/test/earl_grey/chrome_matchers_shorthand.mm b/ios/chrome/test/earl_grey/chrome_matchers_shorthand.mm
new file mode 100644
index 0000000..7f89aad03
--- /dev/null
+++ b/ios/chrome/test/earl_grey/chrome_matchers_shorthand.mm
@@ -0,0 +1,330 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import <EarlGrey/EarlGrey.h>
+#import <WebKit/WebKit.h>
+
+#import "ios/chrome/test/earl_grey/chrome_matchers_shorthand.h"
+
+#import "ios/chrome/test/earl_grey/chrome_matchers.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+namespace chrome_test_util {
+
+id<GREYMatcher> ButtonWithAccessibilityLabel(NSString* label) {
+  return [ChromeMatchers buttonWithAccessibilityLabel:label];
+}
+
+id<GREYMatcher> ButtonWithAccessibilityLabelId(int message_id) {
+  return [ChromeMatchers buttonWithAccessibilityLabelId:message_id];
+}
+
+id<GREYMatcher> ImageViewWithImageNamed(NSString* imageName) {
+  return [ChromeMatchers imageViewWithImageNamed:imageName];
+}
+
+id<GREYMatcher> ImageViewWithImage(int image_id) {
+  return [ChromeMatchers imageViewWithImage:image_id];
+}
+
+id<GREYMatcher> ButtonWithImage(int image_id) {
+  return [ChromeMatchers buttonWithImage:image_id];
+}
+
+id<GREYMatcher> StaticTextWithAccessibilityLabelId(int message_id) {
+  return [ChromeMatchers staticTextWithAccessibilityLabelId:message_id];
+}
+
+id<GREYMatcher> StaticTextWithAccessibilityLabel(NSString* label) {
+  return [ChromeMatchers staticTextWithAccessibilityLabel:label];
+}
+
+id<GREYMatcher> HeaderWithAccessibilityLabelId(int message_id) {
+  return [ChromeMatchers headerWithAccessibilityLabelId:message_id];
+}
+
+id<GREYMatcher> HeaderWithAccessibilityLabel(NSString* label) {
+  return [ChromeMatchers headerWithAccessibilityLabel:label];
+}
+
+id<GREYMatcher> CancelButton() {
+  return [ChromeMatchers cancelButton];
+}
+
+id<GREYMatcher> CloseButton() {
+  return [ChromeMatchers closeButton];
+}
+
+id<GREYMatcher> ForwardButton() {
+  return [ChromeMatchers forwardButton];
+}
+
+id<GREYMatcher> BackButton() {
+  return [ChromeMatchers backButton];
+}
+
+id<GREYMatcher> ReloadButton() {
+  return [ChromeMatchers reloadButton];
+}
+
+id<GREYMatcher> StopButton() {
+  return [ChromeMatchers stopButton];
+}
+
+id<GREYMatcher> Omnibox() {
+  return [ChromeMatchers omnibox];
+}
+
+id<GREYMatcher> DefocusedLocationView() {
+  return [ChromeMatchers defocusedLocationView];
+}
+
+id<GREYMatcher> PageSecurityInfoButton() {
+  return [ChromeMatchers pageSecurityInfoButton];
+}
+
+id<GREYMatcher> PageSecurityInfoIndicator() {
+  return [ChromeMatchers pageSecurityInfoIndicator];
+}
+
+id<GREYMatcher> OmniboxText(std::string text) {
+  return [ChromeMatchers omniboxText:text];
+}
+
+id<GREYMatcher> OmniboxContainingText(std::string text) {
+  return [ChromeMatchers omniboxContainingText:text];
+}
+
+id<GREYMatcher> LocationViewContainingText(std::string text) {
+  return [ChromeMatchers locationViewContainingText:text];
+}
+
+id<GREYMatcher> ToolsMenuButton() {
+  return [ChromeMatchers toolsMenuButton];
+}
+
+id<GREYMatcher> ShareButton() {
+  return [ChromeMatchers shareButton];
+}
+
+id<GREYMatcher> TabletTabSwitcherOpenButton() {
+  return [ChromeMatchers tabletTabSwitcherOpenButton];
+}
+
+id<GREYMatcher> ShowTabsButton() {
+  return [ChromeMatchers showTabsButton];
+}
+
+id<GREYMatcher> SettingsSwitchCell(NSString* accessibility_identifier,
+                                   BOOL is_toggled_on) {
+  return [ChromeMatchers settingsSwitchCell:accessibility_identifier
+                                isToggledOn:is_toggled_on];
+}
+
+id<GREYMatcher> SettingsSwitchCell(NSString* accessibility_identifier,
+                                   BOOL is_toggled_on,
+                                   BOOL is_enabled) {
+  return [ChromeMatchers settingsSwitchCell:accessibility_identifier
+                                isToggledOn:is_toggled_on
+                                  isEnabled:is_enabled];
+}
+
+id<GREYMatcher> SyncSwitchCell(NSString* accessibility_label,
+                               BOOL is_toggled_on) {
+  return [ChromeMatchers syncSwitchCell:accessibility_label
+                            isToggledOn:is_toggled_on];
+}
+
+id<GREYMatcher> OpenLinkInNewTabButton() {
+  return [ChromeMatchers openLinkInNewTabButton];
+}
+
+id<GREYMatcher> NavigationBarDoneButton() {
+  return [ChromeMatchers navigationBarDoneButton];
+}
+
+id<GREYMatcher> BookmarksNavigationBarDoneButton() {
+  return [ChromeMatchers bookmarksNavigationBarDoneButton];
+}
+
+id<GREYMatcher> AccountConsistencySetupSigninButton() {
+  return [ChromeMatchers accountConsistencySetupSigninButton];
+}
+
+id<GREYMatcher> AccountConsistencyConfirmationOkButton() {
+  return [ChromeMatchers accountConsistencyConfirmationOkButton];
+}
+
+id<GREYMatcher> AddAccountButton() {
+  return [ChromeMatchers addAccountButton];
+}
+
+id<GREYMatcher> SignOutAccountsButton() {
+  return [ChromeMatchers signOutAccountsButton];
+}
+
+id<GREYMatcher> ClearBrowsingDataCell() {
+  return [ChromeMatchers clearBrowsingDataCell];
+}
+
+id<GREYMatcher> ClearBrowsingDataButton() {
+  return [ChromeMatchers clearBrowsingDataButton];
+}
+
+id<GREYMatcher> ClearBrowsingDataCollectionView() {
+  return [ChromeMatchers clearBrowsingDataCollectionView];
+}
+
+id<GREYMatcher> ConfirmClearBrowsingDataButton() {
+  return [ChromeMatchers confirmClearBrowsingDataButton];
+}
+
+id<GREYMatcher> SettingsMenuButton() {
+  return [ChromeMatchers settingsMenuButton];
+}
+
+id<GREYMatcher> SettingsDoneButton() {
+  return [ChromeMatchers settingsDoneButton];
+}
+
+id<GREYMatcher> ToolsMenuView() {
+  return [ChromeMatchers toolsMenuView];
+}
+
+id<GREYMatcher> OKButton() {
+  return [ChromeMatchers okButton];
+}
+
+id<GREYMatcher> PrimarySignInButton() {
+  return [ChromeMatchers primarySignInButton];
+}
+
+id<GREYMatcher> SecondarySignInButton() {
+  return [ChromeMatchers secondarySignInButton];
+}
+
+id<GREYMatcher> SettingsAccountButton() {
+  return [ChromeMatchers settingsAccountButton];
+}
+
+id<GREYMatcher> SettingsAccountsCollectionView() {
+  return [ChromeMatchers settingsAccountsCollectionView];
+}
+
+id<GREYMatcher> SettingsImportDataImportButton() {
+  return [ChromeMatchers settingsImportDataImportButton];
+}
+
+id<GREYMatcher> SettingsImportDataKeepSeparateButton() {
+  return [ChromeMatchers settingsImportDataKeepSeparateButton];
+}
+
+id<GREYMatcher> SettingsSyncManageSyncedDataButton() {
+  return [ChromeMatchers settingsSyncManageSyncedDataButton];
+}
+
+id<GREYMatcher> AccountsSyncButton() {
+  return [ChromeMatchers accountsSyncButton];
+}
+
+id<GREYMatcher> ContentSettingsButton() {
+  return [ChromeMatchers contentSettingsButton];
+}
+
+id<GREYMatcher> GoogleServicesSettingsButton() {
+  return [ChromeMatchers googleServicesSettingsButton];
+}
+
+id<GREYMatcher> SettingsMenuBackButton() {
+  return [ChromeMatchers settingsMenuBackButton];
+}
+
+id<GREYMatcher> SettingsMenuPrivacyButton() {
+  return [ChromeMatchers settingsMenuPrivacyButton];
+}
+
+id<GREYMatcher> SettingsMenuPasswordsButton() {
+  return [ChromeMatchers settingsMenuPasswordsButton];
+}
+
+id<GREYMatcher> PaymentRequestView() {
+  return [ChromeMatchers paymentRequestView];
+}
+
+id<GREYMatcher> PaymentRequestErrorView() {
+  return [ChromeMatchers paymentRequestErrorView];
+}
+
+id<GREYMatcher> VoiceSearchButton() {
+  return [ChromeMatchers voiceSearchButton];
+}
+
+id<GREYMatcher> SettingsCollectionView() {
+  return [ChromeMatchers settingsCollectionView];
+}
+
+id<GREYMatcher> ClearBrowsingHistoryButton() {
+  return [ChromeMatchers clearBrowsingHistoryButton];
+}
+
+id<GREYMatcher> ClearCookiesButton() {
+  return [ChromeMatchers clearCookiesButton];
+}
+
+id<GREYMatcher> ClearCacheButton() {
+  return [ChromeMatchers clearCacheButton];
+}
+
+id<GREYMatcher> ClearSavedPasswordsButton() {
+  return [ChromeMatchers clearSavedPasswordsButton];
+}
+
+id<GREYMatcher> ContentSuggestionCollectionView() {
+  return [ChromeMatchers contentSuggestionCollectionView];
+}
+
+id<GREYMatcher> WarningMessageView() {
+  return [ChromeMatchers warningMessageView];
+}
+
+id<GREYMatcher> PaymentRequestPickerRow() {
+  return [ChromeMatchers paymentRequestPickerRow];
+}
+
+id<GREYMatcher> PaymentRequestPickerSearchBar() {
+  return [ChromeMatchers paymentRequestPickerSearchBar];
+}
+
+id<GREYMatcher> BookmarksMenuButton() {
+  return [ChromeMatchers bookmarksMenuButton];
+}
+
+id<GREYMatcher> RecentTabsMenuButton() {
+  return [ChromeMatchers recentTabsMenuButton];
+}
+
+id<GREYMatcher> SystemSelectionCallout() {
+  return [ChromeMatchers systemSelectionCallout];
+}
+
+id<GREYMatcher> SystemSelectionCalloutCopyButton() {
+  return [ChromeMatchers systemSelectionCalloutCopyButton];
+}
+
+id<GREYMatcher> ContextMenuCopyButton() {
+  return [ChromeMatchers contextMenuCopyButton];
+}
+
+id<GREYMatcher> NewTabPageOmnibox() {
+  return [ChromeMatchers NTPOmnibox];
+}
+
+id<GREYMatcher> WebViewMatcher() {
+  return [ChromeMatchers webViewMatcher];
+}
+
+}  // namespace chrome_test_util
diff --git a/ios/web/BUILD.gn b/ios/web/BUILD.gn
index 9781037..f07d144 100644
--- a/ios/web/BUILD.gn
+++ b/ios/web/BUILD.gn
@@ -48,7 +48,6 @@
     "//ios/web/web_state:error_translation_util",
     "//ios/web/web_state:navigation_context",
     "//ios/web/web_state:web_view_internal_creation_util",
-    "//services/catalog/public/cpp",
     "//services/network:network_service",
     "//services/network/public/mojom",
     "//services/service_manager",
diff --git a/ios/web/DEPS b/ios/web/DEPS
index 4a72ec3b..cf49397 100644
--- a/ios/web/DEPS
+++ b/ios/web/DEPS
@@ -12,7 +12,6 @@
   "+ui",
 
   # Needed to embed the ServiceManager in //ios/web.
-  "+services/catalog",
   "+services/service_manager",
 
   # For tests.
diff --git a/ios/web/service_manager_context.mm b/ios/web/service_manager_context.mm
index 4cbbc5b6..6e1bcb9 100644
--- a/ios/web/service_manager_context.mm
+++ b/ios/web/service_manager_context.mm
@@ -25,7 +25,6 @@
 #include "ios/web/service_manager_connection_impl.h"
 #import "ios/web/web_browser_manifest.h"
 #import "ios/web/web_packaged_services_manifest.h"
-#include "services/catalog/public/mojom/constants.mojom.h"
 #include "services/service_manager/connect_params.h"
 #include "services/service_manager/public/cpp/connector.h"
 #include "services/service_manager/public/cpp/constants.h"
diff --git a/media/base/media_switches.cc b/media/base/media_switches.cc
index 489aeeb..4205441 100644
--- a/media/base/media_switches.cc
+++ b/media/base/media_switches.cc
@@ -314,10 +314,6 @@
 const base::Feature kUseSurfaceLayerForVideoPIP{
     "UseSurfaceLayerForVideoPIP", base::FEATURE_ENABLED_BY_DEFAULT};
 
-// Enable VA-API hardware encode acceleration for VP8.
-const base::Feature kVaapiVP8Encoder{"VaapiVP8Encoder",
-                                     base::FEATURE_ENABLED_BY_DEFAULT};
-
 // Enable VA-API hardware encode acceleration for VP9.
 const base::Feature kVaapiVP9Encoder{"VaapiVP9Encoder",
                                      base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/media/base/media_switches.h b/media/base/media_switches.h
index 493ba61..c6d4e0d4 100644
--- a/media/base/media_switches.h
+++ b/media/base/media_switches.h
@@ -138,7 +138,6 @@
 MEDIA_EXPORT extern const base::Feature kUseR16Texture;
 MEDIA_EXPORT extern const base::Feature kUseSurfaceLayerForVideo;
 MEDIA_EXPORT extern const base::Feature kUseSurfaceLayerForVideoPIP;
-MEDIA_EXPORT extern const base::Feature kVaapiVP8Encoder;
 MEDIA_EXPORT extern const base::Feature kVaapiVP9Encoder;
 MEDIA_EXPORT extern const base::Feature kVideoBlitColorAccuracy;
 
diff --git a/media/cast/sender/h264_vt_encoder_unittest.cc b/media/cast/sender/h264_vt_encoder_unittest.cc
index d8f13c6..df56d9c 100644
--- a/media/cast/sender/h264_vt_encoder_unittest.cc
+++ b/media/cast/sender/h264_vt_encoder_unittest.cc
@@ -269,7 +269,7 @@
 scoped_refptr<media::VideoFrame> H264VideoToolboxEncoderTest::frame_;
 FrameSenderConfig H264VideoToolboxEncoderTest::video_sender_config_;
 
-// Failed on mac_chromium_rel_ng trybot. http://crbug.com/627260
+// Failed on mac-rel trybot. http://crbug.com/627260
 TEST_F(H264VideoToolboxEncoderTest, DISABLED_CheckFrameMetadataSequence) {
   scoped_refptr<MetadataRecorder> metadata_recorder(new MetadataRecorder());
   VideoEncoder::FrameEncodedCallback cb = base::Bind(
@@ -299,7 +299,7 @@
 }
 
 #if BUILDFLAG(USE_PROPRIETARY_CODECS)
-// Failed on mac_chromium_rel_ng trybot. http://crbug.com/627260
+// Failed on mac-rel trybot. http://crbug.com/627260
 TEST_F(H264VideoToolboxEncoderTest, DISABLED_CheckFramesAreDecodable) {
   VideoDecoderConfig config(
       kCodecH264, H264PROFILE_MAIN, frame_->format(), VideoColorSpace(),
diff --git a/media/gpu/BUILD.gn b/media/gpu/BUILD.gn
index 136b28c..c4023bb 100644
--- a/media/gpu/BUILD.gn
+++ b/media/gpu/BUILD.gn
@@ -393,6 +393,7 @@
       ]
       deps += [
         "test:decode_helpers",
+        "test:frame_file_writer",
         "test:frame_validator",
         "//mojo/core/embedder",
         "//ui/display",
diff --git a/media/gpu/test/BUILD.gn b/media/gpu/test/BUILD.gn
index 8940e0e..05f0f8c 100644
--- a/media/gpu/test/BUILD.gn
+++ b/media/gpu/test/BUILD.gn
@@ -76,21 +76,18 @@
   ]
 }
 
-# TODO(dstaessens@) Make this work on other platforms too.
-if (is_chromeos) {
-  source_set("frame_file_writer") {
-    testonly = true
-    sources = [
-      "video_frame_file_writer.cc",
-      "video_frame_file_writer.h",
-    ]
-    deps = [
-      ":frame_mapper",
-      ":render_helpers",
-      "//media/gpu",
-      "//ui/gfx/codec:codec",
-    ]
-  }
+source_set("frame_file_writer") {
+  testonly = true
+  sources = [
+    "video_frame_file_writer.cc",
+    "video_frame_file_writer.h",
+  ]
+  deps = [
+    ":frame_mapper",
+    ":render_helpers",
+    "//media/gpu",
+    "//ui/gfx/codec:codec",
+  ]
 }
 
 source_set("decode_helpers") {
diff --git a/media/gpu/test/video_frame_file_writer.cc b/media/gpu/test/video_frame_file_writer.cc
index fd8af99..e80ad10 100644
--- a/media/gpu/test/video_frame_file_writer.cc
+++ b/media/gpu/test/video_frame_file_writer.cc
@@ -8,8 +8,9 @@
 #include <vector>
 
 #include "base/bind.h"
+#include "base/files/file_util.h"
 #include "base/memory/ptr_util.h"
-#include "base/strings/string_number_conversions.h"
+#include "base/strings/stringprintf.h"
 #include "media/gpu/test/video_frame_mapper.h"
 #include "media/gpu/test/video_frame_mapper_factory.h"
 #include "ui/gfx/codec/png_codec.h"
@@ -17,8 +18,10 @@
 namespace media {
 namespace test {
 
-VideoFrameFileWriter::VideoFrameFileWriter(const base::FilePath& output_folder)
+VideoFrameFileWriter::VideoFrameFileWriter(const base::FilePath& output_folder,
+                                           OutputFormat output_format)
     : output_folder_(output_folder),
+      output_format_(output_format),
       num_frames_writing_(0),
       frame_writer_thread_("FrameWriterThread"),
       frame_writer_cv_(&frame_writer_lock_) {
@@ -35,9 +38,24 @@
 
 // static
 std::unique_ptr<VideoFrameFileWriter> VideoFrameFileWriter::Create(
-    const base::FilePath& output_folder) {
-  auto frame_file_writer =
-      base::WrapUnique(new VideoFrameFileWriter(output_folder));
+    const base::FilePath& output_folder,
+    OutputFormat output_format) {
+  // If the directory is not absolute, consider it relative to our working dir.
+  base::FilePath resolved_output_folder(output_folder);
+  if (!resolved_output_folder.IsAbsolute()) {
+    resolved_output_folder =
+        base::MakeAbsoluteFilePath(
+            base::FilePath(base::FilePath::kCurrentDirectory))
+            .Append(resolved_output_folder);
+  }
+
+  // Create the directory tree if it doesn't exist yet.
+  if (!DirectoryExists(resolved_output_folder)) {
+    base::CreateDirectory(resolved_output_folder);
+  }
+
+  auto frame_file_writer = base::WrapUnique(
+      new VideoFrameFileWriter(resolved_output_folder, output_format));
   if (!frame_file_writer->Initialize()) {
     LOG(ERROR) << "Failed to initialize VideoFrameFileWriter";
     return nullptr;
@@ -58,18 +76,6 @@
     return false;
   }
 
-  // If the directory is not absolute, consider it relative to our working dir.
-  if (!output_folder_.IsAbsolute()) {
-    output_folder_ = base::MakeAbsoluteFilePath(
-                         base::FilePath(base::FilePath::kCurrentDirectory))
-                         .Append(output_folder_);
-  }
-
-  // Create the directory tree if it doesn't exist yet.
-  if (!DirectoryExists(output_folder_)) {
-    base::CreateDirectory(output_folder_);
-  }
-
   return true;
 }
 
@@ -100,14 +106,41 @@
     size_t frame_index) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(writer_thread_sequence_checker_);
 
+  base::FilePath::StringType filename;
+  const gfx::Size& visible_size = video_frame->visible_rect().size();
+  base::SStringPrintf(&filename, FILE_PATH_LITERAL("frame_%04zu_%dx%d"),
+                      frame_index, visible_size.width(), visible_size.height());
+
+  switch (output_format_) {
+    case OutputFormat::kPNG:
+      WriteVideoFramePNG(video_frame, base::FilePath(filename));
+      break;
+    case OutputFormat::kYUV:
+      WriteVideoFrameYUV(video_frame, base::FilePath(filename));
+      break;
+  }
+
+  base::AutoLock auto_lock(frame_writer_lock_);
+  num_frames_writing_--;
+  frame_writer_cv_.Signal();
+}
+
+void VideoFrameFileWriter::WriteVideoFramePNG(
+    scoped_refptr<const VideoFrame> video_frame,
+    const base::FilePath& filename) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(writer_thread_sequence_checker_);
+
   auto mapped_frame = video_frame_mapper_->Map(std::move(video_frame));
   if (!mapped_frame) {
     LOG(ERROR) << "Failed to map video frame";
     return;
   }
 
-  auto argb_out_frame = ConvertVideoFrame(mapped_frame.get(),
-                                          VideoPixelFormat::PIXEL_FORMAT_ARGB);
+  scoped_refptr<VideoFrame> argb_out_frame = mapped_frame;
+  if (argb_out_frame->format() != PIXEL_FORMAT_ARGB) {
+    argb_out_frame = ConvertVideoFrame(argb_out_frame.get(),
+                                       VideoPixelFormat::PIXEL_FORMAT_ARGB);
+  }
 
   // Convert the ARGB frame to PNG.
   std::vector<uint8_t> png_output;
@@ -119,22 +152,57 @@
       std::vector<gfx::PNGCodec::Comment>(), &png_output);
   LOG_ASSERT(png_encode_status);
 
-  base::FilePath filename;
-  {
-    base::AutoLock auto_lock(frame_writer_lock_);
-    filename = output_folder_.Append("frame_.png")
-                   .InsertBeforeExtension(base::NumberToString(frame_index));
-  }
-
   // Write the PNG data to file.
+  base::FilePath file_path(
+      output_folder_.Append(filename).AddExtension(FILE_PATH_LITERAL(".png")));
   const int size = base::checked_cast<int>(png_output.size());
   const int bytes_written = base::WriteFile(
-      filename, reinterpret_cast<char*>(png_output.data()), size);
+      file_path, reinterpret_cast<char*>(png_output.data()), size);
   LOG_ASSERT(bytes_written == size);
+}
 
-  base::AutoLock auto_lock(frame_writer_lock_);
-  num_frames_writing_--;
-  frame_writer_cv_.Signal();
+void VideoFrameFileWriter::WriteVideoFrameYUV(
+    scoped_refptr<const VideoFrame> video_frame,
+    const base::FilePath& filename) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(writer_thread_sequence_checker_);
+
+  auto mapped_frame = video_frame_mapper_->Map(std::move(video_frame));
+  if (!mapped_frame) {
+    LOG(ERROR) << "Failed to map video frame";
+    return;
+  }
+
+  scoped_refptr<VideoFrame> I420_out_frame = mapped_frame;
+  if (I420_out_frame->format() != PIXEL_FORMAT_I420) {
+    I420_out_frame = ConvertVideoFrame(I420_out_frame.get(),
+                                       VideoPixelFormat::PIXEL_FORMAT_I420);
+  }
+
+  // Write the YUV data to file.
+  base::FilePath file_path(
+      output_folder_.Append(filename)
+          .AddExtension(FILE_PATH_LITERAL(".yuv"))
+          .InsertBeforeExtension(FILE_PATH_LITERAL("_I420")));
+  base::File yuv_file(file_path,
+                      base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE);
+
+  // TODO(dstaessens@) Take stride into account when visible and coded sizes are
+  // different.
+  LOG_ASSERT(I420_out_frame->visible_rect().size() ==
+             I420_out_frame->coded_size());
+  const int width = I420_out_frame->visible_rect().width();
+  const int height = I420_out_frame->visible_rect().height();
+  const size_t num_planes = VideoFrame::NumPlanes(I420_out_frame->format());
+  for (size_t i = 0; i < num_planes; i++) {
+    size_t plane_w = VideoFrame::Columns(i, I420_out_frame->format(), width);
+    size_t plane_h = VideoFrame::Rows(i, I420_out_frame->format(), height);
+    int data_size = base::checked_cast<int>(plane_w * plane_h);
+    const uint8_t* data = I420_out_frame->data(i);
+    if (yuv_file.WriteAtCurrentPos(reinterpret_cast<const char*>(data),
+                                   data_size) != data_size) {
+      LOG(ERROR) << "Failed to write plane #" << i << " to file.";
+    }
+  }
 }
 
 }  // namespace test
diff --git a/media/gpu/test/video_frame_file_writer.h b/media/gpu/test/video_frame_file_writer.h
index 149bedbf..14c07490 100644
--- a/media/gpu/test/video_frame_file_writer.h
+++ b/media/gpu/test/video_frame_file_writer.h
@@ -25,15 +25,22 @@
 class VideoFrameMapper;
 
 // The video frame file writer class implements functionality to write video
-// frames to file. Currently only the PNG output format is supported.
+// frames to file. The supported output formats are PNG and raw I420 YUV.
 class VideoFrameFileWriter : public VideoFrameProcessor {
  public:
+  // Supported output formats.
+  enum class OutputFormat {
+    kPNG = 0,
+    kYUV,
+  };
+
   ~VideoFrameFileWriter() override;
 
   // Create an instance of the video frame file writer.
   static std::unique_ptr<VideoFrameFileWriter> Create(
       const base::FilePath& output_folder =
-          base::FilePath(kDefaultOutputFolder));
+          base::FilePath(kDefaultOutputFolder),
+      OutputFormat output_format = OutputFormat::kPNG);
 
   // Interface VideoFrameProcessor
   void ProcessVideoFrame(scoped_refptr<const VideoFrame> video_frame,
@@ -42,7 +49,8 @@
   bool WaitUntilDone() override;
 
  private:
-  explicit VideoFrameFileWriter(const base::FilePath& output_folder);
+  VideoFrameFileWriter(const base::FilePath& output_folder,
+                       OutputFormat output_format);
 
   // Initialize the video frame file writer.
   bool Initialize();
@@ -51,8 +59,17 @@
   void ProcessVideoFrameTask(scoped_refptr<const VideoFrame> video_frame,
                              size_t frame_index);
 
+  // Write the video frame to disk in PNG format.
+  void WriteVideoFramePNG(scoped_refptr<const VideoFrame> video_frame,
+                          const base::FilePath& filename);
+  // Write the video frame to disk in I420 YUV format.
+  void WriteVideoFrameYUV(scoped_refptr<const VideoFrame> video_frame,
+                          const base::FilePath& filename);
+
   // Output folder the frames will be written to.
-  base::FilePath output_folder_;
+  const base::FilePath output_folder_;
+  // Output format of the frames.
+  const OutputFormat output_format_;
 
   // The video frame mapper used to gain access to the raw video frame memory.
   std::unique_ptr<VideoFrameMapper> video_frame_mapper_;
diff --git a/media/gpu/test/video_frame_validator.cc b/media/gpu/test/video_frame_validator.cc
index b05b9b2..fb4bc642 100644
--- a/media/gpu/test/video_frame_validator.cc
+++ b/media/gpu/test/video_frame_validator.cc
@@ -28,36 +28,7 @@
   }
 
   auto video_frame_validator = base::WrapUnique(new VideoFrameValidator(
-      VideoFrameValidator::CHECK, base::FilePath(), expected_frame_checksums,
-      std::move(video_frame_mapper)));
-  if (!video_frame_validator->Initialize()) {
-    LOG(ERROR) << "Failed to initialize VideoFrameValidator.";
-    return nullptr;
-  }
-
-  return video_frame_validator;
-}
-
-// static
-std::unique_ptr<VideoFrameValidator> VideoFrameValidator::Create(
-    uint32_t flags,
-    const base::FilePath& prefix_output_yuv,
-    const std::vector<std::string>& expected_frame_checksums) {
-  if ((flags & VideoFrameValidator::OUTPUTYUV) && prefix_output_yuv.empty()) {
-    LOG(ERROR) << "Prefix of yuv files isn't specified with dump flags.";
-    return nullptr;
-  }
-
-  auto video_frame_mapper = VideoFrameMapperFactory::CreateMapper();
-
-  if (!video_frame_mapper) {
-    LOG(ERROR) << "Failed to create VideoFrameMapper.";
-    return nullptr;
-  }
-
-  auto video_frame_validator = base::WrapUnique(new VideoFrameValidator(
-      flags, prefix_output_yuv, std::move(expected_frame_checksums),
-      std::move(video_frame_mapper)));
+      expected_frame_checksums, std::move(video_frame_mapper)));
   if (!video_frame_validator->Initialize()) {
     LOG(ERROR) << "Failed to initialize VideoFrameValidator.";
     return nullptr;
@@ -67,13 +38,9 @@
 }
 
 VideoFrameValidator::VideoFrameValidator(
-    uint32_t flags,
-    const base::FilePath& prefix_output_yuv,
     std::vector<std::string> expected_frame_checksums,
     std::unique_ptr<VideoFrameMapper> video_frame_mapper)
-    : flags_(flags),
-      prefix_output_yuv_(prefix_output_yuv),
-      expected_frame_checksums_(std::move(expected_frame_checksums)),
+    : expected_frame_checksums_(std::move(expected_frame_checksums)),
       video_frame_mapper_(std::move(video_frame_mapper)),
       num_frames_validating_(0),
       frame_validator_thread_("FrameValidatorThread"),
@@ -158,7 +125,7 @@
   base::AutoLock auto_lock(frame_validator_lock_);
   frame_checksums_.push_back(computed_md5);
 
-  if (flags_ & Flags::CHECK) {
+  if (expected_frame_checksums_.size() > 0) {
     LOG_IF(FATAL, frame_index >= expected_frame_checksums_.size())
         << "Frame number is over than the number of read md5 values in file.";
     const auto& expected_md5 = expected_frame_checksums_[frame_index];
@@ -168,11 +135,6 @@
     }
   }
 
-  if (flags_ & Flags::OUTPUTYUV) {
-    LOG_IF(WARNING, !WriteI420ToFile(frame_index, standard_frame.get()))
-        << "Failed to write yuv into file.";
-  }
-
   num_frames_validating_--;
   frame_validator_cv_.Signal();
 }
@@ -200,42 +162,5 @@
   return MD5DigestToBase16(digest);
 }
 
-// TODO(dstaessens@) Move to video_frame_writer.h
-bool VideoFrameValidator::WriteI420ToFile(
-    size_t frame_index,
-    const VideoFrame* const video_frame) const {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(validator_thread_sequence_checker_);
-  if (video_frame->format() != PIXEL_FORMAT_I420) {
-    LOG(ERROR) << "No I420 format frame.";
-    return false;
-  }
-  if (video_frame->storage_type() !=
-      VideoFrame::StorageType::STORAGE_OWNED_MEMORY) {
-    LOG(ERROR) << "Video frame doesn't own memory.";
-    return false;
-  }
-  const int width = video_frame->visible_rect().width();
-  const int height = video_frame->visible_rect().height();
-  base::FilePath::StringType output_yuv_fname;
-  base::SStringPrintf(&output_yuv_fname,
-                      FILE_PATH_LITERAL("%04zu_%dx%d_I420.yuv"), frame_index,
-                      width, height);
-  base::File yuv_file(prefix_output_yuv_.AddExtension(output_yuv_fname),
-                      base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_APPEND);
-  const size_t num_planes = VideoFrame::NumPlanes(video_frame->format());
-  for (size_t i = 0; i < num_planes; i++) {
-    size_t plane_w = VideoFrame::Columns(i, video_frame->format(), width);
-    size_t plane_h = VideoFrame::Rows(i, video_frame->format(), height);
-    int data_size = base::checked_cast<int>(plane_w * plane_h);
-    const uint8_t* data = video_frame->data(i);
-    if (yuv_file.Write(0, reinterpret_cast<const char*>(data), data_size) !=
-        data_size) {
-      LOG(ERROR) << "Fail to write file in plane #" << i;
-      return false;
-    }
-  }
-  return true;
-}
-
 }  // namespace test
 }  // namespace media
diff --git a/media/gpu/test/video_frame_validator.h b/media/gpu/test/video_frame_validator.h
index 36d3c13d..d93d981 100644
--- a/media/gpu/test/video_frame_validator.h
+++ b/media/gpu/test/video_frame_validator.h
@@ -40,38 +40,18 @@
 // performance measurements.
 class VideoFrameValidator : public VideoFrameProcessor {
  public:
-  enum Flags : uint32_t {
-    // Checks soundness of video frames.
-    CHECK = 1 << 0,
-    // Writes out video frames to files.
-    OUTPUTYUV = 1 << 1,
-  };
-
   struct MismatchedFrameInfo {
     size_t frame_index;
     std::string computed_md5;
     std::string expected_md5;
   };
 
-  // Creates an instance of the video frame validator in 'CHECK' mode.
-  // |frame_checksums| should contain the ordered list of md5 frame checksums to
-  // be used by the validator
+  // Create an instance of the video frame validator. The calculated checksums
+  // will be compared to the values in |expected_frame_checksums|. If no
+  // checksums are provided only checksum calculation will be done.
   static std::unique_ptr<VideoFrameValidator> Create(
       const std::vector<std::string>& expected_frame_checksums);
 
-  // |flags| decides the behavior of created video frame validator. See the
-  // detail in Flags.
-  // |prefix_output_yuv| is the prefix name of saved yuv files.
-  // VideoFrameValidator saves all I420 video frames.
-  // If |prefix_output_yuv_| is not specified, no yuv file will be saved.
-  // |frame_checksums| should contain the ordered list of md5 frame checksums to
-  // be used by the validator.
-  // Returns nullptr on failure.
-  static std::unique_ptr<VideoFrameValidator> Create(
-      uint32_t flags,
-      const base::FilePath& prefix_output_yuv,
-      const std::vector<std::string>& frame_checksums);
-
   ~VideoFrameValidator() override;
 
   // Get the ordered list of calculated frame checksums.
@@ -95,9 +75,7 @@
   bool WaitUntilDone() override;
 
  private:
-  VideoFrameValidator(uint32_t flags,
-                      const base::FilePath& prefix_output_yuv,
-                      std::vector<std::string> md5_of_frames,
+  VideoFrameValidator(std::vector<std::string> expected_frame_checksums,
                       std::unique_ptr<VideoFrameMapper> video_frame_mapper);
 
   // Start the frame validation thread.
@@ -128,15 +106,10 @@
   std::vector<MismatchedFrameInfo> mismatched_frames_
       GUARDED_BY(frame_validator_lock_);
 
-  const uint32_t flags_;
-
-  // Prefix of saved yuv files.
-  const base::FilePath prefix_output_yuv_;
-
   // The list of calculated MD5 frame checksums.
   std::vector<std::string> frame_checksums_ GUARDED_BY(frame_validator_lock_);
 
-  // The list of golden MD5 frame checksums.
+  // The list of expected MD5 frame checksums.
   const std::vector<std::string> expected_frame_checksums_;
 
   const std::unique_ptr<VideoFrameMapper> video_frame_mapper_;
diff --git a/media/gpu/vaapi/vaapi_wrapper.cc b/media/gpu/vaapi/vaapi_wrapper.cc
index 4a12557..f5c7da2 100644
--- a/media/gpu/vaapi/vaapi_wrapper.cc
+++ b/media/gpu/vaapi/vaapi_wrapper.cc
@@ -178,13 +178,6 @@
     }
   }
 
-  // TODO(posciak): Remove once VP8 encoding is to be enabled by default.
-  if (mode == VaapiWrapper::CodecMode::kEncode &&
-      va_profile == VAProfileVP8Version0_3 &&
-      !base::FeatureList::IsEnabled(kVaapiVP8Encoder)) {
-    return true;
-  }
-
   // TODO(crbug.com/811912): Remove once VP9 encoding is to be enabled by
   // default.
   if (mode == VaapiWrapper::CodecMode::kEncode &&
@@ -402,7 +395,8 @@
     required_attribs.push_back({VAConfigAttribRateControl, VA_RC_CBR});
 
   // VAConfigAttribEncPackedHeaders is H.264 specific.
-  if (profile >= VAProfileH264Baseline && profile <= VAProfileH264High) {
+  if ((profile >= VAProfileH264Baseline && profile <= VAProfileH264High) ||
+      (profile == VAProfileH264ConstrainedBaseline)) {
     required_attribs.push_back(
         {VAConfigAttribEncPackedHeaders,
          VA_ENC_PACKED_HEADER_SEQUENCE | VA_ENC_PACKED_HEADER_PICTURE});
diff --git a/media/gpu/vaapi/vp8_encoder.cc b/media/gpu/vaapi/vp8_encoder.cc
index b591fd143..5937b75 100644
--- a/media/gpu/vaapi/vp8_encoder.cc
+++ b/media/gpu/vaapi/vp8_encoder.cc
@@ -147,7 +147,11 @@
   DCHECK(!visible_size_.IsEmpty());
   current_frame_hdr_.width = visible_size_.width();
   current_frame_hdr_.height = visible_size_.height();
-  current_frame_hdr_.quantization_hdr.y_ac_qi = current_params_.initial_qp;
+  // Since initial_qp is always kDefaultQP (=31), y_ac_qi should be 27
+  // (the table index for kDefaultQP, see rfc 14.1. table ac_qlookup)
+  DCHECK_EQ(current_params_.initial_qp, kDefaultQP);
+  constexpr uint8_t kDefaultQPACQIndex = 27;
+  current_frame_hdr_.quantization_hdr.y_ac_qi = kDefaultQPACQIndex;
   current_frame_hdr_.show_frame = true;
   // TODO(sprang): Make this dynamic. Value based on reference implementation
   // in libyami (https://github.com/intel/libyami).
diff --git a/media/gpu/video_decode_accelerator_unittest.cc b/media/gpu/video_decode_accelerator_unittest.cc
index 169ff4b..15fb11f 100644
--- a/media/gpu/video_decode_accelerator_unittest.cc
+++ b/media/gpu/video_decode_accelerator_unittest.cc
@@ -68,6 +68,7 @@
 #include "media/gpu/test/texture_ref.h"
 #include "media/gpu/test/video_accelerator_unittest_helpers.h"
 #include "media/gpu/test/video_decode_accelerator_unittest_helpers.h"
+#include "media/gpu/test/video_frame_file_writer.h"
 #include "media/gpu/test/video_frame_validator.h"
 #include "media/video/h264_parser.h"
 #include "mojo/core/embedder/embedder.h"
@@ -134,9 +135,12 @@
 // requesting the VDA itself to allocate buffers.
 bool g_test_import = false;
 
-// VideoFrameValidator flags.
-// If this is set to non-zero, g_test_import becomes true.
-uint32_t g_frame_validator_flags = 0;
+// Validate decoded frames using frame validator.
+bool g_validate_frames = false;
+// Calculate decoded frame checksums using frame validator;
+bool g_calculate_checksums = false;
+// Write decoded frames to YUV files.
+bool g_output_frames = false;
 
 // This is the location of the test files. If empty, they're in the current
 // working directory.
@@ -292,6 +296,7 @@
       std::string encoded_data,
       RenderingHelper* rendering_helper,
       std::unique_ptr<media::test::VideoFrameValidator> video_frame_validator,
+      std::unique_ptr<media::test::VideoFrameFileWriter> video_frame_writer,
       media::test::ClientStateNotification<ClientState>* note);
   ~GLRenderingVDAClient() override;
   void CreateAndStartDecoder();
@@ -394,6 +399,7 @@
   const std::unique_ptr<media::test::EncodedDataHelper> encoded_data_helper_;
   const std::unique_ptr<media::test::VideoFrameValidator>
       video_frame_validator_;
+  const std::unique_ptr<media::test::VideoFrameFileWriter> video_frame_writer_;
 
   base::WeakPtr<GLRenderingVDAClient> weak_this_;
   base::WeakPtrFactory<GLRenderingVDAClient> weak_this_factory_;
@@ -413,6 +419,7 @@
     std::string encoded_data,
     RenderingHelper* rendering_helper,
     std::unique_ptr<media::test::VideoFrameValidator> video_frame_validator,
+    std::unique_ptr<media::test::VideoFrameFileWriter> video_frame_writer,
     media::test::ClientStateNotification<ClientState>* note)
     : config_(std::move(config)),
       rendering_helper_(rendering_helper),
@@ -434,6 +441,7 @@
           std::move(encoded_data),
           config_.profile)),
       video_frame_validator_(std::move(video_frame_validator)),
+      video_frame_writer_(std::move(video_frame_writer)),
       weak_this_factory_(this) {
   DCHECK_NE(config.profile, VIDEO_CODEC_PROFILE_UNKNOWN);
   LOG_ASSERT(config_.num_in_flight_decodes > 0);
@@ -608,8 +616,15 @@
     video_frame_validator_->ProcessVideoFrame(std::move(video_frame),
                                               frame_index_);
     video_frame_validator_->WaitUntilDone();
-    frame_index_++;
   }
+  if (video_frame_writer_) {
+    auto video_frame = texture_it->second->ExportVideoFrame(visible_rect);
+    ASSERT_NE(video_frame.get(), nullptr);
+    video_frame_writer_->ProcessVideoFrame(std::move(video_frame),
+                                           frame_index_);
+    video_frame_writer_->WaitUntilDone();
+  }
+  frame_index_++;
   rendering_helper_->ConsumeVideoFrame(config_.window_id,
                                        std::move(video_frame_texture));
 }
@@ -1151,21 +1166,12 @@
 std::unique_ptr<media::test::VideoFrameValidator>
 CreateAndInitializeVideoFrameValidator(
     const base::FilePath::StringType& video_file) {
-  // Initialize prefix of yuv files.
-  base::FilePath prefix_output_yuv;
-  base::FilePath filepath(video_file);
-  if (g_frame_validator_flags & test::VideoFrameValidator::OUTPUTYUV) {
-    if (!g_thumbnail_output_dir.empty() &&
-        base::DirectoryExists(g_thumbnail_output_dir)) {
-      prefix_output_yuv = g_thumbnail_output_dir.Append(filepath.BaseName());
-    } else {
-      prefix_output_yuv = GetTestDataFile(filepath);
-    }
-  }
+  DCHECK(g_validate_frames || g_calculate_checksums);
 
   // Read md5 frame checksums.
+  base::FilePath filepath(video_file);
   std::vector<std::string> frame_checksums;
-  if (g_frame_validator_flags & test::VideoFrameValidator::CHECK) {
+  if (g_validate_frames) {
     base::FilePath md5_file_path =
         filepath.AddExtension(FILE_PATH_LITERAL(".frames.md5"));
     frame_checksums = test::ReadGoldenThumbnailMD5s(md5_file_path);
@@ -1175,8 +1181,25 @@
     }
   }
 
-  return media::test::VideoFrameValidator::Create(
-      g_frame_validator_flags, prefix_output_yuv, frame_checksums);
+  return media::test::VideoFrameValidator::Create(frame_checksums);
+}
+
+std::unique_ptr<media::test::VideoFrameFileWriter>
+CreateAndInitializeVideoFrameWriter(
+    const base::FilePath::StringType& video_file) {
+  DCHECK(g_output_frames);
+
+  // Initialize prefix of yuv files.
+  base::FilePath prefix_output_yuv;
+  base::FilePath filepath(video_file);
+  if (!g_thumbnail_output_dir.empty() &&
+      base::DirectoryExists(g_thumbnail_output_dir)) {
+    prefix_output_yuv = g_thumbnail_output_dir.Append(filepath.BaseName());
+  } else {
+    prefix_output_yuv = GetTestDataFile(filepath);
+  }
+  return media::test::VideoFrameFileWriter::Create(
+      prefix_output_yuv, media::test::VideoFrameFileWriter::OutputFormat::kYUV);
 }
 
 // Fails on Win only. crbug.com/849368
@@ -1215,8 +1238,7 @@
   notes_.resize(num_concurrent_decoders);
   clients_.resize(num_concurrent_decoders);
 
-  bool use_video_frame_validator = g_frame_validator_flags != 0;
-  if (use_video_frame_validator) {
+  if (g_validate_frames) {
     LOG(INFO) << "Using Frame Validator..";
 #if !defined(OS_CHROMEOS)
     LOG(FATAL) << "FrameValidator (g_frame_validator) cannot be used on "
@@ -1253,14 +1275,20 @@
     config.num_frames = video_file->num_frames;
 
     std::unique_ptr<media::test::VideoFrameValidator> video_frame_validator;
-    if (use_video_frame_validator) {
+    if (g_validate_frames) {
       video_frame_validator =
           CreateAndInitializeVideoFrameValidator(video_file->file_name);
       ASSERT_NE(video_frame_validator.get(), nullptr);
     }
+    std::unique_ptr<media::test::VideoFrameFileWriter> video_frame_writer;
+    if (g_output_frames) {
+      video_frame_writer =
+          CreateAndInitializeVideoFrameWriter(video_file->file_name);
+    }
     clients_[index] = std::make_unique<GLRenderingVDAClient>(
         std::move(config), video_file->data_str, &rendering_helper_,
-        std::move(video_frame_validator), notes_[index].get());
+        std::move(video_frame_validator), std::move(video_frame_writer),
+        notes_[index].get());
   }
 
   RenderingHelperParams helper_params;
@@ -1621,7 +1649,7 @@
 
   clients_.push_back(std::make_unique<GLRenderingVDAClient>(
       std::move(config), video_file->data_str, &rendering_helper_, nullptr,
-      notes_[0].get()));
+      nullptr, notes_[0].get()));
   RenderingHelperParams helper_params;
   helper_params.num_windows = 1;
   InitializeRenderingHelper(helper_params);
@@ -1656,7 +1684,7 @@
 
   clients_.push_back(std::make_unique<GLRenderingVDAClient>(
       std::move(config), video_file->data_str, &rendering_helper_, nullptr,
-      notes_[0].get()));
+      nullptr, notes_[0].get()));
   RenderingHelperParams helper_params;
   helper_params.num_windows = 1;
   InitializeRenderingHelper(helper_params);
@@ -1670,7 +1698,8 @@
 // --gtest_filter=VideoDecodeAcceleratorTest.DISABLED_GenMD5 and
 // --gtest_also_run_disabled_tests
 TEST_F(VideoDecodeAcceleratorTest, DISABLED_GenMD5) {
-  g_frame_validator_flags = 0;
+  g_validate_frames = false;
+  g_calculate_checksums = true;
   g_test_import = true;
 
   ASSERT_EQ(test_video_files_.size(), 1u);
@@ -1688,7 +1717,7 @@
       video_frame_validator.get();
   clients_.push_back(std::make_unique<GLRenderingVDAClient>(
       std::move(config), video_file->data_str, &rendering_helper_,
-      std::move(video_frame_validator), notes_[0].get()));
+      std::move(video_frame_validator), nullptr, notes_[0].get()));
   RenderingHelperParams helper_params;
   helper_params.num_windows = 1;
   InitializeRenderingHelper(helper_params);
@@ -1832,11 +1861,9 @@
                                      base::SPLIT_WANT_NONEMPTY);
       for (auto& f : flags) {
         if (f == "check") {
-          media::g_frame_validator_flags |=
-              media::test::VideoFrameValidator::CHECK;
+          media::g_validate_frames = true;
         } else if (f == "dump") {
-          media::g_frame_validator_flags |=
-              media::test::VideoFrameValidator::OUTPUTYUV;
+          media::g_output_frames = true;
         } else {
           LOG(FATAL) << "Unknown flag: " << f;
         }
diff --git a/media/learning/common/labelled_example.cc b/media/learning/common/labelled_example.cc
index 43e834f9..0d0da63 100644
--- a/media/learning/common/labelled_example.cc
+++ b/media/learning/common/labelled_example.cc
@@ -11,6 +11,10 @@
 
 LabelledExample::LabelledExample() = default;
 
+LabelledExample::LabelledExample(FeatureVector feature_vector,
+                                 TargetValue target)
+    : features(std::move(feature_vector)), target_value(target) {}
+
 LabelledExample::LabelledExample(std::initializer_list<FeatureValue> init_list,
                                  TargetValue target)
     : features(init_list), target_value(target) {}
diff --git a/media/learning/common/labelled_example.h b/media/learning/common/labelled_example.h
index 365abc3c..a728dc70 100644
--- a/media/learning/common/labelled_example.h
+++ b/media/learning/common/labelled_example.h
@@ -28,6 +28,7 @@
 // One training example == group of feature values, plus the desired target.
 struct COMPONENT_EXPORT(LEARNING_COMMON) LabelledExample {
   LabelledExample();
+  LabelledExample(FeatureVector feature_vector, TargetValue target);
   LabelledExample(std::initializer_list<FeatureValue> init_list,
                   TargetValue target);
   LabelledExample(const LabelledExample& rhs);
diff --git a/media/learning/impl/feature_provider.h b/media/learning/impl/feature_provider.h
index a8f0a57..3932905 100644
--- a/media/learning/impl/feature_provider.h
+++ b/media/learning/impl/feature_provider.h
@@ -25,15 +25,14 @@
 // indicates the type of network connection.
 class COMPONENT_EXPORT(LEARNING_IMPL) FeatureProvider {
  public:
-  using LabelledExampleCB = base::OnceCallback<void(LabelledExample)>;
+  using FeatureVectorCB = base::OnceCallback<void(FeatureVector)>;
 
   FeatureProvider();
   virtual ~FeatureProvider();
 
-  // Update |example| to include whatever features are specified by |task_|,
+  // Update |features| to include whatever features are specified by |task_|,
   // and call |cb| once they're filled in.
-  virtual void AddFeatures(const LabelledExample& example,
-                           LabelledExampleCB cb) = 0;
+  virtual void AddFeatures(FeatureVector features, FeatureVectorCB cb) = 0;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(FeatureProvider);
diff --git a/media/learning/impl/learning_session_impl_unittest.cc b/media/learning/impl/learning_session_impl_unittest.cc
index 1b2027b9..6c23d64 100644
--- a/media/learning/impl/learning_session_impl_unittest.cc
+++ b/media/learning/impl/learning_session_impl_unittest.cc
@@ -27,8 +27,8 @@
       // we can verify that it was given to us by the session.
       if (!feature_provider_.is_null()) {
         feature_provider_.Post(FROM_HERE, &FeatureProvider::AddFeatures,
-                               LabelledExample(),
-                               FeatureProvider::LabelledExampleCB());
+                               FeatureVector(),
+                               FeatureProvider::FeatureVectorCB());
       }
     }
 
@@ -45,8 +45,8 @@
     FakeFeatureProvider(bool* flag_ptr) : flag_ptr_(flag_ptr) {}
 
     // Do nothing, except note that we were called.
-    void AddFeatures(const LabelledExample& example,
-                     FeatureProvider::LabelledExampleCB cb) override {
+    void AddFeatures(FeatureVector features,
+                     FeatureProvider::FeatureVectorCB cb) override {
       *flag_ptr_ = true;
     }
 
diff --git a/media/learning/impl/learning_task_controller_impl.cc b/media/learning/impl/learning_task_controller_impl.cc
index 63ba5302..d75a6fe6 100644
--- a/media/learning/impl/learning_task_controller_impl.cc
+++ b/media/learning/impl/learning_task_controller_impl.cc
@@ -39,31 +39,39 @@
   if (feature_provider_) {
     // TODO(liberato): SequenceBound should make this easier.
     feature_provider_.Post(
-        FROM_HERE, &FeatureProvider::AddFeatures, example,
-        base::BindOnce(&LearningTaskControllerImpl::OnExampleReadyTrampoline,
-                       task_runner_, AsWeakPtr()));
+        FROM_HERE, &FeatureProvider::AddFeatures, example.features,
+        base::BindOnce(&LearningTaskControllerImpl::OnFeaturesReadyTrampoline,
+                       task_runner_, AsWeakPtr(), example));
   } else {
-    OnExampleReady(example);
+    AddFinishedExample(example);
   }
 }
 
 // static
-void LearningTaskControllerImpl::OnExampleReadyTrampoline(
+void LearningTaskControllerImpl::OnFeaturesReadyTrampoline(
     scoped_refptr<base::SequencedTaskRunner> task_runner,
     base::WeakPtr<LearningTaskControllerImpl> weak_this,
-    LabelledExample example) {
+    LabelledExample example,
+    FeatureVector features) {
   if (!task_runner->RunsTasksInCurrentSequence()) {
     task_runner->PostTask(
-        FROM_HERE, base::BindOnce(&LearningTaskControllerImpl::OnExampleReady,
-                                  std::move(weak_this), std::move(example)));
+        FROM_HERE, base::BindOnce(&LearningTaskControllerImpl::OnFeaturesReady,
+                                  std::move(weak_this), std::move(example),
+                                  std::move(features)));
     return;
   }
 
   if (weak_this)
-    weak_this->OnExampleReady(std::move(example));
+    weak_this->OnFeaturesReady(std::move(example), std::move(features));
 }
 
-void LearningTaskControllerImpl::OnExampleReady(LabelledExample example) {
+void LearningTaskControllerImpl::OnFeaturesReady(LabelledExample example,
+                                                 FeatureVector features) {
+  example.features = std::move(features);
+  AddFinishedExample(example);
+}
+
+void LearningTaskControllerImpl::AddFinishedExample(LabelledExample example) {
   if (training_data_->size() >= task_.max_data_set_size) {
     // Replace a random example.  We don't necessarily want to replace the
     // oldest, since we don't necessarily want to enforce an ad-hoc recency
diff --git a/media/learning/impl/learning_task_controller_impl.h b/media/learning/impl/learning_task_controller_impl.h
index 516d727e..ef2c12a 100644
--- a/media/learning/impl/learning_task_controller_impl.h
+++ b/media/learning/impl/learning_task_controller_impl.h
@@ -39,16 +39,21 @@
 
  private:
   // Trampoline method for receiving examples from |feature_provider_|.  Will
-  // chain directly to OnExampleReady if we're on |task_runner| and |weak_thiz|
+  // chain directly to OnExampleReady if we're on |task_runner| and |weak_this|
   // is non-null, else it will post to |task_runner|.
-  static void OnExampleReadyTrampoline(
+  static void OnFeaturesReadyTrampoline(
       scoped_refptr<base::SequencedTaskRunner> task_runner,
       base::WeakPtr<LearningTaskControllerImpl> weak_this,
-      LabelledExample example);
+      LabelledExample example,
+      FeatureVector features);
 
-  // Called when a new example has been finished by |feature_provider_|, if
-  // needed, to actually add the example.
-  void OnExampleReady(LabelledExample example);
+  // Called when a new feature vector has been finished by |feature_provider_|,
+  // if needed, to actually add the example.  |features| will replace the ones
+  // in |example|.
+  void OnFeaturesReady(LabelledExample example, FeatureVector features);
+
+  // Add |example| to the training data, and process it.
+  void AddFinishedExample(LabelledExample example);
 
   // Called by |training_cb_| when the model is trained.
   void OnModelTrained(std::unique_ptr<Model> model);
diff --git a/media/learning/impl/learning_task_controller_impl_unittest.cc b/media/learning/impl/learning_task_controller_impl_unittest.cc
index 3d854676..5a18077 100644
--- a/media/learning/impl/learning_task_controller_impl_unittest.cc
+++ b/media/learning/impl/learning_task_controller_impl_unittest.cc
@@ -82,11 +82,9 @@
   // Increments feature 0.
   class FakeFeatureProvider : public FeatureProvider {
    public:
-    void AddFeatures(const LabelledExample& example,
-                     LabelledExampleCB cb) override {
-      LabelledExample new_example = example;
-      new_example.features[0] = FeatureValue(example.features[0].value() + 1);
-      std::move(cb).Run(new_example);
+    void AddFeatures(FeatureVector features, FeatureVectorCB cb) override {
+      features[0] = FeatureValue(features[0].value() + 1);
+      std::move(cb).Run(features);
     }
   };
 
@@ -183,9 +181,11 @@
   CreateController(std::move(feature_provider));
   LabelledExample example;
   example.features.push_back(FeatureValue(123));
+  example.weight = 321u;
   controller_->AddExample(example);
   scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(trainer_raw_->training_data()[0].features[0], FeatureValue(124));
+  EXPECT_EQ(trainer_raw_->training_data()[0].weight, example.weight);
 }
 
 }  // namespace learning
diff --git a/net/third_party/quic/tools/quic_server.cc b/net/third_party/quic/tools/quic_server.cc
index cb02b2d9..f3901d3e 100644
--- a/net/third_party/quic/tools/quic_server.cc
+++ b/net/third_party/quic/tools/quic_server.cc
@@ -14,8 +14,6 @@
 #include <cstdint>
 #include <memory>
 
-#include "base/bind.h"
-#include "base/run_loop.h"
 #include "net/third_party/quic/core/crypto/crypto_handshake.h"
 #include "net/third_party/quic/core/crypto/quic_random.h"
 #include "net/third_party/quic/core/quic_crypto_stream.h"
@@ -79,8 +77,7 @@
       crypto_config_options_(crypto_config_options),
       version_manager_(supported_versions),
       packet_reader_(new QuicPacketReader()),
-      quic_simple_server_backend_(quic_simple_server_backend),
-      weak_factory_(this) {
+      quic_simple_server_backend_(quic_simple_server_backend) {
   Initialize();
 }
 
@@ -165,17 +162,6 @@
   epoll_server_.WaitForEventsAndExecuteCallbacks();
 }
 
-void QuicServer::Start() {
-  Run();
-  base::RunLoop().Run();
-}
-
-void QuicServer::Run() {
-  WaitForEvents();
-  base::ThreadTaskRunnerHandle::Get()->PostTask(
-      FROM_HERE, base::BindOnce(&QuicServer::Run, weak_factory_.GetWeakPtr()));
-}
-
 void QuicServer::Shutdown() {
   if (!silent_close_) {
     // Before we shut down the epoll server, give all active sessions a chance
diff --git a/net/third_party/quic/tools/quic_server.h b/net/third_party/quic/tools/quic_server.h
index fb62348..e5c9588 100644
--- a/net/third_party/quic/tools/quic_server.h
+++ b/net/third_party/quic/tools/quic_server.h
@@ -14,7 +14,6 @@
 #include <memory>
 
 #include "base/macros.h"
-#include "net/quic/quic_chromium_connection_helper.h"
 #include "net/third_party/quic/core/crypto/quic_crypto_server_config.h"
 #include "net/third_party/quic/core/quic_config.h"
 #include "net/third_party/quic/core/quic_framer.h"
@@ -23,7 +22,6 @@
 #include "net/third_party/quic/platform/api/quic_epoll.h"
 #include "net/third_party/quic/platform/api/quic_socket_address.h"
 #include "net/third_party/quic/tools/quic_simple_server_backend.h"
-#include "net/tools/epoll_server/epoll_server.h"
 
 namespace quic {
 
@@ -56,9 +54,6 @@
   // Wait up to 50ms, and handle any events which occur.
   void WaitForEvents();
 
-  void Start();
-  void Run();
-
   // Server deletion is imminent.  Start cleaning up the epoll server.
   virtual void Shutdown();
 
@@ -149,8 +144,6 @@
   std::unique_ptr<QuicPacketReader> packet_reader_;
 
   QuicSimpleServerBackend* quic_simple_server_backend_;  // unowned.
-
-  base::WeakPtrFactory<QuicServer> weak_factory_;
 };
 
 }  // namespace quic
diff --git a/net/third_party/quic/tools/quic_server_bin.cc b/net/third_party/quic/tools/quic_server_bin.cc
index fffbdec..b105a07 100644
--- a/net/third_party/quic/tools/quic_server_bin.cc
+++ b/net/third_party/quic/tools/quic_server_bin.cc
@@ -44,9 +44,6 @@
   base::CommandLine::Init(argc, argv);
   base::CommandLine* line = base::CommandLine::ForCurrentProcess();
 
-  base::MessageLoopForIO message_loop;
-  base::TaskScheduler::CreateAndStartWithDefaultParams("quic_server");
-
   logging::LoggingSettings settings;
   settings.logging_dest = logging::LOG_TO_SYSTEM_DEBUG_LOG;
   CHECK(logging::InitLogging(settings));
@@ -75,7 +72,7 @@
   if (line->HasSwitch("mode")) {
     FLAGS_quic_mode = line->GetSwitchValueASCII("mode");
   }
-  if (FLAGS_quic_mode.compare("cache") == 0) {
+  if (FLAGS_quic_mode == "cache") {
     if (line->HasSwitch("quic_response_cache_dir")) {
       FLAGS_quic_response_cache_dir =
           line->GetSwitchValueASCII("quic_response_cache_dir");
@@ -122,6 +119,6 @@
   }
 
   while (true) {
-    server.Start();
+    server.WaitForEvents();
   }
 }
diff --git a/net/websockets/websocket_basic_stream_test.cc b/net/websockets/websocket_basic_stream_test.cc
index 91217039..1c6e6fc 100644
--- a/net/websockets/websocket_basic_stream_test.cc
+++ b/net/websockets/websocket_basic_stream_test.cc
@@ -33,7 +33,7 @@
 
 #define WEBSOCKET_BASIC_STREAM_TEST_DEFINE_CONSTANT(name, value) \
   const char k##name[] = value;                                  \
-  const size_t k##name##Size = base::size(k##name) - 1;
+  const size_t k##name##Size = base::size(k##name) - 1
 
 WEBSOCKET_BASIC_STREAM_TEST_DEFINE_CONSTANT(SampleFrame, "\x81\x06Sample");
 WEBSOCKET_BASIC_STREAM_TEST_DEFINE_CONSTANT(
diff --git a/services/catalog/BUILD.gn b/services/catalog/BUILD.gn
deleted file mode 100644
index b893976..0000000
--- a/services/catalog/BUILD.gn
+++ /dev/null
@@ -1,56 +0,0 @@
-# Copyright 2016 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import("//testing/test.gni")
-
-group("catalog") {
-  testonly = true
-  deps = [
-    ":lib",
-  ]
-}
-
-source_set("constants") {
-  sources = [
-    "store.cc",
-    "store.h",
-  ]
-}
-
-component("lib") {
-  sources = [
-    "catalog.cc",
-    "catalog.h",
-    "constants.cc",
-    "constants.h",
-    "entry.cc",
-    "entry.h",
-    "entry_cache.cc",
-    "entry_cache.h",
-    "instance.cc",
-    "instance.h",
-    "service_options.cc",
-    "service_options.h",
-  ]
-
-  configs += [ "//build/config/compiler:wexit_time_destructors" ]
-
-  deps = [
-    ":constants",
-    "//base",
-    "//components/services/filesystem:lib",
-    "//services/catalog/public/cpp",
-    "//services/catalog/public/mojom",
-    "//services/service_manager/public/cpp",
-  ]
-
-  public_deps = [
-    # directory.mojom.h is #included by catalog.h
-    "//components/services/filesystem/public/interfaces",
-  ]
-
-  output_name = "catalog_lib"
-
-  defines = [ "IS_CATALOG_IMPL" ]
-}
diff --git a/services/catalog/OWNERS b/services/catalog/OWNERS
deleted file mode 100644
index d2a928b7..0000000
--- a/services/catalog/OWNERS
+++ /dev/null
@@ -1,5 +0,0 @@
-ben@chromium.org
-rockot@google.com
-
-per-file manifest.json=set noparent
-per-file manifest.json=file://ipc/SECURITY_OWNERS
diff --git a/services/catalog/catalog.cc b/services/catalog/catalog.cc
deleted file mode 100644
index 4b7bacb..0000000
--- a/services/catalog/catalog.cc
+++ /dev/null
@@ -1,134 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "services/catalog/catalog.h"
-
-#include <memory>
-#include <string>
-
-#include "base/base_paths.h"
-#include "base/bind.h"
-#include "base/command_line.h"
-#include "base/files/file_path.h"
-#include "base/files/file_util.h"
-#include "base/lazy_instance.h"
-#include "base/macros.h"
-#include "base/memory/ref_counted_delete_on_sequence.h"
-#include "base/path_service.h"
-#include "base/sequenced_task_runner.h"
-#include "base/strings/string_util.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/task/post_task.h"
-#include "components/services/filesystem/directory_impl.h"
-#include "components/services/filesystem/lock_table.h"
-#include "components/services/filesystem/public/interfaces/types.mojom.h"
-#include "mojo/public/cpp/bindings/strong_binding.h"
-#include "services/catalog/constants.h"
-#include "services/catalog/entry_cache.h"
-#include "services/catalog/instance.h"
-
-namespace catalog {
-
-// Wraps state needed for servicing directory requests on a separate thread.
-// filesystem::LockTable is not thread safe, so it's wrapped in
-// DirectoryThreadState.
-class Catalog::DirectoryThreadState
-    : public base::RefCountedDeleteOnSequence<DirectoryThreadState> {
- public:
-  explicit DirectoryThreadState(
-      scoped_refptr<base::SequencedTaskRunner> task_runner)
-      : base::RefCountedDeleteOnSequence<DirectoryThreadState>(
-            std::move(task_runner)) {}
-
-  scoped_refptr<filesystem::LockTable> lock_table() {
-    if (!lock_table_)
-      lock_table_ = new filesystem::LockTable;
-    return lock_table_;
-  }
-
- private:
-  friend class base::DeleteHelper<DirectoryThreadState>;
-  friend class base::RefCountedDeleteOnSequence<DirectoryThreadState>;
-
-  ~DirectoryThreadState() = default;
-
-  scoped_refptr<filesystem::LockTable> lock_table_;
-
-  DISALLOW_COPY_AND_ASSIGN(DirectoryThreadState);
-};
-
-Catalog::Catalog(const std::vector<service_manager::Manifest>& manifests) {
-  for (const auto& manifest : manifests)
-    system_cache_.AddRootEntryFromManifest(manifest);
-  registry_.AddInterface<mojom::Catalog>(base::BindRepeating(
-      &Catalog::BindCatalogRequest, base::Unretained(this)));
-  registry_.AddInterface<filesystem::mojom::Directory>(base::BindRepeating(
-      &Catalog::BindDirectoryRequest, base::Unretained(this)));
-}
-
-Catalog::~Catalog() = default;
-
-void Catalog::BindServiceRequest(
-    service_manager::mojom::ServiceRequest request) {
-  service_binding_.Bind(std::move(request));
-}
-
-Instance* Catalog::GetInstanceForGroup(const base::Token& instance_group) {
-  auto it = instances_.find(instance_group);
-  if (it != instances_.end())
-    return it->second.get();
-
-  auto result = instances_.emplace(instance_group,
-                                   std::make_unique<Instance>(&system_cache_));
-  return result.first->second.get();
-}
-
-void Catalog::BindCatalogRequest(
-    mojom::CatalogRequest request,
-    const service_manager::BindSourceInfo& source_info) {
-  Instance* instance =
-      GetInstanceForGroup(source_info.identity.instance_group());
-  instance->BindCatalog(std::move(request));
-}
-
-void Catalog::BindDirectoryRequest(
-    filesystem::mojom::DirectoryRequest request,
-    const service_manager::BindSourceInfo& source_info) {
-  if (!directory_task_runner_) {
-    directory_task_runner_ = base::CreateSequencedTaskRunnerWithTraits(
-        {base::MayBlock(),
-         // Use USER_BLOCKING as this gates showing UI during startup.
-         base::TaskPriority::USER_BLOCKING,
-         base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN});
-    directory_thread_state_ = new DirectoryThreadState(directory_task_runner_);
-  }
-  directory_task_runner_->PostTask(
-      FROM_HERE,
-      base::BindOnce(&Catalog::BindDirectoryRequestOnBackgroundThread,
-                     directory_thread_state_, std::move(request), source_info));
-}
-
-// static
-void Catalog::BindDirectoryRequestOnBackgroundThread(
-    scoped_refptr<DirectoryThreadState> thread_state,
-    filesystem::mojom::DirectoryRequest request,
-    const service_manager::BindSourceInfo& source_info) {
-  base::FilePath resources_path;
-  base::PathService::Get(base::DIR_MODULE, &resources_path);
-  mojo::MakeStrongBinding(
-      std::make_unique<filesystem::DirectoryImpl>(
-          resources_path, scoped_refptr<filesystem::SharedTempDir>(),
-          thread_state->lock_table()),
-      std::move(request));
-}
-
-void Catalog::OnBindInterface(
-    const service_manager::BindSourceInfo& source_info,
-    const std::string& interface_name,
-    mojo::ScopedMessagePipeHandle interface_pipe) {
-  registry_.BindInterface(interface_name, std::move(interface_pipe),
-                          source_info);
-}
-
-}  // namespace catalog
diff --git a/services/catalog/catalog.h b/services/catalog/catalog.h
deleted file mode 100644
index 2d5d999..0000000
--- a/services/catalog/catalog.h
+++ /dev/null
@@ -1,87 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef SERVICES_CATALOG_CATALOG_H_
-#define SERVICES_CATALOG_CATALOG_H_
-
-#include <map>
-#include <memory>
-#include <string>
-
-#include "base/component_export.h"
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/token.h"
-#include "components/services/filesystem/public/interfaces/directory.mojom.h"
-#include "mojo/public/cpp/bindings/binding.h"
-#include "mojo/public/cpp/bindings/binding_set.h"
-#include "services/catalog/entry_cache.h"
-#include "services/catalog/public/mojom/catalog.mojom.h"
-#include "services/service_manager/public/cpp/binder_registry.h"
-#include "services/service_manager/public/cpp/manifest.h"
-#include "services/service_manager/public/cpp/service.h"
-#include "services/service_manager/public/cpp/service_binding.h"
-#include "services/service_manager/public/mojom/service.mojom.h"
-
-namespace base {
-class SequencedTaskRunner;
-}
-
-namespace catalog {
-
-class Instance;
-
-// Creates and owns an instance of the catalog. Exposes a ServicePtr that
-// can be passed to the service manager, potentially in a different process.
-class COMPONENT_EXPORT(CATALOG) Catalog : public service_manager::Service {
- public:
-  // Constructs a catalog over a set of Manifests to use for lookup.
-  explicit Catalog(const std::vector<service_manager::Manifest>& manifests);
-  ~Catalog() override;
-
-  void BindServiceRequest(service_manager::mojom::ServiceRequest request);
-
-  Instance* GetInstanceForGroup(const base::Token& instance_group);
-
- private:
-  class DirectoryThreadState;
-  class ServiceImpl;
-
-  void BindCatalogRequest(mojom::CatalogRequest request,
-                          const service_manager::BindSourceInfo& source_info);
-
-  void BindDirectoryRequest(filesystem::mojom::DirectoryRequest request,
-                            const service_manager::BindSourceInfo& source_info);
-
-  static void BindDirectoryRequestOnBackgroundThread(
-      scoped_refptr<DirectoryThreadState> thread_state,
-      filesystem::mojom::DirectoryRequest request,
-      const service_manager::BindSourceInfo& source_info);
-
-  // service_manager::Service:
-  void OnBindInterface(const service_manager::BindSourceInfo& source_info,
-                       const std::string& interface_name,
-                       mojo::ScopedMessagePipeHandle interface_pipe) override;
-
-  service_manager::ServiceBinding service_binding_{this};
-  service_manager::BinderRegistryWithArgs<
-      const service_manager::BindSourceInfo&>
-      registry_;
-
-  EntryCache system_cache_;
-  std::map<base::Token, std::unique_ptr<Instance>> instances_;
-
-  // The TaskRunner used for directory requests. Directory requests run on a
-  // separate thread as they run file io, which is not allowed on the thread the
-  // service manager runs on. Additionally we shouldn't block the service
-  // manager while doing file io.
-  scoped_refptr<base::SequencedTaskRunner> directory_task_runner_;
-  scoped_refptr<DirectoryThreadState> directory_thread_state_;
-
-  DISALLOW_COPY_AND_ASSIGN(Catalog);
-};
-
-}  // namespace catalog
-
-#endif  // SERVICES_CATALOG_CATALOG_H_
diff --git a/services/catalog/constants.cc b/services/catalog/constants.cc
deleted file mode 100644
index 2d6ea402..0000000
--- a/services/catalog/constants.cc
+++ /dev/null
@@ -1,11 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "services/catalog/constants.h"
-
-namespace catalog {
-
-const char kPackagesDirName[] = "Packages";
-
-}  // namespace catalog
diff --git a/services/catalog/constants.h b/services/catalog/constants.h
deleted file mode 100644
index f49cf937..0000000
--- a/services/catalog/constants.h
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef SERVICES_CATALOG_CONSTANTS_H_
-#define SERVICES_CATALOG_CONSTANTS_H_
-
-#include "base/component_export.h"
-
-namespace catalog {
-
-COMPONENT_EXPORT(CATALOG) extern const char kPackagesDirName[];
-
-}  // namespace catalog
-
-#endif  // SERVICES_CATALOG_CONSTANTS_H_
diff --git a/services/catalog/entry.cc b/services/catalog/entry.cc
deleted file mode 100644
index c1d438d..0000000
--- a/services/catalog/entry.cc
+++ /dev/null
@@ -1,64 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "services/catalog/entry.h"
-
-#include "base/files/file_path.h"
-#include "services/catalog/store.h"
-#include "services/service_manager/public/mojom/interface_provider_spec.mojom.h"
-
-namespace catalog {
-
-Entry::Entry() {}
-Entry::Entry(const std::string& name)
-    : name_(name),
-      display_name_(name) {}
-Entry::~Entry() {}
-
-bool Entry::ProvidesCapability(const std::string& capability) const {
-  auto it = interface_provider_specs_.find(
-      service_manager::mojom::kServiceManager_ConnectorSpec);
-  if (it == interface_provider_specs_.end())
-    return false;
-
-  const auto& connection_spec = it->second;
-  return connection_spec.provides.find(capability) !=
-      connection_spec.provides.end();
-}
-
-bool Entry::operator==(const Entry& other) const {
-  return other.name_ == name_ && other.display_name_ == display_name_ &&
-         other.sandbox_type_ == sandbox_type_ &&
-         other.interface_provider_specs_ == interface_provider_specs_;
-}
-
-void Entry::AddOptions(ServiceOptions options) {
-  options_ = std::move(options);
-}
-
-void Entry::AddInterfaceProviderSpec(
-    const std::string& name,
-    service_manager::InterfaceProviderSpec spec) {
-  interface_provider_specs_[name] = std::move(spec);
-}
-
-void Entry::AddRequiredFilePath(const std::string& name, base::FilePath path) {
-  required_file_paths_[name] = std::move(path);
-}
-
-}  // catalog
-
-namespace mojo {
-
-// static
-catalog::mojom::EntryPtr
-    TypeConverter<catalog::mojom::EntryPtr, catalog::Entry>::Convert(
-        const catalog::Entry& input) {
-  catalog::mojom::EntryPtr result(catalog::mojom::Entry::New());
-  result->name = input.name();
-  result->display_name = input.display_name();
-  return result;
-}
-
-}  // namespace mojo
diff --git a/services/catalog/entry.h b/services/catalog/entry.h
deleted file mode 100644
index 46de570..0000000
--- a/services/catalog/entry.h
+++ /dev/null
@@ -1,100 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef SERVICES_CATALOG_ENTRY_H_
-#define SERVICES_CATALOG_ENTRY_H_
-
-#include <memory>
-#include <string>
-#include <vector>
-
-#include "base/component_export.h"
-#include "base/files/file_path.h"
-#include "base/macros.h"
-#include "services/catalog/public/mojom/catalog.mojom.h"
-#include "services/catalog/service_options.h"
-#include "services/service_manager/public/cpp/interface_provider_spec.h"
-
-namespace catalog {
-
-// Static information about a service package known to the Catalog.
-class COMPONENT_EXPORT(CATALOG) Entry {
- public:
-  Entry();
-  explicit Entry(const std::string& name);
-  ~Entry();
-
-  bool ProvidesCapability(const std::string& capability) const;
-
-  bool operator==(const Entry& other) const;
-
-  const std::string& name() const { return name_; }
-  void set_name(std::string name) { name_ = std::move(name); }
-
-  const base::FilePath& path() const { return path_; }
-  void set_path(base::FilePath path) { path_ = std::move(path); }
-
-  const std::string& display_name() const { return display_name_; }
-  void set_display_name(std::string display_name) {
-    display_name_ = std::move(display_name);
-  }
-
-  const std::string& sandbox_type() const { return sandbox_type_; }
-  void set_sandbox_type(std::string sandbox_type) {
-    sandbox_type_ = std::move(sandbox_type);
-  }
-
-  const Entry* parent() const { return parent_; }
-  void set_parent(const Entry* parent) { parent_ = parent; }
-
-  const std::vector<std::unique_ptr<Entry>>& children() const {
-    return children_;
-  }
-  std::vector<std::unique_ptr<Entry>>& children() { return children_; }
-  void set_children(std::vector<std::unique_ptr<Entry>> children) {
-    children_ = std::move(children);
-  }
-
-  void AddOptions(ServiceOptions options);
-  const ServiceOptions& options() const { return options_; }
-
-  void AddInterfaceProviderSpec(const std::string& name,
-                                service_manager::InterfaceProviderSpec spec);
-  const service_manager::InterfaceProviderSpecMap&
-      interface_provider_specs() const {
-    return interface_provider_specs_;
-  }
-
-  void AddRequiredFilePath(const std::string& name, base::FilePath path);
-  const std::map<std::string, base::FilePath>& required_file_paths() const {
-    return required_file_paths_;
-  }
-
- private:
-  std::string name_;
-  base::FilePath path_;
-  std::string display_name_;
-  std::string sandbox_type_;
-  ServiceOptions options_;
-
-  service_manager::InterfaceProviderSpecMap interface_provider_specs_;
-  std::map<std::string, base::FilePath> required_file_paths_;
-  const Entry* parent_ = nullptr;
-  std::vector<std::unique_ptr<Entry>> children_;
-
-  DISALLOW_COPY_AND_ASSIGN(Entry);
-};
-
-}  // namespace catalog
-
-namespace mojo {
-
-template<>
-struct TypeConverter<catalog::mojom::EntryPtr, catalog::Entry> {
-  static catalog::mojom::EntryPtr Convert(const catalog::Entry& input);
-};
-
-}  // namespace mojo
-
-#endif  // SERVICES_CATALOG_ENTRY_H_
diff --git a/services/catalog/entry_cache.cc b/services/catalog/entry_cache.cc
deleted file mode 100644
index 3edf088..0000000
--- a/services/catalog/entry_cache.cc
+++ /dev/null
@@ -1,149 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "services/catalog/entry_cache.h"
-
-#include <map>
-#include <set>
-#include <string>
-
-#include "base/base_paths.h"
-#include "base/files/file_path.h"
-#include "base/path_service.h"
-#include "build/build_config.h"
-#include "services/catalog/entry.h"
-#include "services/service_manager/public/cpp/interface_provider_spec.h"
-#include "services/service_manager/public/mojom/interface_provider_spec.mojom.h"
-
-namespace catalog {
-
-namespace {
-
-#if defined(OS_WIN)
-const char kServiceExecutableExtension[] = ".service.exe";
-#else
-const char kServiceExecutableExtension[] = ".service";
-#endif
-
-// Temporary helper to create a cache Entry from a Manifest object. This can
-// disappear once the Service Manager just uses Manifest objects directly.
-std::unique_ptr<Entry> MakeEntryFromManifest(
-    const service_manager::Manifest& manifest) {
-  auto entry = std::make_unique<Entry>();
-  entry->set_name(manifest.service_name);
-  entry->set_display_name(manifest.display_name.raw_string);
-
-  base::FilePath service_exe_root;
-  CHECK(base::PathService::Get(base::DIR_ASSETS, &service_exe_root));
-  entry->set_path(service_exe_root.AppendASCII(entry->name() +
-                                               kServiceExecutableExtension));
-
-  entry->set_sandbox_type(manifest.options.sandbox_type);
-
-  ServiceOptions options;
-  switch (manifest.options.instance_sharing_policy) {
-    case service_manager::Manifest::InstanceSharingPolicy::kNoSharing:
-      options.instance_sharing = ServiceOptions::InstanceSharingType::NONE;
-      break;
-    case service_manager::Manifest::InstanceSharingPolicy::kSingleton:
-      options.instance_sharing = ServiceOptions::InstanceSharingType::SINGLETON;
-      break;
-    case service_manager::Manifest::InstanceSharingPolicy::kSharedAcrossGroups:
-      options.instance_sharing =
-          ServiceOptions::InstanceSharingType::SHARED_ACROSS_INSTANCE_GROUPS;
-      break;
-  }
-  options.can_connect_to_instances_in_any_group =
-      manifest.options.can_connect_to_instances_in_any_group;
-  options.can_connect_to_other_services_with_any_instance_name =
-      manifest.options.can_connect_to_instances_with_any_id;
-  options.can_create_other_service_instances =
-      manifest.options.can_register_other_service_instances;
-  options.interfaces_bindable_on_any_service =
-      manifest.interfaces_bindable_on_any_service;
-  entry->AddOptions(options);
-
-  service_manager::InterfaceProviderSpec main_spec;
-  main_spec.provides = manifest.exposed_capabilities;
-  main_spec.requires = manifest.required_capabilities;
-
-  entry->AddInterfaceProviderSpec(
-      service_manager::mojom::kServiceManager_ConnectorSpec,
-      std::move(main_spec));
-
-  std::map<std::string, service_manager::InterfaceProviderSpec> other_specs;
-  for (const auto& entry : manifest.exposed_interface_filter_capabilities)
-    other_specs[entry.first].provides = entry.second;
-  for (const auto& entry : manifest.required_interface_filter_capabilities)
-    other_specs[entry.first].requires = entry.second;
-  for (auto& spec : other_specs)
-    entry->AddInterfaceProviderSpec(spec.first, std::move(spec.second));
-
-  for (const auto& file : manifest.preloaded_files)
-    entry->AddRequiredFilePath(file.key, file.path);
-
-  for (const auto& packaged_service_manifest : manifest.packaged_services) {
-    auto child = MakeEntryFromManifest(packaged_service_manifest);
-    child->set_parent(entry.get());
-    entry->children().emplace_back(std::move(child));
-  }
-
-  return entry;
-}
-
-}  // namespace
-
-EntryCache::EntryCache() {}
-
-EntryCache::~EntryCache() {}
-
-bool EntryCache::AddRootEntry(std::unique_ptr<Entry> entry) {
-  DCHECK(entry);
-  const std::string& name = entry->name();
-  if (!AddEntry(entry.get()))
-    return false;
-  root_entries_.insert(std::make_pair(name, std::move(entry)));
-  return true;
-}
-
-bool EntryCache::AddRootEntryFromManifest(
-    const service_manager::Manifest& manifest) {
-  return AddRootEntry(MakeEntryFromManifest(manifest));
-}
-
-const Entry* EntryCache::GetEntry(const std::string& name) {
-  auto iter = entries_.find(name);
-  if (iter == entries_.end())
-    return nullptr;
-  return iter->second;
-}
-
-bool EntryCache::AddEntry(const Entry* entry) {
-  auto root_iter = root_entries_.find(entry->name());
-  if (root_iter != root_entries_.end()) {
-    RemoveEntry(root_iter->second.get());
-    root_entries_.erase(root_iter);
-  } else {
-    auto entry_iter = entries_.find(entry->name());
-    if (entry_iter != entries_.end()) {
-      // There's already a non-root entry for this name, so we change nothing.
-      return false;
-    }
-  }
-
-  entries_.insert({ entry->name(), entry });
-  for (const auto& child : entry->children())
-    AddEntry(child.get());
-  return true;
-}
-
-void EntryCache::RemoveEntry(const Entry* entry) {
-  auto iter = entries_.find(entry->name());
-  if (iter->second == entry)
-    entries_.erase(iter);
-  for (const auto& child : entry->children())
-    RemoveEntry(child.get());
-}
-
-}  // namespace catalog
diff --git a/services/catalog/entry_cache.h b/services/catalog/entry_cache.h
deleted file mode 100644
index 8b9d76c..0000000
--- a/services/catalog/entry_cache.h
+++ /dev/null
@@ -1,75 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef SERVICES_CATALOG_ENTRY_CACHE_H_
-#define SERVICES_CATALOG_ENTRY_CACHE_H_
-
-#include <map>
-#include <memory>
-#include <string>
-
-#include "base/component_export.h"
-#include "base/macros.h"
-#include "services/service_manager/public/cpp/manifest.h"
-
-namespace catalog {
-
-class Entry;
-
-// Indexed storage for all existing service catalog entries.
-class COMPONENT_EXPORT(CATALOG) EntryCache {
- public:
-  EntryCache();
-  ~EntryCache();
-
-  // All entries in the cache, including non-root entries.
-  const std::map<std::string, const Entry*>& entries() const {
-    return entries_;
-  }
-
-  // Adds a new root entry to the cache. If a root entry already exists
-  // corresponding to the new entry's name, the old root entry is removed first,
-  // along with its children.
-  //
-  // If a non-root entry already exists corresponding to the new entry's name,
-  // the new entry is ignored.
-  //
-  // Returns |true| if the entry was added and |false| otherwise.
-  //
-  // TODO(rockot): Duplicate entries should be treated as an error, but for now
-  // we tolerate them because of some remaining dependency on Package directory
-  // scanning, which in turn has some unpredictable behavior with respect to
-  // Entry registration.
-  bool AddRootEntry(std::unique_ptr<Entry> entry);
-
-  // Adds a new root entry to the cache given a Manifest.
-  bool AddRootEntryFromManifest(const service_manager::Manifest& manifest);
-
-  // Queries the cache for an entry corresponding to |name|. Returns null if
-  // such an entry is not found.
-  const Entry* GetEntry(const std::string& name);
-
- private:
-  // Adds and entry and its children to |entries_|. Returns |true| if the Entry
-  // was successfully added and |false| otherwise.
-  bool AddEntry(const Entry* entry);
-
-  // Removes an entry and its children from |entries_|.
-  void RemoveEntry(const Entry* entry);
-
-  // Map of top-level service entries. This transitively owns all existing
-  // Entry objects.
-  std::map<std::string, std::unique_ptr<Entry>> root_entries_;
-
-  // Map of service name to Entry. Each value points to an Entry owned either
-  // directly or indirectly by |entries_| above. This is essentially a flattened
-  // version of |entries_| with no ownership.
-  std::map<std::string, const Entry*> entries_;
-
-  DISALLOW_COPY_AND_ASSIGN(EntryCache);
-};
-
-}  // namespace catalog
-
-#endif  // SERVICES_CATALOG_ENTRY_CACHE_H_
diff --git a/services/catalog/instance.cc b/services/catalog/instance.cc
deleted file mode 100644
index 8cc1422..0000000
--- a/services/catalog/instance.cc
+++ /dev/null
@@ -1,74 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "services/catalog/instance.h"
-
-#include <memory>
-
-#include "base/bind.h"
-#include "base/values.h"
-#include "services/catalog/entry.h"
-#include "services/catalog/entry_cache.h"
-
-namespace catalog {
-namespace {
-
-void AddEntry(const Entry& entry, std::vector<mojom::EntryPtr>* ary) {
-  mojom::EntryPtr entry_ptr(mojom::Entry::New());
-  entry_ptr->name = entry.name();
-  entry_ptr->display_name = entry.display_name();
-  ary->push_back(std::move(entry_ptr));
-}
-
-}  // namespace
-
-Instance::Instance(EntryCache* system_cache) : system_cache_(system_cache) {}
-
-Instance::~Instance() = default;
-
-void Instance::BindCatalog(mojom::CatalogRequest request) {
-  catalog_bindings_.AddBinding(this, std::move(request));
-}
-
-const Entry* Instance::Resolve(const std::string& service_name) {
-  DCHECK(system_cache_);
-  const Entry* cached_entry = system_cache_->GetEntry(service_name);
-  if (cached_entry)
-    return cached_entry;
-
-  LOG(ERROR) << "Unable to locate service manifest for " << service_name;
-  return nullptr;
-}
-
-void Instance::GetEntries(const base::Optional<std::vector<std::string>>& names,
-                          GetEntriesCallback callback) {
-  DCHECK(system_cache_);
-
-  std::vector<mojom::EntryPtr> entries;
-  if (!names.has_value()) {
-    // TODO(beng): user catalog.
-    for (const auto& entry : system_cache_->entries())
-      AddEntry(*entry.second, &entries);
-  } else {
-    for (const std::string& name : names.value()) {
-      const Entry* entry = system_cache_->GetEntry(name);
-      // TODO(beng): user catalog.
-      if (entry)
-        AddEntry(*entry, &entries);
-    }
-  }
-  std::move(callback).Run(std::move(entries));
-}
-
-void Instance::GetEntriesProvidingCapability(
-    const std::string& capability,
-    GetEntriesProvidingCapabilityCallback callback) {
-  std::vector<mojom::EntryPtr> entries;
-  for (const auto& entry : system_cache_->entries())
-    if (entry.second->ProvidesCapability(capability))
-      entries.push_back(mojom::Entry::From(*entry.second));
-  std::move(callback).Run(std::move(entries));
-}
-
-}  // namespace catalog
diff --git a/services/catalog/instance.h b/services/catalog/instance.h
deleted file mode 100644
index 14faa9d3..0000000
--- a/services/catalog/instance.h
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef SERVICES_CATALOG_INSTANCE_H_
-#define SERVICES_CATALOG_INSTANCE_H_
-
-#include "base/component_export.h"
-#include "base/files/file_path.h"
-#include "base/path_service.h"
-#include "base/values.h"
-#include "mojo/public/cpp/bindings/binding_set.h"
-#include "services/catalog/entry.h"
-#include "services/catalog/public/mojom/catalog.mojom.h"
-#include "services/catalog/store.h"
-
-namespace catalog {
-
-class EntryCache;
-
-class COMPONENT_EXPORT(CATALOG) Instance : public mojom::Catalog {
- public:
-  // |system_cache| is not owned.
-  explicit Instance(EntryCache* system_cache);
-  ~Instance() override;
-
-  void BindCatalog(mojom::CatalogRequest request);
-
-  const Entry* Resolve(const std::string& service_name);
-
- private:
-  // mojom::Catalog:
-  void GetEntries(const base::Optional<std::vector<std::string>>& names,
-                  GetEntriesCallback callback) override;
-  void GetEntriesProvidingCapability(
-      const std::string& capability,
-      GetEntriesProvidingCapabilityCallback callback) override;
-
-  mojo::BindingSet<mojom::Catalog> catalog_bindings_;
-
-  // A map of name -> Entry data structure for system-level packages (i.e. those
-  // that are visible to all users).
-  // TODO(beng): eventually add per-user applications.
-  EntryCache* const system_cache_;
-
-  DISALLOW_COPY_AND_ASSIGN(Instance);
-};
-
-}  // namespace catalog
-
-#endif  // SERVICES_CATALOG_INSTANCE_H_
diff --git a/services/catalog/public/cpp/BUILD.gn b/services/catalog/public/cpp/BUILD.gn
index 1b61a04..6145b2f 100644
--- a/services/catalog/public/cpp/BUILD.gn
+++ b/services/catalog/public/cpp/BUILD.gn
@@ -15,7 +15,6 @@
     "//components/services/filesystem/public/interfaces",
     "//mojo/public/cpp/bindings",
     "//mojo/public/cpp/system",
-    "//services/catalog:constants",
     "//services/service_manager/public/cpp",
   ]
 }
diff --git a/services/catalog/service_options.cc b/services/catalog/service_options.cc
deleted file mode 100644
index b4a203f..0000000
--- a/services/catalog/service_options.cc
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "services/catalog/service_options.h"
-
-namespace catalog {
-
-ServiceOptions::ServiceOptions() = default;
-
-ServiceOptions::ServiceOptions(const ServiceOptions& other) = default;
-
-ServiceOptions::~ServiceOptions() = default;
-
-}  // namespace catalog
diff --git a/services/catalog/service_options.h b/services/catalog/service_options.h
deleted file mode 100644
index d6cef73..0000000
--- a/services/catalog/service_options.h
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef SERVICES_CATALOG_SERVICE_OPTIONS_H_
-#define SERVICES_CATALOG_SERVICE_OPTIONS_H_
-
-#include <set>
-#include <string>
-
-#include "base/component_export.h"
-#include "base/macros.h"
-
-namespace catalog {
-
-struct COMPONENT_EXPORT(CATALOG) ServiceOptions {
-  enum class InstanceSharingType {
-    NONE,
-    SINGLETON,
-    SHARED_ACROSS_INSTANCE_GROUPS,
-  };
-
-  ServiceOptions();
-  ServiceOptions(const ServiceOptions& other);
-  ~ServiceOptions();
-
-  InstanceSharingType instance_sharing = InstanceSharingType::NONE;
-  bool can_connect_to_instances_in_any_group = false;
-  bool can_connect_to_other_services_with_any_instance_name = false;
-  bool can_create_other_service_instances = false;
-  std::set<std::string> interfaces_bindable_on_any_service;
-};
-
-}  // namespace catalog
-
-#endif  // SERVICES_CATALOG_SERVICE_OPTIONS_H_
diff --git a/services/catalog/store.cc b/services/catalog/store.cc
deleted file mode 100644
index 8edde82..0000000
--- a/services/catalog/store.cc
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "services/catalog/store.h"
-
-namespace catalog {
-
-// static
-const char Store::kNameKey[] = "name";
-// static
-const char Store::kDisplayNameKey[] = "display_name";
-// static
-const char Store::kSandboxTypeKey[] = "sandbox_type";
-// static
-const char Store::kOptionsKey[] = "options";
-// static
-const char Store::kInterfaceProviderSpecsKey[] = "interface_provider_specs";
-// static
-const char Store::kInterfaceProviderSpecs_ProvidesKey[] = "provides";
-// static
-const char Store::kInterfaceProviderSpecs_RequiresKey[] = "requires";
-// static
-const char Store::kServicesKey[] = "services";
-// static
-const char Store::kRequiredFilesKey[] = "required_files";
-// static
-const char Store::kRequiredFilesKey_PathKey[] = "path";
-// static
-const char Store::kRequiredFilesKey_PlatformKey[] = "platform";
-// static
-const char Store::kRequiredFilesKey_PlatformValue_Windows[] = "windows";
-// static
-const char Store::kRequiredFilesKey_PlatformValue_Linux[] = "linux";
-// static
-const char Store::kRequiredFilesKey_PlatformValue_MacOSX[] = "macosx";
-// static
-const char Store::kRequiredFilesKey_PlatformValue_Android[] = "android";
-// static
-const char Store::kRequiredFilesKey_PlatformValue_Fuchsia[] = "fuchsia";
-
-}  // namespace catalog
diff --git a/services/catalog/store.h b/services/catalog/store.h
deleted file mode 100644
index d523c2e1..0000000
--- a/services/catalog/store.h
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef SERVICES_CATALOG_STORE_H_
-#define SERVICES_CATALOG_STORE_H_
-
-namespace catalog {
-
-// TODO(rockot): Clean this up now that it's only a namespace for constants.
-// Alternatively, re-introduce a Store interface once it makes sense to do so.
-class Store {
- public:
-  // Value is a string.
-  static const char kNameKey[];
-  // Value is a string.
-  static const char kDisplayNameKey[];
-  // Value is a string.
-  static const char kSandboxTypeKey[];
-  // Value is a dictionary.
-  static const char kOptionsKey[];
-  // Value is a dictionary.
-  static const char kInterfaceProviderSpecsKey[];
-  // Value is a dictionary.
-  static const char kInterfaceProviderSpecs_ProvidesKey[];
-  // Value is a dictionary.
-  static const char kInterfaceProviderSpecs_RequiresKey[];
-  // Value is a list.
-  static const char kServicesKey[];
-  // Value is a dictionary.
-  static const char kRequiredFilesKey[];
-  // Value is a string.
-  static const char kRequiredFilesKey_PathKey[];
-  // Value is a string.
-  static const char kRequiredFilesKey_PlatformKey[];
-  static const char kRequiredFilesKey_PlatformValue_Windows[];
-  static const char kRequiredFilesKey_PlatformValue_Linux[];
-  static const char kRequiredFilesKey_PlatformValue_MacOSX[];
-  static const char kRequiredFilesKey_PlatformValue_Android[];
-  static const char kRequiredFilesKey_PlatformValue_Fuchsia[];
-};
-
-}  // namespace catalog
-
-#endif  // SERVICES_CATALOG_STORE_H_
diff --git a/services/identity/public/cpp/identity_manager.cc b/services/identity/public/cpp/identity_manager.cc
index 9a64d88..9fb67bb9 100644
--- a/services/identity/public/cpp/identity_manager.cc
+++ b/services/identity/public/cpp/identity_manager.cc
@@ -474,13 +474,13 @@
 
 void IdentityManager::OnAccountUpdated(const AccountInfo& info) {
   for (auto& observer : observer_list_) {
-    observer.OnAccountUpdated(info);
+    observer.OnExtendedAccountInfoUpdated(info);
   }
 }
 
 void IdentityManager::OnAccountRemoved(const AccountInfo& info) {
   for (auto& observer : observer_list_)
-    observer.OnAccountRemovedWithInfo(info);
+    observer.OnExtendedAccountInfoRemoved(info);
 }
 
 }  // namespace identity
diff --git a/services/identity/public/cpp/identity_manager.h b/services/identity/public/cpp/identity_manager.h
index cb27b09..bdd3ccb 100644
--- a/services/identity/public/cpp/identity_manager.h
+++ b/services/identity/public/cpp/identity_manager.h
@@ -151,10 +151,10 @@
     virtual void OnEndBatchOfRefreshTokenStateChanges() {}
 
     // Called after an account is updated.
-    virtual void OnAccountUpdated(const AccountInfo& info) {}
+    virtual void OnExtendedAccountInfoUpdated(const AccountInfo& info) {}
 
     // Called after removing an account info.
-    virtual void OnAccountRemovedWithInfo(const AccountInfo& info) {}
+    virtual void OnExtendedAccountInfoRemoved(const AccountInfo& info) {}
   };
 
   // Observer interface for classes that want to monitor status of various
diff --git a/services/identity/public/cpp/identity_manager_unittest.cc b/services/identity/public/cpp/identity_manager_unittest.cc
index eb701f6c..d862c700 100644
--- a/services/identity/public/cpp/identity_manager_unittest.cc
+++ b/services/identity/public/cpp/identity_manager_unittest.cc
@@ -391,11 +391,11 @@
     is_inside_batch_ = false;
   }
 
-  void OnAccountUpdated(const AccountInfo& info) override {
+  void OnExtendedAccountInfoUpdated(const AccountInfo& info) override {
     account_from_account_updated_callback_ = info;
   }
 
-  void OnAccountRemovedWithInfo(const AccountInfo& info) override {
+  void OnExtendedAccountInfoRemoved(const AccountInfo& info) override {
     was_called_account_removed_with_info_callback_ = true;
     account_from_account_removed_with_info_callback_ = info;
   }
diff --git a/services/service_manager/BUILD.gn b/services/service_manager/BUILD.gn
index 7e921ce..8709a062 100644
--- a/services/service_manager/BUILD.gn
+++ b/services/service_manager/BUILD.gn
@@ -23,6 +23,8 @@
   sources = [
     "background_service_manager.cc",
     "background_service_manager.h",
+    "catalog.cc",
+    "catalog.h",
     "connect_params.cc",
     "connect_params.h",
     "service_manager.cc",
@@ -37,14 +39,14 @@
 
   deps = [
     "//base/third_party/dynamic_annotations",
+    "//components/services/filesystem:lib",
+    "//components/services/filesystem/public/interfaces",
   ]
 
   public_deps = [
     "//base",
     "//mojo/public/cpp/bindings",
-    "//services/catalog:constants",
-    "//services/catalog:lib",
-    "//services/catalog/public/mojom:constants",
+    "//services/catalog/public/mojom",
     "//services/service_manager/public/cpp",
     "//services/service_manager/public/mojom",
     "//services/service_manager/sandbox",
diff --git a/services/service_manager/DEPS b/services/service_manager/DEPS
index a73a7c9..eac54bc 100644
--- a/services/service_manager/DEPS
+++ b/services/service_manager/DEPS
@@ -1,4 +1,5 @@
 include_rules = [
+  "+components/services/filesystem",
   "+sandbox",
   "+services/catalog",
 ]
diff --git a/services/service_manager/background_service_manager.cc b/services/service_manager/background_service_manager.cc
index d8cacde66..0c6ae4d 100644
--- a/services/service_manager/background_service_manager.cc
+++ b/services/service_manager/background_service_manager.cc
@@ -16,7 +16,6 @@
 #include "base/single_thread_task_runner.h"
 #include "base/synchronization/waitable_event.h"
 #include "base/threading/simple_thread.h"
-#include "services/catalog/store.h"
 #include "services/service_manager/connect_params.h"
 #include "services/service_manager/public/cpp/service.h"
 #include "services/service_manager/service_manager.h"
diff --git a/services/service_manager/catalog.cc b/services/service_manager/catalog.cc
new file mode 100644
index 0000000..e656a30
--- /dev/null
+++ b/services/service_manager/catalog.cc
@@ -0,0 +1,194 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "services/service_manager/catalog.h"
+
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "base/base_paths.h"
+#include "base/bind.h"
+#include "base/command_line.h"
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
+#include "base/lazy_instance.h"
+#include "base/macros.h"
+#include "base/memory/ref_counted_delete_on_sequence.h"
+#include "base/path_service.h"
+#include "base/sequenced_task_runner.h"
+#include "base/strings/string_util.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/task/post_task.h"
+#include "components/services/filesystem/directory_impl.h"
+#include "components/services/filesystem/lock_table.h"
+#include "components/services/filesystem/public/interfaces/types.mojom.h"
+#include "mojo/public/cpp/bindings/strong_binding.h"
+
+namespace service_manager {
+
+namespace {
+
+std::map<Manifest::ServiceName, const Manifest*> CreateManifestMap(
+    const std::vector<Manifest>& manifests) {
+  std::map<Manifest::ServiceName, const Manifest*> map;
+  for (const auto& manifest : manifests) {
+    map[manifest.service_name] = &manifest;
+    for (const auto& entry : CreateManifestMap(manifest.packaged_services))
+      map[entry.first] = entry.second;
+  }
+  return map;
+}
+
+std::map<Manifest::ServiceName, const Manifest*> CreateParentManifestMap(
+    const std::vector<Manifest>& manifests) {
+  std::map<Manifest::ServiceName, const Manifest*> map;
+  for (const auto& parent : manifests) {
+    for (const auto& child : parent.packaged_services)
+      map[child.service_name] = &parent;
+    for (const auto& entry : CreateParentManifestMap(parent.packaged_services))
+      map[entry.first] = entry.second;
+  }
+  return map;
+}
+
+}  // namespace
+
+// Wraps state needed for servicing directory requests on a separate thread.
+// filesystem::LockTable is not thread safe, so it's wrapped in
+// DirectoryThreadState.
+class Catalog::DirectoryThreadState
+    : public base::RefCountedDeleteOnSequence<DirectoryThreadState> {
+ public:
+  explicit DirectoryThreadState(
+      scoped_refptr<base::SequencedTaskRunner> task_runner)
+      : base::RefCountedDeleteOnSequence<DirectoryThreadState>(
+            std::move(task_runner)) {}
+
+  scoped_refptr<filesystem::LockTable> lock_table() {
+    if (!lock_table_)
+      lock_table_ = new filesystem::LockTable;
+    return lock_table_;
+  }
+
+ private:
+  friend class base::DeleteHelper<DirectoryThreadState>;
+  friend class base::RefCountedDeleteOnSequence<DirectoryThreadState>;
+
+  ~DirectoryThreadState() = default;
+
+  scoped_refptr<filesystem::LockTable> lock_table_;
+
+  DISALLOW_COPY_AND_ASSIGN(DirectoryThreadState);
+};
+
+Catalog::Catalog(const std::vector<Manifest>& manifests)
+    : manifests_(manifests),
+      manifest_map_(CreateManifestMap(manifests_)),
+      parent_manifest_map_(CreateParentManifestMap(manifests_)) {
+  registry_.AddInterface<catalog::mojom::Catalog>(base::BindRepeating(
+      &Catalog::BindCatalogRequest, base::Unretained(this)));
+  registry_.AddInterface<filesystem::mojom::Directory>(base::BindRepeating(
+      &Catalog::BindDirectoryRequest, base::Unretained(this)));
+}
+
+Catalog::~Catalog() = default;
+
+void Catalog::BindServiceRequest(mojom::ServiceRequest request) {
+  service_binding_.Bind(std::move(request));
+}
+
+const Manifest* Catalog::GetManifest(
+    const Manifest::ServiceName& service_name) {
+  const auto it = manifest_map_.find(service_name);
+  if (it == manifest_map_.end())
+    return nullptr;
+  return it->second;
+}
+
+const Manifest* Catalog::GetParentManifest(
+    const Manifest::ServiceName& service_name) {
+  auto it = parent_manifest_map_.find(service_name);
+  if (it == parent_manifest_map_.end())
+    return nullptr;
+
+  return it->second;
+}
+
+void Catalog::BindCatalogRequest(catalog::mojom::CatalogRequest request) {
+  catalog_bindings_.AddBinding(this, std::move(request));
+}
+
+void Catalog::BindDirectoryRequest(
+    filesystem::mojom::DirectoryRequest request) {
+  if (!directory_task_runner_) {
+    directory_task_runner_ = base::CreateSequencedTaskRunnerWithTraits(
+        {base::MayBlock(),
+         // Use USER_BLOCKING as this gates showing UI during startup.
+         base::TaskPriority::USER_BLOCKING,
+         base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN});
+    directory_thread_state_ = new DirectoryThreadState(directory_task_runner_);
+  }
+  directory_task_runner_->PostTask(
+      FROM_HERE,
+      base::BindOnce(&Catalog::BindDirectoryRequestOnBackgroundThread,
+                     directory_thread_state_, std::move(request)));
+}
+
+// static
+void Catalog::BindDirectoryRequestOnBackgroundThread(
+    scoped_refptr<DirectoryThreadState> thread_state,
+    filesystem::mojom::DirectoryRequest request) {
+  base::FilePath resources_path;
+  base::PathService::Get(base::DIR_MODULE, &resources_path);
+  mojo::MakeStrongBinding(
+      std::make_unique<filesystem::DirectoryImpl>(
+          resources_path, scoped_refptr<filesystem::SharedTempDir>(),
+          thread_state->lock_table()),
+      std::move(request));
+}
+
+void Catalog::OnBindInterface(const BindSourceInfo& source_info,
+                              const std::string& interface_name,
+                              mojo::ScopedMessagePipeHandle interface_pipe) {
+  registry_.BindInterface(interface_name, std::move(interface_pipe));
+}
+
+void Catalog::GetEntries(const base::Optional<std::vector<std::string>>& names,
+                         GetEntriesCallback callback) {
+  std::vector<catalog::mojom::EntryPtr> entries;
+  if (!names.has_value()) {
+    for (const auto& entry : manifest_map_) {
+      const auto* manifest = entry.second;
+      entries.push_back(catalog::mojom::Entry::New(
+          manifest->service_name, manifest->display_name.raw_string));
+    }
+  } else {
+    for (const std::string& name : names.value()) {
+      const auto* manifest = GetManifest(name);
+      if (manifest) {
+        entries.push_back(catalog::mojom::Entry::New(
+            manifest->service_name, manifest->display_name.raw_string));
+      }
+    }
+  }
+  std::move(callback).Run(std::move(entries));
+}
+
+void Catalog::GetEntriesProvidingCapability(
+    const std::string& capability,
+    GetEntriesProvidingCapabilityCallback callback) {
+  std::vector<catalog::mojom::EntryPtr> entries;
+  for (const auto& entry : manifest_map_) {
+    const auto* manifest = entry.second;
+    if (manifest->exposed_capabilities.find(capability) !=
+        manifest->exposed_capabilities.end()) {
+      entries.push_back(catalog::mojom::Entry::New(
+          manifest->service_name, manifest->display_name.raw_string));
+    }
+  }
+  std::move(callback).Run(std::move(entries));
+}
+
+}  // namespace service_manager
diff --git a/services/service_manager/catalog.h b/services/service_manager/catalog.h
new file mode 100644
index 0000000..908c76af
--- /dev/null
+++ b/services/service_manager/catalog.h
@@ -0,0 +1,106 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SERVICES_SERVICE_MANAGER_CATALOG_H_
+#define SERVICES_SERVICE_MANAGER_CATALOG_H_
+
+#include <map>
+#include <string>
+#include <vector>
+
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/token.h"
+#include "components/services/filesystem/public/interfaces/directory.mojom.h"
+#include "mojo/public/cpp/bindings/binding.h"
+#include "mojo/public/cpp/bindings/binding_set.h"
+#include "services/catalog/public/mojom/catalog.mojom.h"
+#include "services/service_manager/public/cpp/binder_registry.h"
+#include "services/service_manager/public/cpp/manifest.h"
+#include "services/service_manager/public/cpp/service.h"
+#include "services/service_manager/public/cpp/service_binding.h"
+#include "services/service_manager/public/mojom/service.mojom.h"
+
+namespace base {
+class SequencedTaskRunner;
+}
+
+namespace service_manager {
+
+// Creates and owns an instance of the catalog and hosts a ServiceBinding to
+// bind interface requests targeting the Catalog service.
+//
+// TODO(https://crbug.com/904240): Get rid of the Service implementation.
+// This doesn't need to be a separate service from the Service Manager.
+class Catalog : public Service, public catalog::mojom::Catalog {
+ public:
+  // Constructs a catalog over a set of Manifests to use for lookup.
+  explicit Catalog(const std::vector<Manifest>& manifests);
+  ~Catalog() override;
+
+  void BindServiceRequest(mojom::ServiceRequest request);
+
+  // Returns manifest data for the service named by |service_name|. If no
+  // service is known by that name, this returns null.
+  const Manifest* GetManifest(const Manifest::ServiceName& service_name);
+
+  // Returns manifest data for the parent of the service named by
+  // |service_name|. If the named service has no parent (i.e. it's not packaged
+  // within another service) then this returns null.
+  const Manifest* GetParentManifest(const Manifest::ServiceName& service_name);
+
+ private:
+  class DirectoryThreadState;
+
+  void BindCatalogRequest(catalog::mojom::CatalogRequest request);
+  void BindDirectoryRequest(filesystem::mojom::DirectoryRequest request);
+
+  static void BindDirectoryRequestOnBackgroundThread(
+      scoped_refptr<DirectoryThreadState> thread_state,
+      filesystem::mojom::DirectoryRequest request);
+
+  // Service:
+  void OnBindInterface(const BindSourceInfo& source_info,
+                       const std::string& interface_name,
+                       mojo::ScopedMessagePipeHandle interface_pipe) override;
+
+  // mojom::Catalog:
+  void GetEntries(const base::Optional<std::vector<std::string>>& names,
+                  GetEntriesCallback callback) override;
+  void GetEntriesProvidingCapability(
+      const std::string& capability,
+      GetEntriesProvidingCapabilityCallback callback) override;
+
+  ServiceBinding service_binding_{this};
+  BinderRegistry registry_;
+
+  // Bindings for consumers of the Catalog interface.
+  mojo::BindingSet<catalog::mojom::Catalog> catalog_bindings_;
+
+  // The set of all top-level manifests known to the Service Manager.
+  const std::vector<Manifest> manifests_;
+
+  // Maintains a mapping from service name to manifest for quick lookup of any
+  // manifest regardless of whether it's packaged. The values in this map refer
+  // to objects owned by |manifests_| above.
+  const std::map<Manifest::ServiceName, const Manifest*> manifest_map_;
+
+  // Maintains a mapping from service name to parent manifest for quick
+  // reverse-lookup of packaged service relationships. The values in this map
+  // refer to objects owned by |manifests_| above.
+  const std::map<Manifest::ServiceName, const Manifest*> parent_manifest_map_;
+
+  // The TaskRunner used for directory requests. Directory requests run on a
+  // separate thread as they run file io, which is not allowed on the thread the
+  // service manager runs on. Additionally we shouldn't block the service
+  // manager while doing file io.
+  scoped_refptr<base::SequencedTaskRunner> directory_task_runner_;
+  scoped_refptr<DirectoryThreadState> directory_thread_state_;
+
+  DISALLOW_COPY_AND_ASSIGN(Catalog);
+};
+
+}  // namespace service_manager
+
+#endif  // SERVICES_SERVICE_MANAGER_CATALOG_H_
diff --git a/services/service_manager/service_manager.cc b/services/service_manager/service_manager.cc
index 7e9c217..b61ce39 100644
--- a/services/service_manager/service_manager.cc
+++ b/services/service_manager/service_manager.cc
@@ -7,16 +7,20 @@
 #include <stdint.h>
 
 #include <algorithm>
-#include <tuple>
+#include <set>
+#include <string>
 #include <utility>
 
+#include "base/base_paths.h"
 #include "base/bind.h"
 #include "base/command_line.h"
+#include "base/files/file_path.h"
 #include "base/logging.h"
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/no_destructor.h"
 #include "base/optional.h"
+#include "base/path_service.h"
 #include "base/process/process.h"
 #include "base/process/process_handle.h"
 #include "base/stl_util.h"
@@ -28,11 +32,10 @@
 #include "mojo/public/cpp/bindings/binding.h"
 #include "mojo/public/cpp/bindings/binding_set.h"
 #include "mojo/public/cpp/bindings/strong_binding.h"
-#include "services/catalog/entry.h"
-#include "services/catalog/instance.h"
 #include "services/catalog/public/mojom/constants.mojom.h"
 #include "services/service_manager/public/cpp/connector.h"
 #include "services/service_manager/public/cpp/constants.h"
+#include "services/service_manager/public/cpp/manifest_builder.h"
 #include "services/service_manager/public/cpp/service.h"
 #include "services/service_manager/public/mojom/connector.mojom.h"
 #include "services/service_manager/public/mojom/service.mojom.h"
@@ -50,21 +53,28 @@
 
 const char kCapability_ServiceManager[] = "service_manager:service_manager";
 
-// Returns the set of capabilities required from the target.
-CapabilitySet GetRequestedCapabilities(const InterfaceProviderSpec& source_spec,
-                                       const Identity& target) {
-  CapabilitySet capabilities;
+#if defined(OS_WIN)
+const char kServiceExecutableExtension[] = ".service.exe";
+#else
+const char kServiceExecutableExtension[] = ".service";
+#endif
 
-  // Start by looking for specs specific to the supplied identity.
-  auto it = source_spec.requires.find(target.name());
-  if (it != source_spec.requires.end()) {
+// Returns the set of capabilities required from the target by the source.
+std::set<std::string> GetRequiredCapabilities(
+    const Manifest::RequiredCapabilityMap& source_requirements,
+    const std::string& target_service) {
+  std::set<std::string> capabilities;
+
+  // Start by looking for requirements specific to the target identity.
+  auto it = source_requirements.find(target_service);
+  if (it != source_requirements.end()) {
     std::copy(it->second.begin(), it->second.end(),
               std::inserter(capabilities, capabilities.begin()));
   }
 
   // Apply wild card rules too.
-  it = source_spec.requires.find("*");
-  if (it != source_spec.requires.end()) {
+  it = source_requirements.find("*");
+  if (it != source_requirements.end()) {
     std::copy(it->second.begin(), it->second.end(),
               std::inserter(capabilities, capabilities.begin()));
   }
@@ -80,39 +90,17 @@
 #endif
 }
 
-// Generates a single set of interfaces that is the union of all interfaces
-// exposed by the target for the capabilities requested by the source.
-InterfaceSet GetInterfacesToExpose(const InterfaceProviderSpec& source_spec,
-                                   const Identity& target,
-                                   const InterfaceProviderSpec& target_spec) {
-  DCHECK(target.IsValid());
-  InterfaceSet exposed_interfaces;
-  CapabilitySet capabilities = GetRequestedCapabilities(source_spec, target);
-  for (const auto& capability : capabilities) {
-    auto it = target_spec.provides.find(capability);
-    if (it != target_spec.provides.end()) {
-      for (const auto& interface_name : it->second)
-        exposed_interfaces.insert(interface_name);
-    }
-  }
-  return exposed_interfaces;
-}
-
-const InterfaceProviderSpec& GetEmptyInterfaceProviderSpec() {
-  static base::NoDestructor<InterfaceProviderSpec> spec;
-  return *spec;
-}
-
-bool HasCapability(const InterfaceProviderSpec& spec,
-                   const std::string& capability) {
-  auto it = spec.requires.find(service_manager::mojom::kServiceName);
-  if (it == spec.requires.end())
+bool RequiresCapability(const Manifest& manifest,
+                        const Manifest::ServiceName& from_service_name,
+                        const Manifest::CapabilityName& capability) {
+  auto it = manifest.required_capabilities.find(from_service_name);
+  if (it == manifest.required_capabilities.end())
     return false;
   return it->second.find(capability) != it->second.end();
 }
 
-void ReportBlockedInterface(const std::string& source_service_name,
-                            const std::string& target_service_name,
+void ReportBlockedInterface(const Manifest::ServiceName& source_service_name,
+                            const Manifest::ServiceName& target_service_name,
                             const std::string& target_interface_name) {
 #if DCHECK_IS_ON()
   // While it would not be correct to assert that this never happens (e.g. a
@@ -148,22 +136,26 @@
       << "services' manifests in order to remedy this situation.";
 }
 
-bool AllowsInterface(const Identity& source,
-                     const InterfaceProviderSpec& source_spec,
-                     const Identity& target,
-                     const InterfaceProviderSpec& target_spec,
+bool AllowsInterface(const Manifest::RequiredCapabilityMap& source_requirements,
+                     const std::string& target_name,
+                     const Manifest::ExposedCapabilityMap& target_capabilities,
                      const std::string& interface_name) {
-  InterfaceSet exposed =
-      GetInterfacesToExpose(source_spec, target, target_spec);
-  bool allowed = (exposed.size() == 1 && exposed.count("*") == 1) ||
-                 exposed.count(interface_name) > 0;
-  if (!allowed)
-    ReportBlockedInterface(source.name(), target.name(), interface_name);
+  std::set<std::string> allowed_interfaces;
+  std::set<std::string> required_capabilities =
+      GetRequiredCapabilities(source_requirements, target_name);
+  for (const auto& capability : required_capabilities) {
+    auto it = target_capabilities.find(capability);
+    if (it != target_capabilities.end()) {
+      for (const auto& interface_name : it->second)
+        allowed_interfaces.insert(interface_name);
+    }
+  }
+
+  bool allowed =
+      allowed_interfaces.count("*") || allowed_interfaces.count(interface_name);
   return allowed;
 }
 
-}  // namespace
-
 const Identity& GetServiceManagerInstanceIdentity() {
   static base::NoDestructor<Identity> id{service_manager::mojom::kServiceName,
                                          kSystemInstanceGroup, base::Token{},
@@ -171,6 +163,8 @@
   return *id;
 }
 
+}  // namespace
+
 // Encapsulates a connection to an instance of a service, tracked by the
 // Service Manager.
 class ServiceManager::Instance
@@ -182,13 +176,12 @@
  public:
   Instance(service_manager::ServiceManager* service_manager,
            const Identity& identity,
-           const InterfaceProviderSpecMap& interface_provider_specs,
-           const catalog::ServiceOptions& options)
+           const Manifest& manifest)
       : service_manager_(service_manager),
         identity_(identity),
-        interface_provider_specs_(interface_provider_specs),
-        options_(options),
-        allow_any_application_(GetConnectionSpec().requires.count("*") == 1),
+        manifest_(manifest),
+        can_contact_all_services_(manifest_.required_capabilities.count("*") ==
+                                  1),
         pid_receiver_binding_(this),
         control_binding_(this),
         state_(mojom::InstanceState::kCreated),
@@ -238,20 +231,21 @@
     }
 
     std::unique_ptr<ConnectParams> params(std::move(*in_params));
-
     Instance* source =
         service_manager_->GetExistingInstance(params->source());
     if (!source)
       return false;
 
-    const InterfaceProviderSpec& source_spec = source->GetConnectionSpec();
+    const Manifest& source_manifest = source->manifest();
     bool bindable_on_any_service =
-        source->options_.interfaces_bindable_on_any_service.count(
+        source->manifest_.interfaces_bindable_on_any_service.count(
             params->interface_name()) > 0;
-
-    if (!bindable_on_any_service &&
-        !AllowsInterface(params->source(), source_spec, identity_,
-                         GetConnectionSpec(), params->interface_name())) {
+    bool allowed_by_capabilities = AllowsInterface(
+        source_manifest.required_capabilities, identity_.name(),
+        manifest_.exposed_capabilities, params->interface_name());
+    if (!bindable_on_any_service && !allowed_by_capabilities) {
+      ReportBlockedInterface(params->source().name(), identity_.name(),
+                             params->interface_name());
       params->set_response_data(mojom::ConnectResult::ACCESS_DENIED, identity_);
       return false;
     }
@@ -266,8 +260,10 @@
     }
 
     service_->OnBindInterface(
-        BindSourceInfo(params->source(),
-                       GetRequestedCapabilities(source_spec, identity_)),
+        BindSourceInfo(
+            params->source(),
+            GetRequiredCapabilities(source_manifest.required_capabilities,
+                                    identity_.name())),
         params->interface_name(), params->TakeInterfaceRequestPipe(),
         std::move(on_bind_interface_complete));
     return true;
@@ -322,19 +318,7 @@
     return info;
   }
 
-  const InterfaceProviderSpec& GetConnectionSpec() const {
-    return GetSpec(mojom::kServiceManager_ConnectorSpec);
-  }
-  bool HasSpec(const std::string& spec) const {
-    auto it = interface_provider_specs_.find(spec);
-    return it != interface_provider_specs_.end();
-  }
-  const InterfaceProviderSpec& GetSpec(const std::string& spec) const {
-    auto it = interface_provider_specs_.find(spec);
-    return it != interface_provider_specs_.end()
-               ? it->second
-               : GetEmptyInterfaceProviderSpec();
-  }
+  const Manifest& manifest() const { return manifest_; }
 
   const Identity& identity() const { return identity_; }
 
@@ -351,8 +335,8 @@
         service_manager_->GetExistingInstance(source_info.identity);
     DCHECK(source);
     if (interface_name == mojom::ServiceManager::Name_ &&
-        HasCapability(source->GetConnectionSpec(),
-                      kCapability_ServiceManager)) {
+        RequiresCapability(source->manifest(), mojom::kServiceName,
+                           kCapability_ServiceManager)) {
       mojom::ServiceManagerRequest request =
           mojom::ServiceManagerRequest(std::move(interface_pipe));
       service_manager_bindings_.AddBinding(this, std::move(request));
@@ -363,14 +347,14 @@
   class InterfaceProviderImpl : public mojom::InterfaceProvider {
    public:
     InterfaceProviderImpl(Instance* instance,
-                          const std::string& spec,
+                          const std::string& filter_name,
                           const Identity& source_identity,
                           const Identity& target_identity,
                           service_manager::ServiceManager* service_manager,
                           mojom::InterfaceProviderPtr target,
                           mojom::InterfaceProviderRequest source_request)
         : instance_(instance),
-          spec_(spec),
+          filter_name_(filter_name),
           source_identity_(source_identity),
           target_identity_(target_identity),
           service_manager_(service_manager),
@@ -396,32 +380,44 @@
           service_manager_->GetExistingInstance(target_identity_);
       if (!source || !target)
         return;
-      if (!ValidateSpec(source) || !ValidateSpec(target))
+
+      const auto& source_filters =
+          source->manifest().required_interface_filter_capabilities;
+      const auto& target_filters =
+          target->manifest().exposed_interface_filter_capabilities;
+
+      auto source_iter = source_filters.find(filter_name_);
+      if (source_iter == source_filters.end()) {
+        DLOG(ERROR) << source_identity_.name() << " does not specify any "
+                    << "requirements for a filter named '" << filter_name_
+                    << "'";
         return;
+      }
 
-      if (AllowsInterface(source_identity_, source->GetSpec(spec_),
-                          target_identity_, target->GetSpec(spec_),
-                          interface_name)) {
+      auto target_iter = target_filters.find(filter_name_);
+      if (target_iter == target_filters.end()) {
+        DLOG(ERROR) << target_identity_.name() << " does not expose any "
+                    << "capabilities for a filter named '" << filter_name_
+                    << "'";
+        return;
+      }
+
+      if (AllowsInterface(source_iter->second, target_identity_.name(),
+                          target_iter->second, interface_name)) {
         target_->GetInterface(interface_name, std::move(interface_pipe));
+      } else {
+        ReportBlockedInterface(source_identity_.name(), target_identity_.name(),
+                               interface_name);
       }
     }
 
-    bool ValidateSpec(Instance* instance) const {
-      if (!instance->HasSpec(spec_)) {
-        LOG(ERROR) << "Instance for: " << instance->identity().name()
-                   << " did not have spec named: " << spec_;
-        return false;
-      }
-      return true;
-    }
-
     void OnConnectionError() {
       // Deletes |this|.
       instance_->filters_.erase(this);
     }
 
     Instance* const instance_;
-    const std::string spec_;
+    const std::string filter_name_;
     const Identity source_identity_;
     const Identity target_identity_;
     const service_manager::ServiceManager* service_manager_;
@@ -507,7 +503,7 @@
     mojom::ServicePtr service(
         mojom::ServicePtrInfo(std::move(service_handle), 0));
 
-    if (!options_.can_create_other_service_instances) {
+    if (!manifest_.options.can_register_other_service_instances) {
       LOG(ERROR) << "Instance: " << identity_.name() << " attempting "
                  << "to register an instance for a process it created for "
                  << "target: " << identity.name() << " without "
@@ -549,13 +545,13 @@
     connectors_.AddBinding(this, std::move(request));
   }
 
-  void FilterInterfaces(const std::string& spec,
+  void FilterInterfaces(const std::string& filter_name,
                         const Identity& source,
                         mojom::InterfaceProviderRequest source_request,
                         mojom::InterfaceProviderPtr target) override {
     auto* filter = new InterfaceProviderImpl(
-        this, spec, source, identity_, service_manager_, std::move(target),
-        std::move(source_request));
+        this, filter_name, source, identity_, service_manager_,
+        std::move(target), std::move(source_request));
     filters_[filter] = base::WrapUnique(filter);
   }
 
@@ -579,18 +575,12 @@
       return mojom::ConnectResult::INVALID_ARGUMENT;
     }
 
-    const InterfaceProviderSpec& connection_spec = GetConnectionSpec();
-
-    // TODO(beng): Need to do the following additional policy validation of
-    // whether this instance is allowed to connect using:
-    // - non-null client process info.
     bool skip_instance_group_check =
-        options_.instance_sharing ==
-            catalog::ServiceOptions::InstanceSharingType::SINGLETON ||
-        options_.instance_sharing ==
-            catalog::ServiceOptions::InstanceSharingType::
-                SHARED_ACROSS_INSTANCE_GROUPS ||
-        options_.can_connect_to_instances_in_any_group;
+        manifest_.options.instance_sharing_policy ==
+            Manifest::InstanceSharingPolicy::kSingleton ||
+        manifest_.options.instance_sharing_policy ==
+            Manifest::InstanceSharingPolicy::kSharedAcrossGroups ||
+        manifest_.options.can_connect_to_instances_in_any_group;
 
     if (!skip_instance_group_check && target_filter.instance_group() &&
         target_filter.instance_group() != identity_.instance_group() &&
@@ -598,25 +588,25 @@
       LOG(ERROR) << "Instance " << identity_.ToString() << " attempting to "
                  << "connect to " << target_filter.service_name() << " in "
                  << "group " << target_filter.instance_group()->ToString()
-                 << " without the 'can_connect_to_instances_in_any_group' "
-                 << "option.";
+                 << " without |can_connect_to_instances_in_any_group| set to "
+                 << "|true|.";
       return mojom::ConnectResult::ACCESS_DENIED;
     }
     if (target_filter.instance_id() &&
         !target_filter.instance_id()->is_zero() &&
-        !options_.can_connect_to_other_services_with_any_instance_name) {
-      LOG(ERROR)
-          << "Instance " << identity_.ToString() << " attempting to connect to "
-          << target_filter.service_name() << " with instance ID "
-          << target_filter.instance_id()->ToString() << " without the "
-          << "'can_connect_to_other_services_with_any_instance_name' option.";
+        !manifest_.options.can_connect_to_instances_with_any_id) {
+      LOG(ERROR) << "Instance " << identity_.ToString()
+                 << " attempting to connect to " << target_filter.service_name()
+                 << " with instance ID "
+                 << target_filter.instance_id()->ToString() << " without "
+                 << "|can_connect_to_instances_with_any_id| set to |true|.";
       return mojom::ConnectResult::ACCESS_DENIED;
     }
 
-    if (allow_any_application_ ||
-        !options_.interfaces_bindable_on_any_service.empty() ||
-        connection_spec.requires.find(target_filter.service_name()) !=
-            connection_spec.requires.end()) {
+    if (can_contact_all_services_ ||
+        !manifest_.interfaces_bindable_on_any_service.empty() ||
+        manifest_.required_capabilities.find(target_filter.service_name()) !=
+            manifest_.required_capabilities.end()) {
       return mojom::ConnectResult::SUCCEEDED;
     }
 
@@ -692,13 +682,18 @@
 
   service_manager::ServiceManager* const service_manager_;
 
-  // An id that identifies this instance. Distinct from pid, as a single process
-  // may vend multiple application instances, and this object may exist before a
-  // process is launched.
+  // An id that identifies this instance. Distinct from PID, as a single process
+  // may host multiple service instances. Globally unique across time and space.
   Identity identity_;
-  const InterfaceProviderSpecMap interface_provider_specs_;
-  const catalog::ServiceOptions options_;
-  const bool allow_any_application_;
+
+  // The static service manifest provided for this service at system
+  // initialization.
+  const Manifest manifest_;
+
+  // Indicates if this instance requires at least one capability from the
+  // wildcard '*' service.
+  const bool can_contact_all_services_;
+
 #if !defined(OS_IOS)
   std::unique_ptr<ServiceProcessLauncher> runner_;
 #endif
@@ -965,33 +960,30 @@
       identity_to_instance_(std::make_unique<IdentityToInstanceMap>()),
       service_process_launcher_factory_(
           std::move(service_process_launcher_factory)) {
-  InterfaceProviderSpec spec;
-  spec.provides[kCapability_ServiceManager].insert(
-      "service_manager.mojom.ServiceManager");
-  spec.requires["*"].insert("service_manager:service_factory");
-  InterfaceProviderSpecMap specs;
-  specs[mojom::kServiceManager_ConnectorSpec] = std::move(spec);
-
-  service_manager_instance_ = CreateInstance(
-      GetServiceManagerInstanceIdentity(), InstanceType::kSingleton,
-      std::move(specs), catalog::ServiceOptions());
+  Manifest service_manager_manifest =
+      ManifestBuilder()
+          .ExposeCapability(kCapability_ServiceManager,
+                            Manifest::InterfaceList<mojom::ServiceManager>())
+          .RequireCapability("*", "service_manager:service_factory")
+          .Build();
+  service_manager_instance_ =
+      CreateInstance(GetServiceManagerInstanceIdentity(),
+                     InstanceType::kSingleton, service_manager_manifest);
 
   mojom::ServicePtr service;
   service_binding_.Bind(mojo::MakeRequest(&service));
   service_manager_instance_->StartWithService(std::move(service));
 
-  InterfaceProviderSpec catalog_spec;
-  catalog_spec.provides["directory"].insert("filesystem.mojom.Directory");
-  catalog_spec.provides["catalog:catalog"].insert("catalog.mojom.Catalog");
-  catalog_spec.provides["control"].insert("catalog.mojom.CatalogControl");
-  InterfaceProviderSpecMap catalog_specs;
-  catalog_specs[mojom::kServiceManager_ConnectorSpec] = std::move(catalog_spec);
+  Manifest catalog_manifest =
+      ManifestBuilder()
+          .ExposeCapability("directory", {"filesystem.mojom.Directory"})
+          .ExposeCapability("catalog:catalog", {"catalog.mojom.Catalog"})
+          .Build();
 
   Identity id{catalog::mojom::kServiceName, kSystemInstanceGroup, base::Token{},
               base::Token::CreateRandom()};
   Instance* instance =
-      CreateInstance(id, InstanceType::kSingleton, std::move(catalog_specs),
-                     catalog::ServiceOptions());
+      CreateInstance(id, InstanceType::kSingleton, catalog_manifest);
 
   mojom::ServicePtr catalog_service;
   catalog_.BindServiceRequest(mojo::MakeRequest(&catalog_service));
@@ -1069,10 +1061,9 @@
   // Beyond this point, in order to fulfill the connection request we need to
   // start a new instance of the target service.
 
-  const catalog::Entry* entry =
-      catalog_.GetInstanceForGroup(*target_filter.instance_group())
-          ->Resolve(target_filter.service_name());
-  if (!entry) {
+  const service_manager::Manifest* manifest =
+      catalog_.GetManifest(target_filter.service_name());
+  if (!manifest) {
     LOG(ERROR) << "Failed to resolve service name: "
                << target_filter.service_name();
     params->set_response_data(mojom::ConnectResult::INVALID_ARGUMENT,
@@ -1080,17 +1071,10 @@
     return;
   }
 
-  const InterfaceProviderSpecMap& interface_provider_specs =
-      entry->interface_provider_specs();
-
-  const catalog::ServiceOptions& options = entry->options();
-
-  bool all_user_instance = entry->options().instance_sharing ==
-                           catalog::ServiceOptions::InstanceSharingType::
-                               SHARED_ACROSS_INSTANCE_GROUPS;
-  bool singleton_instance =
-      entry->options().instance_sharing ==
-      catalog::ServiceOptions::InstanceSharingType::SINGLETON;
+  bool all_user_instance = manifest->options.instance_sharing_policy ==
+                           Manifest::InstanceSharingPolicy::kSharedAcrossGroups;
+  bool singleton_instance = manifest->options.instance_sharing_policy ==
+                            Manifest::InstanceSharingPolicy::kSingleton;
 
   // Services that have "shared_across_instance_groups" value of
   // "instance_sharing" option are allowed to field connection requests from
@@ -1139,19 +1123,8 @@
                  *target_filter.instance_id(), base::Token::CreateRandom());
   }
 
-  // The catalog was unable to read a manifest for this service. We can't do
-  // anything more.
-  if (interface_provider_specs.empty()) {
-    LOG(ERROR)
-        << "Error: The catalog was unable to read a manifest for service \""
-        << entry->name() << "\".";
-    params->set_response_data(mojom::ConnectResult::ACCESS_DENIED,
-                              base::nullopt);
-    return;
-  }
-
-  Instance* instance = CreateInstance(new_instance_identity, instance_type,
-                                      interface_provider_specs, options);
+  Instance* instance =
+      CreateInstance(new_instance_identity, instance_type, *manifest);
 
   // Below are various paths through which a new Instance can be bound to a
   // Service proxy.
@@ -1163,7 +1136,9 @@
     return;
   }
 
-  if (entry->parent()) {
+  const service_manager::Manifest* parent_manifest =
+      catalog_.GetParentManifest(manifest->service_name);
+  if (parent_manifest) {
     // This service is provided by another service via a ServiceFactory.
     //
     // We normally ignore the target instance group and generate a unique
@@ -1181,7 +1156,7 @@
                  new_instance_identity.globally_unique_id()));
 
     auto factory_filter = ServiceFilter::ByNameWithIdInGroup(
-        entry->parent()->name(), *target_filter.instance_id(),
+        parent_manifest->service_name, *target_filter.instance_id(),
         *target_filter.instance_group());
 
     mojom::PIDReceiverPtr pid_receiver;
@@ -1193,11 +1168,12 @@
                              std::move(pid_receiver));
     instance->StartWithService(std::move(service));
   } else {
-    base::FilePath package_path = entry->path();
-    DCHECK(!package_path.empty());
+    base::FilePath service_exe_root;
+    CHECK(base::PathService::Get(base::DIR_ASSETS, &service_exe_root));
     if (!instance->StartWithFilePath(
-            package_path,
-            UtilitySandboxTypeFromString(entry->sandbox_type()))) {
+            service_exe_root.AppendASCII(manifest->service_name +
+                                         kServiceExecutableExtension),
+            UtilitySandboxTypeFromString(manifest->options.sandbox_type))) {
       OnInstanceError(instance);
       params->set_response_data(mojom::ConnectResult::INVALID_ARGUMENT,
                                 base::nullopt);
@@ -1222,11 +1198,10 @@
 bool ServiceManager::QueryCatalog(const std::string& service_name,
                                   const base::Token& instance_group,
                                   std::string* sandbox_type) {
-  const catalog::Entry* entry =
-      catalog_.GetInstanceForGroup(instance_group)->Resolve(service_name);
-  if (!entry)
+  const Manifest* manifest = catalog_.GetManifest(service_name);
+  if (!manifest)
     return false;
-  *sandbox_type = entry->sandbox_type();
+  *sandbox_type = manifest->options.sandbox_type;
   return true;
 }
 
@@ -1319,11 +1294,10 @@
 ServiceManager::Instance* ServiceManager::CreateInstance(
     const Identity& identity,
     InstanceType instance_type,
-    const InterfaceProviderSpecMap& specs,
-    const catalog::ServiceOptions& options) {
+    const Manifest& manifest) {
   DCHECK(identity.IsValid());
 
-  auto instance = std::make_unique<Instance>(this, identity, specs, options);
+  auto instance = std::make_unique<Instance>(this, identity, manifest);
   Instance* raw_instance = instance.get();
 
   instances_.insert(std::make_pair(raw_instance, std::move(instance)));
diff --git a/services/service_manager/service_manager.h b/services/service_manager/service_manager.h
index 793d0570..9d0ea3d 100644
--- a/services/service_manager/service_manager.h
+++ b/services/service_manager/service_manager.h
@@ -14,11 +14,9 @@
 #include "base/process/process.h"
 #include "mojo/public/cpp/bindings/binding_set.h"
 #include "mojo/public/cpp/bindings/interface_ptr_set.h"
-#include "services/catalog/catalog.h"
-#include "services/catalog/service_options.h"
+#include "services/service_manager/catalog.h"
 #include "services/service_manager/connect_params.h"
 #include "services/service_manager/public/cpp/identity.h"
-#include "services/service_manager/public/cpp/interface_provider_spec.h"
 #include "services/service_manager/public/cpp/manifest.h"
 #include "services/service_manager/public/cpp/service.h"
 #include "services/service_manager/public/cpp/service_binding.h"
@@ -31,10 +29,6 @@
 
 namespace service_manager {
 
-// Creates an identity for the singular Service Manager instance which is always
-// present in the system.
-const Identity& GetServiceManagerInstanceIdentity();
-
 class ServiceManager : public Service {
  public:
   // Constructs a new ServiceManager instance which exclusively uses |manifests|
@@ -131,8 +125,7 @@
 
   Instance* CreateInstance(const Identity& identity,
                            InstanceType instance_type,
-                           const InterfaceProviderSpecMap& specs,
-                           const catalog::ServiceOptions& options);
+                           const Manifest& manifest);
 
   // Called from the instance implementing mojom::ServiceManager.
   void AddListener(mojom::ServiceManagerListenerPtr listener);
@@ -160,7 +153,7 @@
   using InstanceMap = std::map<Instance*, std::unique_ptr<Instance>>;
   InstanceMap instances_;
 
-  catalog::Catalog catalog_;
+  Catalog catalog_;
 
   // Maps service identities to reachable instances. Note that the Instance
   // values stored in that map are NOT owned by this map.
diff --git a/services/service_manager/tests/BUILD.gn b/services/service_manager/tests/BUILD.gn
index cfbfe3bd..40e8889 100644
--- a/services/service_manager/tests/BUILD.gn
+++ b/services/service_manager/tests/BUILD.gn
@@ -26,7 +26,6 @@
     "//mojo/core/test:run_all_unittests",
     "//mojo/public/cpp/bindings",
     "//mojo/public/cpp/system",
-    "//services/catalog:lib",
     "//services/service_manager",
     "//services/service_manager/public/cpp",
     "//services/service_manager/public/cpp:unittests",
diff --git a/services/service_manager/tests/DEPS b/services/service_manager/tests/DEPS
index 6d407c4..cef4b41 100644
--- a/services/service_manager/tests/DEPS
+++ b/services/service_manager/tests/DEPS
@@ -1,4 +1,3 @@
 include_rules = [
-  "+services/catalog",
   "+sandbox/win/src",
 ]
diff --git a/storage/browser/BUILD.gn b/storage/browser/BUILD.gn
index a5adcde..d40378c4 100644
--- a/storage/browser/BUILD.gn
+++ b/storage/browser/BUILD.gn
@@ -181,6 +181,8 @@
     "quota/quota_client.h",
     "quota/quota_database.cc",
     "quota/quota_database.h",
+    "quota/quota_disk_info_helper.cc",
+    "quota/quota_disk_info_helper.h",
     "quota/quota_features.cc",
     "quota/quota_features.h",
     "quota/quota_macros.h",
@@ -299,6 +301,7 @@
     "fileapi/transient_file_util_unittest.cc",
     "quota/quota_database_unittest.cc",
     "quota/quota_manager_unittest.cc",
+    "quota/quota_settings_unittest.cc",
     "quota/quota_temporary_storage_evictor_unittest.cc",
     "quota/storage_monitor_unittest.cc",
     "quota/usage_tracker_unittest.cc",
diff --git a/storage/browser/fileapi/copy_or_move_file_validator_unittest.cc b/storage/browser/fileapi/copy_or_move_file_validator_unittest.cc
index 78a17f6a..89671a11 100644
--- a/storage/browser/fileapi/copy_or_move_file_validator_unittest.cc
+++ b/storage/browser/fileapi/copy_or_move_file_validator_unittest.cc
@@ -121,7 +121,7 @@
       EXPECT_TRUE(FileExists(copy_dest_, 10));
     else
       EXPECT_FALSE(FileExists(copy_dest_, 10));
-  };
+  }
 
   void MoveTest(base::File::Error expected) {
     ASSERT_TRUE(FileExists(move_src_, 10));
@@ -138,7 +138,7 @@
       EXPECT_TRUE(FileExists(move_src_, 10));
       EXPECT_FALSE(FileExists(move_dest_, 10));
     }
-  };
+  }
 
  private:
   FileSystemURL SourceURL(const std::string& path) {
diff --git a/storage/browser/fileapi/file_system_operation_context.cc b/storage/browser/fileapi/file_system_operation_context.cc
index 6f03ff45b..3c727d39 100644
--- a/storage/browser/fileapi/file_system_operation_context.cc
+++ b/storage/browser/fileapi/file_system_operation_context.cc
@@ -28,7 +28,7 @@
 
 FileSystemOperationContext::~FileSystemOperationContext() {
   DetachFromSequence();
-  setter_thread_checker_.DetachFromThread();
+  DETACH_FROM_THREAD(setter_thread_checker_);
 }
 
 }  // namespace storage
diff --git a/storage/browser/fileapi/file_system_operation_context.h b/storage/browser/fileapi/file_system_operation_context.h
index a291115..1e4fd76a 100644
--- a/storage/browser/fileapi/file_system_operation_context.h
+++ b/storage/browser/fileapi/file_system_operation_context.h
@@ -63,15 +63,15 @@
   // FileSystemOperationContext is created (i.e. are not supposed be updated
   // after the context's passed onto other task runners).
   void set_change_observers(const ChangeObserverList& list) {
-    DCHECK(setter_thread_checker_.CalledOnValidThread());
+    DCHECK_CALLED_ON_VALID_THREAD(setter_thread_checker_);
     change_observers_ = list;
   }
   void set_update_observers(const UpdateObserverList& list) {
-    DCHECK(setter_thread_checker_.CalledOnValidThread());
+    DCHECK_CALLED_ON_VALID_THREAD(setter_thread_checker_);
     update_observers_ = list;
   }
   void set_quota_limit_type(storage::QuotaLimitType limit_type) {
-    DCHECK(setter_thread_checker_.CalledOnValidThread());
+    DCHECK_CALLED_ON_VALID_THREAD(setter_thread_checker_);
     quota_limit_type_ = limit_type;
   }
 
@@ -90,7 +90,7 @@
   UpdateObserverList update_observers_;
 
   // Used to check its setters are not called on arbitrary thread.
-  base::ThreadChecker setter_thread_checker_;
+  THREAD_CHECKER(setter_thread_checker_);
 
   DISALLOW_COPY_AND_ASSIGN(FileSystemOperationContext);
 };
diff --git a/storage/browser/fileapi/sandbox_file_system_backend_delegate.cc b/storage/browser/fileapi/sandbox_file_system_backend_delegate.cc
index 074d0fe..89afce7 100644
--- a/storage/browser/fileapi/sandbox_file_system_backend_delegate.cc
+++ b/storage/browser/fileapi/sandbox_file_system_backend_delegate.cc
@@ -223,7 +223,7 @@
 }
 
 SandboxFileSystemBackendDelegate::~SandboxFileSystemBackendDelegate() {
-  io_thread_checker_.DetachFromThread();
+  DETACH_FROM_THREAD(io_thread_checker_);
 
   if (!file_task_runner_->RunsTasksInCurrentSequence()) {
     DeleteSoon(file_task_runner_.get(), quota_reservation_manager_.release());
@@ -286,7 +286,7 @@
                      base::BindOnce(std::move(callback), root_url, name),
                      base::Owned(error_ptr)));
 
-  io_thread_checker_.DetachFromThread();
+  DETACH_FROM_THREAD(io_thread_checker_);
   is_filesystem_opened_ = true;
 }
 
@@ -462,7 +462,9 @@
     FileSystemType type,
     FileUpdateObserver* observer,
     base::SequencedTaskRunner* task_runner) {
+#if DCHECK_IS_ON()
   DCHECK(!is_filesystem_opened_ || io_thread_checker_.CalledOnValidThread());
+#endif
   update_observers_[type] =
       update_observers_[type].AddObserver(observer, task_runner);
 }
@@ -471,7 +473,9 @@
     FileSystemType type,
     FileChangeObserver* observer,
     base::SequencedTaskRunner* task_runner) {
+#if DCHECK_IS_ON()
   DCHECK(!is_filesystem_opened_ || io_thread_checker_.CalledOnValidThread());
+#endif
   change_observers_[type] =
       change_observers_[type].AddObserver(observer, task_runner);
 }
@@ -480,7 +484,9 @@
     FileSystemType type,
     FileAccessObserver* observer,
     base::SequencedTaskRunner* task_runner) {
+#if DCHECK_IS_ON()
   DCHECK(!is_filesystem_opened_ || io_thread_checker_.CalledOnValidThread());
+#endif
   access_observers_[type] =
       access_observers_[type].AddObserver(observer, task_runner);
 }
diff --git a/storage/browser/fileapi/sandbox_file_system_backend_delegate.h b/storage/browser/fileapi/sandbox_file_system_backend_delegate.h
index 743e79ad..96ae2a5 100644
--- a/storage/browser/fileapi/sandbox_file_system_backend_delegate.h
+++ b/storage/browser/fileapi/sandbox_file_system_backend_delegate.h
@@ -251,7 +251,7 @@
   FileSystemOptions file_system_options_;
 
   bool is_filesystem_opened_;
-  base::ThreadChecker io_thread_checker_;
+  THREAD_CHECKER(io_thread_checker_);
 
   // Accessed only on the file thread.
   std::set<GURL> visited_origins_;
diff --git a/storage/browser/quota/quota_disk_info_helper.cc b/storage/browser/quota/quota_disk_info_helper.cc
new file mode 100644
index 0000000..0acb2de
--- /dev/null
+++ b/storage/browser/quota/quota_disk_info_helper.cc
@@ -0,0 +1,16 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "storage/browser/quota/quota_disk_info_helper.h"
+
+namespace storage {
+
+QuotaDiskInfoHelper::~QuotaDiskInfoHelper() = default;
+
+int64_t QuotaDiskInfoHelper::AmountOfTotalDiskSpace(
+    const base::FilePath& path) const {
+  return base::SysInfo::AmountOfTotalDiskSpace(path);
+}
+
+}  // namespace storage
diff --git a/storage/browser/quota/quota_disk_info_helper.h b/storage/browser/quota/quota_disk_info_helper.h
new file mode 100644
index 0000000..2009f299
--- /dev/null
+++ b/storage/browser/quota/quota_disk_info_helper.h
@@ -0,0 +1,32 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/component_export.h"
+#include "base/no_destructor.h"
+#include "base/system/sys_info.h"
+
+#ifndef STORAGE_BROWSER_QUOTA_QUOTA_DISK_INFO_HELPER_H_
+#define STORAGE_BROWSER_QUOTA_QUOTA_DISK_INFO_HELPER_H_
+
+namespace storage {
+
+// A thread-safe wrapper class used to get total disk space. The class is
+// subclassed in testing to mock the total disk space, thus allowing us to test
+// experimental behavior in QuotaSettings. It is expected that
+// QuotaDiskInfoHelper is instantiated in calls into QuotaSettings and owned
+// by QuotaSettings.
+class COMPONENT_EXPORT(STORAGE_BROWSER) QuotaDiskInfoHelper {
+ public:
+  QuotaDiskInfoHelper() = default;
+  virtual ~QuotaDiskInfoHelper();
+
+  virtual int64_t AmountOfTotalDiskSpace(const base::FilePath& path) const;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(QuotaDiskInfoHelper);
+};  // class QuotaDiskInfoHelper
+
+}  // namespace storage
+
+#endif  // STORAGE_BROWSER_QUOTA_QUOTA_DISK_INFO_HELPER_H_
diff --git a/storage/browser/quota/quota_settings.cc b/storage/browser/quota/quota_settings.cc
index a63b418a..6c46efe 100644
--- a/storage/browser/quota/quota_settings.cc
+++ b/storage/browser/quota/quota_settings.cc
@@ -5,6 +5,7 @@
 #include "storage/browser/quota/quota_settings.h"
 
 #include <algorithm>
+#include <memory>
 
 #include "base/bind.h"
 #include "base/rand_util.h"
@@ -12,6 +13,7 @@
 #include "base/task/post_task.h"
 #include "base/threading/scoped_blocking_call.h"
 #include "build/build_config.h"
+#include "storage/browser/quota/quota_disk_info_helper.h"
 #include "storage/browser/quota/quota_features.h"
 #include "storage/browser/quota/quota_macros.h"
 
@@ -27,7 +29,8 @@
 
 base::Optional<storage::QuotaSettings> CalculateNominalDynamicSettings(
     const base::FilePath& partition_path,
-    bool is_incognito) {
+    bool is_incognito,
+    QuotaDiskInfoHelper* disk_info_helper) {
   base::ScopedBlockingCall scoped_blocking_call(base::BlockingType::MAY_BLOCK);
   const int64_t kMBytes = 1024 * 1024;
   const int kRandomizedPercentage = 10;
@@ -99,7 +102,7 @@
 
   storage::QuotaSettings settings;
 
-  int64_t total = base::SysInfo::AmountOfTotalDiskSpace(partition_path);
+  int64_t total = disk_info_helper->AmountOfTotalDiskSpace(partition_path);
   if (total == -1) {
     LOG(ERROR) << "Unable to compute QuotaSettings.";
     return base::nullopt;
@@ -127,14 +130,20 @@
 
 void GetNominalDynamicSettings(const base::FilePath& partition_path,
                                bool is_incognito,
+                               QuotaDiskInfoHelper* disk_info_helper,
                                OptionalQuotaSettingsCallback callback) {
   base::PostTaskWithTraitsAndReplyWithResult(
       FROM_HERE,
       {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
        base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
       base::BindOnce(&CalculateNominalDynamicSettings, partition_path,
-                     is_incognito),
+                     is_incognito, base::Unretained(disk_info_helper)),
       std::move(callback));
 }
 
+QuotaDiskInfoHelper* GetDefaultDiskInfoHelper() {
+  static base::NoDestructor<QuotaDiskInfoHelper> singleton;
+  return singleton.get();
+}
+
 }  // namespace storage
diff --git a/storage/browser/quota/quota_settings.h b/storage/browser/quota/quota_settings.h
index aafa93e1..a6844534 100644
--- a/storage/browser/quota/quota_settings.h
+++ b/storage/browser/quota/quota_settings.h
@@ -6,12 +6,14 @@
 #define STORAGE_BROWSER_QUOTA_QUOTA_SETTINGS_H_
 
 #include <stdint.h>
+#include <memory>
 
 #include "base/callback.h"
 #include "base/component_export.h"
 #include "base/files/file_path.h"
 #include "base/optional.h"
 #include "base/time/time.h"
+#include "storage/browser/quota/quota_disk_info_helper.h"
 
 namespace storage {
 
@@ -77,6 +79,7 @@
 COMPONENT_EXPORT(STORAGE_BROWSER)
 void GetNominalDynamicSettings(const base::FilePath& partition_path,
                                bool is_incognito,
+                               QuotaDiskInfoHelper* diskInfoHelper,
                                OptionalQuotaSettingsCallback callback);
 
 // Returns settings with a poolsize of zero and no per host quota.
@@ -91,6 +94,10 @@
                        per_host_quota, per_host_quota);
 }
 
+// Returns object that can fetch actual total disk space; instance lives
+// as long as the process is a live.
+COMPONENT_EXPORT(STORAGE_BROWSER)
+QuotaDiskInfoHelper* GetDefaultDiskInfoHelper();
 }  // namespace storage
 
 #endif  // STORAGE_BROWSER_QUOTA_QUOTA_MANAGER_H_
diff --git a/storage/browser/quota/quota_settings_unittest.cc b/storage/browser/quota/quota_settings_unittest.cc
new file mode 100644
index 0000000..abbfabf
--- /dev/null
+++ b/storage/browser/quota/quota_settings_unittest.cc
@@ -0,0 +1,68 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <memory>
+#include <utility>
+
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/test/bind_test_util.h"
+#include "base/test/scoped_feature_list.h"
+#include "base/test/scoped_task_environment.h"
+#include "storage/browser/quota/quota_disk_info_helper.h"
+#include "storage/browser/quota/quota_features.h"
+#include "storage/browser/quota/quota_settings.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
+using ::testing::_;
+
+namespace storage {
+
+class MockQuotaDiskInfoHelper : public QuotaDiskInfoHelper {
+ public:
+  MockQuotaDiskInfoHelper() = default;
+  MOCK_CONST_METHOD1(AmountOfTotalDiskSpace, int64_t(const base::FilePath&));
+};
+
+class QuotaSettingsTest : public testing::Test {
+ public:
+  QuotaSettingsTest() = default;
+  void SetUp() override { ASSERT_TRUE(data_dir_.CreateUniqueTempDir()); }
+
+ protected:
+  base::test::ScopedFeatureList scoped_feature_list_;
+  base::test::ScopedTaskEnvironment scoped_task_environment_;
+  const base::FilePath& profile_path() const { return data_dir_.GetPath(); }
+
+ private:
+  base::ScopedTempDir data_dir_;
+  QuotaSettings quota_settings_;
+  DISALLOW_COPY_AND_ASSIGN(QuotaSettingsTest);
+};
+
+TEST_F(QuotaSettingsTest, ExpandedTempPool) {
+  MockQuotaDiskInfoHelper disk_info_helper;
+  ON_CALL(disk_info_helper, AmountOfTotalDiskSpace(_))
+      .WillByDefault(::testing::Return(2000));
+  scoped_feature_list_.InitAndEnableFeatureWithParameters(
+      features::kQuotaExpandPoolSize,
+      {{"PoolSizeRatio", "0.75"}, {"PerHostRatio", "0.5"}});
+
+  bool callback_executed = false;
+  GetNominalDynamicSettings(
+      profile_path(), false, &disk_info_helper,
+      base::BindLambdaForTesting([&](base::Optional<QuotaSettings> settings) {
+        callback_executed = true;
+        ASSERT_NE(settings, base::nullopt);
+        // 1500 = 2000 * PoolSizeRatio
+        EXPECT_EQ(settings->pool_size, 1500);
+        // 750 = 1500 * PerHostRatio
+        EXPECT_EQ(settings->per_host_quota, 750);
+      }));
+  scoped_task_environment_.RunUntilIdle();
+  EXPECT_TRUE(callback_executed);
+}
+
+}  // namespace storage
diff --git a/styleguide/c++/blink-c++.md b/styleguide/c++/blink-c++.md
index 4d7f765..406ae2e 100644
--- a/styleguide/c++/blink-c++.md
+++ b/styleguide/c++/blink-c++.md
@@ -66,6 +66,15 @@
   std::unordered_map<int, std::deque<url::Origin>> origins;
 ```
 
+## Do not use `new` and `delete`
+
+Object lifetime should not be managed using raw `new` and `delete`. Prefer to
+allocate objects instead using `std::make_unique`, `base::MakeRefCounted` or
+`blink::MakeGarbageCollected`, depending on the type, and manage their lifetime
+using appropriate smart pointers and handles (`std::unique_ptr`, `scoped_refptr`
+and strong Blink GC references, respectively). See [How Blink Works](https://docs.google.com/document/d/1aitSOucL0VHZa9Z2vbRJSyAIsAz24kX8LFByQ5xQnUg/edit#heading=h.ekwf97my4bgf)
+for more information.
+
 ## Naming
 
 ### Use `CamelCase` for all function names
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json
index 58d7fbca..e50397f 100644
--- a/testing/buildbot/chromium.fyi.json
+++ b/testing/buildbot/chromium.fyi.json
@@ -4040,6 +4040,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "cr_fuchsia_base_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "cronet_tests"
       },
       {
@@ -4085,12 +4091,6 @@
         "test": "media_unittests"
       },
       {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "modular_unittests"
-      },
-      {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.mojo_unittests.filter"
         ],
@@ -4213,6 +4213,17 @@
             }
           ]
         },
+        "test": "cr_fuchsia_base_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "kvm": "1"
+            }
+          ]
+        },
         "test": "cronet_tests"
       },
       {
@@ -4293,17 +4304,6 @@
         "test": "media_unittests"
       },
       {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "kvm": "1"
-            }
-          ]
-        },
-        "test": "modular_unittests"
-      },
-      {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.mojo_unittests.filter"
         ],
@@ -4471,6 +4471,17 @@
             }
           ]
         },
+        "test": "cr_fuchsia_base_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "kvm": "1"
+            }
+          ]
+        },
         "test": "cronet_tests"
       },
       {
@@ -4551,17 +4562,6 @@
         "test": "media_unittests"
       },
       {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "kvm": "1"
-            }
-          ]
-        },
-        "test": "modular_unittests"
-      },
-      {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.mojo_unittests.filter"
         ],
diff --git a/testing/buildbot/chromium.linux.json b/testing/buildbot/chromium.linux.json
index a37f609..1d2b56f 100644
--- a/testing/buildbot/chromium.linux.json
+++ b/testing/buildbot/chromium.linux.json
@@ -720,6 +720,20 @@
             }
           ]
         },
+        "test": "cr_fuchsia_base_unittests"
+      },
+      {
+        "args": [
+          "--qemu-require-kvm"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "kvm": "1"
+            }
+          ]
+        },
         "test": "cronet_tests"
       },
       {
@@ -822,20 +836,6 @@
       },
       {
         "args": [
-          "--qemu-require-kvm"
-        ],
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "kvm": "1"
-            }
-          ]
-        },
-        "test": "modular_unittests"
-      },
-      {
-        "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.mojo_unittests.filter",
           "--qemu-require-kvm"
         ],
diff --git a/testing/buildbot/gn_isolate_map.pyl b/testing/buildbot/gn_isolate_map.pyl
index f21239c..7efc4828 100644
--- a/testing/buildbot/gn_isolate_map.pyl
+++ b/testing/buildbot/gn_isolate_map.pyl
@@ -740,6 +740,10 @@
     "label": "//courgette:courgette_unittests",
     "type": "console_test_launcher",
   },
+  "cr_fuchsia_base_unittests": {
+    "label": "//fuchsia/base:cr_fuchsia_base_unittests",
+    "type": "console_test_launcher",
+  },
   "crashpad_tests": {
     "label": "//third_party/crashpad/crashpad:crashpad_tests",
     "type": "console_test_launcher",
@@ -1560,10 +1564,6 @@
     "label": "//third_party/minizip:minizip_uncompress_fuzzer",
     "type": "fuzzer",
   },
-  "modular_unittests": {
-    "label": "//fuchsia/modular:modular_unittests",
-    "type": "console_test_launcher",
-  },
   "mojo_core_channel_fuzzer": {
     "label": "//mojo/core:mojo_core_channel_fuzzer",
     "type": "fuzzer",
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl
index a0a669c..5f1f576c 100644
--- a/testing/buildbot/test_suites.pyl
+++ b/testing/buildbot/test_suites.pyl
@@ -2749,6 +2749,7 @@
           '--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.content_unittests.filter',
         ],
       },
+      'cr_fuchsia_base_unittests': {},
       'cronet_tests': {},
       'cronet_unittests': {},
       'crypto_unittests': {},
@@ -2757,7 +2758,6 @@
       'http_service_tests': {},
       'ipc_tests': {},
       'media_unittests': {},
-      'modular_unittests': {},
       'mojo_unittests': {
         'args': [
           '--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.mojo_unittests.filter',
diff --git a/third_party/blink/public/BUILD.gn b/third_party/blink/public/BUILD.gn
index 4f1bc3ef..5ab4af8 100644
--- a/third_party/blink/public/BUILD.gn
+++ b/third_party/blink/public/BUILD.gn
@@ -229,6 +229,8 @@
     "platform/web_data.h",
     "platform/web_data_consumer_handle.h",
     "platform/web_database_observer.h",
+    "platform/web_dedicated_worker.h",
+    "platform/web_dedicated_worker_host_factory_client.h",
     "platform/web_distillability.h",
     "platform/web_document_subresource_filter.h",
     "platform/web_double_point.h",
diff --git a/third_party/blink/public/platform/platform.h b/third_party/blink/public/platform/platform.h
index f7ede715..e1429ed 100644
--- a/third_party/blink/public/platform/platform.h
+++ b/third_party/blink/public/platform/platform.h
@@ -55,6 +55,7 @@
 #include "third_party/blink/public/platform/web_common.h"
 #include "third_party/blink/public/platform/web_data.h"
 #include "third_party/blink/public/platform/web_data_consumer_handle.h"
+#include "third_party/blink/public/platform/web_dedicated_worker_host_factory_client.h"
 #include "third_party/blink/public/platform/web_gesture_device.h"
 #include "third_party/blink/public/platform/web_localized_string.h"
 #include "third_party/blink/public/platform/web_rtc_api_name.h"
@@ -109,6 +110,7 @@
 class WebCookieJar;
 class WebCrypto;
 class WebDatabaseObserver;
+class WebDedicatedWorker;
 class WebGraphicsContext3DProvider;
 class WebImageCaptureFrameGrabber;
 class WebLocalFrame;
@@ -669,6 +671,11 @@
 
   // WebWorker ----------------------------------------------------------
 
+  virtual std::unique_ptr<WebDedicatedWorkerHostFactoryClient>
+  CreateDedicatedWorkerHostFactoryClient(WebDedicatedWorker*,
+                                         service_manager::InterfaceProvider*) {
+    return nullptr;
+  }
   virtual void DidStartWorkerThread() {}
   virtual void WillStopWorkerThread() {}
   virtual void WorkerContextCreated(const v8::Local<v8::Context>& worker) {}
diff --git a/third_party/blink/public/platform/web_dedicated_worker.h b/third_party/blink/public/platform/web_dedicated_worker.h
new file mode 100644
index 0000000..91f32d91
--- /dev/null
+++ b/third_party/blink/public/platform/web_dedicated_worker.h
@@ -0,0 +1,35 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_PUBLIC_PLATFORM_WEB_DEDICATED_WORKER_H_
+#define THIRD_PARTY_BLINK_PUBLIC_PLATFORM_WEB_DEDICATED_WORKER_H_
+
+#include "mojo/public/cpp/system/message_pipe.h"
+
+namespace blink {
+
+// PlzDedicatedWorker:
+// WebDedicatedWorker is the interface to access blink::DedicatedWorker from
+// content::DedicatedWorkerHostFactoryClient.
+class WebDedicatedWorker {
+ public:
+  virtual ~WebDedicatedWorker() = default;
+
+  // Called when content::DedicatedWorkerHost is created in the browser process.
+  virtual void OnWorkerHostCreated(
+      mojo::ScopedMessagePipeHandle interface_provider) = 0;
+
+  // Called when content::DedicatedWorkerHost loaded the main worker script in
+  // the browser process, and the script information is sent back to the
+  // content::DedicatedWorkerHostFactoryClient.
+  virtual void OnScriptLoaded() = 0;
+
+  // Called when content::DedicatedWorkerHost failed to load the main worker
+  // script in the browser process.
+  virtual void OnScriptLoadFailed() = 0;
+};
+
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_PUBLIC_PLATFORM_WEB_DEDICATED_WORKER_H_
diff --git a/third_party/blink/public/platform/web_dedicated_worker_host_factory_client.h b/third_party/blink/public/platform/web_dedicated_worker_host_factory_client.h
new file mode 100644
index 0000000..a296155
--- /dev/null
+++ b/third_party/blink/public/platform/web_dedicated_worker_host_factory_client.h
@@ -0,0 +1,30 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_PUBLIC_PLATFORM_WEB_DEDICATED_WORKER_HOST_FACTORY_CLIENT_H_
+#define THIRD_PARTY_BLINK_PUBLIC_PLATFORM_WEB_DEDICATED_WORKER_HOST_FACTORY_CLIENT_H_
+
+#include "mojo/public/cpp/system/message_pipe.h"
+#include "third_party/blink/public/platform/web_security_origin.h"
+#include "third_party/blink/public/platform/web_url.h"
+
+namespace blink {
+
+// PlzDedicatedWorker:
+// WebDedicatedWorkerHostFactoryClient is the interface to access
+// content::DedicatedWorkerHostFactoryClient from blink::DedicatedWorker.
+class WebDedicatedWorkerHostFactoryClient {
+ public:
+  virtual ~WebDedicatedWorkerHostFactoryClient() = default;
+
+  // Requests the creation of DedicatedWorkerHost in the browser process.
+  virtual void CreateWorkerHost(
+      const blink::WebURL& script_url,
+      const blink::WebSecurityOrigin& script_origin,
+      mojo::ScopedMessagePipeHandle blob_url_token) = 0;
+};
+
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_PUBLIC_PLATFORM_WEB_DEDICATED_WORKER_HOST_FACTORY_CLIENT_H_
diff --git a/third_party/blink/renderer/bindings/core/v8/script_streamer.cc b/third_party/blink/renderer/bindings/core/v8/script_streamer.cc
index 4e0c584..3c7f49e 100644
--- a/third_party/blink/renderer/bindings/core/v8/script_streamer.cc
+++ b/third_party/blink/renderer/bindings/core/v8/script_streamer.cc
@@ -78,7 +78,8 @@
   }
 
  private:
-  bool TryGetData(const uint8_t** data, size_t* length) {
+  bool TryGetData(const uint8_t** data, size_t* length)
+      EXCLUSIVE_LOCKS_REQUIRED(mutex_) {
     mutex_.AssertAcquired();
     if (!data_.IsEmpty()) {
       std::pair<const uint8_t*, size_t> next_data = data_.TakeFirst();
@@ -93,17 +94,17 @@
     return false;
   }
 
-  void DiscardQueuedData() {
+  void DiscardQueuedData() EXCLUSIVE_LOCKS_REQUIRED(mutex_) {
     while (!data_.IsEmpty()) {
       std::pair<const uint8_t*, size_t> next_data = data_.TakeFirst();
       delete[] next_data.first;
     }
   }
 
-  Deque<std::pair<const uint8_t*, size_t>> data_;
-  bool finished_;
+  Deque<std::pair<const uint8_t*, size_t>> data_ GUARDED_BY(mutex_);
+  bool finished_ GUARDED_BY(mutex_);
   Mutex mutex_;
-  ThreadCondition have_data_;
+  ThreadCondition have_data_ GUARDED_BY(mutex_);
 };
 
 // SourceStream implements the streaming interface towards V8. The main
@@ -117,9 +118,12 @@
   SourceStream()
       : v8::ScriptCompiler::ExternalSourceStream(),
         cancelled_(false),
+#if DCHECK_IS_ON()
         finished_(false),
+#endif  // DCHECK_IS_ON()
         queue_lead_position_(0),
-        queue_tail_position_(0) {}
+        queue_tail_position_(0) {
+  }
 
   ~SourceStream() override = default;
 
@@ -146,7 +150,9 @@
 
   void DidFinishLoading() {
     DCHECK(IsMainThread());
+#if DCHECK_IS_ON()
     finished_ = true;
+#endif  // DCHECK_IS_ON()
     data_queue_.Finish();
   }
 
@@ -174,7 +180,12 @@
                                ScriptStreamer* streamer) {
     DCHECK(IsMainThread());
 
-    if (cancelled_) {
+    bool was_canceled;
+    {
+      MutexLocker locker(mutex_);
+      was_canceled = cancelled_;
+    }
+    if (was_canceled) {
       data_queue_.Finish();
       return;
     }
@@ -205,7 +216,10 @@
     DCHECK(IsMainThread());
     MutexLocker locker(mutex_);
 
+#if DCHECK_IS_ON()
     DCHECK(!finished_);
+#endif  // DCHECK_IS_ON()
+
     if (cancelled_) {
       data_queue_.Finish();
       return;
@@ -228,14 +242,15 @@
   }
 
   // For coordinating between the main thread and background thread tasks.
-  // Guards m_cancelled and m_queueTailPosition.
   Mutex mutex_;
 
-  // The shared buffer containing the resource data + state variables.
-  // Used by both threads, guarded by m_mutex.
-  bool cancelled_;
-  bool finished_;
+  bool cancelled_ GUARDED_BY(mutex_);  // Used by both threads.
 
+#if DCHECK_IS_ON()
+  bool finished_;  // Only used by the main thread.
+#endif             // DCHECK_IS_ON()
+
+  // The shared buffer containing the resource data + state variables.
   scoped_refptr<const SharedBuffer>
       resource_buffer_;  // Only used by the main thread.
 
@@ -245,7 +260,7 @@
   //   bookmarkPosition: position of the bookmark.
   SourceStreamDataQueue data_queue_;  // Thread safe.
   size_t queue_lead_position_;        // Only used by v8 thread.
-  size_t queue_tail_position_;  // Used by both threads; guarded by m_mutex.
+  size_t queue_tail_position_ GUARDED_BY(mutex_);  // Used by both threads.
 };
 
 size_t ScriptStreamer::small_script_threshold_ = 30 * 1024;
@@ -412,7 +427,7 @@
     DCHECK(!stream_);
     DCHECK(!source_);
     stream_ = new SourceStream;
-    // m_source takes ownership of m_stream.
+    // |source_| takes ownership of |stream_|.
     source_ = std::make_unique<v8::ScriptCompiler::StreamedSource>(stream_,
                                                                    encoding_);
 
diff --git a/third_party/blink/renderer/bindings/core/v8/script_streamer_thread.h b/third_party/blink/renderer/bindings/core/v8/script_streamer_thread.h
index 913aeae..664df34e 100644
--- a/third_party/blink/renderer/bindings/core/v8/script_streamer_thread.h
+++ b/third_party/blink/renderer/bindings/core/v8/script_streamer_thread.h
@@ -49,8 +49,8 @@
   // At the moment, we only use one thread, so we can only stream one script
   // at a time. FIXME: Use a thread pool and stream multiple scripts.
   std::unique_ptr<Thread> thread_;
-  bool running_task_;
-  mutable Mutex mutex_;  // Guards m_runningTask.
+  bool running_task_ GUARDED_BY(mutex_);
+  mutable Mutex mutex_;
 
   DISALLOW_COPY_AND_ASSIGN(ScriptStreamerThread);
 };
diff --git a/third_party/blink/renderer/core/BUILD.gn b/third_party/blink/renderer/core/BUILD.gn
index 97cba9c..ade018d 100644
--- a/third_party/blink/renderer/core/BUILD.gn
+++ b/third_party/blink/renderer/core/BUILD.gn
@@ -1871,6 +1871,7 @@
     "fetch/fetch_response_data_test.cc",
     "fetch/form_data_bytes_consumer_test.cc",
     "fetch/multipart_parser_test.cc",
+    "fetch/place_holder_bytes_consumer_test.cc",
     "fetch/readable_stream_bytes_consumer_test.cc",
     "fetch/request_test.cc",
     "fetch/response_test.cc",
diff --git a/third_party/blink/renderer/core/css/selector_query_test.cc b/third_party/blink/renderer/core/css/selector_query_test.cc
index 8168aeb..b30d942 100644
--- a/third_party/blink/renderer/core/css/selector_query_test.cc
+++ b/third_party/blink/renderer/core/css/selector_query_test.cc
@@ -248,7 +248,7 @@
   ShadowRoot& shadowRoot =
       scope->AttachShadowRootInternal(ShadowRootType::kOpen);
   // Make the inside the shadow root be identical to that of the outer document.
-  shadowRoot.appendChild(document->documentElement()->CloneWithChildren());
+  shadowRoot.appendChild(&document->documentElement()->CloneWithChildren());
   static const struct QueryTest kTestCases[] = {
       // Id in the right most selector.
       {"#first", false, 0, {0, 0, 0, 0, 0, 0, 0}},
diff --git a/third_party/blink/renderer/core/dom/element.cc b/third_party/blink/renderer/core/dom/element.cc
index ab356c7..bfdecf2 100644
--- a/third_party/blink/renderer/core/dom/element.cc
+++ b/third_party/blink/renderer/core/dom/element.cc
@@ -293,38 +293,38 @@
 }
 
 Node* Element::Clone(Document& factory, CloneChildrenFlag flag) const {
-  return flag == CloneChildrenFlag::kClone ? CloneWithChildren(&factory)
-                                           : CloneWithoutChildren(&factory);
+  return flag == CloneChildrenFlag::kClone ? &CloneWithChildren(&factory)
+                                           : &CloneWithoutChildren(&factory);
 }
 
-Element* Element::CloneWithChildren(Document* nullable_factory) const {
-  Element* clone = CloneWithoutAttributesAndChildren(
+Element& Element::CloneWithChildren(Document* nullable_factory) const {
+  Element& clone = CloneWithoutAttributesAndChildren(
       nullable_factory ? *nullable_factory : GetDocument());
   // This will catch HTML elements in the wrong namespace that are not correctly
   // copied.  This is a sanity check as HTML overloads some of the DOM methods.
-  DCHECK_EQ(IsHTMLElement(), clone->IsHTMLElement());
+  DCHECK_EQ(IsHTMLElement(), clone.IsHTMLElement());
 
-  clone->CloneAttributesFrom(*this);
-  clone->CloneNonAttributePropertiesFrom(*this, CloneChildrenFlag::kClone);
-  clone->CloneChildNodesFrom(*this);
+  clone.CloneAttributesFrom(*this);
+  clone.CloneNonAttributePropertiesFrom(*this, CloneChildrenFlag::kClone);
+  clone.CloneChildNodesFrom(*this);
   return clone;
 }
 
-Element* Element::CloneWithoutChildren(Document* nullable_factory) const {
-  Element* clone = CloneWithoutAttributesAndChildren(
+Element& Element::CloneWithoutChildren(Document* nullable_factory) const {
+  Element& clone = CloneWithoutAttributesAndChildren(
       nullable_factory ? *nullable_factory : GetDocument());
   // This will catch HTML elements in the wrong namespace that are not correctly
   // copied.  This is a sanity check as HTML overloads some of the DOM methods.
-  DCHECK_EQ(IsHTMLElement(), clone->IsHTMLElement());
+  DCHECK_EQ(IsHTMLElement(), clone.IsHTMLElement());
 
-  clone->CloneAttributesFrom(*this);
-  clone->CloneNonAttributePropertiesFrom(*this, CloneChildrenFlag::kSkip);
+  clone.CloneAttributesFrom(*this);
+  clone.CloneNonAttributePropertiesFrom(*this, CloneChildrenFlag::kSkip);
   return clone;
 }
 
-Element* Element::CloneWithoutAttributesAndChildren(Document& factory) const {
-  return factory.CreateElement(TagQName(), CreateElementFlags::ByCloneNode(),
-                               IsValue());
+Element& Element::CloneWithoutAttributesAndChildren(Document& factory) const {
+  return *factory.CreateElement(TagQName(), CreateElementFlags::ByCloneNode(),
+                                IsValue());
 }
 
 Attr* Element::DetachAttribute(wtf_size_t index) {
diff --git a/third_party/blink/renderer/core/dom/element.h b/third_party/blink/renderer/core/dom/element.h
index 7f0cd85..019ab18e 100644
--- a/third_party/blink/renderer/core/dom/element.h
+++ b/third_party/blink/renderer/core/dom/element.h
@@ -402,8 +402,8 @@
 
   String nodeName() const override;
 
-  Element* CloneWithChildren(Document* = nullptr) const;
-  Element* CloneWithoutChildren(Document* = nullptr) const;
+  Element& CloneWithChildren(Document* = nullptr) const;
+  Element& CloneWithoutChildren(Document* = nullptr) const;
 
   void SetBooleanAttribute(const QualifiedName&, bool);
 
@@ -1072,7 +1072,7 @@
   // Clone is private so that non-virtual CloneElementWithChildren and
   // CloneElementWithoutChildren are used instead.
   Node* Clone(Document&, CloneChildrenFlag) const override;
-  virtual Element* CloneWithoutAttributesAndChildren(Document& factory) const;
+  virtual Element& CloneWithoutAttributesAndChildren(Document& factory) const;
 
   QualifiedName tag_name_;
 
diff --git a/third_party/blink/renderer/core/editing/commands/apply_style_command.cc b/third_party/blink/renderer/core/editing/commands/apply_style_command.cc
index 7e43b6f..a0a464f6 100644
--- a/third_party/blink/renderer/core/editing/commands/apply_style_command.cc
+++ b/third_party/blink/renderer/core/editing/commands/apply_style_command.cc
@@ -1388,14 +1388,14 @@
         continue;
       if (!child->contains(target_node) && elements_to_push_down.size()) {
         for (const auto& element : elements_to_push_down) {
-          Element* wrapper = element->CloneWithoutChildren();
-          wrapper->removeAttribute(kStyleAttr);
+          Element& wrapper = element->CloneWithoutChildren();
+          wrapper.removeAttribute(kStyleAttr);
           // Delete id attribute from the second element because the same id
           // cannot be used for more than one element
           element->removeAttribute(html_names::kIdAttr);
           if (IsHTMLAnchorElement(element))
             element->removeAttribute(html_names::kNameAttr);
-          SurroundNodeRangeWithElement(child, child, wrapper, editing_state);
+          SurroundNodeRangeWithElement(child, child, &wrapper, editing_state);
           if (editing_state->IsAborted())
             return;
         }
@@ -2010,9 +2010,9 @@
   }
 
   if (styled_inline_element_ && add_styled_element == kAddStyledElement) {
-    SurroundNodeRangeWithElement(start_node, end_node,
-                                 styled_inline_element_->CloneWithoutChildren(),
-                                 editing_state);
+    SurroundNodeRangeWithElement(
+        start_node, end_node, &styled_inline_element_->CloneWithoutChildren(),
+        editing_state);
   }
 }
 
diff --git a/third_party/blink/renderer/core/editing/commands/break_blockquote_command.cc b/third_party/blink/renderer/core/editing/commands/break_blockquote_command.cc
index 7a477b5..ae91516 100644
--- a/third_party/blink/renderer/core/editing/commands/break_blockquote_command.cc
+++ b/third_party/blink/renderer/core/editing/commands/break_blockquote_command.cc
@@ -217,8 +217,8 @@
     ancestors.push_back(node);
 
   // Insert a clone of the top blockquote after the break.
-  Element* cloned_blockquote = top_blockquote->CloneWithoutChildren();
-  InsertNodeAfter(cloned_blockquote, break_element, editing_state);
+  Element& cloned_blockquote = top_blockquote->CloneWithoutChildren();
+  InsertNodeAfter(&cloned_blockquote, break_element, editing_state);
   if (editing_state->IsAborted())
     return;
 
@@ -226,11 +226,11 @@
   // On exiting this loop, clonedAncestor is the lowest ancestor
   // that was cloned (i.e. the clone of either ancestors.last()
   // or clonedBlockquote if ancestors is empty).
-  Element* cloned_ancestor = cloned_blockquote;
+  Element* cloned_ancestor = &cloned_blockquote;
   for (wtf_size_t i = ancestors.size(); i != 0; --i) {
-    Element* cloned_child = ancestors[i - 1]->CloneWithoutChildren();
+    Element& cloned_child = ancestors[i - 1]->CloneWithoutChildren();
     // Preserve list item numbering in cloned lists.
-    if (IsHTMLOListElement(*cloned_child)) {
+    if (IsHTMLOListElement(cloned_child)) {
       Node* list_child_node = i > 1 ? ancestors[i - 2].Get() : start_node;
       // The first child of the cloned list might not be a list item element,
       // find the first one so that we know where to start numbering.
@@ -238,15 +238,15 @@
         list_child_node = list_child_node->nextSibling();
       if (IsListItem(list_child_node))
         SetNodeAttribute(
-            cloned_child, kStartAttr,
+            &cloned_child, kStartAttr,
             AtomicString::Number(
                 ToLayoutListItem(list_child_node->GetLayoutObject())->Value()));
     }
 
-    AppendNode(cloned_child, cloned_ancestor, editing_state);
+    AppendNode(&cloned_child, cloned_ancestor, editing_state);
     if (editing_state->IsAborted())
       return;
-    cloned_ancestor = cloned_child;
+    cloned_ancestor = &cloned_child;
   }
 
   MoveRemainingSiblingsToNewParent(start_node, nullptr, cloned_ancestor,
@@ -282,7 +282,7 @@
   }
 
   // Make sure the cloned block quote renders.
-  AddBlockPlaceholderIfNeeded(cloned_blockquote, editing_state);
+  AddBlockPlaceholderIfNeeded(&cloned_blockquote, editing_state);
   if (editing_state->IsAborted())
     return;
 
diff --git a/third_party/blink/renderer/core/editing/commands/insert_paragraph_separator_command.cc b/third_party/blink/renderer/core/editing/commands/insert_paragraph_separator_command.cc
index bfc599a3..043af880 100644
--- a/third_party/blink/renderer/core/editing/commands/insert_paragraph_separator_command.cc
+++ b/third_party/blink/renderer/core/editing/commands/insert_paragraph_separator_command.cc
@@ -167,14 +167,14 @@
   // Make clones of ancestors in between the start node and the start block.
   Element* parent = block_to_insert;
   for (wtf_size_t i = ancestors.size(); i != 0; --i) {
-    Element* child = ancestors[i - 1]->CloneWithoutChildren();
+    Element& child = ancestors[i - 1]->CloneWithoutChildren();
     // It should always be okay to remove id from the cloned elements, since the
     // originals are not deleted.
-    child->removeAttribute(kIdAttr);
-    AppendNode(child, parent, editing_state);
+    child.removeAttribute(kIdAttr);
+    AppendNode(&child, parent, editing_state);
     if (editing_state->IsAborted())
       return nullptr;
-    parent = child;
+    parent = &child;
   }
 
   return parent;
@@ -274,7 +274,7 @@
   } else if (ShouldUseDefaultParagraphElement(start_block)) {
     block_to_insert = CreateDefaultParagraphElement(GetDocument());
   } else {
-    block_to_insert = start_block->CloneWithoutChildren();
+    block_to_insert = &start_block->CloneWithoutChildren();
   }
 
   VisiblePosition visible_pos =
@@ -314,11 +314,11 @@
       }
 
       if (list_child && list_child != start_block) {
-        Element* list_child_to_insert = list_child->CloneWithoutChildren();
-        AppendNode(block_to_insert, list_child_to_insert, editing_state);
+        Element& list_child_to_insert = list_child->CloneWithoutChildren();
+        AppendNode(block_to_insert, &list_child_to_insert, editing_state);
         if (editing_state->IsAborted())
           return;
-        InsertNodeAfter(list_child_to_insert, list_child, editing_state);
+        InsertNodeAfter(&list_child_to_insert, list_child, editing_state);
       } else {
         // Most of the time we want to stay at the nesting level of the
         // startBlock (e.g., when nesting within lists). However, for div nodes,
@@ -365,11 +365,11 @@
 
     if (is_first_in_block && !nest_new_block) {
       if (list_child && list_child != start_block) {
-        Element* list_child_to_insert = list_child->CloneWithoutChildren();
-        AppendNode(block_to_insert, list_child_to_insert, editing_state);
+        Element& list_child_to_insert = list_child->CloneWithoutChildren();
+        AppendNode(block_to_insert, &list_child_to_insert, editing_state);
         if (editing_state->IsAborted())
           return;
-        InsertNodeBefore(list_child_to_insert, list_child, editing_state);
+        InsertNodeBefore(&list_child_to_insert, list_child, editing_state);
         if (editing_state->IsAborted())
           return;
       } else {
@@ -523,11 +523,11 @@
   if (nest_new_block) {
     AppendNode(block_to_insert, start_block, editing_state);
   } else if (list_child && list_child != start_block) {
-    Element* list_child_to_insert = list_child->CloneWithoutChildren();
-    AppendNode(block_to_insert, list_child_to_insert, editing_state);
+    Element& list_child_to_insert = list_child->CloneWithoutChildren();
+    AppendNode(block_to_insert, &list_child_to_insert, editing_state);
     if (editing_state->IsAborted())
       return;
-    InsertNodeAfter(list_child_to_insert, list_child, editing_state);
+    InsertNodeAfter(&list_child_to_insert, list_child, editing_state);
   } else {
     InsertNodeAfter(block_to_insert, start_block, editing_state);
   }
diff --git a/third_party/blink/renderer/core/editing/serializers/markup_accumulator.cc b/third_party/blink/renderer/core/editing/serializers/markup_accumulator.cc
index 5af2778d..ce26438c 100644
--- a/third_party/blink/renderer/core/editing/serializers/markup_accumulator.cc
+++ b/third_party/blink/renderer/core/editing/serializers/markup_accumulator.cc
@@ -93,6 +93,7 @@
 
 void MarkupAccumulator::AppendElement(const Element& element) {
   // https://html.spec.whatwg.org/multipage/parsing.html#html-fragment-serialisation-algorithm
+  RecordNamespaceInformation(element);
   AppendStartTagOpen(element);
 
   AttributeCollection attributes = element.Attributes();
@@ -161,9 +162,6 @@
   if (attribute_namespace == xmlns_names::kNamespaceURI) {
     if (!attribute.Prefix() && attribute.LocalName() != g_xmlns_atom)
       candidate_prefix = g_xmlns_atom;
-    // Account for the namespace attribute we're about to append.
-    AddPrefix(attribute.Prefix() ? attribute.LocalName() : g_empty_atom,
-              attribute.Value());
   } else if (attribute_namespace == xml_names::kNamespaceURI) {
     // TODO(tkent): Remove this block when we implement 'retrieving a
     // preferred prefix string'.
@@ -179,8 +177,8 @@
 
     // 3.5.3. Otherwise, the attribute namespace in not the XMLNS namespace.
     // Run these steps:
-    if (ShouldAddNamespaceAttribute(attribute, element)) {
-      if (!candidate_prefix) {
+    if (ShouldAddNamespaceAttribute(attribute, candidate_prefix)) {
+      if (!candidate_prefix || LookupNamespaceURI(candidate_prefix)) {
         // 3.5.3.1. Let candidate prefix be the result of generating a prefix
         // providing map, attribute namespace, and prefix index as input.
         candidate_prefix = GeneratePrefix(attribute_namespace);
@@ -198,8 +196,9 @@
                                    attribute.LocalName(), value, false);
 }
 
-bool MarkupAccumulator::ShouldAddNamespaceAttribute(const Attribute& attribute,
-                                                    const Element& element) {
+bool MarkupAccumulator::ShouldAddNamespaceAttribute(
+    const Attribute& attribute,
+    const AtomicString& candidate_prefix) {
   // xmlns and xmlns:prefix attributes should be handled by another branch in
   // AppendAttributeAsXMLWithNamespace().
   DCHECK_NE(attribute.NamespaceURI(), xmlns_names::kNamespaceURI);
@@ -210,10 +209,11 @@
 
   // Attributes without a prefix will need one generated for them, and an xmlns
   // attribute for that prefix.
-  if (!attribute.Prefix())
+  if (!candidate_prefix)
     return true;
 
-  return !element.hasAttribute(WTF::g_xmlns_with_colon + attribute.Prefix());
+  return !EqualIgnoringNullity(LookupNamespaceURI(candidate_prefix),
+                               attribute.NamespaceURI());
 }
 
 void MarkupAccumulator::AppendNamespace(const AtomicString& prefix,
@@ -252,6 +252,16 @@
   namespace_stack_.pop_back();
 }
 
+// https://w3c.github.io/DOM-Parsing/#dfn-recording-the-namespace-information
+void MarkupAccumulator::RecordNamespaceInformation(const Element& element) {
+  if (SerializeAsHTMLDocument(element))
+    return;
+  for (const auto& attr : element.Attributes()) {
+    if (attr.NamespaceURI() == xmlns_names::kNamespaceURI)
+      AddPrefix(attr.Prefix() ? attr.LocalName() : g_empty_atom, attr.Value());
+  }
+}
+
 // https://w3c.github.io/DOM-Parsing/#dfn-add
 void MarkupAccumulator::AddPrefix(const AtomicString& prefix,
                                   const AtomicString& namespace_uri) {
@@ -335,20 +345,20 @@
     // Traverses other DOM tree, i.e., shadow tree.
     std::pair<Node*, Element*> auxiliary_pair =
         GetAuxiliaryDOMTree(target_element);
-    Node* auxiliary_tree = auxiliary_pair.first;
-    Element* enclosing_element = auxiliary_pair.second;
-    if (auxiliary_tree) {
-      if (auxiliary_pair.second)
+    if (Node* auxiliary_tree = auxiliary_pair.first) {
+      Element* enclosing_element = auxiliary_pair.second;
+      if (enclosing_element)
         AppendElement(*enclosing_element);
       for (const Node& child : Strategy::ChildrenOf(*auxiliary_tree))
         SerializeNodesWithNamespaces<Strategy>(child, kIncludeNode);
       if (enclosing_element)
         AppendEndTag(*enclosing_element);
     }
+
+    if (!children_only)
+      AppendEndTag(target_element);
   }
 
-  if (!children_only && has_end_tag)
-    AppendEndTag(target_element);
   PopNamespaces(target_element);
 }
 
diff --git a/third_party/blink/renderer/core/editing/serializers/markup_accumulator.h b/third_party/blink/renderer/core/editing/serializers/markup_accumulator.h
index e78fc05..2e1f2c3 100644
--- a/third_party/blink/renderer/core/editing/serializers/markup_accumulator.h
+++ b/third_party/blink/renderer/core/editing/serializers/markup_accumulator.h
@@ -77,8 +77,8 @@
   void AppendAttributeAsXMLWithNamespace(const Element& element,
                                          const Attribute& attribute,
                                          const String& value);
-  static bool ShouldAddNamespaceAttribute(const Attribute& attribute,
-                                          const Element& element);
+  bool ShouldAddNamespaceAttribute(const Attribute& attribute,
+                                   const AtomicString& candidate_prefix);
 
   void AppendEndTag(const Element&);
 
@@ -86,6 +86,7 @@
 
   void PushNamespaces(const Element& element);
   void PopNamespaces(const Element& element);
+  void RecordNamespaceInformation(const Element& element);
   void AddPrefix(const AtomicString& prefix, const AtomicString& namespace_uri);
   AtomicString LookupNamespaceURI(const AtomicString& prefix);
   AtomicString GeneratePrefix(const AtomicString& new_namespace);
diff --git a/third_party/blink/renderer/core/editing/serializers/serialization.cc b/third_party/blink/renderer/core/editing/serializers/serialization.cc
index b6f10c6..bd2a502 100644
--- a/third_party/blink/renderer/core/editing/serializers/serialization.cc
+++ b/third_party/blink/renderer/core/editing/serializers/serialization.cc
@@ -583,7 +583,7 @@
       element->setAttribute(kClassAttr, AppleInterchangeNewline);
     } else {
       if (use_clones_of_enclosing_block)
-        element = block->CloneWithoutChildren();
+        element = &block->CloneWithoutChildren();
       else
         element = CreateDefaultParagraphElement(document);
       FillContainerFromString(element, s);
diff --git a/third_party/blink/renderer/core/fetch/BUILD.gn b/third_party/blink/renderer/core/fetch/BUILD.gn
index aa9a18b..c1716b27 100644
--- a/third_party/blink/renderer/core/fetch/BUILD.gn
+++ b/third_party/blink/renderer/core/fetch/BUILD.gn
@@ -32,6 +32,8 @@
     "headers.h",
     "multipart_parser.cc",
     "multipart_parser.h",
+    "place_holder_bytes_consumer.cc",
+    "place_holder_bytes_consumer.h",
     "readable_stream_bytes_consumer.cc",
     "readable_stream_bytes_consumer.h",
     "request.cc",
diff --git a/third_party/blink/renderer/core/fetch/fetch_manager.cc b/third_party/blink/renderer/core/fetch/fetch_manager.cc
index 1ea5c5c..06bf76a 100644
--- a/third_party/blink/renderer/core/fetch/fetch_manager.cc
+++ b/third_party/blink/renderer/core/fetch/fetch_manager.cc
@@ -16,6 +16,7 @@
 #include "third_party/blink/renderer/core/fetch/body_stream_buffer.h"
 #include "third_party/blink/renderer/core/fetch/fetch_request_data.h"
 #include "third_party/blink/renderer/core/fetch/form_data_bytes_consumer.h"
+#include "third_party/blink/renderer/core/fetch/place_holder_bytes_consumer.h"
 #include "third_party/blink/renderer/core/fetch/response.h"
 #include "third_party/blink/renderer/core/fetch/response_init.h"
 #include "third_party/blink/renderer/core/fileapi/blob.h"
@@ -72,94 +73,6 @@
   return !value.IsEmpty();
 }
 
-// A BytesConsumer implementation that acts as a place holder. The actual
-// BytesConsumer can be provided later by calling "Update()".
-class PlaceHolderBytesConsumer final : public BytesConsumer {
- public:
-  // BytesConsumer implementation
-  Result BeginRead(const char** buffer, size_t* available) override {
-    if (!underlying_) {
-      *buffer = nullptr;
-      *available = 0;
-      return is_cancelled_ ? Result::kDone : Result::kShouldWait;
-    }
-    return underlying_->BeginRead(buffer, available);
-  }
-  Result EndRead(size_t read_size) override {
-    DCHECK(underlying_);
-    return underlying_->EndRead(read_size);
-  }
-  scoped_refptr<BlobDataHandle> DrainAsBlobDataHandle(
-      BlobSizePolicy policy) override {
-    return underlying_ ? underlying_->DrainAsBlobDataHandle(policy) : nullptr;
-  }
-  scoped_refptr<EncodedFormData> DrainAsFormData() override {
-    return underlying_ ? underlying_->DrainAsFormData() : nullptr;
-  }
-  void SetClient(BytesConsumer::Client* client) override {
-    DCHECK(!client_);
-    DCHECK(client);
-    if (underlying_)
-      underlying_->SetClient(client);
-    else
-      client_ = client;
-  }
-  void ClearClient() override {
-    if (underlying_)
-      underlying_->ClearClient();
-    else
-      client_ = nullptr;
-  }
-  void Cancel() override {
-    if (underlying_) {
-      underlying_->Cancel();
-    } else {
-      is_cancelled_ = true;
-      client_ = nullptr;
-    }
-  }
-  PublicState GetPublicState() const override {
-    return underlying_ ? underlying_->GetPublicState()
-                       : is_cancelled_ ? PublicState::kClosed
-                                       : PublicState::kReadableOrWaiting;
-  }
-  Error GetError() const override {
-    DCHECK(underlying_);
-    // We must not be in the errored state until we get updated.
-    return underlying_->GetError();
-  }
-  String DebugName() const override { return "PlaceHolderBytesConsumer"; }
-
-  // This function can be called at most once.
-  void Update(BytesConsumer* consumer) {
-    DCHECK(!underlying_);
-    if (is_cancelled_) {
-      // This consumer has already been closed.
-      return;
-    }
-
-    underlying_ = consumer;
-    if (client_) {
-      Client* client = client_;
-      client_ = nullptr;
-      underlying_->SetClient(client);
-      if (GetPublicState() != PublicState::kReadableOrWaiting)
-        client->OnStateChange();
-    }
-  }
-
-  void Trace(blink::Visitor* visitor) override {
-    visitor->Trace(underlying_);
-    visitor->Trace(client_);
-    BytesConsumer::Trace(visitor);
-  }
-
- private:
-  TraceWrapperMember<BytesConsumer> underlying_;
-  Member<Client> client_;
-  bool is_cancelled_ = false;
-};
-
 }  // namespace
 
 class FetchManager::Loader final
diff --git a/third_party/blink/renderer/core/fetch/place_holder_bytes_consumer.cc b/third_party/blink/renderer/core/fetch/place_holder_bytes_consumer.cc
new file mode 100644
index 0000000..46fae70c
--- /dev/null
+++ b/third_party/blink/renderer/core/fetch/place_holder_bytes_consumer.cc
@@ -0,0 +1,100 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/fetch/place_holder_bytes_consumer.h"
+
+namespace blink {
+
+BytesConsumer::Result PlaceHolderBytesConsumer::BeginRead(const char** buffer,
+                                                          size_t* available) {
+  if (!underlying_) {
+    *buffer = nullptr;
+    *available = 0;
+    return is_cancelled_ ? Result::kDone : Result::kShouldWait;
+  }
+  return underlying_->BeginRead(buffer, available);
+}
+
+BytesConsumer::Result PlaceHolderBytesConsumer::EndRead(size_t read_size) {
+  DCHECK(underlying_);
+  return underlying_->EndRead(read_size);
+}
+
+scoped_refptr<BlobDataHandle> PlaceHolderBytesConsumer::DrainAsBlobDataHandle(
+    BlobSizePolicy policy) {
+  return underlying_ ? underlying_->DrainAsBlobDataHandle(policy) : nullptr;
+}
+
+scoped_refptr<EncodedFormData> PlaceHolderBytesConsumer::DrainAsFormData() {
+  return underlying_ ? underlying_->DrainAsFormData() : nullptr;
+}
+
+mojo::ScopedDataPipeConsumerHandle PlaceHolderBytesConsumer::DrainAsDataPipe() {
+  if (!underlying_) {
+    return {};
+  }
+  return underlying_->DrainAsDataPipe();
+}
+
+void PlaceHolderBytesConsumer::SetClient(BytesConsumer::Client* client) {
+  DCHECK(!client_);
+  DCHECK(client);
+  if (underlying_)
+    underlying_->SetClient(client);
+  else
+    client_ = client;
+}
+
+void PlaceHolderBytesConsumer::ClearClient() {
+  if (underlying_)
+    underlying_->ClearClient();
+  else
+    client_ = nullptr;
+}
+
+void PlaceHolderBytesConsumer::Cancel() {
+  if (underlying_) {
+    underlying_->Cancel();
+  } else {
+    is_cancelled_ = true;
+    client_ = nullptr;
+  }
+}
+
+BytesConsumer::PublicState PlaceHolderBytesConsumer::GetPublicState() const {
+  return underlying_ ? underlying_->GetPublicState()
+                     : is_cancelled_ ? PublicState::kClosed
+                                     : PublicState::kReadableOrWaiting;
+}
+
+BytesConsumer::Error PlaceHolderBytesConsumer::GetError() const {
+  DCHECK(underlying_);
+  // We must not be in the errored state until we get updated.
+  return underlying_->GetError();
+}
+
+// This function can be called at most once.
+void PlaceHolderBytesConsumer::Update(BytesConsumer* consumer) {
+  DCHECK(!underlying_);
+  if (is_cancelled_) {
+    // This consumer has already been closed.
+    return;
+  }
+
+  underlying_ = consumer;
+  if (client_) {
+    Client* client = client_;
+    client_ = nullptr;
+    underlying_->SetClient(client);
+    client->OnStateChange();
+  }
+}
+
+void PlaceHolderBytesConsumer::Trace(blink::Visitor* visitor) {
+  visitor->Trace(underlying_);
+  visitor->Trace(client_);
+  BytesConsumer::Trace(visitor);
+}
+
+}  // namespace blink
diff --git a/third_party/blink/renderer/core/fetch/place_holder_bytes_consumer.h b/third_party/blink/renderer/core/fetch/place_holder_bytes_consumer.h
new file mode 100644
index 0000000..0cd4c2fc
--- /dev/null
+++ b/third_party/blink/renderer/core/fetch/place_holder_bytes_consumer.h
@@ -0,0 +1,45 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_FETCH_PLACE_HOLDER_BYTES_CONSUMER_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_FETCH_PLACE_HOLDER_BYTES_CONSUMER_H_
+
+#include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/platform/bindings/trace_wrapper_member.h"
+#include "third_party/blink/renderer/platform/loader/fetch/bytes_consumer.h"
+
+namespace blink {
+
+// A BytesConsumer implementation that acts as a place holder. The actual
+// BytesConsumer can be provided later by calling "Update()".
+class CORE_EXPORT PlaceHolderBytesConsumer final : public BytesConsumer {
+ public:
+  // BytesConsumer implementation
+  Result BeginRead(const char** buffer, size_t* available) override;
+  Result EndRead(size_t read_size) override;
+  scoped_refptr<BlobDataHandle> DrainAsBlobDataHandle(
+      BlobSizePolicy policy) override;
+  scoped_refptr<EncodedFormData> DrainAsFormData() override;
+  mojo::ScopedDataPipeConsumerHandle DrainAsDataPipe() override;
+  void SetClient(BytesConsumer::Client* client) override;
+  void ClearClient() override;
+  void Cancel() override;
+  PublicState GetPublicState() const override;
+  Error GetError() const override;
+  String DebugName() const override { return "PlaceHolderBytesConsumer"; }
+
+  // This function can be called at most once.
+  void Update(BytesConsumer* consumer);
+
+  void Trace(blink::Visitor* visitor) override;
+
+ private:
+  TraceWrapperMember<BytesConsumer> underlying_;
+  Member<Client> client_;
+  bool is_cancelled_ = false;
+};
+
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_FETCH_PLACE_HOLDER_BYTES_CONSUMER_H_
diff --git a/third_party/blink/renderer/core/fetch/place_holder_bytes_consumer_test.cc b/third_party/blink/renderer/core/fetch/place_holder_bytes_consumer_test.cc
new file mode 100644
index 0000000..86ed000
--- /dev/null
+++ b/third_party/blink/renderer/core/fetch/place_holder_bytes_consumer_test.cc
@@ -0,0 +1,125 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/fetch/place_holder_bytes_consumer.h"
+
+#include <utility>
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/platform/loader/fetch/data_pipe_bytes_consumer.h"
+#include "third_party/blink/renderer/platform/loader/testing/replaying_bytes_consumer.h"
+#include "third_party/blink/renderer/platform/scheduler/test/fake_task_runner.h"
+
+namespace blink {
+namespace {
+
+class PlaceHolderBytesConsumerTest : public testing::Test {
+ public:
+  using Command = ReplayingBytesConsumer::Command;
+  using PublicState = BytesConsumer::PublicState;
+  using Result = BytesConsumer::Result;
+  using BlobSizePolicy = BytesConsumer::BlobSizePolicy;
+};
+
+TEST_F(PlaceHolderBytesConsumerTest, Construct) {
+  auto* consumer = MakeGarbageCollected<PlaceHolderBytesConsumer>();
+
+  const char* buffer;
+  size_t available;
+
+  EXPECT_EQ(consumer->GetPublicState(), PublicState::kReadableOrWaiting);
+  EXPECT_FALSE(consumer->DrainAsBlobDataHandle(
+      BlobSizePolicy::kAllowBlobWithInvalidSize));
+  EXPECT_FALSE(consumer->DrainAsFormData());
+  EXPECT_FALSE(consumer->DrainAsDataPipe());
+
+  Result result = consumer->BeginRead(&buffer, &available);
+  EXPECT_EQ(result, Result::kShouldWait);
+  EXPECT_EQ(buffer, nullptr);
+  EXPECT_EQ(available, 0u);
+}
+
+TEST_F(PlaceHolderBytesConsumerTest, Update) {
+  auto task_runner = base::MakeRefCounted<scheduler::FakeTaskRunner>();
+  auto* consumer = MakeGarbageCollected<PlaceHolderBytesConsumer>();
+
+  auto* actual_bytes_consumer =
+      MakeGarbageCollected<ReplayingBytesConsumer>(task_runner);
+  actual_bytes_consumer->Add(Command(Command::kDataAndDone, "hello"));
+
+  const char* buffer;
+  size_t available;
+
+  EXPECT_EQ(PublicState::kReadableOrWaiting, consumer->GetPublicState());
+  ASSERT_EQ(Result::kShouldWait, consumer->BeginRead(&buffer, &available));
+  consumer->Update(actual_bytes_consumer);
+
+  EXPECT_EQ(consumer->GetPublicState(), PublicState::kReadableOrWaiting);
+
+  Result result = consumer->BeginRead(&buffer, &available);
+  EXPECT_EQ(result, Result::kOk);
+  ASSERT_EQ(available, 5u);
+  EXPECT_EQ(String(buffer, available), "hello");
+
+  result = consumer->EndRead(available);
+  EXPECT_EQ(result, Result::kDone);
+
+  EXPECT_EQ(consumer->GetPublicState(), PublicState::kClosed);
+}
+
+TEST_F(PlaceHolderBytesConsumerTest, DrainAsDataPipe) {
+  mojo::ScopedDataPipeConsumerHandle consumer_end;
+  mojo::ScopedDataPipeProducerHandle producer_end;
+  auto result = mojo::CreateDataPipe(nullptr, &producer_end, &consumer_end);
+
+  ASSERT_EQ(result, MOJO_RESULT_OK);
+
+  DataPipeBytesConsumer::CompletionNotifier* completion_notifier = nullptr;
+
+  auto task_runner = base::MakeRefCounted<scheduler::FakeTaskRunner>();
+  auto* consumer = MakeGarbageCollected<PlaceHolderBytesConsumer>();
+  auto* actual_bytes_consumer = MakeGarbageCollected<DataPipeBytesConsumer>(
+      task_runner, std::move(consumer_end), &completion_notifier);
+
+  EXPECT_EQ(consumer->GetPublicState(), PublicState::kReadableOrWaiting);
+  EXPECT_FALSE(consumer->DrainAsBlobDataHandle(
+      BlobSizePolicy::kAllowBlobWithInvalidSize));
+  EXPECT_FALSE(consumer->DrainAsFormData());
+  EXPECT_FALSE(consumer->DrainAsDataPipe());
+
+  consumer->Update(actual_bytes_consumer);
+
+  EXPECT_TRUE(consumer->DrainAsDataPipe());
+}
+
+TEST_F(PlaceHolderBytesConsumerTest, Cancel) {
+  auto task_runner = base::MakeRefCounted<scheduler::FakeTaskRunner>();
+  auto* actual_bytes_consumer =
+      MakeGarbageCollected<ReplayingBytesConsumer>(task_runner);
+  actual_bytes_consumer->Add(Command(Command::kData, "hello"));
+  auto* consumer = MakeGarbageCollected<PlaceHolderBytesConsumer>();
+
+  const char* buffer;
+  size_t available;
+
+  EXPECT_EQ(consumer->GetPublicState(), PublicState::kReadableOrWaiting);
+
+  consumer->Cancel();
+
+  EXPECT_EQ(consumer->GetPublicState(), PublicState::kClosed);
+  Result result = consumer->BeginRead(&buffer, &available);
+  EXPECT_EQ(result, Result::kDone);
+  EXPECT_EQ(buffer, nullptr);
+  EXPECT_EQ(available, 0u);
+
+  consumer->Update(actual_bytes_consumer);
+
+  EXPECT_EQ(consumer->GetPublicState(), PublicState::kClosed);
+  result = consumer->BeginRead(&buffer, &available);
+  EXPECT_EQ(result, Result::kDone);
+  EXPECT_EQ(buffer, nullptr);
+  EXPECT_EQ(available, 0u);
+}
+
+}  // namespace
+}  // namespace blink
diff --git a/third_party/blink/renderer/core/frame/web_frame_widget_base.cc b/third_party/blink/renderer/core/frame/web_frame_widget_base.cc
index 2267de3..7e4bc630 100644
--- a/third_party/blink/renderer/core/frame/web_frame_widget_base.cc
+++ b/third_party/blink/renderer/core/frame/web_frame_widget_base.cc
@@ -57,8 +57,6 @@
 void WebFrameWidgetBase::BindLocalRoot(WebLocalFrame& local_root) {
   local_root_ = ToWebLocalFrameImpl(local_root);
   local_root_->SetFrameWidget(this);
-
-  Initialize();
 }
 
 void WebFrameWidgetBase::Close() {
diff --git a/third_party/blink/renderer/core/frame/web_frame_widget_base.h b/third_party/blink/renderer/core/frame/web_frame_widget_base.h
index f2b86f7..e0f0b47 100644
--- a/third_party/blink/renderer/core/frame/web_frame_widget_base.h
+++ b/third_party/blink/renderer/core/frame/web_frame_widget_base.h
@@ -53,8 +53,6 @@
 
   void BindLocalRoot(WebLocalFrame&);
 
-  // Called once the local root is bound via |BindLocalRoot()|.
-  virtual void Initialize() = 0;
   virtual bool ForSubframe() const = 0;
   virtual void IntrinsicSizingInfoChanged(const IntrinsicSizingInfo&) {}
   virtual base::WeakPtr<AnimationWorkletMutatorDispatcherImpl>
diff --git a/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc b/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc
index 7134994..d68cd26 100644
--- a/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc
+++ b/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc
@@ -527,9 +527,6 @@
   return true;
 }
 
-void WebFrameWidgetImpl::Initialize() {
-}
-
 void WebFrameWidgetImpl::IntrinsicSizingInfoChanged(
     const IntrinsicSizingInfo& sizing_info) {
   WebIntrinsicSizingInfo web_sizing_info;
diff --git a/third_party/blink/renderer/core/frame/web_frame_widget_impl.h b/third_party/blink/renderer/core/frame/web_frame_widget_impl.h
index 48ad811..e51f16e 100644
--- a/third_party/blink/renderer/core/frame/web_frame_widget_impl.h
+++ b/third_party/blink/renderer/core/frame/web_frame_widget_impl.h
@@ -132,7 +132,6 @@
                                         mutator_task_runner) override;
 
   // WebFrameWidgetBase overrides:
-  void Initialize() override;
   void SetLayerTreeView(WebLayerTreeView*) override;
   bool ForSubframe() const override { return true; }
   void IntrinsicSizingInfoChanged(const IntrinsicSizingInfo&) override;
diff --git a/third_party/blink/renderer/core/frame/web_view_frame_widget.cc b/third_party/blink/renderer/core/frame/web_view_frame_widget.cc
index 730f819..0eace2c 100644
--- a/third_party/blink/renderer/core/frame/web_view_frame_widget.cc
+++ b/third_party/blink/renderer/core/frame/web_view_frame_widget.cc
@@ -162,8 +162,6 @@
   return web_view_->ScrollFocusedEditableElementIntoView();
 }
 
-void WebViewFrameWidget::Initialize() {}
-
 void WebViewFrameWidget::SetLayerTreeView(WebLayerTreeView*) {
   // The WebViewImpl already has its LayerTreeView, the WebWidgetClient
   // thus does not initialize and set another one here.
diff --git a/third_party/blink/renderer/core/frame/web_view_frame_widget.h b/third_party/blink/renderer/core/frame/web_view_frame_widget.h
index 71ecab44..e09aaae 100644
--- a/third_party/blink/renderer/core/frame/web_view_frame_widget.h
+++ b/third_party/blink/renderer/core/frame/web_view_frame_widget.h
@@ -83,7 +83,6 @@
   WebHitTestResult HitTestResultAt(const gfx::Point&) override;
 
   // WebFrameWidgetBase overrides:
-  void Initialize() override;
   void SetLayerTreeView(WebLayerTreeView*) override;
   bool ForSubframe() const override { return false; }
   base::WeakPtr<AnimationWorkletMutatorDispatcherImpl>
diff --git a/third_party/blink/renderer/core/html/forms/slider_thumb_element.h b/third_party/blink/renderer/core/html/forms/slider_thumb_element.h
index 0794170..52adf04 100644
--- a/third_party/blink/renderer/core/html/forms/slider_thumb_element.h
+++ b/third_party/blink/renderer/core/html/forms/slider_thumb_element.h
@@ -62,7 +62,7 @@
  private:
   LayoutObject* CreateLayoutObject(const ComputedStyle&) override;
   scoped_refptr<ComputedStyle> CustomStyleForLayoutObject() final;
-  Element* CloneWithoutAttributesAndChildren(Document&) const override;
+  Element& CloneWithoutAttributesAndChildren(Document&) const override;
   bool IsDisabledFormControl() const override;
   bool MatchesReadOnlyPseudoClass() const override;
   bool MatchesReadWritePseudoClass() const override;
@@ -73,9 +73,9 @@
       in_drag_mode_;  // Mouse only. Touch is handled by SliderContainerElement.
 };
 
-inline Element* SliderThumbElement::CloneWithoutAttributesAndChildren(
+inline Element& SliderThumbElement::CloneWithoutAttributesAndChildren(
     Document& factory) const {
-  return Create(factory);
+  return *Create(factory);
 }
 
 // FIXME: There are no ways to check if a node is a SliderThumbElement.
diff --git a/third_party/blink/renderer/core/html/html_script_element.cc b/third_party/blink/renderer/core/html/html_script_element.cc
index d763efa..748dfed 100644
--- a/third_party/blink/renderer/core/html/html_script_element.cc
+++ b/third_party/blink/renderer/core/html/html_script_element.cc
@@ -269,12 +269,12 @@
     element.SetHTMLScriptElement(this);
 }
 
-Element* HTMLScriptElement::CloneWithoutAttributesAndChildren(
+Element& HTMLScriptElement::CloneWithoutAttributesAndChildren(
     Document& factory) const {
   CreateElementFlags flags =
       CreateElementFlags::ByCloneNode().SetAlreadyStarted(
           loader_->AlreadyStarted());
-  return factory.CreateElement(TagQName(), flags, IsValue());
+  return *factory.CreateElement(TagQName(), flags, IsValue());
 }
 
 void HTMLScriptElement::Trace(Visitor* visitor) {
diff --git a/third_party/blink/renderer/core/html/html_script_element.h b/third_party/blink/renderer/core/html/html_script_element.h
index 7ccb77f..fa8b725 100644
--- a/third_party/blink/renderer/core/html/html_script_element.h
+++ b/third_party/blink/renderer/core/html/html_script_element.h
@@ -108,7 +108,7 @@
   void SetScriptElementForBinding(
       HTMLScriptElementOrSVGScriptElement&) override;
 
-  Element* CloneWithoutAttributesAndChildren(Document&) const override;
+  Element& CloneWithoutAttributesAndChildren(Document&) const override;
 
   TraceWrapperMember<ScriptLoader> loader_;
 };
diff --git a/third_party/blink/renderer/core/html/track/vtt/vtt_element.cc b/third_party/blink/renderer/core/html/track/vtt/vtt_element.cc
index 1ca3c8f1..e2362cd9 100644
--- a/third_party/blink/renderer/core/html/track/vtt/vtt_element.cc
+++ b/third_party/blink/renderer/core/html/track/vtt/vtt_element.cc
@@ -74,11 +74,11 @@
   return MakeGarbageCollected<VTTElement>(node_type, document);
 }
 
-Element* VTTElement::CloneWithoutAttributesAndChildren(
+Element& VTTElement::CloneWithoutAttributesAndChildren(
     Document& factory) const {
-  VTTElement* clone =
-      Create(static_cast<VTTNodeType>(web_vtt_node_type_), &factory);
-  clone->SetLanguage(language_);
+  VTTElement& clone =
+      *Create(static_cast<VTTNodeType>(web_vtt_node_type_), &factory);
+  clone.SetLanguage(language_);
   return clone;
 }
 
diff --git a/third_party/blink/renderer/core/html/track/vtt/vtt_element.h b/third_party/blink/renderer/core/html/track/vtt/vtt_element.h
index 7e4f9f3..ed66a1c 100644
--- a/third_party/blink/renderer/core/html/track/vtt/vtt_element.h
+++ b/third_party/blink/renderer/core/html/track/vtt/vtt_element.h
@@ -51,7 +51,7 @@
   VTTElement(const QualifiedName&, Document*);
   VTTElement(VTTNodeType, Document*);
 
-  Element* CloneWithoutAttributesAndChildren(Document&) const override;
+  Element& CloneWithoutAttributesAndChildren(Document&) const override;
 
   void SetVTTNodeType(VTTNodeType type) {
     web_vtt_node_type_ = static_cast<unsigned>(type);
diff --git a/third_party/blink/renderer/core/layout/layout_object.cc b/third_party/blink/renderer/core/layout/layout_object.cc
index ac4295f5..0e2257d0 100644
--- a/third_party/blink/renderer/core/layout/layout_object.cc
+++ b/third_party/blink/renderer/core/layout/layout_object.cc
@@ -1644,15 +1644,6 @@
     fragment->SetSelectionVisualRect(LayoutRect());
   }
 
-  if (IsInline()) {
-    auto fragments = NGPaintFragment::InlineFragmentsFor(this);
-    if (fragments.IsInLayoutNGInlineFormattingContext()) {
-      for (auto* fragment : fragments) {
-        fragment->SetSelectionVisualRect(LayoutRect());
-      }
-    }
-  }
-
   // After clearing ("invalidating") the visual rects, mark this object as
   // needing to re-compute them.
   SetShouldDoFullPaintInvalidation();
diff --git a/third_party/blink/renderer/core/layout/layout_object.h b/third_party/blink/renderer/core/layout/layout_object.h
index 1f3cf88c..c5dc43b0 100644
--- a/third_party/blink/renderer/core/layout/layout_object.h
+++ b/third_party/blink/renderer/core/layout/layout_object.h
@@ -277,6 +277,10 @@
     return AdjustVisualRectForInlineBox(VisualRect());
   }
 
+  LayoutRect PartialInvalidationVisualRectForInlineBox() const {
+    return AdjustVisualRectForInlineBox(PartialInvalidationVisualRect());
+  }
+
   String DebugName() const final;
 
   // End of DisplayItemClient methods.
@@ -2476,9 +2480,6 @@
   void ApplyPseudoStyleChanges(const ComputedStyle* old_style);
   void ApplyFirstLineChanges(const ComputedStyle* old_style);
 
-  LayoutRect PartialInvalidationVisualRectForInlineBox() const {
-    return AdjustVisualRectForInlineBox(PartialInvalidationVisualRect());
-  }
   LayoutRect AdjustVisualRectForInlineBox(const LayoutRect&) const;
 
   // This is set by Set[Subtree]ShouldDoFullPaintInvalidation, and cleared
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_items_builder.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_items_builder.cc
index 367be79c..aa41e60 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_items_builder.cc
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_items_builder.cc
@@ -771,6 +771,7 @@
 template <typename OffsetMappingBuilder>
 void NGInlineItemsBuilderTemplate<OffsetMappingBuilder>::AppendFloating(
     LayoutObject* layout_object) {
+  changes_may_affect_earlier_lines_ = true;
   AppendOpaque(NGInlineItem::kFloating, kObjectReplacementCharacter, nullptr,
                layout_object);
 }
@@ -778,6 +779,7 @@
 template <typename OffsetMappingBuilder>
 void NGInlineItemsBuilderTemplate<OffsetMappingBuilder>::
     AppendOutOfFlowPositioned(LayoutObject* layout_object) {
+  changes_may_affect_earlier_lines_ = true;
   AppendOpaque(NGInlineItem::kOutOfFlowPositioned, kObjectReplacementCharacter,
                nullptr, layout_object);
 }
@@ -951,6 +953,9 @@
         // Plaintext is handled as the paragraph level by
         // NGBidiParagraph::SetParagraph().
         has_bidi_controls_ = true;
+        // It's not easy to compute which lines will change with `unicode-bidi:
+        // plaintext`. Since it is quite uncommon that just disable line cache.
+        changes_may_affect_earlier_lines_ = true;
         break;
     }
   } else {
@@ -994,6 +999,7 @@
                          kPopDirectionalIsolateCharacter);
         break;
       case UnicodeBidi::kPlaintext:
+        changes_may_affect_earlier_lines_ = true;
         EnterBidiContext(node, kFirstStrongIsolateCharacter,
                          kPopDirectionalIsolateCharacter);
         break;
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_items_builder.h b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_items_builder.h
index d54d8fa..8ea2961 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_items_builder.h
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_items_builder.h
@@ -54,6 +54,13 @@
   // <span></span> or <span><float></float></span>.
   bool IsEmptyInline() const { return is_empty_inline_; }
 
+  // True if changes to an item may affect different layout of earlier lines.
+  // May not be able to use line caches even when the line or earlier lines are
+  // not dirty.
+  bool ChangesMayAffectEarlierLines() const {
+    return changes_may_affect_earlier_lines_;
+  }
+
   // Append existing items from an unchanged LayoutObject.
   // Returns whether the existing items could be reused.
   // NOTE: The state of the builder remains unchanged if the append operation
@@ -151,6 +158,7 @@
 
   bool has_bidi_controls_ = false;
   bool is_empty_inline_ = true;
+  bool changes_may_affect_earlier_lines_ = false;
 
   // Append a character.
   // Currently this function is for adding control characters such as
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.cc
index 1ae17e9d..4062179 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.cc
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.cc
@@ -516,6 +516,8 @@
   // doesn't contain any RTL characters.
   data->is_bidi_enabled_ = MayBeBidiEnabled(data->text_content, builder);
   data->is_empty_inline_ = builder.IsEmptyInline();
+  data->changes_may_affect_earlier_lines_ =
+      builder.ChangesMayAffectEarlierLines();
 }
 
 void NGInlineNode::SegmentText(NGInlineNodeData* data) {
@@ -963,11 +965,17 @@
   if (!block_flow->AreCachedLinesValidFor(constraint_space))
     return false;
 
+  if (MaybeDirtyData().changes_may_affect_earlier_lines_)
+    return false;
+
   if (!MarkLineBoxesDirty(block_flow))
     return false;
 
   PrepareLayoutIfNeeded();
 
+  if (Data().changes_may_affect_earlier_lines_)
+    return false;
+
   return true;
 }
 
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node_data.h b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node_data.h
index 2037022..64c19d1 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node_data.h
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node_data.h
@@ -48,6 +48,11 @@
   // produce a single zero block-size line box. If the node has text, atomic
   // inlines, open/close tags with margins/border/padding this will be false.
   unsigned is_empty_inline_ : 1;
+
+  // True if changes to an item may affect different layout of earlier lines.
+  // May not be able to use line caches even when the line or earlier lines are
+  // not dirty.
+  unsigned changes_may_affect_earlier_lines_ : 1;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/paint/ng/ng_paint_fragment.cc b/third_party/blink/renderer/core/paint/ng/ng_paint_fragment.cc
index aaf9553..b23de40 100644
--- a/third_party/blink/renderer/core/paint/ng/ng_paint_fragment.cc
+++ b/third_party/blink/renderer/core/paint/ng/ng_paint_fragment.cc
@@ -317,18 +317,6 @@
   return paint_fragment;
 }
 
-NGPaintFragment::RareData& NGPaintFragment::EnsureRareData() {
-  if (!rare_data_)
-    rare_data_ = std::make_unique<RareData>();
-  return *rare_data_;
-}
-
-const NGPaintFragment* NGPaintFragment::Next() const {
-  if (!rare_data_)
-    return nullptr;
-  return rare_data_->next_fragmented_.get();
-}
-
 const NGPaintFragment* NGPaintFragment::Last() const {
   for (const NGPaintFragment* fragment = this;;) {
     const NGPaintFragment* next = fragment->Next();
@@ -363,8 +351,7 @@
     if (!*fragment)
       return fragment;
 
-    scoped_refptr<NGPaintFragment>* next =
-        &(*fragment)->EnsureRareData().next_fragmented_;
+    scoped_refptr<NGPaintFragment>* next = &(*fragment)->next_fragmented_;
     if ((*fragment)->PhysicalFragment().BreakToken() == break_token)
       return next;
     fragment = next;
@@ -373,9 +360,7 @@
 }
 
 void NGPaintFragment::SetNext(scoped_refptr<NGPaintFragment> fragment) {
-  if (!rare_data_ && !fragment)
-    return;
-  EnsureRareData().next_fragmented_ = std::move(fragment);
+  next_fragmented_ = std::move(fragment);
 }
 
 bool NGPaintFragment::IsDescendantOfNotSelf(
@@ -403,18 +388,6 @@
          ToNGPhysicalBoxFragment(*physical_fragment_).ShouldClipOverflow();
 }
 
-LayoutRect NGPaintFragment::SelectionVisualRect() const {
-  if (!rare_data_)
-    return LayoutRect();
-  return rare_data_->selection_visual_rect_;
-}
-
-void NGPaintFragment::SetSelectionVisualRect(const LayoutRect& rect) {
-  if (!rare_data_ && rect.IsEmpty())
-    return;
-  EnsureRareData().selection_visual_rect_ = rect;
-}
-
 LayoutRect NGPaintFragment::SelfInkOverflow() const {
   return physical_fragment_->InkOverflow().ToLayoutRect();
 }
@@ -536,9 +509,8 @@
   return fragment;
 }
 
-LayoutRect NGPaintFragment::VisualRect() const {
-  // VisualRect is computed from fragment tree and set to LayoutObject in
-  // pre-paint. Use the stored value in the LayoutObject.
+const LayoutObject& NGPaintFragment::VisualRectLayoutObject(
+    bool& this_as_inline_box) const {
   const NGPhysicalFragment& fragment = PhysicalFragment();
   if (const LayoutObject* layout_object = fragment.GetLayoutObject()) {
     // For inline fragments, InlineBox uses one united rect for the LayoutObject
@@ -549,20 +521,36 @@
     // formatting context and another as a child of the inline formatting
     // context it participates. |Parent()| can distinguish them because a tree
     // is created for each inline formatting context.
-    if (Parent())
-      return layout_object->VisualRectForInlineBox();
-
-    return static_cast<const DisplayItemClient*>(layout_object)->VisualRect();
+    this_as_inline_box = Parent();
+    return *layout_object;
   }
 
   // Line box does not have corresponding LayoutObject. Use VisualRect of the
   // containing LayoutBlockFlow as RootInlineBox does so.
+  this_as_inline_box = true;
   DCHECK(fragment.IsLineBox());
   // Line box is always a direct child of its containing block.
   NGPaintFragment* containing_block_fragment = Parent();
   DCHECK(containing_block_fragment);
   DCHECK(containing_block_fragment->GetLayoutObject());
-  return containing_block_fragment->GetLayoutObject()->VisualRectForInlineBox();
+  return *containing_block_fragment->GetLayoutObject();
+}
+
+LayoutRect NGPaintFragment::VisualRect() const {
+  // VisualRect is computed from fragment tree and set to LayoutObject in
+  // pre-paint. Use the stored value in the LayoutObject.
+  bool this_as_inline_box;
+  const auto& layout_object = VisualRectLayoutObject(this_as_inline_box);
+  return this_as_inline_box ? layout_object.VisualRectForInlineBox()
+                            : layout_object.FragmentsVisualRectBoundingBox();
+}
+
+LayoutRect NGPaintFragment::PartialInvalidationVisualRect() const {
+  bool this_as_inline_box;
+  const auto& layout_object = VisualRectLayoutObject(this_as_inline_box);
+  return this_as_inline_box
+             ? layout_object.PartialInvalidationVisualRectForInlineBox()
+             : layout_object.PartialInvalidationVisualRect();
 }
 
 bool NGPaintFragment::FlippedLocalVisualRectFor(
diff --git a/third_party/blink/renderer/core/paint/ng/ng_paint_fragment.h b/third_party/blink/renderer/core/paint/ng/ng_paint_fragment.h
index 47f11ca..51336412f 100644
--- a/third_party/blink/renderer/core/paint/ng/ng_paint_fragment.h
+++ b/third_party/blink/renderer/core/paint/ng/ng_paint_fragment.h
@@ -55,7 +55,7 @@
   }
 
   // Next/last fragment for  when this is fragmented.
-  const NGPaintFragment* Next() const;
+  const NGPaintFragment* Next() const { return next_fragmented_.get(); }
   void SetNext(scoped_refptr<NGPaintFragment>);
   const NGPaintFragment* Last() const;
   const NGPaintFragment* Last(const NGBreakToken&) const;
@@ -161,9 +161,7 @@
   bool HasSelfPaintingLayer() const;
   // This is equivalent to LayoutObject::VisualRect
   LayoutRect VisualRect() const override;
-
-  LayoutRect SelectionVisualRect() const;
-  void SetSelectionVisualRect(const LayoutRect& rect);
+  LayoutRect PartialInvalidationVisualRect() const override;
 
   // CSS ink overflow https://www.w3.org/TR/css-overflow-3/#ink
   // Encloses all pixels painted by self + children.
@@ -316,6 +314,9 @@
   // Dirty line boxes containing |layout_object|.
   static void MarkLineBoxesDirtyFor(const LayoutObject& layout_object);
 
+  // This fragment will use the layout object's visual rect.
+  const LayoutObject& VisualRectLayoutObject(bool& this_as_inline_box) const;
+
   //
   // Following fields are computed in the layout phase.
   //
@@ -327,18 +328,8 @@
   scoped_refptr<NGPaintFragment> first_child_;
   scoped_refptr<NGPaintFragment> next_sibling_;
 
-  struct RareData {
-    USING_FAST_MALLOC(RareData);
-
-   public:
-    // The next fragment for when this is fragmented.
-    scoped_refptr<NGPaintFragment> next_fragmented_;
-
-    // Used for invalidating selected fragment.
-    LayoutRect selection_visual_rect_;
-  };
-  RareData& EnsureRareData();
-  std::unique_ptr<RareData> rare_data_;
+  // The next fragment for when this is fragmented.
+  scoped_refptr<NGPaintFragment> next_fragmented_;
 
   NGPaintFragment* next_for_same_layout_object_ = nullptr;
   NGPhysicalOffset inline_offset_to_container_box_;
diff --git a/third_party/blink/renderer/core/paint/ng/ng_paint_fragment_test.cc b/third_party/blink/renderer/core/paint/ng/ng_paint_fragment_test.cc
index af258b9..f51d2d3e 100644
--- a/third_party/blink/renderer/core/paint/ng/ng_paint_fragment_test.cc
+++ b/third_party/blink/renderer/core/paint/ng/ng_paint_fragment_test.cc
@@ -218,7 +218,6 @@
                           .ToString());
   // TODO(kojii): This is still incorrect.
   EXPECT_EQ(LayoutRect(0, 0, 60, 10), outer_text.VisualRect());
-  EXPECT_EQ(LayoutRect(), outer_text.SelectionVisualRect());
 
   // Test |InlineFragmentsFor| can find the outer text.
   LayoutObject* layout_outer_text =
@@ -235,7 +234,6 @@
   EXPECT_EQ(NGPhysicalFragment::kAtomicInline,
             box1.PhysicalFragment().BoxType());
   EXPECT_EQ(LayoutRect(60, 0, 10, 10), box1.VisualRect());
-  EXPECT_EQ(LayoutRect(), box1.SelectionVisualRect());
 
   // Test |InlineFragmentsFor| can find "box1".
   LayoutObject* layout_box1 = GetLayoutObjectByElementId("box1");
@@ -256,7 +254,6 @@
   EXPECT_EQ(NGPhysicalFragment::kFragmentText,
             inner_text.PhysicalFragment().Type());
   EXPECT_EQ(LayoutRect(60, 0, 10, 10), inner_text.VisualRect());
-  EXPECT_EQ(LayoutRect(), inner_text.SelectionVisualRect());
 
   // Test |InlineFragmentsFor| can find the inner text of "box1".
   LayoutObject* layout_inner_text = layout_box1->SlowFirstChild();
@@ -272,18 +269,13 @@
   EXPECT_EQ(NGPhysicalFragment::kAtomicInline,
             box2.PhysicalFragment().BoxType());
   EXPECT_EQ(LayoutRect(70, 10, 10, 10), box2.VisualRect());
-  EXPECT_EQ(LayoutRect(), box2.SelectionVisualRect());
 
   GetDocument().GetFrame()->Selection().SelectAll();
   UpdateAllLifecyclePhasesForTest();
   EXPECT_EQ(LayoutRect(0, 0, 60, 10), outer_text.VisualRect());
-  EXPECT_EQ(LayoutRect(0, 0, 60, 10), outer_text.SelectionVisualRect());
   EXPECT_EQ(LayoutRect(60, 0, 10, 10), box1.VisualRect());
-  EXPECT_EQ(LayoutRect(), box1.SelectionVisualRect());
   EXPECT_EQ(LayoutRect(60, 0, 10, 10), inner_text.VisualRect());
-  EXPECT_EQ(LayoutRect(60, 0, 10, 10), inner_text.SelectionVisualRect());
   EXPECT_EQ(LayoutRect(70, 10, 10, 10), box2.VisualRect());
-  EXPECT_EQ(LayoutRect(), box2.SelectionVisualRect());
 }
 
 TEST_F(NGPaintFragmentTest, RelativeBlock) {
diff --git a/third_party/blink/renderer/core/paint/object_paint_invalidator.cc b/third_party/blink/renderer/core/paint/object_paint_invalidator.cc
index b65003b..74e97b0 100644
--- a/third_party/blink/renderer/core/paint/object_paint_invalidator.cc
+++ b/third_party/blink/renderer/core/paint/object_paint_invalidator.cc
@@ -290,15 +290,6 @@
 DISABLE_CFI_PERF
 PaintInvalidationReason ObjectPaintInvalidatorWithContext::InvalidateSelection(
     PaintInvalidationReason reason) {
-  // In LayoutNG, if NGPaintFragment paints the selection, we invalidate for
-  // selection change in PaintInvalidator.
-  if (RuntimeEnabledFeatures::LayoutNGEnabled() && object_.IsInline() &&
-      // LayoutReplaced still paints selection tint by itself.
-      !object_.IsLayoutReplaced() &&
-      NGPaintFragment::InlineFragmentsFor(&object_)
-          .IsInLayoutNGInlineFormattingContext())
-    return reason;
-
   // Update selection rect when we are doing full invalidation with geometry
   // change (in case that the object is moved, composite status changed, etc.)
   // or shouldInvalidationSelection is set (in case that the selection itself
diff --git a/third_party/blink/renderer/core/paint/paint_invalidator.cc b/third_party/blink/renderer/core/paint/paint_invalidator.cc
index 7cd111e..db85483 100644
--- a/third_party/blink/renderer/core/paint/paint_invalidator.cc
+++ b/third_party/blink/renderer/core/paint/paint_invalidator.cc
@@ -13,7 +13,6 @@
 #include "third_party/blink/renderer/core/layout/layout_table.h"
 #include "third_party/blink/renderer/core/layout/layout_table_section.h"
 #include "third_party/blink/renderer/core/layout/layout_view.h"
-#include "third_party/blink/renderer/core/layout/ng/geometry/ng_physical_offset_rect.h"
 #include "third_party/blink/renderer/core/layout/ng/legacy_layout_tree_walking.h"
 #include "third_party/blink/renderer/core/layout/svg/svg_layout_support.h"
 #include "third_party/blink/renderer/core/paint/clip_path_clipper.h"
@@ -160,31 +159,6 @@
                                                            context);
 }
 
-static LayoutRect ComputeFragmentLocalSelectionRect(
-    const NGPaintFragment& fragment) {
-  DCHECK(fragment.PhysicalFragment().IsText());
-  const FrameSelection& frame_selection =
-      fragment.GetLayoutObject()->GetFrame()->Selection();
-  const LayoutSelectionStatus status =
-      frame_selection.ComputeLayoutSelectionStatus(fragment);
-  if (status.start == status.end)
-    return LayoutRect();
-  return fragment.ComputeLocalSelectionRectForText(status).ToLayoutRect();
-}
-
-LayoutRect PaintInvalidator::MapFragmentLocalRectToVisualRect(
-    const LayoutRect& local_rect,
-    const LayoutObject& object,
-    const NGPaintFragment& fragment,
-    const PaintInvalidatorContext& context) {
-  LayoutRect rect = local_rect;
-  if (!object.IsBox())
-    rect.Move(fragment.InlineOffsetToContainerBox().ToLayoutSize());
-  bool disable_flip = true;
-  return MapLocalRectToVisualRect<LayoutRect, LayoutPoint>(
-      object, rect, context, disable_flip);
-}
-
 void PaintInvalidator::UpdatePaintingLayer(const LayoutObject& object,
                                            PaintInvalidatorContext& context) {
   if (object.HasLayer() &&
@@ -321,57 +295,6 @@
   if (new_visual_rect.IsEmpty())
     new_visual_rect.SetLocation(fragment_data.PaintOffset());
   fragment_data.SetVisualRect(new_visual_rect);
-
-  // For LayoutNG, update NGPaintFragments.
-  // TODO(kojii): If we can compute SelectionVisualRect when needed, the
-  // following code path will not be needed.
-  if (!RuntimeEnabledFeatures::LayoutNGEnabled())
-    return;
-
-  if (object.IsInline()) {
-    // An inline LayoutObject can produce multiple NGPaintFragment. Compute
-    // VisualRect for each fragment from |new_visual_rect|.
-    auto fragments = NGPaintFragment::InlineFragmentsFor(&object);
-    if (fragments.IsInLayoutNGInlineFormattingContext()) {
-      bool has_selection_in_this_object =
-          object.IsText() && ToLayoutText(object).IsSelected();
-      if (!has_selection_in_this_object) {
-        for (NGPaintFragment* fragment : fragments) {
-          if (UNLIKELY(!fragment->SelectionVisualRect().IsEmpty())) {
-            context.painting_layer->SetNeedsRepaint();
-            ObjectPaintInvalidator(object).InvalidateDisplayItemClient(
-                *fragment, PaintInvalidationReason::kSelection);
-            fragment->SetSelectionVisualRect(LayoutRect());
-          }
-        }
-      } else {
-        // TODO(kojii): It's not clear why we need to pre-compute selection rect
-        // for all fragments when legacy can handle it as needed. yoichio will
-        // look into this.
-        for (NGPaintFragment* fragment : fragments) {
-          LayoutRect local_selection_rect =
-              ComputeFragmentLocalSelectionRect(*fragment);
-          LayoutRect selection_visual_rect = MapFragmentLocalRectToVisualRect(
-              local_selection_rect, object, *fragment, context);
-          new_visual_rect.Unite(selection_visual_rect);
-          const bool should_invalidate =
-              object.ShouldInvalidateSelection() ||
-              selection_visual_rect != fragment->SelectionVisualRect();
-          const bool rect_exists = !selection_visual_rect.IsEmpty() ||
-                                   !fragment->SelectionVisualRect().IsEmpty();
-          if (should_invalidate && rect_exists) {
-            context.painting_layer->SetNeedsRepaint();
-            ObjectPaintInvalidator(object).InvalidateDisplayItemClient(
-                *fragment, PaintInvalidationReason::kSelection);
-            fragment->SetSelectionVisualRect(selection_visual_rect);
-          }
-        }
-        // TODO(kojii): Not sure why do we need to include SelectionVisualRect
-        // to VisualRect only in NG, but this is needed to pass some tests.
-        fragment_data.SetVisualRect(new_visual_rect);
-      }
-    }
-  }
 }
 
 void PaintInvalidator::UpdateEmptyVisualRectFlag(
diff --git a/third_party/blink/renderer/core/paint/paint_invalidator.h b/third_party/blink/renderer/core/paint/paint_invalidator.h
index 870bc8a..a96da8f 100644
--- a/third_party/blink/renderer/core/paint/paint_invalidator.h
+++ b/third_party/blink/renderer/core/paint/paint_invalidator.h
@@ -13,7 +13,6 @@
 
 namespace blink {
 
-class NGPaintFragment;
 class PrePaintTreeWalk;
 
 struct CORE_EXPORT PaintInvalidatorContext {
@@ -164,11 +163,6 @@
 
   ALWAYS_INLINE LayoutRect ComputeVisualRect(const LayoutObject&,
                                              const PaintInvalidatorContext&);
-  ALWAYS_INLINE LayoutRect
-  MapFragmentLocalRectToVisualRect(const LayoutRect&,
-                                   const LayoutObject&,
-                                   const NGPaintFragment&,
-                                   const PaintInvalidatorContext&);
   ALWAYS_INLINE void UpdatePaintingLayer(const LayoutObject&,
                                          PaintInvalidatorContext&);
   ALWAYS_INLINE void UpdatePaintInvalidationContainer(const LayoutObject&,
diff --git a/third_party/blink/renderer/core/script/module_map_test.cc b/third_party/blink/renderer/core/script/module_map_test.cc
index 9497735b..411a570 100644
--- a/third_party/blink/renderer/core/script/module_map_test.cc
+++ b/third_party/blink/renderer/core/script/module_map_test.cc
@@ -141,7 +141,7 @@
 
   base::SingleThreadTaskRunner* TaskRunner() override {
     return Thread::Current()->GetTaskRunner().get();
-  };
+  }
 
   struct TestRequest final : public GarbageCollectedFinalized<TestRequest> {
     TestRequest(const ModuleScriptCreationParams& params,
diff --git a/third_party/blink/renderer/core/svg/svg_script_element.cc b/third_party/blink/renderer/core/svg/svg_script_element.cc
index d6b017bf..fbd263ce 100644
--- a/third_party/blink/renderer/core/svg/svg_script_element.cc
+++ b/third_party/blink/renderer/core/svg/svg_script_element.cc
@@ -147,12 +147,12 @@
   return Node::GetDocument();
 }
 
-Element* SVGScriptElement::CloneWithoutAttributesAndChildren(
+Element& SVGScriptElement::CloneWithoutAttributesAndChildren(
     Document& factory) const {
   CreateElementFlags flags =
       CreateElementFlags::ByCloneNode().SetAlreadyStarted(
           loader_->AlreadyStarted());
-  return factory.CreateElement(TagQName(), flags, IsValue());
+  return *factory.CreateElement(TagQName(), flags, IsValue());
 }
 
 void SVGScriptElement::DispatchLoadEvent() {
diff --git a/third_party/blink/renderer/core/svg/svg_script_element.h b/third_party/blink/renderer/core/svg/svg_script_element.h
index 5fe1cc2b236..669ce8e27 100644
--- a/third_party/blink/renderer/core/svg/svg_script_element.h
+++ b/third_party/blink/renderer/core/svg/svg_script_element.h
@@ -99,7 +99,7 @@
   void SetScriptElementForBinding(
       HTMLScriptElementOrSVGScriptElement&) override;
 
-  Element* CloneWithoutAttributesAndChildren(Document&) const override;
+  Element& CloneWithoutAttributesAndChildren(Document&) const override;
   bool LayoutObjectIsNeeded(const ComputedStyle&) const override {
     return false;
   }
diff --git a/third_party/blink/renderer/core/svg/svg_use_element.cc b/third_party/blink/renderer/core/svg/svg_use_element.cc
index 46096de..94f3e09a 100644
--- a/third_party/blink/renderer/core/svg/svg_use_element.cc
+++ b/third_party/blink/renderer/core/svg/svg_use_element.cc
@@ -409,7 +409,7 @@
 }
 
 Element* SVGUseElement::CreateInstanceTree(SVGElement& target_root) const {
-  Element* instance_root = target_root.CloneWithChildren();
+  Element* instance_root = &target_root.CloneWithChildren();
   DCHECK(instance_root->IsSVGElement());
   if (IsSVGSymbolElement(target_root)) {
     // Spec: The referenced 'symbol' and its contents are deep-cloned into
diff --git a/third_party/blink/renderer/core/workers/dedicated_worker.cc b/third_party/blink/renderer/core/workers/dedicated_worker.cc
index 5d9dbf6..7be18ed 100644
--- a/third_party/blink/renderer/core/workers/dedicated_worker.cc
+++ b/third_party/blink/renderer/core/workers/dedicated_worker.cc
@@ -4,11 +4,12 @@
 
 #include "third_party/blink/renderer/core/workers/dedicated_worker.h"
 
-#include <memory>
+#include <utility>
 #include "base/feature_list.h"
 #include "services/network/public/mojom/fetch_api.mojom-blink.h"
 #include "services/service_manager/public/cpp/interface_provider.h"
 #include "services/service_manager/public/mojom/interface_provider.mojom-blink.h"
+#include "third_party/blink/public/common/blob/blob_utils.h"
 #include "third_party/blink/public/common/features.h"
 #include "third_party/blink/public/mojom/script/script_type.mojom-blink.h"
 #include "third_party/blink/public/mojom/worker/dedicated_worker_host_factory.mojom-blink.h"
@@ -19,6 +20,7 @@
 #include "third_party/blink/renderer/core/dom/document.h"
 #include "third_party/blink/renderer/core/events/message_event.h"
 #include "third_party/blink/renderer/core/execution_context/execution_context.h"
+#include "third_party/blink/renderer/core/fileapi/public_url_manager.h"
 #include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/frame/local_frame_client.h"
 #include "third_party/blink/renderer/core/frame/use_counter.h"
@@ -53,6 +55,7 @@
 ConnectToWorkerInterfaceProvider(
     ExecutionContext* execution_context,
     scoped_refptr<const SecurityOrigin> script_origin) {
+  DCHECK(!features::IsPlzDedicatedWorkerEnabled());
   mojom::blink::DedicatedWorkerHostFactoryPtr worker_host_factory;
   execution_context->GetInterfaceProvider()->GetInterface(&worker_host_factory);
   service_manager::mojom::blink::InterfaceProviderPtrInfo
@@ -216,6 +219,25 @@
 
   if (auto* scope = DynamicTo<WorkerGlobalScope>(*GetExecutionContext()))
     scope->EnsureFetcher();
+  if (blink::features::IsPlzDedicatedWorkerEnabled()) {
+    mojom::blink::BlobURLTokenPtr blob_url_token;
+    if (script_request_url_.ProtocolIs("blob") &&
+        BlobUtils::MojoBlobURLsEnabled()) {
+      GetExecutionContext()->GetPublicURLManager().Resolve(
+          script_request_url_, MakeRequest(&blob_url_token));
+    }
+
+    DCHECK(!factory_client_);
+    factory_client_ =
+        Platform::Current()->CreateDedicatedWorkerHostFactoryClient(
+            this, GetExecutionContext()->GetInterfaceProvider());
+    factory_client_->CreateWorkerHost(
+        script_request_url_,
+        WebSecurityOrigin(GetExecutionContext()->GetSecurityOrigin()),
+        blob_url_token.PassInterface().PassHandle());
+    // Continue in OnScriptLoaded().
+    return;
+  }
   if (base::FeatureList::IsEnabled(
           features::kOffMainThreadDedicatedWorkerScriptFetch) ||
       options_->type() == "module") {
@@ -286,6 +308,7 @@
   DCHECK(GetExecutionContext()->IsContextThread());
   if (classic_script_loader_)
     classic_script_loader_->Cancel();
+  factory_client_.reset();
   terminate();
 }
 
@@ -296,6 +319,25 @@
   return context_proxy_->HasPendingActivity() || classic_script_loader_;
 }
 
+void DedicatedWorker::OnWorkerHostCreated(
+    mojo::ScopedMessagePipeHandle interface_provider) {
+  DCHECK(features::IsPlzDedicatedWorkerEnabled());
+  interface_provider_ = service_manager::mojom::blink::InterfaceProviderPtrInfo(
+      std::move(interface_provider),
+      service_manager::mojom::blink::InterfaceProvider::Version_);
+}
+
+void DedicatedWorker::OnScriptLoaded() {
+  DCHECK(features::IsPlzDedicatedWorkerEnabled());
+  // TODO(nhiroki): Continue worker start.
+}
+
+void DedicatedWorker::OnScriptLoadFailed() {
+  DCHECK(features::IsPlzDedicatedWorkerEnabled());
+  context_proxy_->DidFailToFetchScript();
+  factory_client_.reset();
+}
+
 void DedicatedWorker::DispatchErrorEventForScriptFetchFailure() {
   DCHECK(!GetExecutionContext() || GetExecutionContext()->IsContextThread());
   // TODO(nhiroki): Add a console error message.
@@ -427,8 +469,10 @@
       OriginTrialContext::GetTokens(GetExecutionContext()).get(),
       parent_devtools_token, std::move(settings), kV8CacheOptionsDefault,
       nullptr /* worklet_module_responses_map */,
-      ConnectToWorkerInterfaceProvider(GetExecutionContext(),
-                                       SecurityOrigin::Create(script_url)),
+      interface_provider_
+          ? std::move(interface_provider_)
+          : ConnectToWorkerInterfaceProvider(
+                GetExecutionContext(), SecurityOrigin::Create(script_url)),
       CreateBeginFrameProviderParams(),
       GetExecutionContext()->GetSecurityContext().GetFeaturePolicy(),
       GetExecutionContext()->GetAgentClusterID());
diff --git a/third_party/blink/renderer/core/workers/dedicated_worker.h b/third_party/blink/renderer/core/workers/dedicated_worker.h
index a1774b3e..4faf98a 100644
--- a/third_party/blink/renderer/core/workers/dedicated_worker.h
+++ b/third_party/blink/renderer/core/workers/dedicated_worker.h
@@ -5,7 +5,10 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_WORKERS_DEDICATED_WORKER_H_
 #define THIRD_PARTY_BLINK_RENDERER_CORE_WORKERS_DEDICATED_WORKER_H_
 
+#include <memory>
 #include "base/memory/scoped_refptr.h"
+#include "third_party/blink/public/platform/web_dedicated_worker.h"
+#include "third_party/blink/public/platform/web_dedicated_worker_host_factory_client.h"
 #include "third_party/blink/renderer/bindings/core/v8/active_script_wrappable.h"
 #include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/core/dom/events/event_listener.h"
@@ -41,7 +44,8 @@
 // created the worker or a worker thread in the case of nested workers.
 class CORE_EXPORT DedicatedWorker final
     : public AbstractWorker,
-      public ActiveScriptWrappable<DedicatedWorker> {
+      public ActiveScriptWrappable<DedicatedWorker>,
+      public WebDedicatedWorker {
   DEFINE_WRAPPERTYPEINFO();
   USING_GARBAGE_COLLECTED_MIXIN(DedicatedWorker);
   // Eager finalization is needed to notify the parent object destruction of the
@@ -77,6 +81,13 @@
   // (via AbstractWorker -> EventTargetWithInlineData -> EventTarget).
   bool HasPendingActivity() const final;
 
+  // Implements WebDedicatedWorker.
+  // Called only when PlzDedicatedWorker is enabled.
+  void OnWorkerHostCreated(
+      mojo::ScopedMessagePipeHandle interface_provider) override;
+  void OnScriptLoaded() override;
+  void OnScriptLoadFailed() override;
+
   void DispatchErrorEventForScriptFetchFailure();
 
   // Returns the name specified by WorkerOptions.
@@ -109,6 +120,11 @@
   const Member<DedicatedWorkerMessagingProxy> context_proxy_;
 
   Member<WorkerClassicScriptLoader> classic_script_loader_;
+
+  // Used only when PlzDedicatedWorker is enabled.
+  std::unique_ptr<WebDedicatedWorkerHostFactoryClient> factory_client_;
+
+  service_manager::mojom::blink::InterfaceProviderPtrInfo interface_provider_;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/workers/dedicated_worker_global_scope.cc b/third_party/blink/renderer/core/workers/dedicated_worker_global_scope.cc
index ef6e451..198a8fb1 100644
--- a/third_party/blink/renderer/core/workers/dedicated_worker_global_scope.cc
+++ b/third_party/blink/renderer/core/workers/dedicated_worker_global_scope.cc
@@ -36,7 +36,7 @@
 #include "third_party/blink/renderer/bindings/core/v8/worker_or_worklet_script_controller.h"
 #include "third_party/blink/renderer/core/execution_context/execution_context.h"
 #include "third_party/blink/renderer/core/frame/csp/content_security_policy.h"
-#include "third_party/blink/renderer/core/inspector/thread_debugger.h"
+#include "third_party/blink/renderer/core/inspector/worker_thread_debugger.h"
 #include "third_party/blink/renderer/core/messaging/post_message_options.h"
 #include "third_party/blink/renderer/core/origin_trials/origin_trial_context.h"
 #include "third_party/blink/renderer/core/script/modulator.h"
@@ -119,7 +119,8 @@
       exception_state);
   if (exception_state.HadException())
     return;
-  ThreadDebugger* debugger = ThreadDebugger::From(script_state->GetIsolate());
+  WorkerThreadDebugger* debugger =
+      WorkerThreadDebugger::From(script_state->GetIsolate());
   transferable_message.sender_stack_trace_id =
       debugger->StoreCurrentStackTrace("postMessage");
   WorkerObjectProxy().PostMessageToWorkerObject(
diff --git a/third_party/blink/renderer/core/workers/worker_global_scope.cc b/third_party/blink/renderer/core/workers/worker_global_scope.cc
index 8af6e1d0..441af372 100644
--- a/third_party/blink/renderer/core/workers/worker_global_scope.cc
+++ b/third_party/blink/renderer/core/workers/worker_global_scope.cc
@@ -342,7 +342,11 @@
     std::unique_ptr<Vector<uint8_t>> cached_meta_data,
     const v8_inspector::V8StackTraceId& stack_id) {
   DCHECK(!IsContextPaused());
-  ThreadDebugger* debugger = ThreadDebugger::From(GetThread()->GetIsolate());
+  CHECK(!GetExecutionContext()->IsContextDestroyed())
+      << "https://crbug.com/930618: worker global scope was destroyed before "
+         "evaluating classic script";
+  WorkerThreadDebugger* debugger =
+      WorkerThreadDebugger::From(GetThread()->GetIsolate());
   if (debugger)
     debugger->ExternalAsyncTaskStarted(stack_id);
   EvaluateClassicScriptInternal(script_url, source_code,
@@ -450,7 +454,8 @@
   DCHECK(!IsContextPaused());
   MessagePortArray* ports =
       MessagePort::EntanglePorts(*this, std::move(message.ports));
-  ThreadDebugger* debugger = ThreadDebugger::From(GetThread()->GetIsolate());
+  WorkerThreadDebugger* debugger =
+      WorkerThreadDebugger::From(GetThread()->GetIsolate());
   if (debugger)
     debugger->ExternalAsyncTaskStarted(message.sender_stack_trace_id);
   UserActivation* user_activation = nullptr;
diff --git a/third_party/blink/renderer/core/workers/worker_thread.cc b/third_party/blink/renderer/core/workers/worker_thread.cc
index f6683ab..a8be3ea 100644
--- a/third_party/blink/renderer/core/workers/worker_thread.cc
+++ b/third_party/blink/renderer/core/workers/worker_thread.cc
@@ -504,9 +504,16 @@
     String source_code,
     std::unique_ptr<Vector<uint8_t>> cached_meta_data,
     const v8_inspector::V8StackTraceId& stack_id) {
-  To<WorkerGlobalScope>(GlobalScope())
-      ->EvaluateClassicScript(script_url, std::move(source_code),
-                              std::move(cached_meta_data), stack_id);
+  // TODO(crbug.com/930618): Remove this check after we identified the cause
+  // of the crash.
+  {
+    MutexLocker lock(mutex_);
+    CHECK_EQ(ThreadState::kRunning, thread_state_);
+  }
+  WorkerGlobalScope* global_scope = To<WorkerGlobalScope>(GlobalScope());
+  CHECK(global_scope);
+  global_scope->EvaluateClassicScript(script_url, std::move(source_code),
+                                      std::move(cached_meta_data), stack_id);
 }
 
 void WorkerThread::ImportClassicScriptOnWorkerThread(
diff --git a/third_party/blink/renderer/devtools/front_end/elements/ComputedStyleWidget.js b/third_party/blink/renderer/devtools/front_end/elements/ComputedStyleWidget.js
index 5ff492a4..43d8b22 100644
--- a/third_party/blink/renderer/devtools/front_end/elements/ComputedStyleWidget.js
+++ b/third_party/blink/renderer/devtools/front_end/elements/ComputedStyleWidget.js
@@ -83,6 +83,14 @@
     fontsWidget.show(this.contentElement);
   }
 
+  /**
+   * @override
+   */
+  onResize() {
+    const isNarrow = this.contentElement.offsetWidth < 260;
+    this._propertiesOutline.contentElement.classList.toggle('computed-narrow', isNarrow);
+  }
+
   _showInheritedComputedStyleChanged() {
     this.update();
   }
diff --git a/third_party/blink/renderer/devtools/front_end/elements/computedStyleWidgetTree.css b/third_party/blink/renderer/devtools/front_end/elements/computedStyleWidgetTree.css
index ef6371b..ae9aa18 100644
--- a/third_party/blink/renderer/devtools/front_end/elements/computedStyleWidgetTree.css
+++ b/third_party/blink/renderer/devtools/front_end/elements/computedStyleWidgetTree.css
@@ -14,8 +14,9 @@
     width: 16em;
     text-overflow: ellipsis;
     overflow: hidden;
-    max-width: 55%;
+    max-width: 52%;
     display: inline-block;
+    vertical-align: text-top;
 }
 
 .computed-style-property .property-value {
@@ -71,7 +72,7 @@
 .property-trace-value {
     position: relative;
     display: inline-block;
-    margin-left: 2em;
+    margin-left: 16px;
 }
 
 .property-trace-inactive .property-trace-value::before {
@@ -109,3 +110,22 @@
 .delimeter::selection {
     color: transparent;
 }
+
+.computed-narrow .computed-style-property .property-name,
+.computed-narrow .computed-style-property .property-value {
+    display: inline-block;
+    width: 100%;
+    max-width: 100%;
+    margin-left: 0;
+    white-space: nowrap;
+}
+
+.computed-narrow .computed-style-property {
+    padding: 2px 0;
+    display: block;
+    white-space: normal;
+}
+
+.computed-narrow.tree-outline li::before {
+    margin-top: -14px;
+}
diff --git a/third_party/blink/renderer/modules/animationworklet/worklet_animation_test.cc b/third_party/blink/renderer/modules/animationworklet/worklet_animation_test.cc
index 0b2acdd..7a2cf2b 100644
--- a/third_party/blink/renderer/modules/animationworklet/worklet_animation_test.cc
+++ b/third_party/blink/renderer/modules/animationworklet/worklet_animation_test.cc
@@ -252,7 +252,7 @@
 
 // Verifies correctness of current time when playback rate is set while the
 // animation is in idle state.
-TEST_F(WorkletAnimationTest, DocumentTimelineSetPlaybackRate) {
+TEST_F(WorkletAnimationTest, DISABLED_DocumentTimelineSetPlaybackRate) {
   double playback_rate = 2.0;
 
   SimulateFrame(111.0);
diff --git a/third_party/blink/renderer/modules/device_orientation/BUILD.gn b/third_party/blink/renderer/modules/device_orientation/BUILD.gn
index 8911217..ff8e1f17 100644
--- a/third_party/blink/renderer/modules/device_orientation/BUILD.gn
+++ b/third_party/blink/renderer/modules/device_orientation/BUILD.gn
@@ -30,6 +30,9 @@
     "device_orientation_inspector_agent.h",
     "device_rotation_rate.cc",
     "device_rotation_rate.h",
+    "device_sensor_entry.cc",
+    "device_sensor_entry.h",
+    "device_sensor_event_pump.cc",
     "device_sensor_event_pump.h",
     "dom_window_device_motion.h",
     "dom_window_device_orientation.h",
diff --git a/third_party/blink/renderer/modules/device_orientation/device_motion_event_pump.cc b/third_party/blink/renderer/modules/device_orientation/device_motion_event_pump.cc
index 29eae48..14f250d 100644
--- a/third_party/blink/renderer/modules/device_orientation/device_motion_event_pump.cc
+++ b/third_party/blink/renderer/modules/device_orientation/device_motion_event_pump.cc
@@ -2,9 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "third_party/blink/renderer/modules/device_orientation/device_motion_event_pump.h"
+
 #include <cmath>
 
-#include "base/auto_reset.h"
+#include "services/device/public/cpp/generic_sensor/sensor_reading.h"
 #include "services/device/public/mojom/sensor.mojom-blink.h"
 #include "services/service_manager/public/cpp/interface_provider.h"
 #include "third_party/blink/renderer/core/dom/document.h"
@@ -12,8 +14,9 @@
 #include "third_party/blink/renderer/core/frame/platform_event_controller.h"
 #include "third_party/blink/renderer/modules/device_orientation/device_acceleration.h"
 #include "third_party/blink/renderer/modules/device_orientation/device_motion_data.h"
-#include "third_party/blink/renderer/modules/device_orientation/device_motion_event_pump.h"
 #include "third_party/blink/renderer/modules/device_orientation/device_rotation_rate.h"
+#include "third_party/blink/renderer/modules/device_orientation/device_sensor_entry.h"
+#include "third_party/blink/renderer/platform/wtf/functional.h"
 #include "ui/gfx/geometry/angle_conversions.h"
 
 namespace {
@@ -27,17 +30,17 @@
 
 DeviceMotionEventPump::DeviceMotionEventPump(
     scoped_refptr<base::SingleThreadTaskRunner> task_runner)
-    : DeviceSensorEventPump(task_runner),
-      accelerometer_(this, device::mojom::blink::SensorType::ACCELEROMETER),
-      linear_acceleration_sensor_(
-          this,
-          device::mojom::blink::SensorType::LINEAR_ACCELERATION),
-      gyroscope_(this, device::mojom::blink::SensorType::GYROSCOPE) {}
-
-DeviceMotionEventPump::~DeviceMotionEventPump() {
-  StopIfObserving();
+    : DeviceSensorEventPump(std::move(task_runner)) {
+  accelerometer_ = MakeGarbageCollected<DeviceSensorEntry>(
+      this, device::mojom::blink::SensorType::ACCELEROMETER);
+  linear_acceleration_sensor_ = MakeGarbageCollected<DeviceSensorEntry>(
+      this, device::mojom::blink::SensorType::LINEAR_ACCELERATION);
+  gyroscope_ = MakeGarbageCollected<DeviceSensorEntry>(
+      this, device::mojom::blink::SensorType::GYROSCOPE);
 }
 
+DeviceMotionEventPump::~DeviceMotionEventPump() = default;
+
 void DeviceMotionEventPump::SetController(PlatformEventController* controller) {
   DCHECK(controller);
   DCHECK(!controller_);
@@ -58,8 +61,12 @@
 }
 
 void DeviceMotionEventPump::Trace(blink::Visitor* visitor) {
+  visitor->Trace(accelerometer_);
+  visitor->Trace(linear_acceleration_sensor_);
+  visitor->Trace(gyroscope_);
   visitor->Trace(data_);
   visitor->Trace(controller_);
+  DeviceSensorEventPump::Trace(visitor);
 }
 
 void DeviceMotionEventPump::StartListening(LocalFrame* frame) {
@@ -77,12 +84,12 @@
         mojo::MakeRequest(&sensor_provider_));
     sensor_provider_.set_connection_error_handler(
         WTF::Bind(&DeviceSensorEventPump::HandleSensorProviderError,
-                  WrapPersistent(this)));
+                  WrapWeakPersistent(this)));
   }
 
-  accelerometer_.Start(sensor_provider_.get());
-  linear_acceleration_sensor_.Start(sensor_provider_.get());
-  gyroscope_.Start(sensor_provider_.get());
+  accelerometer_->Start(sensor_provider_.get());
+  linear_acceleration_sensor_->Start(sensor_provider_.get());
+  gyroscope_->Start(sensor_provider_.get());
 }
 
 void DeviceMotionEventPump::StopListening() {
@@ -96,9 +103,9 @@
   // event listener is more rare than the page visibility changing,
   // Sensor::Suspend() is used to optimize this case for not doing extra work.
 
-  accelerometer_.Stop();
-  linear_acceleration_sensor_.Stop();
-  gyroscope_.Stop();
+  accelerometer_->Stop();
+  linear_acceleration_sensor_->Stop();
+  gyroscope_->Stop();
 }
 
 void DeviceMotionEventPump::NotifyController() {
@@ -117,9 +124,9 @@
 }
 
 bool DeviceMotionEventPump::SensorsReadyOrErrored() const {
-  return accelerometer_.ReadyOrErrored() &&
-         linear_acceleration_sensor_.ReadyOrErrored() &&
-         gyroscope_.ReadyOrErrored();
+  return accelerometer_->ReadyOrErrored() &&
+         linear_acceleration_sensor_->ReadyOrErrored() &&
+         gyroscope_->ReadyOrErrored();
 }
 
 DeviceMotionData* DeviceMotionEventPump::GetDataFromSharedMemory() {
@@ -127,37 +134,41 @@
   DeviceAcceleration* acceleration_including_gravity = nullptr;
   DeviceRotationRate* rotation_rate = nullptr;
 
-  if (accelerometer_.SensorReadingCouldBeRead()) {
-    if (accelerometer_.reading.timestamp() == 0.0)
+  device::SensorReading accelerometer_reading;
+  if (accelerometer_->GetReading(&accelerometer_reading)) {
+    if (accelerometer_reading.timestamp() == 0.0)
       return nullptr;
 
     acceleration_including_gravity = DeviceAcceleration::Create(
-        accelerometer_.reading.accel.x, accelerometer_.reading.accel.y,
-        accelerometer_.reading.accel.z);
+        accelerometer_reading.accel.x, accelerometer_reading.accel.y,
+        accelerometer_reading.accel.z);
   } else {
     acceleration_including_gravity = DeviceAcceleration::Create(NAN, NAN, NAN);
   }
 
-  if (linear_acceleration_sensor_.SensorReadingCouldBeRead()) {
-    if (linear_acceleration_sensor_.reading.timestamp() == 0.0)
+  device::SensorReading linear_acceleration_sensor_reading;
+  if (linear_acceleration_sensor_->GetReading(
+          &linear_acceleration_sensor_reading)) {
+    if (linear_acceleration_sensor_reading.timestamp() == 0.0)
       return nullptr;
 
     acceleration =
-        DeviceAcceleration::Create(linear_acceleration_sensor_.reading.accel.x,
-                                   linear_acceleration_sensor_.reading.accel.y,
-                                   linear_acceleration_sensor_.reading.accel.z);
+        DeviceAcceleration::Create(linear_acceleration_sensor_reading.accel.x,
+                                   linear_acceleration_sensor_reading.accel.y,
+                                   linear_acceleration_sensor_reading.accel.z);
   } else {
     acceleration = DeviceAcceleration::Create(NAN, NAN, NAN);
   }
 
-  if (gyroscope_.SensorReadingCouldBeRead()) {
-    if (gyroscope_.reading.timestamp() == 0.0)
+  device::SensorReading gyroscope_reading;
+  if (gyroscope_->GetReading(&gyroscope_reading)) {
+    if (gyroscope_reading.timestamp() == 0.0)
       return nullptr;
 
     rotation_rate =
-        DeviceRotationRate::Create(gfx::RadToDeg(gyroscope_.reading.gyro.x),
-                                   gfx::RadToDeg(gyroscope_.reading.gyro.y),
-                                   gfx::RadToDeg(gyroscope_.reading.gyro.z));
+        DeviceRotationRate::Create(gfx::RadToDeg(gyroscope_reading.gyro.x),
+                                   gfx::RadToDeg(gyroscope_reading.gyro.y),
+                                   gfx::RadToDeg(gyroscope_reading.gyro.z));
   } else {
     rotation_rate = DeviceRotationRate::Create(NAN, NAN, NAN);
   }
@@ -168,4 +179,5 @@
   return DeviceMotionData::Create(acceleration, acceleration_including_gravity,
                                   rotation_rate, kDefaultPumpDelayMilliseconds);
 }
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/modules/device_orientation/device_motion_event_pump.h b/third_party/blink/renderer/modules/device_orientation/device_motion_event_pump.h
index b9f3017..852ab48 100644
--- a/third_party/blink/renderer/modules/device_orientation/device_motion_event_pump.h
+++ b/third_party/blink/renderer/modules/device_orientation/device_motion_event_pump.h
@@ -13,11 +13,14 @@
 namespace blink {
 
 class DeviceMotionData;
+class DeviceSensorEntry;
 class PlatformEventController;
 
 class MODULES_EXPORT DeviceMotionEventPump
     : public GarbageCollectedFinalized<DeviceMotionEventPump>,
       public DeviceSensorEventPump {
+  USING_GARBAGE_COLLECTED_MIXIN(DeviceMotionEventPump);
+
  public:
   explicit DeviceMotionEventPump(scoped_refptr<base::SingleThreadTaskRunner>);
   ~DeviceMotionEventPump() override;
@@ -28,7 +31,7 @@
   // Note that the returned object is owned by this class.
   DeviceMotionData* LatestDeviceMotionData();
 
-  void Trace(blink::Visitor*);
+  void Trace(blink::Visitor*) override;
 
   // DeviceSensorEventPump:
   void SendStartMessage(LocalFrame* frame) override;
@@ -38,9 +41,9 @@
   // DeviceSensorEventPump:
   void FireEvent(TimerBase*) override;
 
-  SensorEntry accelerometer_;
-  SensorEntry linear_acceleration_sensor_;
-  SensorEntry gyroscope_;
+  Member<DeviceSensorEntry> accelerometer_;
+  Member<DeviceSensorEntry> linear_acceleration_sensor_;
+  Member<DeviceSensorEntry> gyroscope_;
 
  private:
   friend class DeviceMotionEventPumpTest;
diff --git a/third_party/blink/renderer/modules/device_orientation/device_motion_event_pump_unittest.cc b/third_party/blink/renderer/modules/device_orientation/device_motion_event_pump_unittest.cc
index 4117da4..c5e9835 100644
--- a/third_party/blink/renderer/modules/device_orientation/device_motion_event_pump_unittest.cc
+++ b/third_party/blink/renderer/modules/device_orientation/device_motion_event_pump_unittest.cc
@@ -15,6 +15,7 @@
 #include "third_party/blink/renderer/modules/device_orientation/device_motion_data.h"
 #include "third_party/blink/renderer/modules/device_orientation/device_motion_event_pump.h"
 #include "third_party/blink/renderer/modules/device_orientation/device_rotation_rate.h"
+#include "third_party/blink/renderer/modules/device_orientation/device_sensor_entry.h"
 #include "third_party/blink/renderer/platform/heap/persistent.h"
 #include "ui/gfx/geometry/angle_conversions.h"
 
@@ -86,8 +87,7 @@
 
     controller_ = MakeGarbageCollected<MockDeviceMotionController>(motion_pump);
 
-    ExpectAllThreeSensorsStateToBe(
-        DeviceMotionEventPump::SensorState::NOT_INITIALIZED);
+    ExpectAllThreeSensorsStateToBe(DeviceSensorEntry::State::NOT_INITIALIZED);
     EXPECT_EQ(DeviceMotionEventPump::PumpState::STOPPED,
               controller_->motion_pump()->GetPumpStateForTesting());
   }
@@ -95,26 +95,25 @@
   void FireEvent() { controller_->motion_pump()->FireEvent(nullptr); }
 
   void ExpectAccelerometerStateToBe(
-      DeviceMotionEventPump::SensorState expected_sensor_state) {
+      DeviceSensorEntry::State expected_sensor_state) {
     EXPECT_EQ(expected_sensor_state,
-              controller_->motion_pump()->accelerometer_.sensor_state);
+              controller_->motion_pump()->accelerometer_->state());
   }
 
   void ExpectLinearAccelerationSensorStateToBe(
-      DeviceMotionEventPump::SensorState expected_sensor_state) {
-    EXPECT_EQ(
-        expected_sensor_state,
-        controller_->motion_pump()->linear_acceleration_sensor_.sensor_state);
+      DeviceSensorEntry::State expected_sensor_state) {
+    EXPECT_EQ(expected_sensor_state,
+              controller_->motion_pump()->linear_acceleration_sensor_->state());
   }
 
   void ExpectGyroscopeStateToBe(
-      DeviceMotionEventPump::SensorState expected_sensor_state) {
+      DeviceSensorEntry::State expected_sensor_state) {
     EXPECT_EQ(expected_sensor_state,
-              controller_->motion_pump()->gyroscope_.sensor_state);
+              controller_->motion_pump()->gyroscope_->state());
   }
 
   void ExpectAllThreeSensorsStateToBe(
-      DeviceMotionEventPump::SensorState expected_sensor_state) {
+      DeviceSensorEntry::State expected_sensor_state) {
     ExpectAccelerometerStateToBe(expected_sensor_state);
     ExpectLinearAccelerationSensorStateToBe(expected_sensor_state);
     ExpectGyroscopeStateToBe(expected_sensor_state);
@@ -136,28 +135,28 @@
   controller()->motion_pump()->Start(nullptr);
   base::RunLoop().RunUntilIdle();
 
-  ExpectAllThreeSensorsStateToBe(DeviceMotionEventPump::SensorState::ACTIVE);
+  ExpectAllThreeSensorsStateToBe(DeviceSensorEntry::State::ACTIVE);
   EXPECT_EQ(DeviceMotionEventPump::PumpState::RUNNING,
             controller()->motion_pump()->GetPumpStateForTesting());
 
   controller()->motion_pump()->Stop();
   base::RunLoop().RunUntilIdle();
 
-  ExpectAllThreeSensorsStateToBe(DeviceMotionEventPump::SensorState::SUSPENDED);
+  ExpectAllThreeSensorsStateToBe(DeviceSensorEntry::State::SUSPENDED);
   EXPECT_EQ(DeviceMotionEventPump::PumpState::STOPPED,
             controller()->motion_pump()->GetPumpStateForTesting());
 
   controller()->motion_pump()->Start(nullptr);
   base::RunLoop().RunUntilIdle();
 
-  ExpectAllThreeSensorsStateToBe(DeviceMotionEventPump::SensorState::ACTIVE);
+  ExpectAllThreeSensorsStateToBe(DeviceSensorEntry::State::ACTIVE);
   EXPECT_EQ(DeviceMotionEventPump::PumpState::RUNNING,
             controller()->motion_pump()->GetPumpStateForTesting());
 
   controller()->motion_pump()->Stop();
   base::RunLoop().RunUntilIdle();
 
-  ExpectAllThreeSensorsStateToBe(DeviceMotionEventPump::SensorState::SUSPENDED);
+  ExpectAllThreeSensorsStateToBe(DeviceSensorEntry::State::SUSPENDED);
   EXPECT_EQ(DeviceMotionEventPump::PumpState::STOPPED,
             controller()->motion_pump()->GetPumpStateForTesting());
 }
@@ -166,8 +165,7 @@
   controller()->motion_pump()->Stop();
   base::RunLoop().RunUntilIdle();
 
-  ExpectAllThreeSensorsStateToBe(
-      DeviceMotionEventPump::SensorState::NOT_INITIALIZED);
+  ExpectAllThreeSensorsStateToBe(DeviceSensorEntry::State::NOT_INITIALIZED);
 }
 
 TEST_F(DeviceMotionEventPumpTest, CallStartAndStop) {
@@ -175,7 +173,7 @@
   controller()->motion_pump()->Stop();
   base::RunLoop().RunUntilIdle();
 
-  ExpectAllThreeSensorsStateToBe(DeviceMotionEventPump::SensorState::SUSPENDED);
+  ExpectAllThreeSensorsStateToBe(DeviceSensorEntry::State::SUSPENDED);
 }
 
 TEST_F(DeviceMotionEventPumpTest, CallStartMultipleTimes) {
@@ -184,7 +182,7 @@
   controller()->motion_pump()->Stop();
   base::RunLoop().RunUntilIdle();
 
-  ExpectAllThreeSensorsStateToBe(DeviceMotionEventPump::SensorState::SUSPENDED);
+  ExpectAllThreeSensorsStateToBe(DeviceSensorEntry::State::SUSPENDED);
 }
 
 TEST_F(DeviceMotionEventPumpTest, CallStopMultipleTimes) {
@@ -193,7 +191,7 @@
   controller()->motion_pump()->Stop();
   base::RunLoop().RunUntilIdle();
 
-  ExpectAllThreeSensorsStateToBe(DeviceMotionEventPump::SensorState::SUSPENDED);
+  ExpectAllThreeSensorsStateToBe(DeviceSensorEntry::State::SUSPENDED);
 }
 
 // Test multiple DeviceSensorEventPump::Start() calls only bind sensor once.
@@ -203,11 +201,11 @@
   controller()->motion_pump()->Start(nullptr);
   base::RunLoop().RunUntilIdle();
 
-  ExpectAllThreeSensorsStateToBe(DeviceMotionEventPump::SensorState::ACTIVE);
+  ExpectAllThreeSensorsStateToBe(DeviceSensorEntry::State::ACTIVE);
 
   controller()->motion_pump()->Stop();
 
-  ExpectAllThreeSensorsStateToBe(DeviceMotionEventPump::SensorState::SUSPENDED);
+  ExpectAllThreeSensorsStateToBe(DeviceSensorEntry::State::SUSPENDED);
 }
 
 TEST_F(DeviceMotionEventPumpTest, AllSensorsAreActive) {
@@ -215,7 +213,7 @@
   controller()->motion_pump()->Start(nullptr);
   base::RunLoop().RunUntilIdle();
 
-  ExpectAllThreeSensorsStateToBe(DeviceMotionEventPump::SensorState::ACTIVE);
+  ExpectAllThreeSensorsStateToBe(DeviceSensorEntry::State::ACTIVE);
 
   sensor_provider()->UpdateAccelerometerData(1, 2, 3);
   sensor_provider()->UpdateLinearAccelerationSensorData(4, 5, 6);
@@ -257,7 +255,7 @@
 
   controller()->motion_pump()->Stop();
 
-  ExpectAllThreeSensorsStateToBe(DeviceMotionEventPump::SensorState::SUSPENDED);
+  ExpectAllThreeSensorsStateToBe(DeviceSensorEntry::State::SUSPENDED);
 }
 
 TEST_F(DeviceMotionEventPumpTest, TwoSensorsAreActive) {
@@ -267,10 +265,10 @@
   controller()->motion_pump()->Start(nullptr);
   base::RunLoop().RunUntilIdle();
 
-  ExpectAccelerometerStateToBe(DeviceMotionEventPump::SensorState::ACTIVE);
+  ExpectAccelerometerStateToBe(DeviceSensorEntry::State::ACTIVE);
   ExpectLinearAccelerationSensorStateToBe(
-      DeviceMotionEventPump::SensorState::NOT_INITIALIZED);
-  ExpectGyroscopeStateToBe(DeviceMotionEventPump::SensorState::ACTIVE);
+      DeviceSensorEntry::State::NOT_INITIALIZED);
+  ExpectGyroscopeStateToBe(DeviceSensorEntry::State::ACTIVE);
 
   sensor_provider()->UpdateAccelerometerData(1, 2, 3);
   sensor_provider()->UpdateGyroscopeData(7, 8, 9);
@@ -310,10 +308,10 @@
 
   controller()->motion_pump()->Stop();
 
-  ExpectAccelerometerStateToBe(DeviceMotionEventPump::SensorState::SUSPENDED);
+  ExpectAccelerometerStateToBe(DeviceSensorEntry::State::SUSPENDED);
   ExpectLinearAccelerationSensorStateToBe(
-      DeviceMotionEventPump::SensorState::NOT_INITIALIZED);
-  ExpectGyroscopeStateToBe(DeviceMotionEventPump::SensorState::SUSPENDED);
+      DeviceSensorEntry::State::NOT_INITIALIZED);
+  ExpectGyroscopeStateToBe(DeviceSensorEntry::State::SUSPENDED);
 }
 
 TEST_F(DeviceMotionEventPumpTest, SomeSensorDataFieldsNotAvailable) {
@@ -321,7 +319,7 @@
   controller()->motion_pump()->Start(nullptr);
   base::RunLoop().RunUntilIdle();
 
-  ExpectAllThreeSensorsStateToBe(DeviceMotionEventPump::SensorState::ACTIVE);
+  ExpectAllThreeSensorsStateToBe(DeviceSensorEntry::State::ACTIVE);
 
   sensor_provider()->UpdateAccelerometerData(NAN, 2, 3);
   sensor_provider()->UpdateLinearAccelerationSensorData(4, NAN, 6);
@@ -359,7 +357,7 @@
 
   controller()->motion_pump()->Stop();
 
-  ExpectAllThreeSensorsStateToBe(DeviceMotionEventPump::SensorState::SUSPENDED);
+  ExpectAllThreeSensorsStateToBe(DeviceSensorEntry::State::SUSPENDED);
 }
 
 TEST_F(DeviceMotionEventPumpTest, FireAllNullEvent) {
@@ -372,8 +370,7 @@
   controller()->motion_pump()->Start(nullptr);
   base::RunLoop().RunUntilIdle();
 
-  ExpectAllThreeSensorsStateToBe(
-      DeviceMotionEventPump::SensorState::NOT_INITIALIZED);
+  ExpectAllThreeSensorsStateToBe(DeviceSensorEntry::State::NOT_INITIALIZED);
 
   FireEvent();
 
@@ -389,8 +386,7 @@
 
   controller()->motion_pump()->Stop();
 
-  ExpectAllThreeSensorsStateToBe(
-      DeviceMotionEventPump::SensorState::NOT_INITIALIZED);
+  ExpectAllThreeSensorsStateToBe(DeviceSensorEntry::State::NOT_INITIALIZED);
 }
 
 TEST_F(DeviceMotionEventPumpTest,
@@ -399,7 +395,7 @@
   controller()->motion_pump()->Start(nullptr);
   base::RunLoop().RunUntilIdle();
 
-  ExpectAllThreeSensorsStateToBe(DeviceMotionEventPump::SensorState::ACTIVE);
+  ExpectAllThreeSensorsStateToBe(DeviceSensorEntry::State::ACTIVE);
 
   FireEvent();
   EXPECT_FALSE(controller()->did_change_device_motion());
@@ -419,7 +415,7 @@
 
   controller()->motion_pump()->Stop();
 
-  ExpectAllThreeSensorsStateToBe(DeviceMotionEventPump::SensorState::SUSPENDED);
+  ExpectAllThreeSensorsStateToBe(DeviceSensorEntry::State::SUSPENDED);
 }
 
 // Confirm that the frequency of pumping events is not greater than 60Hz.
@@ -434,7 +430,7 @@
   controller()->motion_pump()->Start(nullptr);
   base::RunLoop().RunUntilIdle();
 
-  ExpectAllThreeSensorsStateToBe(DeviceMotionEventPump::SensorState::ACTIVE);
+  ExpectAllThreeSensorsStateToBe(DeviceSensorEntry::State::ACTIVE);
 
   sensor_provider()->UpdateAccelerometerData(1, 2, 3);
   sensor_provider()->UpdateLinearAccelerationSensorData(4, 5, 6);
@@ -447,7 +443,7 @@
   loop.Run();
   controller()->motion_pump()->Stop();
 
-  ExpectAllThreeSensorsStateToBe(DeviceMotionEventPump::SensorState::SUSPENDED);
+  ExpectAllThreeSensorsStateToBe(DeviceSensorEntry::State::SUSPENDED);
 
   // Check that the PlatformEventController does not receive excess
   // events.
diff --git a/third_party/blink/renderer/modules/device_orientation/device_orientation_event_pump.cc b/third_party/blink/renderer/modules/device_orientation/device_orientation_event_pump.cc
index 145c861..97eb84c 100644
--- a/third_party/blink/renderer/modules/device_orientation/device_orientation_event_pump.cc
+++ b/third_party/blink/renderer/modules/device_orientation/device_orientation_event_pump.cc
@@ -2,14 +2,18 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "third_party/blink/renderer/modules/device_orientation/device_orientation_event_pump.h"
+
 #include <cmath>
 
+#include "services/device/public/cpp/generic_sensor/sensor_reading.h"
 #include "services/device/public/mojom/sensor.mojom-blink.h"
 #include "services/service_manager/public/cpp/interface_provider.h"
 #include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/modules/device_orientation/device_orientation_data.h"
-#include "third_party/blink/renderer/modules/device_orientation/device_orientation_event_pump.h"
+#include "third_party/blink/renderer/modules/device_orientation/device_sensor_entry.h"
 #include "third_party/blink/renderer/platform/heap/persistent.h"
+#include "third_party/blink/renderer/platform/wtf/functional.h"
 
 namespace {
 
@@ -41,26 +45,25 @@
 DeviceOrientationEventPump::DeviceOrientationEventPump(
     scoped_refptr<base::SingleThreadTaskRunner> task_runner,
     bool absolute)
-    : DeviceSensorEventPump(task_runner),
-      relative_orientation_sensor_(
-          this,
-          device::mojom::SensorType::RELATIVE_ORIENTATION_EULER_ANGLES),
-      absolute_orientation_sensor_(
-          this,
-          device::mojom::SensorType::ABSOLUTE_ORIENTATION_EULER_ANGLES),
+    : DeviceSensorEventPump(std::move(task_runner)),
       absolute_(absolute),
-      fall_back_to_absolute_orientation_sensor_(!absolute) {}
-
-DeviceOrientationEventPump::~DeviceOrientationEventPump() {
-  StopIfObserving();
+      fall_back_to_absolute_orientation_sensor_(!absolute) {
+  relative_orientation_sensor_ = MakeGarbageCollected<DeviceSensorEntry>(
+      this, device::mojom::SensorType::RELATIVE_ORIENTATION_EULER_ANGLES);
+  absolute_orientation_sensor_ = MakeGarbageCollected<DeviceSensorEntry>(
+      this, device::mojom::SensorType::ABSOLUTE_ORIENTATION_EULER_ANGLES);
 }
 
+DeviceOrientationEventPump::~DeviceOrientationEventPump() = default;
+
 DeviceOrientationData*
 DeviceOrientationEventPump::LatestDeviceOrientationData() {
   return data_.Get();
 }
 
 void DeviceOrientationEventPump::Trace(blink::Visitor* visitor) {
+  visitor->Trace(relative_orientation_sensor_);
+  visitor->Trace(absolute_orientation_sensor_);
   visitor->Trace(data_);
   PlatformEventDispatcher::Trace(visitor);
 }
@@ -80,15 +83,15 @@
         mojo::MakeRequest(&sensor_provider_));
     sensor_provider_.set_connection_error_handler(
         WTF::Bind(&DeviceSensorEventPump::HandleSensorProviderError,
-                  WrapPersistent(this)));
+                  WrapWeakPersistent(this)));
   }
 
   if (absolute_) {
-    absolute_orientation_sensor_.Start(sensor_provider_.get());
+    absolute_orientation_sensor_->Start(sensor_provider_.get());
   } else {
     fall_back_to_absolute_orientation_sensor_ = true;
     should_suspend_absolute_orientation_sensor_ = false;
-    relative_orientation_sensor_.Start(sensor_provider_.get());
+    relative_orientation_sensor_->Start(sensor_provider_.get());
   }
 }
 
@@ -103,7 +106,7 @@
   // the event listener is more rare than the page visibility changing,
   // Sensor::Suspend() is used to optimize this case for not doing extra work.
 
-  relative_orientation_sensor_.Stop();
+  relative_orientation_sensor_->Stop();
   // This is needed in case we fallback to using the absolute orientation
   // sensor. In this case, the relative orientation sensor is marked as
   // SensorState::SHOULD_SUSPEND, and if the relative orientation sensor
@@ -112,13 +115,13 @@
   // absolute_orientation_sensor_.Start() is called for initializing
   // the absolute orientation sensor in
   // DeviceOrientationEventPump::DidStartIfPossible().
-  if (relative_orientation_sensor_.sensor_state ==
-          SensorState::SHOULD_SUSPEND &&
+  if (relative_orientation_sensor_->state() ==
+          DeviceSensorEntry::State::SHOULD_SUSPEND &&
       fall_back_to_absolute_orientation_sensor_) {
     should_suspend_absolute_orientation_sensor_ = true;
   }
 
-  absolute_orientation_sensor_.Stop();
+  absolute_orientation_sensor_->Stop();
 
   // Reset the cached data because DeviceOrientationDispatcher resets its
   // data when stopping. If we don't reset here as well, then when starting back
@@ -137,16 +140,16 @@
 }
 
 void DeviceOrientationEventPump::DidStartIfPossible() {
-  if (!absolute_ && !relative_orientation_sensor_.sensor &&
+  if (!absolute_ && !relative_orientation_sensor_->IsConnected() &&
       fall_back_to_absolute_orientation_sensor_ && sensor_provider_) {
     // When relative orientation sensor is not available fall back to using
     // the absolute orientation sensor but only on the first failure.
     fall_back_to_absolute_orientation_sensor_ = false;
-    absolute_orientation_sensor_.Start(sensor_provider_.get());
+    absolute_orientation_sensor_->Start(sensor_provider_.get());
     if (should_suspend_absolute_orientation_sensor_) {
       // The absolute orientation sensor needs to be marked as
       // SensorState::SUSPENDED when it is successfully initialized.
-      absolute_orientation_sensor_.sensor_state = SensorState::SHOULD_SUSPEND;
+      absolute_orientation_sensor_->Stop();
       should_suspend_absolute_orientation_sensor_ = false;
     }
     return;
@@ -155,14 +158,14 @@
 }
 
 bool DeviceOrientationEventPump::SensorsReadyOrErrored() const {
-  if (!relative_orientation_sensor_.ReadyOrErrored() ||
-      !absolute_orientation_sensor_.ReadyOrErrored()) {
+  if (!relative_orientation_sensor_->ReadyOrErrored() ||
+      !absolute_orientation_sensor_->ReadyOrErrored()) {
     return false;
   }
 
   // At most one sensor can be successfully initialized.
-  DCHECK(!relative_orientation_sensor_.sensor ||
-         !absolute_orientation_sensor_.sensor);
+  DCHECK(!relative_orientation_sensor_->IsConnected() ||
+         !absolute_orientation_sensor_->IsConnected());
 
   return true;
 }
@@ -172,49 +175,33 @@
   base::Optional<double> beta;
   base::Optional<double> gamma;
   bool absolute = false;
+  bool got_reading = false;
+  device::SensorReading reading;
 
-  if (!absolute_ && relative_orientation_sensor_.SensorReadingCouldBeRead()) {
-    // For DeviceOrientation Event, this provides relative orientation data.
-    if (relative_orientation_sensor_.reading.timestamp() == 0.0)
-      return nullptr;
-
-    if (!std::isnan(
-            relative_orientation_sensor_.reading.orientation_euler.z.value()))
-      alpha = relative_orientation_sensor_.reading.orientation_euler.z;
-
-    if (!std::isnan(
-            relative_orientation_sensor_.reading.orientation_euler.x.value()))
-      beta = relative_orientation_sensor_.reading.orientation_euler.x;
-
-    if (!std::isnan(
-            relative_orientation_sensor_.reading.orientation_euler.y.value()))
-      gamma = relative_orientation_sensor_.reading.orientation_euler.y;
-  } else if (absolute_orientation_sensor_.SensorReadingCouldBeRead()) {
-    // For DeviceOrientationAbsolute Event, this provides absolute orientation
-    // data.
-    //
-    // For DeviceOrientation Event, this provides absolute orientation data if
-    // relative orientation data is not available.
-    if (absolute_orientation_sensor_.reading.timestamp() == 0.0)
-      return nullptr;
-
-    if (!std::isnan(
-            absolute_orientation_sensor_.reading.orientation_euler.z.value()))
-      alpha = absolute_orientation_sensor_.reading.orientation_euler.z;
-
-    if (!std::isnan(
-            absolute_orientation_sensor_.reading.orientation_euler.x.value()))
-      beta = absolute_orientation_sensor_.reading.orientation_euler.x;
-
-    if (!std::isnan(
-            absolute_orientation_sensor_.reading.orientation_euler.y.value()))
-      gamma = absolute_orientation_sensor_.reading.orientation_euler.y;
-
+  if (!absolute_ && relative_orientation_sensor_->GetReading(&reading)) {
+    got_reading = true;
+  } else if (absolute_orientation_sensor_->GetReading(&reading)) {
+    got_reading = true;
     absolute = true;
   } else {
     absolute = absolute_;
   }
 
+  if (got_reading) {
+    // For DeviceOrientation Event, this provides relative orientation data.
+    if (reading.timestamp() == 0.0)
+      return nullptr;
+
+    if (!std::isnan(reading.orientation_euler.z.value()))
+      alpha = reading.orientation_euler.z;
+
+    if (!std::isnan(reading.orientation_euler.x.value()))
+      beta = reading.orientation_euler.x;
+
+    if (!std::isnan(reading.orientation_euler.y.value()))
+      gamma = reading.orientation_euler.y;
+  }
+
   return DeviceOrientationData::Create(alpha, beta, gamma, absolute);
 }
 
diff --git a/third_party/blink/renderer/modules/device_orientation/device_orientation_event_pump.h b/third_party/blink/renderer/modules/device_orientation/device_orientation_event_pump.h
index fca10da..886e232 100644
--- a/third_party/blink/renderer/modules/device_orientation/device_orientation_event_pump.h
+++ b/third_party/blink/renderer/modules/device_orientation/device_orientation_event_pump.h
@@ -13,6 +13,9 @@
 
 namespace blink {
 
+class DeviceOrientationData;
+class DeviceSensorEntry;
+
 class MODULES_EXPORT DeviceOrientationEventPump
     : public GarbageCollectedFinalized<DeviceOrientationEventPump>,
       public DeviceSensorEventPump,
@@ -27,7 +30,6 @@
   explicit DeviceOrientationEventPump(
       scoped_refptr<base::SingleThreadTaskRunner> task_runner,
       bool absolute);
-
   ~DeviceOrientationEventPump() override;
 
   // Note that the returned object is owned by this class.
@@ -44,8 +46,8 @@
   void FireEvent(TimerBase*) override;
   void DidStartIfPossible() override;
 
-  SensorEntry relative_orientation_sensor_;
-  SensorEntry absolute_orientation_sensor_;
+  Member<DeviceSensorEntry> relative_orientation_sensor_;
+  Member<DeviceSensorEntry> absolute_orientation_sensor_;
 
  private:
   friend class DeviceOrientationEventPumpTest;
diff --git a/third_party/blink/renderer/modules/device_orientation/device_orientation_event_pump_unittest.cc b/third_party/blink/renderer/modules/device_orientation/device_orientation_event_pump_unittest.cc
index 7c3d3b4..84fd2ce 100644
--- a/third_party/blink/renderer/modules/device_orientation/device_orientation_event_pump_unittest.cc
+++ b/third_party/blink/renderer/modules/device_orientation/device_orientation_event_pump_unittest.cc
@@ -13,6 +13,7 @@
 #include "third_party/blink/renderer/core/frame/platform_event_controller.h"
 #include "third_party/blink/renderer/modules/device_orientation/device_orientation_data.h"
 #include "third_party/blink/renderer/modules/device_orientation/device_orientation_event_pump.h"
+#include "third_party/blink/renderer/modules/device_orientation/device_sensor_entry.h"
 #include "third_party/blink/renderer/platform/heap/persistent.h"
 
 namespace {
@@ -99,9 +100,9 @@
         MakeGarbageCollected<MockDeviceOrientationController>(orientation_pump);
 
     ExpectRelativeOrientationSensorStateToBe(
-        DeviceOrientationEventPump::SensorState::NOT_INITIALIZED);
+        DeviceSensorEntry::State::NOT_INITIALIZED);
     ExpectAbsoluteOrientationSensorStateToBe(
-        DeviceOrientationEventPump::SensorState::NOT_INITIALIZED);
+        DeviceSensorEntry::State::NOT_INITIALIZED);
     EXPECT_EQ(DeviceOrientationEventPump::PumpState::STOPPED,
               controller_->orientation_pump()->GetPumpStateForTesting());
   }
@@ -109,17 +110,17 @@
   void FireEvent() { controller_->orientation_pump()->FireEvent(nullptr); }
 
   void ExpectRelativeOrientationSensorStateToBe(
-      DeviceOrientationEventPump::SensorState expected_sensor_state) {
-    EXPECT_EQ(expected_sensor_state,
-              controller_->orientation_pump()
-                  ->relative_orientation_sensor_.sensor_state);
+      DeviceSensorEntry::State expected_sensor_state) {
+    EXPECT_EQ(
+        expected_sensor_state,
+        controller_->orientation_pump()->relative_orientation_sensor_->state());
   }
 
   void ExpectAbsoluteOrientationSensorStateToBe(
-      DeviceOrientationEventPump::SensorState expected_sensor_state) {
-    EXPECT_EQ(expected_sensor_state,
-              controller_->orientation_pump()
-                  ->absolute_orientation_sensor_.sensor_state);
+      DeviceSensorEntry::State expected_sensor_state) {
+    EXPECT_EQ(
+        expected_sensor_state,
+        controller_->orientation_pump()->absolute_orientation_sensor_->state());
   }
 
   MockDeviceOrientationController* controller() { return controller_.Get(); }
@@ -137,32 +138,28 @@
   controller()->orientation_pump()->Start(nullptr);
   base::RunLoop().RunUntilIdle();
 
-  ExpectRelativeOrientationSensorStateToBe(
-      DeviceOrientationEventPump::SensorState::ACTIVE);
+  ExpectRelativeOrientationSensorStateToBe(DeviceSensorEntry::State::ACTIVE);
   EXPECT_EQ(DeviceOrientationEventPump::PumpState::RUNNING,
             controller()->orientation_pump()->GetPumpStateForTesting());
 
   controller()->orientation_pump()->Stop();
   base::RunLoop().RunUntilIdle();
 
-  ExpectRelativeOrientationSensorStateToBe(
-      DeviceOrientationEventPump::SensorState::SUSPENDED);
+  ExpectRelativeOrientationSensorStateToBe(DeviceSensorEntry::State::SUSPENDED);
   EXPECT_EQ(DeviceOrientationEventPump::PumpState::STOPPED,
             controller()->orientation_pump()->GetPumpStateForTesting());
 
   controller()->orientation_pump()->Start(nullptr);
   base::RunLoop().RunUntilIdle();
 
-  ExpectRelativeOrientationSensorStateToBe(
-      DeviceOrientationEventPump::SensorState::ACTIVE);
+  ExpectRelativeOrientationSensorStateToBe(DeviceSensorEntry::State::ACTIVE);
   EXPECT_EQ(DeviceOrientationEventPump::PumpState::RUNNING,
             controller()->orientation_pump()->GetPumpStateForTesting());
 
   controller()->orientation_pump()->Stop();
   base::RunLoop().RunUntilIdle();
 
-  ExpectRelativeOrientationSensorStateToBe(
-      DeviceOrientationEventPump::SensorState::SUSPENDED);
+  ExpectRelativeOrientationSensorStateToBe(DeviceSensorEntry::State::SUSPENDED);
   EXPECT_EQ(DeviceOrientationEventPump::PumpState::STOPPED,
             controller()->orientation_pump()->GetPumpStateForTesting());
 }
@@ -175,9 +172,8 @@
   base::RunLoop().RunUntilIdle();
 
   ExpectRelativeOrientationSensorStateToBe(
-      DeviceOrientationEventPump::SensorState::NOT_INITIALIZED);
-  ExpectAbsoluteOrientationSensorStateToBe(
-      DeviceOrientationEventPump::SensorState::ACTIVE);
+      DeviceSensorEntry::State::NOT_INITIALIZED);
+  ExpectAbsoluteOrientationSensorStateToBe(DeviceSensorEntry::State::ACTIVE);
   EXPECT_EQ(DeviceOrientationEventPump::PumpState::RUNNING,
             controller()->orientation_pump()->GetPumpStateForTesting());
 
@@ -185,9 +181,8 @@
   base::RunLoop().RunUntilIdle();
 
   ExpectRelativeOrientationSensorStateToBe(
-      DeviceOrientationEventPump::SensorState::NOT_INITIALIZED);
-  ExpectAbsoluteOrientationSensorStateToBe(
-      DeviceOrientationEventPump::SensorState::SUSPENDED);
+      DeviceSensorEntry::State::NOT_INITIALIZED);
+  ExpectAbsoluteOrientationSensorStateToBe(DeviceSensorEntry::State::SUSPENDED);
   EXPECT_EQ(DeviceOrientationEventPump::PumpState::STOPPED,
             controller()->orientation_pump()->GetPumpStateForTesting());
 
@@ -195,9 +190,8 @@
   base::RunLoop().RunUntilIdle();
 
   ExpectRelativeOrientationSensorStateToBe(
-      DeviceOrientationEventPump::SensorState::NOT_INITIALIZED);
-  ExpectAbsoluteOrientationSensorStateToBe(
-      DeviceOrientationEventPump::SensorState::ACTIVE);
+      DeviceSensorEntry::State::NOT_INITIALIZED);
+  ExpectAbsoluteOrientationSensorStateToBe(DeviceSensorEntry::State::ACTIVE);
   EXPECT_EQ(DeviceOrientationEventPump::PumpState::RUNNING,
             controller()->orientation_pump()->GetPumpStateForTesting());
 
@@ -205,9 +199,8 @@
   base::RunLoop().RunUntilIdle();
 
   ExpectRelativeOrientationSensorStateToBe(
-      DeviceOrientationEventPump::SensorState::NOT_INITIALIZED);
-  ExpectAbsoluteOrientationSensorStateToBe(
-      DeviceOrientationEventPump::SensorState::SUSPENDED);
+      DeviceSensorEntry::State::NOT_INITIALIZED);
+  ExpectAbsoluteOrientationSensorStateToBe(DeviceSensorEntry::State::SUSPENDED);
   EXPECT_EQ(DeviceOrientationEventPump::PumpState::STOPPED,
             controller()->orientation_pump()->GetPumpStateForTesting());
 }
@@ -217,7 +210,7 @@
   base::RunLoop().RunUntilIdle();
 
   ExpectRelativeOrientationSensorStateToBe(
-      DeviceOrientationEventPump::SensorState::NOT_INITIALIZED);
+      DeviceSensorEntry::State::NOT_INITIALIZED);
 }
 
 TEST_F(DeviceOrientationEventPumpTest, CallStopWithSensorFallback) {
@@ -227,9 +220,9 @@
   base::RunLoop().RunUntilIdle();
 
   ExpectRelativeOrientationSensorStateToBe(
-      DeviceOrientationEventPump::SensorState::NOT_INITIALIZED);
+      DeviceSensorEntry::State::NOT_INITIALIZED);
   ExpectAbsoluteOrientationSensorStateToBe(
-      DeviceOrientationEventPump::SensorState::NOT_INITIALIZED);
+      DeviceSensorEntry::State::NOT_INITIALIZED);
 }
 
 TEST_F(DeviceOrientationEventPumpTest, CallStartAndStop) {
@@ -237,8 +230,7 @@
   controller()->orientation_pump()->Stop();
   base::RunLoop().RunUntilIdle();
 
-  ExpectRelativeOrientationSensorStateToBe(
-      DeviceOrientationEventPump::SensorState::SUSPENDED);
+  ExpectRelativeOrientationSensorStateToBe(DeviceSensorEntry::State::SUSPENDED);
 }
 
 TEST_F(DeviceOrientationEventPumpTest, CallStartAndStopWithSensorFallback) {
@@ -249,9 +241,8 @@
   base::RunLoop().RunUntilIdle();
 
   ExpectRelativeOrientationSensorStateToBe(
-      DeviceOrientationEventPump::SensorState::NOT_INITIALIZED);
-  ExpectAbsoluteOrientationSensorStateToBe(
-      DeviceOrientationEventPump::SensorState::SUSPENDED);
+      DeviceSensorEntry::State::NOT_INITIALIZED);
+  ExpectAbsoluteOrientationSensorStateToBe(DeviceSensorEntry::State::SUSPENDED);
 }
 
 TEST_F(DeviceOrientationEventPumpTest, CallStartMultipleTimes) {
@@ -260,8 +251,7 @@
   controller()->orientation_pump()->Stop();
   base::RunLoop().RunUntilIdle();
 
-  ExpectRelativeOrientationSensorStateToBe(
-      DeviceOrientationEventPump::SensorState::SUSPENDED);
+  ExpectRelativeOrientationSensorStateToBe(DeviceSensorEntry::State::SUSPENDED);
 }
 
 TEST_F(DeviceOrientationEventPumpTest,
@@ -274,9 +264,8 @@
   base::RunLoop().RunUntilIdle();
 
   ExpectRelativeOrientationSensorStateToBe(
-      DeviceOrientationEventPump::SensorState::NOT_INITIALIZED);
-  ExpectAbsoluteOrientationSensorStateToBe(
-      DeviceOrientationEventPump::SensorState::SUSPENDED);
+      DeviceSensorEntry::State::NOT_INITIALIZED);
+  ExpectAbsoluteOrientationSensorStateToBe(DeviceSensorEntry::State::SUSPENDED);
 }
 
 TEST_F(DeviceOrientationEventPumpTest, CallStopMultipleTimes) {
@@ -285,8 +274,7 @@
   controller()->orientation_pump()->Stop();
   base::RunLoop().RunUntilIdle();
 
-  ExpectRelativeOrientationSensorStateToBe(
-      DeviceOrientationEventPump::SensorState::SUSPENDED);
+  ExpectRelativeOrientationSensorStateToBe(DeviceSensorEntry::State::SUSPENDED);
 }
 
 TEST_F(DeviceOrientationEventPumpTest,
@@ -299,9 +287,8 @@
   base::RunLoop().RunUntilIdle();
 
   ExpectRelativeOrientationSensorStateToBe(
-      DeviceOrientationEventPump::SensorState::NOT_INITIALIZED);
-  ExpectAbsoluteOrientationSensorStateToBe(
-      DeviceOrientationEventPump::SensorState::SUSPENDED);
+      DeviceSensorEntry::State::NOT_INITIALIZED);
+  ExpectAbsoluteOrientationSensorStateToBe(DeviceSensorEntry::State::SUSPENDED);
 }
 
 // Test a sequence of Start(), Stop(), Start() calls only bind sensor once.
@@ -311,13 +298,11 @@
   controller()->orientation_pump()->Start(nullptr);
   base::RunLoop().RunUntilIdle();
 
-  ExpectRelativeOrientationSensorStateToBe(
-      DeviceOrientationEventPump::SensorState::ACTIVE);
+  ExpectRelativeOrientationSensorStateToBe(DeviceSensorEntry::State::ACTIVE);
 
   controller()->orientation_pump()->Stop();
 
-  ExpectRelativeOrientationSensorStateToBe(
-      DeviceOrientationEventPump::SensorState::SUSPENDED);
+  ExpectRelativeOrientationSensorStateToBe(DeviceSensorEntry::State::SUSPENDED);
 }
 
 // Test when using fallback from relative orientation to absolute orientation,
@@ -331,16 +316,14 @@
   base::RunLoop().RunUntilIdle();
 
   ExpectRelativeOrientationSensorStateToBe(
-      DeviceOrientationEventPump::SensorState::NOT_INITIALIZED);
-  ExpectAbsoluteOrientationSensorStateToBe(
-      DeviceOrientationEventPump::SensorState::ACTIVE);
+      DeviceSensorEntry::State::NOT_INITIALIZED);
+  ExpectAbsoluteOrientationSensorStateToBe(DeviceSensorEntry::State::ACTIVE);
 
   controller()->orientation_pump()->Stop();
 
   ExpectRelativeOrientationSensorStateToBe(
-      DeviceOrientationEventPump::SensorState::NOT_INITIALIZED);
-  ExpectAbsoluteOrientationSensorStateToBe(
-      DeviceOrientationEventPump::SensorState::SUSPENDED);
+      DeviceSensorEntry::State::NOT_INITIALIZED);
+  ExpectAbsoluteOrientationSensorStateToBe(DeviceSensorEntry::State::SUSPENDED);
 }
 
 TEST_F(DeviceOrientationEventPumpTest, SensorIsActive) {
@@ -348,8 +331,7 @@
   controller()->orientation_pump()->Start(nullptr);
   base::RunLoop().RunUntilIdle();
 
-  ExpectRelativeOrientationSensorStateToBe(
-      DeviceOrientationEventPump::SensorState::ACTIVE);
+  ExpectRelativeOrientationSensorStateToBe(DeviceSensorEntry::State::ACTIVE);
 
   sensor_provider()->UpdateRelativeOrientationSensorData(
       1 /* alpha */, 2 /* beta */, 3 /* gamma */);
@@ -371,8 +353,7 @@
 
   controller()->orientation_pump()->Stop();
 
-  ExpectRelativeOrientationSensorStateToBe(
-      DeviceOrientationEventPump::SensorState::SUSPENDED);
+  ExpectRelativeOrientationSensorStateToBe(DeviceSensorEntry::State::SUSPENDED);
 }
 
 TEST_F(DeviceOrientationEventPumpTest, SensorIsActiveWithSensorFallback) {
@@ -383,9 +364,8 @@
   base::RunLoop().RunUntilIdle();
 
   ExpectRelativeOrientationSensorStateToBe(
-      DeviceOrientationEventPump::SensorState::NOT_INITIALIZED);
-  ExpectAbsoluteOrientationSensorStateToBe(
-      DeviceOrientationEventPump::SensorState::ACTIVE);
+      DeviceSensorEntry::State::NOT_INITIALIZED);
+  ExpectAbsoluteOrientationSensorStateToBe(DeviceSensorEntry::State::ACTIVE);
 
   sensor_provider()->UpdateAbsoluteOrientationSensorData(
       4 /* alpha */, 5 /* beta */, 6 /* gamma */);
@@ -412,9 +392,8 @@
   controller()->orientation_pump()->Stop();
 
   ExpectRelativeOrientationSensorStateToBe(
-      DeviceOrientationEventPump::SensorState::NOT_INITIALIZED);
-  ExpectAbsoluteOrientationSensorStateToBe(
-      DeviceOrientationEventPump::SensorState::SUSPENDED);
+      DeviceSensorEntry::State::NOT_INITIALIZED);
+  ExpectAbsoluteOrientationSensorStateToBe(DeviceSensorEntry::State::SUSPENDED);
 }
 
 TEST_F(DeviceOrientationEventPumpTest, SomeSensorDataFieldsNotAvailable) {
@@ -422,8 +401,7 @@
   controller()->orientation_pump()->Start(nullptr);
   base::RunLoop().RunUntilIdle();
 
-  ExpectRelativeOrientationSensorStateToBe(
-      DeviceOrientationEventPump::SensorState::ACTIVE);
+  ExpectRelativeOrientationSensorStateToBe(DeviceSensorEntry::State::ACTIVE);
 
   sensor_provider()->UpdateRelativeOrientationSensorData(
       NAN /* alpha */, 2 /* beta */, 3 /* gamma */);
@@ -442,8 +420,7 @@
 
   controller()->orientation_pump()->Stop();
 
-  ExpectRelativeOrientationSensorStateToBe(
-      DeviceOrientationEventPump::SensorState::SUSPENDED);
+  ExpectRelativeOrientationSensorStateToBe(DeviceSensorEntry::State::SUSPENDED);
 }
 
 TEST_F(DeviceOrientationEventPumpTest,
@@ -455,9 +432,8 @@
   base::RunLoop().RunUntilIdle();
 
   ExpectRelativeOrientationSensorStateToBe(
-      DeviceOrientationEventPump::SensorState::NOT_INITIALIZED);
-  ExpectAbsoluteOrientationSensorStateToBe(
-      DeviceOrientationEventPump::SensorState::ACTIVE);
+      DeviceSensorEntry::State::NOT_INITIALIZED);
+  ExpectAbsoluteOrientationSensorStateToBe(DeviceSensorEntry::State::ACTIVE);
 
   sensor_provider()->UpdateAbsoluteOrientationSensorData(
       4 /* alpha */, NAN /* beta */, 6 /* gamma */);
@@ -482,9 +458,8 @@
   controller()->orientation_pump()->Stop();
 
   ExpectRelativeOrientationSensorStateToBe(
-      DeviceOrientationEventPump::SensorState::NOT_INITIALIZED);
-  ExpectAbsoluteOrientationSensorStateToBe(
-      DeviceOrientationEventPump::SensorState::SUSPENDED);
+      DeviceSensorEntry::State::NOT_INITIALIZED);
+  ExpectAbsoluteOrientationSensorStateToBe(DeviceSensorEntry::State::SUSPENDED);
 }
 
 TEST_F(DeviceOrientationEventPumpTest, FireAllNullEvent) {
@@ -497,9 +472,9 @@
   base::RunLoop().RunUntilIdle();
 
   ExpectRelativeOrientationSensorStateToBe(
-      DeviceOrientationEventPump::SensorState::NOT_INITIALIZED);
+      DeviceSensorEntry::State::NOT_INITIALIZED);
   ExpectAbsoluteOrientationSensorStateToBe(
-      DeviceOrientationEventPump::SensorState::NOT_INITIALIZED);
+      DeviceSensorEntry::State::NOT_INITIALIZED);
 
   FireEvent();
 
@@ -514,9 +489,9 @@
   controller()->orientation_pump()->Stop();
 
   ExpectRelativeOrientationSensorStateToBe(
-      DeviceOrientationEventPump::SensorState::NOT_INITIALIZED);
+      DeviceSensorEntry::State::NOT_INITIALIZED);
   ExpectAbsoluteOrientationSensorStateToBe(
-      DeviceOrientationEventPump::SensorState::NOT_INITIALIZED);
+      DeviceSensorEntry::State::NOT_INITIALIZED);
 }
 
 TEST_F(DeviceOrientationEventPumpTest,
@@ -525,8 +500,7 @@
   controller()->orientation_pump()->Start(nullptr);
   base::RunLoop().RunUntilIdle();
 
-  ExpectRelativeOrientationSensorStateToBe(
-      DeviceOrientationEventPump::SensorState::ACTIVE);
+  ExpectRelativeOrientationSensorStateToBe(DeviceSensorEntry::State::ACTIVE);
 
   FireEvent();
 
@@ -534,8 +508,7 @@
 
   controller()->orientation_pump()->Stop();
 
-  ExpectRelativeOrientationSensorStateToBe(
-      DeviceOrientationEventPump::SensorState::SUSPENDED);
+  ExpectRelativeOrientationSensorStateToBe(DeviceSensorEntry::State::SUSPENDED);
 }
 
 TEST_F(DeviceOrientationEventPumpTest,
@@ -547,9 +520,8 @@
   base::RunLoop().RunUntilIdle();
 
   ExpectRelativeOrientationSensorStateToBe(
-      DeviceOrientationEventPump::SensorState::NOT_INITIALIZED);
-  ExpectAbsoluteOrientationSensorStateToBe(
-      DeviceOrientationEventPump::SensorState::ACTIVE);
+      DeviceSensorEntry::State::NOT_INITIALIZED);
+  ExpectAbsoluteOrientationSensorStateToBe(DeviceSensorEntry::State::ACTIVE);
 
   FireEvent();
 
@@ -558,9 +530,8 @@
   controller()->orientation_pump()->Stop();
 
   ExpectRelativeOrientationSensorStateToBe(
-      DeviceOrientationEventPump::SensorState::NOT_INITIALIZED);
-  ExpectAbsoluteOrientationSensorStateToBe(
-      DeviceOrientationEventPump::SensorState::SUSPENDED);
+      DeviceSensorEntry::State::NOT_INITIALIZED);
+  ExpectAbsoluteOrientationSensorStateToBe(DeviceSensorEntry::State::SUSPENDED);
 }
 
 TEST_F(DeviceOrientationEventPumpTest, UpdateRespectsOrientationThreshold) {
@@ -568,8 +539,7 @@
   controller()->orientation_pump()->Start(nullptr);
   base::RunLoop().RunUntilIdle();
 
-  ExpectRelativeOrientationSensorStateToBe(
-      DeviceOrientationEventPump::SensorState::ACTIVE);
+  ExpectRelativeOrientationSensorStateToBe(DeviceSensorEntry::State::ACTIVE);
 
   sensor_provider()->UpdateRelativeOrientationSensorData(
       1 /* alpha */, 2 /* beta */, 3 /* gamma */);
@@ -630,8 +600,7 @@
 
   controller()->orientation_pump()->Stop();
 
-  ExpectRelativeOrientationSensorStateToBe(
-      DeviceOrientationEventPump::SensorState::SUSPENDED);
+  ExpectRelativeOrientationSensorStateToBe(DeviceSensorEntry::State::SUSPENDED);
 }
 
 TEST_F(DeviceOrientationEventPumpTest,
@@ -643,9 +612,8 @@
   base::RunLoop().RunUntilIdle();
 
   ExpectRelativeOrientationSensorStateToBe(
-      DeviceOrientationEventPump::SensorState::NOT_INITIALIZED);
-  ExpectAbsoluteOrientationSensorStateToBe(
-      DeviceOrientationEventPump::SensorState::ACTIVE);
+      DeviceSensorEntry::State::NOT_INITIALIZED);
+  ExpectAbsoluteOrientationSensorStateToBe(DeviceSensorEntry::State::ACTIVE);
 
   sensor_provider()->UpdateAbsoluteOrientationSensorData(
       4 /* alpha */, 5 /* beta */, 6 /* gamma */);
@@ -714,9 +682,8 @@
   controller()->orientation_pump()->Stop();
 
   ExpectRelativeOrientationSensorStateToBe(
-      DeviceOrientationEventPump::SensorState::NOT_INITIALIZED);
-  ExpectAbsoluteOrientationSensorStateToBe(
-      DeviceOrientationEventPump::SensorState::SUSPENDED);
+      DeviceSensorEntry::State::NOT_INITIALIZED);
+  ExpectAbsoluteOrientationSensorStateToBe(DeviceSensorEntry::State::SUSPENDED);
 }
 
 class DeviceAbsoluteOrientationEventPumpTest : public testing::Test {
@@ -739,7 +706,7 @@
         absolute_orientation_pump);
 
     ExpectAbsoluteOrientationSensorStateToBe(
-        DeviceOrientationEventPump::SensorState::NOT_INITIALIZED);
+        DeviceSensorEntry::State::NOT_INITIALIZED);
     EXPECT_EQ(DeviceOrientationEventPump::PumpState::STOPPED,
               controller_->orientation_pump()->GetPumpStateForTesting());
   }
@@ -747,10 +714,10 @@
   void FireEvent() { controller_->orientation_pump()->FireEvent(nullptr); }
 
   void ExpectAbsoluteOrientationSensorStateToBe(
-      DeviceOrientationEventPump::SensorState expected_sensor_state) {
-    EXPECT_EQ(expected_sensor_state,
-              controller_->orientation_pump()
-                  ->absolute_orientation_sensor_.sensor_state);
+      DeviceSensorEntry::State expected_sensor_state) {
+    EXPECT_EQ(
+        expected_sensor_state,
+        controller_->orientation_pump()->absolute_orientation_sensor_->state());
   }
 
   MockDeviceOrientationController* controller() { return controller_.Get(); }
@@ -768,32 +735,28 @@
   controller()->orientation_pump()->Start(nullptr);
   base::RunLoop().RunUntilIdle();
 
-  ExpectAbsoluteOrientationSensorStateToBe(
-      DeviceOrientationEventPump::SensorState::ACTIVE);
+  ExpectAbsoluteOrientationSensorStateToBe(DeviceSensorEntry::State::ACTIVE);
   EXPECT_EQ(DeviceOrientationEventPump::PumpState::RUNNING,
             controller()->orientation_pump()->GetPumpStateForTesting());
 
   controller()->orientation_pump()->Stop();
   base::RunLoop().RunUntilIdle();
 
-  ExpectAbsoluteOrientationSensorStateToBe(
-      DeviceOrientationEventPump::SensorState::SUSPENDED);
+  ExpectAbsoluteOrientationSensorStateToBe(DeviceSensorEntry::State::SUSPENDED);
   EXPECT_EQ(DeviceOrientationEventPump::PumpState::STOPPED,
             controller()->orientation_pump()->GetPumpStateForTesting());
 
   controller()->orientation_pump()->Start(nullptr);
   base::RunLoop().RunUntilIdle();
 
-  ExpectAbsoluteOrientationSensorStateToBe(
-      DeviceOrientationEventPump::SensorState::ACTIVE);
+  ExpectAbsoluteOrientationSensorStateToBe(DeviceSensorEntry::State::ACTIVE);
   EXPECT_EQ(DeviceOrientationEventPump::PumpState::RUNNING,
             controller()->orientation_pump()->GetPumpStateForTesting());
 
   controller()->orientation_pump()->Stop();
   base::RunLoop().RunUntilIdle();
 
-  ExpectAbsoluteOrientationSensorStateToBe(
-      DeviceOrientationEventPump::SensorState::SUSPENDED);
+  ExpectAbsoluteOrientationSensorStateToBe(DeviceSensorEntry::State::SUSPENDED);
   EXPECT_EQ(DeviceOrientationEventPump::PumpState::STOPPED,
             controller()->orientation_pump()->GetPumpStateForTesting());
 }
@@ -803,7 +766,7 @@
   base::RunLoop().RunUntilIdle();
 
   ExpectAbsoluteOrientationSensorStateToBe(
-      DeviceOrientationEventPump::SensorState::NOT_INITIALIZED);
+      DeviceSensorEntry::State::NOT_INITIALIZED);
 }
 
 TEST_F(DeviceAbsoluteOrientationEventPumpTest, CallStartAndStop) {
@@ -811,8 +774,7 @@
   controller()->orientation_pump()->Stop();
   base::RunLoop().RunUntilIdle();
 
-  ExpectAbsoluteOrientationSensorStateToBe(
-      DeviceOrientationEventPump::SensorState::SUSPENDED);
+  ExpectAbsoluteOrientationSensorStateToBe(DeviceSensorEntry::State::SUSPENDED);
 }
 
 TEST_F(DeviceAbsoluteOrientationEventPumpTest, CallStartMultipleTimes) {
@@ -821,8 +783,7 @@
   controller()->orientation_pump()->Stop();
   base::RunLoop().RunUntilIdle();
 
-  ExpectAbsoluteOrientationSensorStateToBe(
-      DeviceOrientationEventPump::SensorState::SUSPENDED);
+  ExpectAbsoluteOrientationSensorStateToBe(DeviceSensorEntry::State::SUSPENDED);
 }
 
 TEST_F(DeviceAbsoluteOrientationEventPumpTest, CallStopMultipleTimes) {
@@ -831,8 +792,7 @@
   controller()->orientation_pump()->Stop();
   base::RunLoop().RunUntilIdle();
 
-  ExpectAbsoluteOrientationSensorStateToBe(
-      DeviceOrientationEventPump::SensorState::SUSPENDED);
+  ExpectAbsoluteOrientationSensorStateToBe(DeviceSensorEntry::State::SUSPENDED);
 }
 
 // Test multiple DeviceSensorEventPump::Start() calls only bind sensor once.
@@ -842,13 +802,11 @@
   controller()->orientation_pump()->Start(nullptr);
   base::RunLoop().RunUntilIdle();
 
-  ExpectAbsoluteOrientationSensorStateToBe(
-      DeviceOrientationEventPump::SensorState::ACTIVE);
+  ExpectAbsoluteOrientationSensorStateToBe(DeviceSensorEntry::State::ACTIVE);
 
   controller()->orientation_pump()->Stop();
 
-  ExpectAbsoluteOrientationSensorStateToBe(
-      DeviceOrientationEventPump::SensorState::SUSPENDED);
+  ExpectAbsoluteOrientationSensorStateToBe(DeviceSensorEntry::State::SUSPENDED);
 }
 
 TEST_F(DeviceAbsoluteOrientationEventPumpTest, SensorIsActive) {
@@ -856,8 +814,7 @@
   controller()->orientation_pump()->Start(nullptr);
   base::RunLoop().RunUntilIdle();
 
-  ExpectAbsoluteOrientationSensorStateToBe(
-      DeviceOrientationEventPump::SensorState::ACTIVE);
+  ExpectAbsoluteOrientationSensorStateToBe(DeviceSensorEntry::State::ACTIVE);
 
   sensor_provider()->UpdateAbsoluteOrientationSensorData(
       4 /* alpha */, 5 /* beta */, 6 /* gamma */);
@@ -877,8 +834,7 @@
 
   controller()->orientation_pump()->Stop();
 
-  ExpectAbsoluteOrientationSensorStateToBe(
-      DeviceOrientationEventPump::SensorState::SUSPENDED);
+  ExpectAbsoluteOrientationSensorStateToBe(DeviceSensorEntry::State::SUSPENDED);
 }
 
 TEST_F(DeviceAbsoluteOrientationEventPumpTest,
@@ -887,8 +843,7 @@
   controller()->orientation_pump()->Start(nullptr);
   base::RunLoop().RunUntilIdle();
 
-  ExpectAbsoluteOrientationSensorStateToBe(
-      DeviceOrientationEventPump::SensorState::ACTIVE);
+  ExpectAbsoluteOrientationSensorStateToBe(DeviceSensorEntry::State::ACTIVE);
 
   sensor_provider()->UpdateAbsoluteOrientationSensorData(
       4 /* alpha */, NAN /* beta */, 6 /* gamma */);
@@ -907,8 +862,7 @@
 
   controller()->orientation_pump()->Stop();
 
-  ExpectAbsoluteOrientationSensorStateToBe(
-      DeviceOrientationEventPump::SensorState::SUSPENDED);
+  ExpectAbsoluteOrientationSensorStateToBe(DeviceSensorEntry::State::SUSPENDED);
 }
 
 TEST_F(DeviceAbsoluteOrientationEventPumpTest, FireAllNullEvent) {
@@ -920,7 +874,7 @@
   base::RunLoop().RunUntilIdle();
 
   ExpectAbsoluteOrientationSensorStateToBe(
-      DeviceOrientationEventPump::SensorState::NOT_INITIALIZED);
+      DeviceSensorEntry::State::NOT_INITIALIZED);
 
   FireEvent();
 
@@ -935,7 +889,7 @@
   controller()->orientation_pump()->Stop();
 
   ExpectAbsoluteOrientationSensorStateToBe(
-      DeviceOrientationEventPump::SensorState::NOT_INITIALIZED);
+      DeviceSensorEntry::State::NOT_INITIALIZED);
 }
 
 TEST_F(DeviceAbsoluteOrientationEventPumpTest,
@@ -944,8 +898,7 @@
   controller()->orientation_pump()->Start(nullptr);
   base::RunLoop().RunUntilIdle();
 
-  ExpectAbsoluteOrientationSensorStateToBe(
-      DeviceOrientationEventPump::SensorState::ACTIVE);
+  ExpectAbsoluteOrientationSensorStateToBe(DeviceSensorEntry::State::ACTIVE);
 
   FireEvent();
 
@@ -953,8 +906,7 @@
 
   controller()->orientation_pump()->Stop();
 
-  ExpectAbsoluteOrientationSensorStateToBe(
-      DeviceOrientationEventPump::SensorState::SUSPENDED);
+  ExpectAbsoluteOrientationSensorStateToBe(DeviceSensorEntry::State::SUSPENDED);
 }
 
 TEST_F(DeviceAbsoluteOrientationEventPumpTest,
@@ -963,8 +915,7 @@
   controller()->orientation_pump()->Start(nullptr);
   base::RunLoop().RunUntilIdle();
 
-  ExpectAbsoluteOrientationSensorStateToBe(
-      DeviceOrientationEventPump::SensorState::ACTIVE);
+  ExpectAbsoluteOrientationSensorStateToBe(DeviceSensorEntry::State::ACTIVE);
 
   sensor_provider()->UpdateAbsoluteOrientationSensorData(
       4 /* alpha */, 5 /* beta */, 6 /* gamma */);
@@ -1027,8 +978,7 @@
 
   controller()->orientation_pump()->Stop();
 
-  ExpectAbsoluteOrientationSensorStateToBe(
-      DeviceOrientationEventPump::SensorState::SUSPENDED);
+  ExpectAbsoluteOrientationSensorStateToBe(DeviceSensorEntry::State::SUSPENDED);
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/modules/device_orientation/device_sensor_entry.cc b/third_party/blink/renderer/modules/device_orientation/device_sensor_entry.cc
new file mode 100644
index 0000000..a58c56b4
--- /dev/null
+++ b/third_party/blink/renderer/modules/device_orientation/device_sensor_entry.cc
@@ -0,0 +1,175 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/modules/device_orientation/device_sensor_entry.h"
+
+#include "services/device/public/cpp/generic_sensor/sensor_reading_shared_buffer_reader.h"
+#include "third_party/blink/renderer/modules/device_orientation/device_sensor_event_pump.h"
+#include "third_party/blink/renderer/platform/heap/persistent.h"
+#include "third_party/blink/renderer/platform/wtf/functional.h"
+
+namespace blink {
+
+DeviceSensorEntry::DeviceSensorEntry(DeviceSensorEventPump* event_pump,
+                                     device::mojom::blink::SensorType type)
+    : event_pump_(event_pump), type_(type) {}
+
+void DeviceSensorEntry::Dispose() {
+  client_binding_.Close();
+}
+
+DeviceSensorEntry::~DeviceSensorEntry() = default;
+
+void DeviceSensorEntry::Start(
+    device::mojom::blink::SensorProvider* sensor_provider) {
+  if (state_ == State::NOT_INITIALIZED) {
+    state_ = State::INITIALIZING;
+    sensor_provider->GetSensor(type_,
+                               WTF::Bind(&DeviceSensorEntry::OnSensorCreated,
+                                         WrapWeakPersistent(this)));
+  } else if (state_ == State::SUSPENDED) {
+    sensor_->Resume();
+    state_ = State::ACTIVE;
+    event_pump_->DidStartIfPossible();
+  } else if (state_ == State::SHOULD_SUSPEND) {
+    // This can happen when calling Start(), Stop(), Start() in a sequence:
+    // After the first Start() call, the sensor state is
+    // State::INITIALIZING. Then after the Stop() call, the sensor
+    // state is State::SHOULD_SUSPEND, and the next Start() call needs
+    // to set the sensor state to be State::INITIALIZING again.
+    state_ = State::INITIALIZING;
+  } else {
+    NOTREACHED();
+  }
+}
+
+void DeviceSensorEntry::Stop() {
+  if (sensor_) {
+    sensor_->Suspend();
+    state_ = State::SUSPENDED;
+  } else if (state_ == State::INITIALIZING) {
+    // When the sensor needs to be suspended, and it is still in the
+    // State::INITIALIZING state, the sensor creation is not affected
+    // (the DeviceSensorEntry::OnSensorCreated() callback will run as usual),
+    // but the sensor is marked as State::SHOULD_SUSPEND, and when the sensor is
+    // created successfully, it will be suspended and its state will be marked
+    // as State::SUSPENDED in the DeviceSensorEntry::OnSensorAddConfiguration().
+    state_ = State::SHOULD_SUSPEND;
+  }
+}
+
+bool DeviceSensorEntry::IsConnected() const {
+  return sensor_.is_bound();
+}
+
+bool DeviceSensorEntry::ReadyOrErrored() const {
+  // When some sensors are not available, the pump still needs to fire
+  // events which set the unavailable sensor data fields to null.
+  return state_ == State::ACTIVE || state_ == State::NOT_INITIALIZED;
+}
+
+bool DeviceSensorEntry::GetReading(device::SensorReading* reading) {
+  if (!sensor_)
+    return false;
+
+  DCHECK(shared_buffer_);
+
+  if (!shared_buffer_handle_->is_valid() ||
+      !shared_buffer_reader_->GetReading(reading)) {
+    HandleSensorError();
+    return false;
+  }
+
+  return true;
+}
+
+void DeviceSensorEntry::Trace(Visitor* visitor) {
+  visitor->Trace(event_pump_);
+}
+
+void DeviceSensorEntry::RaiseError() {
+  HandleSensorError();
+}
+
+void DeviceSensorEntry::SensorReadingChanged() {
+  // Since DeviceSensorEventPump::FireEvent is called in a fixed
+  // frequency, the |shared_buffer| is read frequently, and
+  // Sensor::ConfigureReadingChangeNotifications() is set to false,
+  // so this method is not called and doesn't need to be implemented.
+  NOTREACHED();
+}
+
+void DeviceSensorEntry::OnSensorCreated(
+    device::mojom::blink::SensorCreationResult result,
+    device::mojom::blink::SensorInitParamsPtr params) {
+  // |state_| can be State::SHOULD_SUSPEND if Stop() is called
+  // before OnSensorCreated() is called.
+  DCHECK(state_ == State::INITIALIZING || state_ == State::SHOULD_SUSPEND);
+
+  if (!params) {
+    HandleSensorError();
+    event_pump_->DidStartIfPossible();
+    return;
+  }
+  DCHECK_EQ(device::mojom::SensorCreationResult::SUCCESS, result);
+
+  constexpr size_t kReadBufferSize = sizeof(device::SensorReadingSharedBuffer);
+
+  DCHECK_EQ(0u, params->buffer_offset % kReadBufferSize);
+
+  sensor_.Bind(std::move(params->sensor));
+  client_binding_.Bind(std::move(params->client_request));
+
+  shared_buffer_handle_ = std::move(params->memory);
+  DCHECK(!shared_buffer_);
+  shared_buffer_ = shared_buffer_handle_->MapAtOffset(kReadBufferSize,
+                                                      params->buffer_offset);
+  if (!shared_buffer_) {
+    HandleSensorError();
+    event_pump_->DidStartIfPossible();
+    return;
+  }
+
+  const device::SensorReadingSharedBuffer* buffer =
+      static_cast<const device::SensorReadingSharedBuffer*>(
+          shared_buffer_.get());
+  shared_buffer_reader_.reset(
+      new device::SensorReadingSharedBufferReader(buffer));
+
+  device::mojom::blink::SensorConfigurationPtr config =
+      std::move(params->default_configuration);
+  config->frequency = std::min(
+      static_cast<double>(DeviceSensorEventPump::kDefaultPumpFrequencyHz),
+      params->maximum_frequency);
+
+  sensor_.set_connection_error_handler(WTF::Bind(
+      &DeviceSensorEntry::HandleSensorError, WrapWeakPersistent(this)));
+  sensor_->ConfigureReadingChangeNotifications(/*enabled=*/false);
+  sensor_->AddConfiguration(
+      std::move(config), WTF::Bind(&DeviceSensorEntry::OnSensorAddConfiguration,
+                                   WrapWeakPersistent(this)));
+}
+
+void DeviceSensorEntry::OnSensorAddConfiguration(bool success) {
+  if (!success)
+    HandleSensorError();
+
+  if (state_ == State::INITIALIZING) {
+    state_ = State::ACTIVE;
+    event_pump_->DidStartIfPossible();
+  } else if (state_ == State::SHOULD_SUSPEND) {
+    sensor_->Suspend();
+    state_ = State::SUSPENDED;
+  }
+}
+
+void DeviceSensorEntry::HandleSensorError() {
+  sensor_.reset();
+  state_ = State::NOT_INITIALIZED;
+  shared_buffer_handle_.reset();
+  shared_buffer_.reset();
+  client_binding_.Close();
+}
+
+}  // namespace blink
diff --git a/third_party/blink/renderer/modules/device_orientation/device_sensor_entry.h b/third_party/blink/renderer/modules/device_orientation/device_sensor_entry.h
new file mode 100644
index 0000000..c3435b6
--- /dev/null
+++ b/third_party/blink/renderer/modules/device_orientation/device_sensor_entry.h
@@ -0,0 +1,90 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_DEVICE_ORIENTATION_DEVICE_SENSOR_ENTRY_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_DEVICE_ORIENTATION_DEVICE_SENSOR_ENTRY_H_
+
+#include "mojo/public/cpp/bindings/binding.h"
+#include "services/device/public/mojom/sensor.mojom-blink.h"
+#include "services/device/public/mojom/sensor_provider.mojom-blink.h"
+#include "third_party/blink/renderer/platform/heap/handle.h"
+
+namespace device {
+union SensorReading;
+class SensorReadingSharedBufferReader;
+}  // namespace device
+
+namespace blink {
+
+class DeviceSensorEventPump;
+
+class DeviceSensorEntry : public GarbageCollectedFinalized<DeviceSensorEntry>,
+                          public device::mojom::blink::SensorClient {
+  USING_PRE_FINALIZER(DeviceSensorEntry, Dispose);
+
+ public:
+  // The sensor state is an automaton with allowed transitions as follows:
+  // NOT_INITIALIZED -> INITIALIZING
+  // INITIALIZING -> ACTIVE
+  // INITIALIZING -> SHOULD_SUSPEND
+  // ACTIVE -> SUSPENDED
+  // SHOULD_SUSPEND -> INITIALIZING
+  // SHOULD_SUSPEND -> SUSPENDED
+  // SUSPENDED -> ACTIVE
+  // { INITIALIZING, ACTIVE, SHOULD_SUSPEND, SUSPENDED } -> NOT_INITIALIZED
+  enum class State {
+    NOT_INITIALIZED,
+    INITIALIZING,
+    ACTIVE,
+    SHOULD_SUSPEND,
+    SUSPENDED
+  };
+
+  DeviceSensorEntry(DeviceSensorEventPump* pump,
+                    device::mojom::blink::SensorType sensor_type);
+  void Dispose();
+  ~DeviceSensorEntry() override;
+
+  void Start(device::mojom::blink::SensorProvider* sensor_provider);
+  void Stop();
+  bool IsConnected() const;
+  bool ReadyOrErrored() const;
+  bool GetReading(device::SensorReading* reading);
+
+  State state() const { return state_; }
+
+  void Trace(Visitor* visitor);
+
+ private:
+  // device::mojom::SensorClient:
+  void RaiseError() override;
+  void SensorReadingChanged() override;
+
+  // Mojo callback for SensorProvider::GetSensor().
+  void OnSensorCreated(device::mojom::blink::SensorCreationResult result,
+                       device::mojom::blink::SensorInitParamsPtr params);
+
+  // Mojo callback for Sensor::AddConfiguration().
+  void OnSensorAddConfiguration(bool success);
+
+  void HandleSensorError();
+
+  Member<DeviceSensorEventPump> event_pump_;
+
+  State state_ = State::NOT_INITIALIZED;
+
+  device::mojom::blink::SensorPtr sensor_;
+  mojo::Binding<device::mojom::blink::SensorClient> client_binding_{this};
+
+  device::mojom::blink::SensorType type_;
+
+  mojo::ScopedSharedBufferHandle shared_buffer_handle_;
+  mojo::ScopedSharedBufferMapping shared_buffer_;
+  std::unique_ptr<device::SensorReadingSharedBufferReader>
+      shared_buffer_reader_;
+};
+
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_RENDERER_MODULES_DEVICE_ORIENTATION_DEVICE_SENSOR_ENTRY_H_
diff --git a/third_party/blink/renderer/modules/device_orientation/device_sensor_event_pump.cc b/third_party/blink/renderer/modules/device_orientation/device_sensor_event_pump.cc
new file mode 100644
index 0000000..bfbd67e
--- /dev/null
+++ b/third_party/blink/renderer/modules/device_orientation/device_sensor_event_pump.cc
@@ -0,0 +1,77 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/modules/device_orientation/device_sensor_event_pump.h"
+
+namespace blink {
+
+void DeviceSensorEventPump::Start(LocalFrame* frame) {
+  DVLOG(2) << "requested start";
+
+  if (state_ != PumpState::STOPPED)
+    return;
+
+  DCHECK(!timer_.IsActive());
+
+  state_ = PumpState::PENDING_START;
+
+  SendStartMessage(frame);
+}
+
+void DeviceSensorEventPump::Stop() {
+  DVLOG(2) << "requested stop";
+
+  if (state_ == PumpState::STOPPED)
+    return;
+
+  DCHECK((state_ == PumpState::PENDING_START && !timer_.IsActive()) ||
+         (state_ == PumpState::RUNNING && timer_.IsActive()));
+
+  if (timer_.IsActive())
+    timer_.Stop();
+
+  SendStopMessage();
+
+  state_ = PumpState::STOPPED;
+}
+
+void DeviceSensorEventPump::HandleSensorProviderError() {
+  sensor_provider_.reset();
+}
+
+void DeviceSensorEventPump::SetSensorProviderForTesting(
+    device::mojom::blink::SensorProviderPtr sensor_provider) {
+  sensor_provider_ = std::move(sensor_provider);
+}
+
+DeviceSensorEventPump::PumpState
+DeviceSensorEventPump::GetPumpStateForTesting() {
+  return state_;
+}
+
+DeviceSensorEventPump::DeviceSensorEventPump(
+    scoped_refptr<base::SingleThreadTaskRunner> task_runner)
+    : state_(PumpState::STOPPED),
+      timer_(std::move(task_runner), this, &DeviceSensorEventPump::FireEvent) {}
+
+DeviceSensorEventPump::~DeviceSensorEventPump() = default;
+
+void DeviceSensorEventPump::DidStartIfPossible() {
+  DVLOG(2) << "did start sensor event pump";
+
+  if (state_ != PumpState::PENDING_START)
+    return;
+
+  if (!SensorsReadyOrErrored())
+    return;
+
+  DCHECK(!timer_.IsActive());
+
+  timer_.StartRepeating(
+      WTF::TimeDelta::FromMicroseconds(kDefaultPumpDelayMicroseconds),
+      FROM_HERE);
+  state_ = PumpState::RUNNING;
+}
+
+}  // namespace blink
diff --git a/third_party/blink/renderer/modules/device_orientation/device_sensor_event_pump.h b/third_party/blink/renderer/modules/device_orientation/device_sensor_event_pump.h
index e64faba..f84d7ec 100644
--- a/third_party/blink/renderer/modules/device_orientation/device_sensor_event_pump.h
+++ b/third_party/blink/renderer/modules/device_orientation/device_sensor_event_pump.h
@@ -5,23 +5,16 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_DEVICE_ORIENTATION_DEVICE_SENSOR_EVENT_PUMP_H_
 #define THIRD_PARTY_BLINK_RENDERER_MODULES_DEVICE_ORIENTATION_DEVICE_SENSOR_EVENT_PUMP_H_
 
-#include <algorithm>
-#include <memory>
-#include <utility>
-#include <vector>
-
-#include "mojo/public/cpp/bindings/binding.h"
-#include "services/device/public/cpp/generic_sensor/sensor_reading.h"
-#include "services/device/public/cpp/generic_sensor/sensor_reading_shared_buffer_reader.h"
 #include "services/device/public/mojom/sensor_provider.mojom-blink.h"
+#include "third_party/blink/renderer/modules/modules_export.h"
+#include "third_party/blink/renderer/platform/heap/handle.h"
 #include "third_party/blink/renderer/platform/timer.h"
-#include "third_party/blink/renderer/platform/wtf/functional.h"
 
 namespace blink {
 
 class LocalFrame;
 
-class DeviceSensorEventPump {
+class MODULES_EXPORT DeviceSensorEventPump : public GarbageCollectedMixin {
  public:
   // Default rate for firing events.
   static constexpr int kDefaultPumpFrequencyHz = 60;
@@ -35,75 +28,21 @@
   // RUNNING -> STOPPED
   enum class PumpState { STOPPED, RUNNING, PENDING_START };
 
-  // The sensor state is an automaton with allowed transitions as follows:
-  // NOT_INITIALIZED -> INITIALIZING
-  // INITIALIZING -> ACTIVE
-  // INITIALIZING -> SHOULD_SUSPEND
-  // ACTIVE -> SUSPENDED
-  // SHOULD_SUSPEND -> INITIALIZING
-  // SHOULD_SUSPEND -> SUSPENDED
-  // SUSPENDED -> ACTIVE
-  // { INITIALIZING, ACTIVE, SHOULD_SUSPEND, SUSPENDED } -> NOT_INITIALIZED
-  enum class SensorState {
-    NOT_INITIALIZED,
-    INITIALIZING,
-    ACTIVE,
-    SHOULD_SUSPEND,
-    SUSPENDED
-  };
+  virtual void Start(LocalFrame* frame);
+  virtual void Stop();
 
-  virtual void Start(LocalFrame* frame) {
-    DVLOG(2) << "requested start";
-
-    if (state_ != PumpState::STOPPED)
-      return;
-
-    DCHECK(!timer_.IsActive());
-
-    state_ = PumpState::PENDING_START;
-
-    DCHECK(!is_observing_);
-    is_observing_ = true;
-
-    SendStartMessage(frame);
-  }
-
-  virtual void Stop() {
-    DVLOG(2) << "requested stop";
-
-    if (state_ == PumpState::STOPPED)
-      return;
-
-    DCHECK((state_ == PumpState::PENDING_START && !timer_.IsActive()) ||
-           (state_ == PumpState::RUNNING && timer_.IsActive()));
-
-    if (timer_.IsActive())
-      timer_.Stop();
-
-    DCHECK(is_observing_);
-    is_observing_ = false;
-
-    SendStopMessage();
-
-    state_ = PumpState::STOPPED;
-  }
-
-  void HandleSensorProviderError() { sensor_provider_.reset(); }
+  void HandleSensorProviderError();
 
   void SetSensorProviderForTesting(
-      device::mojom::blink::SensorProviderPtr sensor_provider) {
-    sensor_provider_ = std::move(sensor_provider);
-  }
-
-  PumpState GetPumpStateForTesting() { return state_; }
+      device::mojom::blink::SensorProviderPtr sensor_provider);
+  PumpState GetPumpStateForTesting();
 
  protected:
-  explicit DeviceSensorEventPump(
-      scoped_refptr<base::SingleThreadTaskRunner> task_runner)
-      : state_(PumpState::STOPPED),
-        timer_(task_runner, this, &DeviceSensorEventPump::FireEvent) {}
+  friend class DeviceSensorEntry;
 
-  virtual ~DeviceSensorEventPump() { DCHECK(!is_observing_); }
+  explicit DeviceSensorEventPump(
+      scoped_refptr<base::SingleThreadTaskRunner> task_runner);
+  virtual ~DeviceSensorEventPump();
 
   // This method is expected to send an IPC to the browser process to let it
   // know that it should start observing.
@@ -115,209 +54,11 @@
   // It is expected for subclasses to override it.
   virtual void SendStopMessage() = 0;
 
-  // Implementations of DeviceSensorEventPump must call StopIfObserving()
-  // from their destructor to shutdown in an orderly manner.
-  // (As Stop() calls a virtual method, it cannot be handled by
-  // ~DeviceSensorEventPump.)
-  void StopIfObserving() {
-    if (is_observing_)
-      Stop();
-  }
-
   // Even though the TimerBase* parameter is not used, it is required by
   // TaskRunnerTimer class
   virtual void FireEvent(TimerBase*) = 0;
 
-  struct SensorEntry : public device::mojom::blink::SensorClient {
-    SensorEntry(DeviceSensorEventPump* pump,
-                device::mojom::blink::SensorType sensor_type)
-        : event_pump(pump),
-          sensor_state(SensorState::NOT_INITIALIZED),
-          type(sensor_type),
-          client_binding(this) {}
-
-    ~SensorEntry() override {}
-
-    // device::mojom::SensorClient:
-    void RaiseError() override { HandleSensorError(); }
-
-    // device::mojom::SensorClient:
-    void SensorReadingChanged() override {
-      // Since DeviceSensorEventPump::FireEvent is called in a fixed
-      // frequency, the |shared_buffer| is read frequently, and
-      // Sensor::ConfigureReadingChangeNotifications() is set to false,
-      // so this method is not called and doesn't need to be implemented.
-      NOTREACHED();
-    }
-
-    // Mojo callback for SensorProvider::GetSensor().
-    void OnSensorCreated(device::mojom::blink::SensorCreationResult result,
-                         device::mojom::blink::SensorInitParamsPtr params) {
-      // |sensor_state| can be SensorState::SHOULD_SUSPEND if Stop() is called
-      // before OnSensorCreated() is called.
-      DCHECK(sensor_state == SensorState::INITIALIZING ||
-             sensor_state == SensorState::SHOULD_SUSPEND);
-
-      if (!params) {
-        HandleSensorError();
-        event_pump->DidStartIfPossible();
-        return;
-      }
-      DCHECK_EQ(device::mojom::SensorCreationResult::SUCCESS, result);
-
-      constexpr size_t kReadBufferSize =
-          sizeof(device::SensorReadingSharedBuffer);
-
-      DCHECK_EQ(0u, params->buffer_offset % kReadBufferSize);
-
-      mode = params->mode;
-      default_config = std::move(params->default_configuration);
-
-      sensor.Bind(std::move(params->sensor));
-      client_binding.Bind(std::move(params->client_request));
-
-      shared_buffer_handle = std::move(params->memory);
-      DCHECK(!shared_buffer);
-      shared_buffer = shared_buffer_handle->MapAtOffset(kReadBufferSize,
-                                                        params->buffer_offset);
-      if (!shared_buffer) {
-        HandleSensorError();
-        event_pump->DidStartIfPossible();
-        return;
-      }
-
-      const device::SensorReadingSharedBuffer* buffer =
-          static_cast<const device::SensorReadingSharedBuffer*>(
-              shared_buffer.get());
-      shared_buffer_reader.reset(
-          new device::SensorReadingSharedBufferReader(buffer));
-
-      default_config->frequency =
-          std::min(static_cast<double>(kDefaultPumpFrequencyHz),
-                   params->maximum_frequency);
-
-      sensor.set_connection_error_handler(
-          WTF::Bind(&SensorEntry::HandleSensorError, WTF::Unretained(this)));
-      sensor->ConfigureReadingChangeNotifications(false /* disabled */);
-      sensor->AddConfiguration(std::move(default_config),
-                               WTF::Bind(&SensorEntry::OnSensorAddConfiguration,
-                                         WTF::Unretained(this)));
-    }
-
-    // Mojo callback for Sensor::AddConfiguration().
-    void OnSensorAddConfiguration(bool success) {
-      if (!success)
-        HandleSensorError();
-
-      if (sensor_state == SensorState::INITIALIZING) {
-        sensor_state = SensorState::ACTIVE;
-        event_pump->DidStartIfPossible();
-      } else if (sensor_state == SensorState::SHOULD_SUSPEND) {
-        sensor->Suspend();
-        sensor_state = SensorState::SUSPENDED;
-      }
-    }
-
-    void HandleSensorError() {
-      sensor.reset();
-      sensor_state = SensorState::NOT_INITIALIZED;
-      shared_buffer_handle.reset();
-      shared_buffer.reset();
-      client_binding.Close();
-    }
-
-    bool SensorReadingCouldBeRead() {
-      if (!sensor)
-        return false;
-
-      DCHECK(shared_buffer);
-
-      if (!shared_buffer_handle->is_valid() ||
-          !shared_buffer_reader->GetReading(&reading)) {
-        HandleSensorError();
-        return false;
-      }
-
-      return true;
-    }
-
-    bool ReadyOrErrored() const {
-      // When some sensors are not available, the pump still needs to fire
-      // events which set the unavailable sensor data fields to null.
-      return sensor_state == SensorState::ACTIVE ||
-             sensor_state == SensorState::NOT_INITIALIZED;
-    }
-
-    void Start(device::mojom::blink::SensorProvider* sensor_provider) {
-      if (sensor_state == SensorState::NOT_INITIALIZED) {
-        sensor_state = SensorState::INITIALIZING;
-        sensor_provider->GetSensor(
-            type,
-            WTF::Bind(&SensorEntry::OnSensorCreated, WTF::Unretained(this)));
-      } else if (sensor_state == SensorState::SUSPENDED) {
-        sensor->Resume();
-        sensor_state = SensorState::ACTIVE;
-        event_pump->DidStartIfPossible();
-      } else if (sensor_state == SensorState::SHOULD_SUSPEND) {
-        // This can happen when calling Start(), Stop(), Start() in a sequence:
-        // After the first Start() call, the sensor state is
-        // SensorState::INITIALIZING. Then after the Stop() call, the sensor
-        // state is SensorState::SHOULD_SUSPEND, and the next Start() call needs
-        // to set the sensor state to be SensorState::INITIALIZING again.
-        sensor_state = SensorState::INITIALIZING;
-      } else {
-        NOTREACHED();
-      }
-    }
-
-    void Stop() {
-      if (sensor) {
-        sensor->Suspend();
-        sensor_state = SensorState::SUSPENDED;
-      } else if (sensor_state == SensorState::INITIALIZING) {
-        // When the sensor needs to be suspended, and it is still in the
-        // SensorState::INITIALIZING state, the sensor creation is not affected
-        // (the SensorEntry::OnSensorCreated() callback will run as usual), but
-        // the sensor is marked as SensorState::SHOULD_SUSPEND, and when the
-        // sensor is created successfully, it will be suspended and its state
-        // will be marked as SensorState::SUSPENDED in the
-        // SensorEntry::OnSensorAddConfiguration().
-        sensor_state = SensorState::SHOULD_SUSPEND;
-      }
-    }
-
-    DeviceSensorEventPump* event_pump;
-    device::mojom::blink::SensorPtr sensor;
-    SensorState sensor_state;
-    device::mojom::blink::SensorType type;
-    device::mojom::blink::ReportingMode mode;
-    device::mojom::blink::SensorConfigurationPtr default_config;
-    mojo::ScopedSharedBufferHandle shared_buffer_handle;
-    mojo::ScopedSharedBufferMapping shared_buffer;
-    std::unique_ptr<device::SensorReadingSharedBufferReader>
-        shared_buffer_reader;
-    device::SensorReading reading;
-    mojo::Binding<device::mojom::blink::SensorClient> client_binding;
-  };
-
-  friend struct SensorEntry;
-
-  virtual void DidStartIfPossible() {
-    DVLOG(2) << "did start sensor event pump";
-
-    if (state_ != PumpState::PENDING_START)
-      return;
-
-    if (!SensorsReadyOrErrored())
-      return;
-
-    DCHECK(!timer_.IsActive());
-
-    timer_.StartRepeating(
-        WTF::TimeDelta::FromMicroseconds(kDefaultPumpDelayMicroseconds),
-        FROM_HERE);
-    state_ = PumpState::RUNNING;
-  }
+  virtual void DidStartIfPossible();
 
   device::mojom::blink::SensorProviderPtr sensor_provider_;
 
@@ -325,11 +66,9 @@
   virtual bool SensorsReadyOrErrored() const = 0;
 
   PumpState state_;
-  bool is_observing_ = false;
   TaskRunnerTimer<DeviceSensorEventPump> timer_;
-
-  DISALLOW_COPY_AND_ASSIGN(DeviceSensorEventPump);
 };
+
 }  // namespace blink
 
 #endif  // THIRD_PARTY_BLINK_RENDERER_MODULES_DEVICE_ORIENTATION_DEVICE_SENSOR_EVENT_PUMP_H_
diff --git a/third_party/blink/renderer/platform/heap/heap_thread_test.cc b/third_party/blink/renderer/platform/heap/heap_thread_test.cc
index b1f86ce..f5d687b6 100644
--- a/third_party/blink/renderer/platform/heap/heap_thread_test.cc
+++ b/third_party/blink/renderer/platform/heap/heap_thread_test.cc
@@ -129,7 +129,7 @@
 };
 
 #if DCHECK_IS_ON()
-// TODO(keishi) This test is flaky on mac_chromium_rel_ng bot.
+// TODO(keishi) This test is flaky on mac-rel bot.
 // crbug.com/709069
 #if !defined(OS_MACOSX)
 TEST(HeapDeathTest, MemberSameThreadCheck) {
@@ -152,7 +152,7 @@
 };
 
 #if DCHECK_IS_ON()
-// TODO(keishi) This test is flaky on mac_chromium_rel_ng bot.
+// TODO(keishi) This test is flaky on mac-rel bot.
 // crbug.com/709069
 #if !defined(OS_MACOSX)
 TEST(HeapDeathTest, PersistentSameThreadCheck) {
@@ -192,7 +192,7 @@
 };
 
 #if DCHECK_IS_ON()
-// TODO(keishi) This test is flaky on mac_chromium_rel_ng bot.
+// TODO(keishi) This test is flaky on mac-rel bot.
 // crbug.com/709069
 #if !defined(OS_MACOSX)
 TEST(HeapDeathTest, MarkingSameThreadCheck) {
diff --git a/third_party/blink/renderer/platform/wtf/assertions_test.cc b/third_party/blink/renderer/platform/wtf/assertions_test.cc
index c242681..e5535ff 100644
--- a/third_party/blink/renderer/platform/wtf/assertions_test.cc
+++ b/third_party/blink/renderer/platform/wtf/assertions_test.cc
@@ -33,6 +33,6 @@
 
   SECURITY_CHECK(true);
   EXPECT_DEATH_IF_SUPPORTED(SECURITY_CHECK(false), "");
-};
+}
 
 }  // namespace WTF
diff --git a/third_party/blink/renderer/platform/wtf/doubly_linked_list_test.cc b/third_party/blink/renderer/platform/wtf/doubly_linked_list_test.cc
index 69621b7..d650168 100644
--- a/third_party/blink/renderer/platform/wtf/doubly_linked_list_test.cc
+++ b/third_party/blink/renderer/platform/wtf/doubly_linked_list_test.cc
@@ -19,7 +19,7 @@
   friend class WTF::DoublyLinkedListNode<TestNode>;
 
  public:
-  TestNode(int i) : i_(i) { ++test_node_counter; };
+  TestNode(int i) : i_(i) { ++test_node_counter; }
   ~TestNode() { --test_node_counter; }
   int i() { return i_; }
 
@@ -57,7 +57,7 @@
 
 int DoublyLinkedListTest::CompareInt(TestNode* first, TestNode* second) {
   return first->i() - second->i();
-};
+}
 
 bool DoublyLinkedListTest::IsSorted() const {
   for (auto* node = list_.Head(); node && node->Next(); node = node->Next()) {
@@ -78,7 +78,7 @@
             result.is_new_entry ? current_size + 1 : current_size);
   EXPECT_FALSE(list_.IsEmpty());
   return result;
-};
+}
 
 TEST_F(DoublyLinkedListTest, InsertEmpty) {
   CheckedInsert(1);
diff --git a/third_party/blink/renderer/platform/wtf/hash_map_test.cc b/third_party/blink/renderer/platform/wtf/hash_map_test.cc
index 16ccad0..8212fb0 100644
--- a/third_party/blink/renderer/platform/wtf/hash_map_test.cc
+++ b/third_party/blink/renderer/platform/wtf/hash_map_test.cc
@@ -565,11 +565,11 @@
   return map.size() == 3 && map.Contains(1) && map.Contains(2) &&
          map.Contains(3) && map.at(1) == 11 && map.at(2) == 22 &&
          map.at(3) == 33;
-};
+}
 
 HashMap<int, int> ReturnOneTwoThreeMap() {
   return {{1, 11}, {2, 22}, {3, 33}};
-};
+}
 
 TEST(HashMapTest, InitializerList) {
   HashMap<int, int> empty({});
diff --git a/third_party/blink/renderer/platform/wtf/list_hash_set_test.cc b/third_party/blink/renderer/platform/wtf/list_hash_set_test.cc
index 07059ab9..efe3098 100644
--- a/third_party/blink/renderer/platform/wtf/list_hash_set_test.cc
+++ b/third_party/blink/renderer/platform/wtf/list_hash_set_test.cc
@@ -482,7 +482,7 @@
 }
 
 struct Simple {
-  Simple(int value) : value_(value){};
+  Simple(int value) : value_(value) {}
   int value_;
 };
 
diff --git a/third_party/blink/renderer/platform/wtf/scoped_logger.cc b/third_party/blink/renderer/platform/wtf/scoped_logger.cc
index d61c9c81..deffc7c 100644
--- a/third_party/blink/renderer/platform/wtf/scoped_logger.cc
+++ b/third_party/blink/renderer/platform/wtf/scoped_logger.cc
@@ -36,7 +36,7 @@
 
 void ScopedLogger::SetPrintFuncForTests(PrintFunctionPtr ptr) {
   print_func_ = ptr;
-};
+}
 
 void ScopedLogger::Init(const char* format, va_list args) {
   Current() = this;
diff --git a/third_party/blink/renderer/platform/wtf/scoped_logger_test.cc b/third_party/blink/renderer/platform/wtf/scoped_logger_test.cc
index 789509f..3343651 100644
--- a/third_party/blink/renderer/platform/wtf/scoped_logger_test.cc
+++ b/third_party/blink/renderer/platform/wtf/scoped_logger_test.cc
@@ -43,7 +43,7 @@
       "  a2 0.5\n"
       ")\n",
       g_builder.ToString());
-};
+}
 #endif  // DCHECK_IS_ON()
 
 }  // namespace WTF
diff --git a/third_party/blink/tools/blinkpy/web_tests/try_flag.py b/third_party/blink/tools/blinkpy/web_tests/try_flag.py
index 10c692f..81b4c88 100644
--- a/third_party/blink/tools/blinkpy/web_tests/try_flag.py
+++ b/third_party/blink/tools/blinkpy/web_tests/try_flag.py
@@ -22,14 +22,14 @@
 
 # TODO(skobes): use blinkpy/config/builders.json instead of hardcoding these.
 BUILDER_CONFIGS = {
-    'linux_chromium_rel_ng': TestConfiguration('Linux', '', 'release'),
-    'mac_chromium_rel_ng': TestConfiguration('Mac', '', 'release'),
-    'win7_chromium_rel_ng': TestConfiguration('Win', '', 'release')
+    'linux-rel': TestConfiguration('Linux', '', 'release'),
+    'mac-rel': TestConfiguration('Mac', '', 'release'),
+    'win7-rel': TestConfiguration('Win', '', 'release')
 }
 BUILDER_BUCKETS = {
-    'linux_chromium_rel_ng': 'luci.chromium.try',
-    'mac_chromium_rel_ng': 'master.tryserver.chromium.mac',
-    'win7_chromium_rel_ng': 'master.tryserver.chromium.win'
+    'linux-rel': 'luci.chromium.try',
+    'mac-rel': 'luci.chromium.try',
+    'win7-rel': 'luci.chromium.try',
 }
 FLAG_FILE = 'additional-driver-flag.setting'
 
diff --git a/third_party/blink/tools/blinkpy/web_tests/try_flag_unittest.py b/third_party/blink/tools/blinkpy/web_tests/try_flag_unittest.py
index 166b1af..e60e2878 100644
--- a/third_party/blink/tools/blinkpy/web_tests/try_flag_unittest.py
+++ b/third_party/blink/tools/blinkpy/web_tests/try_flag_unittest.py
@@ -16,9 +16,9 @@
 class TryFlagTest(unittest.TestCase):
 
     def __init__(self, *args, **kwargs):
-        self.linux_build = Build('linux_chromium_rel_ng', 100)
-        self.mac_build = Build('mac_chromium_rel_ng', 101)
-        self.win_build = Build('win7_chromium_rel_ng', 102)
+        self.linux_build = Build('linux-rel', 100)
+        self.mac_build = Build('mac-rel', 101)
+        self.win_build = Build('win7-rel', 102)
         self.mock_try_results = {
             self.linux_build: TryJobStatus('COMPLETED', 'SUCCESS'),
             self.win_build: TryJobStatus('COMPLETED', 'SUCCESS'),
@@ -57,11 +57,11 @@
             ['git', 'cl', 'upload', '--bypass-hooks', '-f',
              '-m', 'Flag try job for --foo.'],
             ['git', 'cl', 'try', '-B', 'luci.chromium.try',
-             '-b', 'linux_chromium_rel_ng'],
-            ['git', 'cl', 'try', '-B', 'master.tryserver.chromium.mac',
-             '-b', 'mac_chromium_rel_ng'],
-            ['git', 'cl', 'try', '-B', 'master.tryserver.chromium.win',
-             '-b', 'win7_chromium_rel_ng']
+             '-b', 'linux-rel'],
+            ['git', 'cl', 'try', '-B', 'luci.chromium.try',
+             '-b', 'mac-rel'],
+            ['git', 'cl', 'try', '-B', 'luci.chromium.try',
+             '-b', 'win7-rel']
         ])
 
     def test_trigger(self):
diff --git a/third_party/blink/web_tests/FlagExpectations/enable-blink-features=LayoutNG b/third_party/blink/web_tests/FlagExpectations/enable-blink-features=LayoutNG
index ce2b242..73f86f91 100644
--- a/third_party/blink/web_tests/FlagExpectations/enable-blink-features=LayoutNG
+++ b/third_party/blink/web_tests/FlagExpectations/enable-blink-features=LayoutNG
@@ -448,6 +448,7 @@
 crbug.com/591099 fast/writing-mode/auto-sizing-orthogonal-flows.html [ Failure ]
 crbug.com/591099 fast/writing-mode/percentage-height-orthogonal-writing-modes.html [ Failure ]
 crbug.com/591099 fast/writing-mode/table-percent-width-quirk.html [ Pass ]
+crbug.com/930034 fast/writing-mode/vertical-rl-replaced-selection.html [ Failure ]
 crbug.com/591099 html/marquee/marquee-destroyed-without-removed-from-crash.html [ Pass ]
 crbug.com/591099 http/tests/activedomobject/media.html [ Crash Pass ]
 crbug.com/591099 http/tests/appcache/abort-cache-ondownloading.html [ Crash Pass ]
diff --git a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_5.json b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_5.json
index 0ab6bd7..32bc20d1 100644
--- a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_5.json
+++ b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_5.json
@@ -6277,12 +6277,6 @@
      {}
     ]
    ],
-   "uievents/click/auxclick_event-manual.html": [
-    [
-     "/uievents/click/auxclick_event-manual.html",
-     {}
-    ]
-   ],
    "uievents/click/click_event_target-manual.html": [
     [
      "/uievents/click/click_event_target-manual.html",
@@ -142619,6 +142613,11 @@
      {}
     ]
    ],
+   "css/css-syntax/decimal-points-in-numbers-expected.txt": [
+    [
+     {}
+    ]
+   ],
    "css/css-syntax/declarations-trim-whitespace-expected.txt": [
     [
      {}
@@ -187504,11 +187503,6 @@
      {}
     ]
    ],
-   "uievents/click/auxclick_event-manual-expected.txt": [
-    [
-     {}
-    ]
-   ],
    "uievents/constructors/README.md": [
     [
      {}
@@ -209294,6 +209288,12 @@
      {}
     ]
    ],
+   "css/css-box/inheritance.html": [
+    [
+     "/css/css-box/inheritance.html",
+     {}
+    ]
+   ],
    "css/css-box/parsing/clear-invalid.html": [
     [
      "/css/css-box/parsing/clear-invalid.html",
@@ -212976,12 +212976,6 @@
      {}
     ]
    ],
-   "css/css-multicol/multicol-span-all-under-clip-path-crash.html": [
-    [
-     "/css/css-multicol/multicol-span-all-under-clip-path-crash.html",
-     {}
-    ]
-   ],
    "css/css-multicol/parsing/column-count-computed.html": [
     [
      "/css/css-multicol/parsing/column-count-computed.html",
@@ -215100,6 +215094,12 @@
      {}
     ]
    ],
+   "css/css-syntax/decimal-points-in-numbers.html": [
+    [
+     "/css/css-syntax/decimal-points-in-numbers.html",
+     {}
+    ]
+   ],
    "css/css-syntax/declarations-trim-whitespace.html": [
     [
      "/css/css-syntax/declarations-trim-whitespace.html",
@@ -215148,6 +215148,12 @@
      {}
     ]
    ],
+   "css/css-syntax/url-whitespace-consumption.html": [
+    [
+     "/css/css-syntax/url-whitespace-consumption.html",
+     {}
+    ]
+   ],
    "css/css-syntax/whitespace.html": [
     [
      "/css/css-syntax/whitespace.html",
@@ -282444,6 +282450,22 @@
      {}
     ]
    ],
+   "uievents/click/auxclick_event.html": [
+    [
+     "/uievents/click/auxclick_event.html",
+     {
+      "testdriver": true
+     }
+    ]
+   ],
+   "uievents/click/mouse-dblclick-event.html": [
+    [
+     "/uievents/click/mouse-dblclick-event.html",
+     {
+      "testdriver": true
+     }
+    ]
+   ],
    "uievents/constructors/inputevent-constructor.html": [
     [
      "/uievents/constructors/inputevent-constructor.html",
@@ -333997,6 +334019,10 @@
    "dde409360faf79a301c3ae3ea34a995d154d7bb4",
    "support"
   ],
+  "css/css-box/inheritance.html": [
+   "5047b8b1df07cb1c774b5f579101d69b2482058a",
+   "testharness"
+  ],
   "css/css-box/parsing/clear-invalid.html": [
    "38d1821bc8189a5b42c4c0fa75b0195d69b5a91f",
    "testharness"
@@ -353881,10 +353907,6 @@
    "41ac007f00009d60c43b034bce68ded4cf23a007",
    "reftest"
   ],
-  "css/css-multicol/multicol-span-all-under-clip-path-crash.html": [
-   "d37a120b2e0c43be637b0418002db45a53c4975b",
-   "testharness"
-  ],
   "css/css-multicol/multicol-span-float-001-ref.xht": [
    "50addc37797b085d7c59e7389f99fca1c54c50c1",
    "support"
@@ -358561,6 +358583,14 @@
    "512df7a0ba0318bd4de16af5cf46b4feaac71eea",
    "testharness"
   ],
+  "css/css-syntax/decimal-points-in-numbers-expected.txt": [
+   "c802570ac0f0f3857fd82341af0ffcb6b24a1dfe",
+   "support"
+  ],
+  "css/css-syntax/decimal-points-in-numbers.html": [
+   "e59468678bee6b2e6f128844744da6e2100480ea",
+   "testharness"
+  ],
   "css/css-syntax/declarations-trim-whitespace-expected.txt": [
    "57d37ec9c701a51e3dcf9a7e30cf1b11e3083d13",
    "support"
@@ -358609,6 +358639,10 @@
    "2d34e05a98ba895cd0c98415bed32f248b235187",
    "testharness"
   ],
+  "css/css-syntax/url-whitespace-consumption.html": [
+   "2fd55873d9a34b5ec037c665ac44ba1b121da304",
+   "testharness"
+  ],
   "css/css-syntax/whitespace.html": [
    "bc7aa7ebda518a42a32a154c3ed13f00be86429a",
    "testharness"
@@ -453085,18 +453119,18 @@
    "065c0c78848af60244a860c2d785fa48c66e5ef5",
    "support"
   ],
-  "uievents/click/auxclick_event-manual-expected.txt": [
-   "65bcb5c67b0dc3549bf7bca5b25b415447996b99",
-   "support"
-  ],
-  "uievents/click/auxclick_event-manual.html": [
-   "786ebfaaebbc8f14710ac7b347a4383b77df0900",
-   "manual"
+  "uievents/click/auxclick_event.html": [
+   "9f4ffed96e6cb186f8441e9681c281d087ff8faf",
+   "testharness"
   ],
   "uievents/click/click_event_target-manual.html": [
    "1e5670262b5cb39cf74e34616f908d7cc3cc09cf",
    "manual"
   ],
+  "uievents/click/mouse-dblclick-event.html": [
+   "5bf0bbc07e00d3d01bfcc1379b8ac0c2f78fb7b7",
+   "testharness"
+  ],
   "uievents/constructors/README.md": [
    "097a5103959ae8978eaa6256efdf69a0898696a2",
    "support"
diff --git a/third_party/blink/web_tests/external/wpt/css/css-box/inheritance.html b/third_party/blink/web_tests/external/wpt/css/css-box/inheritance.html
new file mode 100644
index 0000000..5047b8b
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-box/inheritance.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Inheritance of CSS Box Model properties</title>
+<link rel="help" href="https://drafts.csswg.org/css-box-3/#property-index">
+<meta name="assert" content="Properties do not inherit.">
+<meta name="assert" content="length-percentage properties have initial value 0.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/css/support/inheritance-testcommon.js"></script>
+</head>
+<body>
+<div id="container">
+  <div id="target"></div>
+</div>
+<script>
+assert_not_inherited('margin-bottom', '0px', '10px');
+assert_not_inherited('margin-left', '0px', '10px');
+assert_not_inherited('margin-right', '0px', '10px');
+assert_not_inherited('margin-top', '0px', '10px');
+assert_not_inherited('margin-trim', 'none', 'all');
+assert_not_inherited('padding-bottom', '0px', '10px');
+assert_not_inherited('padding-left', '0px', '10px');
+assert_not_inherited('padding-right', '0px', '10px');
+assert_not_inherited('padding-top', '0px', '10px');
+</script>
+</body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-syntax/decimal-points-in-numbers-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-syntax/decimal-points-in-numbers-expected.txt
new file mode 100644
index 0000000..c802570a
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-syntax/decimal-points-in-numbers-expected.txt
@@ -0,0 +1,9 @@
+This is a testharness.js-based test.
+PASS decimal point between digits is valid in a number
+PASS decimal point before digits is valid in a number
+PASS decimal point after digits is invalid in a number
+PASS decimal point between digits is valid in a dimension
+PASS decimal point before digits is valid in a dimension
+FAIL decimal point after digits is invalid in a dimension assert_not_equals: got disallowed value "1px"
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/external/wpt/css/css-syntax/decimal-points-in-numbers.html b/third_party/blink/web_tests/external/wpt/css/css-syntax/decimal-points-in-numbers.html
new file mode 100644
index 0000000..e594686
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-syntax/decimal-points-in-numbers.html
@@ -0,0 +1,56 @@
+<!doctype html>
+<title>decimal points in numbers</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<meta name=author title="Tab Atkins-Bittner">
+<link rel=help href="https://drafts.csswg.org/css-syntax/#consume-number">
+
+<style>
+
+.foo {}
+
+</style>
+<script>
+
+function roundTripNumber(input) {
+    const rule = document.styleSheets[0].cssRules[0].style;
+    const fallback = "0";
+    rule.setProperty("line-height", fallback);
+    rule.setProperty("line-height", input);
+    const value = rule.getPropertyValue("line-height");
+    if(value == fallback) return false;
+    return value;
+}
+
+test(()=>{
+    assert_equals(roundTripNumber("1.0"), "1");
+}, "decimal point between digits is valid in a number");
+test(()=>{
+    assert_equals(roundTripNumber(".1"), "0.1");
+}, "decimal point before digits is valid in a number");
+test(()=>{
+    assert_not_equals(roundTripNumber("1."), "1");
+}, "decimal point after digits is invalid in a number");
+
+function roundTripDimension(input) {
+    const rule = document.styleSheets[0].cssRules[0].style;
+    const fallback = "0px";
+    rule.setProperty("width", fallback);
+    rule.setProperty("width", input);
+    const value = rule.getPropertyValue("width");
+    if(value == fallback) return false;
+    return value;
+}
+
+test(()=>{
+    assert_equals(roundTripDimension("1.0px"), "1px");
+}, "decimal point between digits is valid in a dimension");
+test(()=>{
+    assert_equals(roundTripDimension(".1px"), "0.1px");
+}, "decimal point before digits is valid in a dimension");
+test(()=>{
+    assert_not_equals(roundTripDimension("1.px"), "1px");
+}, "decimal point after digits is invalid in a dimension");
+
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-syntax/url-whitespace-consumption.html b/third_party/blink/web_tests/external/wpt/css/css-syntax/url-whitespace-consumption.html
new file mode 100644
index 0000000..2fd5587
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-syntax/url-whitespace-consumption.html
@@ -0,0 +1,32 @@
+<!doctype html>
+<title>url whitespace consumption</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style>
+
+.foo {}
+
+</style>
+
+<meta name=author title="Tab Atkins-Bittner">
+<link rel=help href="https://drafts.csswg.org/css-syntax/#consume-ident-like-token">
+
+<script>
+
+function roundTripUrl(input) {
+    const rule = document.styleSheets[0].cssRules[0].style;
+    const fallback = 'url("fallback")';
+    rule.setProperty("background-image", fallback);
+    rule.setProperty("background-image", input);
+    const value = rule.getPropertyValue("background-image");
+    if(value == fallback) return false;
+    return value;
+}
+
+test(()=>{
+    assert_equals(roundTripUrl('url("foo")'), 'url("foo")');
+    assert_equals(roundTripUrl('url( "foo")'), 'url("foo")');
+    assert_equals(roundTripUrl('url("foo" )'), 'url("foo")');
+}, "whitespace is optional between url( token and the string token");
+
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/domparsing/XMLSerializer-serializeToString-expected.txt b/third_party/blink/web_tests/external/wpt/domparsing/XMLSerializer-serializeToString-expected.txt
index 8729df1..965e6c1 100644
--- a/third_party/blink/web_tests/external/wpt/domparsing/XMLSerializer-serializeToString-expected.txt
+++ b/third_party/blink/web_tests/external/wpt/domparsing/XMLSerializer-serializeToString-expected.txt
@@ -3,6 +3,8 @@
 PASS Check if the default namespace is correctly reset.
 PASS Check if there is no redundant empty namespace declaration.
 PASS check XMLSerializer.serializeToString escapes attribute values for roundtripping
+PASS Check if attribute serialization takes into account of following xmlns:* attributes
+PASS Check if attribute serialization takes into account of the same prefix declared in an ancestor element
 PASS Check if generated prefixes match to "ns${index}".
 FAIL Check if "ns1" is generated even if the element already has xmlns:ns1. assert_equals: expected "<root xmlns:ns2=\"uri2\"><child xmlns:ns1=\"uri1\" xmlns:ns1=\"uri3\" ns1:attr1=\"value1\"/></root>" but got "<root xmlns:ns2=\"uri2\"><child xmlns:ns1=\"uri1\" xmlns:ns3=\"uri3\" ns3:attr1=\"value1\"/></root>"
 Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/external/wpt/domparsing/XMLSerializer-serializeToString.html b/third_party/blink/web_tests/external/wpt/domparsing/XMLSerializer-serializeToString.html
index d71da49..ab37348 100644
--- a/third_party/blink/web_tests/external/wpt/domparsing/XMLSerializer-serializeToString.html
+++ b/third_party/blink/web_tests/external/wpt/domparsing/XMLSerializer-serializeToString.html
@@ -56,6 +56,22 @@
 }, 'check XMLSerializer.serializeToString escapes attribute values for roundtripping');
 
 test(function() {
+  const root = (new Document()).createElement('root');
+  root.setAttributeNS('uri1', 'p:foobar', 'value1');
+  root.setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:p', 'uri2');
+  const xmlString = (new XMLSerializer()).serializeToString(root);
+  assert_equals(xmlString, '<root xmlns:ns1="uri1" ns1:foobar="value1" xmlns:p="uri2"/>');
+}, 'Check if attribute serialization takes into account of following xmlns:* attributes');
+
+test(function() {
+  const input = '<root xmlns:p="uri1"><child/></root>';
+  const root = (new DOMParser()).parseFromString(input, 'text/xml').documentElement;
+  root.firstChild.setAttributeNS('uri2', 'p:foobar', 'v');
+  const xmlString = (new XMLSerializer()).serializeToString(root);
+  assert_equals(xmlString, '<root xmlns:p="uri1"><child xmlns:ns1="uri2" ns1:foobar="v"/></root>');
+}, 'Check if attribute serialization takes into account of the same prefix declared in an ancestor element');
+
+test(function() {
   const input = '<root><child1/><child2/></root>';
   const root = (new DOMParser()).parseFromString(input, 'text/xml').documentElement;
   root.firstChild.setAttributeNS('uri1', 'attr1', 'value1');
diff --git a/third_party/blink/web_tests/fast/peerconnection/RTCPeerConnection-many.html b/third_party/blink/web_tests/fast/peerconnection/RTCPeerConnection-many.html
index 5aedc64..7312192 100644
--- a/third_party/blink/web_tests/fast/peerconnection/RTCPeerConnection-many.html
+++ b/third_party/blink/web_tests/fast/peerconnection/RTCPeerConnection-many.html
@@ -39,11 +39,10 @@
     assert_throws("UnknownError", allocatePeerConnection,
                   'Creating too many RTCPeerConnections gives UnknownError');
   } finally {
-    // On swarming bots running webkit_layout_tests (such as
-    // win7_chromium_rel_ng), garbage collection is not guaranteed to occur
-    // between test pages. As such we cannot assume that the initial count is 0,
-    // and we must clean up after this test regardless of test result or
-    // unrelated tests may fail.
+    // On swarming bots running webkit_layout_tests (such as win7-rel), garbage
+    // collection is not guaranteed to occur between test pages. As such we
+    // cannot assume that the initial count is 0, and we must clean up after
+    // this test regardless of test result or unrelated tests may fail.
     let totalAllocatedPeerConnections = internals.peerConnectionCount();
     let peerConnectionsAllocatedByTest = peerConnections.length;
     cleanUpPeerConnectionsAndGarbageCollect();
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/compositing/squashing/selection-repaint-with-gaps-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/compositing/squashing/selection-repaint-with-gaps-expected.txt
index 1044da7..3f66aed 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/compositing/squashing/selection-repaint-with-gaps-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/compositing/squashing/selection-repaint-with-gaps-expected.txt
@@ -35,12 +35,12 @@
         {
           "object": "NGPhysicalTextFragment 'ipsum'",
           "rect": [0, 80, 40, 40],
-          "reason": "selection"
+          "reason": "geometry"
         },
         {
           "object": "NGPhysicalTextFragment 'lorem'",
           "rect": [0, 80, 40, 40],
-          "reason": "selection"
+          "reason": "geometry"
         }
       ]
     }
@@ -95,22 +95,22 @@
         {
           "object": "NGPhysicalTextFragment 'ipsum'",
           "rect": [0, 160, 40, 40],
-          "reason": "selection"
+          "reason": "geometry"
         },
         {
           "object": "NGPhysicalTextFragment 'lorem'",
           "rect": [0, 160, 40, 40],
-          "reason": "selection"
+          "reason": "geometry"
         },
         {
           "object": "NGPhysicalTextFragment 'ipsum'",
           "rect": [0, 80, 40, 40],
-          "reason": "selection"
+          "reason": "geometry"
         },
         {
           "object": "NGPhysicalTextFragment 'lorem'",
           "rect": [0, 80, 40, 40],
-          "reason": "selection"
+          "reason": "geometry"
         }
       ]
     }
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/selection/invalidation-rect-includes-newline-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/selection/invalidation-rect-includes-newline-expected.txt
index 6070a7d4b..3154b365 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/selection/invalidation-rect-includes-newline-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/selection/invalidation-rect-includes-newline-expected.txt
@@ -20,12 +20,12 @@
         {
           "object": "NGPhysicalTextFragment 'xx'",
           "rect": [8, 8, 48, 32],
-          "reason": "selection"
+          "reason": "geometry"
         },
         {
           "object": "NGPhysicalTextFragment 'y'",
           "rect": [8, 8, 48, 32],
-          "reason": "selection"
+          "reason": "geometry"
         }
       ]
     }
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/selection/invalidation-rect-includes-newline-for-rtl-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/selection/invalidation-rect-includes-newline-for-rtl-expected.txt
index 27aaf261..2019c0a 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/selection/invalidation-rect-includes-newline-for-rtl-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/selection/invalidation-rect-includes-newline-for-rtl-expected.txt
@@ -20,12 +20,12 @@
         {
           "object": "NGPhysicalTextFragment 'xx'",
           "rect": [0, 8, 40, 32],
-          "reason": "selection"
+          "reason": "geometry"
         },
         {
           "object": "NGPhysicalTextFragment 'y'",
           "rect": [0, 8, 40, 32],
-          "reason": "selection"
+          "reason": "geometry"
         }
       ]
     }
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/selection/invalidation-rect-includes-newline-for-vertical-lr-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/selection/invalidation-rect-includes-newline-for-vertical-lr-expected.txt
index 50593eb3..8ca3c09 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/selection/invalidation-rect-includes-newline-for-vertical-lr-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/selection/invalidation-rect-includes-newline-for-vertical-lr-expected.txt
@@ -20,12 +20,12 @@
         {
           "object": "NGPhysicalTextFragment 'xx'",
           "rect": [8, 8, 32, 48],
-          "reason": "selection"
+          "reason": "geometry"
         },
         {
           "object": "NGPhysicalTextFragment 'y'",
           "rect": [8, 8, 32, 48],
-          "reason": "selection"
+          "reason": "geometry"
         }
       ]
     }
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/selection/invalidation-rect-includes-newline-for-vertical-rl-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/selection/invalidation-rect-includes-newline-for-vertical-rl-expected.txt
index 50593eb3..8ca3c09 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/selection/invalidation-rect-includes-newline-for-vertical-rl-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/selection/invalidation-rect-includes-newline-for-vertical-rl-expected.txt
@@ -20,12 +20,12 @@
         {
           "object": "NGPhysicalTextFragment 'xx'",
           "rect": [8, 8, 32, 48],
-          "reason": "selection"
+          "reason": "geometry"
         },
         {
           "object": "NGPhysicalTextFragment 'y'",
           "rect": [8, 8, 32, 48],
-          "reason": "selection"
+          "reason": "geometry"
         }
       ]
     }
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/selection/selection-clear-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/selection/selection-clear-expected.txt
index 08797be0c..e802c6b 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/selection/selection-clear-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/selection/selection-clear-expected.txt
@@ -30,7 +30,7 @@
         {
           "object": "NGPhysicalTextFragment '\u00A0'",
           "rect": [8, 8, 97, 200],
-          "reason": "selection"
+          "reason": "appeared"
         }
       ]
     }
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/selection/selection-partial-invalidation-between-blocks-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/selection/selection-partial-invalidation-between-blocks-expected.txt
index 832c6a9..0209a31 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/selection/selection-partial-invalidation-between-blocks-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/selection/selection-partial-invalidation-between-blocks-expected.txt
@@ -20,12 +20,12 @@
         {
           "object": "NGPhysicalTextFragment 'Second cell'",
           "rect": [11, 35, 74, 20],
-          "reason": "selection"
+          "reason": "geometry"
         },
         {
           "object": "NGPhysicalTextFragment 'First cell'",
           "rect": [11, 11, 58, 20],
-          "reason": "selection"
+          "reason": "geometry"
         }
       ]
     }
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/selection/selection-within-composited-scroller-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/selection/selection-within-composited-scroller-expected.txt
index 516fd53..5f4c110 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/selection/selection-within-composited-scroller-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/selection/selection-within-composited-scroller-expected.txt
@@ -39,7 +39,7 @@
         {
           "object": "NGPhysicalTextFragment 'test'",
           "rect": [0, 610, 22, 20],
-          "reason": "selection"
+          "reason": "geometry"
         }
       ],
       "transform": 1
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/selection/text-selection-rect-in-overflow-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/selection/text-selection-rect-in-overflow-expected.txt
index b86ac261..bd789f0 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/selection/text-selection-rect-in-overflow-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/selection/text-selection-rect-in-overflow-expected.txt
@@ -20,7 +20,7 @@
         {
           "object": "NGPhysicalTextFragment 'Should have green background'",
           "rect": [8, 8, 197, 20],
-          "reason": "selection"
+          "reason": "geometry"
         }
       ]
     }
diff --git a/third_party/dav1d/README.chromium b/third_party/dav1d/README.chromium
index 431452c..0d414b8 100644
--- a/third_party/dav1d/README.chromium
+++ b/third_party/dav1d/README.chromium
@@ -1,7 +1,7 @@
 Name: dav1d is an AV1 decoder :)
 Short Name: dav1d
 URL: https://code.videolan.org/videolan/dav1d
-Version: f1b756ef5bdc0bb759b2b140f15362fec024c1ff
+Version: 3cf4d32e74e38b99036c21b7d2d0fb2108223221
 License: 2-Clause BSD
 License File: LICENSE, copied from: libdav1d/COPYING
 Security Critical: yes
diff --git a/third_party/dav1d/config/win/x64/config.h b/third_party/dav1d/config/win/x64/config.h
index f7d8ef6..5827ada7 100644
--- a/third_party/dav1d/config/win/x64/config.h
+++ b/third_party/dav1d/config/win/x64/config.h
@@ -25,4 +25,6 @@
 
 #define HAVE_ASM 1
 
+#define HAVE_IO_H 1
+
 // #define STACK_ALIGNMENT 16 -- Stack alignment is controlled by Chromium
diff --git a/third_party/dav1d/config/win/x86/config.h b/third_party/dav1d/config/win/x86/config.h
index 75d2ac5..2706de1 100644
--- a/third_party/dav1d/config/win/x86/config.h
+++ b/third_party/dav1d/config/win/x86/config.h
@@ -25,6 +25,8 @@
 
 #define HAVE_ASM 1
 
+#define HAVE_IO_H 1
+
 #define PREFIX 1
 
 // #define STACK_ALIGNMENT 4 -- Stack alignment is controlled by Chromium
diff --git a/third_party/dav1d/dav1d_generated.gni b/third_party/dav1d/dav1d_generated.gni
index d13ce35..3c5b4f7 100644
--- a/third_party/dav1d/dav1d_generated.gni
+++ b/third_party/dav1d/dav1d_generated.gni
@@ -13,6 +13,7 @@
   "libdav1d/src/x86/itx_ssse3.asm",
   "libdav1d/src/x86/loopfilter.asm",
   "libdav1d/src/x86/looprestoration.asm",
+  "libdav1d/src/x86/looprestoration_ssse3.asm",
   "libdav1d/src/x86/mc.asm",
   "libdav1d/src/x86/mc_ssse3.asm",
 ]
@@ -27,17 +28,20 @@
 ]
 
 arm32_asm_sources = [
+  "libdav1d/src/arm/32/looprestoration.S",
   "libdav1d/src/arm/32/mc.S",
   "libdav1d/src/arm/32/util.S",
 ]
 
 arm64_asm_sources = [
+  "libdav1d/src/arm/64/cdef.S",
   "libdav1d/src/arm/64/looprestoration.S",
   "libdav1d/src/arm/64/mc.S",
   "libdav1d/src/arm/64/util.S",
 ]
 
 arm_template_sources = [
+  "libdav1d/src/arm/cdef_init_tmpl.c",
   "libdav1d/src/arm/looprestoration_init_tmpl.c",
   "libdav1d/src/arm/mc_init_tmpl.c",
 ]
diff --git a/third_party/pffft/BUILD.gn b/third_party/pffft/BUILD.gn
index 06f121a..ff7e965 100644
--- a/third_party/pffft/BUILD.gn
+++ b/third_party/pffft/BUILD.gn
@@ -5,8 +5,6 @@
 import("//testing/libfuzzer/fuzzer_test.gni")
 import("//testing/test.gni")
 
-# TODO(crbug.com/webrtc/9577): Add architecture specific flags.
-
 config("simd_config") {
   # TODO(crbug.com/webrtc/9577): Use SIMD while fuzzing.
   # TODO(crbug.com/webrtc/9577): Fix SIMD not detected on Android, fuchsia, iOS.
@@ -15,8 +13,20 @@
   }
 }
 
+config("common_config") {
+  if (is_win) {
+    defines = [
+      # Required to use math constants from math.h.
+      "_USE_MATH_DEFINES",
+    ]
+  }
+}
+
 static_library("pffft") {
-  configs += [ ":simd_config" ]
+  configs += [
+    ":common_config",
+    ":simd_config",
+  ]
   sources = [
     "src/pffft.c",
     "src/pffft.h",
@@ -75,6 +85,9 @@
 # This target must be used only for testing and benchmark purposes.
 static_library("fftpack") {
   testonly = true
+  configs += [
+    ":common_config",
+  ]
   sources = [
     "src/fftpack.c",
     "src/fftpack.h",
@@ -83,8 +96,11 @@
 }
 
 executable("pffft_benchmark") {
-  configs += [ ":simd_config" ]
   testonly = true
+  configs += [
+    ":common_config",
+    ":simd_config",
+  ]
   sources = [
     "src/test_pffft.c",
   ]
@@ -95,6 +111,7 @@
 }
 
 test("pffft_unittest") {
+  testonly = true
   sources = [
     "pffft_unittest.cc",
   ]
diff --git a/third_party/pffft/README.chromium b/third_party/pffft/README.chromium
index eab510e..f3931a3 100644
--- a/third_party/pffft/README.chromium
+++ b/third_party/pffft/README.chromium
@@ -13,9 +13,5 @@
 PFFFT does 1D Fast Fourier Transforms, of single precision real and complex vectors. It tries do it fast, it tries to be correct, and it tries to be small. Computations do take advantage of SSE1 instructions on x86 cpus, Altivec on powerpc cpus, and NEON on ARM cpus.
 
 Local Modifications:
- * 01-add_m_pi.diff: define M_PI if not defined
- * 02-rmv_printf.diff: remove printf and stop including stdio.h
- * 03-decl_validate_simd.diff: declare validate_pffft_simd() in pffft.h
- * 04-add_m_ln2.diff: define M_LN2 if not defined
- * 05-add_m_sqrt2.diff: define M_SQRT2 if not defined
- * 06-add_m_pi_fftpack.diff: define M_PI if not defined (fftpack)
+ * 01-rmv_printf.diff: remove printf and stop including stdio.h
+ * 02-decl_validate_simd.diff: declare validate_pffft_simd() in pffft.h
diff --git a/third_party/pffft/patches/01-add_m_pi.diff b/third_party/pffft/patches/01-add_m_pi.diff
deleted file mode 100644
index aa4b98c7..0000000
--- a/third_party/pffft/patches/01-add_m_pi.diff
+++ /dev/null
@@ -1,14 +0,0 @@
-diff --git a/third_party/pffft/src/pffft.c b/third_party/pffft/src/pffft.c
-index 0603f2b1f698..7934db448a09 100644
---- a/third_party/pffft/src/pffft.c
-+++ b/third_party/pffft/src/pffft.c
-@@ -82,6 +82,9 @@
- #  define VLA_ARRAY_ON_STACK(type__, varname__, size__) type__ *varname__ = (type__*)_alloca(size__ * sizeof(type__))
- #endif
- 
-+#ifndef M_PI
-+#define M_PI 3.14159265358979323846
-+#endif
- 
- /* 
-    vector support macros: the rest of the code is independant of
diff --git a/third_party/pffft/patches/02-rmv_printf.diff b/third_party/pffft/patches/01-rmv_printf.diff
similarity index 100%
rename from third_party/pffft/patches/02-rmv_printf.diff
rename to third_party/pffft/patches/01-rmv_printf.diff
diff --git a/third_party/pffft/patches/03-decl_validate_simd.diff b/third_party/pffft/patches/02-decl_validate_simd.diff
similarity index 100%
rename from third_party/pffft/patches/03-decl_validate_simd.diff
rename to third_party/pffft/patches/02-decl_validate_simd.diff
diff --git a/third_party/pffft/patches/04-add_m_ln2.diff b/third_party/pffft/patches/04-add_m_ln2.diff
deleted file mode 100644
index 171c12ab..0000000
--- a/third_party/pffft/patches/04-add_m_ln2.diff
+++ /dev/null
@@ -1,15 +0,0 @@
-diff --git a/third_party/pffft/src/test_pffft.c b/third_party/pffft/src/test_pffft.c
-index ab78b4dcc0d5..deaf98ed9f09 100644
---- a/third_party/pffft/src/test_pffft.c
-+++ b/third_party/pffft/src/test_pffft.c
-@@ -45,6 +45,10 @@
- #  include <fftw3.h>
- #endif
- 
-+#ifndef M_LN2
-+#define M_LN2 0.693147180559945309417
-+#endif
-+
- #define MAX(x,y) ((x)>(y)?(x):(y))
- 
- double frand() {
diff --git a/third_party/pffft/patches/05-add_m_sqrt2.diff b/third_party/pffft/patches/05-add_m_sqrt2.diff
deleted file mode 100644
index 5b62372..0000000
--- a/third_party/pffft/patches/05-add_m_sqrt2.diff
+++ /dev/null
@@ -1,15 +0,0 @@
-diff --git a/third_party/pffft/src/pffft.c b/third_party/pffft/src/pffft.c
-index 2e0c2f651438..b89e6d7b6fbc 100644
---- a/third_party/pffft/src/pffft.c
-+++ b/third_party/pffft/src/pffft.c
-@@ -86,6 +86,10 @@
- #define M_PI 3.14159265358979323846
- #endif
- 
-+#ifndef M_SQRT2
-+#define M_SQRT2 1.41421356237309504880
-+#endif
-+
- /* 
-    vector support macros: the rest of the code is independant of
-    SSE/Altivec/NEON -- adding support for other platforms with 4-element
diff --git a/third_party/pffft/patches/06-add_m_pi_fftpack.diff b/third_party/pffft/patches/06-add_m_pi_fftpack.diff
deleted file mode 100644
index 0042440e..0000000
--- a/third_party/pffft/patches/06-add_m_pi_fftpack.diff
+++ /dev/null
@@ -1,15 +0,0 @@
-diff --git a/third_party/pffft/src/fftpack.c b/third_party/pffft/src/fftpack.c
-index b6375a80dab4..d801d16602b2 100644
---- a/third_party/pffft/src/fftpack.c
-+++ b/third_party/pffft/src/fftpack.c
-@@ -54,6 +54,10 @@
- #include "fftpack.h"
- #include <math.h>
- 
-+#ifndef M_PI
-+#define M_PI 3.14159265358979323846
-+#endif
-+
- typedef fftpack_real real;
- typedef fftpack_int  integer;
- 
diff --git a/third_party/pffft/src/fftpack.c b/third_party/pffft/src/fftpack.c
index d801d16..b6375a80 100644
--- a/third_party/pffft/src/fftpack.c
+++ b/third_party/pffft/src/fftpack.c
@@ -54,10 +54,6 @@
 #include "fftpack.h"
 #include <math.h>
 
-#ifndef M_PI
-#define M_PI 3.14159265358979323846
-#endif
-
 typedef fftpack_real real;
 typedef fftpack_int  integer;
 
diff --git a/third_party/pffft/src/pffft.c b/third_party/pffft/src/pffft.c
index b89e6d7b..776f564a 100644
--- a/third_party/pffft/src/pffft.c
+++ b/third_party/pffft/src/pffft.c
@@ -82,13 +82,6 @@
 #  define VLA_ARRAY_ON_STACK(type__, varname__, size__) type__ *varname__ = (type__*)_alloca(size__ * sizeof(type__))
 #endif
 
-#ifndef M_PI
-#define M_PI 3.14159265358979323846
-#endif
-
-#ifndef M_SQRT2
-#define M_SQRT2 1.41421356237309504880
-#endif
 
 /* 
    vector support macros: the rest of the code is independant of
diff --git a/third_party/pffft/src/test_pffft.c b/third_party/pffft/src/test_pffft.c
index deaf98e..ab78b4d 100644
--- a/third_party/pffft/src/test_pffft.c
+++ b/third_party/pffft/src/test_pffft.c
@@ -45,10 +45,6 @@
 #  include <fftw3.h>
 #endif
 
-#ifndef M_LN2
-#define M_LN2 0.693147180559945309417
-#endif
-
 #define MAX(x,y) ((x)>(y)?(x):(y))
 
 double frand() {
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl
index 628ad0b4..e7fc99d4 100644
--- a/tools/mb/mb_config.pyl
+++ b/tools/mb/mb_config.pyl
@@ -393,8 +393,8 @@
       'fuchsia-arm64-cast': 'release_bot_fuchsia_arm64_cast',
       'fuchsia-x64-cast': 'release_bot_fuchsia_cast',
       'linux-gcc-rel': 'release_bot_x86_minimal_symbols_no_clang_cxx11',
-      # linux-jumbo-rel is identical to linux_chromium_rel_ng for perf
-      # comparisons, except for the jumbo part.
+      # linux-jumbo-rel is identical to linux-rel for perf comparisons, except
+      # for the jumbo part.
       'linux-jumbo-rel': 'gpu_tests_release_bot_jumbo_no_symbols_use_dummy_lastchange',
       'linux-ozone-rel': 'ozone_linux_release_bot',
       'linux-xenial-rel': 'release_bot',
@@ -2336,7 +2336,7 @@
     },
 
     'vulkan': {
-      'gn_args': 'android32_ndk_api_level=24 android64_ndk_api_level=24',
+      'gn_args': 'android32_ndk_api_level=26 android64_ndk_api_level=26',
     },
 
     'win_cross': {
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index 47e0e7e8..6451b1d 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -12046,9 +12046,9 @@
 
 <histogram name="Bluetooth.Android.GATTConnection.Disconnected.Result"
     enum="AndroidGATTConnectionErrorCodes">
-  <owner>jyasskin@chromium.org</owner>
+  <owner>odejesush@chromium.org</owner>
   <owner>ortuno@chromium.org</owner>
-  <owner>scheib@chromium.org</owner>
+  <owner>reillyg@chromium.org</owner>
   <summary>
     Disconnected GATT connection status codes. Used to better understand errors
     seen in Android.
@@ -12057,9 +12057,9 @@
 
 <histogram name="Bluetooth.Android.GATTConnection.Failure.Result"
     enum="AndroidGATTConnectionErrorCodes">
-  <owner>jyasskin@chromium.org</owner>
+  <owner>odejesush@chromium.org</owner>
   <owner>ortuno@chromium.org</owner>
-  <owner>scheib@chromium.org</owner>
+  <owner>reillyg@chromium.org</owner>
   <summary>
     Failed GATT connection error codes. Used to better understand errors seen in
     Android.
@@ -12068,9 +12068,9 @@
 
 <histogram name="Bluetooth.Android.GATTConnection.Success.Result"
     enum="AndroidGATTConnectionErrorCodes">
-  <owner>jyasskin@chromium.org</owner>
+  <owner>odejesush@chromium.org</owner>
   <owner>ortuno@chromium.org</owner>
-  <owner>scheib@chromium.org</owner>
+  <owner>reillyg@chromium.org</owner>
   <summary>
     Successful GATT connection result codes. Used to better understand Android
     results.
@@ -12098,9 +12098,9 @@
 
 <histogram name="Bluetooth.DiscoverySession.Start.Outcome"
     enum="BluetoothDiscoveryOutcomes">
-  <owner>jyasskin@chromium.org</owner>
+  <owner>odejesush@chromium.org</owner>
   <owner>ortuno@chromium.org</owner>
-  <owner>scheib@chromium.org</owner>
+  <owner>reillyg@chromium.org</owner>
   <summary>
     Records the outcome of calls to BluetoothAdapter::StartDiscoverySession.
     Used to prioritize efforts to fix failures of this function.
@@ -12109,9 +12109,9 @@
 
 <histogram name="Bluetooth.DiscoverySession.Stop.Outcome"
     enum="BluetoothDiscoveryOutcomes">
-  <owner>jyasskin@chromium.org</owner>
+  <owner>odejesush@chromium.org</owner>
   <owner>ortuno@chromium.org</owner>
-  <owner>scheib@chromium.org</owner>
+  <owner>reillyg@chromium.org</owner>
   <summary>
     Records the outcome of calls to BluetoothDiscoverySession::Stop. Used to
     prioritize efforts to fix failures of this function.
@@ -12124,9 +12124,9 @@
     Bluetooth.Web.Characteristic.ReadValue and
     Bluetooth.Web.Characteristic.WriteValue.
   </obsolete>
-  <owner>jyasskin@chromium.org</owner>
+  <owner>odejesush@chromium.org</owner>
   <owner>ortuno@chromium.org</owner>
-  <owner>scheib@chromium.org</owner>
+  <owner>reillyg@chromium.org</owner>
   <summary>
     Records how many times each GATT Error has occured. The results will be used
     to determine how common this errors are and if we need to provide better
@@ -12138,8 +12138,9 @@
     enum="MacOSBluetoothOperationsResult">
 <!-- Name completed by histogram_suffixes name="WebBluetoothMacOSAPIs" -->
 
-  <owner>scheib@chromium.org</owner>
-  <owner>device-dev@chromium.org</owner>
+  <owner>odejesush@chromium.org</owner>
+  <owner>ortuno@chromium.org</owner>
+  <owner>reillyg@chromium.org</owner>
   <summary>
     Records how many times each macOS GATT error has occured. The results will
     be used to determine how commun this errors are and if we need to provide
@@ -12169,9 +12170,9 @@
   <obsolete>
     Deprecated 08/2015 and replaced by Bluetooth.Web.RequestDevice.Outcome.
   </obsolete>
-  <owner>jyasskin@chromium.org</owner>
+  <owner>odejesush@chromium.org</owner>
   <owner>ortuno@chromium.org</owner>
-  <owner>scheib@chromium.org</owner>
+  <owner>reillyg@chromium.org</owner>
   <summary>
     Records the result of a navigator.bluetooth.requestDevice() call. Used to
     understand what errors developers are getting so we can target efforts
@@ -12183,9 +12184,9 @@
 <histogram name="Bluetooth.Web.Android" enum="AndroidGATTStatusResult">
 <!-- Name completed by histogram_suffixes name="AndroidGATTEvents" -->
 
-  <owner>jyasskin@chromium.org</owner>
+  <owner>odejesush@chromium.org</owner>
   <owner>ortuno@chromium.org</owner>
-  <owner>scheib@chromium.org</owner>
+  <owner>reillyg@chromium.org</owner>
   <summary>'status' values returned by Android GATT event.</summary>
 </histogram>
 
@@ -12195,9 +12196,9 @@
     Deprecated as of 11/2016, replaced by
     Bluetooth.Web.Blocklist.ParsedNonEmptyString.
   </obsolete>
-  <owner>jyasskin@chromium.org</owner>
+  <owner>odejesush@chromium.org</owner>
   <owner>ortuno@chromium.org</owner>
-  <owner>scheib@chromium.org</owner>
+  <owner>reillyg@chromium.org</owner>
   <summary>
     Records the result of BluetoothBlacklist::Add parsing a non-empty string.
     These strings will be updated dynamically by a server, and this histogram
@@ -12209,9 +12210,9 @@
 
 <histogram name="Bluetooth.Web.Blocklist.ParsedNonEmptyString"
     enum="BooleanSuccess">
-  <owner>jyasskin@chromium.org</owner>
+  <owner>odejesush@chromium.org</owner>
   <owner>ortuno@chromium.org</owner>
-  <owner>scheib@chromium.org</owner>
+  <owner>reillyg@chromium.org</owner>
   <summary>
     Records the result of BluetoothBlocklist::Add parsing a non-empty string.
     These strings will be updated dynamically by a server, and this histogram
@@ -12223,9 +12224,9 @@
 
 <histogram name="Bluetooth.Web.Characteristic.ReadValue.Outcome"
     enum="WebBluetoothGATTOperationOutcome">
-  <owner>jyasskin@chromium.org</owner>
+  <owner>odejesush@chromium.org</owner>
   <owner>ortuno@chromium.org</owner>
-  <owner>scheib@chromium.org</owner>
+  <owner>reillyg@chromium.org</owner>
   <summary>
     Records the outcome of a call to characteristic.readValue(). Used to know
     what types of errors users are seeing. The results will be used to determine
@@ -12236,9 +12237,9 @@
 
 <histogram name="Bluetooth.Web.Characteristic.StartNotifications.Outcome"
     enum="WebBluetoothGATTOperationOutcome">
-  <owner>jyasskin@chromium.org</owner>
+  <owner>odejesush@chromium.org</owner>
   <owner>ortuno@chromium.org</owner>
-  <owner>scheib@chromium.org</owner>
+  <owner>reillyg@chromium.org</owner>
   <summary>
     Records the outcome of a call to characteristic.startNofications(). Used to
     know what types of errors users are seeing. The results will be used to
@@ -12249,9 +12250,9 @@
 
 <histogram name="Bluetooth.Web.Characteristic.WriteValue.Outcome"
     enum="WebBluetoothGATTOperationOutcome">
-  <owner>jyasskin@chromium.org</owner>
+  <owner>odejesush@chromium.org</owner>
   <owner>ortuno@chromium.org</owner>
-  <owner>scheib@chromium.org</owner>
+  <owner>reillyg@chromium.org</owner>
   <summary>
     Records the outcome of a call to characteristic.writeValue(). Used to know
     what types of errors users are seeing. The results will be used to determine
@@ -12261,9 +12262,9 @@
 </histogram>
 
 <histogram name="Bluetooth.Web.ChooserInteraction" enum="BooleanInvalid">
-  <owner>jyasskin@chromium.org</owner>
+  <owner>odejesush@chromium.org</owner>
   <owner>ortuno@chromium.org</owner>
-  <owner>scheib@chromium.org</owner>
+  <owner>reillyg@chromium.org</owner>
   <summary>
     Counts how many times users interact with a regular chooser vs. an invalid
     chooser. (A chooser is invalid when it's event handler becomes null.)
@@ -12272,9 +12273,9 @@
 
 <histogram name="Bluetooth.Web.ConnectGATT.Outcome"
     enum="WebBluetoothConnectGATTOutcome">
-  <owner>jyasskin@chromium.org</owner>
+  <owner>odejesush@chromium.org</owner>
   <owner>ortuno@chromium.org</owner>
-  <owner>scheib@chromium.org</owner>
+  <owner>reillyg@chromium.org</owner>
   <summary>
     Records the result of a device.gatt.connect() call. Used to understand what
     errors developers are getting so we can target efforts toward the most
@@ -12283,9 +12284,9 @@
 </histogram>
 
 <histogram name="Bluetooth.Web.ConnectGATT.TimeFailed" units="ms">
-  <owner>jyasskin@chromium.org</owner>
+  <owner>odejesush@chromium.org</owner>
   <owner>ortuno@chromium.org</owner>
-  <owner>scheib@chromium.org</owner>
+  <owner>reillyg@chromium.org</owner>
   <summary>
     Records how long it takes for a connection attempt to fail. Use to let
     developers know how to better wait for and handle connection errors.
@@ -12293,9 +12294,9 @@
 </histogram>
 
 <histogram name="Bluetooth.Web.ConnectGATT.TimeSuccess" units="ms">
-  <owner>jyasskin@chromium.org</owner>
+  <owner>odejesush@chromium.org</owner>
   <owner>ortuno@chromium.org</owner>
-  <owner>scheib@chromium.org</owner>
+  <owner>reillyg@chromium.org</owner>
   <summary>
     Records how long it takes for a device to successfully connect. Use to let
     developers know how long it should take to connect to a BLE device.
@@ -12304,9 +12305,9 @@
 
 <histogram name="Bluetooth.Web.Descriptor.ReadValue.Outcome"
     enum="WebBluetoothGATTOperationOutcome">
-  <owner>jyasskin@chromium.org</owner>
+  <owner>odejesush@chromium.org</owner>
   <owner>ortuno@chromium.org</owner>
-  <owner>scheib@chromium.org</owner>
+  <owner>reillyg@chromium.org</owner>
   <summary>
     Records the outcome of a call to descriptor.readValue(). Used to know what
     types of errors users are seeing. The results will be used to determine how
@@ -12317,9 +12318,9 @@
 
 <histogram name="Bluetooth.Web.Descriptor.WriteValue.Outcome"
     enum="WebBluetoothGATTOperationOutcome">
-  <owner>jyasskin@chromium.org</owner>
+  <owner>odejesush@chromium.org</owner>
   <owner>ortuno@chromium.org</owner>
-  <owner>scheib@chromium.org</owner>
+  <owner>reillyg@chromium.org</owner>
   <summary>
     Records the outcome of a call to descriptor.writeValue(). Used to know what
     types of errors users are seeing. The results will be used to determine how
@@ -12333,9 +12334,9 @@
     Deprecated as of 3/2017. Replaced by using blink IDL annotation MeasureAs
     which appear in Blink.UseCounter.Features.
   </obsolete>
-  <owner>jyasskin@chromium.org</owner>
+  <owner>odejesush@chromium.org</owner>
   <owner>ortuno@chromium.org</owner>
-  <owner>scheib@chromium.org</owner>
+  <owner>reillyg@chromium.org</owner>
   <summary>
     Counts the number of times each call to a WebBluetooth function is done.
   </summary>
@@ -12343,9 +12344,9 @@
 
 <histogram name="Bluetooth.Web.GetCharacteristic.Characteristic"
     enum="GATTCharacteristicHash">
-  <owner>jyasskin@chromium.org</owner>
+  <owner>odejesush@chromium.org</owner>
   <owner>ortuno@chromium.org</owner>
-  <owner>scheib@chromium.org</owner>
+  <owner>reillyg@chromium.org</owner>
   <summary>
     Records the UUIDs used when getting a characteristic. The recorded value is
     a 31-bit hash of the UUID. Used to know what types of characteristics to
@@ -12355,9 +12356,9 @@
 
 <histogram name="Bluetooth.Web.GetCharacteristic.Outcome"
     enum="WebBluetoothGetCharacteristicOutcome">
-  <owner>jyasskin@chromium.org</owner>
+  <owner>odejesush@chromium.org</owner>
   <owner>ortuno@chromium.org</owner>
-  <owner>scheib@chromium.org</owner>
+  <owner>reillyg@chromium.org</owner>
   <summary>
     Records the outcome of a call to getCharacteristic(). Used to understand
     what errors developers are getting so we can target efforts toward the most
@@ -12367,9 +12368,9 @@
 
 <histogram name="Bluetooth.Web.GetCharacteristics.Characteristic"
     enum="GATTCharacteristicHash">
-  <owner>jyasskin@chromium.org</owner>
+  <owner>odejesush@chromium.org</owner>
   <owner>ortuno@chromium.org</owner>
-  <owner>scheib@chromium.org</owner>
+  <owner>reillyg@chromium.org</owner>
   <summary>
     Records the UUIDs used when getting characteristics. The recorded value is a
     31-bit hash of the UUID. Used to know what types of characteristics to
@@ -12379,9 +12380,9 @@
 
 <histogram name="Bluetooth.Web.GetCharacteristics.Outcome"
     enum="WebBluetoothGetCharacteristicOutcome">
-  <owner>jyasskin@chromium.org</owner>
+  <owner>odejesush@chromium.org</owner>
   <owner>ortuno@chromium.org</owner>
-  <owner>scheib@chromium.org</owner>
+  <owner>reillyg@chromium.org</owner>
   <summary>
     Records the outcome of a call to getCharacteristics(). Used to understand
     what errors developers are getting so we can target efforts toward the most
@@ -12391,9 +12392,9 @@
 
 <histogram name="Bluetooth.Web.GetDescriptor.Descriptor"
     enum="GATTDescriptorHash">
-  <owner>jyasskin@chromium.org</owner>
+  <owner>odejesush@chromium.org</owner>
   <owner>ortuno@chromium.org</owner>
-  <owner>scheib@chromium.org</owner>
+  <owner>reillyg@chromium.org</owner>
   <summary>
     Records the UUIDs used when getting a descriptor. The recorded value is a
     31-bit hash of the UUID. Used to know what types of descriptors to target
@@ -12403,9 +12404,9 @@
 
 <histogram name="Bluetooth.Web.GetDescriptor.Outcome"
     enum="WebBluetoothGetDescriptorOutcome">
-  <owner>jyasskin@chromium.org</owner>
+  <owner>odejesush@chromium.org</owner>
   <owner>ortuno@chromium.org</owner>
-  <owner>scheib@chromium.org</owner>
+  <owner>reillyg@chromium.org</owner>
   <summary>
     Records the outcome of a call to getDescriptor(). Used to understand what
     errors developers are getting so we can target efforts toward the most
@@ -12415,9 +12416,9 @@
 
 <histogram name="Bluetooth.Web.GetDescriptors.Descriptor"
     enum="GATTDescriptorHash">
-  <owner>jyasskin@chromium.org</owner>
+  <owner>odejesush@chromium.org</owner>
   <owner>ortuno@chromium.org</owner>
-  <owner>scheib@chromium.org</owner>
+  <owner>reillyg@chromium.org</owner>
   <summary>
     Records the UUIDs used when getting descriptors. The recorded value is a
     31-bit hash of the UUID. Used to know what types of descriptors to target
@@ -12427,9 +12428,9 @@
 
 <histogram name="Bluetooth.Web.GetDescriptors.Outcome"
     enum="WebBluetoothGetDescriptorOutcome">
-  <owner>jyasskin@chromium.org</owner>
+  <owner>odejesush@chromium.org</owner>
   <owner>ortuno@chromium.org</owner>
-  <owner>scheib@chromium.org</owner>
+  <owner>reillyg@chromium.org</owner>
   <summary>
     Records the outcome of a call to getDescriptors(). Used to understand what
     errors developers are getting so we can target efforts toward the most
@@ -12439,9 +12440,9 @@
 
 <histogram name="Bluetooth.Web.GetPrimaryService.Outcome"
     enum="WebBluetoothGetPrimaryServiceOutcome">
-  <owner>jyasskin@chromium.org</owner>
+  <owner>odejesush@chromium.org</owner>
   <owner>ortuno@chromium.org</owner>
-  <owner>scheib@chromium.org</owner>
+  <owner>reillyg@chromium.org</owner>
   <summary>
     Records the result of a GATTServer.getPrimaryService() call. Used to
     understand what errors developers are getting so we can target efforts
@@ -12451,9 +12452,9 @@
 
 <histogram name="Bluetooth.Web.GetPrimaryService.Services"
     enum="GATTServiceHash">
-  <owner>jyasskin@chromium.org</owner>
+  <owner>odejesush@chromium.org</owner>
   <owner>ortuno@chromium.org</owner>
-  <owner>scheib@chromium.org</owner>
+  <owner>reillyg@chromium.org</owner>
   <summary>
     Records what GATT Services are used when connected. The record value is a
     31-bit hash of the Service UUID. This will help us know if we should build
@@ -12463,9 +12464,9 @@
 
 <histogram name="Bluetooth.Web.GetPrimaryServices.Outcome"
     enum="WebBluetoothGetPrimaryServiceOutcome">
-  <owner>jyasskin@chromium.org</owner>
+  <owner>odejesush@chromium.org</owner>
   <owner>ortuno@chromium.org</owner>
-  <owner>scheib@chromium.org</owner>
+  <owner>reillyg@chromium.org</owner>
   <summary>
     Records the result of a GATTServer.getPrimaryServices() call. Used to
     understand what errors developers are getting so we can target efforts
@@ -12475,9 +12476,9 @@
 
 <histogram name="Bluetooth.Web.GetPrimaryServices.Services"
     enum="GATTServiceHash">
-  <owner>jyasskin@chromium.org</owner>
+  <owner>odejesush@chromium.org</owner>
   <owner>ortuno@chromium.org</owner>
-  <owner>scheib@chromium.org</owner>
+  <owner>reillyg@chromium.org</owner>
   <summary>
     Records what GATT Services are used when connected. The record value is a
     31-bit hash of the Service UUID. This will help us know if we should build
@@ -12486,9 +12487,9 @@
 </histogram>
 
 <histogram name="Bluetooth.Web.RequestDevice.Filters.Count" units="filters">
-  <owner>jyasskin@chromium.org</owner>
+  <owner>odejesush@chromium.org</owner>
   <owner>ortuno@chromium.org</owner>
-  <owner>scheib@chromium.org</owner>
+  <owner>reillyg@chromium.org</owner>
   <summary>
     Records how many filters are used when scanning. These results will help us
     better understand the uses of the API and make changes according to
@@ -12498,9 +12499,9 @@
 
 <histogram name="Bluetooth.Web.RequestDevice.Filters.Services"
     enum="GATTServiceHash">
-  <owner>jyasskin@chromium.org</owner>
+  <owner>odejesush@chromium.org</owner>
   <owner>ortuno@chromium.org</owner>
-  <owner>scheib@chromium.org</owner>
+  <owner>reillyg@chromium.org</owner>
   <summary>
     Records a 31-bit hash of the GATT Service UUIDs used when scanning. This
     will help us know if we should build an API for specific services rather
@@ -12509,9 +12510,9 @@
 </histogram>
 
 <histogram name="Bluetooth.Web.RequestDevice.FilterSize" units="services">
-  <owner>jyasskin@chromium.org</owner>
+  <owner>odejesush@chromium.org</owner>
   <owner>ortuno@chromium.org</owner>
-  <owner>scheib@chromium.org</owner>
+  <owner>reillyg@chromium.org</owner>
   <summary>
     Records how many services are used in a filter. These results will help us
     better understand the uses of the API and make changes according to
@@ -12522,9 +12523,9 @@
 <histogram
     name="Bluetooth.Web.RequestDevice.NumOfDevicesInChooserWhenNotAcceptingAllDevices"
     units="devices">
-  <owner>jyasskin@chromium.org</owner>
+  <owner>odejesush@chromium.org</owner>
   <owner>ortuno@chromium.org</owner>
-  <owner>scheib@chromium.org</owner>
+  <owner>reillyg@chromium.org</owner>
   <owner>juncai@chromium.org</owner>
   <summary>
     In the case of not accepting all devices, records the number of devices that
@@ -12534,9 +12535,9 @@
 
 <histogram name="Bluetooth.Web.RequestDevice.OptionalServices.Count"
     units="filters">
-  <owner>jyasskin@chromium.org</owner>
+  <owner>odejesush@chromium.org</owner>
   <owner>ortuno@chromium.org</owner>
-  <owner>scheib@chromium.org</owner>
+  <owner>reillyg@chromium.org</owner>
   <summary>
     Records how many optional services are used when scanning. These results
     will help us better understand the uses of the API and make changes
@@ -12546,9 +12547,9 @@
 
 <histogram name="Bluetooth.Web.RequestDevice.OptionalServices.Services"
     enum="GATTServiceHash">
-  <owner>jyasskin@chromium.org</owner>
+  <owner>odejesush@chromium.org</owner>
   <owner>ortuno@chromium.org</owner>
-  <owner>scheib@chromium.org</owner>
+  <owner>reillyg@chromium.org</owner>
   <summary>
     Records what optional services are used. The recorded value is a 31-bit hash
     of the Service UUID. These results will help us better understand the uses
@@ -12558,9 +12559,9 @@
 
 <histogram name="Bluetooth.Web.RequestDevice.Options.AcceptAllDevices"
     enum="Boolean">
-  <owner>jyasskin@chromium.org</owner>
+  <owner>odejesush@chromium.org</owner>
   <owner>ortuno@chromium.org</owner>
-  <owner>scheib@chromium.org</owner>
+  <owner>reillyg@chromium.org</owner>
   <summary>
     Records the value of 'acceptAllDevices' in RequestDeviceOptions. These
     results will help us better understand the uses of the API and make changes
@@ -12570,9 +12571,9 @@
 
 <histogram name="Bluetooth.Web.RequestDevice.Outcome"
     enum="WebBluetoothRequestDeviceOutcome">
-  <owner>jyasskin@chromium.org</owner>
+  <owner>odejesush@chromium.org</owner>
   <owner>ortuno@chromium.org</owner>
-  <owner>scheib@chromium.org</owner>
+  <owner>reillyg@chromium.org</owner>
   <summary>
     Records the result of a navigator.bluetooth.requestDevice() call. Used to
     understand what errors developers are getting so we can target efforts
@@ -12581,9 +12582,9 @@
 </histogram>
 
 <histogram name="Bluetooth.Web.RequestDevice.RSSISignalStrength" units="dBm">
-  <owner>jyasskin@chromium.org</owner>
+  <owner>odejesush@chromium.org</owner>
   <owner>ortuno@chromium.org</owner>
-  <owner>scheib@chromium.org</owner>
+  <owner>reillyg@chromium.org</owner>
   <owner>juncai@chromium.org</owner>
   <summary>
     Raw RSSI values provided to chooser, before processing them for display in
@@ -12593,9 +12594,9 @@
 
 <histogram name="Bluetooth.Web.RequestDevice.RSSISignalStrengthLevel"
     enum="WebBluetoothRSSISignalStrengthLevel">
-  <owner>jyasskin@chromium.org</owner>
+  <owner>odejesush@chromium.org</owner>
   <owner>ortuno@chromium.org</owner>
-  <owner>scheib@chromium.org</owner>
+  <owner>reillyg@chromium.org</owner>
   <owner>juncai@chromium.org</owner>
   <summary>
     Displayed RSSI levels, after processing and as displayed to users in the Web
@@ -12604,9 +12605,9 @@
 </histogram>
 
 <histogram name="Bluetooth.Web.RequestDevice.ScanningDuration" units="ms">
-  <owner>jyasskin@chromium.org</owner>
+  <owner>odejesush@chromium.org</owner>
   <owner>ortuno@chromium.org</owner>
-  <owner>scheib@chromium.org</owner>
+  <owner>reillyg@chromium.org</owner>
   <owner>juncai@chromium.org</owner>
   <summary>
     Records the duration scanning for devices is run, terminated by events such
@@ -12617,9 +12618,9 @@
 
 <histogram name="Bluetooth.Web.RequestDevice.UnionOfServices.Count"
     units="services">
-  <owner>jyasskin@chromium.org</owner>
+  <owner>odejesush@chromium.org</owner>
   <owner>ortuno@chromium.org</owner>
-  <owner>scheib@chromium.org</owner>
+  <owner>reillyg@chromium.org</owner>
   <summary>
     Records how many services are used when scanning. This results will help us
     better understand the uses of the API and make changes according to
@@ -12629,9 +12630,9 @@
 
 <histogram name="Bluetooth.Web.RequestDevice.UnionOfServices.Services"
     enum="GATTServiceHash">
-  <owner>jyasskin@chromium.org</owner>
+  <owner>odejesush@chromium.org</owner>
   <owner>ortuno@chromium.org</owner>
-  <owner>scheib@chromium.org</owner>
+  <owner>reillyg@chromium.org</owner>
   <summary>
     Records what services are used from either required or optional sets. The
     recorded value is a 31-bit hash of the Service UUID. These results will help
diff --git a/ui/accessibility/ax_tree_fuzzer.cc b/ui/accessibility/ax_tree_fuzzer.cc
index f2ad7271..fed5e6c 100644
--- a/ui/accessibility/ax_tree_fuzzer.cc
+++ b/ui/accessibility/ax_tree_fuzzer.cc
@@ -8,7 +8,7 @@
 class EmptyAXTreeObserver : public ui::AXTreeObserver {
  public:
   EmptyAXTreeObserver() {}
-  ~EmptyAXTreeObserver() override{};
+  ~EmptyAXTreeObserver() override {}
 };
 
 // Entry point for LibFuzzer.
diff --git a/ui/accessibility/tree_generator.cc b/ui/accessibility/tree_generator.cc
index faebbfb..6946077 100644
--- a/ui/accessibility/tree_generator.cc
+++ b/ui/accessibility/tree_generator.cc
@@ -104,6 +104,6 @@
 
   // Unserialize the tree update into the destination tree.
   CHECK(out_tree->Unserialize(update)) << out_tree->error();
-};
+}
 
 }  // namespace ui
diff --git a/ui/base/ime/input_method_auralinux_unittest.cc b/ui/base/ime/input_method_auralinux_unittest.cc
index cc67ef7..589c998 100644
--- a/ui/base/ime/input_method_auralinux_unittest.cc
+++ b/ui/base/ime/input_method_auralinux_unittest.cc
@@ -136,7 +136,7 @@
     re << "selectionrangeend:" << selection_range.end();
     TestResult::GetInstance()->RecordAction(base::ASCIIToUTF16(rs.str()));
     TestResult::GetInstance()->RecordAction(base::ASCIIToUTF16(re.str()));
-  };
+  }
 
  private:
   LinuxInputMethodContextDelegate* delegate_;
@@ -152,14 +152,14 @@
 class LinuxInputMethodContextFactoryForTesting
     : public LinuxInputMethodContextFactory {
  public:
-  LinuxInputMethodContextFactoryForTesting(){};
+  LinuxInputMethodContextFactoryForTesting() {}
 
   std::unique_ptr<LinuxInputMethodContext> CreateInputMethodContext(
       LinuxInputMethodContextDelegate* delegate,
       bool is_simple) const override {
     return std::unique_ptr<ui::LinuxInputMethodContext>(
         new LinuxInputMethodContextForTesting(delegate));
-  };
+  }
 
  private:
   DISALLOW_COPY_AND_ASSIGN(LinuxInputMethodContextFactoryForTesting);
@@ -199,7 +199,7 @@
 class TextInputClientForTesting : public DummyTextInputClient {
  public:
   explicit TextInputClientForTesting(TextInputType text_input_type)
-      : DummyTextInputClient(text_input_type){};
+      : DummyTextInputClient(text_input_type) {}
 
   base::string16 composition_text;
   gfx::Range text_range;
diff --git a/ui/base/ime/input_method_base.h b/ui/base/ime/input_method_base.h
index afd0342..10a89ff 100644
--- a/ui/base/ime/input_method_base.h
+++ b/ui/base/ime/input_method_base.h
@@ -120,8 +120,8 @@
   // Gets the bounds of the composition text or cursor in |client|.
   std::vector<gfx::Rect> GetCompositionBounds(const TextInputClient* client);
 
-  bool sending_key_event() const { return sending_key_event_; };
-  internal::InputMethodDelegate* delegate() const { return delegate_; };
+  bool sending_key_event() const { return sending_key_event_; }
+  internal::InputMethodDelegate* delegate() const { return delegate_; }
 
   static IMEEngineHandlerInterface* GetEngine();
 
diff --git a/ui/base/ime/mock_ime_input_context_handler.h b/ui/base/ime/mock_ime_input_context_handler.h
index e1bcb1f6..986efff 100644
--- a/ui/base/ime/mock_ime_input_context_handler.h
+++ b/ui/base/ime/mock_ime_input_context_handler.h
@@ -51,7 +51,7 @@
     return delete_surrounding_text_call_count_;
   }
 
-  const std::string& last_commit_text() const { return last_commit_text_; };
+  const std::string& last_commit_text() const { return last_commit_text_; }
 
   const UpdateCompositionTextArg& last_update_composition_arg() const {
     return last_update_composition_arg_;
diff --git a/ui/compositor/compositor.cc b/ui/compositor/compositor.cc
index ad98381..311c26b 100644
--- a/ui/compositor/compositor.cc
+++ b/ui/compositor/compositor.cc
@@ -582,6 +582,16 @@
   return animation_observer_list_.HasObserver(observer);
 }
 
+void Compositor::DidUpdateLayers() {
+  // Dump property trees and layers if run with:
+  //   --vmodule=*ui/compositor*=3
+  VLOG(3) << "After updating layers:\n"
+          << "property trees:\n"
+          << host_->property_trees()->ToString() << "\n"
+          << "cc::Layers:\n"
+          << host_->LayersAsString();
+}
+
 void Compositor::BeginMainFrame(const viz::BeginFrameArgs& args) {
   DCHECK(!IsLocked());
   for (auto& observer : animation_observer_list_)
diff --git a/ui/compositor/compositor.h b/ui/compositor/compositor.h
index 0f389cee..29784c6 100644
--- a/ui/compositor/compositor.h
+++ b/ui/compositor/compositor.h
@@ -381,6 +381,7 @@
   // LayerTreeHostClient implementation.
   void WillBeginMainFrame() override {}
   void DidBeginMainFrame() override {}
+  void DidUpdateLayers() override;
   void BeginMainFrame(const viz::BeginFrameArgs& args) override;
   void BeginMainFrameNotExpectedSoon() override;
   void BeginMainFrameNotExpectedUntil(base::TimeTicks time) override;
diff --git a/ui/events/scoped_target_handler.cc b/ui/events/scoped_target_handler.cc
index 08608b4..f9cacaa 100644
--- a/ui/events/scoped_target_handler.cc
+++ b/ui/events/scoped_target_handler.cc
@@ -38,6 +38,11 @@
     }
     destroyed_flag_ = old_destroyed_flag;
   }
+
+  // This check is needed due to nested event loops when starting DragDrop.
+  if (event->stopped_propagation())
+    return;
+
   new_handler_->OnEvent(event);
 }
 
diff --git a/ui/events/scoped_target_handler.h b/ui/events/scoped_target_handler.h
index 98d8574..babc68c8 100644
--- a/ui/events/scoped_target_handler.h
+++ b/ui/events/scoped_target_handler.h
@@ -16,7 +16,8 @@
 // An EventHandler that replaces an EventTarget's target handler with itself to
 // pass events first to the original handler and second to an additional new
 // EventHandler. The new handler gets called after the original handler even
-// if it calls SetHandled() or StopPropagation() on the event.
+// if it calls SetHandled() on the event but not if StopPropagation() is called
+// on the event.
 class EVENTS_EXPORT ScopedTargetHandler : public EventHandler {
  public:
   ScopedTargetHandler(EventTarget* target, EventHandler* new_handler);
diff --git a/ui/events/scoped_target_handler_unittest.cc b/ui/events/scoped_target_handler_unittest.cc
index 9eae471..477c5af 100644
--- a/ui/events/scoped_target_handler_unittest.cc
+++ b/ui/events/scoped_target_handler_unittest.cc
@@ -136,41 +136,74 @@
   DISALLOW_COPY_AND_ASSIGN(EventCountingEventHandler);
 };
 
+// An EventCountingEventHandler that will also mark the event to stop further
+// propataion.
+class EventStopPropagationHandler : public EventCountingEventHandler {
+ public:
+  EventStopPropagationHandler(EventTarget* target, int* count)
+      : EventCountingEventHandler(target, count) {}
+  ~EventStopPropagationHandler() override {}
+
+ protected:
+  void OnEvent(Event* event) override {
+    EventCountingEventHandler::OnEvent(event);
+    event->StopPropagation();
+  }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(EventStopPropagationHandler);
+};
+
 }  // namespace
 
 // Tests that a ScopedTargetHandler invokes both the target and a delegate.
 TEST(ScopedTargetHandlerTest, HandlerInvoked) {
   int count = 0;
-  TestEventTarget* target = new TestEventTarget;
+  std::unique_ptr<TestEventTarget> target = std::make_unique<TestEventTarget>();
   std::unique_ptr<NestedEventHandler> target_handler(
-      new NestedEventHandler(target, 1));
+      new NestedEventHandler(target.get(), 1));
   std::unique_ptr<EventCountingEventHandler> delegate(
-      new EventCountingEventHandler(target, &count));
+      new EventCountingEventHandler(target.get(), &count));
   target->SetHandler(std::move(target_handler), std::move(delegate));
   MouseEvent event(ET_MOUSE_PRESSED, gfx::Point(), gfx::Point(),
                    EventTimeForNow(), EF_LEFT_MOUSE_BUTTON,
                    EF_LEFT_MOUSE_BUTTON);
   target->DispatchEvent(&event);
   EXPECT_EQ(1, count);
-  delete target;
+}
+
+// Tests that a ScopedTargetHandler invokes both the target and a delegate but
+// does not further propagate the event after a handler stops event propagation.
+TEST(ScopedTargetHandlerTest, HandlerInvokedOnceThenEventStopsPropagating) {
+  int count = 0;
+  std::unique_ptr<TestEventTarget> target = std::make_unique<TestEventTarget>();
+  std::unique_ptr<NestedEventHandler> target_handler(
+      new NestedEventHandler(target.get(), 3));
+  std::unique_ptr<EventStopPropagationHandler> delegate(
+      new EventStopPropagationHandler(target.get(), &count));
+  target->SetHandler(std::move(target_handler), std::move(delegate));
+  MouseEvent event(ET_MOUSE_PRESSED, gfx::Point(), gfx::Point(),
+                   EventTimeForNow(), EF_LEFT_MOUSE_BUTTON,
+                   EF_LEFT_MOUSE_BUTTON);
+  target->DispatchEvent(&event);
+  EXPECT_EQ(1, count);
 }
 
 // Tests that a ScopedTargetHandler invokes both the target and a delegate when
 // an Event is dispatched recursively such as with synthetic events.
 TEST(ScopedTargetHandlerTest, HandlerInvokedNested) {
   int count = 0;
-  TestEventTarget* target = new TestEventTarget;
+  std::unique_ptr<TestEventTarget> target = std::make_unique<TestEventTarget>();
   std::unique_ptr<NestedEventHandler> target_handler(
-      new NestedEventHandler(target, 2));
+      new NestedEventHandler(target.get(), 2));
   std::unique_ptr<EventCountingEventHandler> delegate(
-      new EventCountingEventHandler(target, &count));
+      new EventCountingEventHandler(target.get(), &count));
   target->SetHandler(std::move(target_handler), std::move(delegate));
   MouseEvent event(ET_MOUSE_PRESSED, gfx::Point(), gfx::Point(),
                    EventTimeForNow(), EF_LEFT_MOUSE_BUTTON,
                    EF_LEFT_MOUSE_BUTTON);
   target->DispatchEvent(&event);
   EXPECT_EQ(2, count);
-  delete target;
 }
 
 // Tests that a it is safe to delete a ScopedTargetHandler while handling an
diff --git a/ui/file_manager/file_manager/background/js/volume_manager_impl.js b/ui/file_manager/file_manager/background/js/volume_manager_impl.js
index de5b199..98356115 100644
--- a/ui/file_manager/file_manager/background/js/volume_manager_impl.js
+++ b/ui/file_manager/file_manager/background/js/volume_manager_impl.js
@@ -272,6 +272,10 @@
 
 /** @override */
 VolumeManagerImpl.prototype.getVolumeInfo = function(entry) {
+  if (!entry) {
+    console.error('Invalid entry passed to getVolumeInfo: ' + entry);
+    return null;
+  }
   for (let i = 0; i < this.volumeInfoList.length; i++) {
     const volumeInfo = this.volumeInfoList.item(i);
     if (volumeInfo.fileSystem &&
@@ -303,6 +307,10 @@
 
 /** @override */
 VolumeManagerImpl.prototype.getLocationInfo = function(entry) {
+  if (!entry) {
+    console.error('Invalid entry passed to getLocationInfo: ' + entry);
+    return null;
+  }
   var volumeInfo = this.getVolumeInfo(entry);
 
   if (util.isFakeEntry(entry)) {
diff --git a/ui/file_manager/file_manager/foreground/js/file_list_model_unittest.js b/ui/file_manager/file_manager/foreground/js/file_list_model_unittest.js
index 11bc54bb..1e0743fe 100644
--- a/ui/file_manager/file_manager/foreground/js/file_list_model_unittest.js
+++ b/ui/file_manager/file_manager/foreground/js/file_list_model_unittest.js
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-var TEST_METADATA = {
+const TEST_METADATA = {
   'a.txt': {
     contentMimeType: 'text/plain',
     size: 1023,
@@ -33,7 +33,7 @@
 }
 
 function makeSimpleFileListModel(names) {
-  var fileListModel = new FileListModel(new TestMetadataModel({}));
+  var fileListModel = new FileListModel(createFakeMetadataModel({}));
   for (var i = 0; i < names.length; i++) {
     fileListModel.push({name: names[i], isDirectory: false});
   }
@@ -41,36 +41,31 @@
 }
 
 /**
- * MetadataModel for this test.
- * It is supposed to provide metadata from TEST_METADATA to work with the
- * FileListModel.
- *
- * @constructor
- * @extends {MetadataModel}
- * @param {Object} testdata
+ * Returns a fake MetadataModel, used to provide metadata from the given |data|
+ * object (usually TEST_METADATA) to the FileListModel.
+ * @param {!Object} data
+ * @return {!MetadataModel}
  */
-function TestMetadataModel(testdata) {
-  this.testdata_ = testdata;
+function createFakeMetadataModel(data) {
+  return /** @type {!MetadataModel} */ ({
+    getCache: (entries, names) => {
+      let result = [];
+      for (let i = 0; i < entries.length; i++) {
+        let metadata = {};
+        if (!entries[i].isDirectory && data[entries[i].name]) {
+          for (let j = 0; j < names.length; j++) {
+            metadata[names[j]] = data[entries[i].name][names[j]];
+          }
+        }
+        result.push(metadata);
+      }
+      return result;
+    },
+  });
 }
 
-TestMetadataModel.prototype = {
-  getCache : function(entries, names) {
-    var result = [];
-    for (var i = 0; i < entries.length; i++) {
-      var metadata = {};
-      if (!entries[i].isDirectory && this.testdata_[entries[i].name]) {
-        for (var j = 0; j < names.length; j++) {
-          metadata[names[j]] = this.testdata_[entries[i].name][names[j]];
-        }
-      }
-      result.push(metadata);
-    }
-    return result;
-  },
-};
-
 function testIsImageDominant() {
-  var fileListModel = new FileListModel(new TestMetadataModel(TEST_METADATA));
+  var fileListModel = new FileListModel(createFakeMetadataModel(TEST_METADATA));
 
   assertEquals(fileListModel.isImageDominant(), false);
 
@@ -97,7 +92,7 @@
 }
 
 function testSortWithFolders() {
-  var fileListModel = new FileListModel(new TestMetadataModel(TEST_METADATA));
+  var fileListModel = new FileListModel(createFakeMetadataModel(TEST_METADATA));
   fileListModel.push({ name: 'dirA', isDirectory: true });
   fileListModel.push({ name: 'dirB', isDirectory: true });
   fileListModel.push({ name: 'a.txt', isDirectory: false });
diff --git a/ui/file_manager/file_manager/foreground/js/mock_directory_model.js b/ui/file_manager/file_manager/foreground/js/mock_directory_model.js
index e14efa74..6c6145a 100644
--- a/ui/file_manager/file_manager/foreground/js/mock_directory_model.js
+++ b/ui/file_manager/file_manager/foreground/js/mock_directory_model.js
@@ -3,87 +3,59 @@
 // found in the LICENSE file.
 
 /**
- * Mock class for DirectoryModel.
- * @constructor
- * @extends {DirectoryModel}
+ * @returns {!FileFilter} fake for unittests.
  */
-function MockDirectoryModel() {
+function createFakeFileFilter() {
   /**
-   * @private {!MockFileFilter}
+   * FileFilter fake.
    */
-  this.fileFilter_ = new MockFileFilter();
+  class FakeFileFilter extends cr.EventTarget {
+    /**
+     * @param {Entry} entry File entry.
+     * @return {boolean} True if the file should be shown.
+     */
+    filter(entry) {
+      return true;
+    }
+  }
 
-  /**
-   * @private {MockDirectoryEntry}
-   */
-  this.currentEntry_ = null;
-
-  /** @private {FilesAppDirEntry} */
-  this.myFiles_ = null;
+  const filter = /** @type {!Object} */ (new FakeFileFilter());
+  return /** @type {!FileFilter} */ (filter);
 }
 
 /**
- * MockDirectoryModel inherits cr.EventTarget.
+ * @returns {!DirectoryModel} fake for unittests.
  */
-MockDirectoryModel.prototype = {__proto__: cr.EventTarget.prototype};
+function createFakeDirectoryModel() {
+  /**
+   * DirectoryModel fake.
+   */
+  class FakeDirectoryModel extends cr.EventTarget {
+    constructor() {
+      super();
 
-/**
- * Returns a file filter.
- * @return {FileFilter} A file filter.
- */
-MockDirectoryModel.prototype.getFileFilter = function() {
-  return this.fileFilter_;
-};
+      /** @private {!FileFilter} */
+      this.fileFilter_ = createFakeFileFilter();
 
-/**
- * @return {MockDirectoryEntry}
- */
-MockDirectoryModel.prototype.getCurrentDirEntry = function() {
-  return this.currentEntry_;
-};
+      /** @private {FilesAppDirEntry} */
+      this.myFiles_ = null;
+    }
 
-/**
- * @param {MockDirectoryEntry} entry
- * @return {Promise}
- */
-MockDirectoryModel.prototype.navigateToMockEntry = function(entry) {
-  return new Promise(function(resolve, reject) {
-    var event = new Event('directory-changed');
-    event.previousDirEntry = this.currentEntry_;
-    event.newDirEntry = entry;
-    event.volumeChanged =
-        this.currentEntry_ && util.isSameEntry(this.currentEntry_, entry);
-    this.currentEntry_ = entry;
-    this.dispatchEvent(event);
-    resolve();
-  }.bind(this));
-};
+    /**
+     * @param {FilesAppDirEntry} myFilesEntry
+     */
+    setMyFiles(myFilesEntry) {
+      this.myFiles_ = myFilesEntry;
+    }
 
-/**
- * @param {FilesAppDirEntry} myFilesEntry
- * @override
- */
-MockDirectoryModel.prototype.setMyFiles = function(myFilesEntry) {
-  this.myFiles_ = myFilesEntry;
-};
+    /**
+     * @return {!FileFilter} file filter.
+     */
+    getFileFilter() {
+      return this.fileFilter_;
+    }
+  }
 
-/**
- * Mock class for FileFilter.
- * @constructor
- * @extends {FileFilter}
- */
-function MockFileFilter() {}
-
-/**
- * MockFileFilter extends cr.EventTarget.
- */
-MockFileFilter.prototype = {__proto__: cr.EventTarget.prototype};
-
-/**
- * Current implementation always returns true.
- * @param {Entry} entry File entry.
- * @return {boolean} True if the file should be shown, false otherwise.
- */
-MockFileFilter.prototype.filter = function(entry) {
-  return true;
-};
+  const model = /** @type {!Object} */ (new FakeDirectoryModel());
+  return /** @type {!DirectoryModel} */ (model);
+}
diff --git a/ui/file_manager/file_manager/foreground/js/navigation_list_model_unittest.js b/ui/file_manager/file_manager/foreground/js/navigation_list_model_unittest.js
index a75581c5..49457a57 100644
--- a/ui/file_manager/file_manager/foreground/js/navigation_list_model_unittest.js
+++ b/ui/file_manager/file_manager/foreground/js/navigation_list_model_unittest.js
@@ -12,6 +12,12 @@
     /** @type {!FilesAppEntry} */ ({toURL: () => 'fake-entry://recent'});
 
 /**
+ * Directory model.
+ * @type {!DirectoryModel}
+ */
+var directoryModel;
+
+/**
  * Drive file system.
  * @type {!MockFileSystem}
  */
@@ -46,7 +52,8 @@
     return Promise.resolve(this.fileSystem_.root);
   };
 
-  // Create mock file systems.
+  // Create mock components.
+  directoryModel = createFakeDirectoryModel();
   drive = new MockFileSystem('drive');
   hoge = new MockFileSystem('removable:hoge');
 }
@@ -68,7 +75,7 @@
           'linux-files-label', VolumeManagerCommon.RootType.CROSTINI));
 
   var model = new NavigationListModel(
-      volumeManager, shortcutListModel, recentItem, new MockDirectoryModel());
+      volumeManager, shortcutListModel, recentItem, directoryModel);
   model.linuxFilesItem = crostiniFakeItem;
 
   assertEquals(4, model.length);
@@ -102,7 +109,7 @@
   var recentItem = null;
 
   var model = new NavigationListModel(
-      volumeManager, shortcutListModel, recentItem, new MockDirectoryModel());
+      volumeManager, shortcutListModel, recentItem, directoryModel);
 
   assertEquals(3, model.length);
   assertEquals(
@@ -125,7 +132,7 @@
   var recentItem = null;
 
   var model = new NavigationListModel(
-      volumeManager, shortcutListModel, recentItem, new MockDirectoryModel());
+      volumeManager, shortcutListModel, recentItem, directoryModel);
 
   assertEquals(3, model.length);
 
@@ -187,7 +194,7 @@
   var recentItem = null;
 
   var model = new NavigationListModel(
-      volumeManager, shortcutListModel, recentItem, new MockDirectoryModel());
+      volumeManager, shortcutListModel, recentItem, directoryModel);
 
   assertEquals(3, model.length);
 
@@ -325,7 +332,7 @@
 
   // Constructor already calls orderAndNestItems_.
   const model = new NavigationListModel(
-      volumeManager, shortcutListModel, recentItem, new MockDirectoryModel());
+      volumeManager, shortcutListModel, recentItem, directoryModel);
 
   // Check items order and that MTP/Archive/Removable respect the original
   // order.
@@ -437,7 +444,7 @@
 
   // Constructor already calls orderAndNestItems_.
   const model = new NavigationListModel(
-      volumeManager, shortcutListModel, recentItem, new MockDirectoryModel());
+      volumeManager, shortcutListModel, recentItem, directoryModel);
   model.linuxFilesItem = crostiniFakeItem;
 
   assertEquals(2, model.length);
diff --git a/ui/file_manager/file_manager/foreground/js/ui/directory_tree_unittest.js b/ui/file_manager/file_manager/foreground/js/ui/directory_tree_unittest.js
index 9910bd1..f8bd92c 100644
--- a/ui/file_manager/file_manager/foreground/js/ui/directory_tree_unittest.js
+++ b/ui/file_manager/file_manager/foreground/js/ui/directory_tree_unittest.js
@@ -59,7 +59,7 @@
 
   // Setup mock components.
   volumeManager = new MockVolumeManager();
-  directoryModel = new MockDirectoryModel();
+  directoryModel = createFakeDirectoryModel();
   metadataModel = /** @type {!MetadataModel} */ ({});
   fileOperationManager = /** @type {!FileOperationManager} */ ({
     addEventListener: (name, callback) => {},
@@ -443,9 +443,9 @@
  */
 function testUpdateSubElementsFromListSections() {
   const recentItem = null;
+  const shortcutListModel = new MockFolderShortcutDataModel([]);
   const treeModel = new NavigationListModel(
-      volumeManager, new MockFolderShortcutDataModel([]), recentItem,
-      new MockDirectoryModel());
+      volumeManager, shortcutListModel, recentItem, directoryModel);
   const myFilesItem = treeModel.item(0);
   const driveItem = treeModel.item(1);
 
diff --git a/ui/file_manager/integration_tests/file_manager/quick_view.js b/ui/file_manager/integration_tests/file_manager/quick_view.js
index c2996a8..e7c503cd 100644
--- a/ui/file_manager/integration_tests/file_manager/quick_view.js
+++ b/ui/file_manager/integration_tests/file_manager/quick_view.js
@@ -155,36 +155,6 @@
 };
 
 /**
- * Tests opening Quick View on a removable partition.
- */
-testcase.openQuickViewRemovablePartitions = async function() {
-  const PARTITION_ONE_QUERY = '#directory-tree [volume-type-icon="removable"]';
-
-  // Open Files app on Downloads containing ENTRIES.photos.
-  const appId =
-      await setupAndWaitUntilReady(RootPath.DOWNLOADS, [ENTRIES.photos], []);
-
-  // Mount USB volume.
-  await sendTestMessage({name: 'mountFakePartitions'});
-
-  // Wait for removable partition-1 to appear in the directory tree.
-  const partition = await remoteCall.waitForElement(appId, PARTITION_ONE_QUERY);
-
-  // Click to open the partition-1.
-  chrome.test.assertTrue(
-      !!await remoteCall.callRemoteTestUtil(
-          'fakeMouseClick', appId, [PARTITION_ONE_QUERY]),
-      'fakeMouseClick failed');
-
-  // Check: the 'hello.txt' file should appear in the file list.
-  const files = [ENTRIES.hello.getExpectedRow()];
-  await remoteCall.waitForFiles(appId, files, {ignoreLastModifiedTime: true});
-
-  // Open the file in Quick View.
-  await openQuickView(appId, ENTRIES.hello.nameText);
-};
-
-/**
  * Tests opening Quick View on an MTP file.
  */
 testcase.openQuickViewMtp = async function() {
diff --git a/ui/gl/gl_visual_picker_glx.h b/ui/gl/gl_visual_picker_glx.h
index 6ee25f6..ad6a1bf 100644
--- a/ui/gl/gl_visual_picker_glx.h
+++ b/ui/gl/gl_visual_picker_glx.h
@@ -30,9 +30,9 @@
 
   ~GLVisualPickerGLX();
 
-  const XVisualInfo& system_visual() { return system_visual_; };
+  const XVisualInfo& system_visual() { return system_visual_; }
 
-  const XVisualInfo& rgba_visual() { return rgba_visual_; };
+  const XVisualInfo& rgba_visual() { return rgba_visual_; }
 
  private:
   friend struct base::DefaultSingletonTraits<GLVisualPickerGLX>;
diff --git a/ui/gl/init/create_gr_gl_interface.cc b/ui/gl/init/create_gr_gl_interface.cc
index 4c644232..7d3c3eb 100644
--- a/ui/gl/init/create_gr_gl_interface.cc
+++ b/ui/gl/init/create_gr_gl_interface.cc
@@ -38,7 +38,7 @@
     ScopedProgressReporter scoped_reporter(progress_reporter);
     return func(args...);
   };
-};
+}
 
 const GLubyte* GetStringHook(const char* version_string, GLenum name) {
   switch (name) {
diff --git a/ui/ozone/common/linux/gbm_wrapper.cc b/ui/ozone/common/linux/gbm_wrapper.cc
index b5d8d40..72a7f16 100644
--- a/ui/ozone/common/linux/gbm_wrapper.cc
+++ b/ui/ozone/common/linux/gbm_wrapper.cc
@@ -15,14 +15,6 @@
 
 namespace gbm_wrapper {
 
-namespace {
-
-// Temporary defines while we migrate to GBM_BO_IMPORT_FD_MODIFIER.
-#define GBM_BO_IMPORT_FD_PLANAR_5504 0x5504
-#define GBM_BO_IMPORT_FD_PLANAR_5505 0x5505
-
-}  // namespace
-
 class Buffer final : public ui::GbmBuffer {
  public:
   Buffer(struct gbm_bo* bo,
@@ -240,17 +232,10 @@
 
     // The fd passed to gbm_bo_import is not ref-counted and need to be
     // kept open for the lifetime of the buffer.
-    //
-    // See the comment regarding the GBM_BO_IMPORT_FD_PLANAR_550X above.
-    bo = gbm_bo_import(device_, GBM_BO_IMPORT_FD_PLANAR_5505, &fd_data,
-                       gbm_flags);
+    bo = gbm_bo_import(device_, GBM_BO_IMPORT_FD_PLANAR, &fd_data, gbm_flags);
     if (!bo) {
-      bo = gbm_bo_import(device_, GBM_BO_IMPORT_FD_PLANAR_5504, &fd_data,
-                         gbm_flags);
-      if (!bo) {
-        LOG(ERROR) << "nullptr returned from gbm_bo_import";
-        return nullptr;
-      }
+      LOG(ERROR) << "nullptr returned from gbm_bo_import";
+      return nullptr;
     }
 
     return std::make_unique<Buffer>(bo, format, gbm_flags, planes[0].modifier,
diff --git a/ui/ozone/platform/wayland/gpu/drm_render_node_path_finder.cc b/ui/ozone/platform/wayland/gpu/drm_render_node_path_finder.cc
index c3367aee..c89309b 100644
--- a/ui/ozone/platform/wayland/gpu/drm_render_node_path_finder.cc
+++ b/ui/ozone/platform/wayland/gpu/drm_render_node_path_finder.cc
@@ -23,14 +23,13 @@
 
 }  // namespace
 
-DrmRenderNodePathFinder::DrmRenderNodePathFinder() = default;
+DrmRenderNodePathFinder::DrmRenderNodePathFinder() {
+  FindDrmRenderNodePath();
+}
 
 DrmRenderNodePathFinder::~DrmRenderNodePathFinder() = default;
 
-base::FilePath DrmRenderNodePathFinder::GetDrmRenderNodePath() {
-  if (drm_render_node_path_.empty())
-    FindDrmRenderNodePath();
-
+base::FilePath DrmRenderNodePathFinder::GetDrmRenderNodePath() const {
   return drm_render_node_path_;
 }
 
diff --git a/ui/ozone/platform/wayland/gpu/drm_render_node_path_finder.h b/ui/ozone/platform/wayland/gpu/drm_render_node_path_finder.h
index a6408e7b..0ea3be6 100644
--- a/ui/ozone/platform/wayland/gpu/drm_render_node_path_finder.h
+++ b/ui/ozone/platform/wayland/gpu/drm_render_node_path_finder.h
@@ -13,12 +13,12 @@
 // A helper class that finds a DRM render node device and returns a path to it.
 class DrmRenderNodePathFinder {
  public:
+  // Triggers FindDrmRenderNodePath.
   DrmRenderNodePathFinder();
   ~DrmRenderNodePathFinder();
 
-  // Returns a path to a drm render node device. If it hasn't been found yet,
-  // triggers FindDrmRenderNodePath and returns the path.
-  base::FilePath GetDrmRenderNodePath();
+  // Returns a path to a drm render node device.
+  base::FilePath GetDrmRenderNodePath() const;
 
  private:
   void FindDrmRenderNodePath();
diff --git a/ui/ozone/platform/wayland/gpu/gbm_pixmap_wayland.cc b/ui/ozone/platform/wayland/gpu/gbm_pixmap_wayland.cc
index 5d153f9..5d46385 100644
--- a/ui/ozone/platform/wayland/gpu/gbm_pixmap_wayland.cc
+++ b/ui/ozone/platform/wayland/gpu/gbm_pixmap_wayland.cc
@@ -31,7 +31,8 @@
     : surface_manager_(surface_manager), connection_(connection) {}
 
 GbmPixmapWayland::~GbmPixmapWayland() {
-  connection_->DestroyZwpLinuxDmabuf(GetUniqueId());
+  if (gbm_bo_)
+    connection_->DestroyZwpLinuxDmabuf(GetUniqueId());
 }
 
 bool GbmPixmapWayland::InitializeBuffer(gfx::Size size,
@@ -39,6 +40,10 @@
                                         gfx::BufferUsage usage) {
   TRACE_EVENT1("wayland", "GbmPixmapWayland::InitializeBuffer", "size",
                size.ToString());
+
+  if (!connection_->gbm_device())
+    return false;
+
   uint32_t flags = 0;
   switch (usage) {
     case gfx::BufferUsage::GPU_READ:
diff --git a/ui/ozone/platform/wayland/gpu/wayland_connection_proxy.cc b/ui/ozone/platform/wayland/gpu/wayland_connection_proxy.cc
index 366bbf0..9126a67 100644
--- a/ui/ozone/platform/wayland/gpu/wayland_connection_proxy.cc
+++ b/ui/ozone/platform/wayland/gpu/wayland_connection_proxy.cc
@@ -14,8 +14,7 @@
 
 WaylandConnectionProxy::WaylandConnectionProxy(WaylandConnection* connection)
     : connection_(connection),
-      gpu_thread_runner_(connection_ ? nullptr
-                                     : base::ThreadTaskRunnerHandle::Get()) {}
+      gpu_thread_runner_(base::ThreadTaskRunnerHandle::Get()) {}
 
 WaylandConnectionProxy::~WaylandConnectionProxy() = default;
 
@@ -125,12 +124,10 @@
     return reinterpret_cast<intptr_t>(connection_->display());
 
 #if defined(WAYLAND_GBM)
-  // It must not be a single process mode. Thus, shared dmabuf approach is used,
-  // which requires |gbm_device_|.
-  DCHECK(gbm_device_);
   return EGL_DEFAULT_DISPLAY;
-#endif
+#else
   return 0;
+#endif
 }
 
 void WaylandConnectionProxy::AddBindingWaylandConnectionClient(
diff --git a/ui/ozone/platform/wayland/ozone_platform_wayland.cc b/ui/ozone/platform/wayland/ozone_platform_wayland.cc
index 904f32ff..fd592ba 100644
--- a/ui/ozone/platform/wayland/ozone_platform_wayland.cc
+++ b/ui/ozone/platform/wayland/ozone_platform_wayland.cc
@@ -132,6 +132,11 @@
 
   bool IsNativePixmapConfigSupported(gfx::BufferFormat format,
                                      gfx::BufferUsage usage) const override {
+    // If there is no drm render node device available, native pixmaps are not
+    // supported.
+    if (path_finder_.GetDrmRenderNodePath().empty())
+      return false;
+
     if (std::find(supported_buffer_formats_.begin(),
                   supported_buffer_formats_.end(),
                   format) == supported_buffer_formats_.end()) {
@@ -154,11 +159,7 @@
     if (!connection_->Initialize())
       LOG(FATAL) << "Failed to initialize Wayland platform";
 
-#if defined(WAYLAND_GBM)
-    if (!args.single_process)
-      connector_.reset(new WaylandConnectionConnector(connection_.get()));
-#endif
-
+    connector_.reset(new WaylandConnectionConnector(connection_.get()));
     cursor_factory_.reset(new BitmapCursorFactoryOzone);
     overlay_manager_.reset(new StubOverlayManager);
     input_controller_ = CreateStubInputController();
@@ -167,27 +168,23 @@
   }
 
   void InitializeGPU(const InitParams& args) override {
-    if (!args.single_process) {
-      proxy_.reset(new WaylandConnectionProxy(nullptr));
+    proxy_.reset(new WaylandConnectionProxy(connection_.get()));
 #if defined(WAYLAND_GBM)
-      DrmRenderNodePathFinder path_finder;
-      const base::FilePath drm_node_path = path_finder.GetDrmRenderNodePath();
-      if (drm_node_path.empty())
-        LOG(FATAL) << "Failed to find drm render node path.";
-
-      DrmRenderNodeHandle handle;
-      if (!handle.Initialize(drm_node_path))
-        LOG(FATAL) << "Failed to initialize drm render node handle.";
-
-      auto gbm = CreateGbmDevice(handle.PassFD().release());
-      if (!gbm)
-        LOG(FATAL) << "Failed to initialize gbm device.";
-
-      proxy_->set_gbm_device(std::move(gbm));
-#endif
+    const base::FilePath drm_node_path = path_finder_.GetDrmRenderNodePath();
+    if (drm_node_path.empty()) {
+      LOG(WARNING) << "Failed to find drm render node path.";
     } else {
-      proxy_.reset(new WaylandConnectionProxy(connection_.get()));
+      DrmRenderNodeHandle handle;
+      if (!handle.Initialize(drm_node_path)) {
+        LOG(WARNING) << "Failed to initialize drm render node handle.";
+      } else {
+        auto gbm = CreateGbmDevice(handle.PassFD().release());
+        if (!gbm)
+          LOG(WARNING) << "Failed to initialize gbm device.";
+        proxy_->set_gbm_device(std::move(gbm));
+      }
     }
+#endif
     surface_factory_.reset(new WaylandSurfaceFactory(proxy_.get()));
   }
 
@@ -226,6 +223,10 @@
 
   std::vector<gfx::BufferFormat> supported_buffer_formats_;
 
+  // This is used both in the gpu and browser processes to find out if a drm
+  // render node is available.
+  DrmRenderNodePathFinder path_finder_;
+
   DISALLOW_COPY_AND_ASSIGN(OzonePlatformWayland);
 };
 
diff --git a/ui/views/controls/button/button.cc b/ui/views/controls/button/button.cc
index 06e6422b..517831f 100644
--- a/ui/views/controls/button/button.cc
+++ b/ui/views/controls/button/button.cc
@@ -359,12 +359,12 @@
     SetState(STATE_HOVERED);
     hover_animation_.Reset(1.0);
     NotifyClick(*event);
-    event->StopPropagation();
+    event->SetHandled();
   } else if (event->type() == ui::ET_GESTURE_TAP_DOWN &&
              ShouldEnterPushedState(*event)) {
     SetState(STATE_PRESSED);
     RequestFocusFromEvent();
-    event->StopPropagation();
+    event->SetHandled();
   } else if (event->type() == ui::ET_GESTURE_TAP_CANCEL ||
              event->type() == ui::ET_GESTURE_END) {
     SetState(STATE_NORMAL);
diff --git a/ui/views/view.cc b/ui/views/view.cc
index 36a82eb..22aef75 100644
--- a/ui/views/view.cc
+++ b/ui/views/view.cc
@@ -1015,8 +1015,7 @@
       }
       FALLTHROUGH;
     case ui::ET_MOUSE_DRAGGED:
-      if (ProcessMouseDragged(*event))
-        event->SetHandled();
+      ProcessMouseDragged(event);
       return;
 
     case ui::ET_MOUSE_RELEASED:
@@ -2441,25 +2440,31 @@
   return !!context_menu_controller || result;
 }
 
-bool View::ProcessMouseDragged(const ui::MouseEvent& event) {
+void View::ProcessMouseDragged(ui::MouseEvent* event) {
   // Copy the field, that way if we're deleted after drag and drop no harm is
   // done.
   ContextMenuController* context_menu_controller = context_menu_controller_;
   const bool possible_drag = GetDragInfo()->possible_drag;
   if (possible_drag &&
-      ExceededDragThreshold(GetDragInfo()->start_pt - event.location()) &&
+      ExceededDragThreshold(GetDragInfo()->start_pt - event->location()) &&
       (!drag_controller_ ||
-       drag_controller_->CanStartDragForView(
-           this, GetDragInfo()->start_pt, event.location()))) {
-    DoDrag(event, GetDragInfo()->start_pt,
-           ui::DragDropTypes::DRAG_EVENT_SOURCE_MOUSE);
+       drag_controller_->CanStartDragForView(this, GetDragInfo()->start_pt,
+                                             event->location()))) {
+    if (DoDrag(*event, GetDragInfo()->start_pt,
+               ui::DragDropTypes::DRAG_EVENT_SOURCE_MOUSE)) {
+      event->StopPropagation();
+      return;
+    }
   } else {
-    if (OnMouseDragged(event))
-      return true;
+    if (OnMouseDragged(*event)) {
+      event->SetHandled();
+      return;
+    }
     // Fall through to return value based on context menu controller.
   }
   // WARNING: we may have been deleted.
-  return (context_menu_controller != nullptr) || possible_drag;
+  if ((context_menu_controller != nullptr) || possible_drag)
+    event->SetHandled();
 }
 
 void View::ProcessMouseReleased(const ui::MouseEvent& event) {
diff --git a/ui/views/view.h b/ui/views/view.h
index 2aa7df41..4c10e98 100644
--- a/ui/views/view.h
+++ b/ui/views/view.h
@@ -1650,7 +1650,7 @@
   // Input ---------------------------------------------------------------------
 
   bool ProcessMousePressed(const ui::MouseEvent& event);
-  bool ProcessMouseDragged(const ui::MouseEvent& event);
+  void ProcessMouseDragged(ui::MouseEvent* event);
   void ProcessMouseReleased(const ui::MouseEvent& event);
 
   // Accelerators --------------------------------------------------------------
diff --git a/ui/views_content_client/views_content_browser_client.cc b/ui/views_content_client/views_content_browser_client.cc
index 325bac3..9674ccdd 100644
--- a/ui/views_content_client/views_content_browser_client.cc
+++ b/ui/views_content_client/views_content_browser_client.cc
@@ -32,7 +32,8 @@
     content::StoragePartition* partition,
     storage::OptionalQuotaSettingsCallback callback) {
   storage::GetNominalDynamicSettings(
-      partition->GetPath(), context->IsOffTheRecord(), std::move(callback));
+      partition->GetPath(), context->IsOffTheRecord(),
+      storage::GetDefaultDiskInfoHelper(), std::move(callback));
 }
 
 }  // namespace ui