diff --git a/DEPS b/DEPS index 24bb66c..cf6e622 100644 --- a/DEPS +++ b/DEPS
@@ -44,7 +44,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. - 'v8_revision': '452f86d592afdd6bebaf067bcf5edc783485d61c', + 'v8_revision': '72a3ba4aff4bbd3fb68c22e36cc48564cfa0fb1e', # 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. @@ -52,7 +52,7 @@ # 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': '85d624a5101da5ed9b327dba5b8186ab25bcd9dc', + 'angle_revision': '553590a57921fd83abb814fee943c0ccc9bf45a2', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling build tools # and whatever else without interference from each other. @@ -60,11 +60,11 @@ # 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': '64ed0d75e58d5b6b12bdb30ae6b83a878a4142a6', + 'swiftshader_revision': '5bf72ee3fc17b345d88e5a75b369f9b52517ec44', # 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': '7e805d1a6f3bf7ddd04b2c1ce857a2cf6d9ff873', + 'pdfium_revision': '00d2ad12fa9d37581fd12d2ea5ea702c9e2e2e16', # 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. @@ -953,6 +953,16 @@ ], }, { + 'name': 'android_system_sdk', + 'pattern': '.', + 'action': ['python', + 'src/build/android/update_deps/update_third_party_deps.py', + 'download', + '-b', 'android_system_stubs', + '-l', 'third_party/android_system_sdk' + ], + }, + { 'name': 'intellij', 'pattern': '.', 'action': ['python',
diff --git a/android_webview/java/src/org/chromium/android_webview/AwContentsStatics.java b/android_webview/java/src/org/chromium/android_webview/AwContentsStatics.java index 0451dba..e4e2605 100644 --- a/android_webview/java/src/org/chromium/android_webview/AwContentsStatics.java +++ b/android_webview/java/src/org/chromium/android_webview/AwContentsStatics.java
@@ -115,21 +115,30 @@ @SuppressWarnings("unchecked") @TargetApi(19) - public static void initSafeBrowsing(Context context, ValueCallback<Boolean> callback) { - if (callback == null) { - callback = new ValueCallback<Boolean>() { - @Override - public void onReceiveValue(Boolean b) {} - }; - } + public static void initSafeBrowsing(Context context, final ValueCallback<Boolean> callback) { + // Wrap the callback to make sure we always invoke it on the UI thread, as guaranteed by the + // API. + ValueCallback<Boolean> wrapperCallback = new ValueCallback<Boolean>() { + @Override + public void onReceiveValue(Boolean b) { + if (callback != null) { + ThreadUtils.runOnUiThread(new Runnable() { + @Override + public void run() { + callback.onReceiveValue(b); + } + }); + } + } + }; try { Class cls = Class.forName(sSafeBrowsingWarmUpHelper); Method m = cls.getDeclaredMethod("warmUpSafeBrowsing", Context.class, ValueCallback.class); - m.invoke(null, context, callback); + m.invoke(null, context, wrapperCallback); } catch (ReflectiveOperationException e) { - callback.onReceiveValue(false); + wrapperCallback.onReceiveValue(false); } }
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/SafeBrowsingTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/SafeBrowsingTest.java index b12600a..3bbce54 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/SafeBrowsingTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/SafeBrowsingTest.java
@@ -63,6 +63,9 @@ private EmbeddedTestServer mTestServer; + // Used to check which thread a callback is invoked on. + private volatile boolean mOnUiThread; + // These colors correspond to the body.background attribute in GREEN_HTML_PATH, SAFE_HTML_PATH, // MALWARE_HTML_PATH, IFRAME_HTML_PATH, etc. They should only be changed if those values are // changed as well @@ -963,4 +966,25 @@ mContentsClient.getOnPageFinishedHelper().waitForCallback(pageFinishedCount); assertEquals(linkUrl, mAwContents.getUrl()); } + + @SmallTest + @Feature({"AndroidWebView"}) + @CommandLineFlags.Add(AwSwitches.WEBVIEW_ENABLE_SAFEBROWSING_SUPPORT) + public void testInitSafeBrowsingCallbackOnUIThread() throws Throwable { + Context ctx = getInstrumentation().getTargetContext().getApplicationContext(); + CallbackHelper helper = new CallbackHelper(); + int count = helper.getCallCount(); + mOnUiThread = false; + AwContentsStatics.initSafeBrowsing(ctx, new ValueCallback<Boolean>() { + @Override + public void onReceiveValue(Boolean b) { + mOnUiThread = ThreadUtils.runningOnUiThread(); + helper.notifyCalled(); + } + }); + helper.waitForCallback(count); + // Don't run the assert on the callback's thread, since the test runner loses the stack + // trace unless on the instrumentation thread. + assertTrue("Callback should run on UI Thread", mOnUiThread); + } }
diff --git a/ash/BUILD.gn b/ash/BUILD.gn index e8d2ecb4..55ee006 100644 --- a/ash/BUILD.gn +++ b/ash/BUILD.gn
@@ -481,7 +481,6 @@ "system/screen_security/screen_share_tray_item.h", "system/screen_security/screen_tray_item.cc", "system/screen_security/screen_tray_item.h", - "system/session/last_window_closed_observer.h", "system/session/logout_button_tray.cc", "system/session/logout_button_tray.h", "system/session/logout_confirmation_controller.cc",
diff --git a/ash/metrics/OWNERS b/ash/metrics/OWNERS deleted file mode 100644 index 21cb7090..0000000 --- a/ash/metrics/OWNERS +++ /dev/null
@@ -1 +0,0 @@ -tdanderson@chromium.org
diff --git a/ash/resources/OWNERS b/ash/resources/OWNERS index 3064b12..92f3fbb9 100644 --- a/ash/resources/OWNERS +++ b/ash/resources/OWNERS
@@ -1,2 +1 @@ oshima@chromium.org -tdanderson@chromium.org
diff --git a/ash/shelf/shelf_constants.h b/ash/shelf/shelf_constants.h index 80749375..862d582d 100644 --- a/ash/shelf/shelf_constants.h +++ b/ash/shelf/shelf_constants.h
@@ -65,8 +65,6 @@ constexpr int kShelfOpaqueColorDarkenAlpha = 178; // The width and height of the material design overflow button. -// TODO(tdanderson): Refactor constants which are common between the shelf -// and the tray. See crbug.com/623987. constexpr int kOverflowButtonSize = 32; // The radius of the rounded corners of the overflow button.
diff --git a/ash/shell.cc b/ash/shell.cc index 1d7b781..b656fd50 100644 --- a/ash/shell.cc +++ b/ash/shell.cc
@@ -736,7 +736,10 @@ for (aura::Window* root : GetAllRootWindows()) Shelf::ForWindow(root)->ShutdownShelfWidget(); tray_bluetooth_helper_.reset(); - DeleteSystemTrayDelegate(); + system_tray_delegate_.reset(); + + // Accesses root window containers. + logout_confirmation_controller_.reset(); // Drag-and-drop must be canceled prior to close all windows. drag_drop_controller_.reset(); @@ -1111,8 +1114,11 @@ resize_shadow_controller_.reset(new ResizeShadowController()); shadow_controller_.reset(new ::wm::ShadowController(focus_controller_.get())); - SetSystemTrayDelegate( - base::WrapUnique(shell_delegate_->CreateSystemTrayDelegate())); + system_tray_delegate_ = + base::WrapUnique(shell_delegate_->CreateSystemTrayDelegate()); + + logout_confirmation_controller_ = + base::MakeUnique<LogoutConfirmationController>(); // May trigger initialization of the Bluetooth adapter. tray_bluetooth_helper_->Initialize(); @@ -1197,24 +1203,6 @@ root_window->AddPostTargetHandler(toplevel_window_event_handler_.get()); } -void Shell::SetSystemTrayDelegate( - std::unique_ptr<SystemTrayDelegate> delegate) { - DCHECK(delegate); - system_tray_delegate_ = std::move(delegate); - system_tray_delegate_->Initialize(); - // Accesses ShellPort in its constructor. - logout_confirmation_controller_.reset(new LogoutConfirmationController( - base::Bind(&SystemTrayController::SignOut, - base::Unretained(system_tray_controller_.get())))); -} - -void Shell::DeleteSystemTrayDelegate() { - DCHECK(system_tray_delegate_); - // Accesses ShellPort in its destructor. - logout_confirmation_controller_.reset(); - system_tray_delegate_.reset(); -} - void Shell::CloseAllRootWindowChildWindows() { for (aura::Window* root : GetAllRootWindows()) { RootWindowController* controller = RootWindowController::ForWindow(root);
diff --git a/ash/system/OWNERS b/ash/system/OWNERS index 6f83f3f7f..bae17c8 100644 --- a/ash/system/OWNERS +++ b/ash/system/OWNERS
@@ -2,6 +2,5 @@ stevenjb@chromium.org jennyz@chromium.org skuhne@chromium.org -tdanderson@chromium.org # COMPONENT: UI>Shell>StatusArea
diff --git a/ash/system/date/date_view.cc b/ash/system/date/date_view.cc index c6346be..fc693e6 100644 --- a/ash/system/date/date_view.cc +++ b/ash/system/date/date_view.cc
@@ -127,7 +127,6 @@ DateView::DateView(SystemTrayItem* owner) : BaseDateTimeView(owner), action_(DateAction::NONE) { - // TODO(tdanderson): Tweak spacing and layout for material design. views::BoxLayout* box_layout = new views::BoxLayout(views::BoxLayout::kHorizontal, gfx::Insets(0, kTrayPopupLabelHorizontalPadding), 0);
diff --git a/ash/system/session/last_window_closed_observer.h b/ash/system/session/last_window_closed_observer.h deleted file mode 100644 index e23e5da..0000000 --- a/ash/system/session/last_window_closed_observer.h +++ /dev/null
@@ -1,22 +0,0 @@ -// Copyright 2014 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 ASH_SYSTEM_SESSION_LAST_WINDOW_CLOSED_OBSERVER_H_ -#define ASH_SYSTEM_SESSION_LAST_WINDOW_CLOSED_OBSERVER_H_ - -#include "ash/ash_export.h" - -namespace ash { - -class ASH_EXPORT LastWindowClosedObserver { - public: - virtual void OnLastWindowClosed() = 0; - - protected: - virtual ~LastWindowClosedObserver() {} -}; - -} // namespace ash - -#endif // ASH_SYSTEM_SESSION_LAST_WINDOW_CLOSED_OBSERVER_H_
diff --git a/ash/system/session/logout_confirmation_controller.cc b/ash/system/session/logout_confirmation_controller.cc index 7fab21d..68a2b46f 100644 --- a/ash/system/session/logout_confirmation_controller.cc +++ b/ash/system/session/logout_confirmation_controller.cc
@@ -7,35 +7,114 @@ #include <utility> #include "ash/login_status.h" +#include "ash/public/cpp/shell_window_ids.h" #include "ash/session/session_controller.h" #include "ash/shell.h" +#include "ash/shell_observer.h" #include "ash/system/session/logout_confirmation_dialog.h" -#include "ash/system/tray/system_tray_notifier.h" +#include "ash/system/tray/system_tray_controller.h" +#include "base/callback.h" #include "base/location.h" #include "base/time/default_tick_clock.h" #include "base/time/tick_clock.h" +#include "ui/aura/window.h" +#include "ui/aura/window_observer.h" #include "ui/views/widget/widget.h" namespace ash { namespace { const int kLogoutConfirmationDelayInSeconds = 20; + +// Shell window containers monitored for when the last window closes. +const int kLastWindowClosedContainerIds[] = { + kShellWindowId_DefaultContainer, kShellWindowId_AlwaysOnTopContainer}; + +void SignOut() { + Shell::Get()->system_tray_controller()->SignOut(); } -LogoutConfirmationController::LogoutConfirmationController( - const base::Closure& logout_closure) - : clock_(new base::DefaultTickClock), - logout_closure_(logout_closure), - dialog_(NULL), +} // namespace + +// Monitors window containers to detect when the last browser or app window is +// closing and shows a logout confirmation dialog. +class LogoutConfirmationController::LastWindowClosedObserver + : public ShellObserver, + public aura::WindowObserver { + public: + LastWindowClosedObserver() { + DCHECK_EQ(Shell::Get()->session_controller()->login_status(), + LoginStatus::PUBLIC); + Shell::Get()->AddShellObserver(this); + + // Observe all displays. + for (aura::Window* root : Shell::GetAllRootWindows()) + ObserveForLastWindowClosed(root); + } + + ~LastWindowClosedObserver() override { + // Stop observing all displays. + for (aura::Window* root : Shell::GetAllRootWindows()) { + for (int id : kLastWindowClosedContainerIds) + root->GetChildById(id)->RemoveObserver(this); + } + Shell::Get()->RemoveShellObserver(this); + } + + private: + // Observes containers in the |root| window for the last browser and/or app + // window being closed. The observers are removed automatically. + void ObserveForLastWindowClosed(aura::Window* root) { + for (int id : kLastWindowClosedContainerIds) + root->GetChildById(id)->AddObserver(this); + } + + // Shows the logout confirmation dialog if the last window is closing in the + // containers we are tracking. Called before closing instead of after closed + // because aura::WindowObserver only provides notifications to parent windows + // before a child is removed, not after. + void ShowDialogIfLastWindowClosing() { + size_t window_count = 0u; + for (aura::Window* root : Shell::GetAllRootWindows()) { + for (int id : kLastWindowClosedContainerIds) + window_count += root->GetChildById(id)->children().size(); + } + + // Prompt if the last window is closing. + if (window_count == 1) { + Shell::Get()->logout_confirmation_controller()->ConfirmLogout( + base::TimeTicks::Now() + + base::TimeDelta::FromSeconds(kLogoutConfirmationDelayInSeconds)); + } + } + + // ShellObserver: + void OnRootWindowAdded(aura::Window* root) override { + ObserveForLastWindowClosed(root); + } + + // aura::WindowObserver: + void OnWindowHierarchyChanging(const HierarchyChangeParams& params) override { + if (!params.new_parent && params.old_parent) { + // A window is being removed (and not moved to another container). + ShowDialogIfLastWindowClosing(); + } + } + + void OnWindowDestroying(aura::Window* window) override { + // Stop observing the container window when it closes. + window->RemoveObserver(this); + } + + DISALLOW_COPY_AND_ASSIGN(LastWindowClosedObserver); +}; + +LogoutConfirmationController::LogoutConfirmationController() + : clock_(base::MakeUnique<base::DefaultTickClock>()), + logout_closure_(base::Bind(&SignOut)), logout_timer_(false, false), - scoped_session_observer_(this) { - if (Shell::HasInstance()) - Shell::Get()->system_tray_notifier()->AddLastWindowClosedObserver(this); -} + scoped_session_observer_(this) {} LogoutConfirmationController::~LogoutConfirmationController() { - if (Shell::HasInstance()) - Shell::Get()->system_tray_notifier()->RemoveLastWindowClosedObserver(this); - if (dialog_) dialog_->ControllerGone(); } @@ -61,9 +140,12 @@ logout_closure_); } -void LogoutConfirmationController::SetClockForTesting( - std::unique_ptr<base::TickClock> clock) { - clock_ = std::move(clock); +void LogoutConfirmationController::OnLoginStatusChanged( + LoginStatus login_status) { + if (login_status == LoginStatus::PUBLIC) + last_window_closed_observer_ = base::MakeUnique<LastWindowClosedObserver>(); + else + last_window_closed_observer_.reset(); } void LogoutConfirmationController::OnLockStateChanged(bool locked) { @@ -89,17 +171,14 @@ logout_timer_.Stop(); } -void LogoutConfirmationController::OnLastWindowClosed() { - if (Shell::Get()->session_controller()->login_status() != - LoginStatus::PUBLIC) { - return; - } +void LogoutConfirmationController::SetClockForTesting( + std::unique_ptr<base::TickClock> clock) { + clock_ = std::move(clock); +} - // Ask the user to confirm logout if a public session is in progress and the - // screen is not locked. - ConfirmLogout( - base::TimeTicks::Now() + - base::TimeDelta::FromSeconds(kLogoutConfirmationDelayInSeconds)); +void LogoutConfirmationController::SetLogoutClosureForTesting( + const base::Closure& logout_closure) { + logout_closure_ = logout_closure; } } // namespace ash
diff --git a/ash/system/session/logout_confirmation_controller.h b/ash/system/session/logout_confirmation_controller.h index eb04e2c..b94affc 100644 --- a/ash/system/session/logout_confirmation_controller.h +++ b/ash/system/session/logout_confirmation_controller.h
@@ -9,8 +9,7 @@ #include "ash/ash_export.h" #include "ash/session/session_observer.h" -#include "ash/system/session/last_window_closed_observer.h" -#include "base/callback.h" +#include "base/callback_forward.h" #include "base/macros.h" #include "base/time/time.h" #include "base/timer/timer.h" @@ -33,12 +32,9 @@ // // In public sessions, asks the user to end the session when the last window is // closed. -class ASH_EXPORT LogoutConfirmationController - : public SessionObserver, - public LastWindowClosedObserver { +class ASH_EXPORT LogoutConfirmationController : public SessionObserver { public: - // The |logout_closure| must be safe to call as long as |this| is alive. - explicit LogoutConfirmationController(const base::Closure& logout_closure); + LogoutConfirmationController(); ~LogoutConfirmationController() override; base::TickClock* clock() const { return clock_.get(); } @@ -48,9 +44,8 @@ // the current dialog's |logout_time_|. void ConfirmLogout(base::TimeTicks logout_time); - void SetClockForTesting(std::unique_ptr<base::TickClock> clock); - // SessionObserver: + void OnLoginStatusChanged(LoginStatus login_status) override; void OnLockStateChanged(bool locked) override; // Called by the |dialog_| when the user confirms logout. @@ -59,17 +54,19 @@ // Called by the |dialog_| when it is closed. void OnDialogClosed(); + void SetClockForTesting(std::unique_ptr<base::TickClock> clock); + void SetLogoutClosureForTesting(const base::Closure& logout_closure); LogoutConfirmationDialog* dialog_for_testing() const { return dialog_; } private: - // LastWindowClosedObserver: - void OnLastWindowClosed() override; + class LastWindowClosedObserver; + std::unique_ptr<LastWindowClosedObserver> last_window_closed_observer_; std::unique_ptr<base::TickClock> clock_; base::Closure logout_closure_; base::TimeTicks logout_time_; - LogoutConfirmationDialog* dialog_; // Owned by the Views hierarchy. + LogoutConfirmationDialog* dialog_ = nullptr; // Owned by the Views hierarchy. base::Timer logout_timer_; ScopedSessionObserver scoped_session_observer_;
diff --git a/ash/system/session/logout_confirmation_controller_unittest.cc b/ash/system/session/logout_confirmation_controller_unittest.cc index 70ebeb5..1b658f7 100644 --- a/ash/system/session/logout_confirmation_controller_unittest.cc +++ b/ash/system/session/logout_confirmation_controller_unittest.cc
@@ -4,13 +4,20 @@ #include "ash/system/session/logout_confirmation_controller.h" +#include "ash/session/test_session_controller_client.h" +#include "ash/shell.h" +#include "ash/test/ash_test_base.h" #include "base/bind.h" #include "base/bind_helpers.h" #include "base/memory/ref_counted.h" #include "base/test/test_mock_time_task_runner.h" #include "base/threading/thread_task_runner_handle.h" #include "base/time/tick_clock.h" +#include "components/session_manager/session_manager_types.h" +#include "components/user_manager/user_type.h" #include "testing/gtest/include/gtest/gtest.h" +#include "ui/aura/window.h" +#include "ui/views/widget/widget.h" namespace ash { @@ -35,10 +42,10 @@ LogoutConfirmationControllerTest::LogoutConfirmationControllerTest() : log_out_called_(false), runner_(new base::TestMockTimeTaskRunner), - runner_handle_(runner_), - controller_(base::Bind(&LogoutConfirmationControllerTest::LogOut, - base::Unretained(this))) { + runner_handle_(runner_) { controller_.SetClockForTesting(runner_->GetMockTickClock()); + controller_.SetLogoutClosureForTesting(base::Bind( + &LogoutConfirmationControllerTest::LogOut, base::Unretained(this))); } LogoutConfirmationControllerTest::~LogoutConfirmationControllerTest() {} @@ -151,4 +158,116 @@ EXPECT_TRUE(log_out_called_); } +class LastWindowClosedTest : public NoSessionAshTestBase { + public: + LastWindowClosedTest() = default; + ~LastWindowClosedTest() override = default; + + // Simulate a public account signing in. + void StartPublicAccountSession() { + TestSessionControllerClient* session = GetSessionControllerClient(); + session->Reset(); + session->AddUserSession("user1@test.com", + user_manager::USER_TYPE_PUBLIC_ACCOUNT); + session->SetSessionState(session_manager::SessionState::ACTIVE); + } + + private: + DISALLOW_COPY_AND_ASSIGN(LastWindowClosedTest); +}; + +TEST_F(LastWindowClosedTest, RegularSession) { + // Dialog is not visible at startup. + LogoutConfirmationController* controller = + Shell::Get()->logout_confirmation_controller(); + EXPECT_FALSE(controller->dialog_for_testing()); + + // Dialog is not visible after login. + SetSessionStarted(true); + EXPECT_FALSE(controller->dialog_for_testing()); + + // Creating and closing a window does not show the dialog because this is not + // a public account session. + std::unique_ptr<aura::Window> window = CreateToplevelTestWindow(); + EXPECT_FALSE(controller->dialog_for_testing()); + window.reset(); + EXPECT_FALSE(controller->dialog_for_testing()); +} + +TEST_F(LastWindowClosedTest, PublicSession) { + LogoutConfirmationController* controller = + Shell::Get()->logout_confirmation_controller(); + + // Dialog is not visible after public account login. + StartPublicAccountSession(); + EXPECT_FALSE(controller->dialog_for_testing()); + + // Opening windows does not show the dialog. + std::unique_ptr<views::Widget> widget1 = CreateTestWidget(); + std::unique_ptr<views::Widget> widget2 = CreateTestWidget(); + EXPECT_FALSE(controller->dialog_for_testing()); + + // Closing the last window shows the dialog. + widget1.reset(); + EXPECT_FALSE(controller->dialog_for_testing()); + widget2.reset(); + EXPECT_TRUE(controller->dialog_for_testing()); +} + +TEST_F(LastWindowClosedTest, AlwaysOnTop) { + LogoutConfirmationController* controller = + Shell::Get()->logout_confirmation_controller(); + StartPublicAccountSession(); + + // The new widget starts in the default window container. + std::unique_ptr<views::Widget> widget = CreateTestWidget(); + + // Moving the widget to the always-on-top container does not trigger the + // dialog because the window didn't close. + widget->SetAlwaysOnTop(true); + EXPECT_FALSE(controller->dialog_for_testing()); + + // Closing the window triggers the dialog. + widget.reset(); + EXPECT_TRUE(controller->dialog_for_testing()); +} + +TEST_F(LastWindowClosedTest, MultipleContainers) { + LogoutConfirmationController* controller = + Shell::Get()->logout_confirmation_controller(); + StartPublicAccountSession(); + + // Create two windows in different containers. + std::unique_ptr<views::Widget> normal_widget = CreateTestWidget(); + std::unique_ptr<views::Widget> always_on_top_widget = CreateTestWidget(); + always_on_top_widget->SetAlwaysOnTop(true); + + // Closing the last window shows the dialog. + always_on_top_widget.reset(); + EXPECT_FALSE(controller->dialog_for_testing()); + normal_widget.reset(); + EXPECT_TRUE(controller->dialog_for_testing()); +} + +TEST_F(LastWindowClosedTest, MultipleDisplays) { + LogoutConfirmationController* controller = + Shell::Get()->logout_confirmation_controller(); + StartPublicAccountSession(); + + // Create two displays, each with a window. + UpdateDisplay("1024x768,800x600"); + std::unique_ptr<aura::Window> window1 = + CreateChildWindow(Shell::GetAllRootWindows()[0]->GetChildById( + kShellWindowId_DefaultContainer)); + std::unique_ptr<aura::Window> window2 = + CreateChildWindow(Shell::GetAllRootWindows()[1]->GetChildById( + kShellWindowId_DefaultContainer)); + + // Closing the last window shows the dialog. + window1.reset(); + EXPECT_FALSE(controller->dialog_for_testing()); + window2.reset(); + EXPECT_TRUE(controller->dialog_for_testing()); +} + } // namespace ash
diff --git a/ash/system/tray/system_tray_delegate.cc b/ash/system/tray/system_tray_delegate.cc index 327920c..33423ae 100644 --- a/ash/system/tray/system_tray_delegate.cc +++ b/ash/system/tray/system_tray_delegate.cc
@@ -10,8 +10,6 @@ SystemTrayDelegate::~SystemTrayDelegate() = default; -void SystemTrayDelegate::Initialize() {} - NetworkingConfigDelegate* SystemTrayDelegate::GetNetworkingConfigDelegate() const { return nullptr;
diff --git a/ash/system/tray/system_tray_delegate.h b/ash/system/tray/system_tray_delegate.h index 671b5e14..cd195db 100644 --- a/ash/system/tray/system_tray_delegate.h +++ b/ash/system/tray/system_tray_delegate.h
@@ -23,9 +23,6 @@ SystemTrayDelegate(); virtual ~SystemTrayDelegate(); - // Called after SystemTray has been instantiated. - virtual void Initialize(); - // Returns NetworkingConfigDelegate. May return nullptr. virtual NetworkingConfigDelegate* GetNetworkingConfigDelegate() const;
diff --git a/ash/system/tray/system_tray_notifier.cc b/ash/system/tray/system_tray_notifier.cc index 11b2c9e5..7ba5172f 100644 --- a/ash/system/tray/system_tray_notifier.cc +++ b/ash/system/tray/system_tray_notifier.cc
@@ -13,7 +13,6 @@ #include "ash/system/network/network_portal_detector_observer.h" #include "ash/system/screen_security/screen_capture_observer.h" #include "ash/system/screen_security/screen_share_observer.h" -#include "ash/system/session/last_window_closed_observer.h" #include "ash/system/status_area_focus_observer.h" #include "ash/system/tray_tracing.h" #include "ash/system/virtual_keyboard/virtual_keyboard_observer.h" @@ -119,21 +118,6 @@ observer.OnIMEMenuActivationChanged(is_active); } -void SystemTrayNotifier::AddLastWindowClosedObserver( - LastWindowClosedObserver* observer) { - last_window_closed_observers_.AddObserver(observer); -} - -void SystemTrayNotifier::RemoveLastWindowClosedObserver( - LastWindowClosedObserver* observer) { - last_window_closed_observers_.RemoveObserver(observer); -} - -void SystemTrayNotifier::NotifyLastWindowClosed() { - for (auto& observer : last_window_closed_observers_) - observer.OnLastWindowClosed(); -} - void SystemTrayNotifier::AddNetworkObserver(NetworkObserver* observer) { network_observers_.AddObserver(observer); }
diff --git a/ash/system/tray/system_tray_notifier.h b/ash/system/tray/system_tray_notifier.h index 3c65f35..84be8bd 100644 --- a/ash/system/tray/system_tray_notifier.h +++ b/ash/system/tray/system_tray_notifier.h
@@ -22,7 +22,6 @@ class ClockObserver; class EnterpriseDomainObserver; class IMEObserver; -class LastWindowClosedObserver; class NetworkObserver; class NetworkPortalDetectorObserver; class ScreenCaptureObserver; @@ -72,11 +71,6 @@ void NotifyRefreshIME(); void NotifyRefreshIMEMenu(bool is_active); - // Last window closed. - void AddLastWindowClosedObserver(LastWindowClosedObserver* observer); - void RemoveLastWindowClosedObserver(LastWindowClosedObserver* observer); - void NotifyLastWindowClosed(); - // Network. void AddNetworkObserver(NetworkObserver* observer); void RemoveNetworkObserver(NetworkObserver* observer); @@ -124,7 +118,6 @@ base::ObserverList<ClockObserver> clock_observers_; base::ObserverList<EnterpriseDomainObserver> enterprise_domain_observers_; base::ObserverList<IMEObserver> ime_observers_; - base::ObserverList<LastWindowClosedObserver> last_window_closed_observers_; base::ObserverList<NetworkObserver> network_observers_; base::ObserverList<NetworkPortalDetectorObserver> network_portal_detector_observers_;
diff --git a/ash/test/ash_test_base.h b/ash/test/ash_test_base.h index 34125cf..b975144 100644 --- a/ash/test/ash_test_base.h +++ b/ash/test/ash_test_base.h
@@ -88,9 +88,9 @@ // Creates and shows a widget. See ash/public/cpp/shell_window_ids.h for // values for |container_id|. static std::unique_ptr<views::Widget> CreateTestWidget( - views::WidgetDelegate* delegate, - int container_id, - const gfx::Rect& bounds); + views::WidgetDelegate* delegate = nullptr, + int container_id = kShellWindowId_DefaultContainer, + const gfx::Rect& bounds = gfx::Rect()); // Creates a visible window in the appropriate container. If // |bounds_in_screen| is empty the window is added to the primary root
diff --git a/ash/wm/overview/window_selector_item.cc b/ash/wm/overview/window_selector_item.cc index 9aecca6..4083e0a 100644 --- a/ash/wm/overview/window_selector_item.cc +++ b/ash/wm/overview/window_selector_item.cc
@@ -59,7 +59,7 @@ // Foreground label color. static const SkColor kLabelColor = SK_ColorWHITE; -// TODO(tdanderson): Move this to a central location. +// Close button color. static const SkColor kCloseButtonColor = SK_ColorWHITE; // Label background color once in overview mode.
diff --git a/base/i18n/file_util_icu.cc b/base/i18n/file_util_icu.cc index 08ff101..e0cf3d52 100644 --- a/base/i18n/file_util_icu.cc +++ b/base/i18n/file_util_icu.cc
@@ -115,23 +115,16 @@ while (cursor < static_cast<int>(file_name->size())) { int char_begin = cursor; uint32_t code_point; -#if defined(OS_MACOSX) - // Mac uses UTF-8 encoding for filenames. - U8_NEXT(file_name->data(), cursor, static_cast<int>(file_name->length()), - code_point); -#elif defined(OS_WIN) +#if defined(OS_WIN) // Windows uses UTF-16 encoding for filenames. U16_NEXT(file_name->data(), cursor, static_cast<int>(file_name->length()), code_point); -#elif defined(OS_POSIX) - // Linux doesn't actually define an encoding. It basically allows anything - // except for a few special ASCII characters. - unsigned char cur_char = static_cast<unsigned char>((*file_name)[cursor++]); - if (cur_char >= 0x80) - continue; - code_point = cur_char; #else - NOTREACHED(); + // Mac and Chrome OS use UTF-8 encoding for filenames. + // Linux doesn't actually define file system encoding. Try to parse as + // UTF-8. + U8_NEXT(file_name->data(), cursor, static_cast<int>(file_name->length()), + code_point); #endif if (illegal->DisallowedEverywhere(code_point) ||
diff --git a/base/i18n/file_util_icu.h b/base/i18n/file_util_icu.h index 6d7f2ec..f8bd9f4 100644 --- a/base/i18n/file_util_icu.h +++ b/base/i18n/file_util_icu.h
@@ -34,6 +34,9 @@ // refer to devices rather than files (E.g. LPT1), and some filenames could be // interpreted as shell namespace extensions (E.g. Foo.{<GUID>}). // +// On Windows, Chrome OS and Mac, the file system encoding is already known and +// parsed as UTF-8 and UTF-16 accordingly. +// On Linux, the file name will be parsed as UTF8. // TODO(asanka): Move full filename sanitization logic here. BASE_I18N_EXPORT void ReplaceIllegalCharactersInPath( FilePath::StringType* file_name,
diff --git a/base/i18n/file_util_icu_unittest.cc b/base/i18n/file_util_icu_unittest.cc index 003fcf5..2028997 100644 --- a/base/i18n/file_util_icu_unittest.cc +++ b/base/i18n/file_util_icu_unittest.cc
@@ -23,7 +23,7 @@ #if defined(OS_POSIX) && !defined(OS_MACOSX) -// Linux disallows some evil ASCII characters, but passes all non-ASCII. +// On linux, file path is parsed and filtered as UTF-8. static const struct GoodBadPairLinux { const char* bad_name; const char* good_name; @@ -82,7 +82,7 @@ {L". ", L"- -"} }; -#if defined(OS_WIN) || defined(OS_MACOSX) +#if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_POSIX) TEST_F(FileUtilICUTest, ReplaceIllegalCharactersInPathTest) { for (size_t i = 0; i < arraysize(kIllegalCharacterCases); ++i) { @@ -90,7 +90,7 @@ std::wstring bad_name(kIllegalCharacterCases[i].bad_name); ReplaceIllegalCharactersInPath(&bad_name, '-'); EXPECT_EQ(kIllegalCharacterCases[i].good_name, bad_name); -#elif defined(OS_MACOSX) +#else std::string bad_name(WideToUTF8(kIllegalCharacterCases[i].bad_name)); ReplaceIllegalCharactersInPath(&bad_name, '-'); EXPECT_EQ(WideToUTF8(kIllegalCharacterCases[i].good_name), bad_name);
diff --git a/build/android/gyp/apk_obfuscate.py b/build/android/gyp/apk_obfuscate.py deleted file mode 100755 index 04a04b3..0000000 --- a/build/android/gyp/apk_obfuscate.py +++ /dev/null
@@ -1,185 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2014 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. - -"""Generates the obfuscated jar and test jar for an apk. - -If proguard is not enabled or 'Release' is not in the configuration name, -obfuscation will be a no-op. -""" - -import json -import optparse -import os -import sys -import tempfile - -from util import build_utils -from util import proguard_util - - -_PROGUARD_KEEP_CLASS = '''-keep class %s { - *; -} -''' - - -def ParseArgs(argv): - parser = optparse.OptionParser() - parser.add_option('--android-sdk', help='path to the Android SDK folder') - parser.add_option('--android-sdk-tools', - help='path to the Android SDK build tools folder') - parser.add_option('--android-sdk-jar', - help='path to Android SDK\'s android.jar') - parser.add_option('--proguard-jar-path', - help='Path to proguard.jar in the sdk') - parser.add_option('--input-jars-paths', - help='Path to jars to include in obfuscated jar') - - parser.add_option('--proguard-configs', - help='Paths to proguard config files') - - parser.add_option('--configuration-name', - help='Gyp configuration name (i.e. Debug, Release)') - - parser.add_option('--debug-build-proguard-enabled', action='store_true', - help='--proguard-enabled takes effect on release ' - 'build, this flag enable the proguard on debug ' - 'build.') - parser.add_option('--proguard-enabled', action='store_true', - help='Set if proguard is enabled for this target.') - - parser.add_option('--obfuscated-jar-path', - help='Output path for obfuscated jar.') - - parser.add_option('--testapp', action='store_true', - help='Set this if building an instrumentation test apk') - parser.add_option('--tested-apk-obfuscated-jar-path', - help='Path to obfusctated jar of the tested apk') - parser.add_option('--test-jar-path', - help='Output path for jar containing all the test apk\'s ' - 'code.') - - parser.add_option('--stamp', help='File to touch on success') - - parser.add_option('--main-dex-list-path', - help='The list of classes to retain in the main dex. ' - 'These will not be obfuscated.') - parser.add_option('--multidex-configuration-path', - help='A JSON file containing multidex build configuration.') - parser.add_option('--verbose', '-v', action='store_true', - help='Print all proguard output') - - (options, args) = parser.parse_args(argv) - - if args: - parser.error('No positional arguments should be given. ' + str(args)) - - # Check that required options have been provided. - required_options = ( - 'android_sdk', - 'android_sdk_tools', - 'android_sdk_jar', - 'proguard_jar_path', - 'input_jars_paths', - 'configuration_name', - 'obfuscated_jar_path', - ) - - if options.testapp: - required_options += ( - 'test_jar_path', - ) - - build_utils.CheckOptions(options, parser, required=required_options) - return options, args - - -def DoProguard(options): - proguard = proguard_util.ProguardCmdBuilder(options.proguard_jar_path) - proguard.outjar(options.obfuscated_jar_path) - - input_jars = build_utils.ParseGnList(options.input_jars_paths) - - exclude_paths = [] - configs = build_utils.ParseGnList(options.proguard_configs) - if options.tested_apk_obfuscated_jar_path: - # configs should only contain the process_resources.py generated config. - assert len(configs) == 1, ( - 'test apks should not have custom proguard configs: ' + str(configs)) - proguard.tested_apk_info(options.tested_apk_obfuscated_jar_path + '.info') - - proguard.libraryjars([options.android_sdk_jar]) - proguard_injars = [p for p in input_jars if p not in exclude_paths] - proguard.injars(proguard_injars) - - multidex_config = _PossibleMultidexConfig(options) - if multidex_config: - configs.append(multidex_config) - - proguard.configs(configs) - proguard.verbose(options.verbose) - proguard.CheckOutput() - - -def _PossibleMultidexConfig(options): - if not options.multidex_configuration_path: - return None - - with open(options.multidex_configuration_path) as multidex_config_file: - multidex_config = json.loads(multidex_config_file.read()) - - if not (multidex_config.get('enabled') and options.main_dex_list_path): - return None - - main_dex_list_config = '' - with open(options.main_dex_list_path) as main_dex_list: - for clazz in (l.strip() for l in main_dex_list): - if clazz.endswith('.class'): - clazz = clazz[:-len('.class')] - clazz = clazz.replace('/', '.') - main_dex_list_config += (_PROGUARD_KEEP_CLASS % clazz) - with tempfile.NamedTemporaryFile( - delete=False, - dir=os.path.dirname(options.main_dex_list_path), - prefix='main_dex_list_proguard', - suffix='.flags') as main_dex_config_file: - main_dex_config_file.write(main_dex_list_config) - return main_dex_config_file.name - - -def main(argv): - options, _ = ParseArgs(argv) - - input_jars = build_utils.ParseGnList(options.input_jars_paths) - - if options.testapp: - dependency_class_filters = [ - '*R.class', '*R$*.class', '*Manifest.class', '*BuildConfig.class'] - build_utils.MergeZips( - options.test_jar_path, input_jars, dependency_class_filters) - - if ((options.configuration_name == 'Release' and options.proguard_enabled) or - (options.configuration_name == 'Debug' and - options.debug_build_proguard_enabled)): - DoProguard(options) - else: - output_files = [ - options.obfuscated_jar_path, - options.obfuscated_jar_path + '.info', - options.obfuscated_jar_path + '.dump', - options.obfuscated_jar_path + '.seeds', - options.obfuscated_jar_path + '.usage', - options.obfuscated_jar_path + '.mapping'] - for f in output_files: - if os.path.exists(f): - os.remove(f) - build_utils.Touch(f) - - if options.stamp: - build_utils.Touch(options.stamp) - -if __name__ == '__main__': - sys.exit(main(sys.argv[1:]))
diff --git a/build/android/gyp/configure_multidex.py b/build/android/gyp/configure_multidex.py deleted file mode 100755 index 63c74f0..0000000 --- a/build/android/gyp/configure_multidex.py +++ /dev/null
@@ -1,87 +0,0 @@ -#!/usr/bin/env python -# Copyright 2015 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 argparse -import json -import os -import sys - -from util import build_utils - - -_GCC_PREPROCESS_PATH = os.path.join( - os.path.dirname(__file__), 'gcc_preprocess.py') - - -def ParseArgs(): - parser = argparse.ArgumentParser() - parser.add_argument('--configuration-name', required=True, - help='The build CONFIGURATION_NAME.') - parser.add_argument('--enable-multidex', action='store_true', default=False, - help='If passed, multidex may be enabled.') - parser.add_argument('--enabled-configurations', default=[], - help='The configuration(s) for which multidex should be ' - 'enabled. If not specified and --enable-multidex is ' - 'passed, multidex will be enabled for all ' - 'configurations.') - parser.add_argument('--multidex-configuration-path', required=True, - help='The path to which the multidex configuration JSON ' - 'should be saved.') - parser.add_argument('--multidex-config-java-file', required=True) - parser.add_argument('--multidex-config-java-stamp', required=True) - parser.add_argument('--multidex-config-java-template', required=True) - - args = parser.parse_args() - - if args.enabled_configurations: - args.enabled_configurations = build_utils.ParseGnList( - args.enabled_configurations) - - return args - - -def _WriteConfigJson(multidex_enabled, multidex_configuration_path): - config = { - 'enabled': multidex_enabled, - } - - with open(multidex_configuration_path, 'w') as f: - f.write(json.dumps(config)) - - -def _GenerateMultidexConfigJava(multidex_enabled, args): - gcc_preprocess_cmd = [ - sys.executable, _GCC_PREPROCESS_PATH, - '--include-path=', - '--template', args.multidex_config_java_template, - '--stamp', args.multidex_config_java_stamp, - '--output', args.multidex_config_java_file, - ] - if multidex_enabled: - gcc_preprocess_cmd += [ - '--defines', 'ENABLE_MULTIDEX', - ] - - build_utils.CheckOutput(gcc_preprocess_cmd) - - -def main(): - args = ParseArgs() - - multidex_enabled = ( - args.enable_multidex - and (not args.enabled_configurations - or args.configuration_name in args.enabled_configurations)) - - _WriteConfigJson(multidex_enabled, args.multidex_configuration_path) - _GenerateMultidexConfigJava(multidex_enabled, args) - - return 0 - - -if __name__ == '__main__': - sys.exit(main()) -
diff --git a/build/android/gyp/create_device_library_links.py b/build/android/gyp/create_device_library_links.py deleted file mode 100755 index 54203067..0000000 --- a/build/android/gyp/create_device_library_links.py +++ /dev/null
@@ -1,121 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2013 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. - -"""Creates symlinks to native libraries for an APK. - -The native libraries should have previously been pushed to the device (in -options.target_dir). This script then creates links in an apk's lib/ folder to -those native libraries. -""" - -import optparse -import os -import sys - -from util import build_device -from util import build_utils - -BUILD_ANDROID_DIR = os.path.abspath( - os.path.join(os.path.dirname(__file__), '..')) -sys.path.append(BUILD_ANDROID_DIR) - -import devil_chromium -from devil.android import apk_helper -from pylib import constants - -def RunShellCommand(device, cmd): - output = device.RunShellCommand(cmd, check_return=True) - - if output: - raise Exception( - 'Unexpected output running command: ' + cmd + '\n' + - '\n'.join(output)) - - -def CreateSymlinkScript(options): - libraries = build_utils.ParseGnList(options.libraries) - - link_cmd = ( - 'rm $APK_LIBRARIES_DIR/%(lib_basename)s > /dev/null 2>&1 \n' - 'ln -s $STRIPPED_LIBRARIES_DIR/%(lib_basename)s ' - '$APK_LIBRARIES_DIR/%(lib_basename)s \n' - ) - - script = '#!/bin/sh \n' - - for lib in libraries: - script += link_cmd % { 'lib_basename': lib } - - with open(options.script_host_path, 'w') as scriptfile: - scriptfile.write(script) - - -def TriggerSymlinkScript(options): - device = build_device.GetBuildDeviceFromPath( - options.build_device_configuration) - if not device: - return - - apk_package = apk_helper.GetPackageName(options.apk) - apk_libraries_dir = '/data/data/%s/lib' % apk_package - - device_dir = os.path.dirname(options.script_device_path) - mkdir_cmd = ('if [ ! -e %(dir)s ]; then mkdir -p %(dir)s; fi ' % - { 'dir': device_dir }) - RunShellCommand(device, mkdir_cmd) - device.PushChangedFiles([(os.path.abspath(options.script_host_path), - options.script_device_path)]) - - trigger_cmd = ( - 'APK_LIBRARIES_DIR=%(apk_libraries_dir)s; ' - 'STRIPPED_LIBRARIES_DIR=%(target_dir)s; ' - '. %(script_device_path)s' - ) % { - 'apk_libraries_dir': apk_libraries_dir, - 'target_dir': options.target_dir, - 'script_device_path': options.script_device_path - } - RunShellCommand(device, trigger_cmd) - - -def main(args): - args = build_utils.ExpandFileArgs(args) - parser = optparse.OptionParser() - parser.add_option('--apk', help='Path to the apk.') - parser.add_option('--script-host-path', - help='Path on the host for the symlink script.') - parser.add_option('--script-device-path', - help='Path on the device to push the created symlink script.') - parser.add_option('--libraries', - help='List of native libraries.') - parser.add_option('--target-dir', - help='Device directory that contains the target libraries for symlinks.') - parser.add_option('--stamp', help='Path to touch on success.') - parser.add_option('--build-device-configuration', - help='Path to build device configuration.') - parser.add_option('--configuration-name', - help='The build CONFIGURATION_NAME') - parser.add_option('--output-directory', - help='The output directory') - options, _ = parser.parse_args(args) - - required_options = ['apk', 'libraries', 'script_host_path', - 'script_device_path', 'target_dir', 'configuration_name'] - build_utils.CheckOptions(options, parser, required=required_options) - constants.SetBuildType(options.configuration_name) - - devil_chromium.Initialize( - output_directory=os.path.abspath(options.output_directory)) - - CreateSymlinkScript(options) - TriggerSymlinkScript(options) - - if options.stamp: - build_utils.Touch(options.stamp) - - -if __name__ == '__main__': - sys.exit(main(sys.argv[1:]))
diff --git a/build/android/gyp/create_placeholder_files.py b/build/android/gyp/create_placeholder_files.py deleted file mode 100755 index 103e1df..0000000 --- a/build/android/gyp/create_placeholder_files.py +++ /dev/null
@@ -1,35 +0,0 @@ -#!/usr/bin/env python -# Copyright 2014 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. - -"""Create placeholder files. -""" - -import optparse -import os -import sys - -from util import build_utils - -def main(): - parser = optparse.OptionParser() - parser.add_option( - '--dest-lib-dir', - help='Destination directory to have placeholder files.') - parser.add_option( - '--stamp', - help='Path to touch on success') - - options, args = parser.parse_args() - - for name in args: - target_path = os.path.join(options.dest_lib_dir, name) - build_utils.Touch(target_path) - - if options.stamp: - build_utils.Touch(options.stamp) - -if __name__ == '__main__': - sys.exit(main()) -
diff --git a/build/android/gyp/create_standalone_apk.py b/build/android/gyp/create_standalone_apk.py deleted file mode 100755 index c560599..0000000 --- a/build/android/gyp/create_standalone_apk.py +++ /dev/null
@@ -1,60 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2013 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. - -"""Combines stripped libraries and incomplete APK into single standalone APK. - -""" - -import optparse -import os -import shutil -import sys -import tempfile - -from util import build_utils -from util import md5_check - -def CreateStandaloneApk(options): - def DoZip(): - with tempfile.NamedTemporaryFile(suffix='.zip') as intermediate_file: - intermediate_path = intermediate_file.name - shutil.copy(options.input_apk_path, intermediate_path) - apk_path_abs = os.path.abspath(intermediate_path) - build_utils.CheckOutput( - ['zip', '-r', '-1', apk_path_abs, 'lib'], - cwd=options.libraries_top_dir) - shutil.copy(intermediate_path, options.output_apk_path) - - input_paths = [options.input_apk_path, options.libraries_top_dir] - record_path = '%s.standalone.stamp' % options.input_apk_path - md5_check.CallAndRecordIfStale( - DoZip, - record_path=record_path, - input_paths=input_paths) - - -def main(): - parser = optparse.OptionParser() - parser.add_option('--libraries-top-dir', - help='Top directory that contains libraries ' - '(i.e. library paths are like ' - 'libraries_top_dir/lib/android_app_abi/foo.so).') - parser.add_option('--input-apk-path', help='Path to incomplete APK.') - parser.add_option('--output-apk-path', help='Path for standalone APK.') - parser.add_option('--stamp', help='Path to touch on success.') - options, _ = parser.parse_args() - - required_options = ['libraries_top_dir', 'input_apk_path', 'output_apk_path'] - build_utils.CheckOptions(options, parser, required=required_options) - - CreateStandaloneApk(options) - - if options.stamp: - build_utils.Touch(options.stamp) - - -if __name__ == '__main__': - sys.exit(main())
diff --git a/build/android/gyp/generate_copy_ex_outputs.py b/build/android/gyp/generate_copy_ex_outputs.py deleted file mode 100755 index e425b4a6..0000000 --- a/build/android/gyp/generate_copy_ex_outputs.py +++ /dev/null
@@ -1,33 +0,0 @@ -#!/usr/bin/env python -# -# Copyright (c) 2015 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. -# -# Generate outputs according source files and destination path for -# copy_ex.gypi - -import argparse -import os -import sys - -def DoMain(argv): - parser = argparse.ArgumentParser(prog='generate_copy_ex_outputs') - parser.add_argument('--src-files', - nargs = '+', - help = 'a list of files to copy') - parser.add_argument('--dest-path', - required = True, - help = 'the directory to copy file to') - options = parser.parse_args(argv) - # Quote each element so filename spaces don't mess up gyp's attempt to parse - # it into a list. - return ' '.join('"%s"' % os.path.join(options.dest_path, - os.path.basename(src)) - for src in options.src_files) - -if __name__ == '__main__': - results = DoMain(sys.argv[1:]) - if results: - print results -
diff --git a/build/android/gyp/get_device_configuration.py b/build/android/gyp/get_device_configuration.py deleted file mode 100755 index 0ec08ef9..0000000 --- a/build/android/gyp/get_device_configuration.py +++ /dev/null
@@ -1,78 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2013 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. - -"""Gets and writes the configurations of the attached devices. - -This configuration is used by later build steps to determine which devices to -install to and what needs to be installed to those devices. -""" - -import optparse -import os -import sys - -from util import build_device -from util import build_utils - -BUILD_ANDROID_DIR = os.path.abspath( - os.path.join(os.path.dirname(__file__), '..')) -sys.path.append(BUILD_ANDROID_DIR) - -import devil_chromium - - -def main(argv): - parser = optparse.OptionParser() - parser.add_option('--stamp', action='store') - parser.add_option('--output', action='store') - parser.add_option('--output-directory', action='store') - options, _ = parser.parse_args(argv) - - devil_chromium.Initialize( - output_directory=os.path.abspath(options.output_directory)) - - devices = build_device.GetAttachedDevices() - - device_configurations = [] - for d in devices: - configuration, is_online, has_root = ( - build_device.GetConfigurationForDevice(d)) - - if not is_online: - build_utils.PrintBigWarning( - '%s is not online. Skipping managed install for this device. ' - 'Try rebooting the device to fix this warning.' % d) - continue - - if not has_root: - build_utils.PrintBigWarning( - '"adb root" failed on device: %s\n' - 'Skipping managed install for this device.' - % configuration['description']) - continue - - device_configurations.append(configuration) - - if len(device_configurations) == 0: - build_utils.PrintBigWarning( - 'No valid devices attached. Skipping managed install steps.') - elif len(devices) > 1: - # Note that this checks len(devices) and not len(device_configurations). - # This way, any time there are multiple devices attached it is - # explicitly stated which device we will install things to even if all but - # one device were rejected for other reasons (e.g. two devices attached, - # one w/o root). - build_utils.PrintBigWarning( - 'Multiple devices attached. ' - 'Installing to the preferred device: ' - '%(id)s (%(description)s)' % (device_configurations[0])) - - - build_device.WriteConfigurations(device_configurations, options.output) - - -if __name__ == '__main__': - sys.exit(main(sys.argv))
diff --git a/build/android/gyp/jar_toc.py b/build/android/gyp/jar_toc.py deleted file mode 100755 index 540a3439..0000000 --- a/build/android/gyp/jar_toc.py +++ /dev/null
@@ -1,120 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2013 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. - -"""Creates a TOC file from a Java jar. - -The TOC file contains the non-package API of the jar. This includes all -public/protected/package classes/functions/members and the values of static -final variables (members with package access are kept because in some cases we -have multiple libraries with the same package, particularly test+non-test). Some -other information (major/minor javac version) is also included. - -This TOC file then can be used to determine if a dependent library should be -rebuilt when this jar changes. I.e. any change to the jar that would require a -rebuild, will have a corresponding change in the TOC file. -""" - -import optparse -import os -import re -import sys -import zipfile - -from util import build_utils -from util import md5_check - - -def GetClassesInZipFile(zip_file): - classes = [] - files = zip_file.namelist() - for f in files: - if f.endswith('.class'): - # f is of the form org/chromium/base/Class$Inner.class - classes.append(f.replace('/', '.')[:-6]) - return classes - - -def CallJavap(classpath, classes): - javap_cmd = [ - 'javap', - '-package', # Show public/protected/package. - # -verbose is required to get constant values (which can be inlined in - # dependents). - '-verbose', - '-J-XX:NewSize=4m', - '-classpath', classpath - ] + classes - return build_utils.CheckOutput(javap_cmd) - - -def ExtractToc(disassembled_classes): - # javap output is structured by indent (2-space) levels. - good_patterns = [ - '^[^ ]', # This includes all class signatures. - '^ SourceFile:', - '^ minor version:', - '^ major version:', - '^ Constant value:', - '^ public ', - '^ protected ', - ] - bad_patterns = [ - '^const #', # Matches the constant pool (i.e. literals used in the class). - ] - - def JavapFilter(line): - return (re.match('|'.join(good_patterns), line) and - not re.match('|'.join(bad_patterns), line)) - toc = filter(JavapFilter, disassembled_classes.split('\n')) - - return '\n'.join(toc) - - -def UpdateToc(jar_path, toc_path): - classes = GetClassesInZipFile(zipfile.ZipFile(jar_path)) - toc = '' - if len(classes) != 0: - javap_output = CallJavap(classpath=jar_path, classes=classes) - toc = ExtractToc(javap_output) - - with open(toc_path, 'w') as tocfile: - tocfile.write(toc) - - -def DoJarToc(options): - jar_path = options.jar_path - toc_path = options.toc_path - record_path = '%s.md5.stamp' % toc_path - md5_check.CallAndRecordIfStale( - lambda: UpdateToc(jar_path, toc_path), - record_path=record_path, - input_paths=[jar_path], - force=not os.path.exists(toc_path), - ) - build_utils.Touch(toc_path, fail_if_missing=True) - - -def main(): - parser = optparse.OptionParser() - build_utils.AddDepfileOption(parser) - - parser.add_option('--jar-path', help='Input .jar path.') - parser.add_option('--toc-path', help='Output .jar.TOC path.') - parser.add_option('--stamp', help='Path to touch on success.') - - options, _ = parser.parse_args() - - DoJarToc(options) - - if options.depfile: - build_utils.WriteDepfile(options.depfile, options.toc_path) - - if options.stamp: - build_utils.Touch(options.stamp) - - -if __name__ == '__main__': - sys.exit(main())
diff --git a/build/android/gyp/push_libraries.py b/build/android/gyp/push_libraries.py deleted file mode 100755 index 1a64f3d..0000000 --- a/build/android/gyp/push_libraries.py +++ /dev/null
@@ -1,85 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2013 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. - -"""Pushes native libraries to a device. - -""" - -import optparse -import os -import sys - -from util import build_device -from util import build_utils -from util import md5_check - -BUILD_ANDROID_DIR = os.path.abspath( - os.path.join(os.path.dirname(__file__), os.pardir)) -sys.path.append(BUILD_ANDROID_DIR) - -import devil_chromium -from pylib import constants - -def DoPush(options): - libraries = build_utils.ParseGnList(options.libraries) - - device = build_device.GetBuildDeviceFromPath( - options.build_device_configuration) - if not device: - return - - serial_number = device.GetSerialNumber() - # A list so that it is modifiable in Push below. - needs_directory = [True] - for lib in libraries: - device_path = os.path.join(options.device_dir, lib) - host_path = os.path.join(options.libraries_dir, lib) - - def Push(): - if needs_directory: - device.RunShellCommand( - ['mkdir', '-p', options.device_dir], check_return=True) - needs_directory[:] = [] # = False - device.PushChangedFiles([(os.path.abspath(host_path), device_path)]) - - record_path = '%s.%s.push.md5.stamp' % (host_path, serial_number) - md5_check.CallAndRecordIfStale( - Push, - record_path=record_path, - input_paths=[host_path], - input_strings=[device_path]) - - -def main(args): - args = build_utils.ExpandFileArgs(args) - parser = optparse.OptionParser() - parser.add_option('--libraries-dir', - help='Directory that contains stripped libraries.') - parser.add_option('--device-dir', - help='Device directory to push the libraries to.') - parser.add_option('--libraries', - help='List of native libraries.') - parser.add_option('--stamp', help='Path to touch on success.') - parser.add_option('--build-device-configuration', - help='Path to build device configuration.') - parser.add_option('--output-directory', - help='The output directory.') - options, _ = parser.parse_args(args) - - required_options = ['libraries', 'device_dir', 'libraries'] - build_utils.CheckOptions(options, parser, required=required_options) - - devil_chromium.Initialize( - output_directory=os.path.abspath(options.output_directory)) - - DoPush(options) - - if options.stamp: - build_utils.Touch(options.stamp) - - -if __name__ == '__main__': - sys.exit(main(sys.argv[1:]))
diff --git a/build/android/gyp/touch.py b/build/android/gyp/touch.py deleted file mode 100755 index 7b4375e..0000000 --- a/build/android/gyp/touch.py +++ /dev/null
@@ -1,16 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2014 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 sys - -from util import build_utils - -def main(argv): - for f in argv[1:]: - build_utils.Touch(f) - -if __name__ == '__main__': - sys.exit(main(sys.argv))
diff --git a/build/android/gyp/util/build_device.py b/build/android/gyp/util/build_device.py deleted file mode 100644 index 6a703c6..0000000 --- a/build/android/gyp/util/build_device.py +++ /dev/null
@@ -1,102 +0,0 @@ -# Copyright 2013 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. - -""" A simple device interface for build steps. - -""" - -import logging -import os -import re -import sys - -from util import build_utils - -from devil.android import device_errors -from devil.android import device_utils -from devil.android.sdk import adb_wrapper - - -def GetAttachedDevices(): - return [a.GetDeviceSerial() - for a in adb_wrapper.AdbWrapper.Devices()] - - -class BuildDevice(object): - def __init__(self, configuration): - self.id = configuration['id'] - self.description = configuration['description'] - self.install_metadata = configuration['install_metadata'] - assert all(isinstance(entry, dict) for entry in self.install_metadata), ( - 'Invalid BuildDevice configuration') - self.device = device_utils.DeviceUtils(self.id) - - def RunShellCommand(self, *args, **kwargs): - return self.device.RunShellCommand(*args, **kwargs) - - def PushChangedFiles(self, *args, **kwargs): - return self.device.PushChangedFiles(*args, **kwargs) - - def GetSerialNumber(self): - return self.id - - def Install(self, *args, **kwargs): - return self.device.Install(*args, **kwargs) - - def InstallSplitApk(self, *args, **kwargs): - return self.device.InstallSplitApk(*args, **kwargs) - - def GetInstallMetadata(self, apk_package, refresh=False): - """Gets the metadata on the device for a given apk. - - Args: - apk_package: A string with the package name for which to get metadata. - refresh: A boolean indicating whether to re-read package metadata from - the device, or use the values from the current configuration. - """ - if refresh: - self.install_metadata = self.device.StatDirectory( - '/data/app/', as_root=True) - # Matches names like: org.chromium.chrome.apk, org.chromium.chrome-1.apk - apk_pattern = re.compile('%s(-[0-9]*)?(.apk)?$' % re.escape(apk_package)) - return next( - (entry for entry in self.install_metadata - if apk_pattern.match(entry['filename'])), - None) - - -def GetConfigurationForDevice(device_id): - device = device_utils.DeviceUtils(device_id) - configuration = None - has_root = False - is_online = device.IsOnline() - if is_online: - has_root = device.HasRoot() - configuration = { - 'id': device_id, - 'description': device.build_description, - 'install_metadata': device.StatDirectory('/data/app/', as_root=True), - } - return configuration, is_online, has_root - - -def WriteConfigurations(configurations, path): - # Currently we only support installing to the first device. - build_utils.WriteJson(configurations[:1], path, only_if_changed=True) - - -def ReadConfigurations(path): - return build_utils.ReadJson(path) - - -def GetBuildDevice(configurations): - assert len(configurations) == 1 - return BuildDevice(configurations[0]) - - -def GetBuildDeviceFromPath(path): - configurations = ReadConfigurations(path) - if len(configurations) > 0: - return GetBuildDevice(ReadConfigurations(path)) - return None
diff --git a/build/android/gyp/zip.py b/build/android/gyp/zip.py deleted file mode 100755 index 51322dfd..0000000 --- a/build/android/gyp/zip.py +++ /dev/null
@@ -1,26 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2014 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. - -"""Archives a set of files. -""" - -import optparse -import sys - -from util import build_utils - -def main(): - parser = optparse.OptionParser() - parser.add_option('--input-dir', help='Directory of files to archive.') - parser.add_option('--output', help='Path to output archive.') - options, _ = parser.parse_args() - - inputs = build_utils.FindInDirectory(options.input_dir, '*') - build_utils.DoZip(inputs, options.output, options.input_dir) - - -if __name__ == '__main__': - sys.exit(main())
diff --git a/build/config/fuchsia/rules.gni b/build/config/fuchsia/rules.gni index b3e7f3b..2b6f99d 100644 --- a/build/config/fuchsia/rules.gni +++ b/build/config/fuchsia/rules.gni
@@ -4,12 +4,7 @@ assert(is_fuchsia) -# This template is used to generate a runner script for test binaries into the -# build dir for Fuchsia. It's generally used from the "test" template. -template("test_runner_script") { - testonly = true - _test_name = invoker.test_name - +template("generate_runner_script") { # This runtime_deps file is used at runtime and thus cannot go in # target_gen_dir. _target_dir_name = get_label_info(":$target_name", "dir") @@ -23,6 +18,7 @@ "data_deps", "deps", "public_deps", + "testonly", ]) write_runtime_deps = _runtime_deps_file } @@ -32,6 +28,9 @@ [ "data_deps", "deps", + "runner_script", + "target", + "testonly", ]) if (!defined(deps)) { deps = [] @@ -40,39 +39,67 @@ data_deps = [] } - script = "//build/fuchsia/create_test_runner_script.py" + script = "//build/fuchsia/create_runner_script.py" depfile = "$target_gen_dir/$target_name.d" data = [] - test_runner_args = [] + runner_args = [] - generated_script = "$root_build_dir/bin/run_${_test_name}" + generated_script = "$root_build_dir/bin/run_${target}" outputs = [ generated_script, ] data += [ generated_script ] - test_runner_args += [ + runner_args += [ + "--runner-script", + runner_script, "--output-directory", rebase_path(root_build_dir, root_build_dir), ] deps += [ ":$_runtime_deps_target" ] data += [ _runtime_deps_file ] - test_runner_args += [ + runner_args += [ "--runtime-deps-path", rebase_path(_runtime_deps_file, root_build_dir), ] + if (defined(args)) { + args = [] + } args = [ "--depfile", rebase_path(depfile, root_build_dir), "--script-output-path", rebase_path(generated_script, root_build_dir), - "--test-name", - _test_name, + "--exe-name", + target, ] - args += test_runner_args + args += runner_args + } +} + +# This template is used to generate a runner script for test binaries into the +# build dir for Fuchsia. It's generally used from the "test" template. +template("test_runner_script") { + generate_runner_script(target_name) { + testonly = true + runner_script = "test_runner.py" + target = invoker.test_name + forward_variables_from(invoker, "*") + } +} + +# This template is used to generate a runner script for arbitrary executables +# into the build dir for Fuchsia. The template should be instantiated alongside +# an "executable" target, and referenced from the executable via its "deps" +# attribute. +template("fuchsia_executable_runner") { + generate_runner_script(target_name) { + runner_script = "exe_runner.py" + target = invoker.exe_name + forward_variables_from(invoker, "*") } }
diff --git a/build/fuchsia/create_test_runner_script.py b/build/fuchsia/create_runner_script.py similarity index 62% rename from build/fuchsia/create_test_runner_script.py rename to build/fuchsia/create_runner_script.py index c85e7ce..f50064b 100755 --- a/build/fuchsia/create_test_runner_script.py +++ b/build/fuchsia/create_runner_script.py
@@ -4,8 +4,8 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -"""Creates a script to run a Fushsia test (typically on QEMU) by delegating to -build/fuchsia/test_runner.py. +"""Creates a script to run a Fushsia executable by delegating to +build/fuchsia/(exe|test)_runner.py. """ import argparse @@ -17,7 +17,7 @@ SCRIPT_TEMPLATE = """\ #!/usr/bin/env python # -# This file was generated by build/fuchsia/create_test_runner_script.py +# This file was generated by build/fuchsia/create_runner_script.py import os import sys @@ -30,14 +30,14 @@ \"\"\" return os.path.abspath(os.path.join(script_directory, path)) - test_runner_path = ResolvePath('{test_runner_path}') - test_runner_args = {test_runner_args} - test_runner_path_args = {test_runner_path_args} - for arg, path in test_runner_path_args: - test_runner_args.extend([arg, ResolvePath(path)]) + runner_path = ResolvePath('{runner_path}') + runner_args = {runner_args} + runner_path_args = {runner_path_args} + for arg, path in runner_path_args: + runner_args.extend([arg, ResolvePath(path)]) - os.execv(test_runner_path, - [test_runner_path] + test_runner_args + sys.argv[1:]) + os.execv(runner_path, + [runner_path] + runner_args + sys.argv[1:]) if __name__ == '__main__': sys.exit(main()) @@ -65,6 +65,8 @@ def main(args): parser = argparse.ArgumentParser() + parser.add_argument('--runner-script', + help='Name of the runner script to use.') parser.add_argument('--script-output-path', help='Output path for executable script.') parser.add_argument('--depfile', @@ -75,33 +77,30 @@ group = parser.add_argument_group('Test runner path arguments.') group.add_argument('--output-directory') group.add_argument('--runtime-deps-path') - group.add_argument('--test-name') - args, test_runner_args = parser.parse_known_args(args) + group.add_argument('--exe-name') + args, runner_args = parser.parse_known_args(args) def RelativizePathToScript(path): """Returns the path relative to the output script directory.""" return os.path.relpath(path, os.path.dirname(args.script_output_path)) - test_runner_path = args.test_runner_path or os.path.join( - os.path.dirname(__file__), 'test_runner.py') - test_runner_path = RelativizePathToScript(test_runner_path) + runner_path = args.test_runner_path or os.path.join( + os.path.dirname(__file__), args.runner_script) + runner_path = RelativizePathToScript(runner_path) - test_runner_path_args = [] - if args.output_directory: - test_runner_path_args.append( - ('--output-directory', RelativizePathToScript(args.output_directory))) - if args.runtime_deps_path: - test_runner_path_args.append( - ('--runtime-deps-path', RelativizePathToScript(args.runtime_deps_path))) - if args.test_name: - test_runner_path_args.append( - ('--test-name', RelativizePathToScript(args.test_name))) + runner_path_args = [] + runner_path_args.append( + ('--output-directory', RelativizePathToScript(args.output_directory))) + runner_path_args.append( + ('--runtime-deps-path', RelativizePathToScript(args.runtime_deps_path))) + runner_path_args.append( + ('--exe-name', RelativizePathToScript(args.exe_name))) with open(args.script_output_path, 'w') as script: script.write(SCRIPT_TEMPLATE.format( - test_runner_path=str(test_runner_path), - test_runner_args=str(test_runner_args), - test_runner_path_args=str(test_runner_path_args))) + runner_path=str(runner_path), + runner_args=str(runner_args), + runner_path_args=str(runner_path_args))) os.chmod(args.script_output_path, 0750)
diff --git a/build/fuchsia/exe_runner.py b/build/fuchsia/exe_runner.py new file mode 100755 index 0000000..1eb0fb6 --- /dev/null +++ b/build/fuchsia/exe_runner.py
@@ -0,0 +1,47 @@ +#!/usr/bin/env python +# +# 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. + +"""Packages a user.bootfs for a Fuchsia boot image, pulling in the runtime +dependencies of a binary, and then uses either QEMU from the Fuchsia SDK +to run, or starts the bootserver to allow running on a hardware device.""" + +import argparse +import os +import sys + +from runner_common import RunFuchsia, BuildBootfs, ReadRuntimeDeps + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument('--dry-run', '-n', action='store_true', default=False, + help='Just print commands, don\'t execute them.') + parser.add_argument('--output-directory', + type=os.path.realpath, + help=('Path to the directory in which build files are' + ' located (must include build type).')) + parser.add_argument('--runtime-deps-path', + type=os.path.realpath, + help='Runtime data dependency file from GN.') + parser.add_argument('--exe-name', + type=os.path.realpath, + help='Name of the the binary executable.') + parser.add_argument('-d', '--device', action='store_true', default=False, + help='Run on hardware device instead of QEMU.') + args, child_args = parser.parse_known_args() + + bootfs = BuildBootfs( + args.output_directory, + ReadRuntimeDeps(args.runtime_deps_path, args.output_directory), + args.exe_name, child_args, args.device, args.dry_run) + if not bootfs: + return 2 + + return RunFuchsia(bootfs, args.exe_name, args.device, args.dry_run) + + +if __name__ == '__main__': + sys.exit(main())
diff --git a/build/fuchsia/runner_common.py b/build/fuchsia/runner_common.py new file mode 100755 index 0000000..e170f03 --- /dev/null +++ b/build/fuchsia/runner_common.py
@@ -0,0 +1,327 @@ +#!/usr/bin/env python +# +# 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. + +"""Packages a user.bootfs for a Fuchsia boot image, pulling in the runtime +dependencies of a binary, and then uses either QEMU from the Fuchsia SDK +to run, or starts the bootserver to allow running on a hardware device.""" + +import argparse +import multiprocessing +import os +import re +import shutil +import signal +import subprocess +import sys +import tempfile + + +DIR_SOURCE_ROOT = os.path.abspath( + os.path.join(os.path.dirname(__file__), os.pardir, os.pardir)) +SDK_ROOT = os.path.join(DIR_SOURCE_ROOT, 'third_party', 'fuchsia-sdk') +SYMBOLIZATION_TIMEOUT_SECS = 10 + + +def _RunAndCheck(dry_run, args): + if dry_run: + print 'Run:', ' '.join(args) + return 0 + else: + try: + subprocess.check_call(args) + return 0 + except subprocess.CalledProcessError as e: + return e.returncode + + +def _DumpFile(dry_run, name, description): + """Prints out the contents of |name| if |dry_run|.""" + if not dry_run: + return + print + print 'Contents of %s (for %s)' % (name, description) + print '-' * 80 + with open(name) as f: + sys.stdout.write(f.read()) + print '-' * 80 + + +def MakeTargetImageName(common_prefix, output_directory, location): + """Generates the relative path name to be used in the file system image. + common_prefix: a prefix of both output_directory and location that + be removed. + output_directory: an optional prefix on location that will also be removed. + location: the file path to relativize. + + .so files will be stored into the lib subdirectory to be able to be found by + default by the loader. + + Examples: + + >>> MakeTargetImageName(common_prefix='/work/cr/src/', + ... output_directory='/work/cr/src/out/fuch', + ... location='/work/cr/src/base/test/data/xyz.json') + 'base/test/data/xyz.json' + + >>> MakeTargetImageName(common_prefix='/work/cr/src/', + ... output_directory='/work/cr/src/out/fuch', + ... location='/work/cr/src/out/fuch/icudtl.dat') + 'icudtl.dat' + + >>> MakeTargetImageName(common_prefix='/work/cr/src/', + ... output_directory='/work/cr/src/out/fuch', + ... location='/work/cr/src/out/fuch/libbase.so') + 'lib/libbase.so' + """ + assert output_directory.startswith(common_prefix) + output_dir_no_common_prefix = output_directory[len(common_prefix):] + assert location.startswith(common_prefix) + loc = location[len(common_prefix):] + if loc.startswith(output_dir_no_common_prefix): + loc = loc[len(output_dir_no_common_prefix)+1:] + # TODO(fuchsia): The requirements for finding/loading .so are in flux, so this + # ought to be reconsidered at some point. See https://crbug.com/732897. + if location.endswith('.so'): + loc = 'lib/' + loc + return loc + + +def _AddToManifest(manifest_file, target_name, source, mapper): + """Appends |source| to the given |manifest_file| (a file object) in a format + suitable for consumption by mkbootfs. + + If |source| is a file it's directly added. If |source| is a directory, its + contents are recursively added. + + |source| must exist on disk at the time this function is called. + """ + if os.path.isdir(source): + files = [os.path.join(dp, f) for dp, dn, fn in os.walk(source) for f in fn] + for f in files: + # We pass None as the mapper because this should never recurse a 2nd time. + _AddToManifest(manifest_file, mapper(f), f, None) + elif os.path.exists(source): + manifest_file.write('%s=%s\n' % (target_name, source)) + else: + raise Exception('%s does not exist' % source) + + +def ReadRuntimeDeps(deps_path, output_dir): + return [os.path.abspath(os.path.join(output_dir, x.strip())) + for x in open(deps_path)] + + +def _StripBinary(dry_run, bin_path): + strip_path = bin_path + '_stripped'; + shutil.copyfile(bin_path, strip_path) + _RunAndCheck(dry_run, ['/usr/bin/strip', strip_path]) + return strip_path + + +def BuildBootfs(output_directory, runtime_deps, bin_name, child_args, + device, dry_run): + locations_to_add = [os.path.abspath(os.path.join(output_directory, x.strip())) + for x in runtime_deps] + + common_prefix = '/' + if len(locations_to_add) > 1: + common_prefix = os.path.commonprefix(locations_to_add) + target_source_pairs = zip( + [MakeTargetImageName(common_prefix, output_directory, loc) + for loc in locations_to_add], + locations_to_add) + + # Stage the stripped binary in the boot image, keeping the original binary's + # name for symbolization purposes. + bin_path = os.path.abspath(os.path.join(output_directory, bin_name)) + stripped_bin_path = _StripBinary(dry_run, bin_path) + target_source_pairs.append( + [MakeTargetImageName(common_prefix, output_directory, bin_path), + stripped_bin_path]) + + # Generate a script that runs the binaries and shuts down QEMU (if used). + autorun_file = tempfile.NamedTemporaryFile() + autorun_file.write('#!/bin/sh\n') + autorun_file.write('echo Executing ' + os.path.basename(bin_name) + ' ' + + ' '.join(child_args) + '\n') + autorun_file.write('/system/' + os.path.basename(bin_name)) + for arg in child_args: + autorun_file.write(' "%s"' % arg); + autorun_file.write('\n') + autorun_file.write('echo Process terminated.\n') + + if not device: + # If shutdown of QEMU happens too soon after the program finishes, log + # statements from the end of the run will be lost, so sleep for a bit before + # shutting down. When running on device don't power off so the output and + # system can be inspected. + autorun_file.write('msleep 3000\n') + autorun_file.write('dm poweroff\n') + + autorun_file.flush() + os.chmod(autorun_file.name, 0750) + _DumpFile(dry_run, autorun_file.name, 'autorun') + target_source_pairs.append(('autorun', autorun_file.name)) + + manifest_file = tempfile.NamedTemporaryFile() + bootfs_name = bin_name + '.bootfs' + + for target, source in target_source_pairs: + _AddToManifest(manifest_file.file, target, source, + lambda x: MakeTargetImageName( + common_prefix, output_directory, x)) + + mkbootfs_path = os.path.join(SDK_ROOT, 'tools', 'mkbootfs') + + manifest_file.flush() + _DumpFile(dry_run, manifest_file.name, 'manifest') + if _RunAndCheck( + dry_run, + [mkbootfs_path, '-o', bootfs_name, + '--target=boot', os.path.join(SDK_ROOT, 'bootdata.bin'), + '--target=system', manifest_file.name]) != 0: + return None + + return bootfs_name + + +def _SymbolizeEntry(entry): + addr2line_output = subprocess.check_output( + ['addr2line', '-Cipf', '--exe=' + entry[1], entry[2]]) + prefix = '#%s: ' % entry[0] + # addr2line outputs a second line for inlining information, offset + # that to align it properly after the frame index. + addr2line_filtered = addr2line_output.strip().replace( + '(inlined', ' ' * len(prefix) + '(inlined') + if '??' in addr2line_filtered: + addr2line_filtered = "%s+%s" % (os.path.basename(entry[1]), entry[2]) + return '%s%s' % (prefix, addr2line_filtered) + + +def _ParallelSymbolizeBacktrace(backtrace): + # Disable handling of SIGINT during sub-process creation, to prevent + # sub-processes from consuming Ctrl-C signals, rather than the parent + # process doing so. + saved_sigint_handler = signal.signal(signal.SIGINT, signal.SIG_IGN) + p = multiprocessing.Pool(multiprocessing.cpu_count()) + + # Restore the signal handler for the parent process. + signal.signal(signal.SIGINT, saved_sigint_handler) + + symbolized = [] + try: + result = p.map_async(_SymbolizeEntry, backtrace) + symbolized = result.get(SYMBOLIZATION_TIMEOUT_SECS) + if not symbolized: + return [] + except multiprocessing.TimeoutError: + return ['(timeout error occurred during symbolization)'] + except KeyboardInterrupt: # SIGINT + p.terminate() + + return symbolized + + +def RunFuchsia(bootfs, exe_name, use_device, dry_run): + kernel_path = os.path.join(SDK_ROOT, 'kernel', 'magenta.bin') + + if use_device: + # TODO(fuchsia): This doesn't capture stdout as there's no way to do so + # currently. See https://crbug.com/749242. + bootserver_path = os.path.join(SDK_ROOT, 'tools', 'bootserver') + bootserver_command = [bootserver_path, '-1', kernel_path, bootfs] + return _RunAndCheck(dry_run, bootserver_command) + + qemu_path = os.path.join(SDK_ROOT, 'qemu', 'bin', 'qemu-system-x86_64') + qemu_command = [qemu_path, + '-m', '2048', + '-nographic', + '-net', 'none', + '-smp', '4', + '-machine', 'q35', + '-kernel', kernel_path, + '-initrd', bootfs, + + # Use stdio for the guest OS only; don't attach the QEMU interactive + # monitor. + '-serial', 'stdio', + '-monitor', 'none', + + # TERM=dumb tells the guest OS to not emit ANSI commands that trigger + # noisy ANSI spew from the user's terminal emulator. + '-append', 'TERM=dumb kernel.halt_on_panic=true'] + + if int(os.environ.get('CHROME_HEADLESS', 0)) == 0: + qemu_command += ['-enable-kvm', '-cpu', 'host,migratable=no'] + else: + qemu_command += ['-cpu', 'Haswell,+smap,-check'] + + if dry_run: + print 'Run:', ' '.join(qemu_command) + return 0 + + # Set up backtrace-parsing regexps. + prefix = r'^.*> ' + bt_end_re = re.compile(prefix + '(bt)?#(\d+):? end') + bt_with_offset_re = re.compile( + prefix + 'bt#(\d+): pc 0x[0-9a-f]+ sp (0x[0-9a-f]+) ' + + '\((\S+),(0x[0-9a-f]+)\)$') + in_process_re = re.compile(prefix + + '#(\d+) 0x[0-9a-f]+ \S+\+(0x[0-9a-f]+)$') + + # We pass a separate stdin stream to qemu. Sharing stdin across processes + # leads to flakiness due to the OS prematurely killing the stream and the + # Python script panicking and aborting. + # The precise root cause is still nebulous, but this fix works. + # See crbug.com/741194 . + qemu_popen = subprocess.Popen( + qemu_command, stdout=subprocess.PIPE, stdin=open(os.devnull)) + + # A buffer of backtrace entries awaiting symbolization, stored as tuples. + # Element #0: backtrace frame number (starting at 0). + # Element #1: path to executable code corresponding to the current frame. + # Element #2: memory offset within the executable. + bt_entries = [] + + success = False + while True: + line = qemu_popen.stdout.readline().strip() + if not line: + break + if 'SUCCESS: all tests passed.' in line: + success = True + + # Check for an end-of-backtrace marker. + if bt_end_re.match(line): + if bt_entries: + print '----- start symbolized stack' + for processed in _ParallelSymbolizeBacktrace(bt_entries): + print processed + print '----- end symbolized stack' + bt_entries = [] + continue + + # Try to parse this as a Fuchsia system backtrace. + m = bt_with_offset_re.match(line) + if m: + bt_entries.append((m.group(1), exe_name, m.group(4))) + continue + + # Try to parse the line as an in-process backtrace entry. + m = in_process_re.match(line) + if m: + bt_entries.append((m.group(1), exe_name, m.group(2))) + continue + + # Some other line, so print it. Back-traces should not be interleaved with + # other output, so while this may re-order lines we see, it should actually + # make things more readable. + print line + + qemu_popen.wait() + + return 0 if success else 1 +
diff --git a/build/fuchsia/test_runner.py b/build/fuchsia/test_runner.py index 0ba1b4c..a9f72d5a 100755 --- a/build/fuchsia/test_runner.py +++ b/build/fuchsia/test_runner.py
@@ -9,207 +9,11 @@ to run, or starts the bootserver to allow running on a hardware device.""" import argparse -import multiprocessing import os -import re -import signal -import subprocess import sys -import tempfile - -DIR_SOURCE_ROOT = os.path.abspath( - os.path.join(os.path.dirname(__file__), os.pardir, os.pardir)) -SDK_ROOT = os.path.join(DIR_SOURCE_ROOT, 'third_party', 'fuchsia-sdk') -SYMBOLIZATION_TIMEOUT_SECS = 10 - - -def RunAndCheck(dry_run, args): - if dry_run: - print 'Run:', args - else: - try: - subprocess.check_call(args) - return 0 - except subprocess.CalledProcessError as e: - return e.returncode - - -def DumpFile(dry_run, name, description): - """Prints out the contents of |name| if |dry_run|.""" - if not dry_run: - return - print - print 'Contents of %s (for %s)' % (name, description) - print '-' * 80 - with open(name) as f: - sys.stdout.write(f.read()) - print '-' * 80 - - -def MakeTargetImageName(common_prefix, output_directory, location): - """Generates the relative path name to be used in the file system image. - common_prefix: a prefix of both output_directory and location that - be removed. - output_directory: an optional prefix on location that will also be removed. - location: the file path to relativize. - - .so files will be stored into the lib subdirectory to be able to be found by - default by the loader. - - Examples: - - >>> MakeTargetImageName(common_prefix='/work/cr/src/', - ... output_directory='/work/cr/src/out/fuch', - ... location='/work/cr/src/base/test/data/xyz.json') - 'base/test/data/xyz.json' - - >>> MakeTargetImageName(common_prefix='/work/cr/src/', - ... output_directory='/work/cr/src/out/fuch', - ... location='/work/cr/src/out/fuch/icudtl.dat') - 'icudtl.dat' - - >>> MakeTargetImageName(common_prefix='/work/cr/src/', - ... output_directory='/work/cr/src/out/fuch', - ... location='/work/cr/src/out/fuch/libbase.so') - 'lib/libbase.so' - """ - assert output_directory.startswith(common_prefix) - output_dir_no_common_prefix = output_directory[len(common_prefix):] - assert location.startswith(common_prefix) - loc = location[len(common_prefix):] - if loc.startswith(output_dir_no_common_prefix): - loc = loc[len(output_dir_no_common_prefix)+1:] - # TODO(fuchsia): The requirements for finding/loading .so are in flux, so this - # ought to be reconsidered at some point. See https://crbug.com/732897. - if location.endswith('.so'): - loc = 'lib/' + loc - return loc - - -def AddToManifest(manifest_file, target_name, source, mapper): - """Appends |source| to the given |manifest_file| (a file object) in a format - suitable for consumption by mkbootfs. - - If |source| is a file it's directly added. If |source| is a directory, its - contents are recursively added. - - |source| must exist on disk at the time this function is called. - """ - if os.path.isdir(source): - files = [os.path.join(dp, f) for dp, dn, fn in os.walk(source) for f in fn] - for f in files: - # We pass None as the mapper because this should never recurse a 2nd time. - AddToManifest(manifest_file, mapper(f), f, None) - elif os.path.exists(source): - manifest_file.write('%s=%s\n' % (target_name, source)) - else: - raise Exception('%s does not exist' % source) - - -def BuildBootfs(output_directory, runtime_deps_path, test_name, child_args, - test_launcher_filter_file, device, dry_run): - with open(runtime_deps_path) as f: - lines = f.readlines() - - locations_to_add = [os.path.abspath(os.path.join(output_directory, x.strip())) - for x in lines] - locations_to_add.append( - os.path.abspath(os.path.join(output_directory, test_name))) - - common_prefix = os.path.commonprefix(locations_to_add) - target_source_pairs = zip( - [MakeTargetImageName(common_prefix, output_directory, loc) - for loc in locations_to_add], - locations_to_add) - - if test_launcher_filter_file: - test_launcher_filter_file = os.path.normpath( - os.path.join(output_directory, test_launcher_filter_file)) - filter_file_on_device = MakeTargetImageName( - common_prefix, output_directory, test_launcher_filter_file) - child_args.append('--test-launcher-filter-file=/system/' + - filter_file_on_device) - target_source_pairs.append( - [filter_file_on_device, test_launcher_filter_file]) - - # Generate a little script that runs the test binaries and then shuts down - # QEMU. - autorun_file = tempfile.NamedTemporaryFile() - autorun_file.write('#!/bin/sh\n') - autorun_file.write('/system/' + os.path.basename(test_name)) - - for arg in child_args: - autorun_file.write(' "%s"' % arg); - - autorun_file.write('\n') - if not device: - # If shutdown of QEMU happens too soon after the test completion, log - # statements from the end of the run will be lost, so sleep for a bit before - # shutting down. When running on device don't power off so the output and - # system can be inspected. - autorun_file.write('msleep 3000\n') - autorun_file.write('dm poweroff\n') - autorun_file.flush() - os.chmod(autorun_file.name, 0750) - DumpFile(dry_run, autorun_file.name, 'autorun') - target_source_pairs.append(('autorun', autorun_file.name)) - - manifest_file = tempfile.NamedTemporaryFile() - bootfs_name = runtime_deps_path + '.bootfs' - - for target, source in target_source_pairs: - AddToManifest(manifest_file.file, target, source, - lambda x: MakeTargetImageName( - common_prefix, output_directory, x)) - - mkbootfs_path = os.path.join(SDK_ROOT, 'tools', 'mkbootfs') - - manifest_file.flush() - DumpFile(dry_run, manifest_file.name, 'manifest') - RunAndCheck(dry_run, - [mkbootfs_path, '-o', bootfs_name, - '--target=boot', os.path.join(SDK_ROOT, 'bootdata.bin'), - '--target=system', manifest_file.name, - ]) - return bootfs_name - - -def SymbolizeEntry(entry): - addr2line_output = subprocess.check_output( - ['addr2line', '-Cipf', '--exe=' + entry[1], entry[2]]) - prefix = '#%s: ' % entry[0] - # addr2line outputs a second line for inlining information, offset - # that to align it properly after the frame index. - addr2line_filtered = addr2line_output.strip().replace( - '(inlined', ' ' * len(prefix) + '(inlined') - if '??' in addr2line_filtered: - addr2line_filtered = "%s+%s" % (os.path.basename(entry[1]), entry[2]) - return '%s%s' % (prefix, addr2line_filtered) - - -def ParallelSymbolizeBacktrace(backtrace): - # Disable handling of SIGINT during sub-process creation, to prevent - # sub-processes from consuming Ctrl-C signals, rather than the parent - # process doing so. - saved_sigint_handler = signal.signal(signal.SIGINT, signal.SIG_IGN) - p = multiprocessing.Pool(multiprocessing.cpu_count()) - - # Restore the signal handler for the parent process. - signal.signal(signal.SIGINT, saved_sigint_handler) - - symbolized = [] - try: - result = p.map_async(SymbolizeEntry, backtrace) - symbolized = result.get(SYMBOLIZATION_TIMEOUT_SECS) - if not symbolized: - return [] - except multiprocessing.TimeoutError: - return ['(timeout error occurred during symbolization)'] - except KeyboardInterrupt: # SIGINT - p.terminate() - - return symbolized +from runner_common import MakeTargetImageName, RunFuchsia, BuildBootfs, \ + ReadRuntimeDeps def main(): @@ -223,7 +27,7 @@ parser.add_argument('--runtime-deps-path', type=os.path.realpath, help='Runtime data dependency file from GN.') - parser.add_argument('--test-name', + parser.add_argument('--exe-name', type=os.path.realpath, help='Name of the the test') parser.add_argument('--gtest_filter', @@ -277,109 +81,27 @@ if args.child_args: child_args.extend(args.child_args) - bootfs = BuildBootfs(args.output_directory, args.runtime_deps_path, - args.test_name, child_args, - args.test_launcher_filter_file, args.device, - args.dry_run) + runtime_deps = ReadRuntimeDeps(args.runtime_deps_path, args.output_directory) - kernel_path = os.path.join(SDK_ROOT, 'kernel', 'magenta.bin') + if args.test_launcher_filter_file: + # Bundle the filter file in the runtime deps and compose the command-line + # flag which references it. + test_launcher_filter_file = os.path.normpath( + os.path.join(args.output_directory, args.test_launcher_filter_file)) + common_prefix = os.path.commonprefix(runtime_deps) + filter_device_path = MakeTargetImageName(common_prefix, + args.output_directory, + test_launcher_filter_file) + runtime_deps.append(args.test_launcher_filter_file) + child_args.append('--test-launcher-filter-file=/system/' + + filter_device_path) - if args.device: - # TODO(fuchsia): This doesn't capture stdout as there's no way to do so - # currently. See https://crbug.com/749242. - bootserver_path = os.path.join(SDK_ROOT, 'tools', 'bootserver') - bootserver_command = [bootserver_path, '-1', kernel_path, bootfs] - return RunAndCheck(args.dry_run, bootserver_command) + bootfs = BuildBootfs(args.output_directory, runtime_deps, args.exe_name, + child_args, args.device, args.dry_run) + if not bootfs: + return 2 - qemu_path = os.path.join(SDK_ROOT, 'qemu', 'bin', 'qemu-system-x86_64') - qemu_command = [qemu_path, - '-m', '2048', - '-nographic', - '-net', 'none', - '-smp', '4', - '-machine', 'q35', - '-kernel', kernel_path, - '-initrd', bootfs, - - # Use stdio for the guest OS only; don't attach the QEMU interactive - # monitor. - '-serial', 'stdio', - '-monitor', 'none', - - # TERM=dumb tells the guest OS to not emit ANSI commands that trigger - # noisy ANSI spew from the user's terminal emulator. - '-append', 'TERM=dumb kernel.halt_on_panic=true'] - - if int(os.environ.get('CHROME_HEADLESS', 0)) == 0: - qemu_command += ['-enable-kvm', '-cpu', 'host,migratable=no'] - else: - qemu_command += ['-cpu', 'Haswell,+smap,-check'] - - if args.dry_run: - print 'Run:', qemu_command - return 0 - - # Set up backtrace-parsing regexps. - prefix = r'^.*> ' - bt_end_re = re.compile(prefix + '(bt)?#(\d+):? end') - bt_with_offset_re = re.compile( - prefix + 'bt#(\d+): pc 0x[0-9a-f]+ sp (0x[0-9a-f]+) ' + - '\((\S+),(0x[0-9a-f]+)\)$') - in_process_re = re.compile(prefix + - '#(\d+) 0x[0-9a-f]+ \S+\+(0x[0-9a-f]+)$') - - # We pass a separate stdin stream to qemu. Sharing stdin across processes - # leads to flakiness due to the OS prematurely killing the stream and the - # Python script panicking and aborting. - # The precise root cause is still nebulous, but this fix works. - # See crbug.com/741194 . - qemu_popen = subprocess.Popen( - qemu_command, stdout=subprocess.PIPE, stdin=open(os.devnull)) - - # A buffer of backtrace entries awaiting symbolization, stored as tuples. - # Element #0: backtrace frame number (starting at 0). - # Element #1: path to executable code corresponding to the current frame. - # Element #2: memory offset within the executable. - bt_entries = [] - - success = False - while True: - line = qemu_popen.stdout.readline().strip() - if not line: - break - if 'SUCCESS: all tests passed.' in line: - success = True - - # Check for an end-of-backtrace marker. - if bt_end_re.match(line): - if bt_entries: - print '----- start symbolized stack' - for processed in ParallelSymbolizeBacktrace(bt_entries): - print processed - print '----- end symbolized stack' - bt_entries = [] - continue - - # Try to parse this as a Fuchsia system backtrace. - m = bt_with_offset_re.match(line) - if m: - bt_entries.append((m.group(1), args.test_name, m.group(4))) - continue - - # Try to parse the line as an in-process backtrace entry. - m = in_process_re.match(line) - if m: - bt_entries.append((m.group(1), args.test_name, m.group(2))) - continue - - # Some other line, so print it. Back-traces should not be interleaved with - # other output, so while this may re-order lines we see, it should actually - # make things more readable. - print line - - qemu_popen.wait() - - return 0 if success else 1 + return RunFuchsia(bootfs, args.exe_name, args.device, args.dry_run) if __name__ == '__main__':
diff --git a/cc/blink/web_layer_impl.cc b/cc/blink/web_layer_impl.cc index c726fe6..fe1a88eb 100644 --- a/cc/blink/web_layer_impl.cc +++ b/cc/blink/web_layer_impl.cc
@@ -405,10 +405,10 @@ constraint.scroll_container_relative_sticky_box_rect; web_constraint.scroll_container_relative_containing_block_rect = constraint.scroll_container_relative_containing_block_rect; - web_constraint.nearest_layer_shifting_sticky_box = - constraint.nearest_layer_shifting_sticky_box; - web_constraint.nearest_layer_shifting_containing_block = - constraint.nearest_layer_shifting_containing_block; + web_constraint.nearest_element_shifting_sticky_box = + constraint.nearest_element_shifting_sticky_box; + web_constraint.nearest_element_shifting_containing_block = + constraint.nearest_element_shifting_containing_block; return web_constraint; } static cc::LayerStickyPositionConstraint ToStickyPositionConstraint( @@ -427,10 +427,10 @@ web_constraint.scroll_container_relative_sticky_box_rect; constraint.scroll_container_relative_containing_block_rect = web_constraint.scroll_container_relative_containing_block_rect; - constraint.nearest_layer_shifting_sticky_box = - web_constraint.nearest_layer_shifting_sticky_box; - constraint.nearest_layer_shifting_containing_block = - web_constraint.nearest_layer_shifting_containing_block; + constraint.nearest_element_shifting_sticky_box = + web_constraint.nearest_element_shifting_sticky_box; + constraint.nearest_element_shifting_containing_block = + web_constraint.nearest_element_shifting_containing_block; return constraint; } void WebLayerImpl::SetStickyPositionConstraint(
diff --git a/cc/layers/layer_sticky_position_constraint.cc b/cc/layers/layer_sticky_position_constraint.cc index 1f80e137..641f5986 100644 --- a/cc/layers/layer_sticky_position_constraint.cc +++ b/cc/layers/layer_sticky_position_constraint.cc
@@ -18,8 +18,8 @@ right_offset(0.f), top_offset(0.f), bottom_offset(0.f), - nearest_layer_shifting_sticky_box(Layer::INVALID_ID), - nearest_layer_shifting_containing_block(Layer::INVALID_ID) {} + nearest_element_shifting_sticky_box(kInvalidElementId), + nearest_element_shifting_containing_block(kInvalidElementId) {} LayerStickyPositionConstraint::LayerStickyPositionConstraint( const LayerStickyPositionConstraint& other) @@ -36,10 +36,10 @@ other.scroll_container_relative_sticky_box_rect), scroll_container_relative_containing_block_rect( other.scroll_container_relative_containing_block_rect), - nearest_layer_shifting_sticky_box( - other.nearest_layer_shifting_sticky_box), - nearest_layer_shifting_containing_block( - other.nearest_layer_shifting_containing_block) {} + nearest_element_shifting_sticky_box( + other.nearest_element_shifting_sticky_box), + nearest_element_shifting_containing_block( + other.nearest_element_shifting_containing_block) {} bool LayerStickyPositionConstraint::operator==( const LayerStickyPositionConstraint& other) const { @@ -57,10 +57,10 @@ other.scroll_container_relative_sticky_box_rect && scroll_container_relative_containing_block_rect == other.scroll_container_relative_containing_block_rect && - nearest_layer_shifting_sticky_box == - other.nearest_layer_shifting_sticky_box && - nearest_layer_shifting_containing_block == - other.nearest_layer_shifting_containing_block; + nearest_element_shifting_sticky_box == + other.nearest_element_shifting_sticky_box && + nearest_element_shifting_containing_block == + other.nearest_element_shifting_containing_block; } bool LayerStickyPositionConstraint::operator!=( @@ -68,10 +68,10 @@ return !(*this == other); } -int LayerStickyPositionConstraint::NearestStickyAncestor() { - return (nearest_layer_shifting_sticky_box != Layer::INVALID_ID) - ? nearest_layer_shifting_sticky_box - : nearest_layer_shifting_containing_block; +ElementId LayerStickyPositionConstraint::NearestStickyAncestor() { + return nearest_element_shifting_sticky_box + ? nearest_element_shifting_sticky_box + : nearest_element_shifting_containing_block; } } // namespace cc
diff --git a/cc/layers/layer_sticky_position_constraint.h b/cc/layers/layer_sticky_position_constraint.h index 782fa942..736355e0 100644 --- a/cc/layers/layer_sticky_position_constraint.h +++ b/cc/layers/layer_sticky_position_constraint.h
@@ -7,6 +7,7 @@ #include "cc/cc_export.h" +#include "cc/trees/element_id.h" #include "ui/gfx/geometry/point.h" #include "ui/gfx/geometry/rect.h" @@ -40,15 +41,14 @@ // block boundary. gfx::Rect scroll_container_relative_containing_block_rect; - // The nearest ancestor sticky layer ids that affect the sticky box constraint - // rect and the containing block constraint rect respectively. If no such - // layer exists, these are set to Layer::INVALID_ID. - int nearest_layer_shifting_sticky_box; - int nearest_layer_shifting_containing_block; + // The nearest ancestor sticky element ids that affect the sticky box + // constraint rect and the containing block constraint rect respectively. + ElementId nearest_element_shifting_sticky_box; + ElementId nearest_element_shifting_containing_block; - // Returns the nearest sticky ancestor layer, or Layer::INVALID_ID if no such - // layer exists. - int NearestStickyAncestor(); + // Returns the nearest sticky ancestor element id or the default element id if + // none exists. + ElementId NearestStickyAncestor(); bool operator==(const LayerStickyPositionConstraint&) const; bool operator!=(const LayerStickyPositionConstraint&) const;
diff --git a/cc/trees/layer_tree_host_common_unittest.cc b/cc/trees/layer_tree_host_common_unittest.cc index 79f77ad..2af1ab53 100644 --- a/cc/trees/layer_tree_host_common_unittest.cc +++ b/cc/trees/layer_tree_host_common_unittest.cc
@@ -7110,6 +7110,7 @@ outer_sticky->AddChild(inner_sticky); host()->SetRootLayer(root); scroller->SetElementId(LayerIdToElementIdForTesting(scroller->id())); + outer_sticky->SetElementId(LayerIdToElementIdForTesting(outer_sticky->id())); root->SetBounds(gfx::Size(100, 100)); container->SetBounds(gfx::Size(100, 100)); @@ -7138,7 +7139,8 @@ gfx::Rect(0, 50, 10, 10); inner_sticky_pos.scroll_container_relative_containing_block_rect = gfx::Rect(0, 50, 10, 50); - inner_sticky_pos.nearest_layer_shifting_containing_block = outer_sticky->id(); + inner_sticky_pos.nearest_element_shifting_containing_block = + outer_sticky->element_id(); inner_sticky->SetStickyPositionConstraint(inner_sticky_pos); ExecuteCalculateDrawProperties(root.get());
diff --git a/cc/trees/property_tree_builder.cc b/cc/trees/property_tree_builder.cc index 359bb1d..ac367b9 100644 --- a/cc/trees/property_tree_builder.cc +++ b/cc/trees/property_tree_builder.cc
@@ -284,14 +284,6 @@ layer->SetClipTreeIndex(data_for_children->clip_tree_parent); } -static Layer* LayerById(Layer* layer, int id) { - return layer->layer_tree_host()->LayerById(id); -} - -static LayerImpl* LayerById(LayerImpl* layer, int id) { - return layer->layer_tree_impl()->LayerById(id); -} - template <typename LayerType> static inline bool IsAtBoundaryOf3dRenderingContext(LayerType* layer) { return Parent(layer) @@ -530,26 +522,24 @@ .AddNodeAffectedByOuterViewportBoundsDelta(node->id); } } - // Copy the ancestor nodes for later use. These layers are guaranteed to + // Copy the ancestor nodes for later use. These elements are guaranteed to // have transform nodes at this point because they are our ancestors (so // have already been processed) and are sticky (so have transform nodes). - int shifting_sticky_box_layer_id = - sticky_data->constraints.nearest_layer_shifting_sticky_box; - if (shifting_sticky_box_layer_id != Layer::INVALID_ID) { + ElementId shifting_sticky_box_element_id = + sticky_data->constraints.nearest_element_shifting_sticky_box; + if (shifting_sticky_box_element_id) { sticky_data->nearest_node_shifting_sticky_box = - LayerById(layer, shifting_sticky_box_layer_id) - ->transform_tree_index(); - DCHECK(sticky_data->nearest_node_shifting_sticky_box != - TransformTree::kInvalidNodeId); + data_for_children->property_trees->transform_tree + .FindNodeFromElementId(shifting_sticky_box_element_id) + ->id; } - int shifting_containing_block_layer_id = - sticky_data->constraints.nearest_layer_shifting_containing_block; - if (shifting_containing_block_layer_id != Layer::INVALID_ID) { + ElementId shifting_containing_block_element_id = + sticky_data->constraints.nearest_element_shifting_containing_block; + if (shifting_containing_block_element_id) { sticky_data->nearest_node_shifting_containing_block = - LayerById(layer, shifting_containing_block_layer_id) - ->transform_tree_index(); - DCHECK(sticky_data->nearest_node_shifting_containing_block != - TransformTree::kInvalidNodeId); + data_for_children->property_trees->transform_tree + .FindNodeFromElementId(shifting_containing_block_element_id) + ->id; } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanel.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanel.java index 5f38661b..94c8e73 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanel.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanel.java
@@ -568,27 +568,25 @@ /** * Handles the click gesture. * - * @param time The timestamp of the gesture. * @param x The x coordinate of the gesture. * @param y The y coordinate of the gesture. */ - public void handleClick(long time, float x, float y) { + public void handleClick(float x, float y) { mHasDetectedTouchGesture = true; if (isCoordinateInsideBasePage(x, y)) { closePanel(StateChangeReason.BASE_PAGE_TAP, true); } else if (isCoordinateInsideBar(x, y) && !onInterceptBarClick()) { - handleBarClick(time, x, y); + handleBarClick(x, y); } } /** * Handles the click gesture specifically on the bar. * - * @param time The timestamp of the gesture. * @param x The x coordinate of the gesture. * @param y The y coordinate of the gesture. */ - protected void handleBarClick(long time, float x, float y) { + protected void handleBarClick(float x, float y) { if (isPeeking()) { expandPanel(StateChangeReason.SEARCH_BAR_TAP); } @@ -700,8 +698,7 @@ @Override public void click(float x, float y, boolean fromMouse, int buttons) { - // TODO(mdjones): The time param for handleClick is not used anywhere, remove it. - handleClick(0, x, y); + handleClick(x, y); } @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanel.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanel.java index ca02f02..bc4b592 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanel.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanel.java
@@ -282,7 +282,7 @@ * Handles a bar click. The position is given in dp. */ @Override - public void handleBarClick(long time, float x, float y) { + public void handleBarClick(float x, float y) { getSearchBarControl().onSearchBarClick(x); if (isPeeking()) { @@ -293,7 +293,7 @@ mActivity.getActivityTab()); } else { // super takes care of expanding the Panel when peeking. - super.handleBarClick(time, x, y); + super.handleBarClick(x, y); } } else if (isExpanded() || isMaximized()) { if (isCoordinateInsideCloseButton(x)) { @@ -895,6 +895,6 @@ float yPosition = getOffsetY() + (getHeight() / 2); // Simulate the tap. - handleClick(System.currentTimeMillis(), xPosition, yPosition); + handleClick(xPosition, yPosition); } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/eventfilter/OverlayPanelEventFilter.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/eventfilter/OverlayPanelEventFilter.java index 2fab8f4..4bdeac5f 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/eventfilter/OverlayPanelEventFilter.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/eventfilter/OverlayPanelEventFilter.java
@@ -121,8 +121,7 @@ @Override public boolean onSingleTapUp(MotionEvent event) { - mPanel.handleClick(event.getEventTime(), event.getX() * mPxToDp, - event.getY() * mPxToDp); + mPanel.handleClick(event.getX() * mPxToDp, event.getY() * mPxToDp); return true; } }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManagerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManagerTest.java index b701801..005a8e32 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManagerTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManagerTest.java
@@ -1114,7 +1114,7 @@ @Override public void run() { // TODO(donnd): provide better time and x,y data to make this more broadly useful. - mPanel.handleBarClick(0, 0, 0); + mPanel.handleBarClick(0, 0); } }); }
diff --git a/chrome/app/settings_strings.grdp b/chrome/app/settings_strings.grdp index 9ab005c..509d1d97 100644 --- a/chrome/app/settings_strings.grdp +++ b/chrome/app/settings_strings.grdp
@@ -1896,16 +1896,14 @@ </message> <!-- Search Page --> + <message name="IDS_SETTINGS_SEARCH" desc="Name of the settings page which displays search engine preferences."> + Search engine + </message> <if expr="chromeos"> - <message name="IDS_SETTINGS_SEARCH" desc="Name of the settings page which displays search engine and assistant preferences on Chrome OS."> + <message name="IDS_SETTINGS_SEARCH_AND_ASSISTANT" desc="Name of the settings page which displays search engine and assistant preferences on Chrome OS."> Search engine and Google Assistant </message> </if> - <if expr="not chromeos"> - <message name="IDS_SETTINGS_SEARCH" desc="Name of the settings page which displays search engine preferences."> - Search engine - </message> - </if> <message name="IDS_SETTINGS_SEARCH_EXPLANATION" desc="Explanation for the search engine dropdown setting."> Search engine used in the <ph name="BEGIN_LINK"><a target="_blank" href="$1"></ph>address bar<ph name="END_LINK"></a></ph> </message>
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index 8239e60..889fe37 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -3354,6 +3354,8 @@ "obsolete_system/obsolete_system_linux.cc", "obsolete_system/obsolete_system_mac.cc", "obsolete_system/obsolete_system_win.cc", + "page_load_metrics/observers/session_restore_page_load_metrics_observer.cc", + "page_load_metrics/observers/session_restore_page_load_metrics_observer.h", "pdf/pdf_extension_util.cc", "pdf/pdf_extension_util.h", "policy/local_sync_policy_handler.cc",
diff --git a/chrome/browser/browser_resources.grd b/chrome/browser/browser_resources.grd index fc35719..5bd6cdb7 100644 --- a/chrome/browser/browser_resources.grd +++ b/chrome/browser/browser_resources.grd
@@ -677,7 +677,7 @@ <include name="IDR_WELCOME_WIN10_PIN_LARGE_WEBP" file="resources\welcome\win10\pin-large.webp" type="BINDATA" /> <include name="IDR_WELCOME_WIN10_PIN_SMALL_WEBP" file="resources\welcome\win10\pin-small.webp" type="BINDATA" /> </if> - <if expr="not is_android and not is_ios"> + <if expr="not is_ios"> <include name="IDR_SSL_ERROR_ASSISTANT_PB" file="${root_gen_dir}/chrome/browser/resources/ssl/ssl_error_assistant/ssl_error_assistant.pb" use_base_dir="false" type="BINDATA" /> </if> <if expr="is_android or is_linux">
diff --git a/chrome/browser/extensions/activity_log/activity_log_unittest.cc b/chrome/browser/extensions/activity_log/activity_log_unittest.cc index a853633..1e27917f 100644 --- a/chrome/browser/extensions/activity_log/activity_log_unittest.cc +++ b/chrome/browser/extensions/activity_log/activity_log_unittest.cc
@@ -21,6 +21,7 @@ #include "chrome/browser/prerender/prerender_handle.h" #include "chrome/browser/prerender/prerender_manager.h" #include "chrome/browser/prerender/prerender_manager_factory.h" +#include "chrome/browser/prerender/prerender_test_utils.h" #include "chrome/common/chrome_constants.h" #include "chrome/common/chrome_switches.h" #include "chrome/test/base/chrome_render_view_host_test_harness.h" @@ -242,6 +243,9 @@ ASSERT_TRUE(GetDatabaseEnabled()); GURL url("http://www.google.com"); + prerender::test_utils::RestorePrerenderMode restore_prerender_mode; + prerender::PrerenderManager::SetOmniboxMode( + prerender::PrerenderManager::PRERENDER_MODE_ENABLED); prerender::PrerenderManager* prerender_manager = prerender::PrerenderManagerFactory::GetForBrowserContext(profile());
diff --git a/chrome/browser/file_select_helper_unittest.cc b/chrome/browser/file_select_helper_unittest.cc index 67cc39c2..93443945 100644 --- a/chrome/browser/file_select_helper_unittest.cc +++ b/chrome/browser/file_select_helper_unittest.cc
@@ -96,10 +96,10 @@ EXPECT_EQ(base::FilePath(FILE_PATH_LITERAL("ascii.txt")), FileSelectHelper::GetSanitizedFileName( base::FilePath(FILE_PATH_LITERAL("ascii.txt")))); - EXPECT_EQ(base::FilePath(FILE_PATH_LITERAL("trailing-spaces-")), + EXPECT_EQ(base::FilePath(FILE_PATH_LITERAL("trailing-spaces_")), FileSelectHelper::GetSanitizedFileName( base::FilePath(FILE_PATH_LITERAL("trailing-spaces ")))); - EXPECT_EQ(base::FilePath(FILE_PATH_LITERAL("path-components-in-name")), + EXPECT_EQ(base::FilePath(FILE_PATH_LITERAL("path_components_in_name")), FileSelectHelper::GetSanitizedFileName( base::FilePath(FILE_PATH_LITERAL("path/components/in/name"))));
diff --git a/chrome/browser/offline_pages/prerender_adapter_unittest.cc b/chrome/browser/offline_pages/prerender_adapter_unittest.cc index 3fa1076..239c78b 100644 --- a/chrome/browser/offline_pages/prerender_adapter_unittest.cc +++ b/chrome/browser/offline_pages/prerender_adapter_unittest.cc
@@ -6,6 +6,7 @@ #include "base/sys_info.h" #include "chrome/browser/prerender/prerender_manager_factory.h" +#include "chrome/browser/prerender/prerender_test_utils.h" #include "chrome/test/base/testing_profile.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/web_contents.h" @@ -116,6 +117,7 @@ void OnPrerenderNetworkBytesChanged(int64_t bytes) override; void SetUp() override; + void TearDown() override; // Returns the PrerenderLoader to test. PrerenderAdapter* adapter() const { return adapter_.get(); } @@ -136,6 +138,8 @@ } private: + using RestorePrerenderMode = prerender::test_utils::RestorePrerenderMode; + content::TestBrowserThreadBundle thread_bundle_; TestingProfile profile_; std::unique_ptr<PrerenderAdapter> adapter_; @@ -145,6 +149,7 @@ bool observer_dom_content_loaded_called_; bool observer_stop_called_; int64_t observer_network_bytes_changed_; + std::unique_ptr<RestorePrerenderMode> restore_prerender_mode_; DISALLOW_COPY_AND_ASSIGN(PrerenderAdapterTest); }; @@ -181,13 +186,18 @@ void PrerenderAdapterTest::SetUp() { if (base::SysInfo::IsLowEndDevice()) return; + + // Prerender mode is stored in a few static variables. Remember the default + // mode to restore it later in TearDown() to avoid affecting other tests. + restore_prerender_mode_ = base::MakeUnique<RestorePrerenderMode>(); + PrerenderManager::SetMode(PrerenderManager::PRERENDER_MODE_ENABLED); + adapter_.reset(new PrerenderAdapter(this)); prerender_contents_factory_ = new StubPrerenderContentsFactory(); prerender_manager_ = PrerenderManagerFactory::GetForBrowserContext(profile()); if (prerender_manager_) { prerender_manager_->SetPrerenderContentsFactoryForTest( prerender_contents_factory_); - prerender_manager_->SetMode(PrerenderManager::PRERENDER_MODE_ENABLED); } observer_stop_loading_called_ = false; observer_dom_content_loaded_called_ = false; @@ -195,6 +205,10 @@ ASSERT_TRUE(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); } +void PrerenderAdapterTest::TearDown() { + restore_prerender_mode_.reset(); +} + TEST_F(PrerenderAdapterTest, StartPrerenderFailsForUnsupportedScheme) { // Skip test on low end device until supported. if (base::SysInfo::IsLowEndDevice())
diff --git a/chrome/browser/page_load_metrics/observers/session_restore_page_load_metrics_observer.cc b/chrome/browser/page_load_metrics/observers/session_restore_page_load_metrics_observer.cc new file mode 100644 index 0000000..c285d6c0 --- /dev/null +++ b/chrome/browser/page_load_metrics/observers/session_restore_page_load_metrics_observer.cc
@@ -0,0 +1,79 @@ +// 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 "chrome/browser/page_load_metrics/observers/session_restore_page_load_metrics_observer.h" + +#include "base/logging.h" +#include "chrome/browser/browser_process.h" +#include "chrome/browser/page_load_metrics/page_load_metrics_util.h" +#include "chrome/browser/resource_coordinator/tab_manager.h" +#include "chrome/common/page_load_metrics/page_load_metrics.mojom.h" +#include "content/public/browser/navigation_handle.h" +#include "content/public/browser/web_contents.h" + +namespace internal { + +const char kHistogramSessionRestoreForegroundTabFirstPaint[] = + "TabManager.Experimental.SessionRestore.ForegroundTab.FirstPaint"; +const char kHistogramSessionRestoreForegroundTabFirstContentfulPaint[] = + "TabManager.Experimental.SessionRestore.ForegroundTab.FirstContentfulPaint"; +const char kHistogramSessionRestoreForegroundTabFirstMeaningfulPaint[] = + "TabManager.Experimental.SessionRestore.ForegroundTab.FirstMeaningfulPaint"; + +} // namespace internal + +SessionRestorePageLoadMetricsObserver::SessionRestorePageLoadMetricsObserver() { +} + +page_load_metrics::PageLoadMetricsObserver::ObservePolicy +SessionRestorePageLoadMetricsObserver::OnStart( + content::NavigationHandle* navigation_handle, + const GURL& currently_committed_url, + bool started_in_foreground) { + content::WebContents* contents = navigation_handle->GetWebContents(); + resource_coordinator::TabManager* tab_manager = + g_browser_process->GetTabManager(); + // Should not be null because this is used only on supported platforms. + DCHECK(tab_manager); + + return (started_in_foreground && + tab_manager->IsTabInSessionRestore(contents) && + tab_manager->IsTabRestoredInForeground(contents)) + ? CONTINUE_OBSERVING + : STOP_OBSERVING; +} + +void SessionRestorePageLoadMetricsObserver::OnFirstPaintInPage( + const page_load_metrics::mojom::PageLoadTiming& timing, + const page_load_metrics::PageLoadExtraInfo& extra_info) { + if (page_load_metrics::WasStartedInForegroundOptionalEventInForeground( + timing.paint_timing->first_paint.value(), extra_info)) { + PAGE_LOAD_HISTOGRAM( + internal::kHistogramSessionRestoreForegroundTabFirstPaint, + timing.paint_timing->first_paint.value()); + } +} + +void SessionRestorePageLoadMetricsObserver::OnFirstContentfulPaintInPage( + const page_load_metrics::mojom::PageLoadTiming& timing, + const page_load_metrics::PageLoadExtraInfo& extra_info) { + if (page_load_metrics::WasStartedInForegroundOptionalEventInForeground( + timing.paint_timing->first_contentful_paint.value(), extra_info)) { + PAGE_LOAD_HISTOGRAM( + internal::kHistogramSessionRestoreForegroundTabFirstContentfulPaint, + timing.paint_timing->first_contentful_paint.value()); + } +} + +void SessionRestorePageLoadMetricsObserver:: + OnFirstMeaningfulPaintInMainFrameDocument( + const page_load_metrics::mojom::PageLoadTiming& timing, + const page_load_metrics::PageLoadExtraInfo& extra_info) { + if (page_load_metrics::WasStartedInForegroundOptionalEventInForeground( + timing.paint_timing->first_meaningful_paint.value(), extra_info)) { + PAGE_LOAD_HISTOGRAM( + internal::kHistogramSessionRestoreForegroundTabFirstMeaningfulPaint, + timing.paint_timing->first_meaningful_paint.value()); + } +}
diff --git a/chrome/browser/page_load_metrics/observers/session_restore_page_load_metrics_observer.h b/chrome/browser/page_load_metrics/observers/session_restore_page_load_metrics_observer.h new file mode 100644 index 0000000..f8c50118 --- /dev/null +++ b/chrome/browser/page_load_metrics/observers/session_restore_page_load_metrics_observer.h
@@ -0,0 +1,45 @@ +// 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 CHROME_BROWSER_PAGE_LOAD_METRICS_OBSERVERS_SESSION_RESTORE_PAGE_LOAD_METRICS_OBSERVER_H_ +#define CHROME_BROWSER_PAGE_LOAD_METRICS_OBSERVERS_SESSION_RESTORE_PAGE_LOAD_METRICS_OBSERVER_H_ + +#include "base/macros.h" +#include "chrome/browser/page_load_metrics/page_load_metrics_observer.h" + +namespace internal { + +extern const char kHistogramSessionRestoreForegroundTabFirstPaint[]; +extern const char kHistogramSessionRestoreForegroundTabFirstContentfulPaint[]; +extern const char kHistogramSessionRestoreForegroundTabFirstMeaningfulPaint[]; + +} // namespace internal + +// Record page load metrics of foreground tabs during session restore. This +// observer observes foreground tabs created by session restores only. It will +// stop observing if the tab gets hidden, reloaded, or navigated away. +class SessionRestorePageLoadMetricsObserver + : public page_load_metrics::PageLoadMetricsObserver { + public: + SessionRestorePageLoadMetricsObserver(); + + // page_load_metrics::PageLoadMetricsObserver: + ObservePolicy OnStart(content::NavigationHandle* navigation_handle, + const GURL& currently_committed_url, + bool started_in_foreground) override; + void OnFirstPaintInPage( + const page_load_metrics::mojom::PageLoadTiming& timing, + const page_load_metrics::PageLoadExtraInfo& extra_info) override; + void OnFirstContentfulPaintInPage( + const page_load_metrics::mojom::PageLoadTiming& timing, + const page_load_metrics::PageLoadExtraInfo& extra_info) override; + void OnFirstMeaningfulPaintInMainFrameDocument( + const page_load_metrics::mojom::PageLoadTiming& timing, + const page_load_metrics::PageLoadExtraInfo& extra_info) override; + + private: + DISALLOW_COPY_AND_ASSIGN(SessionRestorePageLoadMetricsObserver); +}; + +#endif // CHROME_BROWSER_PAGE_LOAD_METRICS_OBSERVERS_SESSION_RESTORE_PAGE_LOAD_METRICS_OBSERVER_H_
diff --git a/chrome/browser/page_load_metrics/observers/session_restore_page_load_metrics_observer_unittest.cc b/chrome/browser/page_load_metrics/observers/session_restore_page_load_metrics_observer_unittest.cc new file mode 100644 index 0000000..724832d4 --- /dev/null +++ b/chrome/browser/page_load_metrics/observers/session_restore_page_load_metrics_observer_unittest.cc
@@ -0,0 +1,263 @@ +// 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 "chrome/browser/page_load_metrics/observers/session_restore_page_load_metrics_observer.h" + +#include <memory> +#include <unordered_map> +#include <utility> +#include <vector> + +#include "base/bind.h" +#include "base/bind_helpers.h" +#include "base/macros.h" +#include "base/stl_util.h" +#include "base/test/histogram_tester.h" +#include "base/time/time.h" +#include "chrome/browser/browser_process.h" +#include "chrome/browser/page_load_metrics/observers/page_load_metrics_observer_tester.h" +#include "chrome/browser/page_load_metrics/page_load_tracker.h" +#include "chrome/browser/resource_coordinator/tab_manager.h" +#include "chrome/browser/sessions/session_restore.h" +#include "chrome/browser/sessions/tab_loader.h" +#include "chrome/common/page_load_metrics/test/page_load_metrics_test_util.h" +#include "chrome/test/base/chrome_render_view_host_test_harness.h" +#include "chrome/test/base/testing_profile.h" +#include "content/public/browser/browser_url_handler.h" +#include "content/public/browser/navigation_controller.h" +#include "content/public/browser/web_contents.h" +#include "content/public/test/navigation_simulator.h" +#include "content/public/test/web_contents_tester.h" +#include "ui/base/page_transition_types.h" +#include "url/gurl.h" + +using RestoredTab = SessionRestoreDelegate::RestoredTab; +using WebContents = content::WebContents; + +class SessionRestorePageLoadMetricsObserverTest + : public ChromeRenderViewHostTestHarness { + public: + static void RegisterObservers(page_load_metrics::PageLoadTracker* tracker) { + tracker->AddObserver( + base::MakeUnique<SessionRestorePageLoadMetricsObserver>()); + } + + protected: + SessionRestorePageLoadMetricsObserverTest() {} + + void SetUp() override { + ChromeRenderViewHostTestHarness::SetUp(); + + // Add a default web contents. + AddForegroundTabWithTester(); + + // Create the tab manager to register its SessionRestoreObserver before + // session restore starts. + g_browser_process->GetTabManager(); + + PopulateFirstPaintTimings(); + } + + void TearDown() override { + // Must be delete tabs before calling TearDown() which cleans up all the + // testing environment. + tabs_.clear(); + ChromeRenderViewHostTestHarness::TearDown(); + } + + // Populate first paint and first [contentful,meaningful] paint timings. + void PopulateFirstPaintTimings() { + page_load_metrics::InitPageLoadTimingForTest(&timing_); + timing_.navigation_start = base::Time::FromDoubleT(1); + // Should be large enough (e.g., >20 ms) for some tests to be able to hide + // foreground tabs before the first pains. + timing_.paint_timing->first_meaningful_paint = + base::TimeDelta::FromSeconds(1); + PopulateRequiredTimingFields(&timing_); + } + + WebContents* AddForegroundTabWithTester() { + tabs_.emplace_back(CreateTestWebContents()); + WebContents* contents = tabs_.back().get(); + auto tester = + base::MakeUnique<page_load_metrics::PageLoadMetricsObserverTester>( + contents, + base::BindRepeating( + &SessionRestorePageLoadMetricsObserverTest::RegisterObservers)); + testers_[contents] = std::move(tester); + restored_tabs_.emplace_back(contents, false /* is_active */, + false /* is_app */, false /* is_pinned */); + NavigateAndCommit(contents, GetTestURL()); + contents->WasShown(); + StopLoading(contents); + return contents; + } + + // Return the default tab. + WebContents* web_contents() { return tabs_.front().get(); } + + std::vector<std::unique_ptr<WebContents>>& tabs() { return tabs_; } + + void ExpectFirstPaintMetricsTotalCount(int expected_total_count) const { + histogram_tester_.ExpectTotalCount( + internal::kHistogramSessionRestoreForegroundTabFirstPaint, + expected_total_count); + histogram_tester_.ExpectTotalCount( + internal::kHistogramSessionRestoreForegroundTabFirstContentfulPaint, + expected_total_count); + histogram_tester_.ExpectTotalCount( + internal::kHistogramSessionRestoreForegroundTabFirstMeaningfulPaint, + expected_total_count); + } + + void RestoreTabs() { + TabLoader::RestoreTabs(restored_tabs_, base::TimeTicks()); + } + + void SimulateTimingUpdateForTab(WebContents* contents) { + ASSERT_TRUE(base::ContainsKey(testers_, contents)); + testers_[contents]->SimulateTimingUpdate(timing_); + } + + void StopLoading(WebContents* contents) const { + contents->Stop(); + content::WebContentsTester::For(contents)->TestSetIsLoading(false); + } + + void NavigateAndCommit(WebContents* contents, const GURL& url) const { + content::NavigationSimulator::NavigateAndCommitFromDocument( + GetTestURL(), contents->GetMainFrame()); + } + + GURL GetTestURL() const { return GURL("https://google.com"); } + + const page_load_metrics::mojom::PageLoadTiming& timing() const { + return timing_; + } + + std::vector<RestoredTab>& restored_tabs() { return restored_tabs_; } + + private: + base::HistogramTester histogram_tester_; + + page_load_metrics::mojom::PageLoadTiming timing_; + std::vector<RestoredTab> restored_tabs_; + std::vector<std::unique_ptr<WebContents>> tabs_; + std::unordered_map< + WebContents*, + std::unique_ptr<page_load_metrics::PageLoadMetricsObserverTester>> + testers_; + + DISALLOW_COPY_AND_ASSIGN(SessionRestorePageLoadMetricsObserverTest); +}; + +TEST_F(SessionRestorePageLoadMetricsObserverTest, NoMetrics) { + ExpectFirstPaintMetricsTotalCount(0); +} + +TEST_F(SessionRestorePageLoadMetricsObserverTest, + FirstPaintsOutOfSessionRestore) { + NavigateAndCommit(web_contents(), GetTestURL()); + ASSERT_NO_FATAL_FAILURE(SimulateTimingUpdateForTab(web_contents())); + ExpectFirstPaintMetricsTotalCount(0); +} + +TEST_F(SessionRestorePageLoadMetricsObserverTest, RestoreSingleForegroundTab) { + // Restore one tab which finishes loading in foreground. + SessionRestore::OnWillRestoreTab(web_contents()); + RestoreTabs(); + NavigateAndCommit(web_contents(), GetTestURL()); + ASSERT_NO_FATAL_FAILURE(SimulateTimingUpdateForTab(web_contents())); + ExpectFirstPaintMetricsTotalCount(1); +} + +TEST_F(SessionRestorePageLoadMetricsObserverTest, + RestoreMultipleForegroundTabs) { + WebContents* second_contents = AddForegroundTabWithTester(); + // Restore each tab separately. + std::vector<std::vector<RestoredTab>> restored_tabs_list{ + std::vector<RestoredTab>{ + RestoredTab(web_contents(), false, false, false)}, + std::vector<RestoredTab>{ + RestoredTab(second_contents, false, false, false)}}; + + for (size_t i = 0; i < tabs().size(); ++i) { + WebContents* contents = tabs()[i].get(); + SessionRestore::OnWillRestoreTab(contents); + TabLoader::RestoreTabs(restored_tabs_list[i], base::TimeTicks()); + NavigateAndCommit(contents, GetTestURL()); + ASSERT_NO_FATAL_FAILURE(SimulateTimingUpdateForTab(contents)); + ExpectFirstPaintMetricsTotalCount(i + 1); + } +} + +TEST_F(SessionRestorePageLoadMetricsObserverTest, RestoreBackgroundTab) { + // Set the tab to background before the PageLoadMetricsObserver was created. + web_contents()->WasHidden(); + + // Load the restored tab in background. + SessionRestore::OnWillRestoreTab(web_contents()); + RestoreTabs(); + NavigateAndCommit(web_contents(), GetTestURL()); + ASSERT_NO_FATAL_FAILURE(SimulateTimingUpdateForTab(web_contents())); + + // No paint timings recorded for tabs restored in background. + ExpectFirstPaintMetricsTotalCount(0); +} + +TEST_F(SessionRestorePageLoadMetricsObserverTest, HideTabBeforeFirstPaints) { + // Start loading the tab. + SessionRestore::OnWillRestoreTab(web_contents()); + RestoreTabs(); + NavigateAndCommit(web_contents(), GetTestURL()); + + // Hide the tab before any paints. + web_contents()->WasHidden(); + ASSERT_NO_FATAL_FAILURE(SimulateTimingUpdateForTab(web_contents())); + + // No paint timings recorded because tab was hidden before the first paints. + ExpectFirstPaintMetricsTotalCount(0); +} + +TEST_F(SessionRestorePageLoadMetricsObserverTest, + SwitchInitialRestoredForegroundTab) { + // Create 2 tabs: tab 0 is foreground, tab 1 is background. + AddForegroundTabWithTester(); + restored_tabs()[0].contents()->WasShown(); + restored_tabs()[1].contents()->WasHidden(); + + // Restore both tabs. + for (size_t i = 0; i < tabs().size(); ++i) + SessionRestore::OnWillRestoreTab(tabs()[i].get()); + TabLoader::RestoreTabs(restored_tabs(), base::TimeTicks()); + + for (size_t i = 0; i < tabs().size(); ++i) + NavigateAndCommit(tabs()[i].get(), GetTestURL()); + + // Switch to tab 1 before any paint events occur. + restored_tabs()[0].contents()->WasHidden(); + restored_tabs()[1].contents()->WasShown(); + ASSERT_NO_FATAL_FAILURE(SimulateTimingUpdateForTab(web_contents())); + + // No paint timings recorded because the initial foreground tab was hidden. + ExpectFirstPaintMetricsTotalCount(0); +} + +TEST_F(SessionRestorePageLoadMetricsObserverTest, MultipleSessionRestores) { + size_t number_of_session_restores = 3; + for (size_t i = 1; i <= number_of_session_restores; ++i) { + // Restore session. + SessionRestore::OnWillRestoreTab(web_contents()); + RestoreTabs(); + NavigateAndCommit(web_contents(), GetTestURL()); + ASSERT_NO_FATAL_FAILURE(SimulateTimingUpdateForTab(web_contents())); + + // Number of paint timings should match the number of session restores. + ExpectFirstPaintMetricsTotalCount(i); + + // Clear committed URL for the next restore starts from an empty URL. + NavigateAndCommit(web_contents(), GURL()); + StopLoading(web_contents()); + } +}
diff --git a/chrome/browser/page_load_metrics/page_load_metrics_browsertest.cc b/chrome/browser/page_load_metrics/page_load_metrics_browsertest.cc index d162b0e..7caedaf 100644 --- a/chrome/browser/page_load_metrics/page_load_metrics_browsertest.cc +++ b/chrome/browser/page_load_metrics/page_load_metrics_browsertest.cc
@@ -2,10 +2,17 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include <memory> +#include <string> +#include <unordered_set> +#include <utility> +#include <vector> + #include "base/command_line.h" #include "base/files/scoped_temp_dir.h" #include "base/logging.h" #include "base/macros.h" +#include "base/memory/ptr_util.h" #include "base/memory/weak_ptr.h" #include "base/run_loop.h" #include "base/test/histogram_tester.h" @@ -19,12 +26,16 @@ #include "chrome/browser/page_load_metrics/observers/core_page_load_metrics_observer.h" #include "chrome/browser/page_load_metrics/observers/document_write_page_load_metrics_observer.h" #include "chrome/browser/page_load_metrics/observers/no_state_prefetch_page_load_metrics_observer.h" +#include "chrome/browser/page_load_metrics/observers/session_restore_page_load_metrics_observer.h" #include "chrome/browser/page_load_metrics/observers/use_counter_page_load_metrics_observer.h" +#include "chrome/browser/page_load_metrics/page_load_metrics_initialize.h" #include "chrome/browser/page_load_metrics/page_load_tracker.h" #include "chrome/browser/prefs/session_startup_pref.h" #include "chrome/browser/prerender/prerender_histograms.h" #include "chrome/browser/prerender/prerender_origin.h" #include "chrome/browser/profiles/profile.h" +#include "chrome/browser/sessions/session_restore.h" +#include "chrome/browser/sessions/session_restore_test_helper.h" #include "chrome/browser/sessions/session_service_factory.h" #include "chrome/browser/sessions/session_service_test_helper.h" #include "chrome/browser/ui/browser.h" @@ -37,11 +48,14 @@ #include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/ui_test_utils.h" #include "components/prefs/pref_service.h" +#include "components/sessions/core/serialized_navigation_entry.h" +#include "components/sessions/core/serialized_navigation_entry_test_helper.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/render_process_host.h" #include "content/public/browser/render_view_host.h" #include "content/public/common/content_features.h" #include "content/public/common/content_switches.h" +#include "content/public/common/referrer.h" #include "content/public/test/browser_test_utils.h" #include "content/public/test/download_test_observer.h" #include "net/base/net_errors.h" @@ -53,6 +67,7 @@ #include "net/url_request/url_request_context.h" #include "net/url_request/url_request_context_getter.h" #include "third_party/WebKit/public/platform/web_feature.mojom.h" +#include "url/gurl.h" namespace { @@ -1119,20 +1134,21 @@ // PageLoadMetricsBrowserTest: void SetUpOnMainThread() override { PageLoadMetricsBrowserTest::SetUpOnMainThread(); - SessionStartupPref::SetStartupPref( - browser()->profile(), SessionStartupPref(SessionStartupPref::LAST)); ASSERT_TRUE(embedded_test_server()->Start()); -#if defined(OS_CHROMEOS) - SessionServiceTestHelper helper( - SessionServiceFactory::GetForProfile(browser()->profile())); - helper.SetForceBrowserNotAliveWithNoWindows(true); - helper.ReleaseService(); -#endif } Browser* QuitBrowserAndRestore(Browser* browser) { Profile* profile = browser->profile(); + SessionStartupPref::SetStartupPref( + profile, SessionStartupPref(SessionStartupPref::LAST)); +#if defined(OS_CHROMEOS) + SessionServiceTestHelper helper( + SessionServiceFactory::GetForProfile(profile)); + helper.SetForceBrowserNotAliveWithNoWindows(true); + helper.ReleaseService(); +#endif + std::unique_ptr<ScopedKeepAlive> keep_alive(new ScopedKeepAlive( KeepAliveOrigin::SESSION_RESTORE, KeepAliveRestartOption::DISABLED)); CloseBrowserSynchronously(browser); @@ -1140,7 +1156,11 @@ // Create a new window, which should trigger session restore. chrome::NewEmptyWindow(profile); ui_test_utils::BrowserAddedObserver window_observer; - return window_observer.WaitForSingleNewBrowser(); + SessionRestoreTestHelper restore_observer; + + Browser* new_browser = window_observer.WaitForSingleNewBrowser(); + restore_observer.Wait(); + return new_browser; } void WaitForTabsToLoad(Browser* browser) { @@ -1148,18 +1168,72 @@ content::WebContents* contents = browser->tab_strip_model()->GetWebContentsAt(i); contents->GetController().LoadIfNecessary(); - content::WaitForLoadStop(contents); + ASSERT_TRUE(content::WaitForLoadStop(contents)); } } + // The PageLoadMetricsWaiter can observe first meaningful paints on these test + // pages while not on other simple pages such as /title1.html. GURL GetTestURL() const { - return embedded_test_server()->GetURL("/title1.html"); + return embedded_test_server()->GetURL( + "/page_load_metrics/main_frame_with_iframe.html"); + } + + GURL GetTestURL2() const { + return embedded_test_server()->GetURL("/title2.html"); + } + + void ExpectFirstPaintMetricsTotalCount(int expected_total_count) const { + histogram_tester_.ExpectTotalCount( + internal::kHistogramSessionRestoreForegroundTabFirstPaint, + expected_total_count); + histogram_tester_.ExpectTotalCount( + internal::kHistogramSessionRestoreForegroundTabFirstContentfulPaint, + expected_total_count); + histogram_tester_.ExpectTotalCount( + internal::kHistogramSessionRestoreForegroundTabFirstMeaningfulPaint, + expected_total_count); } private: DISALLOW_COPY_AND_ASSIGN(SessionRestorePageLoadMetricsBrowserTest); }; +class SessionRestorePaintWaiter : public SessionRestoreObserver { + public: + SessionRestorePaintWaiter() { SessionRestore::AddObserver(this); } + ~SessionRestorePaintWaiter() { SessionRestore::RemoveObserver(this); } + + // SessionRestoreObserver implementation: + void OnWillRestoreTab(content::WebContents* contents) override { + chrome::InitializePageLoadMetricsForWebContents(contents); + auto waiter = base::MakeUnique<PageLoadMetricsWaiter>(contents); + waiter->AddPageExpectation(TimingField::FIRST_PAINT); + waiter->AddPageExpectation(TimingField::FIRST_CONTENTFUL_PAINT); + waiter->AddPageExpectation(TimingField::FIRST_MEANINGFUL_PAINT); + waiters_[contents] = std::move(waiter); + } + + // First meaningful paints occur only on foreground tabs. + void WaitForForegroundTabs(size_t num_expected_foreground_tabs) { + size_t num_actual_foreground_tabs = 0; + for (auto iter = waiters_.begin(); iter != waiters_.end(); ++iter) { + if (!iter->first->IsVisible()) + continue; + iter->second->Wait(); + ++num_actual_foreground_tabs; + } + EXPECT_EQ(num_expected_foreground_tabs, num_actual_foreground_tabs); + } + + private: + std::unordered_map<content::WebContents*, + std::unique_ptr<PageLoadMetricsWaiter>> + waiters_; + + DISALLOW_COPY_AND_ASSIGN(SessionRestorePaintWaiter); +}; + IN_PROC_BROWSER_TEST_F(SessionRestorePageLoadMetricsBrowserTest, InitialVisibilityOfSingleRestoredTab) { ui_test_utils::NavigateToURL(browser(), GetTestURL()); @@ -1169,7 +1243,7 @@ page_load_metrics::internal::kPageLoadStartedInForeground, true, 1); Browser* new_browser = QuitBrowserAndRestore(browser()); - WaitForTabsToLoad(new_browser); + ASSERT_NO_FATAL_FAILURE(WaitForTabsToLoad(new_browser)); histogram_tester_.ExpectTotalCount( page_load_metrics::internal::kPageLoadStartedInForeground, 2); @@ -1189,7 +1263,7 @@ page_load_metrics::internal::kPageLoadStartedInForeground, false, 1); Browser* new_browser = QuitBrowserAndRestore(browser()); - WaitForTabsToLoad(new_browser); + ASSERT_NO_FATAL_FAILURE(WaitForTabsToLoad(new_browser)); TabStripModel* tab_strip = new_browser->tab_strip_model(); ASSERT_TRUE(tab_strip); @@ -1202,3 +1276,229 @@ histogram_tester_.ExpectBucketCount( page_load_metrics::internal::kPageLoadStartedInForeground, false, 2); } + +IN_PROC_BROWSER_TEST_F(SessionRestorePageLoadMetricsBrowserTest, + NoSessionRestore) { + ui_test_utils::NavigateToURL(browser(), GetTestURL()); + ExpectFirstPaintMetricsTotalCount(0); +} + +IN_PROC_BROWSER_TEST_F(SessionRestorePageLoadMetricsBrowserTest, + SingleTabSessionRestore) { + ui_test_utils::NavigateToURL(browser(), GetTestURL()); + + SessionRestorePaintWaiter session_restore_paint_waiter; + QuitBrowserAndRestore(browser()); + + session_restore_paint_waiter.WaitForForegroundTabs(1); + ExpectFirstPaintMetricsTotalCount(1); +} + +IN_PROC_BROWSER_TEST_F(SessionRestorePageLoadMetricsBrowserTest, + MultipleTabsSessionRestore) { + ui_test_utils::NavigateToURL(browser(), GetTestURL()); + ui_test_utils::NavigateToURLWithDisposition( + browser(), GetTestURL(), WindowOpenDisposition::NEW_BACKGROUND_TAB, + ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); + + SessionRestorePaintWaiter session_restore_paint_waiter; + Browser* new_browser = QuitBrowserAndRestore(browser()); + + TabStripModel* tab_strip = new_browser->tab_strip_model(); + ASSERT_TRUE(tab_strip); + ASSERT_EQ(2, tab_strip->count()); + + // Only metrics of the initial foreground tab are recorded. + session_restore_paint_waiter.WaitForForegroundTabs(1); + ExpectFirstPaintMetricsTotalCount(1); +} + +IN_PROC_BROWSER_TEST_F(SessionRestorePageLoadMetricsBrowserTest, + NavigationDuringSessionRestore) { + NavigateToUntrackedUrl(); + Browser* new_browser = QuitBrowserAndRestore(browser()); + + auto waiter = base::MakeUnique<PageLoadMetricsWaiter>( + new_browser->tab_strip_model()->GetActiveWebContents()); + waiter->AddPageExpectation(TimingField::FIRST_MEANINGFUL_PAINT); + ui_test_utils::NavigateToURL(new_browser, GetTestURL()); + waiter->Wait(); + + // No metrics recorded for the second navigation because the tab navigated + // away during session restore. + ExpectFirstPaintMetricsTotalCount(0); +} + +IN_PROC_BROWSER_TEST_F(SessionRestorePageLoadMetricsBrowserTest, + LoadingAfterSessionRestore) { + ui_test_utils::NavigateToURL(browser(), GetTestURL()); + + Browser* new_browser = nullptr; + { + SessionRestorePaintWaiter session_restore_paint_waiter; + new_browser = QuitBrowserAndRestore(browser()); + + session_restore_paint_waiter.WaitForForegroundTabs(1); + ExpectFirstPaintMetricsTotalCount(1); + } + + // Load a new page after session restore. + auto waiter = base::MakeUnique<PageLoadMetricsWaiter>( + new_browser->tab_strip_model()->GetActiveWebContents()); + waiter->AddPageExpectation(TimingField::FIRST_MEANINGFUL_PAINT); + ui_test_utils::NavigateToURL(new_browser, GetTestURL()); + waiter->Wait(); + + // No more metrics because the navigation is after session restore. + ExpectFirstPaintMetricsTotalCount(1); +} + +IN_PROC_BROWSER_TEST_F(SessionRestorePageLoadMetricsBrowserTest, + InitialForegroundTabChanged) { + ui_test_utils::NavigateToURL(browser(), GetTestURL()); + ui_test_utils::NavigateToURLWithDisposition( + browser(), GetTestURL(), WindowOpenDisposition::NEW_BACKGROUND_TAB, + ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); + + SessionRestorePaintWaiter session_restore_paint_waiter; + Browser* new_browser = QuitBrowserAndRestore(browser()); + + // Change the foreground tab before the first meaningful paint. + TabStripModel* tab_strip = new_browser->tab_strip_model(); + ASSERT_TRUE(tab_strip); + ASSERT_EQ(2, tab_strip->count()); + ASSERT_EQ(0, tab_strip->active_index()); + tab_strip->ActivateTabAt(1, true); + + session_restore_paint_waiter.WaitForForegroundTabs(1); + + // No metrics were recorded because initial foreground tab was switched away. + ExpectFirstPaintMetricsTotalCount(0); +} + +IN_PROC_BROWSER_TEST_F(SessionRestorePageLoadMetricsBrowserTest, + MultipleSessionRestores) { + ui_test_utils::NavigateToURL(browser(), GetTestURL()); + + Browser* current_browser = browser(); + const int num_session_restores = 3; + for (int i = 1; i <= num_session_restores; ++i) { + SessionRestorePaintWaiter session_restore_paint_waiter; + current_browser = QuitBrowserAndRestore(current_browser); + session_restore_paint_waiter.WaitForForegroundTabs(1); + ExpectFirstPaintMetricsTotalCount(i); + } +} + +IN_PROC_BROWSER_TEST_F(SessionRestorePageLoadMetricsBrowserTest, + RestoreForeignTab) { + sessions::SerializedNavigationEntry nav = + sessions::SerializedNavigationEntryTestHelper::CreateNavigation( + GetTestURL().spec(), "one"); + + // Set up the restore data. + sync_pb::SessionTab sync_data; + sync_data.set_tab_visual_index(0); + sync_data.set_current_navigation_index(1); + sync_data.set_pinned(false); + sync_data.add_navigation()->CopyFrom(nav.ToSyncData()); + + sessions::SessionTab tab; + tab.SetFromSyncData(sync_data, base::Time::Now()); + ASSERT_EQ(1, browser()->tab_strip_model()->count()); + + // Restore in the current tab. + content::WebContents* tab_contents = nullptr; + { + SessionRestorePaintWaiter session_restore_paint_waiter; + tab_contents = SessionRestore::RestoreForeignSessionTab( + browser()->tab_strip_model()->GetActiveWebContents(), tab, + WindowOpenDisposition::CURRENT_TAB); + ASSERT_EQ(1, browser()->tab_strip_model()->count()); + ASSERT_TRUE(tab_contents); + ASSERT_EQ(GetTestURL(), tab_contents->GetURL()); + + session_restore_paint_waiter.WaitForForegroundTabs(1); + ExpectFirstPaintMetricsTotalCount(1); + } + + // Restore in a new foreground tab. + { + SessionRestorePaintWaiter session_restore_paint_waiter; + tab_contents = SessionRestore::RestoreForeignSessionTab( + browser()->tab_strip_model()->GetActiveWebContents(), tab, + WindowOpenDisposition::NEW_FOREGROUND_TAB); + ASSERT_EQ(2, browser()->tab_strip_model()->count()); + ASSERT_EQ(1, browser()->tab_strip_model()->active_index()); + ASSERT_TRUE(tab_contents); + ASSERT_EQ(GetTestURL(), tab_contents->GetURL()); + + session_restore_paint_waiter.WaitForForegroundTabs(1); + ExpectFirstPaintMetricsTotalCount(2); + } + + // Restore in a new background tab. + { + tab_contents = SessionRestore::RestoreForeignSessionTab( + browser()->tab_strip_model()->GetActiveWebContents(), tab, + WindowOpenDisposition::NEW_BACKGROUND_TAB); + ASSERT_EQ(3, browser()->tab_strip_model()->count()); + ASSERT_EQ(1, browser()->tab_strip_model()->active_index()); + ASSERT_TRUE(tab_contents); + ASSERT_EQ(GetTestURL(), tab_contents->GetURL()); + ASSERT_NO_FATAL_FAILURE(WaitForTabsToLoad(browser())); + + // Do not record timings of initially background tabs. + ExpectFirstPaintMetricsTotalCount(2); + } +} + +IN_PROC_BROWSER_TEST_F(SessionRestorePageLoadMetricsBrowserTest, + RestoreForeignSession) { + Profile* profile = browser()->profile(); + + sessions::SerializedNavigationEntry nav1 = + sessions::SerializedNavigationEntryTestHelper::CreateNavigation( + GetTestURL().spec(), "one"); + sessions::SerializedNavigationEntry nav2 = + sessions::SerializedNavigationEntryTestHelper::CreateNavigation( + GetTestURL2().spec(), "two"); + + // Set up the restore data: one window with two tabs. + std::vector<const sessions::SessionWindow*> session; + sessions::SessionWindow window; + auto tab1 = base::MakeUnique<sessions::SessionTab>(); + { + sync_pb::SessionTab sync_data; + sync_data.set_tab_visual_index(0); + sync_data.set_current_navigation_index(0); + sync_data.set_pinned(true); + sync_data.add_navigation()->CopyFrom(nav1.ToSyncData()); + tab1->SetFromSyncData(sync_data, base::Time::Now()); + } + window.tabs.push_back(std::move(tab1)); + + auto tab2 = base::MakeUnique<sessions::SessionTab>(); + { + sync_pb::SessionTab sync_data; + sync_data.set_tab_visual_index(1); + sync_data.set_current_navigation_index(0); + sync_data.set_pinned(false); + sync_data.add_navigation()->CopyFrom(nav2.ToSyncData()); + tab2->SetFromSyncData(sync_data, base::Time::Now()); + } + window.tabs.push_back(std::move(tab2)); + + // Restore the session window with 2 tabs. + session.push_back(static_cast<const sessions::SessionWindow*>(&window)); + ui_test_utils::BrowserAddedObserver window_observer; + SessionRestorePaintWaiter session_restore_paint_waiter; + SessionRestore::RestoreForeignSessionWindows(profile, session.begin(), + session.end()); + Browser* new_browser = window_observer.WaitForSingleNewBrowser(); + ASSERT_TRUE(new_browser); + ASSERT_EQ(2, new_browser->tab_strip_model()->count()); + + session_restore_paint_waiter.WaitForForegroundTabs(1); + ExpectFirstPaintMetricsTotalCount(1); +}
diff --git a/chrome/browser/page_load_metrics/page_load_metrics_initialize.cc b/chrome/browser/page_load_metrics/page_load_metrics_initialize.cc index 32b78352..774715f5 100644 --- a/chrome/browser/page_load_metrics/page_load_metrics_initialize.cc +++ b/chrome/browser/page_load_metrics/page_load_metrics_initialize.cc
@@ -10,10 +10,8 @@ #include "base/macros.h" #include "base/memory/ptr_util.h" #include "base/timer/timer.h" +#include "build/build_config.h" #include "chrome/browser/page_load_metrics/metrics_web_contents_observer.h" -#if defined(OS_ANDROID) -#include "chrome/browser/page_load_metrics/observers/android_page_load_metrics_observer.h" -#endif // OS_ANDROID #include "chrome/browser/page_load_metrics/observers/aborts_page_load_metrics_observer.h" #include "chrome/browser/page_load_metrics/observers/ads_page_load_metrics_observer.h" #include "chrome/browser/page_load_metrics/observers/amp_page_load_metrics_observer.h" @@ -50,6 +48,12 @@ #include "content/public/browser/web_contents.h" #include "url/gurl.h" +#if defined(OS_ANDROID) +#include "chrome/browser/page_load_metrics/observers/android_page_load_metrics_observer.h" +#else +#include "chrome/browser/page_load_metrics/observers/session_restore_page_load_metrics_observer.h" +#endif + namespace chrome { namespace { @@ -137,6 +141,10 @@ web_contents_); if (loading_predictor_observer) tracker->AddObserver(std::move(loading_predictor_observer)); +#if !defined(OS_ANDROID) + tracker->AddObserver( + base::MakeUnique<SessionRestorePageLoadMetricsObserver>()); +#endif tracker->AddObserver( base::MakeUnique<LocalNetworkRequestsPageLoadMetricsObserver>()); } else {
diff --git a/chrome/browser/predictors/autocomplete_action_predictor_unittest.cc b/chrome/browser/predictors/autocomplete_action_predictor_unittest.cc index 49cef54..7c9bed4dd 100644 --- a/chrome/browser/predictors/autocomplete_action_predictor_unittest.cc +++ b/chrome/browser/predictors/autocomplete_action_predictor_unittest.cc
@@ -18,6 +18,8 @@ #include "base/time/time.h" #include "chrome/browser/history/history_service_factory.h" #include "chrome/browser/prerender/prerender_field_trial.h" +#include "chrome/browser/prerender/prerender_manager.h" +#include "chrome/browser/prerender/prerender_test_utils.h" #include "chrome/common/chrome_switches.h" #include "chrome/test/base/testing_profile.h" #include "components/history/core/browser/history_service.h" @@ -348,6 +350,9 @@ AutocompleteMatch match; match.type = AutocompleteMatchType::HISTORY_URL; + prerender::test_utils::RestorePrerenderMode restore_prerender_mode; + prerender::PrerenderManager::SetMode( + prerender::PrerenderManager::PRERENDER_MODE_NOSTATE_PREFETCH); for (size_t i = 0; i < arraysize(test_url_db); ++i) { match.destination_url = GURL(test_url_db[i].url); @@ -362,6 +367,9 @@ AutocompleteMatch match; match.type = AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED; + prerender::test_utils::RestorePrerenderMode restore_prerender_mode; + prerender::PrerenderManager::SetMode( + prerender::PrerenderManager::PRERENDER_MODE_NOSTATE_PREFETCH); for (size_t i = 0; i < arraysize(test_url_db); ++i) { match.destination_url = GURL(test_url_db[i].url);
diff --git a/chrome/browser/prerender/prerender_browsertest.cc b/chrome/browser/prerender/prerender_browsertest.cc index 4d584d25..3b75da09 100644 --- a/chrome/browser/prerender/prerender_browsertest.cc +++ b/chrome/browser/prerender/prerender_browsertest.cc
@@ -599,6 +599,10 @@ test_utils::PrerenderInProcessBrowserTest::SetUpOnMainThread(); prerender::PrerenderManager::SetMode( prerender::PrerenderManager::PRERENDER_MODE_ENABLED); + prerender::PrerenderManager::SetInstantMode( + prerender::PrerenderManager::PRERENDER_MODE_ENABLED); + prerender::PrerenderManager::SetOmniboxMode( + prerender::PrerenderManager::PRERENDER_MODE_ENABLED); const testing::TestInfo* const test_info = testing::UnitTest::GetInstance()->current_test_info(); // This one test fails with the host resolver redirecting all hosts.
diff --git a/chrome/browser/prerender/prerender_field_trial.cc b/chrome/browser/prerender/prerender_field_trial.cc index 56835cf..6d4892c9 100644 --- a/chrome/browser/prerender/prerender_field_trial.cc +++ b/chrome/browser/prerender/prerender_field_trial.cc
@@ -69,9 +69,9 @@ base::FEATURE_ENABLED_BY_DEFAULT}; void ConfigurePrerender() { - PrerenderManager::PrerenderManagerMode overall_mode = - ParsePrerenderMode(kNoStatePrefetchFeatureModeParameterName, - PrerenderManager::PRERENDER_MODE_ENABLED); + PrerenderManager::PrerenderManagerMode overall_mode = ParsePrerenderMode( + kNoStatePrefetchFeatureModeParameterName, + PrerenderManager::PRERENDER_MODE_SIMPLE_LOAD_EXPERIMENT); PrerenderManager::SetMode(overall_mode); PrerenderManager::SetInstantMode(ParsePrerenderMode(
diff --git a/chrome/browser/prerender/prerender_manager.cc b/chrome/browser/prerender/prerender_manager.cc index f0b3455..c3a03a2 100644 --- a/chrome/browser/prerender/prerender_manager.cc +++ b/chrome/browser/prerender/prerender_manager.cc
@@ -166,11 +166,11 @@ // static PrerenderManager::PrerenderManagerMode PrerenderManager::mode_ = - PRERENDER_MODE_ENABLED; + PRERENDER_MODE_SIMPLE_LOAD_EXPERIMENT; PrerenderManager::PrerenderManagerMode PrerenderManager::instant_mode_ = - PRERENDER_MODE_ENABLED; + PRERENDER_MODE_SIMPLE_LOAD_EXPERIMENT; PrerenderManager::PrerenderManagerMode PrerenderManager::omnibox_mode_ = - PRERENDER_MODE_ENABLED; + PRERENDER_MODE_SIMPLE_LOAD_EXPERIMENT; struct PrerenderManager::NavigationRecord { NavigationRecord(const GURL& url, base::TimeTicks time, Origin origin)
diff --git a/chrome/browser/prerender/prerender_manager.h b/chrome/browser/prerender/prerender_manager.h index 518c8d2..87bebe4 100644 --- a/chrome/browser/prerender/prerender_manager.h +++ b/chrome/browser/prerender/prerender_manager.h
@@ -83,10 +83,19 @@ public MediaCaptureDevicesDispatcher::Observer { public: enum PrerenderManagerMode { + // WARNING: Legacy code, not for use. Disables prerendering and avoids + // creating an instance of PrerenderManager. This mode overrides forced + // prerenders which breaks the assumptions of the CustomTabActivityTest. PRERENDER_MODE_DISABLED, + + // Enables all types of prerendering for any origin. PRERENDER_MODE_ENABLED, + + // For each request to prerender performs a NoStatePrefetch for the same URL + // instead. PRERENDER_MODE_NOSTATE_PREFETCH, - // Like PRERENDER_MODE_DISABLED, but keeps track of pages that would have + + // Ignores requests to prerender, but keeps track of pages that would have // been prerendered and records metrics for comparison with other modes. PRERENDER_MODE_SIMPLE_LOAD_EXPERIMENT };
diff --git a/chrome/browser/prerender/prerender_test_utils.cc b/chrome/browser/prerender/prerender_test_utils.cc index 8471c97..1f6f5fdf 100644 --- a/chrome/browser/prerender/prerender_test_utils.cc +++ b/chrome/browser/prerender/prerender_test_utils.cc
@@ -701,28 +701,34 @@ } void PrerenderInProcessBrowserTest::SetUpOnMainThread() { - // Increase the memory allowed in a prerendered page above normal settings. - // Debug build bots occasionally run against the default limit, and tests - // were failing because the prerender was canceled due to memory exhaustion. - // http://crbug.com/93076 - GetPrerenderManager()->mutable_config().max_bytes = 2000 * 1024 * 1024; - current_browser()->profile()->GetPrefs()->SetBoolean( prefs::kPromptForDownload, false); if (autostart_test_server_) - ASSERT_TRUE(embedded_test_server()->Start()); + CHECK(embedded_test_server()->Start()); ChromeResourceDispatcherHostDelegate:: SetExternalProtocolHandlerDelegateForTesting( external_protocol_handler_delegate_.get()); + // Check that PrerenderManager exists, which is necessary to make sure + // NoStatePrefetch can be enabled and perceived FCP metrics can be recorded. PrerenderManager* prerender_manager = GetPrerenderManager(); - ASSERT_TRUE(prerender_manager); + // Use CHECK to fail fast. The ASSERT_* macros in this context are not useful + // because they only silently exit and make the tests crash later with more + // complicated symptoms. + CHECK(prerender_manager); + + // Increase the memory allowed in a prerendered page above normal settings. + // Debug build bots occasionally run against the default limit, and tests + // were failing because the prerender was canceled due to memory exhaustion. + // http://crbug.com/93076 + prerender_manager->mutable_config().max_bytes = 2000 * 1024 * 1024; + prerender_manager->mutable_config().rate_limit_enabled = false; - ASSERT_FALSE(prerender_contents_factory_); + CHECK(!prerender_contents_factory_); prerender_contents_factory_ = new TestPrerenderContentsFactory; prerender_manager->SetPrerenderContentsFactoryForTest( prerender_contents_factory_); - ASSERT_TRUE(safe_browsing_factory_->test_safe_browsing_service()); + CHECK(safe_browsing_factory_->test_safe_browsing_service()); } void PrerenderInProcessBrowserTest::UseHttpsSrcServer() {
diff --git a/chrome/browser/prerender/prerender_unittest.cc b/chrome/browser/prerender/prerender_unittest.cc index 9eac021b..a6fb221 100644 --- a/chrome/browser/prerender/prerender_unittest.cc +++ b/chrome/browser/prerender/prerender_unittest.cc
@@ -332,6 +332,12 @@ new PrerenderLinkManager(prerender_manager_.get())), last_prerender_id_(0), field_trial_list_(nullptr) { + prerender::PrerenderManager::SetMode( + prerender::PrerenderManager::PRERENDER_MODE_ENABLED); + prerender::PrerenderManager::SetInstantMode( + prerender::PrerenderManager::PRERENDER_MODE_ENABLED); + prerender::PrerenderManager::SetOmniboxMode( + prerender::PrerenderManager::PRERENDER_MODE_ENABLED); prerender_manager()->SetIsLowEndDevice(false); // Enable omnibox prerendering. @@ -458,26 +464,23 @@ // An instance of base::FieldTrialList is necessary in order to initialize // global state. base::FieldTrialList field_trial_list_; + + // Restore prerender mode after this test finishes running. + test_utils::RestorePrerenderMode restore_prerender_mode_; }; TEST_F(PrerenderTest, PrerenderRespectsDisableFlag) { test_utils::RestorePrerenderMode restore_prerender_mode; - ASSERT_TRUE(PrerenderManager::IsAnyPrerenderingPossible()); - ASSERT_EQ(PrerenderManager::PRERENDER_MODE_ENABLED, + base::test::ScopedFeatureList scoped_feature_list; + scoped_feature_list.InitAndDisableFeature(kNoStatePrefetchFeature); + prerender::ConfigurePrerender(); + EXPECT_FALSE(PrerenderManager::IsAnyPrerenderingPossible()); + EXPECT_EQ(PrerenderManager::PRERENDER_MODE_DISABLED, PrerenderManager::GetMode(ORIGIN_NONE)); - - { - base::test::ScopedFeatureList scoped_feature_list; - scoped_feature_list.InitAndDisableFeature(kNoStatePrefetchFeature); - prerender::ConfigurePrerender(); - EXPECT_FALSE(PrerenderManager::IsAnyPrerenderingPossible()); - EXPECT_EQ(PrerenderManager::PRERENDER_MODE_DISABLED, - PrerenderManager::GetMode(ORIGIN_NONE)); - EXPECT_EQ(PrerenderManager::PRERENDER_MODE_DISABLED, - PrerenderManager::GetMode(ORIGIN_OMNIBOX)); - EXPECT_EQ(PrerenderManager::PRERENDER_MODE_DISABLED, - PrerenderManager::GetMode(ORIGIN_INSTANT)); - } + EXPECT_EQ(PrerenderManager::PRERENDER_MODE_DISABLED, + PrerenderManager::GetMode(ORIGIN_OMNIBOX)); + EXPECT_EQ(PrerenderManager::PRERENDER_MODE_DISABLED, + PrerenderManager::GetMode(ORIGIN_INSTANT)); } TEST_F(PrerenderTest, PrerenderRespectsFieldTrialParameters) { @@ -602,7 +605,6 @@ TEST_F(PrerenderTest, PrerenderRespectsThirdPartyCookiesPref) { GURL url("http://www.google.com/"); - test_utils::RestorePrerenderMode restore_prerender_mode; ASSERT_TRUE(PrerenderManager::IsAnyPrerenderingPossible()); profile()->GetPrefs()->SetBoolean(prefs::kBlockThirdPartyCookies, true); @@ -613,7 +615,6 @@ TEST_F(PrerenderTest, OfflinePrerenderIgnoresThirdPartyCookiesPref) { GURL url("http://www.google.com/"); - test_utils::RestorePrerenderMode restore_prerender_mode; ASSERT_TRUE(PrerenderManager::IsAnyPrerenderingPossible()); profile()->GetPrefs()->SetBoolean(prefs::kBlockThirdPartyCookies, true); @@ -2107,7 +2108,7 @@ FINAL_STATUS_USED); std::unique_ptr<PrerenderHandle> prerender_handle( prerender_manager()->AddPrerenderForInstant(url, nullptr, kSize)); - CHECK(prerender_handle); + ASSERT_TRUE(prerender_handle); EXPECT_TRUE(prerender_handle->IsPrerendering()); EXPECT_TRUE(prerender_contents->prerendering_has_started()); EXPECT_EQ(prerender_contents, prerender_handle->contents());
diff --git a/chrome/browser/renderer_context_menu/render_view_context_menu.cc b/chrome/browser/renderer_context_menu/render_view_context_menu.cc index 6e67636..fa0151b 100644 --- a/chrome/browser/renderer_context_menu/render_view_context_menu.cc +++ b/chrome/browser/renderer_context_menu/render_view_context_menu.cc
@@ -785,7 +785,11 @@ AppendPrintItem(); } - if (editable && params_.misspelled_word.empty()) { + // Spell check and writing direction options are not currently supported by + // pepper plugins. + if (editable && params_.misspelled_word.empty() && + !content_type_->SupportsGroup( + ContextMenuContentType::ITEM_GROUP_MEDIA_PLUGIN)) { menu_model_.AddSeparator(ui::NORMAL_SEPARATOR); AppendLanguageSettings(); AppendPlatformEditableItems(); @@ -1173,9 +1177,12 @@ (!embedder_web_contents_ || !embedder_web_contents_->IsSavable()))) { // Both full page and embedded plugins are hosted as guest now, // the difference is a full page plugin is not considered as savable. - // For full page plugin, we show page menu items. - if (params_.link_url.is_empty() && params_.selection_text.empty()) + // For full page plugin, we show page menu items so long as focus is not + // within an editable text area. + if (params_.link_url.is_empty() && params_.selection_text.empty() && + !params_.is_editable) { AppendPageItems(); + } } else { menu_model_.AddItemWithStringId(IDC_CONTENT_CONTEXT_SAVEAVAS, IDS_CONTENT_CONTEXT_SAVEPAGEAS);
diff --git a/chrome/browser/resources/chromeos/login/screen_supervised_user_creation.html b/chrome/browser/resources/chromeos/login/screen_supervised_user_creation.html index 04eec94..baef507 100644 --- a/chrome/browser/resources/chromeos/login/screen_supervised_user_creation.html +++ b/chrome/browser/resources/chromeos/login/screen_supervised_user_creation.html
@@ -158,7 +158,7 @@ </div> </div> <div id="supervised-user-creation-import-template" hidden class="import-pod"> - <img class="import-pod-image"></img> + <img class="import-pod-image"> <div class="import-pod-name"></div> </div> <navigation-bar id="supervised-user-creation-navigation" close-visible>
diff --git a/chrome/browser/resources/extensions/extension_options_overlay.html b/chrome/browser/resources/extensions/extension_options_overlay.html index 2398ac3..e5ee0b9 100644 --- a/chrome/browser/resources/extensions/extension_options_overlay.html +++ b/chrome/browser/resources/extensions/extension_options_overlay.html
@@ -6,8 +6,7 @@ <div id="extension-options-overlay" class="page"> <div class="close-button"></div> <div id="extension-options-overlay-header"> - <img id="extension-options-overlay-icon" - aria-hidden="true"></img> + <img id="extension-options-overlay-icon" aria-hidden="true"> <h1 id="extension-options-overlay-title"></h1> </div> <div id="extension-options-overlay-guest"></div>
diff --git a/chrome/browser/resources/extensions/extensions.html b/chrome/browser/resources/extensions/extensions.html index 7ed15c8..bcca289 100644 --- a/chrome/browser/resources/extensions/extensions.html +++ b/chrome/browser/resources/extensions/extensions.html
@@ -162,7 +162,7 @@ $i18n{extensionSettingsReloadUnpacked} </a> <a is="action-link" role="button" class="errors-link"> - <img class="extension-error-icon"></img> + <img class="extension-error-icon"> <span>$i18n{extensionErrorHeading}</span> </a> </div>
diff --git a/chrome/browser/resources/md_extensions/OWNERS b/chrome/browser/resources/md_extensions/OWNERS index 8483f0b4..4efe53b 100644 --- a/chrome/browser/resources/md_extensions/OWNERS +++ b/chrome/browser/resources/md_extensions/OWNERS
@@ -1,4 +1,5 @@ rdevlin.cronin@chromium.org +scottchen@chromium.org # TEAM: extensions-dev@chromium.org # COMPONENT: Platform>Extensions
diff --git a/chrome/browser/resources/md_extensions/options_dialog.html b/chrome/browser/resources/md_extensions/options_dialog.html index 09e4de7e..9ac04c3 100644 --- a/chrome/browser/resources/md_extensions/options_dialog.html +++ b/chrome/browser/resources/md_extensions/options_dialog.html
@@ -30,7 +30,7 @@ <dialog is="cr-dialog" id="dialog" close-text="$i18n{close}"> <div slot="title"> <div id="icon-and-name-wrapper"> - <img id="icon" src="[[data_.iconUrl]]"></img> + <img id="icon" src="[[data_.iconUrl]]"> <span>[[data_.name]]</span> </div> </div>
diff --git a/chrome/browser/resources/md_user_manager/import_supervised_user.html b/chrome/browser/resources/md_user_manager/import_supervised_user.html index ff2da9e..b308c93 100644 --- a/chrome/browser/resources/md_user_manager/import_supervised_user.html +++ b/chrome/browser/resources/md_user_manager/import_supervised_user.html
@@ -69,7 +69,7 @@ <paper-listbox class="no-padding" selected="{{supervisedUserIndex_}}"> <template is="dom-repeat" items="[[supervisedUsers_]]"> <paper-item disabled="[[item.onCurrentDevice]]"> - <img class="profile-img" src="[[item.iconURL]]"></img> + <img class="profile-img" src="[[item.iconURL]]"> <div class="profile-name">[[item.name]]</div> <div class="on-device" hidden="[[!item.onCurrentDevice]]"> $i18n{supervisedUserAlreadyOnThisDevice}
diff --git a/chrome/browser/resources/policy.css b/chrome/browser/resources/policy.css index eb4f543..3dce761 100644 --- a/chrome/browser/resources/policy.css +++ b/chrome/browser/resources/policy.css
@@ -69,11 +69,11 @@ text-align: left; } -div.reload-policies-button { +div.left-aligned-button { float: left; } -html[dir='rtl'] div.reload-policies-button { +html[dir='rtl'] div.left-aligned-button { float: right; }
diff --git a/chrome/browser/resources/policy.html b/chrome/browser/resources/policy.html index dbf20f2..6a5d9eaa 100644 --- a/chrome/browser/resources/policy.html +++ b/chrome/browser/resources/policy.html
@@ -31,9 +31,13 @@ <h1 i18n-content="title"></h1> </header> <section class="reload-show-unset-section"> - <div class="reload-policies-button"> + <div class="left-aligned-button"> <button id="reload-policies" i18n-content="reloadPolicies"></button> </div> + <div class="left-aligned-button"> + <button id="export-policies" i18n-content="exportPoliciesJSON"> + </button> + </div> <div class="chrome-for-work"> <a href="http://g.co/chromeent/learn" target="_blank"> <span i18n-content="chromeForWork"></span></a>
diff --git a/chrome/browser/resources/policy.js b/chrome/browser/resources/policy.js index a46ff41a..242ab60 100644 --- a/chrome/browser/resources/policy.js +++ b/chrome/browser/resources/policy.js
@@ -451,6 +451,10 @@ chrome.send('reloadPolicies'); }; + $('export-policies').onclick = function(event) { + chrome.send('exportPoliciesJSON'); + }; + $('show-unset').onchange = function() { for (policyTable in self.policyTables) { self.policyTables[policyTable].filter();
diff --git a/chrome/browser/resources/set_as_default_browser.html b/chrome/browser/resources/set_as_default_browser.html index 945ec326..92865ee5 100644 --- a/chrome/browser/resources/set_as_default_browser.html +++ b/chrome/browser/resources/set_as_default_browser.html
@@ -33,7 +33,7 @@ </div> </div> <div id="chrome-logo-box"> - <img src="chrome-logo-faded.png" i18n-values="alt:chromeLogoString"></img> + <img src="chrome-logo-faded.png" i18n-values="alt:chromeLogoString"> </div> </div> </body>
diff --git a/chrome/browser/resources/settings/OWNERS b/chrome/browser/resources/settings/OWNERS index 61b5877..387901f 100644 --- a/chrome/browser/resources/settings/OWNERS +++ b/chrome/browser/resources/settings/OWNERS
@@ -2,6 +2,7 @@ dschuyler@chromium.org hcarmona@chromium.org michaelpg@chromium.org +scottchen@chromium.org stevenjb@chromium.org tommycli@chromium.org
diff --git a/chrome/browser/resources/signin/sync_confirmation/sync_confirmation.html b/chrome/browser/resources/signin/sync_confirmation/sync_confirmation.html index 6f7d2eff..99a1e11 100644 --- a/chrome/browser/resources/signin/sync_confirmation/sync_confirmation.html +++ b/chrome/browser/resources/signin/sync_confirmation/sync_confirmation.html
@@ -37,7 +37,7 @@ <div id="icon-circle-4" class="icon-circle fade-top-right"></div> </div> <div class="picture"> - <img id="profile-picture"></img> + <img id="profile-picture"> <div id="checkmark-circle"> <svg id="checkmark-check" width="13" height="10" viewBox="0 0 13 10"> <path id="checkmark-path" d="M1 5l3.5 3.5L12 1" stroke="#FFF"
diff --git a/chrome/browser/ssl/ssl_error_assistant.proto b/chrome/browser/ssl/ssl_error_assistant.proto index ba05957c..99f6b1ca 100644 --- a/chrome/browser/ssl/ssl_error_assistant.proto +++ b/chrome/browser/ssl/ssl_error_assistant.proto
@@ -18,7 +18,20 @@ optional string sha256_hash = 1; } +message MITMSoftware { + // Regex that SSLErrorHandler matches against the |issuer.common_name| + // of a certificate to determine whether or not it's a MITM software + // certificate. + optional string regex = 1; + // Name of the MITM software to display on the interstitial. + optional string name = 2; + // Link to a help center URL with information about how to uninstall or + // reconfigure the offending MITM software. + optional string help_url = 3; +} + message SSLErrorAssistantConfig { optional uint32 version_id = 1; repeated CaptivePortalCert captive_portal_cert = 2; + repeated MITMSoftware mitm_software = 3; }
diff --git a/chrome/browser/ssl/ssl_error_handler.cc b/chrome/browser/ssl/ssl_error_handler.cc index 2b367d4..6952d1d 100644 --- a/chrome/browser/ssl/ssl_error_handler.cc +++ b/chrome/browser/ssl/ssl_error_handler.cc
@@ -5,6 +5,7 @@ #include "chrome/browser/ssl/ssl_error_handler.h" #include <stdint.h> +#include <regex> #include <unordered_set> #include <utility> @@ -37,6 +38,7 @@ #include "content/public/browser/render_frame_host.h" #include "content/public/browser/web_contents.h" #include "net/base/net_errors.h" +#include "third_party/protobuf/src/google/protobuf/io/zero_copy_stream_impl_lite.h" #include "ui/base/resource/resource_bundle.h" #if BUILDFLAG(ENABLE_CAPTIVE_PORTAL_DETECTION) @@ -44,11 +46,15 @@ #include "chrome/browser/captive_portal/captive_portal_service_factory.h" #include "chrome/browser/captive_portal/captive_portal_tab_helper.h" #include "chrome/browser/ssl/captive_portal_blocking_page.h" -#include "third_party/protobuf/src/google/protobuf/io/zero_copy_stream_impl_lite.h" #endif namespace { +#if !defined(OS_IOS) +const base::Feature kMITMSoftwareInterstitial{ + "MITMSoftwareInterstitial", base::FEATURE_DISABLED_BY_DEFAULT}; +#endif + #if BUILDFLAG(ENABLE_CAPTIVE_PORTAL_DETECTION) const base::Feature kCaptivePortalInterstitial{ "CaptivePortalInterstitial", base::FEATURE_ENABLED_BY_DEFAULT}; @@ -177,6 +183,34 @@ return base::FeatureList::IsEnabled(kCaptivePortalInterstitial); } +std::unique_ptr<std::unordered_set<std::string>> LoadCaptivePortalCertHashes( + const chrome_browser_ssl::SSLErrorAssistantConfig& proto) { + auto hashes = base::MakeUnique<std::unordered_set<std::string>>(); + for (const chrome_browser_ssl::CaptivePortalCert& cert : + proto.captive_portal_cert()) { + hashes.get()->insert(cert.sha256_hash()); + } + return hashes; +} +#endif + +#if !defined(OS_IOS) +bool IsMITMSoftwareInterstitialEnabled() { + return base::FeatureList::IsEnabled(kMITMSoftwareInterstitial); +} + +std::unique_ptr<std::vector<std::regex>> LoadMITMSoftwareRegexes( + const chrome_browser_ssl::SSLErrorAssistantConfig& proto) { + auto regexes = base::MakeUnique<std::vector<std::regex>>(); + for (const chrome_browser_ssl::MITMSoftware& filter : proto.mitm_software()) { + // There isn't a regex type in proto buffer world, so convert the string + // literals returned from our proto to regexes. + regexes.get()->push_back(std::regex(filter.regex())); + } + return regexes; +} +#endif + // Reads the SSL error assistant configuration from the resource bundle. std::unique_ptr<chrome_browser_ssl::SSLErrorAssistantConfig> ReadErrorAssistantProtoFromResourceBundle() { @@ -190,17 +224,6 @@ return proto->ParseFromZeroCopyStream(&stream) ? std::move(proto) : nullptr; } -std::unique_ptr<std::unordered_set<std::string>> LoadCaptivePortalCertHashes( - const chrome_browser_ssl::SSLErrorAssistantConfig& proto) { - auto hashes = base::MakeUnique<std::unordered_set<std::string>>(); - for (const chrome_browser_ssl::CaptivePortalCert& cert : - proto.captive_portal_cert()) { - hashes.get()->insert(cert.sha256_hash()); - } - return hashes; -} -#endif - bool IsSSLCommonNameMismatchHandlingEnabled() { return base::FeatureList::IsEnabled(kSSLCommonNameMismatchHandling); } @@ -222,6 +245,12 @@ bool IsKnownCaptivePortalCert(const net::SSLInfo& ssl_info); #endif +#if !defined(OS_IOS) + // Returns true if the cert issuer matches one of our known MITM software + // providers. + bool CertContainsMITMSoftwareString(const net::SSLInfo& ssl_info); +#endif + // Testing methods: void ResetForTesting(); void SetInterstitialDelayForTesting(const base::TimeDelta& delay); @@ -230,12 +259,9 @@ void SetClockForTesting(base::Clock* clock); void SetNetworkTimeTrackerForTesting( network_time::NetworkTimeTracker* tracker); - -#if BUILDFLAG(ENABLE_CAPTIVE_PORTAL_DETECTION) void SetErrorAssistantProto( std::unique_ptr<chrome_browser_ssl::SSLErrorAssistantConfig> error_assistant_proto); -#endif private: base::TimeDelta interstitial_delay_; @@ -250,11 +276,15 @@ network_time::NetworkTimeTracker* network_time_tracker_ = nullptr; -#if BUILDFLAG(ENABLE_CAPTIVE_PORTAL_DETECTION) +#if !defined(OS_IOS) // Error assistant configuration. std::unique_ptr<chrome_browser_ssl::SSLErrorAssistantConfig> error_assistant_proto_; + std::unique_ptr<std::vector<std::regex>> mitm_software_regexes_; +#endif + +#if BUILDFLAG(ENABLE_CAPTIVE_PORTAL_DETECTION) // SPKI hashes belonging to certs treated as captive portals. Null until the // first time IsKnownCaptivePortalCert() or SetErrorAssistantProto() // is called. @@ -292,8 +322,11 @@ timer_started_callback_ = nullptr; network_time_tracker_ = nullptr; testing_clock_ = nullptr; -#if BUILDFLAG(ENABLE_CAPTIVE_PORTAL_DETECTION) +#if !defined(OS_IOS) error_assistant_proto_.reset(); + mitm_software_regexes_.reset(); +#endif +#if BUILDFLAG(ENABLE_CAPTIVE_PORTAL_DETECTION) captive_portal_spki_hashes_.reset(); #endif } @@ -318,7 +351,7 @@ network_time_tracker_ = tracker; } -#if BUILDFLAG(ENABLE_CAPTIVE_PORTAL_DETECTION) +#if !defined(OS_IOS) void ConfigSingleton::SetErrorAssistantProto( std::unique_ptr<chrome_browser_ssl::SSLErrorAssistantConfig> proto) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); @@ -329,10 +362,17 @@ return; } error_assistant_proto_ = std::move(proto); + + mitm_software_regexes_ = LoadMITMSoftwareRegexes(*error_assistant_proto_); + +#if BUILDFLAG(ENABLE_CAPTIVE_PORTAL_DETECTION) captive_portal_spki_hashes_ = LoadCaptivePortalCertHashes(*error_assistant_proto_); +#endif // ENABLE_CAPTIVE_PORTAL_DETECTION } +#endif // OS_IOS +#if BUILDFLAG(ENABLE_CAPTIVE_PORTAL_DETECTION) bool ConfigSingleton::IsKnownCaptivePortalCert(const net::SSLInfo& ssl_info) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); if (!captive_portal_spki_hashes_) { @@ -355,6 +395,32 @@ } #endif +#if !defined(OS_IOS) +bool ConfigSingleton::CertContainsMITMSoftwareString( + const net::SSLInfo& ssl_info) { + // If the certificate doesn't have an issuer common name return false. + if (ssl_info.cert->issuer().common_name.empty()) { + return false; + } + + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + if (!mitm_software_regexes_) { + error_assistant_proto_ = ReadErrorAssistantProtoFromResourceBundle(); + DCHECK(error_assistant_proto_); + mitm_software_regexes_ = LoadMITMSoftwareRegexes(*error_assistant_proto_); + } + + // Compares the common name of the issuer of the certificate to our + // MITM software regexes. + for (const std::regex& regex : *mitm_software_regexes_) { + if (std::regex_match(ssl_info.cert->issuer().common_name, regex)) { + return true; + } + } + return false; +} +#endif + class SSLErrorHandlerDelegateImpl : public SSLErrorHandler::Delegate { public: SSLErrorHandlerDelegateImpl( @@ -387,6 +453,7 @@ void NavigateToSuggestedURL(const GURL& suggested_url) override; bool IsErrorOverridable() const override; void ShowCaptivePortalInterstitial(const GURL& landing_url) override; + void ShowMITMSoftwareInterstitial() override; void ShowSSLInterstitial() override; void ShowBadClockInterstitial(const base::Time& now, ssl_errors::ClockState clock_state) override; @@ -462,6 +529,24 @@ #endif } +void SSLErrorHandlerDelegateImpl::ShowMITMSoftwareInterstitial() { +#if !defined(OS_IOS) + // TODO(sperigo): Update this code to render the MITM software blocking + // page. For the first MITM software interstitial CL, I am not checking + // in any of the UI code. Therefore ShowMITMSoftwareInterstitial() + // currently renders the generic SSL interstitial. + (SSLBlockingPage::Create( + web_contents_, cert_error_, ssl_info_, request_url_, options_mask_, + base::Time::NowFromSystemTime(), std::move(ssl_cert_reporter_), + base::FeatureList::IsEnabled(kSuperfishInterstitial) && + IsSuperfish(ssl_info_.cert), + callback_)) + ->Show(); +#else + NOTREACHED(); +#endif +} + void SSLErrorHandlerDelegateImpl::ShowSSLInterstitial() { // Show SSL blocking page. The interstitial owns the blocking page. (SSLBlockingPage::Create( @@ -554,7 +639,7 @@ void SSLErrorHandler::SetErrorAssistantProto( std::unique_ptr<chrome_browser_ssl::SSLErrorAssistantConfig> config_proto) { -#if BUILDFLAG(ENABLE_CAPTIVE_PORTAL_DETECTION) +#if !defined(OS_IOS) g_config.Pointer()->SetErrorAssistantProto(std::move(config_proto)); #endif } @@ -591,12 +676,8 @@ return; } - const net::CertStatus non_name_mismatch_errors = - ssl_info_.cert_status ^ net::CERT_STATUS_COMMON_NAME_INVALID; const bool only_error_is_name_mismatch = - cert_error_ == net::ERR_CERT_COMMON_NAME_INVALID && - (!net::IsCertStatusError(non_name_mismatch_errors) || - net::IsCertStatusMinorError(ssl_info_.cert_status)); + IsOnlyCertError(net::CERT_STATUS_COMMON_NAME_INVALID); #if BUILDFLAG(ENABLE_CAPTIVE_PORTAL_DETECTION) // Check known captive portal certificate list if the only error is @@ -613,6 +694,20 @@ } #endif +#if !defined(OS_IOS) + // The MITM software interstitial is displayed if and only if: + // - the error thrown is not overridable + // - the only certificate error is CERT_STATUS_AUTHORITY_INVALID + // - the certificate contains a string that indicates it was issued by a + // MITM software + if (IsMITMSoftwareInterstitialEnabled() && !delegate_->IsErrorOverridable() && + IsOnlyCertError(net::CERT_STATUS_AUTHORITY_INVALID) && + g_config.Pointer()->CertContainsMITMSoftwareString(ssl_info_)) { + ShowMITMSoftwareInterstitial(); + return; + } +#endif + if (IsSSLCommonNameMismatchHandlingEnabled() && cert_error_ == net::ERR_CERT_COMMON_NAME_INVALID && delegate_->IsErrorOverridable()) { @@ -688,6 +783,19 @@ #endif } +void SSLErrorHandler::ShowMITMSoftwareInterstitial() { +#if !defined(OS_IOS) + // Show SSL blocking page. The interstitial owns the blocking page. + RecordUMA(SHOW_MITM_SOFTWARE_INTERSTITIAL); + delegate_->ShowMITMSoftwareInterstitial(); + // Once an interstitial is displayed, no need to keep the handler around. + // This is the equivalent of "delete this". + web_contents_->RemoveUserData(UserDataKey()); +#else + NOTREACHED(); +#endif +} + void SSLErrorHandler::ShowSSLInterstitial() { // Show SSL blocking page. The interstitial owns the blocking page. RecordUMA(delegate_->IsErrorOverridable() @@ -822,3 +930,20 @@ } ShowSSLInterstitial(); } + +// Returns true if |only_cert_error_expected| is the only error code present in +// the certificate. The parameter |only_cert_error_expected| is a +// net::CertStatus code representing the most serious error identified on the +// certificate. For example, this could be net::CERT_STATUS_COMMON_NAME_INVALID. +// This function is useful for rendering interstitials that are triggered by one +// specific error code only. +bool SSLErrorHandler::IsOnlyCertError( + net::CertStatus only_cert_error_expected) const { + const net::CertStatus other_errors = + ssl_info_.cert_status ^ only_cert_error_expected; + + return cert_error_ == + net::MapCertStatusToNetError(only_cert_error_expected) && + (!net::IsCertStatusError(other_errors) || + net::IsCertStatusMinorError(ssl_info_.cert_status)); +}
diff --git a/chrome/browser/ssl/ssl_error_handler.h b/chrome/browser/ssl/ssl_error_handler.h index c1ae36c..b01cf0d 100644 --- a/chrome/browser/ssl/ssl_error_handler.h +++ b/chrome/browser/ssl/ssl_error_handler.h
@@ -78,6 +78,7 @@ SHOW_BAD_CLOCK = 8, CAPTIVE_PORTAL_CERT_FOUND = 9, WWW_MISMATCH_FOUND_IN_SAN = 10, + SHOW_MITM_SOFTWARE_INTERSTITIAL = 11, SSL_ERROR_HANDLER_EVENT_COUNT }; @@ -95,6 +96,7 @@ virtual void NavigateToSuggestedURL(const GURL& suggested_url) = 0; virtual bool IsErrorOverridable() const = 0; virtual void ShowCaptivePortalInterstitial(const GURL& landing_url) = 0; + virtual void ShowMITMSoftwareInterstitial() = 0; virtual void ShowSSLInterstitial() = 0; virtual void ShowBadClockInterstitial( const base::Time& now, @@ -152,6 +154,7 @@ private: void ShowCaptivePortalInterstitial(const GURL& landing_url); + void ShowMITMSoftwareInterstitial(); void ShowSSLInterstitial(); void ShowBadClockInterstitial(const base::Time& now, ssl_errors::ClockState clock_state); @@ -182,6 +185,8 @@ void HandleCertDateInvalidError(); void HandleCertDateInvalidErrorImpl(base::TimeTicks started_handling_error); + bool IsOnlyCertError(net::CertStatus only_cert_error_expected) const; + std::unique_ptr<Delegate> delegate_; content::WebContents* const web_contents_; Profile* const profile_;
diff --git a/chrome/browser/ssl/ssl_error_handler_unittest.cc b/chrome/browser/ssl/ssl_error_handler_unittest.cc index 43a34b4d..0b4013ae 100644 --- a/chrome/browser/ssl/ssl_error_handler_unittest.cc +++ b/chrome/browser/ssl/ssl_error_handler_unittest.cc
@@ -14,6 +14,7 @@ #include "base/test/simple_test_clock.h" #include "base/test/simple_test_tick_clock.h" #include "base/time/time.h" +#include "build/build_config.h" #include "chrome/browser/captive_portal/captive_portal_service.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ssl/common_name_mismatch_handler.h" @@ -47,6 +48,65 @@ const net::SHA256HashValue kCertPublicKeyHashValue = {{0x01, 0x02}}; +const char kOkayCertName[] = "ok_cert.pem"; + +// These certificates are self signed certificates with relevant issuer common +// names generated using the following openssl command: +// openssl req -new -x509 -keyout server.pem -out server.pem -days 365 -nodes +const char kOutdatedAntivirusCert[] = + "-----BEGIN CERTIFICATE-----\n" + "MIIEKzCCAxOgAwIBAgIJAKEHkWB4gBwRMA0GCSqGSIb3DQEBCwUAMIGrMQswCQYD\n" + "VQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNU2FuIEZyYW5j\n" + "aXNjbzEgMB4GA1UECgwXTWlzY29uZmlndXJlZCBBbnRpdmlydXMxLDAqBgNVBAMM\n" + "I01pc2NvbmZpZ3VyZWQgRmlyZXdhbGxfNEdIUE9TNTQxMkVGMR8wHQYJKoZIhvcN\n" + "AQkBFhB0ZXN0QGV4YW1wbGUuY29tMB4XDTE3MDgwOTA2MjQxMloXDTE4MDgwOTA2\n" + "MjQxMlowgasxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYD\n" + "VQQHDA1TYW4gRnJhbmNpc2NvMSAwHgYDVQQKDBdNaXNjb25maWd1cmVkIEFudGl2\n" + "aXJ1czEsMCoGA1UEAwwjTWlzY29uZmlndXJlZCBGaXJld2FsbF80R0hQT1M1NDEy\n" + "RUYxHzAdBgkqhkiG9w0BCQEWEHRlc3RAZXhhbXBsZS5jb20wggEiMA0GCSqGSIb3\n" + "DQEBAQUAA4IBDwAwggEKAoIBAQDJUkuPE7tJzTS1n2B8sPM/yUxRysJ3OgFGT2ah\n" + "X7O/SFujnbWngjJNeCd/5BFoWcvlNIvnCexgpmkwY7A2IF02lqloqpXUxDusshgx\n" + "CHWtpGJPsfQgBr/G+DuskDxstpZwL/U9ib/hfFH3BxacpIr67vP/phox5LilPL2x\n" + "K5++c1ky1m0nBV6tgQdHK6tNDzsUwDtLWQoastf/QpAHNQ4FwHeeMAS3MyIc4UrR\n" + "UY79jQM6pI/PvDvpIXAfR+p4FFrYQDqKANNUfL//AKoYxyLUmvLnmHDtFAyvJZDL\n" + "ET/owkPr97FF9tYrx4/yFKnTVlK1XLZtvMWfKf4dOKp6xXuPAgMBAAGjUDBOMB0G\n" + "A1UdDgQWBBRjVm9bd9WCEKU2moKxqG2Lb7AqADAfBgNVHSMEGDAWgBRjVm9bd9WC\n" + "EKU2moKxqG2Lb7AqADAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQBo\n" + "Xes5dVRP336D6Hhna5S/y5rEz/GHgksljszTUMFQoUpsG+NHH/4PV85JQHv/+qgd\n" + "CcBug8i7C63Uvgex6dhPfiyOp1/EEdqQ+WCTCtuZuTGidEAAIHwC1RpcDlVZ46pM\n" + "aZyvRJcR+9axQ8KKvuJcgQQpYi3eqC/j9oaGP9O+qHKvcp94SvwRjgBsEEkcsaA5\n" + "4KE5UtzJg5+e4suG+GTKkE51LCGnP62/qaMujrxdVv6on1oDrGmGW0ro05gM+GiX\n" + "CbMn1qQ7+wn+sESgR45HnqhlWpTYL12tRVnDdJPupqkihr8nwV5+uR0C5CG0pIJ+\n" + "Sv4GFvNvKocwCQBPb/Hd\n" + "-----END CERTIFICATE-----"; + +const char kMisconfiguredFirewallCert[] = + "-----BEGIN CERTIFICATE-----\n" + "MIIEJTCCAw2gAwIBAgIJAO0EVfP6VLU9MA0GCSqGSIb3DQEBCwUAMIGoMQswCQYD\n" + "VQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNU2FuIEZyYW5j\n" + "aXNjbzEfMB0GA1UECgwWTWlzY29uZmlndXJlZCBGaXJld2FsbDEqMCgGA1UEAwwh\n" + "TWlzY29uZmlndXJlZCBGaXJld2FsbF8xR0gzNUZJTzMyMR8wHQYJKoZIhvcNAQkB\n" + "FhB0ZXN0QGV4YW1wbGUuY29tMB4XDTE3MDgwOTE3NDgxNloXDTE4MDgwOTE3NDgx\n" + "NlowgagxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQH\n" + "DA1TYW4gRnJhbmNpc2NvMR8wHQYDVQQKDBZNaXNjb25maWd1cmVkIEZpcmV3YWxs\n" + "MSowKAYDVQQDDCFNaXNjb25maWd1cmVkIEZpcmV3YWxsXzFHSDM1RklPMzIxHzAd\n" + "BgkqhkiG9w0BCQEWEHRlc3RAZXhhbXBsZS5jb20wggEiMA0GCSqGSIb3DQEBAQUA\n" + "A4IBDwAwggEKAoIBAQDXazq1NGo2TOr7OIFi14KnBBBA9rJ3HXH78/gDUj7B+/ji\n" + "EB2+j1tNtdPHf7uaz0O6X3PKDeed5GV+C37khr7J+12NkIQqH2TdpXZ1rHvbjV8D\n" + "L/NUERwoGR0+xKS9cQdMYHGyUzPkOeTg+/UKQGpeUGfFbWJVPyxjIGZ1GFKkzstX\n" + "CLMv9lKFgU9Q0b6WNRyfvMt7ofTxkUuyTgzoN/M2WRzj8PPczYGhopsMIpQie8c5\n" + "ziX3VQTKTPyEVwAat7uNVaKi8nza02hEahGFvv5oUiyi1dVfsSCDvzL9IeNtvO1w\n" + "G/ooZrfqBsH45oa7kigzntwnsf0fb7Op0S1RDPnDAgMBAAGjUDBOMB0GA1UdDgQW\n" + "BBTkWcrjWP6EivGW0GdJbZikRh/AZTAfBgNVHSMEGDAWgBTkWcrjWP6EivGW0GdJ\n" + "bZikRh/AZTAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQA1ZSnE+ntm\n" + "2KTfmT3Xj9cWezTPWD2kc+tVSfuFCNqFBlZE586wmmlPXzkiI3UTOs0BJvoIEZYb\n" + "yiuJW3xPe9ZVsL8y8d8z1miUIcYt1EVpoF3CxPWI0iilXoF/6GbDtmdzFk990fSO\n" + "oGjq1Zadc4E/wxkHcYChlkIUG94WemkFRBcYmabxDJOgEGK+KDI/2cy5OlqZReBM\n" + "o82wrUg88gNy2IdgT7LAh8nLoEwxDEE0nmawV7FXpJdEZzKlXrAidRtbrsC2hyDa\n" + "N/rrXaEJK0iLuDxeBH6d4cu+MSho5z2paevIJSIyX8SQfVFCwjTEqf06OE02a94T\n" + "D+5GEBRIUV20\n" + "-----END CERTIFICATE-----"; + // Runs |quit_closure| on the UI thread once a URL request has been // seen. Returns a request that hangs. std::unique_ptr<net::test_server::HttpResponse> WaitForRequest( @@ -91,6 +151,7 @@ ssl_interstitial_shown_(false), bad_clock_interstitial_shown_(false), captive_portal_interstitial_shown_(false), + mitm_software_interstitial_shown_(false), redirected_to_suggested_url_(false), is_overridable_error_(true) {} @@ -116,6 +177,9 @@ int captive_portal_interstitial_shown() const { return captive_portal_interstitial_shown_; } + int mitm_software_interstitial_shown() const { + return mitm_software_interstitial_shown_; + } bool bad_clock_interstitial_shown() const { return bad_clock_interstitial_shown_; } @@ -134,6 +198,7 @@ ssl_interstitial_shown_ = false; bad_clock_interstitial_shown_ = false; captive_portal_interstitial_shown_ = false; + mitm_software_interstitial_shown_ = false; redirected_to_suggested_url_ = false; } @@ -161,6 +226,10 @@ captive_portal_interstitial_shown_ = true; } + void ShowMITMSoftwareInterstitial() override { + mitm_software_interstitial_shown_ = true; + } + void CheckSuggestedUrl( const GURL& suggested_url, const CommonNameMismatchHandler::CheckUrlCallback& callback) override { @@ -182,6 +251,7 @@ bool ssl_interstitial_shown_; bool bad_clock_interstitial_shown_; bool captive_portal_interstitial_shown_; + bool mitm_software_interstitial_shown_; bool redirected_to_suggested_url_; bool is_overridable_error_; CommonNameMismatchHandler::CheckUrlCallback suggested_url_callback_; @@ -264,16 +334,16 @@ // A class to test the captive portal certificate list feature. Creates an error // handler with a name mismatch error by default. The error handler can be // recreated by calling ResetErrorHandler() with an appropriate cert status. -class SSLErrorHandlerCaptivePortalCertListTest - : public ChromeRenderViewHostTestHarness { +class SSLErrorAssistantTest : public ChromeRenderViewHostTestHarness { public: - SSLErrorHandlerCaptivePortalCertListTest() : field_trial_list_(nullptr) {} + SSLErrorAssistantTest() : field_trial_list_(nullptr) {} void SetUp() override { ChromeRenderViewHostTestHarness::SetUp(); SSLErrorHandler::ResetConfigForTesting(); SSLErrorHandler::SetInterstitialDelayForTesting(base::TimeDelta()); - ResetErrorHandler(net::CERT_STATUS_COMMON_NAME_INVALID); + ResetErrorHandlerFromFile(kOkayCertName, + net::CERT_STATUS_COMMON_NAME_INVALID); } void TearDown() override { @@ -289,7 +359,7 @@ const net::SSLInfo& ssl_info() { return ssl_info_; } protected: - void SetFeatureEnabled(bool enabled) { + void SetCaptivePortalFeatureEnabled(bool enabled) { if (enabled) { scoped_feature_list_.InitFromCommandLine( "CaptivePortalCertificateList" /* enabled */, @@ -300,36 +370,37 @@ } } - // Deletes the current error handler and creates a new one with the given - // |cert_status|. - void ResetErrorHandler(net::CertStatus cert_status) { - ssl_info_.Reset(); - ssl_info_.cert = - net::ImportCertFromFile(net::GetTestCertsDirectory(), "ok_cert.pem"); - ssl_info_.cert_status = cert_status; - ssl_info_.public_key_hashes.push_back( - net::HashValue(kCertPublicKeyHashValue)); - - delegate_ = - new TestSSLErrorHandlerDelegate(profile(), web_contents(), ssl_info_); - error_handler_.reset(new TestSSLErrorHandler( - std::unique_ptr<SSLErrorHandler::Delegate>(delegate_), web_contents(), - profile(), net::MapCertStatusToNetError(ssl_info_.cert_status), - ssl_info_, - GURL(), // request_url - base::Callback<void(content::CertificateRequestResultType)>())); - - // Enable finch experiment for captive portal interstitials. - ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial( - "CaptivePortalInterstitial", "Enabled")); - // Enable finch experiment for SSL common name mismatch handling. - ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial( - "SSLCommonNameMismatchHandling", "Enabled")); + void SetMITMSoftwareFeatureEnabled(bool enabled) { + if (enabled) { + scoped_feature_list_.InitFromCommandLine( + "MITMSoftwareInterstitial" /* enabled */, + std::string() /* disabled */); + } else { + scoped_feature_list_.InitFromCommandLine( + std::string(), "MITMSoftwareInterstitial" /* disabled */); + } } - void TestNoCaptivePortalInterstitial() { - base::HistogramTester histograms; + void ResetErrorHandlerFromString(const std::string& cert_data, + net::CertStatus cert_status) { + net::CertificateList certs = + net::X509Certificate::CreateCertificateListFromBytes( + cert_data.data(), cert_data.size(), + net::X509Certificate::FORMAT_AUTO); + ASSERT_FALSE(certs.empty()); + ResetErrorHandler(certs[0], cert_status); + } + void ResetErrorHandlerFromFile(const std::string& cert_name, + net::CertStatus cert_status) { + ResetErrorHandler( + net::ImportCertFromFile(net::GetTestCertsDirectory(), cert_name), + cert_status); + } + + // Set up an error assistant proto with mock captive portal hash data and + // begin handling the certificate error. + void RunCaptivePortalTest() { EXPECT_FALSE(error_handler()->IsTimerRunningForTesting()); EXPECT_EQ(1u, ssl_info().public_key_hashes.size()); @@ -344,6 +415,12 @@ SSLErrorHandler::SetErrorAssistantProto(std::move(config_proto)); error_handler()->StartHandlingError(); + } + + void TestNoCaptivePortalInterstitial() { + base::HistogramTester histograms; + + RunCaptivePortalTest(); // Timer should start for captive portal detection. EXPECT_TRUE(error_handler()->IsTimerRunningForTesting()); @@ -370,17 +447,109 @@ SSLErrorHandler::SHOW_SSL_INTERSTITIAL_OVERRIDABLE, 1); } + // Set up a mock SSL Error Assistant config with regexes that match the + // outdated antivirus and misconfigured firewall certificate. + void InitMITMSoftwareList() { + auto config_proto = + base::MakeUnique<chrome_browser_ssl::SSLErrorAssistantConfig>(); + chrome_browser_ssl::MITMSoftware* filter1 = + config_proto->add_mitm_software(); + filter1->set_name("Outdated Antivirus"); + filter1->set_regex("Outdated Antivirus"); + + chrome_browser_ssl::MITMSoftware* filter2 = + config_proto->add_mitm_software(); + filter2->set_name("Misconfigured Firewall"); + filter2->set_regex("Misconfigured Firewall_[A-Z0-9]+"); + SSLErrorHandler::SetErrorAssistantProto(std::move(config_proto)); + } + + // Calls RunMITMSoftwareTest() to set up an error assistant proto with mock + // MITM software strings and start handling the SSL error. Check that the + // generic interstitial was not shown, and the MITM software interstitial + // was. Check the UMA histograms. + void TestMITMSoftwareInterstitial() { + base::HistogramTester histograms; + + InitMITMSoftwareList(); + error_handler()->StartHandlingError(); + base::RunLoop().RunUntilIdle(); + + EXPECT_FALSE(delegate()->ssl_interstitial_shown()); + EXPECT_TRUE(delegate()->mitm_software_interstitial_shown()); + EXPECT_FALSE(delegate()->suggested_url_checked()); + + histograms.ExpectTotalCount(SSLErrorHandler::GetHistogramNameForTesting(), + 2); + histograms.ExpectBucketCount(SSLErrorHandler::GetHistogramNameForTesting(), + SSLErrorHandler::HANDLE_ALL, 1); + histograms.ExpectBucketCount( + SSLErrorHandler::GetHistogramNameForTesting(), + SSLErrorHandler::SHOW_SSL_INTERSTITIAL_NONOVERRIDABLE, 0); + histograms.ExpectBucketCount( + SSLErrorHandler::GetHistogramNameForTesting(), + SSLErrorHandler::SHOW_SSL_INTERSTITIAL_OVERRIDABLE, 0); + histograms.ExpectBucketCount( + SSLErrorHandler::GetHistogramNameForTesting(), + SSLErrorHandler::SHOW_MITM_SOFTWARE_INTERSTITIAL, 1); + } + + // Calls RunMITMSoftwareTest() to set up an error assistant proto with mock + // MITM software strings and start handling the SSL error. Check that the + // MITM software interstitial is not shown, and a nonoverridable generic SSL + // interstitial is shown in its place. Check UMA histograms. + void TestNoMITMSoftwareInterstitial() { + base::HistogramTester histograms; + + InitMITMSoftwareList(); + error_handler()->StartHandlingError(); + base::RunLoop().RunUntilIdle(); + + EXPECT_FALSE(error_handler()->IsTimerRunningForTesting()); + EXPECT_TRUE(delegate()->ssl_interstitial_shown()); + EXPECT_FALSE(delegate()->mitm_software_interstitial_shown()); + EXPECT_FALSE(delegate()->suggested_url_checked()); + + histograms.ExpectTotalCount(SSLErrorHandler::GetHistogramNameForTesting(), + 2); + histograms.ExpectBucketCount(SSLErrorHandler::GetHistogramNameForTesting(), + SSLErrorHandler::HANDLE_ALL, 1); + histograms.ExpectBucketCount( + SSLErrorHandler::GetHistogramNameForTesting(), + SSLErrorHandler::SHOW_SSL_INTERSTITIAL_NONOVERRIDABLE, 1); + histograms.ExpectBucketCount( + SSLErrorHandler::GetHistogramNameForTesting(), + SSLErrorHandler::SHOW_MITM_SOFTWARE_INTERSTITIAL, 0); + } + private: + void ResetErrorHandler(scoped_refptr<net::X509Certificate> cert, + net::CertStatus cert_status) { + ssl_info_.Reset(); + ssl_info_.cert = cert; + ssl_info_.cert_status = cert_status; + ssl_info_.public_key_hashes.push_back( + net::HashValue(kCertPublicKeyHashValue)); + + delegate_ = + new TestSSLErrorHandlerDelegate(profile(), web_contents(), ssl_info_); + error_handler_.reset(new TestSSLErrorHandler( + std::unique_ptr<SSLErrorHandler::Delegate>(delegate_), web_contents(), + profile(), net::MapCertStatusToNetError(ssl_info_.cert_status), + ssl_info_, + GURL(), // request_url + base::Callback<void(content::CertificateRequestResultType)>())); + } + net::SSLInfo ssl_info_; std::unique_ptr<TestSSLErrorHandler> error_handler_; TestSSLErrorHandlerDelegate* delegate_; base::FieldTrialList field_trial_list_; base::test::ScopedFeatureList scoped_feature_list_; - DISALLOW_COPY_AND_ASSIGN(SSLErrorHandlerCaptivePortalCertListTest); + DISALLOW_COPY_AND_ASSIGN(SSLErrorAssistantTest); }; - class SSLErrorHandlerDateInvalidTest : public ChromeRenderViewHostTestHarness { public: SSLErrorHandlerDateInvalidTest() @@ -858,24 +1027,12 @@ // Tests that a certificate marked as a known captive portal certificate causes // the captive portal interstitial to be shown. -TEST_F(SSLErrorHandlerCaptivePortalCertListTest, Enabled) { - SetFeatureEnabled(true); - - EXPECT_FALSE(error_handler()->IsTimerRunningForTesting()); - EXPECT_EQ(1u, ssl_info().public_key_hashes.size()); - - auto config_proto = - base::MakeUnique<chrome_browser_ssl::SSLErrorAssistantConfig>(); - config_proto->add_captive_portal_cert()->set_sha256_hash( - "sha256/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"); - config_proto->add_captive_portal_cert()->set_sha256_hash( - ssl_info().public_key_hashes[0].ToString()); - config_proto->add_captive_portal_cert()->set_sha256_hash( - "sha256/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"); - SSLErrorHandler::SetErrorAssistantProto(std::move(config_proto)); +TEST_F(SSLErrorAssistantTest, CaptivePortal_FeatureEnabled) { + SetCaptivePortalFeatureEnabled(true); base::HistogramTester histograms; - error_handler()->StartHandlingError(); + + RunCaptivePortalTest(); // Timer shouldn't start for a known captive portal certificate. EXPECT_FALSE(error_handler()->IsTimerRunningForTesting()); @@ -908,8 +1065,8 @@ // Tests that a certificate marked as a known captive portal certificate does // not cause the captive portal interstitial to be shown, if the feature is // disabled. -TEST_F(SSLErrorHandlerCaptivePortalCertListTest, Disabled) { - SetFeatureEnabled(false); +TEST_F(SSLErrorAssistantTest, CaptivePortal_FeatureDisabled) { + SetCaptivePortalFeatureEnabled(false); // Default error for SSLErrorHandlerNameMismatchTest tests is name mismatch. TestNoCaptivePortalInterstitial(); @@ -918,10 +1075,11 @@ // Tests that an error other than name mismatch does not cause a captive portal // interstitial to be shown, even if the certificate is marked as a known // captive portal certificate. -TEST_F(SSLErrorHandlerCaptivePortalCertListTest, AuthorityInvalid) { - SetFeatureEnabled(true); +TEST_F(SSLErrorAssistantTest, + CaptivePortal_AuthorityInvalidError_NoInterstitial) { + SetCaptivePortalFeatureEnabled(true); - ResetErrorHandler(net::CERT_STATUS_AUTHORITY_INVALID); + ResetErrorHandlerFromFile(kOkayCertName, net::CERT_STATUS_AUTHORITY_INVALID); TestNoCaptivePortalInterstitial(); } @@ -929,16 +1087,15 @@ // not cause a captive portal interstitial to be shown, even if the certificate // is marked as a known captive portal certificate. The resulting error is // authority-invalid. -TEST_F(SSLErrorHandlerCaptivePortalCertListTest, - NameMismatchAndAuthorityInvalid) { - SetFeatureEnabled(true); +TEST_F(SSLErrorAssistantTest, CaptivePortal_TwoErrors_NoInterstitial) { + SetCaptivePortalFeatureEnabled(true); const net::CertStatus cert_status = net::CERT_STATUS_COMMON_NAME_INVALID | net::CERT_STATUS_AUTHORITY_INVALID; // Sanity check that AUTHORITY_INVALID is seen as the net error. ASSERT_EQ(net::ERR_CERT_AUTHORITY_INVALID, net::MapCertStatusToNetError(cert_status)); - ResetErrorHandler(cert_status); + ResetErrorHandlerFromFile(kOkayCertName, cert_status); TestNoCaptivePortalInterstitial(); } @@ -946,8 +1103,9 @@ // captive portal interstitial to be shown, even if the certificate is marked as // a known captive portal certificate. Similar to // NameMismatchAndAuthorityInvalid, except the resulting error is name mismatch. -TEST_F(SSLErrorHandlerCaptivePortalCertListTest, NameMismatchAndWeakKey) { - SetFeatureEnabled(true); +TEST_F(SSLErrorAssistantTest, + CaptivePortal_TwoErrorsIncludingNameMismatch_NoInterstitial) { + SetCaptivePortalFeatureEnabled(true); const net::CertStatus cert_status = net::CERT_STATUS_COMMON_NAME_INVALID | net::CERT_STATUS_WEAK_KEY; @@ -956,34 +1114,21 @@ // CertStatus even when COMMON_NAME_INVALID is the net error. ASSERT_EQ(net::ERR_CERT_COMMON_NAME_INVALID, net::MapCertStatusToNetError(cert_status)); - ResetErrorHandler(cert_status); + ResetErrorHandlerFromFile(kOkayCertName, cert_status); TestNoCaptivePortalInterstitial(); } #else -TEST_F(SSLErrorHandlerCaptivePortalCertListTest, DisabledByBuild) { - SetFeatureEnabled(true); +TEST_F(SSLErrorAssistantTest, CaptivePortal_DisabledByBuild) { + SetCaptivePortalFeatureEnabled(true); // Default error for SSLErrorHandlerNameMismatchTest tests is name mismatch, // but the feature is disabled by build so a generic SSL interstitial will be // displayed. base::HistogramTester histograms; - EXPECT_FALSE(error_handler()->IsTimerRunningForTesting()); - EXPECT_EQ(1u, ssl_info().public_key_hashes.size()); - - auto config_proto = - base::MakeUnique<chrome_browser_ssl::SSLErrorAssistantConfig>(); - config_proto->add_captive_portal_cert()->set_sha256_hash( - "sha256/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"); - config_proto->add_captive_portal_cert()->set_sha256_hash( - ssl_info().public_key_hashes[0].ToString()); - config_proto->add_captive_portal_cert()->set_sha256_hash( - "sha256/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"); - SSLErrorHandler::SetErrorAssistantProto(std::move(config_proto)); - - error_handler()->StartHandlingError(); + RunCaptivePortalTest(); EXPECT_FALSE(error_handler()->IsTimerRunningForTesting()); EXPECT_FALSE(delegate()->captive_portal_checked()); @@ -1008,3 +1153,111 @@ } #endif // BUILDFLAG(ENABLE_CAPTIVE_PORTAL_DETECTION) + +#if !defined(OS_IOS) + +TEST_F(SSLErrorAssistantTest, MITMSoftware_OutdatedAntivirusCertificate) { + SetMITMSoftwareFeatureEnabled(true); + + ResetErrorHandlerFromString(kOutdatedAntivirusCert, + net::CERT_STATUS_AUTHORITY_INVALID); + delegate()->set_non_overridable_error(); + + TestMITMSoftwareInterstitial(); +} + +TEST_F(SSLErrorAssistantTest, MITMSoftware_MisconfiguredFirewallCertificate) { + SetMITMSoftwareFeatureEnabled(true); + + ResetErrorHandlerFromString(kMisconfiguredFirewallCert, + net::CERT_STATUS_AUTHORITY_INVALID); + delegate()->set_non_overridable_error(); + + TestMITMSoftwareInterstitial(); +} + +TEST_F(SSLErrorAssistantTest, MITMSoftware_FeatureDisabled) { + SetMITMSoftwareFeatureEnabled(false); + + ResetErrorHandlerFromString(kOutdatedAntivirusCert, + net::CERT_STATUS_AUTHORITY_INVALID); + delegate()->set_non_overridable_error(); + + TestNoMITMSoftwareInterstitial(); +} + +TEST_F(SSLErrorAssistantTest, + MITMSoftware_NonMatchingCertificate_NoInterstitial) { + SetMITMSoftwareFeatureEnabled(true); + + ResetErrorHandlerFromFile(kOkayCertName, net::CERT_STATUS_AUTHORITY_INVALID); + delegate()->set_non_overridable_error(); + + TestNoMITMSoftwareInterstitial(); +} + +TEST_F(SSLErrorAssistantTest, MITMSoftware_WrongError_NoInterstitial) { + SetMITMSoftwareFeatureEnabled(true); + + ResetErrorHandlerFromString(kOutdatedAntivirusCert, + net::CERT_STATUS_COMMON_NAME_INVALID); + delegate()->set_non_overridable_error(); + + TestNoMITMSoftwareInterstitial(); +} + +TEST_F(SSLErrorAssistantTest, MITMSoftware_TwoErrors_NoInterstitial) { + SetMITMSoftwareFeatureEnabled(true); + + ResetErrorHandlerFromString(kOutdatedAntivirusCert, + net::CERT_STATUS_AUTHORITY_INVALID | + net::CERT_STATUS_COMMON_NAME_INVALID); + delegate()->set_non_overridable_error(); + + TestNoMITMSoftwareInterstitial(); +} + +TEST_F(SSLErrorAssistantTest, MITMSoftware_Overridable_NoInterstitial) { + base::HistogramTester histograms; + + SetMITMSoftwareFeatureEnabled(true); + ResetErrorHandlerFromString(kOutdatedAntivirusCert, + net::CERT_STATUS_AUTHORITY_INVALID); + + // Don't use the TestNoMITMSoftwareInterstitial helper here because it + // checks the histograms for a nonoverridable SSL error. + InitMITMSoftwareList(); + error_handler()->StartHandlingError(); + base::RunLoop().RunUntilIdle(); + + EXPECT_TRUE(delegate()->ssl_interstitial_shown()); + EXPECT_FALSE(delegate()->mitm_software_interstitial_shown()); + EXPECT_FALSE(delegate()->suggested_url_checked()); + + histograms.ExpectTotalCount(SSLErrorHandler::GetHistogramNameForTesting(), 2); + histograms.ExpectBucketCount(SSLErrorHandler::GetHistogramNameForTesting(), + SSLErrorHandler::HANDLE_ALL, 1); + histograms.ExpectBucketCount( + SSLErrorHandler::GetHistogramNameForTesting(), + SSLErrorHandler::SHOW_SSL_INTERSTITIAL_NONOVERRIDABLE, 0); + histograms.ExpectBucketCount( + SSLErrorHandler::GetHistogramNameForTesting(), + SSLErrorHandler::SHOW_SSL_INTERSTITIAL_OVERRIDABLE, 1); + histograms.ExpectBucketCount(SSLErrorHandler::GetHistogramNameForTesting(), + SSLErrorHandler::SHOW_MITM_SOFTWARE_INTERSTITIAL, + 0); +} + +#else + +TEST_F(SSLErrorAssistantTest, MITMSoftware_DisabledByBuild_NoInterstitial) { + SetMITMSoftwareFeatureEnabled(true); + + ResetErrorHandlerFromString(kOutdatedAntivirusCert, + net::CERT_STATUS_AUTHORITY_INVALID); + delegate()->set_non_overridable_error(); + + TestNoMITMSoftwareInterstitial(); +} + +#endif // #if !defined(OS_IOS)
diff --git a/chrome/browser/sync/test/integration/single_client_user_events_sync_test.cc b/chrome/browser/sync/test/integration/single_client_user_events_sync_test.cc index 809f704..de68d07 100644 --- a/chrome/browser/sync/test/integration/single_client_user_events_sync_test.cc +++ b/chrome/browser/sync/test/integration/single_client_user_events_sync_test.cc
@@ -4,8 +4,11 @@ #include "base/macros.h" #include "base/time/time.h" +#include "chrome/browser/sync/test/integration/profile_sync_service_harness.h" +#include "chrome/browser/sync/test/integration/sessions_helper.cc" #include "chrome/browser/sync/test/integration/single_client_status_change_checker.h" #include "chrome/browser/sync/test/integration/status_change_checker.h" +#include "chrome/browser/sync/test/integration/sync_integration_test_util.h" #include "chrome/browser/sync/test/integration/sync_test.h" #include "chrome/browser/sync/user_event_service_factory.h" #include "components/sync/protocol/user_event_specifics.pb.h" @@ -122,7 +125,7 @@ GetFakeServer()->GetSyncEntitiesByModelType(syncer::USER_EVENTS).size()); syncer::UserEventService* event_service = browser_sync::UserEventServiceFactory::GetForProfile(GetProfile(0)); - UserEventSpecifics specifics = CreateEvent(0); + const UserEventSpecifics specifics = CreateEvent(0); event_service->RecordUserEvent(specifics); UserEventEqualityChecker(GetSyncService(0), GetFakeServer(), {specifics}) .Wait(); @@ -130,8 +133,8 @@ IN_PROC_BROWSER_TEST_F(SingleClientUserEventsSyncTest, RetrySequential) { ASSERT_TRUE(SetupSync()); - UserEventSpecifics specifics1 = CreateEvent(1); - UserEventSpecifics specifics2 = CreateEvent(2); + const UserEventSpecifics specifics1 = CreateEvent(1); + const UserEventSpecifics specifics2 = CreateEvent(2); syncer::UserEventService* event_service = browser_sync::UserEventServiceFactory::GetForProfile(GetProfile(0)); @@ -162,8 +165,8 @@ IN_PROC_BROWSER_TEST_F(SingleClientUserEventsSyncTest, RetryParallel) { ASSERT_TRUE(SetupSync()); bool first = true; - UserEventSpecifics specifics1 = CreateEvent(1); - UserEventSpecifics specifics2 = CreateEvent(2); + const UserEventSpecifics specifics1 = CreateEvent(1); + const UserEventSpecifics specifics2 = CreateEvent(2); UserEventSpecifics retry_specifics; syncer::UserEventService* event_service = @@ -185,4 +188,63 @@ .Wait(); } +IN_PROC_BROWSER_TEST_F(SingleClientUserEventsSyncTest, NoHistory) { + const UserEventSpecifics specifics1 = CreateEvent(1); + const UserEventSpecifics specifics2 = CreateEvent(2); + const UserEventSpecifics specifics3 = CreateEvent(3); + ASSERT_TRUE(SetupSync()); + syncer::UserEventService* event_service = + browser_sync::UserEventServiceFactory::GetForProfile(GetProfile(0)); + + event_service->RecordUserEvent(specifics1); + ASSERT_TRUE(GetClient(0)->DisableSyncForDatatype(syncer::TYPED_URLS)); + event_service->RecordUserEvent(specifics2); + ASSERT_TRUE(GetClient(0)->EnableSyncForDatatype(syncer::TYPED_URLS)); + event_service->RecordUserEvent(specifics3); + + // No |specifics2| because it was recorded while history was disabled. + UserEventEqualityChecker(GetSyncService(0), GetFakeServer(), + {specifics1, specifics3}) + .Wait(); +} + +IN_PROC_BROWSER_TEST_F(SingleClientUserEventsSyncTest, NoSessions) { + const UserEventSpecifics specifics = CreateEvent(1); + ASSERT_TRUE(SetupSync()); + ASSERT_TRUE(GetClient(0)->DisableSyncForDatatype(syncer::PROXY_TABS)); + syncer::UserEventService* event_service = + browser_sync::UserEventServiceFactory::GetForProfile(GetProfile(0)); + + event_service->RecordUserEvent(specifics); + + // PROXY_TABS shouldn't affect us in any way. + UserEventEqualityChecker(GetSyncService(0), GetFakeServer(), {specifics}) + .Wait(); +} + +IN_PROC_BROWSER_TEST_F(SingleClientUserEventsSyncTest, Encryption) { + const UserEventSpecifics specifics1 = CreateEvent(1); + const UserEventSpecifics specifics2 = CreateEvent(2); + const GURL url("http://www.one.com/"); + + ASSERT_TRUE(SetupSync()); + syncer::UserEventService* event_service = + browser_sync::UserEventServiceFactory::GetForProfile(GetProfile(0)); + event_service->RecordUserEvent(specifics1); + ASSERT_TRUE(EnableEncryption(0)); + UserEventEqualityChecker(GetSyncService(0), GetFakeServer(), {specifics1}) + .Wait(); + event_service->RecordUserEvent(specifics2); + + // Just checking that we don't see specifics2 isn't very convincing yet, + // because it may simply not have reached the server yet. So lets send + // something else through the system that we can wait on before checking. + // Tab/SESSIONS data was picked fairly arbitrarily, note that we expect 2 + // entries, one for the window/header and one for the tab. + sessions_helper::OpenTab(0, url); + ServerCountMatchStatusChecker(syncer::SESSIONS, 2); + UserEventEqualityChecker(GetSyncService(0), GetFakeServer(), {specifics1}) + .Wait(); +} + } // namespace
diff --git a/chrome/browser/ui/app_list/search/arc/arc_playstore_search_provider.cc b/chrome/browser/ui/app_list/search/arc/arc_playstore_search_provider.cc index f2894ac..fc95abb4 100644 --- a/chrome/browser/ui/app_list/search/arc/arc_playstore_search_provider.cc +++ b/chrome/browser/ui/app_list/search/arc/arc_playstore_search_provider.cc
@@ -9,13 +9,31 @@ #include "base/metrics/histogram_macros.h" #include "base/strings/utf_string_conversions.h" #include "base/time/time.h" +#include "chrome/browser/chromeos/extensions/gfx_utils.h" +#include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/app_list/arc/arc_app_list_prefs.h" #include "chrome/browser/ui/app_list/search/arc/arc_playstore_search_result.h" #include "components/arc/arc_bridge_service.h" #include "components/arc/arc_service_manager.h" namespace { -constexpr int kHistogramBuckets = 7; +constexpr int kHistogramBuckets = 13; + +// Skips Play Store apps that have equivalent extensions installed. +// Do not skip recent instant apps since they should be treated like +// on-device apps. +bool CanSkipSearchResult(content::BrowserContext* context, + const arc::mojom::AppDiscoveryResult& result) { + if (result.is_instant_app && result.is_recent) + return false; + + if (!result.package_name.has_value()) + return false; + + return !extensions::util::GetEquivalentInstalledExtensions( + context, result.package_name.value()) + .empty(); +} } // namespace namespace app_list { @@ -27,7 +45,9 @@ : max_results_(max_results), profile_(profile), list_controller_(list_controller), - weak_ptr_factory_(this) {} + weak_ptr_factory_(this) { + DCHECK_EQ(kHistogramBuckets, max_results + 1); +} ArcPlayStoreSearchProvider::~ArcPlayStoreSearchProvider() = default; @@ -67,6 +87,10 @@ for (auto& result : results) { if (result->is_instant_app) ++instant_app_count; + + if (CanSkipSearchResult(profile_, *result)) + continue; + new_results.emplace_back(base::MakeUnique<ArcPlayStoreSearchResult>( std::move(result), profile_, list_controller_)); }
diff --git a/chrome/browser/ui/app_list/search/arc/arc_playstore_search_provider_unittest.cc b/chrome/browser/ui/app_list/search/arc/arc_playstore_search_provider_unittest.cc index 3931883..e2ec5a8 100644 --- a/chrome/browser/ui/app_list/search/arc/arc_playstore_search_provider_unittest.cc +++ b/chrome/browser/ui/app_list/search/arc/arc_playstore_search_provider_unittest.cc
@@ -10,11 +10,14 @@ #include "base/macros.h" #include "base/strings/utf_string_conversions.h" +#include "chrome/browser/extensions/extension_service.h" #include "chrome/browser/ui/app_list/app_list_test_util.h" #include "chrome/browser/ui/app_list/arc/arc_app_test.h" #include "chrome/browser/ui/app_list/search/arc/arc_playstore_search_result.h" #include "chrome/browser/ui/app_list/test/test_app_list_controller_delegate.h" #include "chrome/test/base/testing_profile.h" +#include "extensions/common/extension_builder.h" +#include "extensions/common/value_builder.h" #include "ui/app_list/search_result.h" namespace app_list { @@ -43,6 +46,20 @@ max_results, profile_.get(), controller_.get()); } + scoped_refptr<extensions::Extension> CreateExtension(const std::string& id) { + return extensions::ExtensionBuilder() + .SetManifest(extensions::DictionaryBuilder() + .Set("name", "test") + .Set("version", "0.1") + .Build()) + .SetID(id) + .Build(); + } + + void AddExtension(const extensions::Extension* extension) { + service()->AddExtension(extension); + } + private: std::unique_ptr<test::TestAppListControllerDelegate> controller_; ArcAppTest arc_test_; @@ -51,7 +68,7 @@ }; TEST_F(ArcPlayStoreSearchProviderTest, Basic) { - constexpr size_t kMaxResults = 6; + constexpr size_t kMaxResults = 12; constexpr char kQuery[] = "Play App"; std::unique_ptr<ArcPlayStoreSearchProvider> provider = @@ -59,11 +76,15 @@ EXPECT_TRUE(provider->results().empty()); ArcPlayStoreSearchResult::DisableSafeDecodingForTesting(); + AddExtension(CreateExtension(extension_misc::kGmailAppId).get()); + // Check that the result size of a query doesn't exceed the |kMaxResults|. provider->Start(false, base::UTF8ToUTF16(kQuery)); const app_list::SearchProvider::Results& results = provider->results(); ASSERT_GT(results.size(), 0u); - ASSERT_GE(kMaxResults, results.size()); + // Play Store returns |kMaxResults| results, but the first one (GMail) already + // has Chrome extension installed, so it will be skipped. + ASSERT_EQ(kMaxResults - 1, results.size()); // Check that information is correctly set in each result. for (size_t i = 0; i < results.size(); ++i) {
diff --git a/chrome/browser/ui/app_list/search/search_controller_factory.cc b/chrome/browser/ui/app_list/search/search_controller_factory.cc index c1d0e5b..8bd8e2c 100644 --- a/chrome/browser/ui/app_list/search/search_controller_factory.cc +++ b/chrome/browser/ui/app_list/search/search_controller_factory.cc
@@ -44,7 +44,13 @@ constexpr size_t kMaxSuggestionsResults = 6; constexpr size_t kMaxLauncherSearchResults = 2; #if defined(OS_CHROMEOS) -constexpr size_t kMaxPlayStoreResults = 6; +// We show up to 6 Play Store results. However, part of Play Store results may +// be filtered out because they may correspond to already installed Web apps. So +// we request twice as many Play Store apps as we can show. Note that this still +// doesn't guarantee that all 6 positions will be filled, as we might in theory +// filter out more than half of results. +// TODO(753947): Consider progressive algorithm of getting Play Store results. +constexpr size_t kMaxPlayStoreResults = 12; #endif // Constants related to the SuggestionsService in AppList field trial.
diff --git a/chrome/browser/ui/ash/chrome_shell_delegate.cc b/chrome/browser/ui/ash/chrome_shell_delegate.cc index af9d1a5..04a9dba5 100644 --- a/chrome/browser/ui/ash/chrome_shell_delegate.cc +++ b/chrome/browser/ui/ash/chrome_shell_delegate.cc
@@ -15,6 +15,7 @@ #include "ash/accessibility_types.h" #include "ash/content/gpu_support_impl.h" #include "ash/shell.h" +#include "ash/system/tray/system_tray_controller.h" #include "ash/wallpaper/wallpaper_delegate.h" #include "ash/wm/mru_window_tracker.h" #include "ash/wm/window_state.h" @@ -73,9 +74,11 @@ #include "content/public/browser/media_session.h" #include "content/public/browser/notification_service.h" #include "content/public/common/service_manager_connection.h" +#include "content/public/common/url_constants.h" #include "ui/aura/window.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/resource/resource_bundle.h" +#include "url/url_constants.h" #if defined(USE_OZONE) #include "services/ui/public/cpp/input_devices/input_device_controller_client.h" @@ -468,6 +471,15 @@ url_to_open = arc::ArcUrlToExternalFileUrl(url_to_open); } + // If the url is for system settings, show the settings in a system tray + // instead of a browser tab. + if (url_to_open.GetContent() == "settings" && + (url_to_open.SchemeIs(url::kAboutScheme) || + url_to_open.SchemeIs(content::kChromeUIScheme))) { + ash::Shell::Get()->system_tray_controller()->ShowSettings(); + return; + } + chrome::ScopedTabbedBrowserDisplayer displayer( ProfileManager::GetActiveUserProfile()); chrome::AddSelectedTabWithURL(
diff --git a/chrome/browser/ui/ash/system_tray_delegate_chromeos.cc b/chrome/browser/ui/ash/system_tray_delegate_chromeos.cc index 7ccbf40..f400c2cb 100644 --- a/chrome/browser/ui/ash/system_tray_delegate_chromeos.cc +++ b/chrome/browser/ui/ash/system_tray_delegate_chromeos.cc
@@ -22,8 +22,6 @@ #include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/ui/ash/networking_config_delegate_chromeos.h" #include "chrome/browser/ui/ash/system_tray_client.h" -#include "chrome/browser/ui/browser.h" -#include "chrome/browser/ui/browser_list.h" #include "chrome/browser/ui/chrome_pages.h" #include "chrome/common/pref_names.h" #include "chrome/grit/generated_resources.h" @@ -37,11 +35,9 @@ namespace chromeos { SystemTrayDelegateChromeOS::SystemTrayDelegateChromeOS() - : networking_config_delegate_( + : registrar_(base::MakeUnique<content::NotificationRegistrar>()), + networking_config_delegate_( base::MakeUnique<NetworkingConfigDelegateChromeos>()) { - // Register notifications on construction so that events such as - // PROFILE_CREATED do not get missed if they happen before Initialize(). - registrar_.reset(new content::NotificationRegistrar); if (SystemTrayClient::GetUserLoginStatus() == ash::LoginStatus::NOT_LOGGED_IN) { registrar_->Add(this, @@ -62,10 +58,6 @@ base::Unretained(this))); } -void SystemTrayDelegateChromeOS::Initialize() { - BrowserList::AddObserver(this); -} - SystemTrayDelegateChromeOS::~SystemTrayDelegateChromeOS() { user_pref_registrar_.reset(); @@ -74,9 +66,6 @@ // Unregister a11y status subscription. accessibility_subscription_.reset(); - - BrowserList::RemoveObserver(this); - StopObservingAppWindowRegistry(); } ash::NetworkingConfigDelegate* @@ -93,14 +82,8 @@ } void SystemTrayDelegateChromeOS::SetProfile(Profile* profile) { - // Stop observing the AppWindowRegistry of the current |user_profile_|. - StopObservingAppWindowRegistry(); - user_profile_ = profile; - // Start observing the AppWindowRegistry of the newly set |user_profile_|. - extensions::AppWindowRegistry::Get(user_profile_)->AddObserver(this); - // TODO(jamescook): Move all these prefs into ash. See LogoutButtonTray for // an example of how to do this. PrefService* prefs = profile->GetPrefs(); @@ -128,40 +111,6 @@ return true; } -void SystemTrayDelegateChromeOS::StopObservingAppWindowRegistry() { - if (!user_profile_) - return; - - extensions::AppWindowRegistry* registry = - extensions::AppWindowRegistry::Factory::GetForBrowserContext( - user_profile_, false); - if (registry) - registry->RemoveObserver(this); -} - -void SystemTrayDelegateChromeOS::NotifyIfLastWindowClosed() { - if (!user_profile_) - return; - - BrowserList* browser_list = BrowserList::GetInstance(); - for (BrowserList::const_iterator it = browser_list->begin(); - it != browser_list->end(); - ++it) { - if ((*it)->profile()->IsSameProfile(user_profile_)) { - // The current user has at least one open browser window. - return; - } - } - - if (!extensions::AppWindowRegistry::Get( - user_profile_)->app_windows().empty()) { - // The current user has at least one open app window. - return; - } - - GetSystemTrayNotifier()->NotifyLastWindowClosed(); -} - // content::NotificationObserver implementation. void SystemTrayDelegateChromeOS::Observe( int type, @@ -197,17 +146,6 @@ GetSystemTrayNotifier()->NotifyAccessibilityModeChanged(notify); } -// Overridden from chrome::BrowserListObserver. -void SystemTrayDelegateChromeOS::OnBrowserRemoved(Browser* browser) { - NotifyIfLastWindowClosed(); -} - -// Overridden from extensions::AppWindowRegistry::Observer. -void SystemTrayDelegateChromeOS::OnAppWindowRemoved( - extensions::AppWindow* app_window) { - NotifyIfLastWindowClosed(); -} - void SystemTrayDelegateChromeOS::OnAccessibilityStatusChanged( const AccessibilityStatusEventDetails& details) { if (details.notification_type == ACCESSIBILITY_MANAGER_SHUTDOWN)
diff --git a/chrome/browser/ui/ash/system_tray_delegate_chromeos.h b/chrome/browser/ui/ash/system_tray_delegate_chromeos.h index c9ec3691..54b57fc9 100644 --- a/chrome/browser/ui/ash/system_tray_delegate_chromeos.h +++ b/chrome/browser/ui/ash/system_tray_delegate_chromeos.h
@@ -13,11 +13,9 @@ #include "base/observer_list.h" #include "chrome/browser/chromeos/accessibility/accessibility_manager.h" #include "chrome/browser/profiles/profile.h" -#include "chrome/browser/ui/browser_list_observer.h" #include "components/prefs/pref_change_registrar.h" #include "content/public/browser/notification_observer.h" #include "content/public/browser/notification_registrar.h" -#include "extensions/browser/app_window/app_window_registry.h" namespace ash { class SystemTrayNotifier; @@ -29,17 +27,13 @@ // the transition to mustash. New code should be added to SystemTrayClient. // Use system_tray.mojom methods if you need to send information to ash. // Please contact jamescook@chromium.org if you have questions or need help. -class SystemTrayDelegateChromeOS - : public ash::SystemTrayDelegate, - public content::NotificationObserver, - public chrome::BrowserListObserver, - public extensions::AppWindowRegistry::Observer { +class SystemTrayDelegateChromeOS : public ash::SystemTrayDelegate, + public content::NotificationObserver { public: SystemTrayDelegateChromeOS(); ~SystemTrayDelegateChromeOS() override; // Overridden from ash::SystemTrayDelegate: - void Initialize() override; ash::NetworkingConfigDelegate* GetNetworkingConfigDelegate() const override; void ActiveUserWasChanged() override; @@ -50,16 +44,6 @@ bool UnsetProfile(Profile* profile); - void UpdateSessionStartTime(); - - void UpdateSessionLengthLimit(); - - void StopObservingAppWindowRegistry(); - - // Notify observers if the current user has no more open browser or app - // windows. - void NotifyIfLastWindowClosed(); - // content::NotificationObserver implementation. void Observe(int type, const content::NotificationSource& source, @@ -68,12 +52,6 @@ void OnAccessibilityModeChanged( ash::AccessibilityNotificationVisibility notify); - // Overridden from chrome::BrowserListObserver: - void OnBrowserRemoved(Browser* browser) override; - - // Overridden from extensions::AppWindowRegistry::Observer: - void OnAppWindowRemoved(extensions::AppWindow* app_window) override; - void OnAccessibilityStatusChanged( const AccessibilityStatusEventDetails& details);
diff --git a/chrome/browser/ui/search/instant_search_prerenderer_unittest.cc b/chrome/browser/ui/search/instant_search_prerenderer_unittest.cc index 55cc8da..abcf4e7 100644 --- a/chrome/browser/ui/search/instant_search_prerenderer_unittest.cc +++ b/chrome/browser/ui/search/instant_search_prerenderer_unittest.cc
@@ -22,6 +22,7 @@ #include "chrome/browser/prerender/prerender_manager_factory.h" #include "chrome/browser/prerender/prerender_origin.h" #include "chrome/browser/prerender/prerender_tab_helper.h" +#include "chrome/browser/prerender/prerender_test_utils.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/search/instant_service.h" #include "chrome/browser/search/instant_unittest_base.h" @@ -187,12 +188,25 @@ InstantSearchPrerendererTest() {} protected: + using RestorePrerenderMode = prerender::test_utils::RestorePrerenderMode; + void SetUp() override { ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial("EmbeddedSearch", "Group1 strk:20")); + + // Prerender mode is stored in a few static variables. Remember the default + // mode to restore it later in TearDown() to avoid affecting other tests. + restore_prerender_mode_ = base::MakeUnique<RestorePrerenderMode>(); + PrerenderManager::SetInstantMode(PrerenderManager::PRERENDER_MODE_ENABLED); + InstantUnitTestBase::SetUp(); } + void TearDown() override { + InstantUnitTestBase::TearDown(); + restore_prerender_mode_.reset(); + } + void Init(bool prerender_search_results_base_page, bool call_did_finish_load) { AddTab(browser(), GURL(url::kAboutBlankURL)); @@ -250,6 +264,7 @@ private: MockEmbeddedSearchClient mock_embedded_search_client_; + std::unique_ptr<RestorePrerenderMode> restore_prerender_mode_; }; TEST_F(InstantSearchPrerendererTest, GetSearchTermsFromPrerenderedPage) {
diff --git a/chrome/browser/ui/views/tabs/tab_strip.cc b/chrome/browser/ui/views/tabs/tab_strip.cc index 3762681..b7a9acd 100644 --- a/chrome/browser/ui/views/tabs/tab_strip.cc +++ b/chrome/browser/ui/views/tabs/tab_strip.cc
@@ -1153,7 +1153,13 @@ if (active_tab && is_dragging) active_tab->Paint(paint_info); - ui::PaintRecorder recorder(paint_info.context(), size()); + // Keep the recording scales consistent for the tab strip and its children. + // See crbug/753911 + ui::PaintRecorder recorder(paint_info.context(), + paint_info.paint_recording_size(), + paint_info.paint_recording_scale_x(), + paint_info.paint_recording_scale_y(), nullptr); + gfx::Canvas* canvas = recorder.canvas(); if (active_tab) { canvas->sk_canvas()->clipRect(
diff --git a/chrome/browser/ui/webui/policy_ui.cc b/chrome/browser/ui/webui/policy_ui.cc index 35c90bc..326f03da 100644 --- a/chrome/browser/ui/webui/policy_ui.cc +++ b/chrome/browser/ui/webui/policy_ui.cc
@@ -21,6 +21,7 @@ source->AddLocalizedString("filterPlaceholder", IDS_POLICY_FILTER_PLACEHOLDER); source->AddLocalizedString("reloadPolicies", IDS_POLICY_RELOAD_POLICIES); + source->AddLocalizedString("exportPoliciesJSON", IDS_EXPORT_POLICIES_JSON); source->AddLocalizedString("chromeForWork", IDS_POLICY_CHROME_FOR_WORK); source->AddLocalizedString("status", IDS_POLICY_STATUS); source->AddLocalizedString("statusDevice", IDS_POLICY_STATUS_DEVICE);
diff --git a/chrome/browser/ui/webui/policy_ui_browsertest.cc b/chrome/browser/ui/webui/policy_ui_browsertest.cc index 38dbbb4..bc73159 100644 --- a/chrome/browser/ui/webui/policy_ui_browsertest.cc +++ b/chrome/browser/ui/webui/policy_ui_browsertest.cc
@@ -11,6 +11,7 @@ #include "base/callback.h" #include "base/files/scoped_temp_dir.h" #include "base/json/json_reader.h" +#include "base/json/json_writer.h" #include "base/macros.h" #include "base/memory/ptr_util.h" #include "base/run_loop.h" @@ -38,6 +39,8 @@ #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/base/l10n/l10n_util.h" +#include "ui/shell_dialogs/select_file_dialog.h" +#include "ui/shell_dialogs/select_file_dialog_factory.h" #include "url/gurl.h" using testing::Return; @@ -93,6 +96,23 @@ return expected_policy; } +void SetExpectedPolicy(base::DictionaryValue* expected, + const std::string& name, + const std::string& level, + const std::string& scope, + const std::string& source, + const base::Value& value) { + std::string prefix = "chromePolicies." + name + "."; + expected->SetString(prefix + "level", level); + expected->SetString(prefix + "scope", scope); + expected->SetString(prefix + "source", source); + expected->Set(prefix + "value", base::MakeUnique<base::Value>(value)); +} + +// The temporary directory and file paths for policy saving. +base::ScopedTempDir export_policies_test_dir; +base::FilePath export_policies_test_file_path; + } // namespace class PolicyUITest : public InProcessBrowserTest { @@ -108,6 +128,8 @@ void VerifyPolicies(const std::vector<std::vector<std::string> >& expected); + void VerifyExportingPolicies(const base::DictionaryValue& expected); + protected: policy::MockConfigurationPolicyProvider provider_; @@ -115,6 +137,46 @@ DISALLOW_COPY_AND_ASSIGN(PolicyUITest); }; +// An artificial SelectFileDialog that immediately returns the location of test +// file instead of showing the UI file picker. +class TestSelectFileDialog : public ui::SelectFileDialog { + public: + TestSelectFileDialog(ui::SelectFileDialog::Listener* listener, + ui::SelectFilePolicy* policy) + : ui::SelectFileDialog(listener, policy) {} + + void SelectFileImpl(Type type, + const base::string16& title, + const base::FilePath& default_path, + const FileTypeInfo* file_types, + int file_type_index, + const base::FilePath::StringType& default_extension, + gfx::NativeWindow owning_window, + void* params) override { + listener_->FileSelected(export_policies_test_file_path, 0, nullptr); + } + + bool IsRunning(gfx::NativeWindow owning_window) const override { + return false; + } + + void ListenerDestroyed() override {} + + bool HasMultipleFileTypeChoicesImpl() override { return false; } + + private: + ~TestSelectFileDialog() override {} +}; + +// A factory associated with the artificial file picker. +class TestSelectFileDialogFactory : public ui::SelectFileDialogFactory { + private: + ui::SelectFileDialog* Create(ui::SelectFileDialog::Listener* listener, + ui::SelectFilePolicy* policy) override { + return new TestSelectFileDialog(listener, policy); + } +}; + PolicyUITest::PolicyUITest() { } @@ -125,6 +187,12 @@ EXPECT_CALL(provider_, IsInitializationComplete(_)) .WillRepeatedly(Return(true)); policy::BrowserPolicyConnector::SetPolicyProviderForTesting(&provider_); + + // Create a directory for testing exporting policies. + ASSERT_TRUE(export_policies_test_dir.CreateUniqueTempDir()); + const std::string filename = "policy.json"; + export_policies_test_file_path = + export_policies_test_dir.GetPath().AppendASCII(filename); } void PolicyUITest::UpdateProviderPolicy(const policy::PolicyMap& policy) { @@ -183,6 +251,120 @@ } } +void PolicyUITest::VerifyExportingPolicies( + const base::DictionaryValue& expected) { + // Set SelectFileDialog to use our factory. + ui::SelectFileDialog::SetFactory(new TestSelectFileDialogFactory()); + + // Navigate to the about:policy page. + ui_test_utils::NavigateToURL(browser(), GURL("chrome://policy")); + + // Click on 'save policies' button. + const std::string javascript = + "document.getElementById(\"export-policies\").click()"; + + content::WebContents* contents = + browser()->tab_strip_model()->GetActiveWebContents(); + EXPECT_TRUE(content::ExecuteScript(contents, javascript)); + + base::TaskScheduler::GetInstance()->FlushForTesting(); + // Open the created file. + base::ThreadRestrictions::ScopedAllowIO allow_io; + std::string file_contents; + EXPECT_TRUE( + base::ReadFileToString(export_policies_test_file_path, &file_contents)); + + std::unique_ptr<base::Value> value_ptr = + base::JSONReader::Read(file_contents); + + // Check that the file contains a valid dictionary. + EXPECT_TRUE(value_ptr.get()); + base::DictionaryValue* actual_policies = nullptr; + EXPECT_TRUE(value_ptr->GetAsDictionary(&actual_policies)); + + // Check that this dictionary is the same as expected. + EXPECT_EQ(expected, *actual_policies); +} + +IN_PROC_BROWSER_TEST_F(PolicyUITest, WritePoliciesToJSONFile) { + // Set policy values and generate expected dictionary. + policy::PolicyMap values; + base::DictionaryValue expected_values; + + base::ListValue popups_blocked_for_urls; + popups_blocked_for_urls.AppendString("aaa"); + popups_blocked_for_urls.AppendString("bbb"); + popups_blocked_for_urls.AppendString("ccc"); + values.Set(policy::key::kPopupsBlockedForUrls, policy::POLICY_LEVEL_MANDATORY, + policy::POLICY_SCOPE_MACHINE, policy::POLICY_SOURCE_PLATFORM, + base::MakeUnique<base::Value>(popups_blocked_for_urls), nullptr); + SetExpectedPolicy(&expected_values, policy::key::kPopupsBlockedForUrls, + "mandatory", "machine", "sourcePlatform", + popups_blocked_for_urls); + + values.Set(policy::key::kDefaultImagesSetting, policy::POLICY_LEVEL_MANDATORY, + policy::POLICY_SCOPE_MACHINE, policy::POLICY_SOURCE_CLOUD, + base::MakeUnique<base::Value>(2), nullptr); + SetExpectedPolicy(&expected_values, policy::key::kDefaultImagesSetting, + "mandatory", "machine", "sourceCloud", base::Value(2)); + + // This also checks that we save complex policies correctly. + base::DictionaryValue unknown_policy; + base::DictionaryValue body; + body.SetInteger("first", 0); + body.SetBoolean("second", true); + unknown_policy.SetInteger("head", 12); + unknown_policy.SetDictionary("body", + base::MakeUnique<base::DictionaryValue>(body)); + const std::string kUnknownPolicy = "NoSuchThing"; + values.Set(kUnknownPolicy, policy::POLICY_LEVEL_RECOMMENDED, + policy::POLICY_SCOPE_USER, policy::POLICY_SOURCE_CLOUD, + base::MakeUnique<base::Value>(unknown_policy), nullptr); + SetExpectedPolicy(&expected_values, kUnknownPolicy, "recommended", "user", + "sourceCloud", unknown_policy); + + // Set the extension policies to an empty dictionary as we haven't added any + // such policies. + expected_values.SetDictionary("extensionPolicies", + base::MakeUnique<base::DictionaryValue>()); + + UpdateProviderPolicy(values); + + // Check writing those policies to a newly created file. + VerifyExportingPolicies(expected_values); + + // Change policy values. + values.Erase(policy::key::kDefaultImagesSetting); + expected_values.RemovePath( + std::string("chromePolicies.") + + std::string(policy::key::kDefaultImagesSetting), + nullptr); + + // This also checks that we bypass the policy that blocks file selection + // dialogs. + values.Set(policy::key::kAllowFileSelectionDialogs, + policy::POLICY_LEVEL_MANDATORY, policy::POLICY_SCOPE_MACHINE, + policy::POLICY_SOURCE_PLATFORM, + base::MakeUnique<base::Value>(false), nullptr); + SetExpectedPolicy(&expected_values, policy::key::kAllowFileSelectionDialogs, + "mandatory", "machine", "sourcePlatform", + base::Value(false)); + + popups_blocked_for_urls.AppendString("ddd"); + values.Set(policy::key::kPopupsBlockedForUrls, policy::POLICY_LEVEL_MANDATORY, + policy::POLICY_SCOPE_MACHINE, policy::POLICY_SOURCE_PLATFORM, + base::MakeUnique<base::Value>(popups_blocked_for_urls), nullptr); + SetExpectedPolicy(&expected_values, policy::key::kPopupsBlockedForUrls, + "mandatory", "machine", "sourcePlatform", + popups_blocked_for_urls); + + UpdateProviderPolicy(values); + + // Check writing changed policies to the same file (should overwrite the + // contents). + VerifyExportingPolicies(expected_values); +} + IN_PROC_BROWSER_TEST_F(PolicyUITest, SendPolicyNames) { // Verifies that the names of known policies are sent to the UI and processed // there correctly by checking that the policy table contains all policies in
diff --git a/chrome/browser/ui/webui/policy_ui_handler.cc b/chrome/browser/ui/webui/policy_ui_handler.cc index 42f02b4..7f3c502b 100644 --- a/chrome/browser/ui/webui/policy_ui_handler.cc +++ b/chrome/browser/ui/webui/policy_ui_handler.cc
@@ -12,16 +12,20 @@ #include "base/bind_helpers.h" #include "base/callback.h" #include "base/compiler_specific.h" +#include "base/files/file_util.h" #include "base/json/json_writer.h" #include "base/logging.h" #include "base/macros.h" #include "base/memory/ptr_util.h" #include "base/memory/weak_ptr.h" #include "base/strings/string16.h" +#include "base/task_scheduler/post_task.h" +#include "base/task_scheduler/task_traits.h" #include "base/time/time.h" #include "base/values.h" #include "build/build_config.h" #include "chrome/browser/browser_process.h" +#include "chrome/browser/download/download_prefs.h" #include "chrome/browser/policy/profile_policy_connector.h" #include "chrome/browser/policy/profile_policy_connector_factory.h" #include "chrome/browser/policy/schema_registry_service.h" @@ -180,9 +184,13 @@ return base::MakeUnique<base::Value>(json_string); } -// Returns a copy of |value| with some values converted to a representation that -// i18n_template.js will display in a nicer way. -std::unique_ptr<base::Value> CopyAndConvert(const base::Value* value) { +// Returns a copy of |value|. If necessary (which is specified by +// |convert_values|), converts some values to a representation that +// i18n_template.js will display. +std::unique_ptr<base::Value> CopyAndMaybeConvert(const base::Value* value, + bool convert_values) { + if (!convert_values) + return value->CreateDeepCopy(); const base::DictionaryValue* dict = NULL; if (value->GetAsDictionary(&dict)) return DictionaryToJSONString(*dict); @@ -597,6 +605,10 @@ "reloadPolicies", base::Bind(&PolicyUIHandler::HandleReloadPolicies, base::Unretained(this))); + web_ui()->RegisterMessageCallback( + "exportPoliciesJSON", + base::Bind(&PolicyUIHandler::HandleExportPoliciesJSON, + base::Unretained(this))); } #if BUILDFLAG(ENABLE_EXTENSIONS) @@ -687,12 +699,13 @@ web_ui()->CallJavascriptFunctionUnsafe("policy.Page.setPolicyNames", names); } -void PolicyUIHandler::SendPolicyValues() const { +std::unique_ptr<base::DictionaryValue> PolicyUIHandler::GetAllPolicyValues( + bool convert_values) const { base::DictionaryValue all_policies; // Add Chrome policy values. auto chrome_policies = base::MakeUnique<base::DictionaryValue>(); - GetChromePolicyValues(chrome_policies.get()); + GetChromePolicyValues(chrome_policies.get(), convert_values); all_policies.Set("chromePolicies", std::move(chrome_policies)); #if BUILDFLAG(ENABLE_EXTENSIONS) @@ -712,21 +725,29 @@ policy::POLICY_DOMAIN_EXTENSIONS, extension->id()); policy::PolicyErrorMap empty_error_map; GetPolicyValues(GetPolicyService()->GetPolicies(policy_namespace), - &empty_error_map, extension_policies.get()); + &empty_error_map, extension_policies.get(), convert_values); extension_values->Set(extension->id(), std::move(extension_policies)); } all_policies.Set("extensionPolicies", std::move(extension_values)); #endif + return base::MakeUnique<base::DictionaryValue>(all_policies); +} + +void PolicyUIHandler::SendPolicyValues() const { + std::unique_ptr<base::DictionaryValue> all_policies = + GetAllPolicyValues(true); web_ui()->CallJavascriptFunctionUnsafe("policy.Page.setPolicyValues", - all_policies); + *all_policies); } void PolicyUIHandler::GetPolicyValues(const policy::PolicyMap& map, policy::PolicyErrorMap* errors, - base::DictionaryValue* values) const { + base::DictionaryValue* values, + bool convert_values) const { for (const auto& entry : map) { std::unique_ptr<base::DictionaryValue> value(new base::DictionaryValue); - value->Set("value", CopyAndConvert(entry.second.value.get())); + value->Set("value", + CopyAndMaybeConvert(entry.second.value.get(), convert_values)); if (entry.second.scope == policy::POLICY_SCOPE_USER) value->SetString("scope", "user"); else @@ -743,8 +764,8 @@ } } -void PolicyUIHandler::GetChromePolicyValues( - base::DictionaryValue* values) const { +void PolicyUIHandler::GetChromePolicyValues(base::DictionaryValue* values, + bool convert_values) const { policy::PolicyService* policy_service = GetPolicyService(); policy::PolicyMap map; @@ -762,7 +783,7 @@ // Convert dictionary values to strings for display. handler_list->PrepareForDisplaying(&map); - GetPolicyValues(map, &errors, values); + GetPolicyValues(map, &errors, values, convert_values); } void PolicyUIHandler::SendStatus() const { @@ -815,6 +836,70 @@ &PolicyUIHandler::OnRefreshPoliciesDone, weak_factory_.GetWeakPtr())); } +void DoWritePoliciesToJSONFile(const base::FilePath& path, + const std::string& data) { + base::WriteFile(path, data.c_str(), data.size()); +} + +void PolicyUIHandler::WritePoliciesToJSONFile( + const base::FilePath& path) const { + std::unique_ptr<base::DictionaryValue> all_policies = + GetAllPolicyValues(false); + std::string json_policies = + DictionaryToJSONString(*all_policies)->GetString(); + + base::PostTaskWithTraits( + FROM_HERE, + {base::MayBlock(), base::TaskPriority::BACKGROUND, + base::TaskShutdownBehavior::BLOCK_SHUTDOWN}, + base::BindOnce(&DoWritePoliciesToJSONFile, path, json_policies)); +} + +void PolicyUIHandler::FileSelected(const base::FilePath& path, + int index, + void* params) { + DCHECK(export_policies_select_file_dialog_); + + WritePoliciesToJSONFile(path); + + export_policies_select_file_dialog_ = nullptr; +} + +void PolicyUIHandler::FileSelectionCanceled(void* params) { + DCHECK(export_policies_select_file_dialog_); + export_policies_select_file_dialog_ = nullptr; +} + +void PolicyUIHandler::HandleExportPoliciesJSON(const base::ListValue* args) { + // If the "select file" dialog window is already opened, we don't want to open + // it again. + if (export_policies_select_file_dialog_) + return; + + content::WebContents* webcontents = web_ui()->GetWebContents(); + + // Building initial path based on download preferences. + base::FilePath initial_dir = + DownloadPrefs::FromBrowserContext(webcontents->GetBrowserContext()) + ->DownloadPath(); + base::FilePath initial_path = + initial_dir.Append(FILE_PATH_LITERAL("policies.json")); + + // Here we overwrite the actual value of SelectFileDialog policy by passing a + // nullptr to ui::SelectFileDialog::Create instead of the actual policy value. + // This is done for the following reason: the admin might want to set this + // policy for the user to forbid the select file dialogs, but this shouldn't + // block the possibility to export the policies. + export_policies_select_file_dialog_ = + ui::SelectFileDialog::Create(this, nullptr); + ui::SelectFileDialog::FileTypeInfo file_type_info; + file_type_info.extensions = {{FILE_PATH_LITERAL("json")}}; + gfx::NativeWindow owning_window = webcontents->GetTopLevelNativeWindow(); + export_policies_select_file_dialog_->SelectFile( + ui::SelectFileDialog::SELECT_SAVEAS_FILE, base::string16(), initial_path, + &file_type_info, 0, base::FilePath::StringType(), owning_window, nullptr); +} + void PolicyUIHandler::OnRefreshPoliciesDone() const { web_ui()->CallJavascriptFunctionUnsafe("policy.Page.reloadPoliciesDone"); }
diff --git a/chrome/browser/ui/webui/policy_ui_handler.h b/chrome/browser/ui/webui/policy_ui_handler.h index 1201ce0..e181e422 100644 --- a/chrome/browser/ui/webui/policy_ui_handler.h +++ b/chrome/browser/ui/webui/policy_ui_handler.h
@@ -21,6 +21,7 @@ #include "content/public/browser/web_ui_data_source.h" #include "content/public/browser/web_ui_message_handler.h" #include "extensions/features/features.h" +#include "ui/shell_dialogs/select_file_dialog.h" #if BUILDFLAG(ENABLE_EXTENSIONS) #include "extensions/browser/extension_registry_observer.h" @@ -39,7 +40,8 @@ public extensions::ExtensionRegistryObserver, #endif public policy::PolicyService::Observer, - public policy::SchemaRegistry::Observer { + public policy::SchemaRegistry::Observer, + public ui::SelectFileDialog::Listener { public: PolicyUIHandler(); ~PolicyUIHandler() override; @@ -79,6 +81,12 @@ // Send a dictionary containing the names of all known policies to the UI. virtual void SendPolicyNames() const; + // ui::SelectFileDialog::Listener implementation. + void FileSelected(const base::FilePath& path, + int index, + void* params) override; + void FileSelectionCanceled(void* params) override; + private: // Send information about the current policy values to the UI. For each policy // whose value has been set, a dictionary containing the value and additional @@ -91,15 +99,26 @@ void SendStatus() const; // Inserts a description of each policy in |policy_map| into |values|, using - // the optional errors in |errors| to determine the status of each policy. + // the optional errors in |errors| to determine the status of each policy. If + // |convert_values| is true, converts the values to show them in javascript. void GetPolicyValues(const policy::PolicyMap& policy_map, policy::PolicyErrorMap* errors, - base::DictionaryValue* values) const; + base::DictionaryValue* values, + bool convert_values) const; - void GetChromePolicyValues(base::DictionaryValue* values) const; + // Returns a dictionary with the values of all set policies, with some values + // converted to be shown in javascript, if it is specified. + std::unique_ptr<base::DictionaryValue> GetAllPolicyValues( + bool convert_values) const; + + void GetChromePolicyValues(base::DictionaryValue* values, + bool convert_values) const; + + void WritePoliciesToJSONFile(const base::FilePath& path) const; void HandleInitialized(const base::ListValue* args); void HandleReloadPolicies(const base::ListValue* args); + void HandleExportPoliciesJSON(const base::ListValue* args); void OnRefreshPoliciesDone() const; @@ -107,6 +126,8 @@ std::string device_domain_; + scoped_refptr<ui::SelectFileDialog> export_policies_select_file_dialog_; + // Providers that supply status dictionaries for user and device policy, // respectively. These are created on initialization time as appropriate for // the platform (Chrome OS / desktop) and type of policy that is in effect.
diff --git a/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc b/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc index 792243a4..5e54afaa 100644 --- a/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc +++ b/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc
@@ -1648,7 +1648,13 @@ void AddSearchStrings(content::WebUIDataSource* html_source) { LocalizedString localized_strings[] = { +#if defined(OS_CHROMEOS) + {"searchPageTitle", chromeos::switches::IsVoiceInteractionEnabled() + ? IDS_SETTINGS_SEARCH_AND_ASSISTANT + : IDS_SETTINGS_SEARCH}, +#else {"searchPageTitle", IDS_SETTINGS_SEARCH}, +#endif {"searchEnginesManage", IDS_SETTINGS_SEARCH_MANAGE_SEARCH_ENGINES}, {"searchOkGoogleLabel", IDS_SETTINGS_SEARCH_OK_GOOGLE_LABEL}, #if defined(OS_CHROMEOS)
diff --git a/chrome/common/logging_chrome.cc b/chrome/common/logging_chrome.cc index dc58f8d2..8899916 100644 --- a/chrome/common/logging_chrome.cc +++ b/chrome/common/logging_chrome.cc
@@ -161,21 +161,51 @@ base::FilePath SetUpSymlinkIfNeeded(const base::FilePath& symlink_path, bool new_log) { DCHECK(!symlink_path.empty()); + // For backward compatibility, set up a .../chrome symlink to + // .../chrome.LATEST as needed. This code needs to run only + // after the migration (i.e. the addition of chrome.LATEST). + if (symlink_path.Extension() == ".LATEST") { + base::FilePath extensionless_path = symlink_path.ReplaceExtension(""); + base::FilePath target_path; - // If not starting a new log, then just log through the existing - // symlink, but if the symlink doesn't exist, create it. If - // starting a new log, then delete the old symlink and make a new - // one to a fresh log file. + base::ReadSymbolicLink(extensionless_path, &target_path); + if (target_path != symlink_path) { + // No link, or wrong link. Clean up. This should happen only once in + // each log directory after the OS version update, but some of those + // directories may not be accessed for a long time, so this code needs to + // stay in forever :/ + if (base::PathExists(extensionless_path) && + !base::DeleteFile(extensionless_path, false)) { + DPLOG(WARNING) << "Cannot delete " << extensionless_path.value(); + } + // After cleaning up, create the symlink. + if (!base::CreateSymbolicLink(symlink_path, extensionless_path)) { + DPLOG(ERROR) << "Cannot create " << extensionless_path.value(); + } + } + } + + // If not starting a new log, then just log through the existing symlink, but + // if the symlink doesn't exist, create it. + // + // If starting a new log, then rename the old symlink as + // symlink_path.PREVIOUS and make a new symlink to a fresh log file. base::FilePath target_path; bool symlink_exists = base::PathExists(symlink_path); if (new_log || !symlink_exists) { target_path = GenerateTimestampedName(symlink_path, base::Time::Now()); - // We don't care if the unlink fails; we're going to continue anyway. - if (::unlink(symlink_path.value().c_str()) == -1) { - if (symlink_exists) // only warn if we might expect it to succeed. - DPLOG(WARNING) << "Unable to unlink " << symlink_path.value(); + if (symlink_exists) { + base::FilePath previous_symlink_path = + symlink_path.ReplaceExtension(".PREVIOUS"); + // Rename symlink to .PREVIOUS. This nukes an existing symlink just like + // the rename(2) syscall does. + if (!base::ReplaceFile(symlink_path, previous_symlink_path, nullptr)) { + DPLOG(WARNING) << "Cannot rename " << symlink_path.value() << " to " + << previous_symlink_path.value(); + } } + // If all went well, the symlink no longer exists. Recreate it. if (!base::CreateSymbolicLink(target_path, symlink_path)) { DPLOG(ERROR) << "Unable to create symlink " << symlink_path.value() << " pointing at " << target_path.value(); @@ -231,7 +261,6 @@ OldFileDeletionState delete_old_log_file) { DCHECK(!chrome_logging_initialized_) << "Attempted to initialize logging when it was already initialized."; - LoggingDestination logging_dest = DetermineLoggingDestination(command_line); LogLockingState log_locking_state = LOCK_LOG_FILE; base::FilePath log_path; @@ -379,10 +408,17 @@ bool DialogsAreSuppressed() { return dialogs_are_suppressed_; } + +#if defined(OS_CHROMEOS) base::FilePath GenerateTimestampedName(const base::FilePath& base_path, base::Time timestamp) { base::Time::Exploded time_deets; timestamp.LocalExplode(&time_deets); + base::FilePath new_path = base_path; + // Assume that the base_path is "chrome.LATEST", and remove the extension. + // Ideally we would also check the value of base_path, but we cannot reliably + // log anything here, and aborting seems too harsh a choice. + new_path = new_path.ReplaceExtension(""); std::string suffix = base::StringPrintf("_%02d%02d%02d-%02d%02d%02d", time_deets.year, time_deets.month, @@ -390,7 +426,8 @@ time_deets.hour, time_deets.minute, time_deets.second); - return base_path.InsertBeforeExtensionASCII(suffix); + return new_path.InsertBeforeExtensionASCII(suffix); } +#endif // defined(OS_CHROMEOS) } // namespace logging
diff --git a/chrome/common/logging_chrome.h b/chrome/common/logging_chrome.h index 42ba0343..0b00997 100644 --- a/chrome/common/logging_chrome.h +++ b/chrome/common/logging_chrome.h
@@ -61,10 +61,12 @@ // otherwise. bool DialogsAreSuppressed(); -// Inserts timestamp before file extension in the format +#if defined(OS_CHROMEOS) +// Inserts timestamp before file extension (if any) in the form // "_yymmdd-hhmmss". base::FilePath GenerateTimestampedName(const base::FilePath& base_path, base::Time timestamp); +#endif } // namespace logging #endif // CHROME_COMMON_LOGGING_CHROME_H_
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index 128f68b7..9df6bbc 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -3637,6 +3637,7 @@ "../browser/media_galleries/media_galleries_preferences_unittest.cc", "../browser/media_galleries/win/mtp_device_delegate_impl_win_unittest.cc", "../browser/media_galleries/win/mtp_device_object_enumerator_unittest.cc", + "../browser/page_load_metrics/observers/session_restore_page_load_metrics_observer_unittest.cc", "../browser/resource_coordinator/background_tab_navigation_throttle_unittest.cc", "../browser/resource_coordinator/tab_manager_delegate_chromeos_unittest.cc", "../browser/resource_coordinator/tab_manager_stats_collector_unittest.cc",
diff --git a/chrome/test/ppapi/ppapi_filechooser_browsertest.cc b/chrome/test/ppapi/ppapi_filechooser_browsertest.cc index 3d7d234..0214d7c 100644 --- a/chrome/test/ppapi/ppapi_filechooser_browsertest.cc +++ b/chrome/test/ppapi/ppapi_filechooser_browsertest.cc
@@ -349,7 +349,7 @@ RunTestViaHTTP("FileChooser_SaveAsUnsafeDefaultName"); base::FilePath actual_filename = - temp_dir.GetPath().AppendASCII("unsafe.txt-"); + temp_dir.GetPath().AppendASCII("unsafe.txt_"); ASSERT_TRUE(base::PathExists(actual_filename)); std::string file_contents;
diff --git a/components/arc/common/app.mojom b/components/arc/common/app.mojom index 9f31167..bfdf4ecf 100644 --- a/components/arc/common/app.mojom +++ b/components/arc/common/app.mojom
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // -// Next MinVersion: 22 +// Next MinVersion: 23 module arc.mojom; @@ -86,6 +86,7 @@ string? formatted_price; float review_score; array<uint8> icon_png_data; + [MinVersion=22] string? package_name; }; // Describes the status of an app discovery request.
diff --git a/components/arc/test/fake_app_instance.cc b/components/arc/test/fake_app_instance.cc index da10ceb..7b1e74c 100644 --- a/components/arc/test/fake_app_instance.cc +++ b/components/arc/test/fake_app_instance.cc
@@ -285,13 +285,26 @@ const GetRecentAndSuggestedAppsFromPlayStoreCallback& callback) { // Fake Play Store app info std::vector<arc::mojom::AppDiscoveryResultPtr> fake_apps; - for (int i = 0; i < max_results; ++i) { - // Fake icon data - std::string png_data_as_string; - GetFakeIcon(mojom::ScaleFactor::SCALE_FACTOR_100P, &png_data_as_string); - std::vector<uint8_t> fake_icon_png_data(png_data_as_string.begin(), - png_data_as_string.end()); + // Fake icon data. + std::string png_data_as_string; + GetFakeIcon(mojom::ScaleFactor::SCALE_FACTOR_100P, &png_data_as_string); + std::vector<uint8_t> fake_icon_png_data(png_data_as_string.begin(), + png_data_as_string.end()); + + fake_apps.push_back(mojom::AppDiscoveryResult::New( + std::string("LauncherIntentUri"), // launch_intent_uri + std::string("InstallIntentUri"), // install_intent_uri + std::string(query), // label + false, // is_instant_app + false, // is_recent + std::string("Publisher"), // publisher_name + std::string("$7.22"), // formatted_price + 5, // review_score + fake_icon_png_data, // icon_png_data + std::string("com.google.android.gm"))); // package_name + + for (int i = 0; i < max_results - 1; ++i) { fake_apps.push_back(mojom::AppDiscoveryResult::New( base::StringPrintf("LauncherIntentUri %d", i), // launch_intent_uri base::StringPrintf("InstallIntentUri %d", i), // install_intent_uri @@ -301,7 +314,8 @@ base::StringPrintf("Publisher %d", i), // publisher_name base::StringPrintf("$%d.22", i), // formatted_price i, // review_score - fake_icon_png_data)); // icon_png_data + fake_icon_png_data, // icon_png_data + base::StringPrintf("test.package.%d", i))); // package_name } callback.Run(arc::mojom::AppDiscoveryRequestState::SUCCESS, std::move(fake_apps));
diff --git a/components/autofill/content/common/autofill_types_struct_traits.cc b/components/autofill/content/common/autofill_types_struct_traits.cc index d76e5b0..ed4c5c4 100644 --- a/components/autofill/content/common/autofill_types_struct_traits.cc +++ b/components/autofill/content/common/autofill_types_struct_traits.cc
@@ -604,24 +604,25 @@ } // static -void* StructTraits<mojom::PasswordFormFieldPredictionMapDataView, - PasswordFormFieldPredictionMap>:: - SetUpContext(const PasswordFormFieldPredictionMap& r) { - // Extracts keys vector and values vector from the map, saves them as a pair. - auto* pair = new KeysValuesPair(); - for (const auto& i : r) { - pair->first.push_back(i.first); - pair->second.push_back(i.second); - } - - return pair; +std::vector<autofill::FormFieldData> StructTraits< + mojom::PasswordFormFieldPredictionMapDataView, + PasswordFormFieldPredictionMap>::keys(const PasswordFormFieldPredictionMap& + r) { + std::vector<autofill::FormFieldData> data; + for (const auto& i : r) + data.push_back(i.first); + return data; } // static -void StructTraits<mojom::PasswordFormFieldPredictionMapDataView, - PasswordFormFieldPredictionMap>:: - TearDownContext(const PasswordFormFieldPredictionMap& r, void* context) { - delete static_cast<KeysValuesPair*>(context); +std::vector<autofill::PasswordFormFieldPredictionType> +StructTraits<mojom::PasswordFormFieldPredictionMapDataView, + PasswordFormFieldPredictionMap>:: + values(const PasswordFormFieldPredictionMap& r) { + std::vector<autofill::PasswordFormFieldPredictionType> types; + for (const auto& i : r) + types.push_back(i.second); + return types; } // static @@ -646,23 +647,23 @@ } // static -void* StructTraits<mojom::FormsPredictionsMapDataView, - FormsPredictionsMap>::SetUpContext(const FormsPredictionsMap& - r) { - // Extracts keys vector and values vector from the map, saves them as a pair. - auto* pair = new KeysValuesPair(); - for (const auto& i : r) { - pair->first.push_back(i.first); - pair->second.push_back(i.second); - } - - return pair; +std::vector<autofill::FormData> +StructTraits<mojom::FormsPredictionsMapDataView, FormsPredictionsMap>::keys( + const FormsPredictionsMap& r) { + std::vector<autofill::FormData> data; + for (const auto& i : r) + data.push_back(i.first); + return data; } // static -void StructTraits<mojom::FormsPredictionsMapDataView, FormsPredictionsMap>:: - TearDownContext(const FormsPredictionsMap& r, void* context) { - delete static_cast<KeysValuesPair*>(context); +std::vector<autofill::PasswordFormFieldPredictionMap> +StructTraits<mojom::FormsPredictionsMapDataView, FormsPredictionsMap>::values( + const FormsPredictionsMap& r) { + std::vector<autofill::PasswordFormFieldPredictionMap> maps; + for (const auto& i : r) + maps.push_back(i.second); + return maps; } // static
diff --git a/components/autofill/content/common/autofill_types_struct_traits.h b/components/autofill/content/common/autofill_types_struct_traits.h index 0c51ed5..b98c9dc 100644 --- a/components/autofill/content/common/autofill_types_struct_traits.h +++ b/components/autofill/content/common/autofill_types_struct_traits.h
@@ -519,26 +519,11 @@ template <> struct StructTraits<autofill::mojom::PasswordFormFieldPredictionMapDataView, autofill::PasswordFormFieldPredictionMap> { - using KeysValuesPair = - std::pair<std::vector<autofill::FormFieldData>, - std::vector<autofill::PasswordFormFieldPredictionType>>; + static std::vector<autofill::FormFieldData> keys( + const autofill::PasswordFormFieldPredictionMap& r); - static void* SetUpContext(const autofill::PasswordFormFieldPredictionMap& r); - - static void TearDownContext(const autofill::PasswordFormFieldPredictionMap& r, - void* context); - - static const std::vector<autofill::FormFieldData>& keys( - const autofill::PasswordFormFieldPredictionMap& r, - void* context) { - return static_cast<KeysValuesPair*>(context)->first; - } - - static const std::vector<autofill::PasswordFormFieldPredictionType>& values( - const autofill::PasswordFormFieldPredictionMap& r, - void* context) { - return static_cast<KeysValuesPair*>(context)->second; - } + static std::vector<autofill::PasswordFormFieldPredictionType> values( + const autofill::PasswordFormFieldPredictionMap& r); static bool Read(autofill::mojom::PasswordFormFieldPredictionMapDataView data, autofill::PasswordFormFieldPredictionMap* out); @@ -547,26 +532,11 @@ template <> struct StructTraits<autofill::mojom::FormsPredictionsMapDataView, autofill::FormsPredictionsMap> { - using KeysValuesPair = - std::pair<std::vector<autofill::FormData>, - std::vector<autofill::PasswordFormFieldPredictionMap>>; + static std::vector<autofill::FormData> keys( + const autofill::FormsPredictionsMap& r); - static void* SetUpContext(const autofill::FormsPredictionsMap& r); - - static void TearDownContext(const autofill::FormsPredictionsMap& r, - void* context); - - static const std::vector<autofill::FormData>& keys( - const autofill::FormsPredictionsMap& r, - void* context) { - return static_cast<KeysValuesPair*>(context)->first; - } - - static const std::vector<autofill::PasswordFormFieldPredictionMap>& values( - const autofill::FormsPredictionsMap& r, - void* context) { - return static_cast<KeysValuesPair*>(context)->second; - } + static std::vector<autofill::PasswordFormFieldPredictionMap> values( + const autofill::FormsPredictionsMap& r); static bool Read(autofill::mojom::FormsPredictionsMapDataView data, autofill::FormsPredictionsMap* out);
diff --git a/components/payments/core/payments_profile_comparator.cc b/components/payments/core/payments_profile_comparator.cc index faeab2d7..23f7c865 100644 --- a/components/payments/core/payments_profile_comparator.cc +++ b/components/payments/core/payments_profile_comparator.cc
@@ -142,6 +142,12 @@ GetRequiredProfileFieldsForContact()); } +base::string16 PaymentsProfileComparator::GetTitleForMissingContactFields( + const autofill::AutofillProfile& profile) const { + return GetTitleForMissingFields(GetMissingProfileFields(&profile) & + GetRequiredProfileFieldsForContact()); +} + std::vector<autofill::AutofillProfile*> PaymentsProfileComparator::FilterProfilesForShipping( const std::vector<autofill::AutofillProfile*>& profiles) const { @@ -266,6 +272,28 @@ } } +base::string16 PaymentsProfileComparator::GetTitleForMissingFields( + PaymentsProfileComparator::ProfileFields fields) const { + switch (fields) { + case 0: + NOTREACHED() << "Title should not be requested if no fields are missing"; + return base::string16(); + case kName: + return l10n_util::GetStringUTF16(IDS_PAYMENTS_ADD_NAME); + case kPhone: + return l10n_util::GetStringUTF16(IDS_PAYMENTS_ADD_PHONE_NUMBER); + case kEmail: + return l10n_util::GetStringUTF16(IDS_PAYMENTS_ADD_EMAIL); + case kAddress: + return l10n_util::GetStringUTF16(IDS_PAYMENTS_ADD_VALID_ADDRESS); + default: + // Either multiple bits are set (likely) or one bit that doesn't + // correspond to a named constant is set (shouldn't happen). Return a + // generic "More information" message. + return l10n_util::GetStringUTF16(IDS_PAYMENTS_ADD_MORE_INFORMATION); + } +} + bool PaymentsProfileComparator::AreRequiredAddressFieldsPresent( const autofill::AutofillProfile& profile) const { std::unique_ptr<::i18n::addressinput::AddressData> data =
diff --git a/components/payments/core/payments_profile_comparator.h b/components/payments/core/payments_profile_comparator.h index 61e7609..ab7ea02 100644 --- a/components/payments/core/payments_profile_comparator.h +++ b/components/payments/core/payments_profile_comparator.h
@@ -89,6 +89,12 @@ base::string16 GetStringForMissingContactFields( const autofill::AutofillProfile& profile) const; + // Returns a localized string to be displayed as the title of a piece of UI, + // indicating what action must be taken for the given profile to be used as + // contact info. + base::string16 GetTitleForMissingContactFields( + const autofill::AutofillProfile& profile) const; + // Returns a localized string to be displayed in UI indicating what action, // if any, must be taken for the given profile to be used as a shipping // address. @@ -105,6 +111,7 @@ ProfileFields GetRequiredProfileFieldsForContact() const; ProfileFields GetRequiredProfileFieldsForShipping() const; base::string16 GetStringForMissingFields(ProfileFields fields) const; + base::string16 GetTitleForMissingFields(ProfileFields fields) const; bool AreRequiredAddressFieldsPresent( const autofill::AutofillProfile& profile) const;
diff --git a/components/payments/core/payments_profile_comparator_unittest.cc b/components/payments/core/payments_profile_comparator_unittest.cc index 18f3e58a..a1b0dc7 100644 --- a/components/payments/core/payments_profile_comparator_unittest.cc +++ b/components/payments/core/payments_profile_comparator_unittest.cc
@@ -417,6 +417,35 @@ comp.GetStringForMissingContactFields(p5)); } +TEST(PaymentRequestProfileUtilTest, GetTitleForMissingContactFields) { + MockPaymentOptionsProvider provider(kRequestPayerName | kRequestPayerPhone | + kRequestPayerEmail | kRequestShipping); + PaymentsProfileComparator comp("en-US", provider); + + // Error message for email address if email address is missing and required. + AutofillProfile p1 = CreateProfileWithContactInfo("Homer", "", "6515553226"); + EXPECT_EQ(l10n_util::GetStringUTF16(IDS_PAYMENTS_ADD_EMAIL), + comp.GetTitleForMissingContactFields(p1)); + + // Error message for phone number if phone is missing and required. + AutofillProfile p2 = + CreateProfileWithContactInfo("Homer", "homer@simpson.net", ""); + EXPECT_EQ(l10n_util::GetStringUTF16(IDS_PAYMENTS_ADD_PHONE_NUMBER), + comp.GetTitleForMissingContactFields(p2)); + + // Error message for name if name is missing and required. + AutofillProfile p3 = + CreateProfileWithContactInfo("", "homer@simpson.net", "6515553226"); + EXPECT_EQ(l10n_util::GetStringUTF16(IDS_PAYMENTS_ADD_NAME), + comp.GetTitleForMissingContactFields(p3)); + + // Generic error message if multiple fields missing. + AutofillProfile p4 = + CreateProfileWithContactInfo("", "homer@simpson.net", ""); + EXPECT_EQ(l10n_util::GetStringUTF16(IDS_PAYMENTS_ADD_MORE_INFORMATION), + comp.GetTitleForMissingContactFields(p4)); +} + TEST(PaymentRequestProfileUtilTest, GetStringForMissingShippingFields) { MockPaymentOptionsProvider provider(kRequestPayerName | kRequestPayerPhone | kRequestPayerEmail | kRequestShipping);
diff --git a/components/policy_strings.grdp b/components/policy_strings.grdp index 4b96b81..2d0599b 100644 --- a/components/policy_strings.grdp +++ b/components/policy_strings.grdp
@@ -234,6 +234,9 @@ <message name="IDS_POLICY_RELOAD_POLICIES" desc="Label for the button that reloads policies."> Reload policies </message> + <message name="IDS_EXPORT_POLICIES_JSON" desc="Label for the button that exports policies in JSON format."> + Export to JSON + </message> <message name="IDS_POLICY_CHROME_FOR_WORK" desc="Title of the link to the chrome for work website."> Using Chrome at work? Businesses can manage Chrome settings for their employees. Learn more </message>
diff --git a/components/sync/driver/about_sync_util.cc b/components/sync/driver/about_sync_util.cc index 3da933e..414a952 100644 --- a/components/sync/driver/about_sync_util.cc +++ b/components/sync/driver/about_sync_util.cc
@@ -336,14 +336,15 @@ "Sync Backend Initialization"); BoolSyncStat is_syncing(section_local, "Syncing"); BoolSyncStat is_local_sync_enabled(section_local, - "Local sync backend enabled"); - StringSyncStat local_backend_path(section_local, "Local backend path"); + "Local Sync Backend Enabled"); + StringSyncStat local_backend_path(section_local, "Local Backend Path"); base::ListValue* section_network = AddSection(stats_list.get(), "Network"); // TODO(crbug.com/702230): Remove the usages of raw pointers in this file. section_network->Reserve(3); - BoolSyncStat is_throttled(section_network, "Throttled"); - StringSyncStat retry_time(section_network, "Retry time (maybe stale)"); + BoolSyncStat is_any_throttled_or_backoff(section_network, + "Throttled or Backoff"); + StringSyncStat retry_time(section_network, "Retry Time"); BoolSyncStat are_notifications_enabled(section_network, "Notifications Enabled"); @@ -473,7 +474,7 @@ } if (snapshot.is_initialized()) - is_throttled.SetValue(snapshot.is_silenced()); + is_any_throttled_or_backoff.SetValue(snapshot.is_silenced()); if (is_status_valid) { are_notifications_enabled.SetValue(full_status.notifications_enabled); }
diff --git a/components/sync/engine_impl/cycle/sync_cycle.cc b/components/sync/engine_impl/cycle/sync_cycle.cc index a8cf982..ed53404 100644 --- a/components/sync/engine_impl/cycle/sync_cycle.cc +++ b/components/sync/engine_impl/cycle/sync_cycle.cc
@@ -42,7 +42,7 @@ SyncCycleSnapshot snapshot( status_controller_->model_neutral_state(), download_progress_markers, - delegate_->IsCurrentlyThrottled(), + delegate_->IsAnyThrottleOrBackoff(), status_controller_->num_encryption_conflicts(), status_controller_->num_hierarchy_conflicts(), status_controller_->num_server_conflicts(),
diff --git a/components/sync/engine_impl/cycle/sync_cycle.h b/components/sync/engine_impl/cycle/sync_cycle.h index 0d8804e..11201dd 100644 --- a/components/sync/engine_impl/cycle/sync_cycle.h +++ b/components/sync/engine_impl/cycle/sync_cycle.h
@@ -56,7 +56,7 @@ // solely based on absolute time values. So, this cannot be used to infer // that any given cycle _instance_ is silenced. An example of reasonable // use is for UI reporting. - virtual bool IsCurrentlyThrottled() = 0; + virtual bool IsAnyThrottleOrBackoff() = 0; // The client has been instructed to change its short poll interval. virtual void OnReceivedShortPollIntervalUpdate(
diff --git a/components/sync/engine_impl/sync_scheduler_impl.cc b/components/sync/engine_impl/sync_scheduler_impl.cc index 58d3e57..8595a3d2 100644 --- a/components/sync/engine_impl/sync_scheduler_impl.cc +++ b/components/sync/engine_impl/sync_scheduler_impl.cc
@@ -287,12 +287,12 @@ bool SyncSchedulerImpl::CanRunJobNow(JobPriority priority) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - if (IsCurrentlyThrottled()) { + if (IsGlobalThrottle()) { SDVLOG(1) << "Unable to run a job because we're throttled."; return false; } - if (IsBackingOff() && priority != CANARY_PRIORITY) { + if (IsGlobalBackoff() && priority != CANARY_PRIORITY) { SDVLOG(1) << "Unable to run a job because we're backing off."; return false; } @@ -512,28 +512,26 @@ } void SyncSchedulerImpl::HandleSuccess() { - // If we're here, then we successfully reached the server. End all backoff. + // If we're here, then we successfully reached the server. End all global + // throttle or backoff. wait_interval_.reset(); - NotifyRetryTime(base::Time()); } void SyncSchedulerImpl::HandleFailure( const ModelNeutralState& model_neutral_state) { - if (IsCurrentlyThrottled()) { + if (IsGlobalThrottle()) { SDVLOG(2) << "Was throttled during previous sync cycle."; - } else if (!IsBackingOff()) { - // Setup our backoff if this is our first such failure. - TimeDelta length = delay_provider_->GetDelay( - delay_provider_->GetInitialDelay(model_neutral_state)); - wait_interval_ = base::MakeUnique<WaitInterval>( - WaitInterval::EXPONENTIAL_BACKOFF, length); - SDVLOG(2) << "Sync cycle failed. Will back off for " - << wait_interval_->length.InMilliseconds() << "ms."; } else { - // Increase our backoff interval and schedule another retry. - TimeDelta length = delay_provider_->GetDelay(wait_interval_->length); + // TODO(skym): Slightly bizarre, the initial SYNC_AUTH_ERROR seems to + // trigger exponential backoff here, although it's immediately retried with + // correct credentials, it'd be nice if things were a bit more clean. + base::TimeDelta previous_delay = + IsGlobalBackoff() + ? wait_interval_->length + : delay_provider_->GetInitialDelay(model_neutral_state); + TimeDelta next_delay = delay_provider_->GetDelay(previous_delay); wait_interval_ = base::MakeUnique<WaitInterval>( - WaitInterval::EXPONENTIAL_BACKOFF, length); + WaitInterval::EXPONENTIAL_BACKOFF, next_delay); SDVLOG(2) << "Sync cycle failed. Will back off for " << wait_interval_->length.InMilliseconds() << "ms."; } @@ -625,7 +623,8 @@ } void SyncSchedulerImpl::RestartWaiting() { - if (wait_interval_.get()) { + NotifyBlockedTypesChanged(); + if (wait_interval_) { // Global throttling or backoff. if (!IsEarlierThanCurrentPendingJob(wait_interval_->length)) { // We check here because if we do not check here, and we already scheduled @@ -656,9 +655,12 @@ if (!IsEarlierThanCurrentPendingJob(time_until_next_unblock)) { return; } + NotifyRetryTime(base::Time::Now() + time_until_next_unblock); pending_wakeup_timer_.Start(FROM_HERE, time_until_next_unblock, base::Bind(&SyncSchedulerImpl::OnTypesUnblocked, weak_ptr_factory_.GetWeakPtr())); + } else { + NotifyRetryTime(base::Time()); } } @@ -722,7 +724,7 @@ } else { // We must be in an error state. Transitioning out of each of these // error states should trigger a canary job. - DCHECK(IsCurrentlyThrottled() || IsBackingOff() || + DCHECK(IsGlobalThrottle() || IsGlobalBackoff() || cycle_context_->connection_manager()->HasInvalidAuthToken()); } @@ -746,8 +748,6 @@ // We're no longer throttled, so clear the wait interval. wait_interval_.reset(); - NotifyRetryTime(base::Time()); - NotifyBlockedTypesChanged(nudge_tracker_.GetBlockedTypes()); // We treat this as a 'canary' in the sense that it was originally scheduled // to run some time ago, failed, and we now want to retry, versus a job that @@ -761,7 +761,6 @@ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); nudge_tracker_.UpdateTypeThrottlingAndBackoffState(); - NotifyBlockedTypesChanged(nudge_tracker_.GetBlockedTypes()); // Maybe this is a good time to run a nudge job. Let's try it. // If not a good time, reschedule a new run. @@ -794,63 +793,63 @@ observer.OnRetryTimeChanged(retry_time); } -void SyncSchedulerImpl::NotifyBlockedTypesChanged(ModelTypeSet types) { +void SyncSchedulerImpl::NotifyBlockedTypesChanged() { + ModelTypeSet types = nudge_tracker_.GetBlockedTypes(); ModelTypeSet throttled_types; ModelTypeSet backed_off_types; for (ModelTypeSet::Iterator type_it = types.First(); type_it.Good(); type_it.Inc()) { - if (nudge_tracker_.GetTypeBlockingMode(type_it.Get()) == - WaitInterval::THROTTLED) { + WaitInterval::BlockingMode mode = + nudge_tracker_.GetTypeBlockingMode(type_it.Get()); + if (mode == WaitInterval::THROTTLED) { throttled_types.Put(type_it.Get()); - } else if (nudge_tracker_.GetTypeBlockingMode(type_it.Get()) == - WaitInterval::EXPONENTIAL_BACKOFF) { + } else if (mode == WaitInterval::EXPONENTIAL_BACKOFF || + mode == WaitInterval::EXPONENTIAL_BACKOFF_RETRYING) { backed_off_types.Put(type_it.Get()); } } for (auto& observer : *cycle_context_->listeners()) { - observer.OnThrottledTypesChanged(throttled_types); - observer.OnBackedOffTypesChanged(backed_off_types); + observer.OnThrottledTypesChanged(IsGlobalThrottle() ? ModelTypeSet::All() + : throttled_types); + observer.OnBackedOffTypesChanged(IsGlobalBackoff() ? ModelTypeSet::All() + : backed_off_types); } } -bool SyncSchedulerImpl::IsBackingOff() const { +bool SyncSchedulerImpl::IsGlobalThrottle() const { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + return wait_interval_ && wait_interval_->mode == WaitInterval::THROTTLED; +} - return wait_interval_.get() && +bool SyncSchedulerImpl::IsGlobalBackoff() const { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + return wait_interval_ && wait_interval_->mode == WaitInterval::EXPONENTIAL_BACKOFF; } void SyncSchedulerImpl::OnThrottled(const TimeDelta& throttle_duration) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - wait_interval_ = base::MakeUnique<WaitInterval>(WaitInterval::THROTTLED, throttle_duration); - NotifyRetryTime(base::Time::Now() + wait_interval_->length); - for (auto& observer : *cycle_context_->listeners()) { observer.OnThrottledTypesChanged(ModelTypeSet::All()); } + RestartWaiting(); } void SyncSchedulerImpl::OnTypesThrottled(ModelTypeSet types, const TimeDelta& throttle_duration) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - - TimeTicks now = TimeTicks::Now(); - SDVLOG(1) << "Throttling " << ModelTypeSetToString(types) << " for " << throttle_duration.InMinutes() << " minutes."; - - nudge_tracker_.SetTypesThrottledUntil(types, throttle_duration, now); - NotifyBlockedTypesChanged(nudge_tracker_.GetBlockedTypes()); + nudge_tracker_.SetTypesThrottledUntil(types, throttle_duration, + TimeTicks::Now()); + RestartWaiting(); } void SyncSchedulerImpl::OnTypesBackedOff(ModelTypeSet types) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - - TimeTicks now = TimeTicks::Now(); - for (ModelTypeSet::Iterator type = types.First(); type.Good(); type.Inc()) { TimeDelta last_backoff_time = TimeDelta::FromSeconds(kInitialBackoffRetrySeconds); @@ -860,18 +859,15 @@ } TimeDelta length = delay_provider_->GetDelay(last_backoff_time); - nudge_tracker_.SetTypeBackedOff(type.Get(), length, now); + nudge_tracker_.SetTypeBackedOff(type.Get(), length, TimeTicks::Now()); SDVLOG(1) << "Backing off " << ModelTypeToString(type.Get()) << " for " << length.InSeconds() << " second."; } - NotifyBlockedTypesChanged(nudge_tracker_.GetBlockedTypes()); + RestartWaiting(); } -bool SyncSchedulerImpl::IsCurrentlyThrottled() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - - return wait_interval_.get() && - wait_interval_->mode == WaitInterval::THROTTLED; +bool SyncSchedulerImpl::IsAnyThrottleOrBackoff() { + return wait_interval_ || nudge_tracker_.IsAnyTypeBlocked(); } void SyncSchedulerImpl::OnReceivedShortPollIntervalUpdate( @@ -965,11 +961,8 @@ } #undef SDVLOG_LOC - #undef SDVLOG - #undef SLOG - #undef ENUM_CASE } // namespace syncer
diff --git a/components/sync/engine_impl/sync_scheduler_impl.h b/components/sync/engine_impl/sync_scheduler_impl.h index d83b038..40d018e 100644 --- a/components/sync/engine_impl/sync_scheduler_impl.h +++ b/components/sync/engine_impl/sync_scheduler_impl.h
@@ -70,7 +70,7 @@ void OnTypesThrottled(ModelTypeSet types, const base::TimeDelta& throttle_duration) override; void OnTypesBackedOff(ModelTypeSet types) override; - bool IsCurrentlyThrottled() override; + bool IsAnyThrottleOrBackoff() override; void OnReceivedShortPollIntervalUpdate( const base::TimeDelta& new_interval) override; void OnReceivedLongPollIntervalUpdate( @@ -83,8 +83,8 @@ void OnReceivedGuRetryDelay(const base::TimeDelta& delay) override; void OnReceivedMigrationRequest(ModelTypeSet types) override; - // Returns true if the client is currently in exponential backoff. - bool IsBackingOff() const; + bool IsGlobalThrottle() const; + bool IsGlobalBackoff() const; // Changes the default delay between nudge cycles. Model-type specific // overrides will still apply. This is made public so that nudge cycles can be @@ -174,7 +174,7 @@ void NotifyRetryTime(base::Time retry_time); // Helper to signal listeners about changed throttled or backed off types. - void NotifyBlockedTypesChanged(ModelTypeSet types); + void NotifyBlockedTypesChanged(); // Looks for pending work and, if it finds any, run this work at "canary" // priority.
diff --git a/components/sync/engine_impl/sync_scheduler_impl_unittest.cc b/components/sync/engine_impl/sync_scheduler_impl_unittest.cc index e6a5c65..ca018cd4 100644 --- a/components/sync/engine_impl/sync_scheduler_impl_unittest.cc +++ b/components/sync/engine_impl/sync_scheduler_impl_unittest.cc
@@ -205,7 +205,7 @@ scheduler()->ScheduleLocalNudge(nudge_types, FROM_HERE); RunLoop(); - return scheduler()->IsBackingOff(); + return scheduler()->IsGlobalBackoff(); } void UseMockDelayProvider() { @@ -854,9 +854,9 @@ PumpLoop(); // To get PerformDelayedNudge called. PumpLoop(); // To get TrySyncCycleJob called - EXPECT_TRUE(scheduler()->IsCurrentlyThrottled()); + EXPECT_TRUE(scheduler()->IsGlobalThrottle()); RunLoop(); - EXPECT_FALSE(scheduler()->IsCurrentlyThrottled()); + EXPECT_FALSE(scheduler()->IsGlobalThrottle()); StopSyncScheduler(); } @@ -889,10 +889,10 @@ PumpLoop(); EXPECT_EQ(0, ready_counter.times_called()); EXPECT_EQ(1, retry_counter.times_called()); - EXPECT_TRUE(scheduler()->IsCurrentlyThrottled()); + EXPECT_TRUE(scheduler()->IsGlobalThrottle()); RunLoop(); - EXPECT_FALSE(scheduler()->IsCurrentlyThrottled()); + EXPECT_FALSE(scheduler()->IsGlobalThrottle()); StopSyncScheduler(); } @@ -916,8 +916,8 @@ PumpLoop(); // To get PerformDelayedNudge called. PumpLoop(); // To get TrySyncCycleJob called EXPECT_TRUE(GetThrottledTypes().HasAll(types)); - EXPECT_FALSE(scheduler()->IsBackingOff()); - EXPECT_FALSE(scheduler()->IsCurrentlyThrottled()); + EXPECT_FALSE(scheduler()->IsGlobalBackoff()); + EXPECT_FALSE(scheduler()->IsGlobalThrottle()); // This won't cause a sync cycle because the types are throttled. scheduler()->ScheduleLocalNudge(types, FROM_HERE); @@ -946,8 +946,8 @@ PumpLoop(); // To get PerformDelayedNudge called. PumpLoop(); // To get TrySyncCycleJob called EXPECT_TRUE(GetBackedOffTypes().HasAll(types)); - EXPECT_FALSE(scheduler()->IsBackingOff()); - EXPECT_FALSE(scheduler()->IsCurrentlyThrottled()); + EXPECT_FALSE(scheduler()->IsGlobalBackoff()); + EXPECT_FALSE(scheduler()->IsGlobalThrottle()); // This won't cause a sync cycle because the types are backed off. scheduler()->ScheduleLocalNudge(types, FROM_HERE); @@ -976,8 +976,8 @@ PumpLoop(); // To get PerformDelayedNudge called. PumpLoop(); // To get TrySyncCycleJob called EXPECT_TRUE(GetBackedOffTypes().HasAll(types)); - EXPECT_FALSE(scheduler()->IsBackingOff()); - EXPECT_FALSE(scheduler()->IsCurrentlyThrottled()); + EXPECT_FALSE(scheduler()->IsGlobalBackoff()); + EXPECT_FALSE(scheduler()->IsGlobalThrottle()); SyncShareTimes times; EXPECT_CALL(*syncer(), NormalSyncShare(_, _, _)) @@ -986,8 +986,8 @@ PumpLoop(); // To get PerformDelayedNudge called. PumpLoop(); // To get TrySyncCycleJob called EXPECT_FALSE(IsAnyTypeBlocked()); - EXPECT_FALSE(scheduler()->IsBackingOff()); - EXPECT_FALSE(scheduler()->IsCurrentlyThrottled()); + EXPECT_FALSE(scheduler()->IsGlobalBackoff()); + EXPECT_FALSE(scheduler()->IsGlobalThrottle()); StopSyncScheduler(); } @@ -1013,8 +1013,8 @@ PumpLoop(); // To get TrySyncCycleJob called EXPECT_TRUE(GetBackedOffTypes().HasAll(types)); EXPECT_TRUE(BlockTimerIsRunning()); - EXPECT_FALSE(scheduler()->IsBackingOff()); - EXPECT_FALSE(scheduler()->IsCurrentlyThrottled()); + EXPECT_FALSE(scheduler()->IsGlobalBackoff()); + EXPECT_FALSE(scheduler()->IsGlobalThrottle()); TimeDelta throttle1(TimeDelta::FromMilliseconds(150)); @@ -1031,8 +1031,8 @@ EXPECT_TRUE(GetBackedOffTypes().HasAll(types)); EXPECT_TRUE(BlockTimerIsRunning()); - EXPECT_FALSE(scheduler()->IsBackingOff()); - EXPECT_TRUE(scheduler()->IsCurrentlyThrottled()); + EXPECT_FALSE(scheduler()->IsGlobalBackoff()); + EXPECT_TRUE(scheduler()->IsGlobalThrottle()); // Unthrottled client, but the backingoff datatype is still in backoff and // scheduled. @@ -1040,7 +1040,7 @@ .WillOnce(DoAll(Invoke(test_util::SimulateNormalSuccess), QuitLoopNowAction(true))); RunLoop(); - EXPECT_FALSE(scheduler()->IsCurrentlyThrottled()); + EXPECT_FALSE(scheduler()->IsGlobalThrottle()); EXPECT_TRUE(GetBackedOffTypes().HasAll(types)); EXPECT_TRUE(BlockTimerIsRunning()); @@ -1085,8 +1085,8 @@ EXPECT_TRUE(GetThrottledTypes().HasAll(throttled_types)); EXPECT_TRUE(GetBackedOffTypes().HasAll(backed_off_types)); EXPECT_TRUE(BlockTimerIsRunning()); - EXPECT_FALSE(scheduler()->IsBackingOff()); - EXPECT_FALSE(scheduler()->IsCurrentlyThrottled()); + EXPECT_FALSE(scheduler()->IsGlobalBackoff()); + EXPECT_FALSE(scheduler()->IsGlobalThrottle()); // This won't cause a sync cycle because the types are throttled or backed // off. @@ -1121,8 +1121,8 @@ PumpLoop(); // To get PerformDelayedNudge called. PumpLoop(); // To get TrySyncCycleJob called EXPECT_TRUE(GetThrottledTypes().HasAll(throttled_types)); - EXPECT_FALSE(scheduler()->IsBackingOff()); - EXPECT_FALSE(scheduler()->IsCurrentlyThrottled()); + EXPECT_FALSE(scheduler()->IsGlobalBackoff()); + EXPECT_FALSE(scheduler()->IsGlobalThrottle()); // Ignore invalidations for throttled types. scheduler()->ScheduleInvalidationNudge(THEMES, BuildInvalidation(10, "test"), @@ -1169,8 +1169,8 @@ PumpLoop(); // To get PerformDelayedNudge called. PumpLoop(); // To get TrySyncCycleJob called EXPECT_TRUE(GetBackedOffTypes().HasAll(backed_off_types)); - EXPECT_FALSE(scheduler()->IsBackingOff()); - EXPECT_FALSE(scheduler()->IsCurrentlyThrottled()); + EXPECT_FALSE(scheduler()->IsGlobalBackoff()); + EXPECT_FALSE(scheduler()->IsGlobalThrottle()); // Ignore invalidations for backed off types. scheduler()->ScheduleInvalidationNudge(THEMES, BuildInvalidation(10, "test"), @@ -1313,7 +1313,7 @@ scheduler()->ScheduleConfiguration(params); RunLoop(); - EXPECT_TRUE(scheduler()->IsBackingOff()); + EXPECT_TRUE(scheduler()->IsGlobalBackoff()); } // Test that no polls or extraneous nudges occur when in backoff. @@ -1486,11 +1486,11 @@ // Run the unsuccessful poll. The failed poll should not trigger backoff. RunLoop(); - EXPECT_TRUE(scheduler()->IsBackingOff()); + EXPECT_TRUE(scheduler()->IsGlobalBackoff()); // Run the successful poll. RunLoop(); - EXPECT_FALSE(scheduler()->IsBackingOff()); + EXPECT_FALSE(scheduler()->IsGlobalBackoff()); } // Test that starting the syncer thread without a valid connection doesn't @@ -1531,7 +1531,7 @@ scheduler()->ScheduleLocalNudge(ModelTypeSet(THEMES), FROM_HERE); PumpLoop(); // To get PerformDelayedNudge called. PumpLoop(); // Run the nudge, that will fail and schedule a quick retry. - ASSERT_TRUE(scheduler()->IsBackingOff()); + ASSERT_TRUE(scheduler()->IsGlobalBackoff()); // Before we run the scheduled canary, trigger a server connection change. scheduler()->OnConnectionStatusChange(); @@ -1563,7 +1563,7 @@ PumpLoop(); // To get PerformDelayedNudge called. PumpLoop(); // Run the nudge, that will fail and schedule a quick retry. - ASSERT_TRUE(scheduler()->IsBackingOff()); + ASSERT_TRUE(scheduler()->IsGlobalBackoff()); // Before we run the scheduled canary, trigger a server connection change. scheduler()->OnConnectionStatusChange(); @@ -1665,7 +1665,7 @@ // Run to wait for retrying. RunLoop(); - EXPECT_TRUE(scheduler()->IsBackingOff()); + EXPECT_TRUE(scheduler()->IsGlobalBackoff()); EXPECT_CALL(*syncer(), NormalSyncShare(_, _, _)) .WillOnce(DoAll(Invoke(test_util::SimulateNormalSuccess), RecordSyncShare(×, true))); @@ -1738,13 +1738,13 @@ scheduler()->ScheduleClearServerData(params); PumpLoop(); ASSERT_EQ(0, success_counter.times_called()); - ASSERT_TRUE(scheduler()->IsBackingOff()); + ASSERT_TRUE(scheduler()->IsGlobalBackoff()); // Now succeed. connection()->SetServerReachable(); PumpLoopFor(2 * delta); ASSERT_EQ(1, success_counter.times_called()); - ASSERT_FALSE(scheduler()->IsBackingOff()); + ASSERT_FALSE(scheduler()->IsGlobalBackoff()); } TEST_F(SyncSchedulerImplTest, PartialFailureWillExponentialBackoff) { @@ -1764,8 +1764,8 @@ PumpLoop(); // To get PerformDelayedNudge called. PumpLoop(); // To get TrySyncCycleJob called EXPECT_TRUE(GetBackedOffTypes().HasAll(types)); - EXPECT_FALSE(scheduler()->IsBackingOff()); - EXPECT_FALSE(scheduler()->IsCurrentlyThrottled()); + EXPECT_FALSE(scheduler()->IsGlobalBackoff()); + EXPECT_FALSE(scheduler()->IsGlobalThrottle()); TimeDelta first_blocking_time = GetTypeBlockingTime(THEMES); SetTypeBlockingMode(THEMES, WaitInterval::EXPONENTIAL_BACKOFF_RETRYING); @@ -1811,8 +1811,8 @@ PumpLoop(); // To get TrySyncCycleJob called EXPECT_TRUE(GetBackedOffTypes().HasAll(types)); EXPECT_TRUE(BlockTimerIsRunning()); - EXPECT_FALSE(scheduler()->IsBackingOff()); - EXPECT_FALSE(scheduler()->IsCurrentlyThrottled()); + EXPECT_FALSE(scheduler()->IsGlobalBackoff()); + EXPECT_FALSE(scheduler()->IsGlobalThrottle()); SyncShareTimes times; EXPECT_CALL(*syncer(), NormalSyncShare(_, _, _)) @@ -1829,8 +1829,8 @@ // Timer is still running for backoff datatype after Sync success. EXPECT_TRUE(GetBackedOffTypes().HasAll(types)); EXPECT_TRUE(BlockTimerIsRunning()); - EXPECT_FALSE(scheduler()->IsBackingOff()); - EXPECT_FALSE(scheduler()->IsCurrentlyThrottled()); + EXPECT_FALSE(scheduler()->IsGlobalBackoff()); + EXPECT_FALSE(scheduler()->IsGlobalThrottle()); StopSyncScheduler(); } @@ -1861,8 +1861,8 @@ PumpLoop(); // To get TrySyncCycleJob called EXPECT_TRUE(GetBackedOffTypes().HasAll(themes_types)); EXPECT_TRUE(BlockTimerIsRunning()); - EXPECT_FALSE(scheduler()->IsBackingOff()); - EXPECT_FALSE(scheduler()->IsCurrentlyThrottled()); + EXPECT_FALSE(scheduler()->IsGlobalBackoff()); + EXPECT_FALSE(scheduler()->IsGlobalThrottle()); // Set anther backoff datatype. const ModelTypeSet typed_urls_types(TYPED_URLS); @@ -1882,8 +1882,8 @@ EXPECT_TRUE(GetBackedOffTypes().HasAll(themes_types)); EXPECT_TRUE(GetBackedOffTypes().HasAll(typed_urls_types)); EXPECT_TRUE(BlockTimerIsRunning()); - EXPECT_FALSE(scheduler()->IsBackingOff()); - EXPECT_FALSE(scheduler()->IsCurrentlyThrottled()); + EXPECT_FALSE(scheduler()->IsGlobalBackoff()); + EXPECT_FALSE(scheduler()->IsGlobalThrottle()); // Unblock one datatype. SyncShareTimes times; @@ -1899,8 +1899,8 @@ EXPECT_TRUE(GetBackedOffTypes().HasAll(themes_types)); EXPECT_FALSE(GetBackedOffTypes().HasAll(typed_urls_types)); EXPECT_TRUE(BlockTimerIsRunning()); - EXPECT_FALSE(scheduler()->IsBackingOff()); - EXPECT_FALSE(scheduler()->IsCurrentlyThrottled()); + EXPECT_FALSE(scheduler()->IsGlobalBackoff()); + EXPECT_FALSE(scheduler()->IsGlobalThrottle()); StopSyncScheduler(); } @@ -1917,14 +1917,14 @@ scheduler()->ScheduleLocalNudge({THEMES}, FROM_HERE); PumpLoop(); // To get PerformDelayedNudge called. EXPECT_FALSE(BlockTimerIsRunning()); - EXPECT_FALSE(scheduler()->IsBackingOff()); + EXPECT_FALSE(scheduler()->IsGlobalBackoff()); // This is the tricky piece. We have a gap while the sync job is bouncing to // get onto the |pending_wakeup_timer_|, should be scheduled with no delay. scheduler()->ScheduleLocalNudge({TYPED_URLS}, FROM_HERE); EXPECT_TRUE(BlockTimerIsRunning()); EXPECT_EQ(TimeDelta(), GetPendingWakeupTimerDelay()); - EXPECT_FALSE(scheduler()->IsBackingOff()); + EXPECT_FALSE(scheduler()->IsGlobalBackoff()); // Setup mock as we're about to attempt to sync. SyncShareTimes times; @@ -1937,7 +1937,7 @@ PumpLoop(); EXPECT_TRUE(BlockTimerIsRunning()); EXPECT_EQ(TimeDelta(), GetPendingWakeupTimerDelay()); - EXPECT_TRUE(scheduler()->IsBackingOff()); + EXPECT_TRUE(scheduler()->IsGlobalBackoff()); // Triggers TYPED_URLS PerformDelayedNudge(), which should no-op, because // we're no long healthy, and normal priorities shouldn't go through, but it @@ -1946,7 +1946,7 @@ PumpLoop(); EXPECT_TRUE(BlockTimerIsRunning()); EXPECT_LT(TimeDelta::FromSeconds(50), GetPendingWakeupTimerDelay()); - EXPECT_TRUE(scheduler()->IsBackingOff()); + EXPECT_TRUE(scheduler()->IsGlobalBackoff()); } } // namespace syncer
diff --git a/components/sync/engine_impl/syncer_unittest.cc b/components/sync/engine_impl/syncer_unittest.cc index 5f75d5a..9eb8a88f 100644 --- a/components/sync/engine_impl/syncer_unittest.cc +++ b/components/sync/engine_impl/syncer_unittest.cc
@@ -193,7 +193,7 @@ void OnTypesBackedOff(ModelTypeSet types) override { scheduler_->OnTypesBackedOff(types); } - bool IsCurrentlyThrottled() override { return false; } + bool IsAnyThrottleOrBackoff() override { return false; } void OnReceivedLongPollIntervalUpdate( const base::TimeDelta& new_interval) override { last_long_poll_interval_received_ = new_interval;
diff --git a/components/sync/test/engine/fake_sync_scheduler.cc b/components/sync/test/engine/fake_sync_scheduler.cc index 1b879cb..8a91921 100644 --- a/components/sync/test/engine/fake_sync_scheduler.cc +++ b/components/sync/test/engine/fake_sync_scheduler.cc
@@ -52,7 +52,7 @@ void FakeSyncScheduler::OnTypesBackedOff(ModelTypeSet types) {} -bool FakeSyncScheduler::IsCurrentlyThrottled() { +bool FakeSyncScheduler::IsAnyThrottleOrBackoff() { return false; }
diff --git a/components/sync/test/engine/fake_sync_scheduler.h b/components/sync/test/engine/fake_sync_scheduler.h index 6982fc7..70347f4 100644 --- a/components/sync/test/engine/fake_sync_scheduler.h +++ b/components/sync/test/engine/fake_sync_scheduler.h
@@ -47,7 +47,7 @@ void OnTypesThrottled(ModelTypeSet types, const base::TimeDelta& throttle_duration) override; void OnTypesBackedOff(ModelTypeSet types) override; - bool IsCurrentlyThrottled() override; + bool IsAnyThrottleOrBackoff() override; void OnReceivedShortPollIntervalUpdate( const base::TimeDelta& new_interval) override; void OnReceivedLongPollIntervalUpdate(
diff --git a/components/sync/user_events/user_event_service_impl.cc b/components/sync/user_events/user_event_service_impl.cc index 2c692724..e4e2c0e1 100644 --- a/components/sync/user_events/user_event_service_impl.cc +++ b/components/sync/user_events/user_event_service_impl.cc
@@ -61,9 +61,9 @@ bool UserEventServiceImpl::ShouldRecordEvent( const UserEventSpecifics& specifics) { - // We only record events if the user is syncing history and has not enabled - // a custom passphrase. The type HISTORY_DELETE_DIRECTIVES is enabled in and - // only in this exact scenario. + // We only record events if the user is syncing history (as indicated by + // GetPreferredDataTypes()) and has not enabled a custom passphrase (as + // indicated by IsUsingSecondaryPassphrase()). return sync_service_->IsEngineInitialized() && !sync_service_->IsUsingSecondaryPassphrase() && sync_service_->GetPreferredDataTypes().Has(HISTORY_DELETE_DIRECTIVES);
diff --git a/components/sync/user_events/user_event_service_impl_unittest.cc b/components/sync/user_events/user_event_service_impl_unittest.cc index 083565e..eee46dd 100644 --- a/components/sync/user_events/user_event_service_impl_unittest.cc +++ b/components/sync/user_events/user_event_service_impl_unittest.cc
@@ -24,11 +24,17 @@ class TestSyncService : public FakeSyncService { public: - TestSyncService(bool is_engine_initialized, ModelTypeSet preferred_data_types) + TestSyncService(bool is_engine_initialized, + bool is_using_secondary_passphrase, + ModelTypeSet preferred_data_types) : is_engine_initialized_(is_engine_initialized), + is_using_secondary_passphrase_(is_using_secondary_passphrase), preferred_data_types_(preferred_data_types) {} bool IsEngineInitialized() const override { return is_engine_initialized_; } + bool IsUsingSecondaryPassphrase() const override { + return is_using_secondary_passphrase_; + } ModelTypeSet GetPreferredDataTypes() const override { return preferred_data_types_; @@ -36,6 +42,7 @@ private: bool is_engine_initialized_; + bool is_using_secondary_passphrase_; ModelTypeSet preferred_data_types_; }; @@ -47,7 +54,7 @@ class UserEventServiceImplTest : public testing::Test { protected: UserEventServiceImplTest() - : sync_service_(true, ModelTypeSet(HISTORY_DELETE_DIRECTIVES)) {} + : sync_service_(true, false, {HISTORY_DELETE_DIRECTIVES}) {} std::unique_ptr<UserEventSyncBridge> MakeBridge() { return base::MakeUnique<UserEventSyncBridge>( @@ -83,15 +90,23 @@ } TEST_F(UserEventServiceImplTest, ShouldNotRecordNoHistory) { - TestSyncService no_history_sync_service(true, ModelTypeSet()); + TestSyncService no_history_sync_service(true, false, ModelTypeSet()); UserEventServiceImpl service(&no_history_sync_service, MakeBridge()); service.RecordUserEvent(base::MakeUnique<UserEventSpecifics>()); EXPECT_EQ(0u, processor().put_multimap().size()); } +TEST_F(UserEventServiceImplTest, ShouldNotRecordPassphrase) { + TestSyncService passphrase_sync_service(true, true, + {HISTORY_DELETE_DIRECTIVES}); + UserEventServiceImpl service(&passphrase_sync_service, MakeBridge()); + service.RecordUserEvent(base::MakeUnique<UserEventSpecifics>()); + EXPECT_EQ(0u, processor().put_multimap().size()); +} + TEST_F(UserEventServiceImplTest, ShouldNotRecordEngineOff) { TestSyncService engine_not_initialized_sync_service( - false, ModelTypeSet(HISTORY_DELETE_DIRECTIVES)); + false, false, {HISTORY_DELETE_DIRECTIVES}); UserEventServiceImpl service(&engine_not_initialized_sync_service, MakeBridge()); service.RecordUserEvent(base::MakeUnique<UserEventSpecifics>());
diff --git a/components/viz/PRESUBMIT.py b/components/viz/PRESUBMIT.py index a3b3d1b..c8bef10 100644 --- a/components/viz/PRESUBMIT.py +++ b/components/viz/PRESUBMIT.py
@@ -2,317 +2,15 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -"""Top-level presubmit script for components/viz. - -See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts -for more details about the presubmit API built into depot_tools. -""" - -import re -import string - -VIZ_SOURCE_FILES=(r'^components[\\/]viz[\\/].*\.(cc|h)$',) - -def CheckChangeLintsClean(input_api, output_api): - source_filter = lambda x: input_api.FilterSourceFile( - x, white_list=VIZ_SOURCE_FILES, black_list=None) - - return input_api.canned_checks.CheckChangeLintsClean( - input_api, output_api, source_filter, lint_filters=[], verbose_level=1) - -def CheckAsserts(input_api, output_api, white_list=VIZ_SOURCE_FILES, black_list=None): - black_list = tuple(black_list or input_api.DEFAULT_BLACK_LIST) - source_file_filter = lambda x: input_api.FilterSourceFile(x, white_list, black_list) - - assert_files = [] - - for f in input_api.AffectedSourceFiles(source_file_filter): - contents = input_api.ReadFile(f, 'rb') - # WebKit ASSERT() is not allowed. - if re.search(r"\bASSERT\(", contents): - assert_files.append(f.LocalPath()) - - if assert_files: - return [output_api.PresubmitError( - 'These files use ASSERT instead of using DCHECK:', - items=assert_files)] - return [] - -def CheckStdAbs(input_api, output_api, - white_list=VIZ_SOURCE_FILES, black_list=None): - black_list = tuple(black_list or input_api.DEFAULT_BLACK_LIST) - source_file_filter = lambda x: input_api.FilterSourceFile(x, - white_list, - black_list) - - using_std_abs_files = [] - found_fabs_files = [] - missing_std_prefix_files = [] - - for f in input_api.AffectedSourceFiles(source_file_filter): - contents = input_api.ReadFile(f, 'rb') - if re.search(r"using std::f?abs;", contents): - using_std_abs_files.append(f.LocalPath()) - if re.search(r"\bfabsf?\(", contents): - found_fabs_files.append(f.LocalPath()); - - no_std_prefix = r"(?<!std::)" - # Matches occurrences of abs/absf/fabs/fabsf without a "std::" prefix. - abs_without_prefix = r"%s(\babsf?\()" % no_std_prefix - fabs_without_prefix = r"%s(\bfabsf?\()" % no_std_prefix - # Skips matching any lines that have "// NOLINT". - no_nolint = r"(?![^\n]*//\s+NOLINT)" - - expression = re.compile("(%s|%s)%s" % - (abs_without_prefix, fabs_without_prefix, no_nolint)) - if expression.search(contents): - missing_std_prefix_files.append(f.LocalPath()) - - result = [] - if using_std_abs_files: - result.append(output_api.PresubmitError( - 'These files have "using std::abs" which is not permitted.', - items=using_std_abs_files)) - if found_fabs_files: - result.append(output_api.PresubmitError( - 'std::abs() should be used instead of std::fabs() for consistency.', - items=found_fabs_files)) - if missing_std_prefix_files: - result.append(output_api.PresubmitError( - 'These files use abs(), absf(), fabs(), or fabsf() without qualifying ' - 'the std namespace. Please use std::abs() in all places.', - items=missing_std_prefix_files)) - return result - -def CheckPassByValue(input_api, - output_api, - white_list=VIZ_SOURCE_FILES, - black_list=None): - black_list = tuple(black_list or input_api.DEFAULT_BLACK_LIST) - source_file_filter = lambda x: input_api.FilterSourceFile(x, - white_list, - black_list) - - local_errors = [] - - # Well-defined simple classes the same size as a primitive type. - pass_by_value_types = ['base::Time', - 'base::TimeTicks', - ] - - for f in input_api.AffectedSourceFiles(source_file_filter): - contents = input_api.ReadFile(f, 'rb') - match = re.search( - r'\bconst +' + '(?P<type>(%s))&' % - string.join(pass_by_value_types, '|'), - contents) - if match: - local_errors.append(output_api.PresubmitError( - '%s passes %s by const ref instead of by value.' % - (f.LocalPath(), match.group('type')))) - return local_errors - -def CheckTodos(input_api, output_api): - errors = [] - - source_file_filter = lambda x: x - for f in input_api.AffectedSourceFiles(source_file_filter): - contents = input_api.ReadFile(f, 'rb') - if ('FIX'+'ME') in contents: - errors.append(f.LocalPath()) - - if errors: - return [output_api.PresubmitError( - 'All TODO comments should be of the form TODO(name/bug). ' + - 'Use TODO instead of FIX' + 'ME', - items=errors)] - return [] - -def CheckDoubleAngles(input_api, output_api, white_list=VIZ_SOURCE_FILES, - black_list=None): - errors = [] - - source_file_filter = lambda x: input_api.FilterSourceFile(x, - white_list, - black_list) - for f in input_api.AffectedSourceFiles(source_file_filter): - contents = input_api.ReadFile(f, 'rb') - if ('> >') in contents: - errors.append(f.LocalPath()) - - if errors: - return [output_api.PresubmitError('Use >> instead of > >:', items=errors)] - return [] - -def CheckUniquePtr(input_api, output_api, - white_list=VIZ_SOURCE_FILES, black_list=None): - black_list = tuple(black_list or input_api.DEFAULT_BLACK_LIST) - source_file_filter = lambda x: input_api.FilterSourceFile(x, - white_list, - black_list) - errors = [] - for f in input_api.AffectedSourceFiles(source_file_filter): - for line_number, line in f.ChangedContents(): - # Disallow: - # return std::unique_ptr<T>(foo); - # bar = std::unique_ptr<T>(foo); - # But allow: - # return std::unique_ptr<T[]>(foo); - # bar = std::unique_ptr<T[]>(foo); - if re.search(r'(=|\breturn)\s*std::unique_ptr<.*?(?<!])>\([^)]+\)', line): - errors.append(output_api.PresubmitError( - ('%s:%d uses explicit std::unique_ptr constructor. ' + - 'Use base::MakeUnique<T>() instead.') % - (f.LocalPath(), line_number))) - # Disallow: - # std::unique_ptr<T>() - if re.search(r'\bstd::unique_ptr<.*?>\(\)', line): - errors.append(output_api.PresubmitError( - '%s:%d uses std::unique_ptr<T>(). Use nullptr instead.' % - (f.LocalPath(), line_number))) - return errors - -def FindUnquotedQuote(contents, pos): - match = re.search(r"(?<!\\)(?P<quote>\")", contents[pos:]) - return -1 if not match else match.start("quote") + pos - -def FindUselessIfdefs(input_api, output_api): - errors = [] - source_file_filter = lambda x: x - for f in input_api.AffectedSourceFiles(source_file_filter): - contents = input_api.ReadFile(f, 'rb') - if re.search(r'#if\s*0\s', contents): - errors.append(f.LocalPath()) - if errors: - return [output_api.PresubmitError( - 'Don\'t use #if '+'0; just delete the code.', - items=errors)] - return [] - -def FindNamespaceInBlock(pos, namespace, contents, whitelist=[]): - open_brace = -1 - close_brace = -1 - quote = -1 - name = -1 - brace_count = 1 - quote_count = 0 - while pos < len(contents) and brace_count > 0: - if open_brace < pos: open_brace = contents.find("{", pos) - if close_brace < pos: close_brace = contents.find("}", pos) - if quote < pos: quote = FindUnquotedQuote(contents, pos) - if name < pos: name = contents.find(("%s::" % namespace), pos) - - if name < 0: - return False # The namespace is not used at all. - if open_brace < 0: - open_brace = len(contents) - if close_brace < 0: - close_brace = len(contents) - if quote < 0: - quote = len(contents) - - next = min(open_brace, min(close_brace, min(quote, name))) - - if next == open_brace: - brace_count += 1 - elif next == close_brace: - brace_count -= 1 - elif next == quote: - quote_count = 0 if quote_count else 1 - elif next == name and not quote_count: - in_whitelist = False - for w in whitelist: - if re.match(w, contents[next:]): - in_whitelist = True - break - if not in_whitelist: - return True - pos = next + 1 - return False - -# Checks for the use of viz:: within the viz namespace, which is usually -# redundant. -def CheckNamespace(input_api, output_api): - errors = [] - - source_file_filter = lambda x: x - for f in input_api.AffectedSourceFiles(source_file_filter): - contents = input_api.ReadFile(f, 'rb') - match = re.search(r'namespace\s*viz\s*{', contents) - if match: - whitelist = [] - if FindNamespaceInBlock(match.end(), 'viz', contents, whitelist=whitelist): - errors.append(f.LocalPath()) - - if errors: - return [output_api.PresubmitError( - 'Do not use viz:: inside of the viz namespace.', - items=errors)] - return [] - -def CheckForUseOfWrongClock(input_api, - output_api, - white_list=VIZ_SOURCE_FILES, - black_list=None): - """Make sure new lines of code don't use a clock susceptible to skew.""" - black_list = tuple(black_list or input_api.DEFAULT_BLACK_LIST) - source_file_filter = lambda x: input_api.FilterSourceFile(x, - white_list, - black_list) - # Regular expression that should detect any explicit references to the - # base::Time type (or base::Clock/DefaultClock), whether in using decls, - # typedefs, or to call static methods. - base_time_type_pattern = r'(^|\W)base::(Time|Clock|DefaultClock)(\W|$)' - - # Regular expression that should detect references to the base::Time class - # members, such as a call to base::Time::Now. - base_time_member_pattern = r'(^|\W)(Time|Clock|DefaultClock)::' - - # Regular expression to detect "using base::Time" declarations. We want to - # prevent these from triggerring a warning. For example, it's perfectly - # reasonable for code to be written like this: - # - # using base::Time; - # ... - # int64 foo_us = foo_s * Time::kMicrosecondsPerSecond; - using_base_time_decl_pattern = r'^\s*using\s+(::)?base::Time\s*;' - - # Regular expression to detect references to the kXXX constants in the - # base::Time class. We want to prevent these from triggerring a warning. - base_time_konstant_pattern = r'(^|\W)Time::k\w+' - - problem_re = input_api.re.compile( - r'(' + base_time_type_pattern + r')|(' + base_time_member_pattern + r')') - exception_re = input_api.re.compile( - r'(' + using_base_time_decl_pattern + r')|(' + - base_time_konstant_pattern + r')') - problems = [] - for f in input_api.AffectedSourceFiles(source_file_filter): - for line_number, line in f.ChangedContents(): - if problem_re.search(line): - if not exception_re.search(line): - problems.append( - ' %s:%d\n %s' % (f.LocalPath(), line_number, line.strip())) - - if problems: - return [output_api.PresubmitPromptOrNotify( - 'You added one or more references to the base::Time class and/or one\n' - 'of its member functions (or base::Clock/DefaultClock). In cc code,\n' - 'it is most certainly incorrect! Instead use base::TimeTicks.\n\n' - '\n'.join(problems))] - else: - return [] +"""Top-level presubmit script for components/viz.""" def CheckChangeOnUpload(input_api, output_api): - results = [] - results += CheckAsserts(input_api, output_api) - results += CheckStdAbs(input_api, output_api) - results += CheckPassByValue(input_api, output_api) - results += CheckChangeLintsClean(input_api, output_api) - results += CheckTodos(input_api, output_api) - results += CheckDoubleAngles(input_api, output_api) - results += CheckUniquePtr(input_api, output_api) - results += CheckNamespace(input_api, output_api) - results += CheckForUseOfWrongClock(input_api, output_api) - results += FindUselessIfdefs(input_api, output_api) - return results + import sys + original_sys_path = sys.path + sys.path = sys.path + [input_api.os_path.join( + input_api.change.RepositoryRoot(), + 'components', 'viz')] + + import presubmit_checks as ps + white_list=(r'^components[\\/]viz[\\/].*\.(cc|h)$',) + return ps.RunAllChecks(input_api, output_api, white_list)
diff --git a/components/viz/host/host_frame_sink_manager_unittests.cc b/components/viz/host/host_frame_sink_manager_unittests.cc index bd89d4f3..1571f91 100644 --- a/components/viz/host/host_frame_sink_manager_unittests.cc +++ b/components/viz/host/host_frame_sink_manager_unittests.cc
@@ -24,8 +24,9 @@ namespace test { namespace { -constexpr FrameSinkId kParentFrameSinkId(1, 1); -constexpr FrameSinkId kClientFrameSinkId(2, 1); +constexpr FrameSinkId kFrameSinkParent1(1, 1); +constexpr FrameSinkId kFrameSinkParent2(2, 1); +constexpr FrameSinkId kFrameSinkChild1(3, 1); // Makes a SurfaceId with a default nonce. SurfaceId MakeSurfaceId(const FrameSinkId& frame_sink_id, uint32_t local_id) { @@ -91,9 +92,9 @@ HostFrameSinkManagerTest() = default; ~HostFrameSinkManagerTest() override = default; - HostFrameSinkManager& host_manager() { return *host_manager_; } + HostFrameSinkManager& host() { return *host_manager_; } - MockFrameSinkManagerImpl& manager_impl() { return *manager_impl_; } + MockFrameSinkManagerImpl& impl() { return *manager_impl_; } std::unique_ptr<CompositorFrameSinkSupport> CreateCompositorFrameSinkSupport( const FrameSinkId& frame_sink_id, @@ -138,105 +139,99 @@ TEST_F(HostFrameSinkManagerTest, CreateMojomCompositorFrameSink) { // Calling CreateCompositorFrameSink() should first register the frame sink // and then request to create it. - EXPECT_CALL(manager_impl(), RegisterFrameSinkId(kClientFrameSinkId)); + EXPECT_CALL(impl(), RegisterFrameSinkId(kFrameSinkChild1)); FakeHostFrameSinkClient client; - host_manager().RegisterFrameSinkId(kClientFrameSinkId, &client); + host().RegisterFrameSinkId(kFrameSinkChild1, &client); - EXPECT_CALL(manager_impl(), - MockCreateCompositorFrameSink(kClientFrameSinkId)); - host_manager().CreateCompositorFrameSink( - kClientFrameSinkId, nullptr /* request */, nullptr /* client */); + EXPECT_CALL(impl(), MockCreateCompositorFrameSink(kFrameSinkChild1)); + host().CreateCompositorFrameSink(kFrameSinkChild1, nullptr /* request */, + nullptr /* client */); - EXPECT_TRUE(FrameSinkDataExists(kClientFrameSinkId)); + EXPECT_TRUE(FrameSinkDataExists(kFrameSinkChild1)); // Register should call through to FrameSinkManagerImpl and should work even - // though |kParentFrameSinkId| was not created yet. - EXPECT_CALL(manager_impl(), RegisterFrameSinkHierarchy(kParentFrameSinkId, - kClientFrameSinkId)); - host_manager().RegisterFrameSinkHierarchy(kParentFrameSinkId, - kClientFrameSinkId); + // though |kFrameSinkParent1| was not created yet. + EXPECT_CALL(impl(), + RegisterFrameSinkHierarchy(kFrameSinkParent1, kFrameSinkChild1)); + host().RegisterFrameSinkHierarchy(kFrameSinkParent1, kFrameSinkChild1); // Destroying the CompositorFrameSink should invalidate it in viz. - EXPECT_CALL(manager_impl(), InvalidateFrameSinkId(kClientFrameSinkId)); + EXPECT_CALL(impl(), InvalidateFrameSinkId(kFrameSinkChild1)); - // We should still have the hierarchy data for |kClientFrameSinkId|. - EXPECT_TRUE(FrameSinkDataExists(kClientFrameSinkId)); + // We should still have the hierarchy data for |kFrameSinkChild1|. + EXPECT_TRUE(FrameSinkDataExists(kFrameSinkChild1)); // Unregister should work after the CompositorFrameSink is destroyed. - EXPECT_CALL(manager_impl(), UnregisterFrameSinkHierarchy(kParentFrameSinkId, - kClientFrameSinkId)); - host_manager().UnregisterFrameSinkHierarchy(kParentFrameSinkId, - kClientFrameSinkId); - host_manager().InvalidateFrameSinkId(kClientFrameSinkId); + EXPECT_CALL(impl(), UnregisterFrameSinkHierarchy(kFrameSinkParent1, + kFrameSinkChild1)); + host().UnregisterFrameSinkHierarchy(kFrameSinkParent1, kFrameSinkChild1); + host().InvalidateFrameSinkId(kFrameSinkChild1); - // Data for |kClientFrameSinkId| should be deleted now. - EXPECT_FALSE(FrameSinkDataExists(kClientFrameSinkId)); + // Data for |kFrameSinkChild1| should be deleted now. + EXPECT_FALSE(FrameSinkDataExists(kFrameSinkChild1)); } // Verify that that creating two CompositorFrameSinkSupports works. TEST_F(HostFrameSinkManagerTest, CreateCompositorFrameSinkSupport) { auto support_client = - CreateCompositorFrameSinkSupport(kClientFrameSinkId, true /* is_root */); - EXPECT_TRUE(FrameSinkDataExists(kClientFrameSinkId)); + CreateCompositorFrameSinkSupport(kFrameSinkChild1, true /* is_root */); + EXPECT_TRUE(FrameSinkDataExists(kFrameSinkChild1)); auto support_parent = - CreateCompositorFrameSinkSupport(kParentFrameSinkId, true /* is_root */); - EXPECT_TRUE(FrameSinkDataExists(kParentFrameSinkId)); + CreateCompositorFrameSinkSupport(kFrameSinkParent1, true /* is_root */); + EXPECT_TRUE(FrameSinkDataExists(kFrameSinkParent1)); // Register should call through to FrameSinkManagerImpl. - EXPECT_CALL(manager_impl(), RegisterFrameSinkHierarchy(kParentFrameSinkId, - kClientFrameSinkId)); - host_manager().RegisterFrameSinkHierarchy(kParentFrameSinkId, - kClientFrameSinkId); + EXPECT_CALL(impl(), + RegisterFrameSinkHierarchy(kFrameSinkParent1, kFrameSinkChild1)); + host().RegisterFrameSinkHierarchy(kFrameSinkParent1, kFrameSinkChild1); - EXPECT_CALL(manager_impl(), UnregisterFrameSinkHierarchy(kParentFrameSinkId, - kClientFrameSinkId)); - host_manager().UnregisterFrameSinkHierarchy(kParentFrameSinkId, - kClientFrameSinkId); + EXPECT_CALL(impl(), UnregisterFrameSinkHierarchy(kFrameSinkParent1, + kFrameSinkChild1)); + host().UnregisterFrameSinkHierarchy(kFrameSinkParent1, kFrameSinkChild1); - // We should still have the CompositorFrameSink data for |kClientFrameSinkId|. - EXPECT_TRUE(FrameSinkDataExists(kClientFrameSinkId)); + // We should still have the CompositorFrameSink data for |kFrameSinkChild1|. + EXPECT_TRUE(FrameSinkDataExists(kFrameSinkChild1)); support_client.reset(); - // Data for |kClientFrameSinkId| should be deleted now. - EXPECT_FALSE(FrameSinkDataExists(kClientFrameSinkId)); + // Data for |kFrameSinkChild1| should be deleted now. + EXPECT_FALSE(FrameSinkDataExists(kFrameSinkChild1)); support_parent.reset(); - // Data for |kParentFrameSinkId| should be deleted now. - EXPECT_FALSE(FrameSinkDataExists(kParentFrameSinkId)); + // Data for |kFrameSinkParent1| should be deleted now. + EXPECT_FALSE(FrameSinkDataExists(kFrameSinkParent1)); } TEST_F(HostFrameSinkManagerTest, AssignTemporaryReference) { FakeHostFrameSinkClient client; - host_manager().RegisterFrameSinkId(kParentFrameSinkId, &client); - host_manager().RegisterFrameSinkId(kClientFrameSinkId, &client); + host().RegisterFrameSinkId(kFrameSinkParent1, &client); + host().RegisterFrameSinkId(kFrameSinkChild1, &client); - const SurfaceId surface_id = MakeSurfaceId(kClientFrameSinkId, 1); + const SurfaceId surface_id = MakeSurfaceId(kFrameSinkChild1, 1); auto support = CreateCompositorFrameSinkSupport(surface_id.frame_sink_id(), false /* is_root */); - host_manager().RegisterFrameSinkHierarchy(kParentFrameSinkId, - surface_id.frame_sink_id()); + host().RegisterFrameSinkHierarchy(kFrameSinkParent1, + surface_id.frame_sink_id()); // When HostFrameSinkManager gets OnFirstSurfaceActivation() it should assign - // the temporary reference to the registered parent |kParentFrameSinkId|. - EXPECT_CALL(manager_impl(), - AssignTemporaryReference(surface_id, kParentFrameSinkId)); + // the temporary reference to the registered parent |kFrameSinkParent1|. + EXPECT_CALL(impl(), AssignTemporaryReference(surface_id, kFrameSinkParent1)); GetFrameSinkManagerClient()->OnFirstSurfaceActivation( MakeSurfaceInfo(surface_id)); } TEST_F(HostFrameSinkManagerTest, DropTemporaryReference) { - const SurfaceId surface_id = MakeSurfaceId(kClientFrameSinkId, 1); + const SurfaceId surface_id = MakeSurfaceId(kFrameSinkChild1, 1); auto support = CreateCompositorFrameSinkSupport(surface_id.frame_sink_id(), false /* is_root */); // When HostFrameSinkManager gets OnFirstSurfaceActivation() it should find no // registered parent and drop the temporary reference. - EXPECT_CALL(manager_impl(), DropTemporaryReference(surface_id)); + EXPECT_CALL(impl(), DropTemporaryReference(surface_id)); GetFrameSinkManagerClient()->OnFirstSurfaceActivation( MakeSurfaceInfo(surface_id)); } @@ -245,104 +240,143 @@ // sink that corresponds to the new surface has been invalidated. TEST_F(HostFrameSinkManagerTest, DropTemporaryReferenceForStaleClient) { FakeHostFrameSinkClient client; - host_manager().RegisterFrameSinkId(kClientFrameSinkId, &client); + host().RegisterFrameSinkId(kFrameSinkChild1, &client); auto support_client = - CreateCompositorFrameSinkSupport(kClientFrameSinkId, false /* is_root */); - EXPECT_TRUE(FrameSinkDataExists(kClientFrameSinkId)); + CreateCompositorFrameSinkSupport(kFrameSinkChild1, false /* is_root */); + EXPECT_TRUE(FrameSinkDataExists(kFrameSinkChild1)); - host_manager().RegisterFrameSinkId(kParentFrameSinkId, &client); + host().RegisterFrameSinkId(kFrameSinkParent1, &client); auto support_parent = - CreateCompositorFrameSinkSupport(kParentFrameSinkId, true /* is_root */); - EXPECT_TRUE(FrameSinkDataExists(kParentFrameSinkId)); + CreateCompositorFrameSinkSupport(kFrameSinkParent1, true /* is_root */); + EXPECT_TRUE(FrameSinkDataExists(kFrameSinkParent1)); // Register should call through to FrameSinkManagerImpl. - EXPECT_CALL(manager_impl(), RegisterFrameSinkHierarchy(kParentFrameSinkId, - kClientFrameSinkId)); - host_manager().RegisterFrameSinkHierarchy(kParentFrameSinkId, - kClientFrameSinkId); + EXPECT_CALL(impl(), + RegisterFrameSinkHierarchy(kFrameSinkParent1, kFrameSinkChild1)); + host().RegisterFrameSinkHierarchy(kFrameSinkParent1, kFrameSinkChild1); - const SurfaceId client_surface_id = MakeSurfaceId(kClientFrameSinkId, 1); - EXPECT_CALL(manager_impl(), DropTemporaryReference(client_surface_id)) - .Times(0); - EXPECT_CALL(manager_impl(), - AssignTemporaryReference(client_surface_id, kParentFrameSinkId)) + const SurfaceId client_surface_id = MakeSurfaceId(kFrameSinkChild1, 1); + EXPECT_CALL(impl(), DropTemporaryReference(client_surface_id)).Times(0); + EXPECT_CALL(impl(), + AssignTemporaryReference(client_surface_id, kFrameSinkParent1)) .Times(1); GetFrameSinkManagerClient()->OnFirstSurfaceActivation( MakeSurfaceInfo(client_surface_id)); - testing::Mock::VerifyAndClearExpectations(&manager_impl()); + testing::Mock::VerifyAndClearExpectations(&impl()); // Invaidating the client should cause the next SurfaceId to be dropped. support_client.reset(); - host_manager().InvalidateFrameSinkId(kClientFrameSinkId); + host().InvalidateFrameSinkId(kFrameSinkChild1); - const SurfaceId client_surface_id2 = MakeSurfaceId(kClientFrameSinkId, 2); - EXPECT_CALL(manager_impl(), DropTemporaryReference(client_surface_id2)) - .Times(1); - EXPECT_CALL(manager_impl(), AssignTemporaryReference(client_surface_id2, _)) - .Times(0); + const SurfaceId client_surface_id2 = MakeSurfaceId(kFrameSinkChild1, 2); + EXPECT_CALL(impl(), DropTemporaryReference(client_surface_id2)).Times(1); + EXPECT_CALL(impl(), AssignTemporaryReference(client_surface_id2, _)).Times(0); GetFrameSinkManagerClient()->OnFirstSurfaceActivation( MakeSurfaceInfo(client_surface_id2)); support_parent.reset(); - host_manager().InvalidateFrameSinkId(kParentFrameSinkId); + host().InvalidateFrameSinkId(kFrameSinkParent1); +} + +// Verify that multiple parents in the frame sink hierarchy works. +TEST_F(HostFrameSinkManagerTest, HierarchyMultipleParents) { + FakeHostFrameSinkClient client; + + // Register two parent and child CompositorFrameSink. + const FrameSinkId& id_parent1 = kFrameSinkParent1; + host().RegisterFrameSinkId(id_parent1, &client); + auto support_parent1 = + CreateCompositorFrameSinkSupport(id_parent1, true /* is_root */); + + const FrameSinkId& id_parent2 = kFrameSinkChild1; + host().RegisterFrameSinkId(id_parent2, &client); + auto support_parent2 = + CreateCompositorFrameSinkSupport(id_parent2, true /* is_root */); + + const FrameSinkId& id_child = kFrameSinkParent2; + host().RegisterFrameSinkId(id_child, &client); + auto support_child = + CreateCompositorFrameSinkSupport(id_child, false /* is_root */); + + // Register |id_parent1| in hierarchy first, this is the original window + // embedding. + EXPECT_CALL(impl(), RegisterFrameSinkHierarchy(id_parent1, id_child)); + host().RegisterFrameSinkHierarchy(id_parent1, id_child); + + // Register |id_parent2| in hierarchy second, this is a second embedding for + // something like alt-tab on a different monitor. + EXPECT_CALL(impl(), RegisterFrameSinkHierarchy(id_parent2, id_child)); + host().RegisterFrameSinkHierarchy(id_parent2, id_child); + testing::Mock::VerifyAndClearExpectations(&impl()); + + // The oldest registered parent in the hierarchy is assigned the temporary + // reference. + const SurfaceId surface_id = MakeSurfaceId(id_child, 1); + EXPECT_CALL(impl(), AssignTemporaryReference(surface_id, id_parent1)); + GetFrameSinkManagerClient()->OnFirstSurfaceActivation( + MakeSurfaceInfo(surface_id)); + testing::Mock::VerifyAndClearExpectations(&impl()); + + // Unregistering hierarchy with multiple parents should also work. + EXPECT_CALL(impl(), UnregisterFrameSinkHierarchy(id_parent2, id_child)); + host().UnregisterFrameSinkHierarchy(id_parent2, id_child); + + EXPECT_CALL(impl(), UnregisterFrameSinkHierarchy(id_parent1, id_child)); + host().UnregisterFrameSinkHierarchy(id_parent1, id_child); } // Verify that we drop the temporary reference to a new surface if the only // frame sink registered as an embedder has been invalidated. TEST_F(HostFrameSinkManagerTest, DropTemporaryReferenceForInvalidatedParent) { FakeHostFrameSinkClient client; - host_manager().RegisterFrameSinkId(kClientFrameSinkId, &client); + host().RegisterFrameSinkId(kFrameSinkChild1, &client); auto support_client = - CreateCompositorFrameSinkSupport(kClientFrameSinkId, false /* is_root */); - EXPECT_TRUE(FrameSinkDataExists(kClientFrameSinkId)); + CreateCompositorFrameSinkSupport(kFrameSinkChild1, false /* is_root */); + EXPECT_TRUE(FrameSinkDataExists(kFrameSinkChild1)); - host_manager().RegisterFrameSinkId(kParentFrameSinkId, &client); + host().RegisterFrameSinkId(kFrameSinkParent1, &client); auto support_parent = - CreateCompositorFrameSinkSupport(kParentFrameSinkId, true /* is_root */); - EXPECT_TRUE(FrameSinkDataExists(kParentFrameSinkId)); + CreateCompositorFrameSinkSupport(kFrameSinkParent1, true /* is_root */); + EXPECT_TRUE(FrameSinkDataExists(kFrameSinkParent1)); // Register should call through to FrameSinkManagerImpl. - EXPECT_CALL(manager_impl(), RegisterFrameSinkHierarchy(kParentFrameSinkId, - kClientFrameSinkId)); - host_manager().RegisterFrameSinkHierarchy(kParentFrameSinkId, - kClientFrameSinkId); + EXPECT_CALL(impl(), + RegisterFrameSinkHierarchy(kFrameSinkParent1, kFrameSinkChild1)); + host().RegisterFrameSinkHierarchy(kFrameSinkParent1, kFrameSinkChild1); - const SurfaceId client_surface_id = MakeSurfaceId(kClientFrameSinkId, 1); - EXPECT_CALL(manager_impl(), DropTemporaryReference(client_surface_id)) - .Times(0); - EXPECT_CALL(manager_impl(), - AssignTemporaryReference(client_surface_id, kParentFrameSinkId)) + const SurfaceId client_surface_id = MakeSurfaceId(kFrameSinkChild1, 1); + EXPECT_CALL(impl(), DropTemporaryReference(client_surface_id)).Times(0); + EXPECT_CALL(impl(), + AssignTemporaryReference(client_surface_id, kFrameSinkParent1)) .Times(1); GetFrameSinkManagerClient()->OnFirstSurfaceActivation( MakeSurfaceInfo(client_surface_id)); - testing::Mock::VerifyAndClearExpectations(&manager_impl()); + testing::Mock::VerifyAndClearExpectations(&impl()); // Invaidating the parent should cause the next SurfaceId to be dropped // because there is no registered frame sink as the parent. support_parent.reset(); - host_manager().InvalidateFrameSinkId(kParentFrameSinkId); + host().InvalidateFrameSinkId(kFrameSinkParent1); - const SurfaceId client_surface_id2 = MakeSurfaceId(kClientFrameSinkId, 2); - EXPECT_CALL(manager_impl(), DropTemporaryReference(client_surface_id2)) - .Times(1); - EXPECT_CALL(manager_impl(), AssignTemporaryReference(client_surface_id2, _)) - .Times(0); + const SurfaceId client_surface_id2 = MakeSurfaceId(kFrameSinkChild1, 2); + EXPECT_CALL(impl(), DropTemporaryReference(client_surface_id2)).Times(1); + EXPECT_CALL(impl(), AssignTemporaryReference(client_surface_id2, _)).Times(0); GetFrameSinkManagerClient()->OnFirstSurfaceActivation( MakeSurfaceInfo(client_surface_id2)); support_client.reset(); - host_manager().InvalidateFrameSinkId(kClientFrameSinkId); + host().InvalidateFrameSinkId(kFrameSinkChild1); } TEST_F(HostFrameSinkManagerTest, DisplayRootTemporaryReference) { - const SurfaceId surface_id = MakeSurfaceId(kParentFrameSinkId, 1); + const SurfaceId surface_id = MakeSurfaceId(kFrameSinkParent1, 1); auto support = CreateCompositorFrameSinkSupport(surface_id.frame_sink_id(), true /* is_root */); // When HostFrameSinkManager gets OnFirstSurfaceActivation() it should do - // nothing since |kParentFrameSinkId| is a display root. - EXPECT_CALL(manager_impl(), DropTemporaryReference(surface_id)).Times(0); - EXPECT_CALL(manager_impl(), AssignTemporaryReference(surface_id, _)).Times(0); + // nothing since |kFrameSinkParent1| is a display root. + EXPECT_CALL(impl(), DropTemporaryReference(surface_id)).Times(0); + EXPECT_CALL(impl(), AssignTemporaryReference(surface_id, _)).Times(0); GetFrameSinkManagerClient()->OnFirstSurfaceActivation( MakeSurfaceInfo(surface_id)); }
diff --git a/components/viz/presubmit_checks.py b/components/viz/presubmit_checks.py new file mode 100644 index 0000000..9db40f1 --- /dev/null +++ b/components/viz/presubmit_checks.py
@@ -0,0 +1,312 @@ +# 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. + +"""Presubmit checks used in viz""" + +import re +import string + +def CheckChangeLintsClean(input_api, output_api, white_list, black_list=None): + source_filter = lambda x: input_api.FilterSourceFile( + x, white_list=white_list, black_list=black_list) + + return input_api.canned_checks.CheckChangeLintsClean( + input_api, output_api, source_filter, lint_filters=[], verbose_level=1) + +def CheckAsserts(input_api, output_api, white_list, black_list=None): + black_list = tuple(black_list or input_api.DEFAULT_BLACK_LIST) + source_file_filter = lambda x: input_api.FilterSourceFile(x, white_list, black_list) + + assert_files = [] + + for f in input_api.AffectedSourceFiles(source_file_filter): + contents = input_api.ReadFile(f, 'rb') + # WebKit ASSERT() is not allowed. + if re.search(r"\bASSERT\(", contents): + assert_files.append(f.LocalPath()) + + if assert_files: + return [output_api.PresubmitError( + 'These files use ASSERT instead of using DCHECK:', + items=assert_files)] + return [] + +def CheckStdAbs(input_api, output_api, + white_list, black_list=None): + black_list = tuple(black_list or input_api.DEFAULT_BLACK_LIST) + source_file_filter = lambda x: input_api.FilterSourceFile(x, + white_list, + black_list) + + using_std_abs_files = [] + found_fabs_files = [] + missing_std_prefix_files = [] + + for f in input_api.AffectedSourceFiles(source_file_filter): + contents = input_api.ReadFile(f, 'rb') + if re.search(r"using std::f?abs;", contents): + using_std_abs_files.append(f.LocalPath()) + if re.search(r"\bfabsf?\(", contents): + found_fabs_files.append(f.LocalPath()); + + no_std_prefix = r"(?<!std::)" + # Matches occurrences of abs/absf/fabs/fabsf without a "std::" prefix. + abs_without_prefix = r"%s(\babsf?\()" % no_std_prefix + fabs_without_prefix = r"%s(\bfabsf?\()" % no_std_prefix + # Skips matching any lines that have "// NOLINT". + no_nolint = r"(?![^\n]*//\s+NOLINT)" + + expression = re.compile("(%s|%s)%s" % + (abs_without_prefix, fabs_without_prefix, no_nolint)) + if expression.search(contents): + missing_std_prefix_files.append(f.LocalPath()) + + result = [] + if using_std_abs_files: + result.append(output_api.PresubmitError( + 'These files have "using std::abs" which is not permitted.', + items=using_std_abs_files)) + if found_fabs_files: + result.append(output_api.PresubmitError( + 'std::abs() should be used instead of std::fabs() for consistency.', + items=found_fabs_files)) + if missing_std_prefix_files: + result.append(output_api.PresubmitError( + 'These files use abs(), absf(), fabs(), or fabsf() without qualifying ' + 'the std namespace. Please use std::abs() in all places.', + items=missing_std_prefix_files)) + return result + +def CheckPassByValue(input_api, + output_api, + white_list, + black_list=None): + black_list = tuple(black_list or input_api.DEFAULT_BLACK_LIST) + source_file_filter = lambda x: input_api.FilterSourceFile(x, + white_list, + black_list) + + local_errors = [] + + # Well-defined simple classes the same size as a primitive type. + pass_by_value_types = ['base::Time', + 'base::TimeTicks', + ] + + for f in input_api.AffectedSourceFiles(source_file_filter): + contents = input_api.ReadFile(f, 'rb') + match = re.search( + r'\bconst +' + '(?P<type>(%s))&' % + string.join(pass_by_value_types, '|'), + contents) + if match: + local_errors.append(output_api.PresubmitError( + '%s passes %s by const ref instead of by value.' % + (f.LocalPath(), match.group('type')))) + return local_errors + +def CheckTodos(input_api, output_api): + errors = [] + + source_file_filter = lambda x: x + for f in input_api.AffectedSourceFiles(source_file_filter): + contents = input_api.ReadFile(f, 'rb') + if ('FIX'+'ME') in contents: + errors.append(f.LocalPath()) + + if errors: + return [output_api.PresubmitError( + 'All TODO comments should be of the form TODO(name/bug). ' + + 'Use TODO instead of FIX' + 'ME', + items=errors)] + return [] + +def CheckDoubleAngles(input_api, output_api, white_list, + black_list=None): + errors = [] + + source_file_filter = lambda x: input_api.FilterSourceFile(x, + white_list, + black_list) + for f in input_api.AffectedSourceFiles(source_file_filter): + contents = input_api.ReadFile(f, 'rb') + if ('> >') in contents: + errors.append(f.LocalPath()) + + if errors: + return [output_api.PresubmitError('Use >> instead of > >:', items=errors)] + return [] + +def CheckUniquePtr(input_api, output_api, + white_list, black_list=None): + black_list = tuple(black_list or input_api.DEFAULT_BLACK_LIST) + source_file_filter = lambda x: input_api.FilterSourceFile(x, + white_list, + black_list) + errors = [] + for f in input_api.AffectedSourceFiles(source_file_filter): + for line_number, line in f.ChangedContents(): + # Disallow: + # return std::unique_ptr<T>(foo); + # bar = std::unique_ptr<T>(foo); + # But allow: + # return std::unique_ptr<T[]>(foo); + # bar = std::unique_ptr<T[]>(foo); + if re.search(r'(=|\breturn)\s*std::unique_ptr<.*?(?<!])>\([^)]+\)', line): + errors.append(output_api.PresubmitError( + ('%s:%d uses explicit std::unique_ptr constructor. ' + + 'Use base::MakeUnique<T>() instead.') % + (f.LocalPath(), line_number))) + # Disallow: + # std::unique_ptr<T>() + if re.search(r'\bstd::unique_ptr<.*?>\(\)', line): + errors.append(output_api.PresubmitError( + '%s:%d uses std::unique_ptr<T>(). Use nullptr instead.' % + (f.LocalPath(), line_number))) + return errors + +def FindUnquotedQuote(contents, pos): + match = re.search(r"(?<!\\)(?P<quote>\")", contents[pos:]) + return -1 if not match else match.start("quote") + pos + +def FindUselessIfdefs(input_api, output_api): + errors = [] + source_file_filter = lambda x: x + for f in input_api.AffectedSourceFiles(source_file_filter): + contents = input_api.ReadFile(f, 'rb') + if re.search(r'#if\s*0\s', contents): + errors.append(f.LocalPath()) + if errors: + return [output_api.PresubmitError( + 'Don\'t use #if '+'0; just delete the code.', + items=errors)] + return [] + +def FindNamespaceInBlock(pos, namespace, contents, whitelist=[]): + open_brace = -1 + close_brace = -1 + quote = -1 + name = -1 + brace_count = 1 + quote_count = 0 + while pos < len(contents) and brace_count > 0: + if open_brace < pos: open_brace = contents.find("{", pos) + if close_brace < pos: close_brace = contents.find("}", pos) + if quote < pos: quote = FindUnquotedQuote(contents, pos) + if name < pos: name = contents.find(("%s::" % namespace), pos) + + if name < 0: + return False # The namespace is not used at all. + if open_brace < 0: + open_brace = len(contents) + if close_brace < 0: + close_brace = len(contents) + if quote < 0: + quote = len(contents) + + next = min(open_brace, min(close_brace, min(quote, name))) + + if next == open_brace: + brace_count += 1 + elif next == close_brace: + brace_count -= 1 + elif next == quote: + quote_count = 0 if quote_count else 1 + elif next == name and not quote_count: + in_whitelist = False + for w in whitelist: + if re.match(w, contents[next:]): + in_whitelist = True + break + if not in_whitelist: + return True + pos = next + 1 + return False + +# Checks for the use of viz:: within the viz namespace, which is usually +# redundant. +def CheckNamespace(input_api, output_api): + errors = [] + + source_file_filter = lambda x: x + for f in input_api.AffectedSourceFiles(source_file_filter): + contents = input_api.ReadFile(f, 'rb') + match = re.search(r'namespace\s*viz\s*{', contents) + if match: + whitelist = [] + if FindNamespaceInBlock(match.end(), 'viz', contents, whitelist=whitelist): + errors.append(f.LocalPath()) + + if errors: + return [output_api.PresubmitError( + 'Do not use viz:: inside of the viz namespace.', + items=errors)] + return [] + +def CheckForUseOfWrongClock(input_api, + output_api, + white_list, + black_list=None): + """Make sure new lines of code don't use a clock susceptible to skew.""" + black_list = tuple(black_list or input_api.DEFAULT_BLACK_LIST) + source_file_filter = lambda x: input_api.FilterSourceFile(x, + white_list, + black_list) + # Regular expression that should detect any explicit references to the + # base::Time type (or base::Clock/DefaultClock), whether in using decls, + # typedefs, or to call static methods. + base_time_type_pattern = r'(^|\W)base::(Time|Clock|DefaultClock)(\W|$)' + + # Regular expression that should detect references to the base::Time class + # members, such as a call to base::Time::Now. + base_time_member_pattern = r'(^|\W)(Time|Clock|DefaultClock)::' + + # Regular expression to detect "using base::Time" declarations. We want to + # prevent these from triggerring a warning. For example, it's perfectly + # reasonable for code to be written like this: + # + # using base::Time; + # ... + # int64 foo_us = foo_s * Time::kMicrosecondsPerSecond; + using_base_time_decl_pattern = r'^\s*using\s+(::)?base::Time\s*;' + + # Regular expression to detect references to the kXXX constants in the + # base::Time class. We want to prevent these from triggerring a warning. + base_time_konstant_pattern = r'(^|\W)Time::k\w+' + + problem_re = input_api.re.compile( + r'(' + base_time_type_pattern + r')|(' + base_time_member_pattern + r')') + exception_re = input_api.re.compile( + r'(' + using_base_time_decl_pattern + r')|(' + + base_time_konstant_pattern + r')') + problems = [] + for f in input_api.AffectedSourceFiles(source_file_filter): + for line_number, line in f.ChangedContents(): + if problem_re.search(line): + if not exception_re.search(line): + problems.append( + ' %s:%d\n %s' % (f.LocalPath(), line_number, line.strip())) + + if problems: + return [output_api.PresubmitPromptOrNotify( + 'You added one or more references to the base::Time class and/or one\n' + 'of its member functions (or base::Clock/DefaultClock). In cc code,\n' + 'it is most certainly incorrect! Instead use base::TimeTicks.\n\n' + '\n'.join(problems))] + else: + return [] + +def RunAllChecks(input_api, output_api, white_list): + results = [] + results += CheckAsserts(input_api, output_api, white_list) + results += CheckStdAbs(input_api, output_api, white_list) + results += CheckPassByValue(input_api, output_api, white_list) + results += CheckChangeLintsClean(input_api, output_api, white_list) + results += CheckTodos(input_api, output_api) + results += CheckDoubleAngles(input_api, output_api, white_list) + results += CheckUniquePtr(input_api, output_api, white_list) + results += CheckNamespace(input_api, output_api) + results += CheckForUseOfWrongClock(input_api, output_api, white_list) + results += FindUselessIfdefs(input_api, output_api) + return results
diff --git a/content/browser/accessibility/browser_accessibility_manager.cc b/content/browser/accessibility/browser_accessibility_manager.cc index adfe70a..3826931 100644 --- a/content/browser/accessibility/browser_accessibility_manager.cc +++ b/content/browser/accessibility/browser_accessibility_manager.cc
@@ -137,7 +137,6 @@ factory_(factory), tree_(new ui::AXSerializableTree()), user_is_navigating_away_(false), - osk_state_(OSK_ALLOWED), last_focused_node_(nullptr), last_focused_manager_(nullptr), connected_to_parent_tree_node_(false), @@ -156,7 +155,6 @@ factory_(factory), tree_(new ui::AXSerializableTree()), user_is_navigating_away_(false), - osk_state_(OSK_ALLOWED), last_focused_node_(nullptr), last_focused_manager_(nullptr), ax_tree_id_(ui::AXTreeIDRegistry::kNoAXTreeID), @@ -445,11 +443,6 @@ if (event_type == ui::AX_EVENT_FOCUS || event_type == ui::AX_EVENT_BLUR) { - if (osk_state_ != OSK_DISALLOWED_BECAUSE_TAB_HIDDEN && - osk_state_ != OSK_DISALLOWED_BECAUSE_TAB_JUST_APPEARED) { - osk_state_ = OSK_ALLOWED; - } - // We already handled all focus events above. continue; }
diff --git a/content/browser/accessibility/browser_accessibility_manager.h b/content/browser/accessibility/browser_accessibility_manager.h index 1624878..9486d9f 100644 --- a/content/browser/accessibility/browser_accessibility_manager.h +++ b/content/browser/accessibility/browser_accessibility_manager.h
@@ -411,29 +411,6 @@ virtual void SendLocationChangeEvents( const std::vector<AccessibilityHostMsg_LocationChangeParams>& params); - private: - // The following states keep track of whether or not the - // on-screen keyboard is allowed to be shown. - enum OnScreenKeyboardState { - // Never show the on-screen keyboard because this tab is hidden. - OSK_DISALLOWED_BECAUSE_TAB_HIDDEN, - - // This tab was just shown, so don't pop-up the on-screen keyboard if a - // text field gets focus that wasn't the result of an explicit touch. - OSK_DISALLOWED_BECAUSE_TAB_JUST_APPEARED, - - // A touch event has occurred within the window, but focus has not - // explicitly changed. Allow the on-screen keyboard to be shown if the - // touch event was within the bounds of the currently focused object. - // Otherwise we'll just wait to see if focus changes. - OSK_ALLOWED_WITHIN_FOCUSED_OBJECT, - - // Focus has changed within a tab that's already visible. Allow the - // on-screen keyboard to show anytime that a touch event leads to an - // editable text control getting focus. - OSK_ALLOWED - }; - protected: // The object that can perform actions on our behalf. BrowserAccessibilityDelegate* delegate_; @@ -455,9 +432,6 @@ // True if the user has initiated a navigation to another page. bool user_is_navigating_away_; - // The on-screen keyboard state. - OnScreenKeyboardState osk_state_; - BrowserAccessibilityFindInPageInfo find_in_page_info_; // These are only used by the root BrowserAccessibilityManager of a
diff --git a/content/browser/cache_storage/cache_storage_blob_to_disk_cache_unittest.cc b/content/browser/cache_storage/cache_storage_blob_to_disk_cache_unittest.cc index 9b60c731..a650aaa 100644 --- a/content/browser/cache_storage/cache_storage_blob_to_disk_cache_unittest.cc +++ b/content/browser/cache_storage/cache_storage_blob_to_disk_cache_unittest.cc
@@ -141,8 +141,7 @@ int rv = CreateCacheBackend( net::MEMORY_CACHE, net::CACHE_BACKEND_DEFAULT, base::FilePath(), (CacheStorageBlobToDiskCache::kBufferSize * 100) /* max bytes */, - false /* force */, base::ThreadTaskRunnerHandle::Get(), - nullptr /* net log */, &cache_backend_, + false /* force */, nullptr /* net log */, &cache_backend_, base::Bind(&DoNothingCompletion)); // The memory cache runs synchronously. EXPECT_EQ(net::OK, rv);
diff --git a/content/browser/cache_storage/cache_storage_cache.cc b/content/browser/cache_storage/cache_storage_cache.cc index 702f5af..d872977 100644 --- a/content/browser/cache_storage/cache_storage_cache.cc +++ b/content/browser/cache_storage/cache_storage_cache.cc
@@ -1402,11 +1402,18 @@ } void CacheStorageCache::CloseImpl(base::OnceClosure callback) { - DCHECK_NE(BACKEND_CLOSED, backend_state_); + DCHECK_EQ(BACKEND_OPEN, backend_state_); - backend_state_ = BACKEND_CLOSED; backend_.reset(); - std::move(callback).Run(); + post_backend_closed_callback_ = std::move(callback); +} + +void CacheStorageCache::DeleteBackendCompletedIO() { + if (!post_backend_closed_callback_.is_null()) { + DCHECK_NE(BACKEND_CLOSED, backend_state_); + backend_state_ = BACKEND_CLOSED; + std::move(post_backend_closed_callback_).Run(); + } } void CacheStorageCache::SizeImpl(SizeCallback callback) { @@ -1439,13 +1446,13 @@ weak_ptr_factory_.GetWeakPtr(), std::move(callback), base::Passed(std::move(backend_ptr)))); - // TODO(jkarlin): Use the cache task runner that ServiceWorkerCacheCore - // has for disk caches. int rv = disk_cache::CreateCacheBackend( cache_type, net::CACHE_BACKEND_SIMPLE, path_, kMaxCacheBytes, false, /* force */ - BrowserThread::GetTaskRunnerForThread(BrowserThread::CACHE).get(), NULL, - backend, create_cache_callback); + NULL, backend, + base::BindOnce(&CacheStorageCache::DeleteBackendCompletedIO, + weak_ptr_factory_.GetWeakPtr()), + create_cache_callback); if (rv != net::ERR_IO_PENDING) create_cache_callback.Run(rv); }
diff --git a/content/browser/cache_storage/cache_storage_cache.h b/content/browser/cache_storage/cache_storage_cache.h index 3a737bd..46ea4f0 100644 --- a/content/browser/cache_storage/cache_storage_cache.h +++ b/content/browser/cache_storage/cache_storage_cache.h
@@ -362,6 +362,7 @@ void InitGotCacheSize(base::OnceClosure callback, CacheStorageError cache_create_error, int cache_size); + void DeleteBackendCompletedIO(); std::unique_ptr<storage::BlobDataHandle> PopulateResponseBody( disk_cache::ScopedEntryPtr entry, @@ -396,6 +397,10 @@ // Whether or not to store data in disk or memory. bool memory_only_; + // Active while waiting for the backend to finish its closing up, and contains + // the callback passed to CloseImpl. + base::OnceClosure post_backend_closed_callback_; + base::WeakPtrFactory<CacheStorageCache> weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(CacheStorageCache);
diff --git a/content/browser/cache_storage/cache_storage_cache_unittest.cc b/content/browser/cache_storage/cache_storage_cache_unittest.cc index a92dd20..5802535 100644 --- a/content/browser/cache_storage/cache_storage_cache_unittest.cc +++ b/content/browser/cache_storage/cache_storage_cache_unittest.cc
@@ -29,7 +29,9 @@ #include "content/public/common/referrer.h" #include "content/public/test/test_browser_context.h" #include "content/public/test/test_browser_thread_bundle.h" +#include "content/public/test/test_utils.h" #include "net/base/test_completion_callback.h" +#include "net/disk_cache/disk_cache.h" #include "net/url_request/url_request_context.h" #include "net/url_request/url_request_context_getter.h" #include "net/url_request/url_request_job_factory_impl.h" @@ -384,7 +386,8 @@ void TearDown() override { quota_manager_proxy_->SimulateQuotaManagerDestroyed(); - base::RunLoop().RunUntilIdle(); + disk_cache::FlushCacheThreadForTesting(); + content::RunAllBlockingPoolTasksUntilIdle(); } void CreateRequests(ChromeBlobStorageContext* blob_storage_context) {
diff --git a/content/browser/cache_storage/cache_storage_manager_unittest.cc b/content/browser/cache_storage/cache_storage_manager_unittest.cc index 04d8675..f1fbe6c 100644 --- a/content/browser/cache_storage/cache_storage_manager_unittest.cc +++ b/content/browser/cache_storage/cache_storage_manager_unittest.cc
@@ -34,6 +34,8 @@ #include "content/public/browser/storage_partition.h" #include "content/public/test/test_browser_context.h" #include "content/public/test/test_browser_thread_bundle.h" +#include "content/public/test/test_utils.h" +#include "net/disk_cache/disk_cache.h" #include "net/url_request/url_request_context.h" #include "net/url_request/url_request_context_getter.h" #include "net/url_request/url_request_job_factory_impl.h" @@ -108,7 +110,11 @@ CreateStorageManager(); } - void TearDown() override { DestroyStorageManager(); } + void TearDown() override { + DestroyStorageManager(); + disk_cache::FlushCacheThreadForTesting(); + content::RunAllBlockingPoolTasksUntilIdle(); + } virtual bool MemoryOnly() { return false; }
diff --git a/content/common/input/input_event_struct_traits.cc b/content/common/input/input_event_struct_traits.cc index a02c660..1c57527 100644 --- a/content/common/input/input_event_struct_traits.cc +++ b/content/common/input/input_event_struct_traits.cc
@@ -366,178 +366,175 @@ return event.ReadLatency(&((*out)->latency_info)); } -void* StructTraits<content::mojom::EventDataView, - InputEventUniquePtr>::SetUpContext(const InputEventUniquePtr& - event) { - InputEventSerializationContext* context = - new InputEventSerializationContext(); +// static +content::mojom::KeyDataPtr +StructTraits<content::mojom::EventDataView, InputEventUniquePtr>::key_data( + const InputEventUniquePtr& event) { + if (!event->web_event || + !blink::WebInputEvent::IsKeyboardEventType(event->web_event->GetType())) + return nullptr; + const blink::WebKeyboardEvent* key_event = + static_cast<const blink::WebKeyboardEvent*>(event->web_event.get()); + return content::mojom::KeyData::New( + key_event->dom_key, key_event->dom_code, key_event->windows_key_code, + key_event->native_key_code, key_event->is_system_key, + key_event->is_browser_shortcut, key_event->text, + key_event->unmodified_text); +} +// static +content::mojom::PointerDataPtr +StructTraits<content::mojom::EventDataView, InputEventUniquePtr>::pointer_data( + const InputEventUniquePtr& event) { if (!event->web_event) - return context; - - if (blink::WebInputEvent::IsKeyboardEventType(event->web_event->GetType())) { - const blink::WebKeyboardEvent* key_event = - static_cast<const blink::WebKeyboardEvent*>(event->web_event.get()); - context->key_data = content::mojom::KeyData::New( - key_event->dom_key, key_event->dom_code, key_event->windows_key_code, - key_event->native_key_code, key_event->is_system_key, - key_event->is_browser_shortcut, key_event->text, - key_event->unmodified_text); - return context; - } - if (blink::WebInputEvent::IsGestureEventType(event->web_event->GetType())) { - const blink::WebGestureEvent* gesture_event = - static_cast<const blink::WebGestureEvent*>(event->web_event.get()); - - context->gesture_data = content::mojom::GestureData::New(); - content::mojom::GestureDataPtr& gesture_data = context->gesture_data; - gesture_data->screen_position = gesture_event->PositionInScreen(); - gesture_data->widget_position = gesture_event->PositionInWidget(); - gesture_data->source_device = gesture_event->source_device; - gesture_data->unique_touch_event_id = gesture_event->unique_touch_event_id; - gesture_data->resending_plugin_id = gesture_event->resending_plugin_id; - - switch (gesture_event->GetType()) { - default: - break; - case blink::WebInputEvent::Type::kGestureTapDown: - gesture_data->contact_size = - gfx::Size(gesture_event->data.tap_down.width, - gesture_event->data.tap_down.height); - break; - case blink::WebInputEvent::Type::kGestureShowPress: - gesture_data->contact_size = - gfx::Size(gesture_event->data.show_press.width, - gesture_event->data.show_press.height); - break; - case blink::WebInputEvent::Type::kGestureTap: - case blink::WebInputEvent::Type::kGestureTapUnconfirmed: - case blink::WebInputEvent::Type::kGestureDoubleTap: - gesture_data->contact_size = gfx::Size(gesture_event->data.tap.width, - gesture_event->data.tap.height); - gesture_data->tap_data = - content::mojom::TapData::New(gesture_event->data.tap.tap_count); - break; - case blink::WebInputEvent::Type::kGestureLongPress: - gesture_data->contact_size = - gfx::Size(gesture_event->data.long_press.width, - gesture_event->data.long_press.height); - break; - - case blink::WebInputEvent::Type::kGestureTwoFingerTap: - gesture_data->contact_size = - gfx::Size(gesture_event->data.two_finger_tap.first_finger_width, - gesture_event->data.two_finger_tap.first_finger_height); - break; - case blink::WebInputEvent::Type::kGestureScrollBegin: - gesture_data->scroll_data = content::mojom::ScrollData::New( - gesture_event->data.scroll_begin.delta_x_hint, - gesture_event->data.scroll_begin.delta_y_hint, - gesture_event->data.scroll_begin.delta_hint_units, - gesture_event->data.scroll_begin.target_viewport, - gesture_event->data.scroll_begin.inertial_phase, - gesture_event->data.scroll_begin.synthetic, - gesture_event->data.scroll_begin.pointer_count, nullptr); - break; - case blink::WebInputEvent::Type::kGestureScrollEnd: - gesture_data->scroll_data = content::mojom::ScrollData::New( - 0, 0, gesture_event->data.scroll_end.delta_units, false, - gesture_event->data.scroll_end.inertial_phase, - gesture_event->data.scroll_end.synthetic, 0, nullptr); - break; - case blink::WebInputEvent::Type::kGestureScrollUpdate: - gesture_data->scroll_data = content::mojom::ScrollData::New( - gesture_event->data.scroll_update.delta_x, - gesture_event->data.scroll_update.delta_y, - gesture_event->data.scroll_update.delta_units, false, - gesture_event->data.scroll_update.inertial_phase, false, 0, - content::mojom::ScrollUpdate::New( - gesture_event->data.scroll_update.velocity_x, - gesture_event->data.scroll_update.velocity_y, - gesture_event->data.scroll_update - .previous_update_in_sequence_prevented, - gesture_event->data.scroll_update.prevent_propagation)); - break; - case blink::WebInputEvent::Type::kGestureFlingStart: - gesture_data->fling_data = content::mojom::FlingData::New( - gesture_event->data.fling_start.velocity_x, - gesture_event->data.fling_start.velocity_y, - gesture_event->data.fling_start.target_viewport, false); - break; - case blink::WebInputEvent::Type::kGestureFlingCancel: - gesture_data->fling_data = content::mojom::FlingData::New( - 0, 0, gesture_event->data.fling_cancel.target_viewport, - gesture_event->data.fling_cancel.prevent_boosting); - break; - case blink::WebInputEvent::Type::kGesturePinchUpdate: - gesture_data->pinch_data = content::mojom::PinchData::New( - gesture_event->data.pinch_update.zoom_disabled, - gesture_event->data.pinch_update.scale); - break; - } - return context; - } - if (blink::WebInputEvent::IsTouchEventType(event->web_event->GetType())) { - const blink::WebTouchEvent* touch_event = - static_cast<const blink::WebTouchEvent*>(event->web_event.get()); - - context->touch_data = content::mojom::TouchData::New( - touch_event->dispatch_type, touch_event->moved_beyond_slop_region, - touch_event->touch_start_or_first_touch_move, - touch_event->unique_touch_event_id, - std::vector<content::mojom::TouchPointPtr>()); - - for (unsigned i = 0; i < touch_event->touches_length; ++i) { - content::mojom::PointerDataPtr pointer_data = - PointerDataFromPointerProperties(touch_event->touches[i], nullptr); - context->touch_data->touches.emplace_back(content::mojom::TouchPoint::New( - touch_event->touches[i].state, touch_event->touches[i].radius_x, - touch_event->touches[i].radius_y, - touch_event->touches[i].rotation_angle, std::move(pointer_data))); - } - - return context; - } - + return nullptr; bool is_wheel_event = event->web_event->GetType() == blink::WebInputEvent::Type::kMouseWheel; - if (blink::WebInputEvent::IsMouseEventType(event->web_event->GetType()) || - is_wheel_event) { - const blink::WebMouseEvent* mouse_event = - static_cast<const blink::WebMouseEvent*>(event->web_event.get()); + if (!blink::WebInputEvent::IsMouseEventType(event->web_event->GetType()) && + !is_wheel_event) { + return nullptr; + } + const blink::WebMouseEvent* mouse_event = + static_cast<const blink::WebMouseEvent*>(event->web_event.get()); - content::mojom::WheelDataPtr wheel_data; - if (is_wheel_event) { - const blink::WebMouseWheelEvent* wheel_event = - static_cast<const blink::WebMouseWheelEvent*>(mouse_event); - wheel_data = content::mojom::WheelData::New( - wheel_event->delta_x, wheel_event->delta_y, - wheel_event->wheel_ticks_x, wheel_event->wheel_ticks_y, - wheel_event->acceleration_ratio_x, wheel_event->acceleration_ratio_y, - wheel_event->resending_plugin_id, wheel_event->phase, - wheel_event->momentum_phase, wheel_event->scroll_by_page, - wheel_event->has_precise_scrolling_deltas, - wheel_event->dispatch_type); - } - - context->pointer_data = PointerDataFromPointerProperties( - *mouse_event, content::mojom::MouseData::New(mouse_event->click_count, - std::move(wheel_data))); - return context; + content::mojom::WheelDataPtr wheel_data; + if (is_wheel_event) { + const blink::WebMouseWheelEvent* wheel_event = + static_cast<const blink::WebMouseWheelEvent*>(mouse_event); + wheel_data = content::mojom::WheelData::New( + wheel_event->delta_x, wheel_event->delta_y, wheel_event->wheel_ticks_x, + wheel_event->wheel_ticks_y, wheel_event->acceleration_ratio_x, + wheel_event->acceleration_ratio_y, wheel_event->resending_plugin_id, + wheel_event->phase, wheel_event->momentum_phase, + wheel_event->scroll_by_page, wheel_event->has_precise_scrolling_deltas, + wheel_event->dispatch_type); } - return context; + return PointerDataFromPointerProperties( + *mouse_event, content::mojom::MouseData::New(mouse_event->click_count, + std::move(wheel_data))); } -void StructTraits<content::mojom::EventDataView, InputEventUniquePtr>:: - TearDownContext(const InputEventUniquePtr& event, void* context) { - delete static_cast<InputEventSerializationContext*>(context); +// static +content::mojom::GestureDataPtr +StructTraits<content::mojom::EventDataView, InputEventUniquePtr>::gesture_data( + const InputEventUniquePtr& event) { + if (!event->web_event || + !blink::WebInputEvent::IsGestureEventType(event->web_event->GetType())) + return nullptr; + const blink::WebGestureEvent* gesture_event = + static_cast<const blink::WebGestureEvent*>(event->web_event.get()); + auto gesture_data = content::mojom::GestureData::New(); + gesture_data->screen_position = gesture_event->PositionInScreen(); + gesture_data->widget_position = gesture_event->PositionInWidget(); + gesture_data->source_device = gesture_event->source_device; + gesture_data->unique_touch_event_id = gesture_event->unique_touch_event_id; + gesture_data->resending_plugin_id = gesture_event->resending_plugin_id; + switch (gesture_event->GetType()) { + default: + break; + case blink::WebInputEvent::Type::kGestureTapDown: + gesture_data->contact_size = + gfx::Size(gesture_event->data.tap_down.width, + gesture_event->data.tap_down.height); + break; + case blink::WebInputEvent::Type::kGestureShowPress: + gesture_data->contact_size = + gfx::Size(gesture_event->data.show_press.width, + gesture_event->data.show_press.height); + break; + case blink::WebInputEvent::Type::kGestureTap: + case blink::WebInputEvent::Type::kGestureTapUnconfirmed: + case blink::WebInputEvent::Type::kGestureDoubleTap: + gesture_data->contact_size = gfx::Size(gesture_event->data.tap.width, + gesture_event->data.tap.height); + gesture_data->tap_data = + content::mojom::TapData::New(gesture_event->data.tap.tap_count); + break; + case blink::WebInputEvent::Type::kGestureLongPress: + gesture_data->contact_size = + gfx::Size(gesture_event->data.long_press.width, + gesture_event->data.long_press.height); + break; + + case blink::WebInputEvent::Type::kGestureTwoFingerTap: + gesture_data->contact_size = + gfx::Size(gesture_event->data.two_finger_tap.first_finger_width, + gesture_event->data.two_finger_tap.first_finger_height); + break; + case blink::WebInputEvent::Type::kGestureScrollBegin: + gesture_data->scroll_data = content::mojom::ScrollData::New( + gesture_event->data.scroll_begin.delta_x_hint, + gesture_event->data.scroll_begin.delta_y_hint, + gesture_event->data.scroll_begin.delta_hint_units, + gesture_event->data.scroll_begin.target_viewport, + gesture_event->data.scroll_begin.inertial_phase, + gesture_event->data.scroll_begin.synthetic, + gesture_event->data.scroll_begin.pointer_count, nullptr); + break; + case blink::WebInputEvent::Type::kGestureScrollEnd: + gesture_data->scroll_data = content::mojom::ScrollData::New( + 0, 0, gesture_event->data.scroll_end.delta_units, false, + gesture_event->data.scroll_end.inertial_phase, + gesture_event->data.scroll_end.synthetic, 0, nullptr); + break; + case blink::WebInputEvent::Type::kGestureScrollUpdate: + gesture_data->scroll_data = content::mojom::ScrollData::New( + gesture_event->data.scroll_update.delta_x, + gesture_event->data.scroll_update.delta_y, + gesture_event->data.scroll_update.delta_units, false, + gesture_event->data.scroll_update.inertial_phase, false, 0, + content::mojom::ScrollUpdate::New( + gesture_event->data.scroll_update.velocity_x, + gesture_event->data.scroll_update.velocity_y, + gesture_event->data.scroll_update + .previous_update_in_sequence_prevented, + gesture_event->data.scroll_update.prevent_propagation)); + break; + case blink::WebInputEvent::Type::kGestureFlingStart: + gesture_data->fling_data = content::mojom::FlingData::New( + gesture_event->data.fling_start.velocity_x, + gesture_event->data.fling_start.velocity_y, + gesture_event->data.fling_start.target_viewport, false); + break; + case blink::WebInputEvent::Type::kGestureFlingCancel: + gesture_data->fling_data = content::mojom::FlingData::New( + 0, 0, gesture_event->data.fling_cancel.target_viewport, + gesture_event->data.fling_cancel.prevent_boosting); + break; + case blink::WebInputEvent::Type::kGesturePinchUpdate: + gesture_data->pinch_data = content::mojom::PinchData::New( + gesture_event->data.pinch_update.zoom_disabled, + gesture_event->data.pinch_update.scale); + break; + } + return gesture_data; } -StructTraits<content::mojom::EventDataView, InputEventUniquePtr>:: - InputEventSerializationContext::InputEventSerializationContext() {} +// static +content::mojom::TouchDataPtr +StructTraits<content::mojom::EventDataView, InputEventUniquePtr>::touch_data( + const InputEventUniquePtr& event) { + if (!event->web_event || + !blink::WebInputEvent::IsTouchEventType(event->web_event->GetType())) + return nullptr; -StructTraits<content::mojom::EventDataView, InputEventUniquePtr>:: - InputEventSerializationContext::~InputEventSerializationContext() {} + const blink::WebTouchEvent* touch_event = + static_cast<const blink::WebTouchEvent*>(event->web_event.get()); + auto touch_data = content::mojom::TouchData::New( + touch_event->dispatch_type, touch_event->moved_beyond_slop_region, + touch_event->touch_start_or_first_touch_move, + touch_event->unique_touch_event_id, + std::vector<content::mojom::TouchPointPtr>()); + for (unsigned i = 0; i < touch_event->touches_length; ++i) { + content::mojom::PointerDataPtr pointer_data = + PointerDataFromPointerProperties(touch_event->touches[i], nullptr); + touch_data->touches.emplace_back(content::mojom::TouchPoint::New( + touch_event->touches[i].state, touch_event->touches[i].radius_x, + touch_event->touches[i].radius_y, + touch_event->touches[i].rotation_angle, std::move(pointer_data))); + } + return touch_data; +} } // namespace mojo
diff --git a/content/common/input/input_event_struct_traits.h b/content/common/input/input_event_struct_traits.h index 9237448..d63ca68 100644 --- a/content/common/input/input_event_struct_traits.h +++ b/content/common/input/input_event_struct_traits.h
@@ -33,44 +33,15 @@ return event->latency_info; } - static const content::mojom::KeyDataPtr& key_data( - const InputEventUniquePtr& event, - void* context) { - return static_cast<InputEventSerializationContext*>(context)->key_data; - } - - static const content::mojom::PointerDataPtr& pointer_data( - const InputEventUniquePtr& event, - void* context) { - return static_cast<InputEventSerializationContext*>(context)->pointer_data; - } - - static const content::mojom::GestureDataPtr& gesture_data( - const InputEventUniquePtr& event, - void* context) { - return static_cast<InputEventSerializationContext*>(context)->gesture_data; - } - - static const content::mojom::TouchDataPtr& touch_data( - const InputEventUniquePtr& event, - void* context) { - return static_cast<InputEventSerializationContext*>(context)->touch_data; - } + static content::mojom::KeyDataPtr key_data(const InputEventUniquePtr& event); + static content::mojom::PointerDataPtr pointer_data( + const InputEventUniquePtr& event); + static content::mojom::GestureDataPtr gesture_data( + const InputEventUniquePtr& event); + static content::mojom::TouchDataPtr touch_data( + const InputEventUniquePtr& event); static bool Read(content::mojom::EventDataView r, InputEventUniquePtr* out); - static void* SetUpContext(const InputEventUniquePtr& handle); - static void TearDownContext(const InputEventUniquePtr& handle, void* context); - - private: - struct InputEventSerializationContext { - content::mojom::KeyDataPtr key_data; - content::mojom::GestureDataPtr gesture_data; - content::mojom::PointerDataPtr pointer_data; - content::mojom::TouchDataPtr touch_data; - - InputEventSerializationContext(); - ~InputEventSerializationContext(); - }; }; } // namespace mojo
diff --git a/content/common/sandbox_linux/bpf_renderer_policy_linux.cc b/content/common/sandbox_linux/bpf_renderer_policy_linux.cc index 67c1301..5f76e35b 100644 --- a/content/common/sandbox_linux/bpf_renderer_policy_linux.cc +++ b/content/common/sandbox_linux/bpf_renderer_policy_linux.cc
@@ -69,6 +69,18 @@ #if defined(__i386__) || defined(__x86_64__) || defined(__mips__) || \ defined(__aarch64__) case __NR_getrlimit: + case __NR_setrlimit: +// We allow setrlimit to dynamically adjust the address space limit as +// needed for WebAssembly memory objects (https://crbug.com/750378). Even +// with setrlimit being allowed, we cannot raise rlim_max once it's +// lowered. Thus we generally have the same protection because we normally +// set rlim_max and rlim_cur together. +// +// See LinuxSandbox::LimitAddressSpace() in +// content/common/sandbox_linux/sandbox_linux.cc and +// ArrayBufferContents::ReserveMemory, +// ArrayBufferContents::ReleaseReservedMemory in +// third_party/WebKit/Source/platform/wtf/typed_arrays/ArrayBufferContents.cpp. #endif #if defined(__i386__) || defined(__arm__) case __NR_ugetrlimit:
diff --git a/content/common/sandbox_linux/sandbox_linux.cc b/content/common/sandbox_linux/sandbox_linux.cc index c45d826b..530fd5a 100644 --- a/content/common/sandbox_linux/sandbox_linux.cc +++ b/content/common/sandbox_linux/sandbox_linux.cc
@@ -22,6 +22,7 @@ #include "base/callback_helpers.h" #include "base/command_line.h" #include "base/debug/stack_trace.h" +#include "base/feature_list.h" #include "base/files/scoped_file.h" #include "base/logging.h" #include "base/macros.h" @@ -33,6 +34,7 @@ #include "base/time/time.h" #include "build/build_config.h" #include "content/common/sandbox_linux/sandbox_seccomp_bpf_linux.h" +#include "content/public/common/content_features.h" #include "content/public/common/content_switches.h" #include "content/public/common/sandbox_linux.h" #include "sandbox/linux/services/credentials.h" @@ -389,6 +391,7 @@ // This is in the hope of making some kernel exploits more complex and less // reliable. It also limits sprays a little on 64-bit. rlim_t address_space_limit = std::numeric_limits<uint32_t>::max(); + rlim_t address_space_limit_max = std::numeric_limits<uint32_t>::max(); #if defined(__LP64__) // On 64 bits, V8 and possibly others will reserve massive memory ranges and // rely on on-demand paging for allocation. Unfortunately, even @@ -396,11 +399,23 @@ // See crbug.com/169327 for a discussion. // On the GPU process, irrespective of V8, we can exhaust a 4GB address space // under normal usage, see crbug.com/271119 - // For now, increase limit to 16GB for renderer and worker and gpu processes + // For now, increase limit to 16GB for renderer and worker and GPU processes // to accomodate. if (process_type == switches::kRendererProcess || process_type == switches::kGpuProcess) { address_space_limit = 1L << 34; + // WebAssembly memory objects use a large amount of address space when + // trap-based bounds checks are enabled. To accomodate this, we allow the + // address space limit to adjust dynamically up to a certain limit. The + // limit is currently 4TiB, which should allow enough address space for any + // reasonable page. See https://crbug.com/750378 + if (base::FeatureList::IsEnabled(features::kWebAssemblyTrapHandler)) { + address_space_limit_max = 1L << 42; + } else { + // If we are not using trap-based bounds checks, there's no reason to + // allow the address space limit to grow. + address_space_limit_max = address_space_limit; + } } #endif // defined(__LP64__) @@ -408,8 +423,8 @@ // allocations that can't be index by an int. const rlim_t kNewDataSegmentMaxSize = std::numeric_limits<int>::max(); - bool limited_as = - sandbox::ResourceLimits::Lower(RLIMIT_AS, address_space_limit); + bool limited_as = sandbox::ResourceLimits::LowerSoftAndHardLimits( + RLIMIT_AS, address_space_limit, address_space_limit_max); bool limited_data = sandbox::ResourceLimits::Lower(RLIMIT_DATA, kNewDataSegmentMaxSize);
diff --git a/content/common/service_worker/service_worker_fetch_request_struct_traits.cc b/content/common/service_worker/service_worker_fetch_request_struct_traits.cc index dec7383..f5f94399 100644 --- a/content/common/service_worker/service_worker_fetch_request_struct_traits.cc +++ b/content/common/service_worker/service_worker_fetch_request_struct_traits.cc
@@ -10,19 +10,6 @@ namespace mojo { -namespace { - -// Struct traits context for the FetchAPIRequest type. Since getters are invoked -// twice when serializing the type, this reduces the load for heavy members. -struct ServiceWorkerFetchRequestStructTraitsContext { - ServiceWorkerFetchRequestStructTraitsContext() = default; - ~ServiceWorkerFetchRequestStructTraitsContext() = default; - - std::map<std::string, std::string> headers; -}; - -} // namespace - using blink::mojom::FetchCredentialsMode; using blink::mojom::FetchRedirectMode; using blink::mojom::FetchRequestMode; @@ -404,29 +391,13 @@ return false; } -void* StructTraits<blink::mojom::FetchAPIRequestDataView, - content::ServiceWorkerFetchRequest>:: - SetUpContext(const content::ServiceWorkerFetchRequest& request) { - ServiceWorkerFetchRequestStructTraitsContext* context = - new ServiceWorkerFetchRequestStructTraitsContext(); - context->headers.insert(request.headers.begin(), request.headers.end()); - - return context; -} - -void StructTraits<blink::mojom::FetchAPIRequestDataView, - content::ServiceWorkerFetchRequest>:: - TearDownContext(const content::ServiceWorkerFetchRequest& request, - void* context) { - delete static_cast<ServiceWorkerFetchRequestStructTraitsContext*>(context); -} - -const std::map<std::string, std::string>& +std::map<std::string, std::string> StructTraits<blink::mojom::FetchAPIRequestDataView, content::ServiceWorkerFetchRequest>:: - headers(const content::ServiceWorkerFetchRequest& request, void* context) { - return static_cast<ServiceWorkerFetchRequestStructTraitsContext*>(context) - ->headers; + headers(const content::ServiceWorkerFetchRequest& request) { + std::map<std::string, std::string> header_map; + header_map.insert(request.headers.begin(), request.headers.end()); + return header_map; } bool StructTraits<blink::mojom::FetchAPIRequestDataView,
diff --git a/content/common/service_worker/service_worker_fetch_request_struct_traits.h b/content/common/service_worker/service_worker_fetch_request_struct_traits.h index 80912e2..c357154 100644 --- a/content/common/service_worker/service_worker_fetch_request_struct_traits.h +++ b/content/common/service_worker/service_worker_fetch_request_struct_traits.h
@@ -73,10 +73,6 @@ template <> struct StructTraits<blink::mojom::FetchAPIRequestDataView, content::ServiceWorkerFetchRequest> { - static void* SetUpContext(const content::ServiceWorkerFetchRequest& request); - static void TearDownContext(const content::ServiceWorkerFetchRequest& request, - void* context); - static content::FetchRequestMode mode( const content::ServiceWorkerFetchRequest& request) { return request.mode; @@ -106,9 +102,8 @@ return request.method; } - static const std::map<std::string, std::string>& headers( - const content::ServiceWorkerFetchRequest& request, - void* context); + static std::map<std::string, std::string> headers( + const content::ServiceWorkerFetchRequest& request); static const std::string& blob_uuid( const content::ServiceWorkerFetchRequest& request) {
diff --git a/content/gpu/gpu_main.cc b/content/gpu/gpu_main.cc index 453ee7c..2bea832 100644 --- a/content/gpu/gpu_main.cc +++ b/content/gpu/gpu_main.cc
@@ -266,7 +266,9 @@ // exits early, the browser process will never detect it. For this reason we // defer tearing down the GPU process until receiving the initialization // message from the browser (through mojom::GpuMain::CreateGpuService()). - const bool init_success = gpu_init.InitializeAndStartSandbox(command_line); + constexpr bool kInProcessGpu = false; + const bool init_success = + gpu_init.InitializeAndStartSandbox(command_line, kInProcessGpu); const bool dead_on_arrival = !init_success; logging::SetLogMessageHandler(NULL);
diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc index 1380274..ec03f8c 100644 --- a/content/public/common/content_features.cc +++ b/content/public/common/content_features.cc
@@ -282,6 +282,12 @@ const base::Feature kSkipCompositingSmallScrollers{ "SkipCompositingSmallScrollers", base::FEATURE_DISABLED_BY_DEFAULT}; +// An experiment to reduce the soft tile memory limit on low-end android +// devices. +const base::Feature kReducedSoftTileMemoryLimitOnLowEndAndroid{ + "kReducedSoftTileMemoryLimitOnLowEndAndroid", + base::FEATURE_DISABLED_BY_DEFAULT}; + // Paint invalidation based on slimming paint. See https://goo.gl/eQczQW const base::Feature kSlimmingPaintInvalidation{ "SlimmingPaintInvalidation", base::FEATURE_ENABLED_BY_DEFAULT};
diff --git a/content/public/common/content_features.h b/content/public/common/content_features.h index 371fda8..2d0cfbb 100644 --- a/content/public/common/content_features.h +++ b/content/public/common/content_features.h
@@ -31,6 +31,8 @@ CONTENT_EXPORT extern const base::Feature kCompositorTouchAction; CONTENT_EXPORT extern const base::Feature kDisablePreferCompositingToLCDTextOnLowEndAndroid; +CONTENT_EXPORT extern const base::Feature + kReducedSoftTileMemoryLimitOnLowEndAndroid; CONTENT_EXPORT extern const base::Feature kExpensiveBackgroundTimerThrottling; CONTENT_EXPORT extern const base::Feature kFeaturePolicy; CONTENT_EXPORT extern const base::Feature kFetchKeepaliveTimeoutSetting;
diff --git a/content/renderer/gpu/render_widget_compositor.cc b/content/renderer/gpu/render_widget_compositor.cc index 3b28891..eb49179 100644 --- a/content/renderer/gpu/render_widget_compositor.cc +++ b/content/renderer/gpu/render_widget_compositor.cc
@@ -487,10 +487,21 @@ // Memory policy on Android WebView does not depend on whether device is // low end, so always use default policy. if (using_low_memory_policy && !using_synchronous_compositor) { - // On low-end we want to be very carefull about killing other - // apps. So initially we use 50% more memory to avoid flickering - // or raster-on-demand. - settings.max_memory_for_prepaint_percentage = 67; + // |using_low_memory_policy| includes both 1GB and 512MB devices. We'd like + // the change of the following percentage to be applied only to 512MB + // devices. + if (base::SysInfo::AmountOfPhysicalMemoryMB() <= 512 && + base::FeatureList::IsEnabled( + features::kReducedSoftTileMemoryLimitOnLowEndAndroid)) { + // The soft tile memroy limit is computed by multiplying hard limit (8MB) + // with this percentage. Seeting this to 13% makes the soft limit ~1MB. + settings.max_memory_for_prepaint_percentage = 13; + } else { + // On low-end we want to be very carefull about killing other + // apps. So initially we use 50% more memory to avoid flickering + // or raster-on-demand. + settings.max_memory_for_prepaint_percentage = 67; + } } else { // On other devices we have increased memory excessively to avoid // raster-on-demand already, so now we reserve 50% _only_ to avoid @@ -540,10 +551,10 @@ settings.preferred_tile_format = viz::RGBA_4444; } - // When running on a low end device, we limit cached bytes to 2MB. - // This allows a typical page to fit its images in cache, but prevents - // most long-term caching. - settings.decoded_image_cache_budget_bytes = 2 * 1024 * 1024; + // When running on a low end device, we limit cached bytes to 512KB. + // This allows pages which are light on images to stay in cache, but + // prevents most long-term caching. + settings.decoded_image_cache_budget_bytes = 512 * 1024; } if (cmd.HasSwitch(switches::kEnableLowResTiling))
diff --git a/device/sensors/BUILD.gn b/device/sensors/BUILD.gn index 3fd38d4..cf68f3d 100644 --- a/device/sensors/BUILD.gn +++ b/device/sensors/BUILD.gn
@@ -68,6 +68,10 @@ "//ui/gfx", ] } + if (is_fuchsia) { + sources += [ "data_fetcher_shared_memory_fuchsia.cc" ] + sources -= [ "data_fetcher_shared_memory_default.cc" ] + } } if (is_android) {
diff --git a/device/sensors/data_fetcher_shared_memory_fuchsia.cc b/device/sensors/data_fetcher_shared_memory_fuchsia.cc new file mode 100644 index 0000000..ce1aee90 --- /dev/null +++ b/device/sensors/data_fetcher_shared_memory_fuchsia.cc
@@ -0,0 +1,29 @@ +// 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 "device/sensors/data_fetcher_shared_memory.h" + +#include "base/logging.h" + +namespace device { + +DataFetcherSharedMemory::DataFetcherSharedMemory() {} + +DataFetcherSharedMemory::~DataFetcherSharedMemory() {} + +bool DataFetcherSharedMemory::Start(ConsumerType consumer_type, void* buffer) { + // TODO(fuchsia): Implement support for sensor consumer buffers. + // (crbug.com/750934) + NOTIMPLEMENTED(); + return false; +} + +bool DataFetcherSharedMemory::Stop(ConsumerType consumer_type) { + // TODO(fuchsia): Implement support for sensor consumer buffers. + // (crbug.com/750934) + NOTIMPLEMENTED(); + return false; +} + +} // namespace device
diff --git a/extensions/renderer/BUILD.gn b/extensions/renderer/BUILD.gn index 84fe159..654c8242 100644 --- a/extensions/renderer/BUILD.gn +++ b/extensions/renderer/BUILD.gn
@@ -106,6 +106,8 @@ "extensions_render_frame_observer.h", "extensions_renderer_client.cc", "extensions_renderer_client.h", + "feature_cache.cc", + "feature_cache.h", "file_system_natives.cc", "file_system_natives.h", "gc_callback.cc", @@ -342,6 +344,7 @@ "bindings/event_emitter_unittest.cc", "bindings/exception_handler_unittest.cc", "event_unittest.cc", + "feature_cache_unittest.cc", "gc_callback_unittest.cc", "json_schema_unittest.cc", "messaging_utils_unittest.cc",
diff --git a/extensions/renderer/dispatcher.cc b/extensions/renderer/dispatcher.cc index f0b69a3..80b3710b 100644 --- a/extensions/renderer/dispatcher.cc +++ b/extensions/renderer/dispatcher.cc
@@ -1129,6 +1129,8 @@ ExtensionsRendererClient::Get()->OnExtensionUnloaded(id); + bindings_system_->OnExtensionRemoved(id); + active_extension_ids_.erase(id); script_injection_manager_->OnExtensionUnloaded(id); @@ -1193,6 +1195,8 @@ extension->permissions_data()->SetPolicyHostRestrictions( params.policy_blocked_hosts, params.policy_allowed_hosts); } + + bindings_system_->OnExtensionPermissionsUpdated(params.extension_id); UpdateBindings(extension->id()); }
diff --git a/extensions/renderer/extension_bindings_system.h b/extensions/renderer/extension_bindings_system.h index ff32b4a..6791fcab 100644 --- a/extensions/renderer/extension_bindings_system.h +++ b/extensions/renderer/extension_bindings_system.h
@@ -7,6 +7,8 @@ #include <string> +#include "extensions/common/extension_id.h" + namespace base { class ListValue; } @@ -62,6 +64,12 @@ // TODO(devlin): Factor this out. virtual RequestSender* GetRequestSender() = 0; + // Called when an extension is removed. + virtual void OnExtensionRemoved(const ExtensionId& id) {} + + // Called when an extension's permissions are updated. + virtual void OnExtensionPermissionsUpdated(const ExtensionId& id) {} + // Returns true if any portion of the runtime API is available to the given // |context|. This is different than just checking features because runtime's // availability depends on the installed extensions and the active URL (in the
diff --git a/extensions/renderer/feature_cache.cc b/extensions/renderer/feature_cache.cc new file mode 100644 index 0000000..22cff87 --- /dev/null +++ b/extensions/renderer/feature_cache.cc
@@ -0,0 +1,100 @@ +// 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 "extensions/renderer/feature_cache.h" + +#include <algorithm> + +#include "base/command_line.h" +#include "content/public/common/content_switches.h" +#include "extensions/common/extension_api.h" +#include "extensions/common/features/feature_provider.h" +#include "extensions/renderer/script_context.h" + +namespace extensions { + +FeatureCache::FeatureCache() {} +FeatureCache::~FeatureCache() = default; + +FeatureCache::FeatureNameVector FeatureCache::GetAvailableFeatures( + ScriptContext* context) { + const FeatureVector& features = GetFeaturesFromCache(context); + FeatureNameVector names; + names.reserve(features.size()); + for (const Feature* feature : features) { + // Since we only cache based on extension id and context type, instead of + // all attributes of a context (like URL), we need to double-check if the + // feature is actually available to the context. This is still a win, since + // we only perform this check on the (much smaller) set of features that + // *may* be available, rather than all known features. + // TODO(devlin): Optimize this - we should be able to tell if a feature may + // change based on additional context attributes. + if (context->IsAnyFeatureAvailableToContext( + *feature, CheckAliasStatus::NOT_ALLOWED)) { + names.push_back(feature->name()); + } + } + return names; +} + +void FeatureCache::InvalidateExtension(const ExtensionId& extension_id) { + for (auto iter = feature_cache_.begin(); iter != feature_cache_.end();) { + if (iter->first.first == extension_id) + iter = feature_cache_.erase(iter); + else + ++iter; + } +} + +const FeatureCache::FeatureVector& FeatureCache::GetFeaturesFromCache( + ScriptContext* context) { + CacheMapKey key(context->GetExtensionID(), context->context_type()); + + auto iter = feature_cache_.find(key); + if (iter != feature_cache_.end()) + return iter->second; + + FeatureVector features; + const FeatureProvider* api_feature_provider = + FeatureProvider::GetAPIFeatures(); + GURL empty_url; + const Extension* extension = context->extension(); + for (const auto& map_entry : api_feature_provider->GetAllFeatures()) { + Feature* feature = map_entry.second.get(); + // Exclude internal APIs. + if (feature->IsInternal()) + continue; + + // Exclude child features (like events or specific functions). + // TODO(devlin): Optimize this - instead of skipping child features and then + // checking IsAnyFeatureAvailableToContext() (which checks child features), + // we should just check all features directly. + if (api_feature_provider->GetParent(feature) != nullptr) + continue; + + // Skip chrome.test if this isn't a test. + if (map_entry.first == "test" && + !base::CommandLine::ForCurrentProcess()->HasSwitch( + ::switches::kTestType)) { + continue; + } + + if (!ExtensionAPI::GetSharedInstance()->IsAnyFeatureAvailableToContext( + *feature, extension, context->context_type(), empty_url, + CheckAliasStatus::NOT_ALLOWED)) { + continue; + } + + features.push_back(feature); + } + + std::sort( + features.begin(), features.end(), + [](const Feature* a, const Feature* b) { return a->name() < b->name(); }); + DCHECK(std::unique(features.begin(), features.end()) == features.end()); + + return feature_cache_.emplace(key, std::move(features)).first->second; +} + +} // namespace extensions
diff --git a/extensions/renderer/feature_cache.h b/extensions/renderer/feature_cache.h new file mode 100644 index 0000000..e66b42f --- /dev/null +++ b/extensions/renderer/feature_cache.h
@@ -0,0 +1,57 @@ +// 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 EXTENSIONS_RENDERER_FEATURE_CACHE_H_ +#define EXTENSIONS_RENDERER_FEATURE_CACHE_H_ + +#include <map> +#include <string> +#include <utility> +#include <vector> + +#include "base/macros.h" +#include "extensions/common/extension_id.h" +#include "extensions/common/features/feature.h" + +namespace extensions { +class ScriptContext; + +// Caches features available to different extensions in different context types, +// and returns features available to a given context. Note: currently, this is +// only used for non-webpage contexts. +// TODO(devlin): Use it for all context types? +class FeatureCache { + public: + using FeatureNameVector = std::vector<std::string>; + + FeatureCache(); + ~FeatureCache(); + + // Returns the names of features available to the given |context| in a + // lexicographically sorted vector. + FeatureNameVector GetAvailableFeatures(ScriptContext* context); + + // Invalidates the cache for the specified extension. + void InvalidateExtension(const ExtensionId& extension_id); + + private: + // Note: We use a key of ExtensionId, Feature::Context to maximize cache hits. + // Unfortunately, this won't always be perfectly accurate, since some features + // may have other context-dependent restrictions (such as URLs), but caching + // by extension id + context + url would result in significantly fewer hits. + using FeatureVector = std::vector<const Feature*>; + using CacheMapKey = std::pair<ExtensionId, Feature::Context>; + using CacheMap = std::map<CacheMapKey, FeatureVector>; + + // Returns the features available to the given context from the cache. + const FeatureVector& GetFeaturesFromCache(ScriptContext* context); + + CacheMap feature_cache_; + + DISALLOW_COPY_AND_ASSIGN(FeatureCache); +}; + +} // namespace extensions + +#endif // EXTENSIONS_RENDERER_FEATURE_CACHE_H_
diff --git a/extensions/renderer/feature_cache_unittest.cc b/extensions/renderer/feature_cache_unittest.cc new file mode 100644 index 0000000..a5a3ccc6 --- /dev/null +++ b/extensions/renderer/feature_cache_unittest.cc
@@ -0,0 +1,105 @@ +// 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 "extensions/renderer/feature_cache.h" + +#include "base/memory/ptr_util.h" +#include "base/stl_util.h" +#include "components/crx_file/id_util.h" +#include "extensions/common/extension.h" +#include "extensions/common/extension_builder.h" +#include "extensions/common/permissions/permissions_data.h" +#include "extensions/common/value_builder.h" +#include "extensions/renderer/bindings/api_binding_test.h" +#include "extensions/renderer/scoped_web_frame.h" +#include "extensions/renderer/script_context.h" +#include "v8/include/v8.h" + +#include "third_party/WebKit/public/platform/WebData.h" +#include "third_party/WebKit/public/platform/WebURL.h" +#include "third_party/WebKit/public/web/WebDocument.h" +#include "third_party/WebKit/public/web/WebLocalFrame.h" + +namespace extensions { + +namespace { + +// TODO(devlin): We should really just make ExtensionBuilder better to avoid +// having so many of these methods lying around. +scoped_refptr<Extension> CreateExtension( + const std::string& name, + const std::vector<std::string>& permissions) { + DictionaryBuilder manifest; + manifest.Set("name", name); + manifest.Set("manifest_version", 2); + manifest.Set("version", "0.1"); + manifest.Set("description", "test extension"); + + { + ListBuilder permissions_builder; + for (const std::string& permission : permissions) + permissions_builder.Append(permission); + manifest.Set("permissions", permissions_builder.Build()); + } + + return ExtensionBuilder() + .SetManifest(manifest.Build()) + .SetLocation(Manifest::INTERNAL) + .SetID(crx_file::id_util::GenerateId(name)) + .Build(); +} + +} // namespace + +using FeatureCacheTest = APIBindingTest; + +TEST_F(FeatureCacheTest, Basic) { + FeatureCache cache; + scoped_refptr<const Extension> extension_a = CreateExtension("a", {}); + scoped_refptr<const Extension> extension_b = + CreateExtension("b", {"storage"}); + + v8::HandleScope handle_scope(isolate()); + v8::Local<v8::Context> v8_context_a = MainContext(); + v8::Local<v8::Context> v8_context_b = AddContext(); + + auto script_context_a = base::MakeUnique<ScriptContext>( + v8_context_a, nullptr, extension_a.get(), + Feature::BLESSED_EXTENSION_CONTEXT, extension_a.get(), + Feature::BLESSED_EXTENSION_CONTEXT); + auto script_context_b = base::MakeUnique<ScriptContext>( + v8_context_b, nullptr, extension_b.get(), + Feature::BLESSED_EXTENSION_CONTEXT, extension_b.get(), + Feature::BLESSED_EXTENSION_CONTEXT); + + auto has_feature = [&cache](const std::unique_ptr<ScriptContext>& context, + const std::string& feature) { + return base::ContainsValue(cache.GetAvailableFeatures(context.get()), + feature); + }; + + // To start, context a should not have access to storage, but context b + // should. + EXPECT_FALSE(has_feature(script_context_a, "storage")); + EXPECT_TRUE(has_feature(script_context_b, "storage")); + + // Update extension b's permissions and invalidate the cache. + extension_b->permissions_data()->SetPermissions( + base::MakeUnique<PermissionSet>(), base::MakeUnique<PermissionSet>()); + cache.InvalidateExtension(extension_b->id()); + + // Now, neither context should have storage access. + EXPECT_FALSE(has_feature(script_context_a, "storage")); + EXPECT_FALSE(has_feature(script_context_b, "storage")); + + script_context_a->Invalidate(); + script_context_b->Invalidate(); +} + +// TODO(devlin): It'd be nice to test that the FeatureCache properly handles +// features that are restricted to certain URLs; unfortunately, for that we'd +// need a stubbed out web frame with a given URL, and there's no good way to do +// that outside Blink. + +} // namespace extensions
diff --git a/extensions/renderer/native_extension_bindings_system.cc b/extensions/renderer/native_extension_bindings_system.cc index ceac3305..b1c5987 100644 --- a/extensions/renderer/native_extension_bindings_system.cc +++ b/extensions/renderer/native_extension_bindings_system.cc
@@ -507,38 +507,13 @@ return; } - const FeatureProvider* api_feature_provider = - FeatureProvider::GetAPIFeatures(); + FeatureCache::FeatureNameVector features = + feature_cache_.GetAvailableFeatures(context); base::StringPiece last_accessor; - for (const auto& map_entry : api_feature_provider->GetAllFeatures()) { + for (const std::string& feature : features) { // If we've already set up an accessor for the immediate property of the // chrome object, we don't need to do more. - if (IsPrefixedAPI(map_entry.first, last_accessor)) - continue; - - // Internal APIs are included via require(api_name) from internal code - // rather than chrome[api_name]. - if (map_entry.second->IsInternal()) - continue; - - // If this API has a parent feature (and isn't marked 'noparent'), - // then this must be a function or event, so we should not register. - if (api_feature_provider->GetParent(map_entry.second.get()) != nullptr) - continue; - - // Skip chrome.test if this isn't a test. - if (map_entry.first == "test" && - !base::CommandLine::ForCurrentProcess()->HasSwitch( - ::switches::kTestType)) { - continue; - } - - // TODO(devlin): UpdateBindingsForContext can be called during context - // creation, but also when e.g. permissions change. We need to be checking - // for whether or not the API already exists on the object as well as - // if we need to remove any existing APIs. - if (!context->IsAnyFeatureAvailableToContext(*map_entry.second, - CheckAliasStatus::NOT_ALLOWED)) + if (IsPrefixedAPI(feature, last_accessor)) continue; // We've found an API that's available to the extension. Normally, we will @@ -546,8 +521,13 @@ // cases, this will be a prefixed API, such as 'app.runtime'. Find what the // property on the chrome object is named, and use that. So in the case of // 'app.runtime', we surface a getter for simply 'app'. + // + // TODO(devlin): UpdateBindingsForContext can be called during context + // creation, but also when e.g. permissions change. Do we need to be + // checking for whether or not the API already exists on the object as well + // as if we need to remove any existing APIs? base::StringPiece accessor_name = - GetFirstDifferentAPIName(map_entry.first, base::StringPiece()); + GetFirstDifferentAPIName(feature, base::StringPiece()); last_accessor = accessor_name; if (!set_accessor(accessor_name)) { LOG(ERROR) << "Failed to create API on Chrome object."; @@ -597,6 +577,15 @@ return ipc_message_sender_.get(); } +void NativeExtensionBindingsSystem::OnExtensionPermissionsUpdated( + const ExtensionId& id) { + feature_cache_.InvalidateExtension(id); +} + +void NativeExtensionBindingsSystem::OnExtensionRemoved(const ExtensionId& id) { + feature_cache_.InvalidateExtension(id); +} + v8::Local<v8::Object> NativeExtensionBindingsSystem::GetAPIObjectForTesting( ScriptContext* context, const std::string& api_name) {
diff --git a/extensions/renderer/native_extension_bindings_system.h b/extensions/renderer/native_extension_bindings_system.h index bac4e85..64c598b 100644 --- a/extensions/renderer/native_extension_bindings_system.h +++ b/extensions/renderer/native_extension_bindings_system.h
@@ -13,6 +13,7 @@ #include "extensions/renderer/bindings/api_bindings_system.h" #include "extensions/renderer/bindings/event_emitter.h" #include "extensions/renderer/extension_bindings_system.h" +#include "extensions/renderer/feature_cache.h" #include "v8/include/v8.h" namespace extensions { @@ -47,6 +48,8 @@ const std::string& error) override; RequestSender* GetRequestSender() override; IPCMessageSender* GetIPCMessageSender() override; + void OnExtensionPermissionsUpdated(const ExtensionId& id) override; + void OnExtensionRemoved(const ExtensionId& id) override; APIBindingsSystem* api_system() { return &api_system_; } @@ -97,6 +100,8 @@ // The APIBindingsSystem associated with this class. APIBindingsSystem api_system_; + FeatureCache feature_cache_; + // A function to acquire an internal API. v8::Eternal<v8::FunctionTemplate> get_internal_api_;
diff --git a/extensions/renderer/native_extension_bindings_system_unittest.cc b/extensions/renderer/native_extension_bindings_system_unittest.cc index 9ebd8c36..972779e 100644 --- a/extensions/renderer/native_extension_bindings_system_unittest.cc +++ b/extensions/renderer/native_extension_bindings_system_unittest.cc
@@ -1024,6 +1024,7 @@ extension->permissions_data()->SetPermissions( base::MakeUnique<PermissionSet>(), base::MakeUnique<PermissionSet>()); + bindings_system()->OnExtensionPermissionsUpdated(extension->id()); bindings_system()->UpdateBindingsForContext(script_context); { // TODO(devlin): Neither the native nor JS bindings systems clear the @@ -1064,6 +1065,7 @@ base::MakeUnique<PermissionSet>(apis, ManifestPermissionSet(), URLPatternSet(), URLPatternSet()), base::MakeUnique<PermissionSet>()); + bindings_system()->OnExtensionPermissionsUpdated(extension->id()); bindings_system()->UpdateBindingsForContext(script_context); }
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doers.cc b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doers.cc index bd0656e..10ffaf7 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doers.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doers.cc
@@ -319,8 +319,16 @@ error::Error GLES2DecoderPassthroughImpl::DoBindBufferBase(GLenum target, GLuint index, GLuint buffer) { - glBindBufferBase(target, index, GetBufferServiceID(buffer, resources_, - bind_generates_resource_)); + FlushErrors(); + glBindBufferBase( + target, index, + GetBufferServiceID(buffer, resources_, bind_generates_resource_)); + if (FlushErrors()) { + return error::kNoError; + } + + bound_buffers_[target] = buffer; + return error::kNoError; } @@ -329,9 +337,17 @@ GLuint buffer, GLintptr offset, GLsizeiptr size) { - glBindBufferRange(target, index, GetBufferServiceID(buffer, resources_, - bind_generates_resource_), - offset, size); + FlushErrors(); + glBindBufferRange( + target, index, + GetBufferServiceID(buffer, resources_, bind_generates_resource_), offset, + size); + if (FlushErrors()) { + return error::kNoError; + } + + bound_buffers_[target] = buffer; + return error::kNoError; }
diff --git a/gpu/command_buffer/tests/gl_clear_framebuffer_unittest.cc b/gpu/command_buffer/tests/gl_clear_framebuffer_unittest.cc index 1e99d48b..b3b3ae30 100644 --- a/gpu/command_buffer/tests/gl_clear_framebuffer_unittest.cc +++ b/gpu/command_buffer/tests/gl_clear_framebuffer_unittest.cc
@@ -58,6 +58,9 @@ void SetDrawDepth(GLfloat depth); void DrawQuad(); + void SetupFramebufferWithDepthStencil(); + void DestroyFramebuffer(); + void TearDown() override { GLTestHelper::CheckGLError("no errors", __LINE__); gl_.Destroy(); @@ -67,6 +70,10 @@ GLManager gl_; GLuint color_handle_; GLuint depth_handle_; + + GLuint framebuffer_handle_; + GLuint color_buffer_handle_; + GLuint depth_stencil_handle_; }; void GLClearFramebufferTest::InitDraw() { @@ -113,6 +120,40 @@ glDrawArrays(GL_TRIANGLES, 0, 6); } +void GLClearFramebufferTest::SetupFramebufferWithDepthStencil() { + glGenFramebuffers(1, &framebuffer_handle_); + DCHECK_NE(0u, framebuffer_handle_); + glBindFramebuffer(GL_FRAMEBUFFER, framebuffer_handle_); + + static const int kFramebufferSize = 4; + + glGenRenderbuffers(1, &color_buffer_handle_); + DCHECK_NE(0u, color_buffer_handle_); + glBindRenderbuffer(GL_RENDERBUFFER, color_buffer_handle_); + glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8_OES, kFramebufferSize, + kFramebufferSize); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + GL_RENDERBUFFER, color_buffer_handle_); + + glGenRenderbuffers(1, &depth_stencil_handle_); + DCHECK_NE(0u, depth_stencil_handle_); + glBindRenderbuffer(GL_RENDERBUFFER, depth_stencil_handle_); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8_OES, + kFramebufferSize, kFramebufferSize); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, + GL_RENDERBUFFER, depth_stencil_handle_); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, + GL_RENDERBUFFER, depth_stencil_handle_); + + glViewport(0, 0, kFramebufferSize, kFramebufferSize); +} + +void GLClearFramebufferTest::DestroyFramebuffer() { + glDeleteRenderbuffers(1, &color_buffer_handle_); + glDeleteRenderbuffers(1, &depth_stencil_handle_); + glDeleteFramebuffers(1, &framebuffer_handle_); +} + INSTANTIATE_TEST_CASE_P(GLClearFramebufferTestWithParam, GLClearFramebufferTest, ::testing::Values(true, false)); @@ -177,6 +218,8 @@ return; } + SetupFramebufferWithDepthStencil(); + const GLuint kStencilRef = 1 << 2; InitDraw(); SetDrawColor(1.0f, 0.0f, 0.0f, 1.0f); @@ -222,6 +265,8 @@ // Verify - depth test should have passed, so red. EXPECT_TRUE( GLTestHelper::CheckPixels(0, 0, 1, 1, 0 /* tolerance */, kRed, nullptr)); + + DestroyFramebuffer(); } } // namespace gpu
diff --git a/gpu/command_buffer/tests/occlusion_query_unittest.cc b/gpu/command_buffer/tests/occlusion_query_unittest.cc index 2f749c7..80331d0e 100644 --- a/gpu/command_buffer/tests/occlusion_query_unittest.cc +++ b/gpu/command_buffer/tests/occlusion_query_unittest.cc
@@ -12,23 +12,36 @@ namespace gpu { +static const int kBackbufferSize = 512; + class OcclusionQueryTest : public testing::Test { protected: void SetUp() override { GLManager::Options options; - options.size = gfx::Size(512, 512); + options.size = gfx::Size(kBackbufferSize, kBackbufferSize); gl_.Initialize(options); + SetupFramebuffer(); } - void TearDown() override { gl_.Destroy(); } + void TearDown() override { + DestroyFramebuffer(); + gl_.Destroy(); + } void DrawRect(float x, float z, float scale, float* color); + void SetupFramebuffer(); + void DestroyFramebuffer(); + GLManager gl_; GLint position_loc_; GLint matrix_loc_; GLint color_loc_; + + GLuint framebuffer_handle_; + GLuint color_buffer_handle_; + GLuint depth_stencil_handle_; }; static void SetMatrix(float x, float z, float scale, float* matrix) { @@ -65,6 +78,36 @@ glDrawArrays(GL_TRIANGLES, 0, 6); } +void OcclusionQueryTest::SetupFramebuffer() { + glGenFramebuffers(1, &framebuffer_handle_); + DCHECK_NE(0u, framebuffer_handle_); + glBindFramebuffer(GL_FRAMEBUFFER, framebuffer_handle_); + + glGenRenderbuffers(1, &color_buffer_handle_); + DCHECK_NE(0u, color_buffer_handle_); + glBindRenderbuffer(GL_RENDERBUFFER, color_buffer_handle_); + glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8_OES, kBackbufferSize, + kBackbufferSize); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + GL_RENDERBUFFER, color_buffer_handle_); + + glGenRenderbuffers(1, &depth_stencil_handle_); + DCHECK_NE(0u, depth_stencil_handle_); + glBindRenderbuffer(GL_RENDERBUFFER, depth_stencil_handle_); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8_OES, + kBackbufferSize, kBackbufferSize); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, + GL_RENDERBUFFER, depth_stencil_handle_); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, + GL_RENDERBUFFER, depth_stencil_handle_); +} + +void OcclusionQueryTest::DestroyFramebuffer() { + glDeleteRenderbuffers(1, &color_buffer_handle_); + glDeleteRenderbuffers(1, &depth_stencil_handle_); + glDeleteFramebuffers(1, &framebuffer_handle_); +} + TEST_F(OcclusionQueryTest, Occlusion) { #if defined(OS_MACOSX) EXPECT_TRUE(GLTestHelper::HasExtension("GL_EXT_occlusion_query_boolean"))
diff --git a/gpu/ipc/service/gpu_init.cc b/gpu/ipc/service/gpu_init.cc index 1cb9b3c..7050908 100644 --- a/gpu/ipc/service/gpu_init.cc +++ b/gpu/ipc/service/gpu_init.cc
@@ -135,7 +135,8 @@ GpuInit::~GpuInit() {} -bool GpuInit::InitializeAndStartSandbox(const base::CommandLine& command_line) { +bool GpuInit::InitializeAndStartSandbox(const base::CommandLine& command_line, + bool in_process_gpu) { if (command_line.HasSwitch(switches::kSupportsDualGpus)) { std::set<int> workarounds; gpu::GpuDriverBugList::AppendWorkaroundsFromCommandLine(&workarounds, @@ -192,7 +193,7 @@ gpu_info_.driver_vendor == "NVIDIA" && !CanAccessNvidiaDeviceFile()) return false; #endif - gpu_info_.in_process_gpu = false; + gpu_info_.in_process_gpu = in_process_gpu; gpu_info_.passthrough_cmd_decoder = gl::UsePassthroughCommandDecoder(&command_line); @@ -218,7 +219,7 @@ // Initialize Ozone GPU after the watchdog in case it hangs. The sandbox // may also have started at this point. ui::OzonePlatform::InitParams params; - params.single_process = false; + params.single_process = in_process_gpu; ui::OzonePlatform::InitializeForGPU(params); #endif
diff --git a/gpu/ipc/service/gpu_init.h b/gpu/ipc/service/gpu_init.h index 268fffc61..5617bce 100644 --- a/gpu/ipc/service/gpu_init.h +++ b/gpu/ipc/service/gpu_init.h
@@ -36,7 +36,8 @@ sandbox_helper_ = helper; } - bool InitializeAndStartSandbox(const base::CommandLine& command_line); + bool InitializeAndStartSandbox(const base::CommandLine& command_line, + bool in_process_gpu); const GPUInfo& gpu_info() const { return gpu_info_; } const GpuFeatureInfo& gpu_feature_info() const { return gpu_feature_info_; }
diff --git a/headless/BUILD.gn b/headless/BUILD.gn index 661f806..91987a4 100644 --- a/headless/BUILD.gn +++ b/headless/BUILD.gn
@@ -804,6 +804,12 @@ } } +if (is_fuchsia) { + fuchsia_executable_runner("headless_shell_fuchsia") { + exe_name = "headless_shell" + } +} + executable("headless_shell") { sources = [ "app/headless_shell_main.cc", @@ -817,6 +823,10 @@ if (is_win) { deps += [ "//build/win:default_exe_manifest" ] } + + if (is_fuchsia) { + deps += [ ":headless_shell_fuchsia" ] + } } process_version("version_header") {
diff --git a/infra/config/cq.cfg b/infra/config/cq.cfg index 54c4888..eec7f9105 100644 --- a/infra/config/cq.cfg +++ b/infra/config/cq.cfg
@@ -94,7 +94,8 @@ name: "master.tryserver.chromium.win" builders { name: "win_chromium_compile_dbg_ng" } builders { name: "win_chromium_rel_ng" } - builders { name: "win_chromium_x64_rel_ng" } + # crbug.com/753184 - take out of the CQ temporarily. + # builders { name: "win_chromium_x64_rel_ng" } builders { name: "win_clang" } } }
diff --git a/ios/chrome/browser/tabs/tab_model.mm b/ios/chrome/browser/tabs/tab_model.mm index 493c1e6..94993a0 100644 --- a/ios/chrome/browser/tabs/tab_model.mm +++ b/ios/chrome/browser/tabs/tab_model.mm
@@ -43,6 +43,7 @@ #import "ios/chrome/browser/tabs/tab_model_synced_window_delegate.h" #import "ios/chrome/browser/tabs/tab_model_web_state_list_delegate.h" #import "ios/chrome/browser/tabs/tab_parenting_observer.h" +#import "ios/chrome/browser/web/page_placeholder_tab_helper.h" #import "ios/chrome/browser/web_state_list/web_state_list.h" #import "ios/chrome/browser/web_state_list/web_state_list_fast_enumeration_helper.h" #import "ios/chrome/browser/web_state_list/web_state_list_metrics_observer.h" @@ -683,13 +684,13 @@ for (int index = oldCount; index < _webStateList->count(); ++index) { web::WebState* webState = _webStateList->GetWebStateAt(index); - Tab* tab = LegacyTabHelper::GetTabForWebState(webState); - tab.webController.usePlaceholderOverlay = YES; + PagePlaceholderTabHelper::FromWebState(webState) + ->AddPlaceholderForNextNavigation(); // Restore the CertificatePolicyCache (note that webState is invalid after // passing it via move semantic to -initWithWebState:model:). - UpdateCertificatePolicyCacheFromWebState(policyCache, [tab webState]); - [restoredTabs addObject:tab]; + UpdateCertificatePolicyCacheFromWebState(policyCache, webState); + [restoredTabs addObject:LegacyTabHelper::GetTabForWebState(webState)]; } // If there was only one tab and it was the new tab page, clobber it.
diff --git a/ios/chrome/browser/ui/browser_view_controller.mm b/ios/chrome/browser/ui/browser_view_controller.mm index 4b4d9b9..e2ccc99c 100644 --- a/ios/chrome/browser/ui/browser_view_controller.mm +++ b/ios/chrome/browser/ui/browser_view_controller.mm
@@ -695,6 +695,15 @@ alignment:(BubbleAlignment)alignment text:(NSString*)text; +// Waits to present a bubble associated with the new tab tip in-product help +// promotion until the feature engagement tracker database is fully initialized. +// Does not present the bubble if |tabTipBubblePresenter.userEngaged| is |YES| +// to prevent resetting |tabTipBubblePresenter| and affecting the value of +// |userEngaged|. +- (void)presentNewTabTipBubbleOnInitialized; +// Presents a bubble associated with the new tab tip in-product help promotion. +- (void)presentNewTabTipBubble; + // Create and show the find bar. - (void)initFindBarForTab; // Search for find bar query string. @@ -1260,36 +1269,7 @@ [super viewDidAppear:animated]; self.viewVisible = YES; [self updateDialogPresenterActiveState]; - - // If the tab tip bubble has already been presented and the user is still - // considered engaged, it can't be overwritten or set to |nil| or else it will - // reset the |userEngaged| property. Once the user is not engaged, the bubble - // can be safely overwritten or set to |nil|. - if (!self.tabTipBubblePresenter.isUserEngaged) { - __weak BrowserViewController* weakSelf = self; - void (^onInitializedBlock)(bool) = ^(bool successfullyLoaded) { - NSString* text = - l10n_util::GetNSStringWithFixup(IDS_IOS_NEW_TAB_IPH_PROMOTION_TEXT); - CGPoint tabSwitcherAnchor = [weakSelf.toolbarController - anchorPointForTabSwitcherButton:BubbleArrowDirectionUp]; - weakSelf.tabTipBubblePresenter = [weakSelf - bubblePresenterForFeature:feature_engagement::kIPHNewTabTipFeature - direction:BubbleArrowDirectionUp - alignment:BubbleAlignmentTrailing - text:text]; - [weakSelf.tabTipBubblePresenter - presentInViewController:self - view:self.view - anchorPoint:tabSwitcherAnchor]; - }; - - // Because the new tab tip occurs on startup, the feature engagement - // tracker's database is not guaranteed to be loaded by this time. For the - // bubble to appear properly, a callback is used to guarantee the event data - // is loaded before the check to see if the promotion should be displayed. - feature_engagement::TrackerFactory::GetForBrowserState(self.browserState) - ->AddOnInitializedCallback(base::BindBlockArc(onInitializedBlock)); - } + [self presentNewTabTipBubbleOnInitialized]; } - (void)viewWillAppear:(BOOL)animated { @@ -2071,6 +2051,51 @@ return bubbleViewControllerPresenter; } +- (void)presentNewTabTipBubbleOnInitialized { + // If the tab tip bubble has already been presented and the user is still + // considered engaged, it can't be overwritten or set to |nil| or else it will + // reset the |userEngaged| property. Once the user is not engaged, the bubble + // can be safely overwritten or set to |nil|. + if (!self.tabTipBubblePresenter.isUserEngaged) { + __weak BrowserViewController* weakSelf = self; + void (^onInitializedBlock)(bool) = ^(bool successfullyLoaded) { + [weakSelf presentNewTabTipBubble]; + }; + + // Because the new tab tip occurs on startup, the feature engagement + // tracker's database is not guaranteed to be loaded by this time. For the + // bubble to appear properly, a callback is used to guarantee the event data + // is loaded before the check to see if the promotion should be displayed. + feature_engagement::TrackerFactory::GetForBrowserState(self.browserState) + ->AddOnInitializedCallback(base::BindBlockArc(onInitializedBlock)); + } +} + +- (void)presentNewTabTipBubble { + NSString* text = + l10n_util::GetNSStringWithFixup(IDS_IOS_NEW_TAB_IPH_PROMOTION_TEXT); + CGPoint tabSwitcherAnchor; + if (IsIPadIdiom()) { + DCHECK([self.tabStripController + respondsToSelector:@selector(anchorPointForTabSwitcherButton:)]); + tabSwitcherAnchor = [self.tabStripController + anchorPointForTabSwitcherButton:BubbleArrowDirectionUp]; + } else { + DCHECK([self.toolbarController + respondsToSelector:@selector(anchorPointForTabSwitcherButton:)]); + tabSwitcherAnchor = [self.toolbarController + anchorPointForTabSwitcherButton:BubbleArrowDirectionUp]; + } + self.tabTipBubblePresenter = + [self bubblePresenterForFeature:feature_engagement::kIPHNewTabTipFeature + direction:BubbleArrowDirectionUp + alignment:BubbleAlignmentTrailing + text:text]; + [self.tabTipBubblePresenter presentInViewController:self + view:self.view + anchorPoint:tabSwitcherAnchor]; +} + #pragma mark - Tap handling - (void)setLastTapPoint:(OpenNewTabCommand*)command {
diff --git a/ios/chrome/browser/ui/bubble/bubble_view_anchor_point_provider.h b/ios/chrome/browser/ui/bubble/bubble_view_anchor_point_provider.h index c16e688..31dd9b2a 100644 --- a/ios/chrome/browser/ui/bubble/bubble_view_anchor_point_provider.h +++ b/ios/chrome/browser/ui/bubble/bubble_view_anchor_point_provider.h
@@ -11,6 +11,7 @@ // Points must be in window-coordinates. @protocol BubbleViewAnchorPointProvider +@optional // Returns either the top-middle or bottom-middle of the tab switcher button // based on |direction|. Point is in window-coordinates. - (CGPoint)anchorPointForTabSwitcherButton:(BubbleArrowDirection)direction;
diff --git a/ios/chrome/browser/ui/payments/contact_info_edit_mediator.mm b/ios/chrome/browser/ui/payments/contact_info_edit_mediator.mm index a6f2686..44bf9d4 100644 --- a/ios/chrome/browser/ui/payments/contact_info_edit_mediator.mm +++ b/ios/chrome/browser/ui/payments/contact_info_edit_mediator.mm
@@ -68,11 +68,17 @@ #pragma mark - PaymentRequestEditViewControllerDataSource - (NSString*)title { - // TODO(crbug.com/602666): Title varies depending on what field is missing. - // e.g., Add Email vs. Add Phone Number. - return self.profile - ? l10n_util::GetNSString(IDS_PAYMENTS_EDIT_CONTACT_DETAILS_LABEL) - : l10n_util::GetNSString(IDS_PAYMENTS_ADD_CONTACT_DETAILS_LABEL); + if (!self.profile) + return l10n_util::GetNSString(IDS_PAYMENTS_ADD_CONTACT_DETAILS_LABEL); + + if (self.paymentRequest->profile_comparator()->IsContactInfoComplete( + self.profile)) { + return l10n_util::GetNSString(IDS_PAYMENTS_EDIT_CONTACT_DETAILS_LABEL); + } + + return base::SysUTF16ToNSString( + self.paymentRequest->profile_comparator() + ->GetTitleForMissingContactFields(*self.profile)); } - (CollectionViewItem*)headerItem {
diff --git a/ios/chrome/browser/ui/payments/contact_info_edit_mediator_unittest.mm b/ios/chrome/browser/ui/payments/contact_info_edit_mediator_unittest.mm index 35400c26..45ac83c 100644 --- a/ios/chrome/browser/ui/payments/contact_info_edit_mediator_unittest.mm +++ b/ios/chrome/browser/ui/payments/contact_info_edit_mediator_unittest.mm
@@ -196,3 +196,26 @@ EXPECT_OCMOCK_VERIFY(consumer); } + +// Tests that the editor's title is correct in various situations. +TEST_F(PaymentRequestContactInfoEditMediatorTest, Title) { + // No profile, so the title should ask to add contact details. + ContactInfoEditMediator* mediator = + [[ContactInfoEditMediator alloc] initWithPaymentRequest:payment_request() + profile:nil]; + EXPECT_TRUE([mediator.title + isEqualToString:l10n_util::GetNSString( + IDS_PAYMENTS_ADD_CONTACT_DETAILS_LABEL)]); + + // Name missing, so title should ask to add a name. + autofill::AutofillProfile autofill_profile = autofill::test::GetFullProfile(); + autofill::test::SetProfileInfo(&autofill_profile, "", "", "", + "johndoe@example.com", "", "", "", "", "", "", + "", "16502111111"); + + mediator = [[ContactInfoEditMediator alloc] + initWithPaymentRequest:payment_request() + profile:&autofill_profile]; + EXPECT_TRUE([mediator.title + isEqualToString:l10n_util::GetNSString(IDS_PAYMENTS_ADD_NAME)]); +}
diff --git a/ios/chrome/browser/ui/side_swipe/BUILD.gn b/ios/chrome/browser/ui/side_swipe/BUILD.gn index 233f2ea..1ea03427 100644 --- a/ios/chrome/browser/ui/side_swipe/BUILD.gn +++ b/ios/chrome/browser/ui/side_swipe/BUILD.gn
@@ -30,6 +30,7 @@ "//ios/chrome/browser/ui", "//ios/chrome/browser/ui/ntp", "//ios/chrome/browser/ui/tabs", + "//ios/chrome/browser/web", "//ios/chrome/common", "//ios/web", "//ui/base",
diff --git a/ios/chrome/browser/ui/side_swipe/card_side_swipe_view.mm b/ios/chrome/browser/ui/side_swipe/card_side_swipe_view.mm index 109380d..8023824e 100644 --- a/ios/chrome/browser/ui/side_swipe/card_side_swipe_view.mm +++ b/ios/chrome/browser/ui/side_swipe/card_side_swipe_view.mm
@@ -22,6 +22,7 @@ #include "ios/chrome/browser/ui/ui_util.h" #import "ios/chrome/browser/ui/uikit_ui_util.h" #import "ios/chrome/browser/ui/util/constraints_ui_util.h" +#import "ios/chrome/browser/web/page_placeholder_tab_helper.h" #include "ios/chrome/grit/ios_theme_resources.h" #import "ios/web/web_state/ui/crw_web_controller.h" #include "url/gurl.h" @@ -241,7 +242,8 @@ dispatch_queue_t priorityQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul); [tab retrieveSnapshot:^(UIImage* image) { - if (tab.webController.usePlaceholderOverlay && + if (PagePlaceholderTabHelper::FromWebState(tab.webState) + ->will_add_placeholder_for_next_navigation() && !ios::device_util::IsSingleCoreDevice()) { [card setImage:[CRWWebController defaultSnapshotImage]]; dispatch_async(priorityQueue, ^{
diff --git a/ios/chrome/browser/ui/side_swipe/side_swipe_controller.mm b/ios/chrome/browser/ui/side_swipe/side_swipe_controller.mm index 397b5d2..85bbec0 100644 --- a/ios/chrome/browser/ui/side_swipe/side_swipe_controller.mm +++ b/ios/chrome/browser/ui/side_swipe/side_swipe_controller.mm
@@ -21,6 +21,7 @@ #import "ios/chrome/browser/ui/side_swipe/side_swipe_util.h" #import "ios/chrome/browser/ui/side_swipe_gesture_recognizer.h" #include "ios/chrome/browser/ui/ui_util.h" +#import "ios/chrome/browser/web/page_placeholder_tab_helper.h" #import "ios/web/public/web_state/web_state_observer_bridge.h" #import "ios/web/web_state/ui/crw_web_controller.h" @@ -253,7 +254,8 @@ break; Tab* tab = [model_ tabAtIndex:index]; - if (tab && tab.webController.usePlaceholderOverlay) { + if (tab && PagePlaceholderTabHelper::FromWebState(tab.webState) + ->will_add_placeholder_for_next_navigation()) { [sessionIDs addObject:tab.tabId]; } index = index + dx;
diff --git a/ios/chrome/browser/ui/tabs/BUILD.gn b/ios/chrome/browser/ui/tabs/BUILD.gn index 5f90849ff..99bcd06 100644 --- a/ios/chrome/browser/ui/tabs/BUILD.gn +++ b/ios/chrome/browser/ui/tabs/BUILD.gn
@@ -39,6 +39,7 @@ "//ios/chrome/browser", "//ios/chrome/browser/browser_state", "//ios/chrome/browser/ui", + "//ios/chrome/browser/ui/bubble", "//ios/chrome/browser/ui/colors", "//ios/chrome/browser/ui/commands", "//ios/chrome/browser/ui/util",
diff --git a/ios/chrome/browser/ui/tabs/tab_strip_controller.h b/ios/chrome/browser/ui/tabs/tab_strip_controller.h index a5c7b11..304e8d4 100644 --- a/ios/chrome/browser/ui/tabs/tab_strip_controller.h +++ b/ios/chrome/browser/ui/tabs/tab_strip_controller.h
@@ -7,6 +7,8 @@ #import <UIKit/UIKit.h> +#import "ios/chrome/browser/ui/bubble/bubble_view_anchor_point_provider.h" + @protocol ApplicationCommands; @protocol BrowserCommands; @protocol FullScreenControllerDelegate; @@ -32,7 +34,7 @@ // display in sync with the TabModel. This controller is only instantiated on // tablet. The tab strip view itself is a subclass of UIScrollView, which // manages scroll offsets and scroll animations. -@interface TabStripController : NSObject +@interface TabStripController : NSObject<BubbleViewAnchorPointProvider> @property(nonatomic, assign) BOOL highlightsSelectedTab; @property(nonatomic, readonly, retain) UIView* view;
diff --git a/ios/chrome/browser/ui/tabs/tab_strip_controller.mm b/ios/chrome/browser/ui/tabs/tab_strip_controller.mm index 8af3768..23258ac9 100644 --- a/ios/chrome/browser/ui/tabs/tab_strip_controller.mm +++ b/ios/chrome/browser/ui/tabs/tab_strip_controller.mm
@@ -20,6 +20,9 @@ #import "ios/chrome/browser/tabs/tab.h" #import "ios/chrome/browser/tabs/tab_model.h" #import "ios/chrome/browser/tabs/tab_model_observer.h" +#import "ios/chrome/browser/ui/bubble/bubble_util.h" +#import "ios/chrome/browser/ui/bubble/bubble_view.h" +#import "ios/chrome/browser/ui/bubble/bubble_view_anchor_point_provider.h" #import "ios/chrome/browser/ui/commands/UIKit+ChromeExecuteCommand.h" #import "ios/chrome/browser/ui/commands/browser_commands.h" #include "ios/chrome/browser/ui/commands/ios_command_ids.h" @@ -698,6 +701,16 @@ } #pragma mark - +#pragma mark BubbleViewAnchorPointProvider methods + +- (CGPoint)anchorPointForTabSwitcherButton:(BubbleArrowDirection)direction { + CGPoint anchorPoint = + bubble_util::AnchorPoint(_tabSwitcherButton.frame, direction); + return [_tabSwitcherButton.superview convertPoint:anchorPoint + toView:_tabSwitcherButton.window]; +} + +#pragma mark - #pragma mark Tab Drag and Drop methods - (void)beginDrag:(UILongPressGestureRecognizer*)gesture {
diff --git a/ios/chrome/browser/ui/webui/net_export/net_export_ui.cc b/ios/chrome/browser/ui/webui/net_export/net_export_ui.cc index c6c3966..48314887 100644 --- a/ios/chrome/browser/ui/webui/net_export/net_export_ui.cc +++ b/ios/chrome/browser/ui/webui/net_export/net_export_ui.cc
@@ -46,8 +46,7 @@ // This class receives javascript messages from the renderer. // Note that the WebUI infrastructure runs on the UI thread, therefore all of -// this class's public methods are expected to run on the UI thread. All static -// functions except SendEmail run on FILE_USER_BLOCKING thread. +// this class's member methods are expected to run on the UI thread. class NetExportMessageHandler : public web::WebUIIOSMessageHandler, public base::SupportsWeakPtr<NetExportMessageHandler>,
diff --git a/ios/chrome/browser/web/page_placeholder_tab_helper.h b/ios/chrome/browser/web/page_placeholder_tab_helper.h index 860783a7..25108b17 100644 --- a/ios/chrome/browser/web/page_placeholder_tab_helper.h +++ b/ios/chrome/browser/web/page_placeholder_tab_helper.h
@@ -29,6 +29,12 @@ // will be removed before navigation is finished. void AddPlaceholderForNextNavigation(); + // true if placeholder will be displayed between DidStartNavigation and + // PageLoaded WebStateObserver callbacks. + bool will_add_placeholder_for_next_navigation() { + return add_placeholder_for_next_navigation_; + } + private: PagePlaceholderTabHelper(web::WebState* web_state, id<PagePlaceholderTabHelperDelegate> delegate); @@ -49,8 +55,6 @@ // true if placeholder is currently being displayed. bool displaying_placeholder_ = false; - // true if placeholder should be displayed between DidStartNavigation and - // PageLoaded WebStateObserver callbacks. bool add_placeholder_for_next_navigation_ = false; base::WeakPtrFactory<PagePlaceholderTabHelper> weak_factory_;
diff --git a/ios/chrome/browser/web/page_placeholder_tab_helper_unittest.mm b/ios/chrome/browser/web/page_placeholder_tab_helper_unittest.mm index 29c0da2..f6a0533 100644 --- a/ios/chrome/browser/web/page_placeholder_tab_helper_unittest.mm +++ b/ios/chrome/browser/web/page_placeholder_tab_helper_unittest.mm
@@ -76,30 +76,39 @@ // requested. TEST_F(PagePlaceholderTabHelperTest, NotShown) { ASSERT_FALSE(delegate_.displayingPlaceholder); + ASSERT_FALSE(tab_helper()->will_add_placeholder_for_next_navigation()); web_state_->OnNavigationStarted(nullptr); EXPECT_FALSE(delegate_.displayingPlaceholder); + EXPECT_FALSE(tab_helper()->will_add_placeholder_for_next_navigation()); } // Tests that placeholder is shown between DidStartNavigation/PageLoaded // WebStateObserver callbacks. TEST_F(PagePlaceholderTabHelperTest, Shown) { + ASSERT_FALSE(tab_helper()->will_add_placeholder_for_next_navigation()); tab_helper()->AddPlaceholderForNextNavigation(); ASSERT_FALSE(delegate_.displayingPlaceholder); + EXPECT_TRUE(tab_helper()->will_add_placeholder_for_next_navigation()); web_state_->OnNavigationStarted(nullptr); EXPECT_TRUE(delegate_.displayingPlaceholder); + EXPECT_FALSE(tab_helper()->will_add_placeholder_for_next_navigation()); web_state_->OnPageLoaded(web::PageLoadCompletionStatus::SUCCESS); EXPECT_FALSE(delegate_.displayingPlaceholder); + EXPECT_FALSE(tab_helper()->will_add_placeholder_for_next_navigation()); } // Tests that destructing WebState removes the placeholder. TEST_F(PagePlaceholderTabHelperTest, DestructWebStateWhenShowingPlaceholder) { + ASSERT_FALSE(tab_helper()->will_add_placeholder_for_next_navigation()); tab_helper()->AddPlaceholderForNextNavigation(); ASSERT_FALSE(delegate_.displayingPlaceholder); + EXPECT_TRUE(tab_helper()->will_add_placeholder_for_next_navigation()); web_state_->OnNavigationStarted(nullptr); EXPECT_TRUE(delegate_.displayingPlaceholder); + EXPECT_FALSE(tab_helper()->will_add_placeholder_for_next_navigation()); web_state_.reset(); EXPECT_FALSE(delegate_.displayingPlaceholder);
diff --git a/ios/web/web_state/ui/crw_web_controller.h b/ios/web/web_state/ui/crw_web_controller.h index 2f55229a..2493e20 100644 --- a/ios/web/web_state/ui/crw_web_controller.h +++ b/ios/web/web_state/ui/crw_web_controller.h
@@ -83,10 +83,6 @@ // is not supported. @property(nonatomic, readonly) UIView* viewForPrinting; -// Content view was reset due to low memory. Use placeholder overlay view on -// next creation. -@property(nonatomic, readwrite, assign) BOOL usePlaceholderOverlay; - // Returns the current page loading phase. @property(nonatomic, readonly) web::LoadPhase loadPhase;
diff --git a/ios/web/web_state/ui/crw_web_controller.mm b/ios/web/web_state/ui/crw_web_controller.mm index 053d100..1750621a 100644 --- a/ios/web/web_state/ui/crw_web_controller.mm +++ b/ios/web/web_state/ui/crw_web_controller.mm
@@ -320,9 +320,6 @@ base::scoped_nsobject<NSMutableArray> _webViewToolbars; // Flag to say if browsing is enabled. BOOL _webUsageEnabled; - // Content view was reset due to low memory. Use the placeholder overlay on - // next creation. - BOOL _usePlaceholderOverlay; // The next time the view is requested, reload the page (using the placeholder // overlay until it's loaded). BOOL _requireReloadOnDisplay; @@ -939,7 +936,6 @@ @implementation CRWWebController @synthesize webUsageEnabled = _webUsageEnabled; -@synthesize usePlaceholderOverlay = _usePlaceholderOverlay; @synthesize loadPhase = _loadPhase; @synthesize shouldSuppressDialogs = _shouldSuppressDialogs; @synthesize webProcessCrashed = _webProcessCrashed; @@ -1979,12 +1975,8 @@ // Display overlay view until current url has finished loading or delay and // then transition away. - if ((_overlayPreviewMode || _usePlaceholderOverlay) && !isChromeScheme) + if (_overlayPreviewMode && !isChromeScheme) [self addPlaceholderOverlay]; - - // Don't reset the overlay flag if in preview mode. - if (!_overlayPreviewMode) - _usePlaceholderOverlay = NO; } else if (_requireReloadOnDisplay && _webView) { _requireReloadOnDisplay = NO; [self addPlaceholderOverlay];
diff --git a/media/mojo/interfaces/video_frame_struct_traits.cc b/media/mojo/interfaces/video_frame_struct_traits.cc index c68fed42..bd73cde 100644 --- a/media/mojo/interfaces/video_frame_struct_traits.cc +++ b/media/mojo/interfaces/video_frame_struct_traits.cc
@@ -56,26 +56,10 @@ } // namespace // static -void* StructTraits<media::mojom::VideoFrameDataView, - scoped_refptr<media::VideoFrame>>:: - SetUpContext(const scoped_refptr<media::VideoFrame>& input) { - return new media::mojom::VideoFrameDataPtr(MakeVideoFrameData(input)); -} - -// static -void StructTraits<media::mojom::VideoFrameDataView, - scoped_refptr<media::VideoFrame>>:: - TearDownContext(const scoped_refptr<media::VideoFrame>& input, - void* context) { - delete static_cast<media::mojom::VideoFrameDataPtr*>(context); -} - -// static -media::mojom::VideoFrameDataPtr& -StructTraits<media::mojom::VideoFrameDataView, - scoped_refptr<media::VideoFrame>>:: - data(const scoped_refptr<media::VideoFrame>& input, void* context) { - return *static_cast<media::mojom::VideoFrameDataPtr*>(context); +media::mojom::VideoFrameDataPtr StructTraits<media::mojom::VideoFrameDataView, + scoped_refptr<media::VideoFrame>>:: + data(const scoped_refptr<media::VideoFrame>& input) { + return media::mojom::VideoFrameDataPtr(MakeVideoFrameData(input)); } // static
diff --git a/media/mojo/interfaces/video_frame_struct_traits.h b/media/mojo/interfaces/video_frame_struct_traits.h index 3324b09..712a3270 100644 --- a/media/mojo/interfaces/video_frame_struct_traits.h +++ b/media/mojo/interfaces/video_frame_struct_traits.h
@@ -19,11 +19,6 @@ template <> struct StructTraits<media::mojom::VideoFrameDataView, scoped_refptr<media::VideoFrame>> { - static void* SetUpContext(const scoped_refptr<media::VideoFrame>& input); - - static void TearDownContext(const scoped_refptr<media::VideoFrame>&, - void* context); - static bool IsNull(const scoped_refptr<media::VideoFrame>& input) { return !input; } @@ -57,9 +52,8 @@ return input->timestamp(); } - static media::mojom::VideoFrameDataPtr& data( - const scoped_refptr<media::VideoFrame>& input, - void* context); + static media::mojom::VideoFrameDataPtr data( + const scoped_refptr<media::VideoFrame>& input); static bool Read(media::mojom::VideoFrameDataView input, scoped_refptr<media::VideoFrame>* output);
diff --git a/mojo/edk/system/ports/node.cc b/mojo/edk/system/ports/node.cc index 658c9d0e..5931318 100644 --- a/mojo/edk/system/ports/node.cc +++ b/mojo/edk/system/ports/node.cc
@@ -11,10 +11,13 @@ #include "base/atomicops.h" #include "base/containers/stack_container.h" +#include "base/lazy_instance.h" #include "base/logging.h" #include "base/memory/ref_counted.h" #include "base/optional.h" #include "base/synchronization/lock.h" +#include "base/threading/thread_local.h" +#include "build/build_config.h" #include "mojo/edk/system/ports/event.h" #include "mojo/edk/system/ports/node_delegate.h" #include "mojo/edk/system/ports/port_locker.h" @@ -31,6 +34,44 @@ namespace { +constexpr size_t kRandomNameCacheSize = 256; + +// Random port name generator which maintains a cache of random bytes to draw +// from. This amortizes the cost of random name generation on platforms where +// RandBytes may have significant per-call overhead. +// +// Note that the use of this cache means one has to be careful about fork()ing +// a process once any port names have been generated, as that behavior can lead +// to collisions between independently generated names in different processes. +class RandomNameGenerator { + public: + RandomNameGenerator() = default; + ~RandomNameGenerator() = default; + + PortName GenerateRandomPortName() { + base::AutoLock lock(lock_); + if (cache_index_ == kRandomNameCacheSize) { +#if defined(OS_NACL) + base::RandBytes(cache_, sizeof(PortName) * kRandomNameCacheSize); +#else + crypto::RandBytes(cache_, sizeof(PortName) * kRandomNameCacheSize); +#endif + cache_index_ = 0; + } + return cache_[cache_index_++]; + } + + private: + base::Lock lock_; + PortName cache_[kRandomNameCacheSize]; + size_t cache_index_ = kRandomNameCacheSize; + + DISALLOW_COPY_AND_ASSIGN(RandomNameGenerator); +}; + +base::LazyInstance<RandomNameGenerator>::Leaky g_name_generator = + LAZY_INSTANCE_INITIALIZER; + int DebugError(const char* message, int error_code) { NOTREACHED() << "Oops: " << message; return error_code; @@ -52,11 +93,7 @@ } void GenerateRandomPortName(PortName* name) { -#if defined(OS_NACL) - base::RandBytes(name, sizeof(PortName)); -#else - crypto::RandBytes(name, sizeof(PortName)); -#endif + *name = g_name_generator.Get().GenerateRandomPortName(); } } // namespace
diff --git a/mojo/public/cpp/bindings/lib/multiplex_router.cc b/mojo/public/cpp/bindings/lib/multiplex_router.cc index c98b7d4..54fae5c8 100644 --- a/mojo/public/cpp/bindings/lib/multiplex_router.cc +++ b/mojo/public/cpp/bindings/lib/multiplex_router.cc
@@ -384,6 +384,11 @@ DCHECK(endpoints_.empty()); } +void MultiplexRouter::AddIncomingMessageFilter( + std::unique_ptr<MessageReceiver> filter) { + filters_.Append(std::move(filter)); +} + void MultiplexRouter::SetMasterInterfaceName(const char* name) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); header_validator_->SetDescription(std::string(name) +
diff --git a/mojo/public/cpp/bindings/lib/multiplex_router.h b/mojo/public/cpp/bindings/lib/multiplex_router.h index be6b2cc..ecbf1a1 100644 --- a/mojo/public/cpp/bindings/lib/multiplex_router.h +++ b/mojo/public/cpp/bindings/lib/multiplex_router.h
@@ -78,6 +78,10 @@ bool set_interface_id_namespace_bit, scoped_refptr<base::SequencedTaskRunner> runner); + // Adds a MessageReceiver which can filter a message after validation but + // before dispatch. + void AddIncomingMessageFilter(std::unique_ptr<MessageReceiver> filter); + // Sets the master interface name for this router. Only used when reporting // message header or control message validation errors. // |name| must be a string literal.
diff --git a/mojo/public/cpp/bindings/tests/struct_with_traits_impl_traits.cc b/mojo/public/cpp/bindings/tests/struct_with_traits_impl_traits.cc index 6b770b1..2586d8d0 100644 --- a/mojo/public/cpp/bindings/tests/struct_with_traits_impl_traits.cc +++ b/mojo/public/cpp/bindings/tests/struct_with_traits_impl_traits.cc
@@ -5,39 +5,11 @@ #include "mojo/public/cpp/bindings/tests/struct_with_traits_impl_traits.h" namespace mojo { -namespace { - -struct Context { - int32_t value; -}; - -} // namespace - -// static -void* StructTraits<test::NestedStructWithTraitsDataView, - test::NestedStructWithTraitsImpl>:: - SetUpContext(const test::NestedStructWithTraitsImpl& input) { - Context* context = new Context; - context->value = input.value; - return context; -} - -// static -void StructTraits<test::NestedStructWithTraitsDataView, - test::NestedStructWithTraitsImpl>:: - TearDownContext(const test::NestedStructWithTraitsImpl& input, - void* context) { - Context* context_obj = static_cast<Context*>(context); - CHECK_EQ(context_obj->value, input.value); - delete context_obj; -} // static int32_t StructTraits<test::NestedStructWithTraitsDataView, test::NestedStructWithTraitsImpl>:: - value(const test::NestedStructWithTraitsImpl& input, void* context) { - Context* context_obj = static_cast<Context*>(context); - CHECK_EQ(context_obj->value, input.value); + value(const test::NestedStructWithTraitsImpl& input) { return input.value; }
diff --git a/mojo/public/cpp/bindings/tests/struct_with_traits_impl_traits.h b/mojo/public/cpp/bindings/tests/struct_with_traits_impl_traits.h index 3590bd55..59a5d1a2 100644 --- a/mojo/public/cpp/bindings/tests/struct_with_traits_impl_traits.h +++ b/mojo/public/cpp/bindings/tests/struct_with_traits_impl_traits.h
@@ -20,12 +20,7 @@ template <> struct StructTraits<test::NestedStructWithTraitsDataView, test::NestedStructWithTraitsImpl> { - static void* SetUpContext(const test::NestedStructWithTraitsImpl& input); - static void TearDownContext(const test::NestedStructWithTraitsImpl& input, - void* context); - - static int32_t value(const test::NestedStructWithTraitsImpl& input, - void* context); + static int32_t value(const test::NestedStructWithTraitsImpl& input); static bool Read(test::NestedStructWithTraitsDataView data, test::NestedStructWithTraitsImpl* output);
diff --git a/mojo/public/tools/fuzzers/fuzz.mojom b/mojo/public/tools/fuzzers/fuzz.mojom index f4a8275..53c8ac6a 100644 --- a/mojo/public/tools/fuzzers/fuzz.mojom +++ b/mojo/public/tools/fuzzers/fuzz.mojom
@@ -59,6 +59,10 @@ array<map<FuzzEnum, map<int8, array<FuzzStruct?>?>>>? fuzz_complex; }; +interface FuzzDummyInterface { + Ping(); +}; + interface FuzzInterface { FuzzBasic(); FuzzBasicResp() => (); @@ -69,4 +73,6 @@ FuzzArgsResp(FuzzStruct a, FuzzStruct? b) => (); [Sync] FuzzArgsSyncResp(FuzzStruct a, FuzzStruct? b) => (); + + FuzzAssociated(associated FuzzDummyInterface& request); };
diff --git a/mojo/public/tools/fuzzers/fuzz_impl.cc b/mojo/public/tools/fuzzers/fuzz_impl.cc index 313327c5..d3b1012 100644 --- a/mojo/public/tools/fuzzers/fuzz_impl.cc +++ b/mojo/public/tools/fuzzers/fuzz_impl.cc
@@ -36,3 +36,10 @@ FuzzArgsSyncRespCallback callback) { std::move(callback).Run(); } + +void FuzzImpl::FuzzAssociated( + fuzz::mojom::FuzzDummyInterfaceAssociatedRequest req) { + associated_bindings_.AddBinding(this, std::move(req)); +} + +void FuzzImpl::Ping() {}
diff --git a/mojo/public/tools/fuzzers/fuzz_impl.h b/mojo/public/tools/fuzzers/fuzz_impl.h index f2d4774..d63a707 100644 --- a/mojo/public/tools/fuzzers/fuzz_impl.h +++ b/mojo/public/tools/fuzzers/fuzz_impl.h
@@ -5,14 +5,17 @@ #ifndef MOJO_PUBLIC_TOOLS_FUZZERS_FUZZ_IMPL_H_ #define MOJO_PUBLIC_TOOLS_FUZZERS_FUZZ_IMPL_H_ +#include "mojo/public/cpp/bindings/associated_binding_set.h" #include "mojo/public/cpp/bindings/binding.h" #include "mojo/public/tools/fuzzers/fuzz.mojom.h" -class FuzzImpl : public fuzz::mojom::FuzzInterface { +class FuzzImpl : public fuzz::mojom::FuzzInterface, + public fuzz::mojom::FuzzDummyInterface { public: explicit FuzzImpl(fuzz::mojom::FuzzInterfaceRequest request); ~FuzzImpl() override; + // fuzz::mojom::FuzzInterface: void FuzzBasic() override; void FuzzBasicResp(FuzzBasicRespCallback callback) override; void FuzzBasicSyncResp(FuzzBasicSyncRespCallback callback) override; @@ -26,8 +29,17 @@ fuzz::mojom::FuzzStructPtr b, FuzzArgsSyncRespCallback callback) override; + void FuzzAssociated( + fuzz::mojom::FuzzDummyInterfaceAssociatedRequest req) override; + + // fuzz::mojom::FuzzDummyInterface: + void Ping() override; + /* Expose the binding to the fuzz harness. */ mojo::Binding<FuzzInterface> binding_; + + private: + mojo::AssociatedBindingSet<FuzzDummyInterface> associated_bindings_; }; #endif // MOJO_PUBLIC_TOOLS_FUZZERS_FUZZ_IMPL_H_
diff --git a/mojo/public/tools/fuzzers/message_corpus/message_0.mojomsg b/mojo/public/tools/fuzzers/message_corpus/message_0.mojomsg index 7b5b302..945b63c4 100644 --- a/mojo/public/tools/fuzzers/message_corpus/message_0.mojomsg +++ b/mojo/public/tools/fuzzers/message_corpus/message_0.mojomsg Binary files differ
diff --git a/mojo/public/tools/fuzzers/message_corpus/message_1.mojomsg b/mojo/public/tools/fuzzers/message_corpus/message_1.mojomsg index 945b63c4..41715c8 100644 --- a/mojo/public/tools/fuzzers/message_corpus/message_1.mojomsg +++ b/mojo/public/tools/fuzzers/message_corpus/message_1.mojomsg Binary files differ
diff --git a/mojo/public/tools/fuzzers/message_corpus/message_10.mojomsg b/mojo/public/tools/fuzzers/message_corpus/message_10.mojomsg new file mode 100644 index 0000000..c19d5c75 --- /dev/null +++ b/mojo/public/tools/fuzzers/message_corpus/message_10.mojomsg Binary files differ
diff --git a/mojo/public/tools/fuzzers/message_corpus/message_11.mojomsg b/mojo/public/tools/fuzzers/message_corpus/message_11.mojomsg new file mode 100644 index 0000000..61ba989 --- /dev/null +++ b/mojo/public/tools/fuzzers/message_corpus/message_11.mojomsg Binary files differ
diff --git a/mojo/public/tools/fuzzers/message_corpus/message_2.mojomsg b/mojo/public/tools/fuzzers/message_corpus/message_2.mojomsg index 41715c8..7b5b302 100644 --- a/mojo/public/tools/fuzzers/message_corpus/message_2.mojomsg +++ b/mojo/public/tools/fuzzers/message_corpus/message_2.mojomsg Binary files differ
diff --git a/mojo/public/tools/fuzzers/message_corpus/message_9.mojomsg b/mojo/public/tools/fuzzers/message_corpus/message_9.mojomsg new file mode 100644 index 0000000..61049cf1 --- /dev/null +++ b/mojo/public/tools/fuzzers/message_corpus/message_9.mojomsg Binary files differ
diff --git a/mojo/public/tools/fuzzers/mojo_fuzzer_message_dump.cc b/mojo/public/tools/fuzzers/mojo_fuzzer_message_dump.cc index 9f2c5077c1..1cc412e 100644 --- a/mojo/public/tools/fuzzers/mojo_fuzzer_message_dump.cc +++ b/mojo/public/tools/fuzzers/mojo_fuzzer_message_dump.cc
@@ -223,10 +223,11 @@ * supplied directory. */ void DumpMessages(std::string output_directory) { fuzz::mojom::FuzzInterfacePtr fuzz; + fuzz::mojom::FuzzDummyInterfaceAssociatedPtr dummy; /* Create the impl and add a MessageDumper to the filter chain. */ env->impl = base::MakeUnique<FuzzImpl>(MakeRequest(&fuzz)); - env->impl->binding_.AddFilter( + env->impl->binding_.RouterForTesting()->AddIncomingMessageFilter( base::MakeUnique<MessageDumper>(output_directory)); /* Call methods in various ways to generate interesting messages. */ @@ -244,6 +245,8 @@ GetPopulatedFuzzStruct(), base::Bind(FuzzCallback)); fuzz->FuzzArgsSyncResp(fuzz::mojom::FuzzStruct::New(), GetPopulatedFuzzStruct(), base::Bind(FuzzCallback)); + fuzz->FuzzAssociated(MakeRequest(&dummy)); + dummy->Ping(); } int main(int argc, char** argv) {
diff --git a/mojo/public/tools/fuzzers/mojo_parse_message_fuzzer.cc b/mojo/public/tools/fuzzers/mojo_parse_message_fuzzer.cc index 0c4fb90..db84644 100644 --- a/mojo/public/tools/fuzzers/mojo_parse_message_fuzzer.cc +++ b/mojo/public/tools/fuzzers/mojo_parse_message_fuzzer.cc
@@ -48,10 +48,9 @@ mojo::internal::ScopedSuppressValidationErrorLoggingForTests log_suppression; }; -Environment* env = new Environment(); - // Entry point for LibFuzzer. extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + static Environment* env = new Environment(); /* Pass the data along to run on a MessageLoop, and wait for it to finish. */ base::RunLoop run; env->message_loop.task_runner()->PostTask(
diff --git a/net/base/filename_util_internal.cc b/net/base/filename_util_internal.cc index fa81d18..6cb28e7 100644 --- a/net/base/filename_util_internal.cc +++ b/net/base/filename_util_internal.cc
@@ -77,7 +77,7 @@ void SanitizeGeneratedFileName(base::FilePath::StringType* filename, bool replace_trailing) { - const base::FilePath::CharType kReplace[] = FILE_PATH_LITERAL("-"); + const base::FilePath::CharType kReplace[] = FILE_PATH_LITERAL("_"); if (filename->empty()) return; if (replace_trailing) { @@ -277,7 +277,7 @@ : base::FilePath::StringType(kFinalFallbackName); overwrite_extension = false; } - replace_illegal_characters_function(&result_str, '-'); + replace_illegal_characters_function(&result_str, '_'); base::FilePath result(result_str); // extension should not appended to filename derived from // content-disposition, if it does not have one.
diff --git a/net/base/filename_util_unittest.cc b/net/base/filename_util_unittest.cc index 22cf1e01..b209666f 100644 --- a/net/base/filename_util_unittest.cc +++ b/net/base/filename_util_unittest.cc
@@ -518,7 +518,7 @@ "", "", L"", - L"-test.html"}, + L"_test.html"}, {__LINE__, "http://www.google.com/", "attachment; filename=\"..\\test.html\"", @@ -534,7 +534,7 @@ "", "", L"", - L"-test.html"}, + L"_test.html"}, {// Filename disappears after leading and trailing periods are removed. __LINE__, "http://www.google.com/", @@ -802,26 +802,26 @@ {// Disposition has relative paths, remove directory separators __LINE__, "http://www.evil.com/my_download.txt", "filename=../../../../././../a_file_name.txt", "", "", "text/plain", - L"download", L"-..-..-..-.-.-..-a_file_name.txt"}, + L"download", L"_.._.._.._._._.._a_file_name.txt"}, {// Disposition has parent directories, remove directory separators __LINE__, "http://www.evil.com/my_download.txt", "filename=dir1/dir2/a_file_name.txt", "", "", "text/plain", L"download", - L"dir1-dir2-a_file_name.txt"}, + L"dir1_dir2_a_file_name.txt"}, {// Disposition has relative paths, remove directory separators __LINE__, "http://www.evil.com/my_download.txt", "filename=..\\..\\..\\..\\.\\.\\..\\a_file_name.txt", "", "", "text/plain", - L"download", L"-..-..-..-.-.-..-a_file_name.txt"}, + L"download", L"_.._.._.._._._.._a_file_name.txt"}, {// Disposition has parent directories, remove directory separators __LINE__, "http://www.evil.com/my_download.txt", "filename=dir1\\dir2\\a_file_name.txt", "", "", "text/plain", L"download", - L"dir1-dir2-a_file_name.txt"}, + L"dir1_dir2_a_file_name.txt"}, {// No useful information in disposition or URL, use default __LINE__, "http://www.truncated.com/path/", "", "", "", "text/plain", L"download", L"download" TXT_EXT}, {// Filename looks like HTML? __LINE__, "http://www.evil.com/get/malware/here", "filename=\"<blink>Hello kitty</blink>\"", "", "", "text/plain", - L"default", L"-blink-Hello kitty--blink-"}, + L"default", L"_blink_Hello kitty__blink_"}, {// A normal avi should get .avi and not .avi.avi __LINE__, "https://blah.google.com/misc/2.avi", "", "", "", "video/x-msvideo", L"download", L"2.avi"}, @@ -854,17 +854,17 @@ {__LINE__, "http://www.goodguy.com/evil.exe ", "filename=evil.exe ", "", "", "binary/octet-stream", L"download", L"evil.exe"}, {__LINE__, "http://www.goodguy.com/evil.exe.", "filename=evil.exe.", "", "", - "binary/octet-stream", L"download", L"evil.exe-"}, + "binary/octet-stream", L"download", L"evil.exe_"}, {__LINE__, "http://www.goodguy.com/evil.exe. . .", "filename=evil.exe. . .", "", "", "binary/octet-stream", L"download", - L"evil.exe-------"}, + L"evil.exe_______"}, {__LINE__, "http://www.goodguy.com/evil.", "filename=evil.", "", "", - "binary/octet-stream", L"download", L"evil-"}, + "binary/octet-stream", L"download", L"evil_"}, {__LINE__, "http://www.goodguy.com/. . . . .", "filename=. . . . .", "", "", "binary/octet-stream", L"download", L"download"}, {__LINE__, "http://www.badguy.com/attachment?name=meh.exe%C2%A0", "attachment; filename=\"meh.exe\xC2\xA0\"", "", "", "binary/octet-stream", - L"", L"meh.exe-"}, + L"", L"meh.exe_"}, #endif // OS_WIN {__LINE__, "http://www.goodguy.com/utils.js", "filename=utils.js", "", "", "application/x-javascript", L"download", L"utils.js"}, @@ -881,15 +881,15 @@ {__LINE__, "http://www.goodguy.com/program.exe", "filename=program.exe", "", "", "application/foo-bar", L"download", L"program.exe"}, {__LINE__, "http://www.evil.com/../foo.txt", "filename=../foo.txt", "", "", - "text/plain", L"download", L"-foo.txt"}, + "text/plain", L"download", L"_foo.txt"}, {__LINE__, "http://www.evil.com/..\\foo.txt", "filename=..\\foo.txt", "", - "", "text/plain", L"download", L"-foo.txt"}, + "", "text/plain", L"download", L"_foo.txt"}, {__LINE__, "http://www.evil.com/.hidden", "filename=.hidden", "", "", "text/plain", L"download", L"hidden"}, {__LINE__, "http://www.evil.com/trailing.", "filename=trailing.", "", "", "dance/party", L"download", #if defined(OS_WIN) - L"trailing-" + L"trailing_" #else L"trailing" #endif @@ -897,7 +897,7 @@ {__LINE__, "http://www.evil.com/trailing.", "filename=trailing.", "", "", "text/plain", L"download", #if defined(OS_WIN) - L"trailing-" + L"trailing_" #else L"trailing" #endif @@ -1031,7 +1031,7 @@ __LINE__, "http://www.example.com/image.aspx?id=blargh", "", "", "", "image/jpeg", L"download", L"image" JPEG_EXT}, {__LINE__, "http://www.example.com/image.aspx?id=blargh", "", "", " .foo", - "", L"download", L"-.foo"}, + "", L"download", L"_.foo"}, // Note that the next 4 tests will not fail on all platforms on regression. // They only fail if application/[x-]gzip has a default extension, which
diff --git a/net/cert/test_root_certs.h b/net/cert/test_root_certs.h index 8a87704e..2a8276ca 100644 --- a/net/cert/test_root_certs.h +++ b/net/cert/test_root_certs.h
@@ -14,6 +14,7 @@ #if defined(USE_NSS_CERTS) #include <cert.h> #include <vector> +#include "net/cert/scoped_nss_types.h" #elif defined(OS_WIN) #include <windows.h> #include "crypto/wincrypt_shim.h" @@ -100,15 +101,15 @@ public: // Creates a new TrustEntry by incrementing the reference to |certificate| // and copying |trust|. - TrustEntry(CERTCertificate* certificate, const CERTCertTrust& trust); + TrustEntry(ScopedCERTCertificate certificate, const CERTCertTrust& trust); ~TrustEntry(); - CERTCertificate* certificate() const { return certificate_; } + CERTCertificate* certificate() const { return certificate_.get(); } const CERTCertTrust& trust() const { return trust_; } private: // The temporary root certificate. - CERTCertificate* certificate_; + ScopedCERTCertificate certificate_; // The original trust settings, before |certificate_| was manipulated to // be a temporarily trusted root.
diff --git a/net/cert/test_root_certs_nss.cc b/net/cert/test_root_certs_nss.cc index f6c489b..8df9a31 100644 --- a/net/cert/test_root_certs_nss.cc +++ b/net/cert/test_root_certs_nss.cc
@@ -11,26 +11,25 @@ #include "base/memory/ptr_util.h" #include "crypto/nss_util.h" #include "net/cert/x509_certificate.h" +#include "net/cert/x509_util_nss.h" namespace net { - -TestRootCerts::TrustEntry::TrustEntry(CERTCertificate* certificate, +TestRootCerts::TrustEntry::TrustEntry(ScopedCERTCertificate certificate, const CERTCertTrust& trust) - : certificate_(CERT_DupCertificate(certificate)), - trust_(trust) { -} + : certificate_(std::move(certificate)), trust_(trust) {} -TestRootCerts::TrustEntry::~TrustEntry() { - CERT_DestroyCertificate(certificate_); -} +TestRootCerts::TrustEntry::~TrustEntry() = default; bool TestRootCerts::Add(X509Certificate* certificate) { - CERTCertificate* cert_handle = certificate->os_cert_handle(); + ScopedCERTCertificate cert_handle = + x509_util::CreateCERTCertificateFromX509Certificate(certificate); + if (!cert_handle) + return false; // Preserve the original trust bits so that they can be restored when // the certificate is removed. CERTCertTrust original_trust; - SECStatus rv = CERT_GetCertTrust(cert_handle, &original_trust); + SECStatus rv = CERT_GetCertTrust(cert_handle.get(), &original_trust); if (rv != SECSuccess) { // CERT_GetCertTrust will fail if the certificate does not have any // particular trust settings associated with it, and attempts to use @@ -49,14 +48,15 @@ return false; } - rv = CERT_ChangeCertTrust(CERT_GetDefaultCertDB(), cert_handle, &new_trust); + rv = CERT_ChangeCertTrust(CERT_GetDefaultCertDB(), cert_handle.get(), + &new_trust); if (rv != SECSuccess) { LOG(ERROR) << "Cannot change certificate trust."; return false; } trust_cache_.push_back( - base::MakeUnique<TrustEntry>(cert_handle, original_trust)); + base::MakeUnique<TrustEntry>(std::move(cert_handle), original_trust)); return true; } @@ -85,7 +85,7 @@ bool TestRootCerts::Contains(CERTCertificate* cert) const { for (const auto& item : trust_cache_) - if (X509Certificate::IsSameOSCert(cert, item->certificate())) + if (x509_util::IsSameCertificate(cert, item->certificate())) return true; return false;
diff --git a/net/cert/test_root_certs_unittest.cc b/net/cert/test_root_certs_unittest.cc index bc7e09f0..92e7d0f 100644 --- a/net/cert/test_root_certs_unittest.cc +++ b/net/cert/test_root_certs_unittest.cc
@@ -18,6 +18,8 @@ #if defined(USE_NSS_CERTS) #include <nss.h> + +#include "net/cert/x509_util_nss.h" #endif using net::test::IsOk; @@ -135,30 +137,36 @@ const char kRootCertificateFile2[] = "2048-rsa-root.pem"; TestRootCerts* test_roots = TestRootCerts::GetInstance(); - ASSERT_NE(static_cast<TestRootCerts*>(NULL), test_roots); + ASSERT_TRUE(test_roots); scoped_refptr<X509Certificate> root_cert_1 = ImportCertFromFile(GetTestCertsDirectory(), kRootCertificateFile); - ASSERT_NE(static_cast<X509Certificate*>(NULL), root_cert_1.get()); + ASSERT_TRUE(root_cert_1); + ScopedCERTCertificate nss_root_cert_1 = + x509_util::CreateCERTCertificateFromX509Certificate(root_cert_1.get()); + ASSERT_TRUE(nss_root_cert_1); scoped_refptr<X509Certificate> root_cert_2 = ImportCertFromFile(GetTestCertsDirectory(), kRootCertificateFile2); - ASSERT_NE(static_cast<X509Certificate*>(NULL), root_cert_2.get()); + ASSERT_TRUE(root_cert_2); + ScopedCERTCertificate nss_root_cert_2 = + x509_util::CreateCERTCertificateFromX509Certificate(root_cert_2.get()); + ASSERT_TRUE(nss_root_cert_2); - EXPECT_FALSE(test_roots->Contains(root_cert_1->os_cert_handle())); - EXPECT_FALSE(test_roots->Contains(root_cert_2->os_cert_handle())); + EXPECT_FALSE(test_roots->Contains(nss_root_cert_1.get())); + EXPECT_FALSE(test_roots->Contains(nss_root_cert_2.get())); EXPECT_TRUE(test_roots->Add(root_cert_1.get())); - EXPECT_TRUE(test_roots->Contains(root_cert_1->os_cert_handle())); - EXPECT_FALSE(test_roots->Contains(root_cert_2->os_cert_handle())); + EXPECT_TRUE(test_roots->Contains(nss_root_cert_1.get())); + EXPECT_FALSE(test_roots->Contains(nss_root_cert_2.get())); EXPECT_TRUE(test_roots->Add(root_cert_2.get())); - EXPECT_TRUE(test_roots->Contains(root_cert_1->os_cert_handle())); - EXPECT_TRUE(test_roots->Contains(root_cert_2->os_cert_handle())); + EXPECT_TRUE(test_roots->Contains(nss_root_cert_1.get())); + EXPECT_TRUE(test_roots->Contains(nss_root_cert_2.get())); test_roots->Clear(); - EXPECT_FALSE(test_roots->Contains(root_cert_1->os_cert_handle())); - EXPECT_FALSE(test_roots->Contains(root_cert_2->os_cert_handle())); + EXPECT_FALSE(test_roots->Contains(nss_root_cert_1.get())); + EXPECT_FALSE(test_roots->Contains(nss_root_cert_2.get())); } #endif
diff --git a/net/cert/x509_certificate_nss.cc b/net/cert/x509_certificate_nss.cc index 69f2de0..0ae96ca 100644 --- a/net/cert/x509_certificate_nss.cc +++ b/net/cert/x509_certificate_nss.cc
@@ -294,11 +294,7 @@ // static bool X509Certificate::IsSameOSCert(X509Certificate::OSCertHandle a, X509Certificate::OSCertHandle b) { - DCHECK(a && b); - if (a == b) - return true; - return a->derCert.len == b->derCert.len && - memcmp(a->derCert.data, b->derCert.data, a->derCert.len) == 0; + return x509_util::IsSameCertificate(a, b); } // static
diff --git a/net/cert/x509_util_nss.cc b/net/cert/x509_util_nss.cc index 38306ab8..e51f7a9 100644 --- a/net/cert/x509_util_nss.cc +++ b/net/cert/x509_util_nss.cc
@@ -13,11 +13,13 @@ #include <secder.h> #include <secmod.h> #include <secport.h> +#include <string.h> #include "base/logging.h" #include "base/strings/stringprintf.h" #include "crypto/nss_util.h" #include "crypto/scoped_nss_types.h" +#include "third_party/boringssl/src/include/openssl/pool.h" namespace net { @@ -130,6 +132,14 @@ } // namespace +bool IsSameCertificate(CERTCertificate* a, CERTCertificate* b) { + DCHECK(a && b); + if (a == b) + return true; + return a->derCert.len == b->derCert.len && + memcmp(a->derCert.data, b->derCert.data, a->derCert.len) == 0; +} + ScopedCERTCertificate CreateCERTCertificateFromBytes(const uint8_t* data, size_t length) { crypto::EnsureNSSInit(); @@ -148,6 +158,21 @@ PR_FALSE /* is_perm */, PR_TRUE /* copyDER */)); } +ScopedCERTCertificate CreateCERTCertificateFromX509Certificate( + const X509Certificate* cert) { +#if BUILDFLAG(USE_BYTE_CERTS) + return CreateCERTCertificateFromBytes( + CRYPTO_BUFFER_data(cert->os_cert_handle()), + CRYPTO_BUFFER_len(cert->os_cert_handle())); +#else + return DupCERTCertificate(cert->os_cert_handle()); +#endif +} + +ScopedCERTCertificate DupCERTCertificate(CERTCertificate* cert) { + return ScopedCERTCertificate(CERT_DupCertificate(cert)); +} + void GetRFC822SubjectAltNames(CERTCertificate* cert_handle, std::vector<std::string>* names) { crypto::ScopedSECItem alt_name(SECITEM_AllocItem(NULL, NULL, 0));
diff --git a/net/cert/x509_util_nss.h b/net/cert/x509_util_nss.h index efcaa04..def75eb 100644 --- a/net/cert/x509_util_nss.h +++ b/net/cert/x509_util_nss.h
@@ -13,6 +13,7 @@ #include "net/base/net_export.h" #include "net/cert/cert_type.h" #include "net/cert/scoped_nss_types.h" +#include "net/cert/x509_certificate.h" typedef struct CERTCertificateStr CERTCertificate; typedef struct CERTNameStr CERTName; @@ -23,12 +24,24 @@ namespace x509_util { +// Returns true if two certificate handles refer to identical certificates. +NET_EXPORT bool IsSameCertificate(CERTCertificate* a, CERTCertificate* b); + // Returns a CERTCertificate handle from the DER-encoded representation. The // returned value may reference an already existing CERTCertificate object. // Returns NULL on failure. NET_EXPORT ScopedCERTCertificate CreateCERTCertificateFromBytes(const uint8_t* data, size_t length); +// Returns a CERTCertificate handle from |cert|. The returned value may +// reference an already existing CERTCertificate object. Returns NULL on +// failure. +NET_EXPORT ScopedCERTCertificate +CreateCERTCertificateFromX509Certificate(const X509Certificate* cert); + +// Increments the refcount of |cert| and returns a handle for that reference. +NET_EXPORT ScopedCERTCertificate DupCERTCertificate(CERTCertificate* cert); + // Stores the values of all rfc822Name subjectAltNames from |cert_handle| // into |names|. If no names are present, clears |names|. // WARNING: This method does not validate that the rfc822Name is
diff --git a/net/cert/x509_util_nss_unittest.cc b/net/cert/x509_util_nss_unittest.cc index 7b49310a..b6ca74c6 100644 --- a/net/cert/x509_util_nss_unittest.cc +++ b/net/cert/x509_util_nss_unittest.cc
@@ -13,6 +13,34 @@ namespace net { +TEST(X509UtilNSSTest, IsSameCertificate) { + ScopedCERTCertificate google_nss_cert( + x509_util::CreateCERTCertificateFromBytes(google_der, + arraysize(google_der))); + ASSERT_TRUE(google_nss_cert); + + ScopedCERTCertificate google_nss_cert2( + x509_util::CreateCERTCertificateFromBytes(google_der, + arraysize(google_der))); + ASSERT_TRUE(google_nss_cert2); + + ScopedCERTCertificate webkit_nss_cert( + x509_util::CreateCERTCertificateFromBytes(webkit_der, + arraysize(webkit_der))); + ASSERT_TRUE(webkit_nss_cert); + + EXPECT_TRUE(x509_util::IsSameCertificate(google_nss_cert.get(), + google_nss_cert.get())); + EXPECT_TRUE(x509_util::IsSameCertificate(google_nss_cert.get(), + google_nss_cert2.get())); + + EXPECT_TRUE(x509_util::IsSameCertificate(webkit_nss_cert.get(), + webkit_nss_cert.get())); + + EXPECT_FALSE(x509_util::IsSameCertificate(google_nss_cert.get(), + webkit_nss_cert.get())); +} + TEST(X509UtilNSSTest, CreateCERTCertificateFromBytes) { ScopedCERTCertificate google_cert(x509_util::CreateCERTCertificateFromBytes( google_der, arraysize(google_der))); @@ -30,6 +58,34 @@ garbage_data, arraysize(garbage_data))); } +TEST(X509UtilNSSTest, CreateCERTCertificateFromX509Certificate) { + scoped_refptr<X509Certificate> x509_cert = + ImportCertFromFile(GetTestCertsDirectory(), "ok_cert.pem"); + ASSERT_TRUE(x509_cert); + ScopedCERTCertificate nss_cert = + x509_util::CreateCERTCertificateFromX509Certificate(x509_cert.get()); + ASSERT_TRUE(nss_cert); + EXPECT_STREQ("CN=127.0.0.1,O=Test CA,L=Mountain View,ST=California,C=US", + nss_cert->subjectName); +} + +TEST(X509UtilNSSTest, DupCERTCertificate) { + ScopedCERTCertificate cert(x509_util::CreateCERTCertificateFromBytes( + google_der, arraysize(google_der))); + ASSERT_TRUE(cert); + + ScopedCERTCertificate cert2 = x509_util::DupCERTCertificate(cert.get()); + // Both handles should hold a reference to the same CERTCertificate object. + ASSERT_EQ(cert.get(), cert2.get()); + + // Release the initial handle. + cert.reset(); + // The duped handle should still be safe to access. + EXPECT_STREQ( + "CN=www.google.com,O=Google Inc,L=Mountain View,ST=California,C=US", + cert2->subjectName); +} + TEST(X509UtilNSSTest, GetDefaultNickname) { base::FilePath certs_dir = GetTestCertsDirectory();
diff --git a/net/quic/core/quic_connection.cc b/net/quic/core/quic_connection.cc index e1f2cbbd..6260660 100644 --- a/net/quic/core/quic_connection.cc +++ b/net/quic/core/quic_connection.cc
@@ -1105,14 +1105,17 @@ ScopedPacketBundler ack_bundler(this, SEND_ACK_IF_PENDING); // The optimized path may be used for data only packets which fit into a // standard buffer and don't need padding. - if (id != kCryptoStreamId && !packet_generator_.HasQueuedFrames() && + const bool flag_run_fast_path = + FLAGS_quic_reloadable_flag_quic_consuming_data_faster; + if (!flag_run_fast_path && id != kCryptoStreamId && + !packet_generator_.HasQueuedFrames() && iov.total_length > kMaxPacketSize && state != FIN_AND_PADDING) { // Use the fast path to send full data packets. return packet_generator_.ConsumeDataFastPath( - id, iov, offset, state != NO_FIN, std::move(ack_listener)); + id, iov, offset, state != NO_FIN, 0, ack_listener); } - return packet_generator_.ConsumeData(id, iov, offset, state, - std::move(ack_listener)); + return packet_generator_.ConsumeData( + id, iov, offset, state, std::move(ack_listener), flag_run_fast_path); } void QuicConnection::SendRstStream(QuicStreamId id,
diff --git a/net/quic/core/quic_flags_list.h b/net/quic/core/quic_flags_list.h index 467e0eab..2ce2872c 100644 --- a/net/quic/core/quic_flags_list.h +++ b/net/quic/core/quic_flags_list.h
@@ -201,3 +201,6 @@ // Add 4 new ack decimation modes to QUIC that are entirely time based at 1/4 // or 1/8 RTT. QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_ack_decimation, false) + +// Enables using the ConsumeDataFastPath more often for large transfers. +QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_consuming_data_faster, false)
diff --git a/net/quic/core/quic_packet_generator.cc b/net/quic/core/quic_packet_generator.cc index 7487cde..2c36419 100644 --- a/net/quic/core/quic_packet_generator.cc +++ b/net/quic/core/quic_packet_generator.cc
@@ -55,7 +55,8 @@ QuicIOVector iov, QuicStreamOffset offset, StreamSendingState state, - QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener) { + QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener, + bool flag_run_fast_path) { bool has_handshake = (id == kCryptoStreamId); bool fin = state != NO_FIN; QUIC_BUG_IF(has_handshake && fin) @@ -77,9 +78,16 @@ QUIC_BUG << "Attempt to consume empty data without FIN."; return QuicConsumedData(0, false); } + // We determine if we can enter the fast path before executing + // the slow path loop. + bool run_fast_path = + flag_run_fast_path && + (!has_handshake && state != FIN_AND_PADDING && !HasQueuedFrames() && + iov.total_length - total_bytes_consumed > kMaxPacketSize); - while (delegate_->ShouldGeneratePacket( - HAS_RETRANSMITTABLE_DATA, has_handshake ? IS_HANDSHAKE : NOT_HANDSHAKE)) { + while (!run_fast_path && delegate_->ShouldGeneratePacket( + HAS_RETRANSMITTABLE_DATA, + has_handshake ? IS_HANDSHAKE : NOT_HANDSHAKE)) { QuicFrame frame; if (!packet_creator_.ConsumeData(id, iov, total_bytes_consumed, offset + total_bytes_consumed, fin, @@ -115,6 +123,16 @@ } // TODO(ianswett): Move to having the creator flush itself when it's full. packet_creator_.Flush(); + + run_fast_path = + flag_run_fast_path && + (!has_handshake && state != FIN_AND_PADDING && !HasQueuedFrames() && + iov.total_length - total_bytes_consumed > kMaxPacketSize); + } + + if (run_fast_path) { + return ConsumeDataFastPath(id, iov, offset, state != NO_FIN, + total_bytes_consumed, std::move(ack_listener)); } // Don't allow the handshake to be bundled with other retransmittable frames. @@ -131,9 +149,10 @@ const QuicIOVector& iov, QuicStreamOffset offset, bool fin, - QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener) { + size_t total_bytes_consumed, + const QuicReferenceCountedPointer<QuicAckListenerInterface>& ack_listener) { DCHECK_NE(id, kCryptoStreamId); - size_t total_bytes_consumed = 0; + while (total_bytes_consumed < iov.total_length && delegate_->ShouldGeneratePacket(HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE)) {
diff --git a/net/quic/core/quic_packet_generator.h b/net/quic/core/quic_packet_generator.h index 43bffc1..637653c 100644 --- a/net/quic/core/quic_packet_generator.h +++ b/net/quic/core/quic_packet_generator.h
@@ -101,17 +101,22 @@ QuicIOVector iov, QuicStreamOffset offset, StreamSendingState state, - QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener); + QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener, + bool flag_run_fast_path); // Sends as many data only packets as allowed by the send algorithm and the // available iov. - // This path does not support FEC, padding, or bundling pending frames. + // This path does not support padding, or bundling pending frames. + // In case we access this method from ConsumeData, total_bytes_consumed + // keeps track of how many bytes have already been consumed. QuicConsumedData ConsumeDataFastPath( QuicStreamId id, const QuicIOVector& iov, QuicStreamOffset offset, bool fin, - QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener); + size_t total_bytes_consumed, + const QuicReferenceCountedPointer<QuicAckListenerInterface>& + ack_listener); // Generates an MTU discovery packet of specified size. void GenerateMtuDiscoveryPacket(
diff --git a/net/quic/core/quic_packet_generator_test.cc b/net/quic/core/quic_packet_generator_test.cc index d965070..5e7acc58 100644 --- a/net/quic/core/quic_packet_generator_test.cc +++ b/net/quic/core/quic_packet_generator_test.cc
@@ -131,7 +131,7 @@ producer_->SaveStreamData(id, iov, 0, offset, iov.total_length); } } - return QuicPacketGenerator::ConsumeDataFastPath(id, iov, offset, fin, + return QuicPacketGenerator::ConsumeDataFastPath(id, iov, offset, fin, 0, std::move(ack_listener)); } @@ -149,8 +149,9 @@ producer_->SaveStreamData(id, iov, 0, offset, iov.total_length); } } - return QuicPacketGenerator::ConsumeData(id, iov, offset, state, - std::move(ack_listener)); + return QuicPacketGenerator::ConsumeData( + id, iov, offset, state, std::move(ack_listener), + FLAGS_quic_reloadable_flag_quic_consuming_data_faster); } SimpleDataProducer* producer_; @@ -598,6 +599,113 @@ PacketContents contents; contents.num_stream_frames = 1; CheckPacketContains(contents, 0); + EXPECT_FALSE(packets_.empty()); + SerializedPacket packet = packets_.back(); + EXPECT_TRUE(!packet.retransmittable_frames.empty()); + EXPECT_EQ(STREAM_FRAME, packet.retransmittable_frames.front().type); + QuicStreamFrame* stream_frame = + packet.retransmittable_frames.front().stream_frame; + EXPECT_EQ(10000u, stream_frame->data_length + stream_frame->offset); +} + +TEST_F(QuicPacketGeneratorTest, ConsumeDataLarge) { + delegate_.SetCanWriteAnything(); + + // Create a 10000 byte IOVector. + QuicIOVector iov(CreateData(10000)); + EXPECT_CALL(delegate_, OnSerializedPacket(_)) + .WillRepeatedly(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); + QuicConsumedData consumed = + generator_.ConsumeData(kHeadersStreamId, iov, 0, FIN, nullptr); + EXPECT_EQ(10000u, consumed.bytes_consumed); + EXPECT_TRUE(consumed.fin_consumed); + EXPECT_FALSE(generator_.HasQueuedFrames()); + EXPECT_FALSE(generator_.HasRetransmittableFrames()); + + PacketContents contents; + contents.num_stream_frames = 1; + CheckPacketContains(contents, 0); + EXPECT_FALSE(packets_.empty()); + SerializedPacket packet = packets_.back(); + EXPECT_TRUE(!packet.retransmittable_frames.empty()); + EXPECT_EQ(STREAM_FRAME, packet.retransmittable_frames.front().type); + QuicStreamFrame* stream_frame = + packet.retransmittable_frames.front().stream_frame; + EXPECT_EQ(10000u, stream_frame->data_length + stream_frame->offset); +} + +TEST_F(QuicPacketGeneratorTest, ConsumeDataLargeSendAckFalse) { + delegate_.SetCanNotWrite(); + + generator_.SetShouldSendAck(false); + generator_.AddControlFrame(QuicFrame(CreateRstStreamFrame())); + EXPECT_TRUE(generator_.HasQueuedFrames()); + EXPECT_TRUE(generator_.HasRetransmittableFrames()); + + delegate_.SetCanWriteAnything(); + + generator_.StartBatchOperations(); + + EXPECT_CALL(delegate_, GetUpdatedAckFrame()) + .WillOnce(Return(QuicFrame(&ack_frame_))); + + // Create a 10000 byte IOVector. + QuicIOVector iov(CreateData(10000)); + EXPECT_CALL(delegate_, OnSerializedPacket(_)) + .WillRepeatedly(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); + QuicConsumedData consumed = + generator_.ConsumeData(kHeadersStreamId, iov, 0, FIN, nullptr); + generator_.FinishBatchOperations(); + + EXPECT_EQ(10000u, consumed.bytes_consumed); + EXPECT_TRUE(consumed.fin_consumed); + EXPECT_FALSE(generator_.HasQueuedFrames()); + EXPECT_FALSE(generator_.HasRetransmittableFrames()); + + EXPECT_FALSE(packets_.empty()); + SerializedPacket packet = packets_.back(); + EXPECT_TRUE(!packet.retransmittable_frames.empty()); + EXPECT_EQ(STREAM_FRAME, packet.retransmittable_frames.front().type); + QuicStreamFrame* stream_frame = + packet.retransmittable_frames.front().stream_frame; + EXPECT_EQ(10000u, stream_frame->data_length + stream_frame->offset); +} + +TEST_F(QuicPacketGeneratorTest, ConsumeDataLargeSendAckTrue) { + delegate_.SetCanNotWrite(); + generator_.SetShouldSendAck(true); + delegate_.SetCanWriteAnything(); + generator_.StartBatchOperations(); + + // Set up frames to write into the creator when control frames are written. + EXPECT_CALL(delegate_, GetUpdatedAckFrame()) + .WillOnce(Return(QuicFrame(&ack_frame_))); + EXPECT_CALL(delegate_, PopulateStopWaitingFrame(_)); + // Generator should have queued control frames, and creator should be empty. + EXPECT_TRUE(generator_.HasQueuedFrames()); + EXPECT_FALSE(generator_.HasRetransmittableFrames()); + EXPECT_FALSE(creator_->HasPendingFrames()); + + // Create a 10000 byte IOVector. + QuicIOVector iov(CreateData(10000)); + EXPECT_CALL(delegate_, OnSerializedPacket(_)) + .WillRepeatedly(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); + QuicConsumedData consumed = + generator_.ConsumeData(kHeadersStreamId, iov, 0, FIN, nullptr); + generator_.FinishBatchOperations(); + + EXPECT_EQ(10000u, consumed.bytes_consumed); + EXPECT_TRUE(consumed.fin_consumed); + EXPECT_FALSE(generator_.HasQueuedFrames()); + EXPECT_FALSE(generator_.HasRetransmittableFrames()); + + EXPECT_FALSE(packets_.empty()); + SerializedPacket packet = packets_.back(); + EXPECT_TRUE(!packet.retransmittable_frames.empty()); + EXPECT_EQ(STREAM_FRAME, packet.retransmittable_frames.front().type); + QuicStreamFrame* stream_frame = + packet.retransmittable_frames.front().stream_frame; + EXPECT_EQ(10000u, stream_frame->data_length + stream_frame->offset); } TEST_F(QuicPacketGeneratorTest, NotWritableThenBatchOperations) {
diff --git a/ppapi/tests/test_file_chooser.cc b/ppapi/tests/test_file_chooser.cc index dbacc0b6..4ce42a0 100644 --- a/ppapi/tests/test_file_chooser.cc +++ b/ppapi/tests/test_file_chooser.cc
@@ -131,7 +131,7 @@ const std::vector<pp::FileRef>& output_ref = filechooser_callback.output(); ASSERT_EQ(1u, output_ref.size()); - ASSERT_EQ("unsafe.txt-", output_ref.front().GetName().AsString()); + ASSERT_EQ("unsafe.txt_", output_ref.front().GetName().AsString()); ASSERT_TRUE(WriteDefaultContentsToFile(output_ref.front())); PASS();
diff --git a/sandbox/linux/services/resource_limits.cc b/sandbox/linux/services/resource_limits.cc index 1ec1129..51f13c3 100644 --- a/sandbox/linux/services/resource_limits.cc +++ b/sandbox/linux/services/resource_limits.cc
@@ -3,6 +3,7 @@ // found in the LICENSE file. #include "sandbox/linux/services/resource_limits.h" +#include "base/numerics/safe_math.h" #include <sys/resource.h> #include <sys/time.h> @@ -13,14 +14,32 @@ // static bool ResourceLimits::Lower(int resource, rlim_t limit) { + return LowerSoftAndHardLimits(resource, limit, limit); +} + +// static +bool ResourceLimits::LowerSoftAndHardLimits(int resource, + rlim_t soft_limit, + rlim_t hard_limit) { struct rlimit old_rlimit; if (getrlimit(resource, &old_rlimit)) return false; // Make sure we don't raise the existing limit. - const struct rlimit new_rlimit = {std::min(old_rlimit.rlim_cur, limit), - std::min(old_rlimit.rlim_max, limit)}; - int rc = setrlimit(resource, &new_rlimit); - return rc == 0; + const struct rlimit new_rlimit = {std::min(old_rlimit.rlim_cur, soft_limit), + std::min(old_rlimit.rlim_max, hard_limit)}; + return setrlimit(resource, &new_rlimit) == 0; +} + +// static +bool ResourceLimits::AdjustCurrent(int resource, long long int change) { + struct rlimit old_rlimit; + if (getrlimit(resource, &old_rlimit)) + return false; + base::CheckedNumeric<rlim_t> limit = old_rlimit.rlim_cur; + limit += change; + const struct rlimit new_rlimit = {limit.ValueOrDie(), old_rlimit.rlim_max}; + // setrlimit will fail if limit > old_rlimit.rlim_max. + return setrlimit(resource, &new_rlimit) == 0; } } // namespace sandbox
diff --git a/sandbox/linux/services/resource_limits.h b/sandbox/linux/services/resource_limits.h index 3464dab..ab949dd 100644 --- a/sandbox/linux/services/resource_limits.h +++ b/sandbox/linux/services/resource_limits.h
@@ -19,6 +19,16 @@ // Lower the soft and hard limit of |resource| to |limit|. If the current // limit is lower than |limit|, keep it. static bool Lower(int resource, rlim_t limit) WARN_UNUSED_RESULT; + // Lower the soft limit of |resource| to |limit| and the hard limit to + // |max|. If the current limit is lower than the new values, keep it. + static bool LowerSoftAndHardLimits(int resource, + rlim_t soft_limit, + rlim_t hard_limit) WARN_UNUSED_RESULT; + // Change soft limit of |resource| to the current limit plus |change|. Fails + // and returns false if the new soft limit would be greater than the hard + // limit. + static bool AdjustCurrent(int resource, + long long int change) WARN_UNUSED_RESULT; private: DISALLOW_IMPLICIT_CONSTRUCTORS(ResourceLimits);
diff --git a/services/identity/public/cpp/scope_set_struct_traits.h b/services/identity/public/cpp/scope_set_struct_traits.h index 467b9065..17882b0 100644 --- a/services/identity/public/cpp/scope_set_struct_traits.h +++ b/services/identity/public/cpp/scope_set_struct_traits.h
@@ -11,22 +11,11 @@ template <> struct StructTraits<identity::mojom::ScopeSet::DataView, identity::ScopeSet> { - static void* SetUpContext(const identity::ScopeSet& scope_set) { - std::vector<std::string>* scopes = new std::vector<std::string>(); + static std::vector<std::string> scopes(const identity::ScopeSet& scope_set) { + std::vector<std::string> entries; for (const auto& scope : scope_set) - scopes->push_back(scope); - return scopes; - } - - static void TearDownContext(const identity::ScopeSet& scope_set, - void* context) { - delete static_cast<std::vector<std::string>*>(context); - } - - static const std::vector<std::string>& scopes( - const identity::ScopeSet& scope_set, - void* context) { - return *(static_cast<std::vector<std::string>*>(context)); + entries.push_back(scope); + return entries; } static bool Read(identity::mojom::ScopeSetDataView data,
diff --git a/services/ui/gpu/gpu_main.cc b/services/ui/gpu/gpu_main.cc index 09033e8..a329902 100644 --- a/services/ui/gpu/gpu_main.cc +++ b/services/ui/gpu/gpu_main.cc
@@ -150,10 +150,13 @@ void GpuMain::InitOnGpuThread( scoped_refptr<base::SingleThreadTaskRunner> io_runner, scoped_refptr<base::SingleThreadTaskRunner> compositor_runner) { + // TODO(kylechar): When process split happens this shouldn't be a constant. + constexpr bool kInProcessGpu = true; + gpu_init_.reset(new gpu::GpuInit()); gpu_init_->set_sandbox_helper(this); bool success = gpu_init_->InitializeAndStartSandbox( - *base::CommandLine::ForCurrentProcess()); + *base::CommandLine::ForCurrentProcess(), kInProcessGpu); if (!success) return;
diff --git a/services/ui/service.cc b/services/ui/service.cc index e8f02c9..7b2b52e 100644 --- a/services/ui/service.cc +++ b/services/ui/service.cc
@@ -239,7 +239,7 @@ // in MUS, |InitializeForUI| will load the GL libraries. ui::OzonePlatform::InitParams params; params.connector = context()->connector(); - params.single_process = false; + params.single_process = true; ui::OzonePlatform::InitializeForUI(params); // Assume a client will change the layout to an appropriate configuration.
diff --git a/services/viz/PRESUBMIT.py b/services/viz/PRESUBMIT.py new file mode 100644 index 0000000..babbf3f --- /dev/null +++ b/services/viz/PRESUBMIT.py
@@ -0,0 +1,16 @@ +# 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. + +"""Top-level presubmit script for services/viz.""" + +def CheckChangeOnUpload(input_api, output_api): + import sys + original_sys_path = sys.path + sys.path = sys.path + [input_api.os_path.join( + input_api.change.RepositoryRoot(), + 'components', 'viz')] + + import presubmit_checks as ps + white_list=(r'^services[\\/]viz[\\/].*\.(cc|h)$',) + return ps.RunAllChecks(input_api, output_api, white_list)
diff --git a/skia/config/SkUserConfig.h b/skia/config/SkUserConfig.h index 4ec4597..675126e 100644 --- a/skia/config/SkUserConfig.h +++ b/skia/config/SkUserConfig.h
@@ -208,6 +208,10 @@ #define SK_SUPPORT_LEGACY_STREAM_API #endif +#ifndef SK_SUPPORT_LEGACY_LOCAL_ROTATE_SHADER +#define SK_SUPPORT_LEGACY_LOCAL_ROTATE_SHADER +#endif + #ifndef SK_DISABLE_DEFERRED_PROXIES #define SK_DISABLE_DEFERRED_PROXIES #endif
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json index 6e25bc7..19d9833b 100644 --- a/testing/buildbot/chromium.fyi.json +++ b/testing/buildbot/chromium.fyi.json
@@ -10567,95 +10567,19 @@ }, "Fuchsia (dbg)": { "additional_compile_targets": [ + "base_unittests", + "crypto_unittests", "gl_unittests", + "ipc_tests", "media_unittests", - "net_unittests" - ], - "gtest_tests": [ - { - "args": [ - "--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.base_unittests.filter" - ], - "swarming": { - "can_use_on_swarming_builders": false - }, - "test": "base_unittests" - }, - { - "swarming": { - "can_use_on_swarming_builders": false - }, - "test": "crypto_unittests" - }, - { - "args": [ - "--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.ipc_tests.filter" - ], - "swarming": { - "can_use_on_swarming_builders": false - }, - "test": "ipc_tests" - }, - { - "args": [ - "--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.media_unittests.filter" - ], - "swarming": { - "can_use_on_swarming_builders": false - }, - "test": "media_unittests" - }, - { - "swarming": { - "can_use_on_swarming_builders": false - }, - "test": "mojo_common_unittests" - }, - { - "args": [ - "--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.mojo_js_unittests.filter" - ], - "swarming": { - "can_use_on_swarming_builders": false - }, - "test": "mojo_js_unittests" - }, - { - "swarming": { - "can_use_on_swarming_builders": false - }, - "test": "mojo_public_bindings_unittests" - }, - { - "swarming": { - "can_use_on_swarming_builders": false - }, - "test": "mojo_public_system_unittests" - }, - { - "args": [ - "--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.mojo_system_unittests.filter" - ], - "swarming": { - "can_use_on_swarming_builders": false - }, - "test": "mojo_system_unittests" - }, - { - "swarming": { - "can_use_on_swarming_builders": false - }, - "test": "skia_unittests" - }, - { - "args": [ - "--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.ui_base_unittests.filter" - ], - "swarming": { - "can_use_on_swarming_builders": false - }, - "test": "ui_base_unittests" - } + "mojo_common_unittests", + "mojo_js_unittests", + "mojo_public_bindings_unittests", + "mojo_public_system_unittests", + "mojo_system_unittests", + "net_unittests", + "skia_unittests", + "ui_base_unittests" ] }, "Fuchsia Compile": {
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index b655dcd4..7fa0129 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -1296,6 +1296,22 @@ ] } ], + "MITMSoftwareInterstitial": [ + { + "platforms": [ + "chromeos", + "linux", + "mac", + "win", + "android" + ], + "experiments": [ + { + "name": "Enabled" + } + ] + } + ], "MacAllowBackgroundingProcesses": [ { "platforms": [ @@ -1706,30 +1722,6 @@ ] } ], - "NoStatePrefetchValidation": [ - { - "platforms": [ - "android", - "chromeos", - "linux", - "mac", - "win" - ], - "experiments": [ - { - "name": "PrerenderDisabled_R2", - "params": { - "instant_mode": "simple_load", - "mode": "simple_load", - "omnibox_mode": "simple_load" - }, - "enable_features": [ - "NoStatePrefetch" - ] - } - ] - } - ], "NonDelayableThrottlesDelayable": [ { "platforms": [ @@ -3002,24 +2994,6 @@ "enable_features": [ "TranslateCompactUI" ] - }, - { - "name": "CompactUIAndRanker", - "enable_features": [ - "TranslateCompactUI", - "TranslateRankerEnforcement", - "TranslateRankerQuery" - ] - }, - { - "name": "RankerOnly", - "enable_features": [ - "TranslateRankerEnforcement", - "TranslateRankerQuery" - ], - "disable_features": [ - "TranslateCompactUI" - ] } ] } @@ -3056,6 +3030,16 @@ ], "experiments": [ { + "name": "Enforcement20170329", + "params": { + "translate-ranker-model-url": "https://www.gstatic.com/chrome/intelligence/assist/ranker/models/translate/2017/03/translate_ranker_model_20170329.pb.bin" + }, + "enable_features": [ + "TranslateRankerEnforcement", + "TranslateRankerQuery" + ] + }, + { "name": "Query20170329", "params": { "translate-ranker-model-url": "https://www.gstatic.com/chrome/intelligence/assist/ranker/models/translate/2017/03/translate_ranker_model_20170329.pb.bin"
diff --git a/third_party/.gitignore b/third_party/.gitignore index c16a25f..4213f70 100644 --- a/third_party/.gitignore +++ b/third_party/.gitignore
@@ -9,6 +9,7 @@ /android_protobuf/src /android_support_test_runner/lib/*.aar /android_support_test_runner/lib/*.jar +/android_system_sdk/*.jar /android_tools/ /android_tools_internal/ /android_webview_glue/src
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-features=NetworkService b/third_party/WebKit/LayoutTests/FlagExpectations/enable-features=NetworkService index 77b35744..f7ed034 100644 --- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-features=NetworkService +++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-features=NetworkService
@@ -173,6 +173,7 @@ Bug(none) external/wpt/FileAPI/url/url_xmlhttprequest.html [ Crash Failure Timeout ] Bug(none) external/wpt/XMLHttpRequest [ Crash Failure Timeout ] Bug(none) external/wpt/background-fetch/interfaces-worker.https.html [ Crash Failure Timeout ] +Bug(none) external/wpt/beacon/headers/header-content-type.html [ Timeout ] Bug(none) external/wpt/clear-site-data/navigation.https.html [ Timeout ] Bug(none) external/wpt/content-security-policy/child-src/child-src-about-blank-allowed-by-default.sub.html [ Failure Timeout ] Bug(none) external/wpt/content-security-policy/child-src/child-src-about-blank-allowed-by-scheme.sub.html [ Failure Timeout ] @@ -391,7 +392,7 @@ Bug(715632) http/tests/appcache/manifest-redirect.html [ Crash ] Bug(none) http/tests/appcache/manifest-parsing.html [ Failure ] Bug(none) http/tests/appcache/multi-fallback.html [ Failure Timeout ] -Bug(none) http/tests/appcache/non-html.xhtml [ Timeout ] +Bug(none) http/tests/appcache/non-html.xhtml [ Crash ] Bug(none) http/tests/appcache/offline-access.html [ Timeout ] Bug(none) http/tests/appcache/online-fallback-layering.html [ Timeout ] Bug(none) http/tests/appcache/online-whitelist.html [ Failure ] @@ -1288,4 +1289,4 @@ Bug(none) tables/mozilla_expected_failures/marvin/backgr_fixed-bg.html [ Failure ] Bug(none) traversal/node-iterator-009.html [ Failure ] Bug(none) traversal/tree-walker-006.html [ Failure ] -Bug(none) virtual [ Crash Failure Timeout ] \ No newline at end of file +Bug(none) virtual [ Crash Failure Timeout ]
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations index d3b1e31d..1d28bc8 100644 --- a/third_party/WebKit/LayoutTests/TestExpectations +++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -2666,8 +2666,6 @@ crbug.com/747751 http/tests/inspector/application-panel/resources-panel-resource-preview.html [ Failure Pass ] crbug.com/689781 external/wpt/media-source/mediasource-duration.html [ Failure Pass ] -crbug.com/689781 http/tests/media/media-source/mediasource-duration.html [ Failure Pass ] -crbug.com/689781 virtual/mojo-loading/http/tests/media/media-source/mediasource-duration.html [ Failure Pass ] crbug.com/701445 external/wpt/dom/events/EventListener-invoke-legacy.html [ Timeout Pass ]
diff --git a/third_party/WebKit/LayoutTests/editing/execCommand/insert-list-items-in-table-cell.html b/third_party/WebKit/LayoutTests/editing/execCommand/insert-list-items-in-table-cell.html new file mode 100644 index 0000000..2e84db8 --- /dev/null +++ b/third_party/WebKit/LayoutTests/editing/execCommand/insert-list-items-in-table-cell.html
@@ -0,0 +1,59 @@ +<!DOCTYPE html> +<script src="../../resources/testharness.js"></script> +<script src="../../resources/testharnessreport.js"></script> +<script src="../assert_selection.js"></script> +<script> +function doubleInsertOrderedList(s) { + document.execCommand('insertOrderedList'); + document.execCommand('insertOrderedList'); +} + +test(() => assert_selection( + '<div contenteditable><table><tr><td>|fsdf</td><td>fsdf</td></tr><tr><td>gghfg</td><td>fsfg</td></tr></table></div>', + 'insertOrderedList', + '<div contenteditable><table><tbody><tr><td><ol><li>|fsdf</li></ol></td><td>fsdf</td></tr><tr><td>gghfg</td><td>fsfg</td></tr></tbody></table></div>'), + 'insertOrderedList - Insert list items in a single table cell.'); + +test(() => assert_selection( + '<div contenteditable><table><tr><td>^fsdf</td><td>fsdf|</td></tr><tr><td>gghfg</td><td>fsfg</td></tr></table></div>', + 'insertOrderedList', + '<div contenteditable><table><tbody><tr><td><ol><li>^fsdf</li></ol></td><td><ol><li>fsdf|</li></ol></td></tr><tr><td>gghfg</td><td>fsfg</td></tr></tbody></table></div>'), + 'insertOrderedList - Insert list items in all the cells of a table row.'); + +test(() => assert_selection( + '<div contenteditable><table><tr><td>^fsdf</td><td>fsdf</td></tr><tr><td>gghfg</td><td>fsfg|</td></tr></table></div>', + 'insertOrderedList', + '<div contenteditable><table><tbody><tr><td><ol><li>^fsdf</li></ol></td><td><ol><li>fsdf</li></ol></td></tr><tr><td><ol><li>gghfg</li></ol></td><td><ol><li>fsfg|</li></ol></td></tr></tbody></table></div>'), + 'insertOrderedList - Insert list items in all the cells of a table.'); + +test(() => assert_selection( + '<div contenteditable>^<table><tr><td>fsdf</td><td>fsdf</td></tr><tr><td>gghfg</td><td>fsfg</td></tr></table>|</div>', + 'insertOrderedList', + '<div contenteditable><ol><li>^<table><tbody><tr><td>fsdf</td><td>fsdf</td></tr><tr><td>gghfg</td><td>fsfg</td></tr></tbody></table>|</li></ol></div>'), + 'insertOrderedList - Insert a list item in a table.'); + +test(() => assert_selection( + '<div contenteditable><table><tr><td>|fsdf</td><td>fsdf</td></tr><tr><td>gghfg</td><td>fsfg</td></tr></table></div>', + 'doubleInsertOrderedList', + '<div contenteditable><table><tbody><tr><td>|fsdf</td><td>fsdf</td></tr><tr><td>gghfg</td><td>fsfg</td></tr></tbody></table></div>'), + 'doubleInsertOrderedList - Exec insertOrderedList twice in a single cell of a table row does not change the editable area at all.'); + +test(() => assert_selection( + '<div contenteditable><table><tr><td>^fsdf</td><td>fsdf|</td></tr><tr><td>gghfg</td><td>fsfg</td></tr></table></div>', + 'doubleInsertOrderedList', + '<div contenteditable><table><tbody><tr><td>^fsdf</td><td>fsdf|</td></tr><tr><td>gghfg</td><td>fsfg</td></tr></tbody></table></div>'), + 'doubleInsertOrderedList - Exec insertOrderedList twice in all the cells of a table row does not change the editable area at all.'); + +test(() => assert_selection( + '<div contenteditable><table><tr><td>^fsdf</td><td>fsdf</td></tr><tr><td>gghfg</td><td>fsfg|</td></tr></table></div>', + 'doubleInsertOrderedList', + '<div contenteditable><table><tbody><tr><td>^fsdf</td><td>fsdf</td></tr><tr><td>gghfg</td><td>fsfg|</td></tr></tbody></table></div>'), + 'doubleInsertOrderedList - Exec insertOrderedList twice in all the cells of a table does not change the editable area at all.'); + +test(() => assert_selection( + '<div contenteditable>^<table><tr><td>fsdf</td><td>fsdf</td></tr><tr><td>gghfg</td><td>fsfg</td></tr></table>|</div>', + 'doubleInsertOrderedList', + '<div contenteditable>^<table><tbody><tr><td>fsdf</td><td>fsdf</td></tr><tr><td>gghfg</td><td>fsfg</td></tr></tbody></table>|</div>'), + 'doubleInsertOrderedList - Exec insertOrderedList twice in a table does not change the editable area at all.'); + +</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/editing/data/insert-list-items-in-table-cells.js b/third_party/WebKit/LayoutTests/external/wpt/editing/data/insert-list-items-in-table-cells.js new file mode 100644 index 0000000..e1c1e15c --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/editing/data/insert-list-items-in-table-cells.js
@@ -0,0 +1,43 @@ +// For documentation of the format, see README in this directory. +var browserTests = [ +['<div contenteditable="true"><table><tr><td>[fsdf]</td><td>fsdf</td></tr><tr><td>gghfg</td><td>fsfg</td></tr></table></div>', + [["insertOrderedList",""]], + '<div contenteditable="true"><table><tbody><tr><td><ol><li>fsdf<br></li></ol></td><td>fsdf</td></tr><tr><td>gghfg</td><td>fsfg</td></tr></tbody></table></div>', + [true], + {"insertOrderedList":[false,false,"false",false,true,"true"]}], +['<div contenteditable="true"><table><tr data-start=0 data-end=2><td>fsdf</td><td>fsdf</td></tr><tr><td>gghfg</td><td>fsfg</td></tr></table></div>', + [["insertOrderedList",""]], + '<div contenteditable="true"><table><tbody><tr><td><ol><li>fsdf<br></li></ol></td><td><ol><li>fsdf<br></li></ol></td></tr><tr><td>gghfg</td><td>fsfg</td></tr></tbody></table></div>', + [true], + {"insertOrderedList":[false,false,"false",false,false,"false"]}], +['<div contenteditable="true"><table><tr data-start=0><td>fsdf</td><td>fsdf</td></tr><tr data-end=2><td>gghfg</td><td>fsfg</td></tr></table></div>', + [["insertOrderedList",""]], + '<div contenteditable="true"><table><tbody><tr><td><ol><li>fsdf<br></li></ol></td><td><ol><li>fsdf<br></li></ol></td></tr><tr><td><ol><li>gghfg<br></li></ol></td><td><ol><li>fsfg<br></li></ol></td></tr></tbody></table></div>', + [true], + {"insertOrderedList":[false,false,"false",false,false,"false"]}], +['<div contenteditable="true"><table data-start=0 data-end=1><tr><td>fsdf</td><td>fsdf</td></tr><tr><td>gghfg</td><td>fsfg</td></tr></table></div>', + [["insertOrderedList",""]], + '<div contenteditable="true"><ol><li><table><tbody><tr><td>fsdf</td><td>fsdf</td></tr><tr><td>gghfg</td><td>fsfg</td></tr></tbody></table></li></ol></div>', + [true], + {"insertOrderedList":[false,false,"false",false,true,"true"]}], +['<div contenteditable="true"><table><tr><td>[fsdf]</td><td>fsdf</td></tr><tr><td>gghfg</td><td>fsfg</td></tr></table></div>', + [["insertOrderedList",""], ["insertOrderedList","1"]], + '<div contenteditable="true"><table><tbody><tr><td>fsdf<br></td><td>fsdf</td></tr><tr><td>gghfg</td><td>fsfg</td></tr></tbody></table></div>', + [true, true], + {"insertOrderedList":[false,false,"false",false,true,"true"], "insertOrderedList":[false,false,"false",false,false,"false"]}], +['<div contenteditable="true"><table><tr data-start=0 data-end=2><td>fsdf</td><td>fsdf</td></tr><tr><td>gghfg</td><td>fsfg</td></tr></table></div>', + [["insertOrderedList",""], ["insertOrderedList","1"]], + '<div contenteditable="true"><table><tbody><tr><td>fsdf<br></td><td>fsdf<br></td></tr><tr><td>gghfg</td><td>fsfg</td></tr></tbody></table></div>', + [true, true], + {"insertOrderedList":[false,false,"false",false,true,"true"], "insertOrderedList":[false,false,"false",false,false,"false"]}], +['<div contenteditable="true"><table><tr data-start=0><td>fsdf</td><td>fsdf</td></tr><tr data-end=2><td>gghfg</td><td>fsfg</td></tr></table></div>', + [["insertOrderedList",""], ["insertOrderedList","1"]], + '<div contenteditable="true"><table><tbody><tr><td>fsdf<br></td><td>fsdf<br></td></tr><tr><td>gghfg<br></td><td>fsfg<br></td></tr></tbody></table></div>', + [true, true], + {"insertOrderedList":[false,false,"false",false,true,"true"], "insertOrderedList":[false,false,"false",false,false,"false"]}], +['<div contenteditable="true"><table data-start=0 data-end=1><tr><td>fsdf</td><td>fsdf</td></tr><tr><td>gghfg</td><td>fsfg</td></tr></table></div>', + [["insertOrderedList",""], ["insertOrderedList","1"]], + '<div contenteditable="true"><table><tbody><tr><td>fsdf</td><td>fsdf</td></tr><tr><td>gghfg</td><td>fsfg</td></tr></tbody></table></div>', + [true, true], + {"insertOrderedList":[false,false,"false",false,true,"true"], "insertOrderedList":[false,false,"false",false,false,"false"]}] +]
diff --git a/third_party/WebKit/LayoutTests/external/wpt/editing/run/insert-list-items-in-table-cell.html b/third_party/WebKit/LayoutTests/external/wpt/editing/run/insert-list-items-in-table-cell.html new file mode 100644 index 0000000..ebb14f4 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/editing/run/insert-list-items-in-table-cell.html
@@ -0,0 +1,51 @@ +<!doctype html> +<meta charset=utf-8> +<link rel=stylesheet href=../include/reset.css> +<title>Insert list items in table cells - HTML editing conformance tests</title> + +<p id=timing></p> + +<div id=log></div> + +<div id=test-container></div> + +<script src=../include/implementation.js></script> +<script>var testsJsLibraryOnly = true</script> +<script src=../include/tests.js></script> +<script src=../data/insert-list-items-in-table-cells.js></script> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<script> +"use strict"; + +(function() { + var startTime = Date.now(); + + // Make document.body.innerHTML more tidy by removing unnecessary things. + [].forEach.call(document.querySelectorAll("script"), function(node) { + node.parentNode.removeChild(node); + }); + + if (true) { + // Silly hack: the CSS styling flag should be true, not false, to match + // expected results. This is because every group of tests except the + // last (multitest) sets styleWithCSS automatically, and it sets it + // first to false and then to true. Thus it's left at true at the end + // of each group of tests, so in gentest.html it will be true when + // starting each group of tests other than the first. But browsers are + // supposed to default it to false when the page loads, so flip it. + try { document.execCommand("styleWithCSS", false, "true") } catch(e) {} + } + + browserTests.forEach(runConformanceTest); + + document.getElementById("test-container").parentNode + .removeChild(document.getElementById("test-container")); + + var elapsed = Math.round(Date.now() - startTime)/1000; + document.getElementById("timing").textContent = + "Time elapsed: " + Math.floor(elapsed/60) + ":" + + ((elapsed % 60) < 10 ? "0" : "") + + (elapsed % 60).toFixed(3) + " min."; +})(); +</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/wasm/create_multiple_memory.worker.js b/third_party/WebKit/LayoutTests/external/wpt/wasm/create_multiple_memory.worker.js new file mode 100644 index 0000000..f5733b7 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/wasm/create_multiple_memory.worker.js
@@ -0,0 +1,13 @@ +// 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. + +// The WebAssembly spec doesn't specify a limit on how many Memory objects can +// be allocated. This test makes sure we can have at least two at once. + +importScripts("/resources/testharness.js"); +test(function () { + const mem1 = new WebAssembly.Memory({initial: 1}); + const mem2 = new WebAssembly.Memory({initial: 1}); +}, "WebAssembly#CreateMultipleMemories."); +done();
diff --git a/third_party/WebKit/LayoutTests/http/tests/media/media-source/mediasource-duration.html b/third_party/WebKit/LayoutTests/http/tests/media/media-source/mediasource-duration.html index 45d480d8..9ceb29a 100644 --- a/third_party/WebKit/LayoutTests/http/tests/media/media-source/mediasource-duration.html +++ b/third_party/WebKit/LayoutTests/http/tests/media/media-source/mediasource-duration.html
@@ -176,7 +176,7 @@ // Append all the segments test.expectEvent(sourceBuffer, 'updateend', 'sourceBuffer append completed'); - test.expectEvent(mediaElement, 'playing', 'Playing triggered'); + test.expectEvent(mediaElement, 'loadedmetadata', 'mediaElement loadedmetadata'); sourceBuffer.appendBuffer(mediaData); test.waitForExpectedEvents(function() @@ -190,30 +190,31 @@ // Increase duration. This should result in one 'durationchange' fired. mediaSource.duration = newDuration; - assert_false(sourceBuffer.updating, "sourceBuffer.updating after duration set to newDuration"); + assert_false(sourceBuffer.updating, 'sourceBuffer.updating after duration set to newDuration'); + assert_equals(mediaElement.duration, newDuration, 'mediaElement duration matches newDuration'); // Set duration again to make sure it does not trigger another 'durationchange' event. mediaSource.duration = newDuration; - assert_false(sourceBuffer.updating, "sourceBuffer.updating after duration set again to newDuration"); + assert_false(sourceBuffer.updating, 'sourceBuffer.updating after duration set again to newDuration'); + assert_equals(mediaElement.duration, newDuration, 'mediaElement duration matches newDuration after mediaSource duration set again to newDuration'); // Mark endOfStream so that playback can reach 'ended' at the new duration. test.expectEvent(mediaSource, 'sourceended', 'endOfStream acknowledged'); mediaSource.endOfStream(); - // endOfStream can change duration downwards slightly. - // Allow for one more 'durationchange' event only in this case. - var currentDuration = mediaSource.duration; - if (currentDuration != newDuration) { - assert_true(currentDuration > 0 && currentDuration < newDuration, 'adjusted duration check'); - newDuration = currentDuration; - ++expectedDurationChangeEventCount; - } + // endOfStream should reduce the duration back to fullDuration. + assert_equals(mediaElement.duration, fullDuration, 'mediaElement duration returns to fullDuration after endOfStream()'); + assert_equals(mediaSource.duration, fullDuration, 'mediaSource duration returns to fullDuration after endOfStream()'); + + // Adjust the duration and durationchanged event expectations due to endOfStream()'s duration change. + newDuration = fullDuration; + ++expectedDurationChangeEventCount; }); test.waitForExpectedEvents(function() { - // Allow any remaining queued durationchange to fire, while counting 'durationchange' them. + // Allow any remaining queued durationchange to fire, while counting them. test.step_timeout(test.step_func(function() { mediaElement.removeEventListener('durationchange', durationchangeEventHandler); @@ -221,7 +222,7 @@ test.done(); }), 0); }); - }, 'Test setting same duration multiple times does not fire duplicate durationchange', {timeout: 2500}); + }, 'Test setting same duration multiple times does not fire duplicate durationchange'); mediasource_testafterdataloaded(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData) {
diff --git a/third_party/WebKit/LayoutTests/resize-observer/observe-expected.txt b/third_party/WebKit/LayoutTests/resize-observer/observe-expected.txt deleted file mode 100644 index 15cc717..0000000 --- a/third_party/WebKit/LayoutTests/resize-observer/observe-expected.txt +++ /dev/null
@@ -1,13 +0,0 @@ -CONSOLE ERROR: ResizeObserver loop limit exceeded -This is a testharness.js-based test. -PASS guard -PASS test0: simple observation -PASS test1: multiple observation on same element trigger only one -FAIL test2: throw exception when observing non-element Test bug: need to pass exception to assert_throws() -PASS test3: disconnect stops all notifications -PASS test4: unobserve target stops notifications, unobserve non-observed does nothing -PASS test5: observe img -PASS test6: iframe notifications -PASS test7: callback.this -Harness: the test ran to completion. -
diff --git a/third_party/WebKit/LayoutTests/resize-observer/observe.html b/third_party/WebKit/LayoutTests/resize-observer/observe.html index a34aed8..45ebcd6 100644 --- a/third_party/WebKit/LayoutTests/resize-observer/observe.html +++ b/third_party/WebKit/LayoutTests/resize-observer/observe.html
@@ -56,7 +56,7 @@ function test2() { test(() => { - assert_throws(null, _=> { + assert_throws({name: "TypeError"}, _=> { let ro = new ResizeObserver(() => {}); ro.observe({}); });
diff --git a/third_party/WebKit/Source/bindings/core/v8/V8IntersectionObserverDelegate.cpp b/third_party/WebKit/Source/bindings/core/v8/V8IntersectionObserverDelegate.cpp index f752e4a2..be1f6466 100644 --- a/third_party/WebKit/Source/bindings/core/v8/V8IntersectionObserverDelegate.cpp +++ b/third_party/WebKit/Source/bindings/core/v8/V8IntersectionObserverDelegate.cpp
@@ -17,7 +17,7 @@ V8IntersectionObserverDelegate::V8IntersectionObserverDelegate( IntersectionObserverCallback* callback, ScriptState* script_state) - : callback_(this, callback), script_state_(script_state) {} + : callback_(callback), script_state_(script_state) {} V8IntersectionObserverDelegate::~V8IntersectionObserverDelegate() {}
diff --git a/third_party/WebKit/Source/core/clipboard/DataTransferItem.cpp b/third_party/WebKit/Source/core/clipboard/DataTransferItem.cpp index 24e38bae..566e674 100644 --- a/third_party/WebKit/Source/core/clipboard/DataTransferItem.cpp +++ b/third_party/WebKit/Source/core/clipboard/DataTransferItem.cpp
@@ -76,7 +76,7 @@ if (!callback || item_->Kind() != DataObjectItem::kStringKind) return; - callbacks_.emplace_back(this, callback); + callbacks_.emplace_back(callback); ExecutionContext* context = ExecutionContext::From(script_state); probe::AsyncTaskScheduled(context, "DataTransferItem.getAsString", callback); TaskRunnerHelper::Get(TaskType::kUserInteraction, script_state)
diff --git a/third_party/WebKit/Source/core/css/PropertySetCSSStyleDeclaration.cpp b/third_party/WebKit/Source/core/css/PropertySetCSSStyleDeclaration.cpp index ecd21c4..eb470b9 100644 --- a/third_party/WebKit/Source/core/css/PropertySetCSSStyleDeclaration.cpp +++ b/third_party/WebKit/Source/core/css/PropertySetCSSStyleDeclaration.cpp
@@ -354,7 +354,7 @@ MutableStylePropertySet& property_set_arg, CSSRule* parent_rule) : PropertySetCSSStyleDeclaration(property_set_arg), - parent_rule_(this, parent_rule) {} + parent_rule_(parent_rule) {} StyleRuleCSSStyleDeclaration::~StyleRuleCSSStyleDeclaration() {}
diff --git a/third_party/WebKit/Source/core/dom/Attr.cpp b/third_party/WebKit/Source/core/dom/Attr.cpp index 1745a700..7213b4b 100644 --- a/third_party/WebKit/Source/core/dom/Attr.cpp +++ b/third_party/WebKit/Source/core/dom/Attr.cpp
@@ -38,14 +38,13 @@ Attr::Attr(Element& element, const QualifiedName& name) : Node(&element.GetDocument(), kCreateOther), - element_(this, &element), + element_(&element), name_(name) {} Attr::Attr(Document& document, const QualifiedName& name, const AtomicString& standalone_value) : Node(&document, kCreateOther), - element_(this, nullptr), name_(name), standalone_value_or_attached_local_name_(standalone_value) {}
diff --git a/third_party/WebKit/Source/core/dom/Document.cpp b/third_party/WebKit/Source/core/dom/Document.cpp index 3d1d8c1..6bccac9 100644 --- a/third_party/WebKit/Source/core/dom/Document.cpp +++ b/third_party/WebKit/Source/core/dom/Document.cpp
@@ -515,11 +515,9 @@ // TODO(dcheng): Why does this need both a LocalFrame and LocalDOMWindow // pointer? dom_window_(frame_ ? frame_->DomWindow() : nullptr), - imports_controller_(this, initializer.ImportsController()), - parser_(this, nullptr), + imports_controller_(initializer.ImportsController()), context_features_(ContextFeatures::DefaultSwitch()), well_formed_(false), - implementation_(this, nullptr), printing_(kNotPrinting), paginated_for_screen_(false), compatibility_mode_(kNoQuirksMode), @@ -533,8 +531,6 @@ style_version_(0), listener_types_(0), mutation_observer_types_(0), - style_engine_(this, nullptr), - style_sheet_list_(this, nullptr), visited_link_state_(VisitedLinkState::Create(*this)), visually_ordered_(false), ready_state_(kComplete),
diff --git a/third_party/WebKit/Source/core/dom/ElementShadow.cpp b/third_party/WebKit/Source/core/dom/ElementShadow.cpp index 19e159c4..0a1a744 100644 --- a/third_party/WebKit/Source/core/dom/ElementShadow.cpp +++ b/third_party/WebKit/Source/core/dom/ElementShadow.cpp
@@ -42,10 +42,7 @@ return new ElementShadow(); } -ElementShadow::ElementShadow() - : element_shadow_v0_(this, nullptr), - shadow_root_(this, nullptr), - needs_distribution_recalc_(false) {} +ElementShadow::ElementShadow() : needs_distribution_recalc_(false) {} ShadowRoot& ElementShadow::YoungestShadowRoot() const { ShadowRoot* current = shadow_root_;
diff --git a/third_party/WebKit/Source/core/dom/ModulatorImpl.cpp b/third_party/WebKit/Source/core/dom/ModulatorImpl.cpp index d0bc44b..6b175eb 100644 --- a/third_party/WebKit/Source/core/dom/ModulatorImpl.cpp +++ b/third_party/WebKit/Source/core/dom/ModulatorImpl.cpp
@@ -28,9 +28,9 @@ task_runner_( TaskRunnerHelper::Get(TaskType::kNetworking, script_state_.Get())), fetcher_(fetcher), - map_(this, ModuleMap::Create(this)), + map_(ModuleMap::Create(this)), loader_registry_(ModuleScriptLoaderRegistry::Create()), - tree_linker_registry_(this, ModuleTreeLinkerRegistry::Create()), + tree_linker_registry_(ModuleTreeLinkerRegistry::Create()), script_module_resolver_(ScriptModuleResolverImpl::Create( this, ExecutionContext::From(script_state_.Get()))) {
diff --git a/third_party/WebKit/Source/core/dom/ModuleMap.cpp b/third_party/WebKit/Source/core/dom/ModuleMap.cpp index f5e15a51..6e7b31e 100644 --- a/third_party/WebKit/Source/core/dom/ModuleMap.cpp +++ b/third_party/WebKit/Source/core/dom/ModuleMap.cpp
@@ -49,8 +49,7 @@ HeapHashSet<Member<SingleModuleClient>> clients_; }; -ModuleMap::Entry::Entry(ModuleMap* map) - : module_script_(this, nullptr), map_(map) { +ModuleMap::Entry::Entry(ModuleMap* map) : map_(map) { DCHECK(map_); } @@ -124,11 +123,10 @@ // Step 2. If moduleMap[url] is "fetching", wait in parallel until that // entry's value changes, then queue a task on the networking task source to // proceed with running the following steps. - MapImpl::AddResult result = - map_.insert(request.Url(), TraceWrapperMember<Entry>(this, nullptr)); + MapImpl::AddResult result = map_.insert(request.Url(), nullptr); TraceWrapperMember<Entry>& entry = result.stored_value->value; if (result.is_new_entry) { - entry = TraceWrapperMember<Entry>(this, Entry::Create(this)); + entry = Entry::Create(this); // Steps 4-9 loads a new single module script. // Delegates to ModuleScriptLoader via Modulator.
diff --git a/third_party/WebKit/Source/core/dom/ModulePendingScript.cpp b/third_party/WebKit/Source/core/dom/ModulePendingScript.cpp index 7367ae6..0a8e452 100644 --- a/third_party/WebKit/Source/core/dom/ModulePendingScript.cpp +++ b/third_party/WebKit/Source/core/dom/ModulePendingScript.cpp
@@ -9,8 +9,7 @@ namespace blink { -ModulePendingScriptTreeClient::ModulePendingScriptTreeClient() - : module_script_(this, nullptr), pending_script_(this, nullptr) {} +ModulePendingScriptTreeClient::ModulePendingScriptTreeClient() {} void ModulePendingScriptTreeClient::SetPendingScript( ModulePendingScript* pending_script) { @@ -53,7 +52,7 @@ ModulePendingScriptTreeClient* client, bool is_external) : PendingScript(element, TextPosition()), - module_tree_client_(this, client), + module_tree_client_(client), is_external_(is_external) { CHECK(this->GetElement()); DCHECK(module_tree_client_);
diff --git a/third_party/WebKit/Source/core/dom/MutationObserver.cpp b/third_party/WebKit/Source/core/dom/MutationObserver.cpp index d37ea672..05e76dc 100644 --- a/third_party/WebKit/Source/core/dom/MutationObserver.cpp +++ b/third_party/WebKit/Source/core/dom/MutationObserver.cpp
@@ -82,7 +82,7 @@ private: V8DelegateImpl(MutationCallback* callback, ExecutionContext* execution_context) - : ContextClient(execution_context), callback_(this, callback) {} + : ContextClient(execution_context), callback_(callback) {} TraceWrapperMember<MutationCallback> callback_; }; @@ -112,7 +112,7 @@ MutationObserver::MutationObserver(ExecutionContext* execution_context, Delegate* delegate) : ContextClient(execution_context), - delegate_(this, delegate), + delegate_(delegate), priority_(g_observer_priority++) {} MutationObserver::~MutationObserver() { @@ -271,7 +271,7 @@ void MutationObserver::EnqueueMutationRecord(MutationRecord* mutation) { DCHECK(IsMainThread()); - records_.push_back(TraceWrapperMember<MutationRecord>(this, mutation)); + records_.push_back(mutation); ActivateObserver(this); probe::AsyncTaskScheduled(delegate_->GetExecutionContext(), mutation->type(), mutation);
diff --git a/third_party/WebKit/Source/core/dom/MutationObserverRegistration.cpp b/third_party/WebKit/Source/core/dom/MutationObserverRegistration.cpp index c2c568a..90441a5 100644 --- a/third_party/WebKit/Source/core/dom/MutationObserverRegistration.cpp +++ b/third_party/WebKit/Source/core/dom/MutationObserverRegistration.cpp
@@ -49,7 +49,7 @@ Node* registration_node, MutationObserverOptions options, const HashSet<AtomicString>& attribute_filter) - : observer_(this, &observer), + : observer_(&observer), registration_node_(registration_node), options_(options), attribute_filter_(attribute_filter) {
diff --git a/third_party/WebKit/Source/core/dom/MutationRecord.cpp b/third_party/WebKit/Source/core/dom/MutationRecord.cpp index f252deb..e4efd5e 100644 --- a/third_party/WebKit/Source/core/dom/MutationRecord.cpp +++ b/third_party/WebKit/Source/core/dom/MutationRecord.cpp
@@ -47,9 +47,9 @@ StaticNodeList* removed, Node* previous_sibling, Node* next_sibling) - : target_(this, target), - added_nodes_(this, added), - removed_nodes_(this, removed), + : target_(target), + added_nodes_(added), + removed_nodes_(removed), previous_sibling_(previous_sibling), next_sibling_(next_sibling) {} @@ -87,10 +87,7 @@ class RecordWithEmptyNodeLists : public MutationRecord { public: RecordWithEmptyNodeLists(Node* target, const String& old_value) - : target_(this, target), - old_value_(old_value), - added_nodes_(this, nullptr), - removed_nodes_(this, nullptr) {} + : target_(target), old_value_(old_value) {} DEFINE_INLINE_VIRTUAL_TRACE() { visitor->Trace(target_); @@ -160,8 +157,7 @@ class MutationRecordWithNullOldValue : public MutationRecord { public: - MutationRecordWithNullOldValue(MutationRecord* record) - : record_(this, record) {} + MutationRecordWithNullOldValue(MutationRecord* record) : record_(record) {} DEFINE_INLINE_VIRTUAL_TRACE() { visitor->Trace(record_);
diff --git a/third_party/WebKit/Source/core/dom/NodeIterator.cpp b/third_party/WebKit/Source/core/dom/NodeIterator.cpp index f74a75bd..f6f1a26 100644 --- a/third_party/WebKit/Source/core/dom/NodeIterator.cpp +++ b/third_party/WebKit/Source/core/dom/NodeIterator.cpp
@@ -65,7 +65,7 @@ NodeIterator::NodeIterator(Node* root_node, unsigned what_to_show, V8NodeFilterCondition* filter) - : NodeIteratorBase(this, root_node, what_to_show, filter), + : NodeIteratorBase(root_node, what_to_show, filter), reference_node_(root(), true) { // If NodeIterator target is Attr node, don't subscribe for nodeWillBeRemoved, // as it would never have child nodes.
diff --git a/third_party/WebKit/Source/core/dom/NodeIteratorBase.cpp b/third_party/WebKit/Source/core/dom/NodeIteratorBase.cpp index b2c338cd..3af3aa6 100644 --- a/third_party/WebKit/Source/core/dom/NodeIteratorBase.cpp +++ b/third_party/WebKit/Source/core/dom/NodeIteratorBase.cpp
@@ -31,13 +31,10 @@ namespace blink { -NodeIteratorBase::NodeIteratorBase(void* child_this, - Node* root_node, +NodeIteratorBase::NodeIteratorBase(Node* root_node, unsigned what_to_show, V8NodeFilterCondition* node_filter) - : root_(root_node), - what_to_show_(what_to_show), - filter_(child_this, node_filter) {} + : root_(root_node), what_to_show_(what_to_show), filter_(node_filter) {} unsigned NodeIteratorBase::AcceptNode(Node* node, ExceptionState& exception_state) const {
diff --git a/third_party/WebKit/Source/core/dom/NodeIteratorBase.h b/third_party/WebKit/Source/core/dom/NodeIteratorBase.h index 6d9c8ae..e21d76c5 100644 --- a/third_party/WebKit/Source/core/dom/NodeIteratorBase.h +++ b/third_party/WebKit/Source/core/dom/NodeIteratorBase.h
@@ -44,13 +44,7 @@ DECLARE_VIRTUAL_TRACE_WRAPPERS(); protected: - // In order to properly trace wrappers it is necessary for TraceWrapperMember - // to find the object header from within the mixin. |childThis| is safe to - // find the header so we pass it instead of |this|. - NodeIteratorBase(void* child_this, - Node*, - unsigned what_to_show, - V8NodeFilterCondition*); + NodeIteratorBase(Node*, unsigned what_to_show, V8NodeFilterCondition*); unsigned AcceptNode(Node*, ExceptionState&) const; private:
diff --git a/third_party/WebKit/Source/core/dom/NodeRareData.h b/third_party/WebKit/Source/core/dom/NodeRareData.h index 1b2fc5b..6e40e4d 100644 --- a/third_party/WebKit/Source/core/dom/NodeRareData.h +++ b/third_party/WebKit/Source/core/dom/NodeRareData.h
@@ -50,8 +50,7 @@ } void AddTransientRegistration(MutationObserverRegistration* registration) { - transient_registry_.insert( - TraceWrapperMember<MutationObserverRegistration>(this, registration)); + transient_registry_.insert(registration); } void RemoveTransientRegistration(MutationObserverRegistration* registration) { @@ -60,8 +59,7 @@ } void AddRegistration(MutationObserverRegistration* registration) { - registry_.push_back( - TraceWrapperMember<MutationObserverRegistration>(this, registration)); + registry_.push_back(registration); } void RemoveRegistration(MutationObserverRegistration* registration) {
diff --git a/third_party/WebKit/Source/core/dom/ScriptLoader.cpp b/third_party/WebKit/Source/core/dom/ScriptLoader.cpp index b75fac94..aeb386a 100644 --- a/third_party/WebKit/Source/core/dom/ScriptLoader.cpp +++ b/third_party/WebKit/Source/core/dom/ScriptLoader.cpp
@@ -78,9 +78,7 @@ created_during_document_write_(created_during_document_write), async_exec_type_(ScriptRunner::kNone), document_write_intervention_( - DocumentWriteIntervention::kDocumentWriteInterventionNone), - pending_script_(this, nullptr), - module_tree_client_(this, nullptr) { + DocumentWriteIntervention::kDocumentWriteInterventionNone) { // https://html.spec.whatwg.org/#already-started // "The cloning steps for script elements must set the "already started" // flag on the copy if it is set on the element being cloned."
diff --git a/third_party/WebKit/Source/core/dom/StyleEngine.cpp b/third_party/WebKit/Source/core/dom/StyleEngine.cpp index 7d8c869..e26e46d 100644 --- a/third_party/WebKit/Source/core/dom/StyleEngine.cpp +++ b/third_party/WebKit/Source/core/dom/StyleEngine.cpp
@@ -68,7 +68,6 @@ is_master_(!document.ImportsController() || document.ImportsController()->Master() == &document), document_style_sheet_collection_( - this, DocumentStyleSheetCollection::Create(document)) { if (document.GetFrame()) { // We don't need to create CSSFontSelector for imported document or @@ -141,10 +140,9 @@ WebStyleSheetId StyleEngine::InjectAuthorSheet( StyleSheetContents* author_sheet) { - injected_author_style_sheets_.push_back(std::make_pair( - ++injected_author_sheets_id_count_, - TraceWrapperMember<CSSStyleSheet>( - this, CSSStyleSheet::Create(author_sheet, *document_)))); + injected_author_style_sheets_.push_back( + std::make_pair(++injected_author_sheets_id_count_, + CSSStyleSheet::Create(author_sheet, *document_))); MarkDocumentDirty(); return injected_author_sheets_id_count_;
diff --git a/third_party/WebKit/Source/core/dom/StyleSheetCollection.cpp b/third_party/WebKit/Source/core/dom/StyleSheetCollection.cpp index 9e92312c..f1fa1cf 100644 --- a/third_party/WebKit/Source/core/dom/StyleSheetCollection.cpp +++ b/third_party/WebKit/Source/core/dom/StyleSheetCollection.cpp
@@ -59,8 +59,7 @@ } void StyleSheetCollection::AppendSheetForList(StyleSheet* sheet) { - style_sheets_for_style_sheet_list_.push_back( - TraceWrapperMember<StyleSheet>(this, sheet)); + style_sheets_for_style_sheet_list_.push_back(sheet); } DEFINE_TRACE(StyleSheetCollection) {
diff --git a/third_party/WebKit/Source/core/dom/TreeWalker.cpp b/third_party/WebKit/Source/core/dom/TreeWalker.cpp index 94e21fb10..c8248d7 100644 --- a/third_party/WebKit/Source/core/dom/TreeWalker.cpp +++ b/third_party/WebKit/Source/core/dom/TreeWalker.cpp
@@ -35,8 +35,7 @@ TreeWalker::TreeWalker(Node* root_node, unsigned what_to_show, V8NodeFilterCondition* filter) - : NodeIteratorBase(this, root_node, what_to_show, filter), - current_(root()) {} + : NodeIteratorBase(root_node, what_to_show, filter), current_(root()) {} void TreeWalker::setCurrentNode(Node* node) { DCHECK(node);
diff --git a/third_party/WebKit/Source/core/editing/commands/CompositeEditCommand.cpp b/third_party/WebKit/Source/core/editing/commands/CompositeEditCommand.cpp index 234f802e..62a98b3 100644 --- a/third_party/WebKit/Source/core/editing/commands/CompositeEditCommand.cpp +++ b/third_party/WebKit/Source/core/editing/commands/CompositeEditCommand.cpp
@@ -1499,7 +1499,8 @@ VisiblePosition after_paragraph = CreateVisiblePosition(after_paragraph_position.GetPosition()); if (before_paragraph.IsNotNull() && - (!IsEndOfParagraph(before_paragraph) || + ((!IsStartOfParagraph(before_paragraph) && + !IsEndOfParagraph(before_paragraph)) || before_paragraph.DeepEquivalent() == after_paragraph.DeepEquivalent())) { // FIXME: Trim text between beforeParagraph and afterParagraph if they // aren't equal.
diff --git a/third_party/WebKit/Source/core/editing/markers/ActiveSuggestionMarkerListImpl.cpp b/third_party/WebKit/Source/core/editing/markers/ActiveSuggestionMarkerListImpl.cpp index 0cc267c..be35da3 100644 --- a/third_party/WebKit/Source/core/editing/markers/ActiveSuggestionMarkerListImpl.cpp +++ b/third_party/WebKit/Source/core/editing/markers/ActiveSuggestionMarkerListImpl.cpp
@@ -57,7 +57,8 @@ length); } -bool ActiveSuggestionMarkerListImpl::ShiftMarkers(unsigned offset, +bool ActiveSuggestionMarkerListImpl::ShiftMarkers(const String&, + unsigned offset, unsigned old_length, unsigned new_length) { return DocumentMarkerListEditor::ShiftMarkersContentIndependent(
diff --git a/third_party/WebKit/Source/core/editing/markers/ActiveSuggestionMarkerListImpl.h b/third_party/WebKit/Source/core/editing/markers/ActiveSuggestionMarkerListImpl.h index f36d21c..2711706 100644 --- a/third_party/WebKit/Source/core/editing/markers/ActiveSuggestionMarkerListImpl.h +++ b/third_party/WebKit/Source/core/editing/markers/ActiveSuggestionMarkerListImpl.h
@@ -37,7 +37,8 @@ bool MoveMarkers(int length, DocumentMarkerList* dst_list) final; bool RemoveMarkers(unsigned start_offset, int length) final; - bool ShiftMarkers(unsigned offset, + bool ShiftMarkers(const String& node_text, + unsigned offset, unsigned old_length, unsigned new_length) final;
diff --git a/third_party/WebKit/Source/core/editing/markers/CompositionMarkerListImpl.cpp b/third_party/WebKit/Source/core/editing/markers/CompositionMarkerListImpl.cpp index 75dcf99..b709959 100644 --- a/third_party/WebKit/Source/core/editing/markers/CompositionMarkerListImpl.cpp +++ b/third_party/WebKit/Source/core/editing/markers/CompositionMarkerListImpl.cpp
@@ -55,7 +55,8 @@ length); } -bool CompositionMarkerListImpl::ShiftMarkers(unsigned offset, +bool CompositionMarkerListImpl::ShiftMarkers(const String&, + unsigned offset, unsigned old_length, unsigned new_length) { return DocumentMarkerListEditor::ShiftMarkersContentIndependent(
diff --git a/third_party/WebKit/Source/core/editing/markers/CompositionMarkerListImpl.h b/third_party/WebKit/Source/core/editing/markers/CompositionMarkerListImpl.h index dfa4ea8..2c057d4 100644 --- a/third_party/WebKit/Source/core/editing/markers/CompositionMarkerListImpl.h +++ b/third_party/WebKit/Source/core/editing/markers/CompositionMarkerListImpl.h
@@ -36,7 +36,8 @@ bool MoveMarkers(int length, DocumentMarkerList* dst_list) final; bool RemoveMarkers(unsigned start_offset, int length) final; - bool ShiftMarkers(unsigned offset, + bool ShiftMarkers(const String& node_text, + unsigned offset, unsigned old_length, unsigned new_length) final;
diff --git a/third_party/WebKit/Source/core/editing/markers/DocumentMarkerController.cpp b/third_party/WebKit/Source/core/editing/markers/DocumentMarkerController.cpp index 97bc652..fb78832 100644 --- a/third_party/WebKit/Source/core/editing/markers/DocumentMarkerController.cpp +++ b/third_party/WebKit/Source/core/editing/markers/DocumentMarkerController.cpp
@@ -789,7 +789,7 @@ if (!list) continue; - if (list->ShiftMarkers(offset, old_length, new_length)) + if (list->ShiftMarkers(node->data(), offset, old_length, new_length)) did_shift_marker = true; }
diff --git a/third_party/WebKit/Source/core/editing/markers/DocumentMarkerList.h b/third_party/WebKit/Source/core/editing/markers/DocumentMarkerList.h index 2387105e..960fcf2e 100644 --- a/third_party/WebKit/Source/core/editing/markers/DocumentMarkerList.h +++ b/third_party/WebKit/Source/core/editing/markers/DocumentMarkerList.h
@@ -51,8 +51,13 @@ // Returns true if at least one marker is removed, false otherwise virtual bool RemoveMarkers(unsigned start_offset, int length) = 0; - // Returns true if at least one marker is shifted or removed, false otherwise - virtual bool ShiftMarkers(unsigned offset, + // Returns true if at least one marker is shifted or removed, false otherwise. + // Called in response to an edit replacing the range + // [offset, offset + old_length] by a string of length new_length. + // node_text is the full text of the affected node *after* the edit is + // applied. + virtual bool ShiftMarkers(const String& node_text, + unsigned offset, unsigned old_length, unsigned new_length) = 0;
diff --git a/third_party/WebKit/Source/core/editing/markers/SpellCheckMarkerListImpl.cpp b/third_party/WebKit/Source/core/editing/markers/SpellCheckMarkerListImpl.cpp index ca97ecf..df924c1 100644 --- a/third_party/WebKit/Source/core/editing/markers/SpellCheckMarkerListImpl.cpp +++ b/third_party/WebKit/Source/core/editing/markers/SpellCheckMarkerListImpl.cpp
@@ -91,7 +91,8 @@ length); } -bool SpellCheckMarkerListImpl::ShiftMarkers(unsigned offset, +bool SpellCheckMarkerListImpl::ShiftMarkers(const String&, + unsigned offset, unsigned old_length, unsigned new_length) { return DocumentMarkerListEditor::ShiftMarkersContentDependent(
diff --git a/third_party/WebKit/Source/core/editing/markers/SpellCheckMarkerListImpl.h b/third_party/WebKit/Source/core/editing/markers/SpellCheckMarkerListImpl.h index d56d868a8..c7beb9b 100644 --- a/third_party/WebKit/Source/core/editing/markers/SpellCheckMarkerListImpl.h +++ b/third_party/WebKit/Source/core/editing/markers/SpellCheckMarkerListImpl.h
@@ -31,7 +31,8 @@ bool MoveMarkers(int length, DocumentMarkerList* dst_list) final; bool RemoveMarkers(unsigned start_offset, int length) final; - bool ShiftMarkers(unsigned offset, + bool ShiftMarkers(const String& node_text, + unsigned offset, unsigned old_length, unsigned new_length) final;
diff --git a/third_party/WebKit/Source/core/editing/markers/SuggestionMarkerListImpl.cpp b/third_party/WebKit/Source/core/editing/markers/SuggestionMarkerListImpl.cpp index cd7f3119..a73cb341 100644 --- a/third_party/WebKit/Source/core/editing/markers/SuggestionMarkerListImpl.cpp +++ b/third_party/WebKit/Source/core/editing/markers/SuggestionMarkerListImpl.cpp
@@ -107,7 +107,8 @@ return did_remove_marker; } -bool SuggestionMarkerListImpl::ShiftMarkers(unsigned offset, +bool SuggestionMarkerListImpl::ShiftMarkers(const String&, + unsigned offset, unsigned old_length, unsigned new_length) { // Since suggestion markers are stored unsorted, the quickest way to perform
diff --git a/third_party/WebKit/Source/core/editing/markers/SuggestionMarkerListImpl.h b/third_party/WebKit/Source/core/editing/markers/SuggestionMarkerListImpl.h index 0149e64..29d0e73 100644 --- a/third_party/WebKit/Source/core/editing/markers/SuggestionMarkerListImpl.h +++ b/third_party/WebKit/Source/core/editing/markers/SuggestionMarkerListImpl.h
@@ -35,7 +35,8 @@ bool MoveMarkers(int length, DocumentMarkerList* dst_list) final; bool RemoveMarkers(unsigned start_offset, int length) final; - bool ShiftMarkers(unsigned offset, + bool ShiftMarkers(const String& node_text, + unsigned offset, unsigned old_length, unsigned new_length) final;
diff --git a/third_party/WebKit/Source/core/editing/markers/SuggestionMarkerListImplTest.cpp b/third_party/WebKit/Source/core/editing/markers/SuggestionMarkerListImplTest.cpp index 8fa41f6..212b46d78 100644 --- a/third_party/WebKit/Source/core/editing/markers/SuggestionMarkerListImplTest.cpp +++ b/third_party/WebKit/Source/core/editing/markers/SuggestionMarkerListImplTest.cpp
@@ -261,7 +261,7 @@ marker_list_->Add(CreateMarker(0, 10)); marker_list_->Add(CreateMarker(20, 30)); - EXPECT_TRUE(marker_list_->ShiftMarkers(15, 20, 0)); + EXPECT_TRUE(marker_list_->ShiftMarkers("", 15, 20, 0)); DocumentMarkerVector markers = marker_list_->GetMarkers(); std::sort(markers.begin(), markers.end(), compare_markers);
diff --git a/third_party/WebKit/Source/core/editing/markers/TextMatchMarkerListImpl.cpp b/third_party/WebKit/Source/core/editing/markers/TextMatchMarkerListImpl.cpp index 4adeb5f..1db3b60a 100644 --- a/third_party/WebKit/Source/core/editing/markers/TextMatchMarkerListImpl.cpp +++ b/third_party/WebKit/Source/core/editing/markers/TextMatchMarkerListImpl.cpp
@@ -59,7 +59,8 @@ length); } -bool TextMatchMarkerListImpl::ShiftMarkers(unsigned offset, +bool TextMatchMarkerListImpl::ShiftMarkers(const String&, + unsigned offset, unsigned old_length, unsigned new_length) { return DocumentMarkerListEditor::ShiftMarkersContentDependent(
diff --git a/third_party/WebKit/Source/core/editing/markers/TextMatchMarkerListImpl.h b/third_party/WebKit/Source/core/editing/markers/TextMatchMarkerListImpl.h index 084052c..4a953f6 100644 --- a/third_party/WebKit/Source/core/editing/markers/TextMatchMarkerListImpl.h +++ b/third_party/WebKit/Source/core/editing/markers/TextMatchMarkerListImpl.h
@@ -35,7 +35,8 @@ bool MoveMarkers(int length, DocumentMarkerList* dst_list) final; bool RemoveMarkers(unsigned start_offset, int length) final; - bool ShiftMarkers(unsigned offset, + bool ShiftMarkers(const String& node_text, + unsigned offset, unsigned old_length, unsigned new_length) final; DECLARE_VIRTUAL_TRACE();
diff --git a/third_party/WebKit/Source/core/exported/WebPluginContainerImpl.cpp b/third_party/WebKit/Source/core/exported/WebPluginContainerImpl.cpp index e79abb2..2df5552c 100644 --- a/third_party/WebKit/Source/core/exported/WebPluginContainerImpl.cpp +++ b/third_party/WebKit/Source/core/exported/WebPluginContainerImpl.cpp
@@ -401,6 +401,11 @@ return web_plugin_->ExecuteEditCommand(name, value); } +bool WebPluginContainerImpl::SupportsCommand(const WebString& name) { + return name == "Copy" || name == "Cut" || name == "Paste" || + name == "PasteAndMatchStyle"; +} + WebElement WebPluginContainerImpl::GetElement() { return WebElement(element_); }
diff --git a/third_party/WebKit/Source/core/exported/WebPluginContainerImpl.h b/third_party/WebKit/Source/core/exported/WebPluginContainerImpl.h index 7508e1a0..4e517327 100644 --- a/third_party/WebKit/Source/core/exported/WebPluginContainerImpl.h +++ b/third_party/WebKit/Source/core/exported/WebPluginContainerImpl.h
@@ -74,6 +74,9 @@ WebPlugin* web_plugin) { return new WebPluginContainerImpl(element, web_plugin); } + // Check if plugins support a given command |name|. + static bool SupportsCommand(const WebString& name); + ~WebPluginContainerImpl() override; // PluginView methods
diff --git a/third_party/WebKit/Source/core/exported/WebPluginContainerTest.cpp b/third_party/WebKit/Source/core/exported/WebPluginContainerTest.cpp index 49169c9..5ba0f825 100644 --- a/third_party/WebKit/Source/core/exported/WebPluginContainerTest.cpp +++ b/third_party/WebKit/Source/core/exported/WebPluginContainerTest.cpp
@@ -147,6 +147,9 @@ bool HasSelection() const override { return true; } bool CanEditText() const override { return true; } + bool ExecuteEditCommand(const WebString& name) { + return ExecuteEditCommand(name, WebString()); + } bool ExecuteEditCommand(const WebString& name, const WebString& value) override { if (name == "Cut") { @@ -657,6 +660,87 @@ EXPECT_TRUE(test_plugin->IsPasteCalled()); } +TEST_F(WebPluginContainerTest, CutFromContextMenu) { + RegisterMockedURL("plugin_container.html"); + // Must outlive |web_view_helper|. + TestPluginWebFrameClient plugin_web_frame_client; + FrameTestHelpers::WebViewHelper web_view_helper; + + // Use TestPluginWithEditableText for testing "Cut". + plugin_web_frame_client.SetHasEditableText(true); + + WebViewImpl* web_view = web_view_helper.InitializeAndLoad( + base_url_ + "plugin_container.html", &plugin_web_frame_client); + EnablePlugins(web_view, WebSize(300, 300)); + + WebElement plugin_container_one_element = + web_view->MainFrameImpl()->GetDocument().GetElementById( + WebString::FromUTF8("translated-plugin")); + + WebPlugin* plugin = + ToWebPluginContainerImpl(plugin_container_one_element.PluginContainer()) + ->Plugin(); + TestPluginWithEditableText* test_plugin = + static_cast<TestPluginWithEditableText*>(plugin); + + ExecuteContextMenuCommand(web_view, "Cut"); + EXPECT_TRUE(test_plugin->IsCutCalled()); +} + +TEST_F(WebPluginContainerTest, PasteFromContextMenu) { + RegisterMockedURL("plugin_container.html"); + // Must outlive |web_view_helper|. + TestPluginWebFrameClient plugin_web_frame_client; + FrameTestHelpers::WebViewHelper web_view_helper; + + // Use TestPluginWithEditableText for testing "Paste". + plugin_web_frame_client.SetHasEditableText(true); + + WebViewImpl* web_view = web_view_helper.InitializeAndLoad( + base_url_ + "plugin_container.html", &plugin_web_frame_client); + EnablePlugins(web_view, WebSize(300, 300)); + + WebElement plugin_container_one_element = + web_view->MainFrameImpl()->GetDocument().GetElementById( + WebString::FromUTF8("translated-plugin")); + + WebPlugin* plugin = + ToWebPluginContainerImpl(plugin_container_one_element.PluginContainer()) + ->Plugin(); + TestPluginWithEditableText* test_plugin = + static_cast<TestPluginWithEditableText*>(plugin); + + ExecuteContextMenuCommand(web_view, "Paste"); + EXPECT_TRUE(test_plugin->IsPasteCalled()); +} + +TEST_F(WebPluginContainerTest, PasteAndMatchStyleFromContextMenu) { + RegisterMockedURL("plugin_container.html"); + // Must outlive |web_view_helper|. + TestPluginWebFrameClient plugin_web_frame_client; + FrameTestHelpers::WebViewHelper web_view_helper; + + // Use TestPluginWithEditableText for testing "Paste". + plugin_web_frame_client.SetHasEditableText(true); + + WebViewImpl* web_view = web_view_helper.InitializeAndLoad( + base_url_ + "plugin_container.html", &plugin_web_frame_client); + EnablePlugins(web_view, WebSize(300, 300)); + + WebElement plugin_container_one_element = + web_view->MainFrameImpl()->GetDocument().GetElementById( + WebString::FromUTF8("translated-plugin")); + + WebPlugin* plugin = + ToWebPluginContainerImpl(plugin_container_one_element.PluginContainer()) + ->Plugin(); + TestPluginWithEditableText* test_plugin = + static_cast<TestPluginWithEditableText*>(plugin); + + ExecuteContextMenuCommand(web_view, "PasteAndMatchStyle"); + EXPECT_TRUE(test_plugin->IsPasteCalled()); +} + // A class to facilitate testing that events are correctly received by plugins. class EventTestPlugin : public FakeWebPlugin { public:
diff --git a/third_party/WebKit/Source/core/exported/WebViewImpl.cpp b/third_party/WebKit/Source/core/exported/WebViewImpl.cpp index 5c52e7a..41353c58 100644 --- a/third_party/WebKit/Source/core/exported/WebViewImpl.cpp +++ b/third_party/WebKit/Source/core/exported/WebViewImpl.cpp
@@ -1187,7 +1187,7 @@ if ((is_unmodified_menu_key && event.GetType() == kContextMenuKeyTriggeringEventType) || (is_shift_f10 && event.GetType() == kShiftF10TriggeringEventType)) { - SendContextMenuEvent(event); + SendContextMenuEvent(); return WebInputEventResult::kHandledSystem; } #endif // !defined(OS_MACOSX) @@ -1616,8 +1616,7 @@ #if !defined(OS_MACOSX) // Mac has no way to open a context menu based on a keyboard event. -WebInputEventResult WebViewImpl::SendContextMenuEvent( - const WebKeyboardEvent& event) { +WebInputEventResult WebViewImpl::SendContextMenuEvent() { // The contextMenuController() holds onto the last context menu that was // popped up on the page until a new one is created. We need to clear // this menu before propagating the event through the DOM so that we can @@ -1642,8 +1641,7 @@ } } #else -WebInputEventResult WebViewImpl::SendContextMenuEvent( - const WebKeyboardEvent& event) { +WebInputEventResult WebViewImpl::SendContextMenuEvent() { return WebInputEventResult::kNotHandled; } #endif
diff --git a/third_party/WebKit/Source/core/exported/WebViewImpl.h b/third_party/WebKit/Source/core/exported/WebViewImpl.h index e9f8485..dde3c42 100644 --- a/third_party/WebKit/Source/core/exported/WebViewImpl.h +++ b/third_party/WebKit/Source/core/exported/WebViewImpl.h
@@ -325,7 +325,7 @@ // wParam, LPARAM lParam) in webkit\webkit\win\WebView.cpp. The only // significant change in this function is the code to convert from a // Keyboard event to the Right Mouse button down event. - WebInputEventResult SendContextMenuEvent(const WebKeyboardEvent&); + WebInputEventResult SendContextMenuEvent(); void ShowContextMenuAtPoint(float x, float y, ContextMenuProvider*);
diff --git a/third_party/WebKit/Source/core/frame/DOMWindow.cpp b/third_party/WebKit/Source/core/frame/DOMWindow.cpp index 5a43c8c..84dd3c7 100644 --- a/third_party/WebKit/Source/core/frame/DOMWindow.cpp +++ b/third_party/WebKit/Source/core/frame/DOMWindow.cpp
@@ -35,7 +35,6 @@ DOMWindow::DOMWindow(Frame& frame) : frame_(frame), window_proxy_manager_(frame.GetWindowProxyManager()), - location_(this, nullptr), window_is_closing_(false) {} DOMWindow::~DOMWindow() {
diff --git a/third_party/WebKit/Source/core/frame/LocalDOMWindow.cpp b/third_party/WebKit/Source/core/frame/LocalDOMWindow.cpp index f61635b..ee7e241 100644 --- a/third_party/WebKit/Source/core/frame/LocalDOMWindow.cpp +++ b/third_party/WebKit/Source/core/frame/LocalDOMWindow.cpp
@@ -249,15 +249,12 @@ LocalDOMWindow::LocalDOMWindow(LocalFrame& frame) : DOMWindow(frame), - document_(this, nullptr), visualViewport_(DOMVisualViewport::Create(this)), unused_preloads_timer_( TaskRunnerHelper::Get(TaskType::kUnspecedTimer, &frame), this, &LocalDOMWindow::WarnUnusedPreloads), - should_print_when_finished_loading_(false), - custom_elements_(this, nullptr), - modulator_(this, nullptr) {} + should_print_when_finished_loading_(false) {} void LocalDOMWindow::ClearDocument() { if (!document_)
diff --git a/third_party/WebKit/Source/core/frame/WebFrameWidgetImpl.cpp b/third_party/WebKit/Source/core/frame/WebFrameWidgetImpl.cpp index 88b3c20..eab267d 100644 --- a/third_party/WebKit/Source/core/frame/WebFrameWidgetImpl.cpp +++ b/third_party/WebKit/Source/core/frame/WebFrameWidgetImpl.cpp
@@ -987,7 +987,7 @@ if ((is_unmodified_menu_key && event.GetType() == kContextMenuKeyTriggeringEventType) || (is_shift_f10 && event.GetType() == kShiftF10TriggeringEventType)) { - View()->SendContextMenuEvent(event); + View()->SendContextMenuEvent(); return WebInputEventResult::kHandledSystem; } #endif // !defined(OS_MACOSX)
diff --git a/third_party/WebKit/Source/core/frame/WebLocalFrameImpl.cpp b/third_party/WebKit/Source/core/frame/WebLocalFrameImpl.cpp index 7ddba14..e652c8c5 100644 --- a/third_party/WebKit/Source/core/frame/WebLocalFrameImpl.cpp +++ b/third_party/WebKit/Source/core/frame/WebLocalFrameImpl.cpp
@@ -1033,7 +1033,10 @@ command = command.Substring(0, command.length() - 1); Node* plugin_lookup_context_node = - context_menu_node_ && name == "Copy" ? context_menu_node_ : nullptr; + context_menu_node_ && WebPluginContainerImpl::SupportsCommand(name) + ? context_menu_node_ + : nullptr; + WebPluginContainerImpl* plugin_container = GetFrame()->GetWebPluginContainer(plugin_lookup_context_node); if (plugin_container && plugin_container->ExecuteEditCommand(name))
diff --git a/third_party/WebKit/Source/core/html/HTMLCanvasElement.cpp b/third_party/WebKit/Source/core/html/HTMLCanvasElement.cpp index 0af7065..ab5533e 100644 --- a/third_party/WebKit/Source/core/html/HTMLCanvasElement.cpp +++ b/third_party/WebKit/Source/core/html/HTMLCanvasElement.cpp
@@ -136,7 +136,6 @@ ContextLifecycleObserver(&document), PageVisibilityObserver(document.GetPage()), size_(kDefaultWidth, kDefaultHeight), - context_(this, nullptr), ignore_reset_(false), externally_allocated_memory_(0), origin_clean_(true),
diff --git a/third_party/WebKit/Source/core/html/HTMLLinkElement.cpp b/third_party/WebKit/Source/core/html/HTMLLinkElement.cpp index 058fa55..3e5451d 100644 --- a/third_party/WebKit/Source/core/html/HTMLLinkElement.cpp +++ b/third_party/WebKit/Source/core/html/HTMLLinkElement.cpp
@@ -53,7 +53,7 @@ : HTMLElement(linkTag, document), link_loader_(LinkLoader::Create(this)), sizes_(DOMTokenList::Create(*this, HTMLNames::sizesAttr)), - rel_list_(this, RelList::Create(this)), + rel_list_(RelList::Create(this)), created_by_parser_(created_by_parser) {} HTMLLinkElement* HTMLLinkElement::Create(Document& document,
diff --git a/third_party/WebKit/Source/core/html/HTMLMediaElement.cpp b/third_party/WebKit/Source/core/html/HTMLMediaElement.cpp index 08d68c7..ae921cd 100644 --- a/third_party/WebKit/Source/core/html/HTMLMediaElement.cpp +++ b/third_party/WebKit/Source/core/html/HTMLMediaElement.cpp
@@ -498,9 +498,8 @@ playing_remotely_(false), in_overlay_fullscreen_video_(false), mostly_filling_viewport_(false), - audio_tracks_(this, AudioTrackList::Create(*this)), - video_tracks_(this, VideoTrackList::Create(*this)), - text_tracks_(this, nullptr), + audio_tracks_(AudioTrackList::Create(*this)), + video_tracks_(VideoTrackList::Create(*this)), audio_source_node_(nullptr), autoplay_policy_(new AutoplayPolicy(this)), remote_playback_client_(nullptr),
diff --git a/third_party/WebKit/Source/core/html/HTMLScriptElement.cpp b/third_party/WebKit/Source/core/html/HTMLScriptElement.cpp index 2787cca..da2d7e2d 100644 --- a/third_party/WebKit/Source/core/html/HTMLScriptElement.cpp +++ b/third_party/WebKit/Source/core/html/HTMLScriptElement.cpp
@@ -45,8 +45,7 @@ bool already_started, bool created_during_document_write) : HTMLElement(scriptTag, document), - loader_(this, - InitializeScriptLoader(was_inserted_by_parser, + loader_(InitializeScriptLoader(was_inserted_by_parser, already_started, created_during_document_write)) {}
diff --git a/third_party/WebKit/Source/core/html/HTMLTemplateElement.cpp b/third_party/WebKit/Source/core/html/HTMLTemplateElement.cpp index d91e600..b4a0c79 100644 --- a/third_party/WebKit/Source/core/html/HTMLTemplateElement.cpp +++ b/third_party/WebKit/Source/core/html/HTMLTemplateElement.cpp
@@ -39,7 +39,7 @@ using namespace HTMLNames; inline HTMLTemplateElement::HTMLTemplateElement(Document& document) - : HTMLElement(templateTag, document), content_(this, nullptr) {} + : HTMLElement(templateTag, document) {} DEFINE_NODE_FACTORY(HTMLTemplateElement)
diff --git a/third_party/WebKit/Source/core/html/custom/CustomElementReactionStack.cpp b/third_party/WebKit/Source/core/html/custom/CustomElementReactionStack.cpp index 83d9b424..d507666 100644 --- a/third_party/WebKit/Source/core/html/custom/CustomElementReactionStack.cpp +++ b/third_party/WebKit/Source/core/html/custom/CustomElementReactionStack.cpp
@@ -77,7 +77,7 @@ CustomElementReactionQueue* reactions = map_.at(element); if (!reactions) { reactions = new CustomElementReactionQueue(); - map_.insert(TraceWrapperMember<Element>(this, element), reactions); + map_.insert(element, reactions); } reactions->Add(reaction);
diff --git a/third_party/WebKit/Source/core/html/custom/CustomElementRegistry.cpp b/third_party/WebKit/Source/core/html/custom/CustomElementRegistry.cpp index a405197..eafc297 100644 --- a/third_party/WebKit/Source/core/html/custom/CustomElementRegistry.cpp +++ b/third_party/WebKit/Source/core/html/custom/CustomElementRegistry.cpp
@@ -196,8 +196,7 @@ CustomElementDefinition* definition = builder.Build(descriptor, id); CHECK(!exception_state.HadException()); CHECK(definition->Descriptor() == descriptor); - definitions_.emplace_back( - TraceWrapperMember<CustomElementDefinition>(this, definition)); + definitions_.emplace_back(definition); NameIdMap::AddResult result = name_id_map_.insert(descriptor.GetName(), id); CHECK(result.is_new_entry);
diff --git a/third_party/WebKit/Source/core/html/imports/HTMLImportTreeRoot.cpp b/third_party/WebKit/Source/core/html/imports/HTMLImportTreeRoot.cpp index 47b69713..1443ff3 100644 --- a/third_party/WebKit/Source/core/html/imports/HTMLImportTreeRoot.cpp +++ b/third_party/WebKit/Source/core/html/imports/HTMLImportTreeRoot.cpp
@@ -17,7 +17,7 @@ HTMLImportTreeRoot::HTMLImportTreeRoot(Document* document) : HTMLImport(HTMLImport::kSync), - document_(this, document), + document_(document), recalc_timer_( TaskRunnerHelper::Get(TaskType::kUnspecedTimer, document->GetFrame()), this,
diff --git a/third_party/WebKit/Source/core/html/imports/HTMLImportsController.cpp b/third_party/WebKit/Source/core/html/imports/HTMLImportsController.cpp index c3625ef..b353969 100644 --- a/third_party/WebKit/Source/core/html/imports/HTMLImportsController.cpp +++ b/third_party/WebKit/Source/core/html/imports/HTMLImportsController.cpp
@@ -41,7 +41,7 @@ namespace blink { HTMLImportsController::HTMLImportsController(Document& master) - : root_(this, HTMLImportTreeRoot::Create(&master)) { + : root_(HTMLImportTreeRoot::Create(&master)) { UseCounter::Count(master, WebFeature::kHTMLImports); }
diff --git a/third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.cpp b/third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.cpp index 29d1842..4a3dde3 100644 --- a/third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.cpp +++ b/third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.cpp
@@ -131,7 +131,6 @@ tokenizer_(sync_policy == kForceSynchronousParsing ? HTMLTokenizer::Create(options_) : nullptr), - script_runner_(this, nullptr), loading_task_runner_( TaskRunnerHelper::Get(TaskType::kNetworking, &document)), parser_scheduler_(
diff --git a/third_party/WebKit/Source/core/html/parser/HTMLParserScriptRunner.cpp b/third_party/WebKit/Source/core/html/parser/HTMLParserScriptRunner.cpp index e7e992f..b4e5b028 100644 --- a/third_party/WebKit/Source/core/html/parser/HTMLParserScriptRunner.cpp +++ b/third_party/WebKit/Source/core/html/parser/HTMLParserScriptRunner.cpp
@@ -159,10 +159,7 @@ HTMLParserReentryPermit* reentry_permit, Document* document, HTMLParserScriptRunnerHost* host) - : reentry_permit_(reentry_permit), - document_(document), - host_(host), - parser_blocking_script_(this, nullptr) { + : reentry_permit_(reentry_permit), document_(document), host_(host) { DCHECK(host_); } @@ -553,8 +550,7 @@ // "Add the element to the end of the list of scripts that will execute // when the document has finished parsing associated with the Document // of the parser that created the element." - scripts_to_execute_after_parsing_.push_back( - TraceWrapperMember<PendingScript>(this, pending_script)); + scripts_to_execute_after_parsing_.push_back(pending_script); } // The initial steps for 'An end tag whose tag name is "script"'
diff --git a/third_party/WebKit/Source/core/html/track/TextTrack.cpp b/third_party/WebKit/Source/core/html/track/TextTrack.cpp index 7845313..a6f27f7 100644 --- a/third_party/WebKit/Source/core/html/track/TextTrack.cpp +++ b/third_party/WebKit/Source/core/html/track/TextTrack.cpp
@@ -88,7 +88,6 @@ const AtomicString& id, TextTrackType type) : TrackBase(WebMediaPlayer::kTextTrack, kind, label, language, id), - cues_(this, nullptr), active_cues_(nullptr), track_list_(nullptr), mode_(DisabledKeyword()),
diff --git a/third_party/WebKit/Source/core/html/track/TextTrackCueList.cpp b/third_party/WebKit/Source/core/html/track/TextTrackCueList.cpp index 43076f5..103bc18c 100644 --- a/third_party/WebKit/Source/core/html/track/TextTrackCueList.cpp +++ b/third_party/WebKit/Source/core/html/track/TextTrackCueList.cpp
@@ -70,7 +70,7 @@ if (!list_.IsEmpty() && (index > 0) && (list_[index - 1].Get() == cue)) return false; - list_.insert(index, TraceWrapperMember<TextTrackCue>(this, cue)); + list_.insert(index, cue); InvalidateCueIndex(index); return true; }
diff --git a/third_party/WebKit/Source/core/html/track/TextTrackList.cpp b/third_party/WebKit/Source/core/html/track/TextTrackList.cpp index 66bdda3..74f8b9e 100644 --- a/third_party/WebKit/Source/core/html/track/TextTrackList.cpp +++ b/third_party/WebKit/Source/core/html/track/TextTrackList.cpp
@@ -169,13 +169,13 @@ void TextTrackList::Append(TextTrack* track) { if (track->TrackType() == TextTrack::kAddTrack) { - add_track_tracks_.push_back(TraceWrapperMember<TextTrack>(this, track)); + add_track_tracks_.push_back(track); } else if (track->TrackType() == TextTrack::kTrackElement) { // Insert tracks added for <track> element in tree order. size_t index = ToLoadableTextTrack(track)->TrackElementIndex(); - element_tracks_.insert(index, TraceWrapperMember<TextTrack>(this, track)); + element_tracks_.insert(index, track); } else if (track->TrackType() == TextTrack::kInBand) { - inband_tracks_.push_back(TraceWrapperMember<TextTrack>(this, track)); + inband_tracks_.push_back(track); } else { NOTREACHED(); }
diff --git a/third_party/WebKit/Source/core/html/track/TrackListBase.h b/third_party/WebKit/Source/core/html/track/TrackListBase.h index 9eb7734..df11e6d 100644 --- a/third_party/WebKit/Source/core/html/track/TrackListBase.h +++ b/third_party/WebKit/Source/core/html/track/TrackListBase.h
@@ -50,7 +50,7 @@ void Add(T* track) { track->SetMediaElement(media_element_); - tracks_.push_back(TraceWrapperMember<T>(this, track)); + tracks_.push_back(track); ScheduleEvent(TrackEvent::Create(EventTypeNames::addtrack, track)); }
diff --git a/third_party/WebKit/Source/core/input/KeyboardEventManager.cpp b/third_party/WebKit/Source/core/input/KeyboardEventManager.cpp index 4d7e534..bd9a08b 100644 --- a/third_party/WebKit/Source/core/input/KeyboardEventManager.cpp +++ b/third_party/WebKit/Source/core/input/KeyboardEventManager.cpp
@@ -192,14 +192,12 @@ // To be meaningful enough to indicate user intention, a keyboard event needs // - not to be a modifier event - // - not to be a browser shortcut // https://crbug.com/709765 bool is_modifier = Platform::Current()->IsDomKeyForModifier(initial_key_event.dom_key); - bool is_browser_shortcut = initial_key_event.is_browser_shortcut; std::unique_ptr<UserGestureIndicator> gesture_indicator; - if (!is_modifier && !is_browser_shortcut) { + if (!is_modifier) { gesture_indicator.reset(new UserGestureIndicator( UserGestureToken::Create(frame_->GetDocument()))); }
diff --git a/third_party/WebKit/Source/core/inspector/InspectorLayerTreeAgent.cpp b/third_party/WebKit/Source/core/inspector/InspectorLayerTreeAgent.cpp index 934ae43..aec02ab 100644 --- a/third_party/WebKit/Source/core/inspector/InspectorLayerTreeAgent.cpp +++ b/third_party/WebKit/Source/core/inspector/InspectorLayerTreeAgent.cpp
@@ -48,6 +48,7 @@ #include "core/paint/compositing/PaintLayerCompositor.h" #include "platform/geometry/IntRect.h" #include "platform/graphics/CompositingReasons.h" +#include "platform/graphics/CompositorElementId.h" #include "platform/graphics/GraphicsLayer.h" #include "platform/graphics/PictureSnapshot.h" #include "platform/transforms/TransformationMatrix.h" @@ -120,8 +121,22 @@ return scroll_rects->length() ? std::move(scroll_rects) : nullptr; } +// TODO(flackr): We should be getting the sticky position constraints from the +// property tree once blink is able to access them. https://crbug.com/754339 +static GraphicsLayer* FindLayerByElementId(GraphicsLayer* root, + CompositorElementId element_id) { + if (root->PlatformLayer()->GetElementId() == element_id) + return root; + for (size_t i = 0, size = root->Children().size(); i < size; ++i) { + if (GraphicsLayer* layer = + FindLayerByElementId(root->Children()[i], element_id)) + return layer; + } + return nullptr; +} + static std::unique_ptr<protocol::LayerTree::StickyPositionConstraint> -BuildStickyInfoForLayer(WebLayer* layer) { +BuildStickyInfoForLayer(GraphicsLayer* root, WebLayer* layer) { WebLayerStickyPositionConstraint constraints = layer->StickyPositionConstraint(); if (!constraints.is_sticky) @@ -140,19 +155,26 @@ .setStickyBoxRect(std::move(sticky_box_rect)) .setContainingBlockRect(std::move(containing_block_rect)) .build(); - if (constraints.nearest_layer_shifting_sticky_box >= 0) { - constraints_obj->setNearestLayerShiftingStickyBox( - String::Number(constraints.nearest_layer_shifting_sticky_box)); + if (constraints.nearest_element_shifting_sticky_box) { + constraints_obj->setNearestLayerShiftingStickyBox(String::Number( + FindLayerByElementId(root, + constraints.nearest_element_shifting_sticky_box) + ->PlatformLayer() + ->Id())); } - if (constraints.nearest_layer_shifting_containing_block >= 0) { - constraints_obj->setNearestLayerShiftingContainingBlock( - String::Number(constraints.nearest_layer_shifting_containing_block)); + if (constraints.nearest_element_shifting_containing_block) { + constraints_obj->setNearestLayerShiftingContainingBlock(String::Number( + FindLayerByElementId( + root, constraints.nearest_element_shifting_containing_block) + ->PlatformLayer() + ->Id())); } return constraints_obj; } static std::unique_ptr<protocol::LayerTree::Layer> BuildObjectForLayer( + GraphicsLayer* root, GraphicsLayer* graphics_layer, int node_id, bool report_wheel_event_listeners) { @@ -203,7 +225,7 @@ if (scroll_rects) layer_object->setScrollRects(std::move(scroll_rects)); std::unique_ptr<protocol::LayerTree::StickyPositionConstraint> sticky_info = - BuildStickyInfoForLayer(web_layer); + BuildStickyInfoForLayer(root, web_layer); if (sticky_info) layer_object->setStickyPositionConstraint(std::move(sticky_info)); return layer_object; @@ -320,19 +342,19 @@ } void InspectorLayerTreeAgent::GatherGraphicsLayers( - GraphicsLayer* root, + GraphicsLayer* layer, HashMap<int, int>& layer_id_to_node_id_map, std::unique_ptr<Array<protocol::LayerTree::Layer>>& layers, bool has_wheel_event_handlers, int scrolling_layer_id) { - if (client_->IsInspectorLayer(root)) + if (client_->IsInspectorLayer(layer)) return; - int layer_id = root->PlatformLayer()->Id(); + int layer_id = layer->PlatformLayer()->Id(); layers->addItem(BuildObjectForLayer( - root, layer_id_to_node_id_map.at(layer_id), + RootGraphicsLayer(), layer, layer_id_to_node_id_map.at(layer_id), has_wheel_event_handlers && layer_id == scrolling_layer_id)); - for (size_t i = 0, size = root->Children().size(); i < size; ++i) - GatherGraphicsLayers(root->Children()[i], layer_id_to_node_id_map, layers, + for (size_t i = 0, size = layer->Children().size(); i < size; ++i) + GatherGraphicsLayers(layer->Children()[i], layer_id_to_node_id_map, layers, has_wheel_event_handlers, scrolling_layer_id); }
diff --git a/third_party/WebKit/Source/core/intersection_observer/ElementIntersectionObserverData.cpp b/third_party/WebKit/Source/core/intersection_observer/ElementIntersectionObserverData.cpp index 0996438..b3a337e 100644 --- a/third_party/WebKit/Source/core/intersection_observer/ElementIntersectionObserverData.cpp +++ b/third_party/WebKit/Source/core/intersection_observer/ElementIntersectionObserverData.cpp
@@ -34,9 +34,7 @@ void ElementIntersectionObserverData::AddObservation( IntersectionObservation& observation) { DCHECK(observation.Observer()); - intersection_observations_.insert( - TraceWrapperMember<IntersectionObserver>(this, observation.Observer()), - &observation); + intersection_observations_.insert(observation.Observer(), &observation); } void ElementIntersectionObserverData::RemoveObservation(
diff --git a/third_party/WebKit/Source/core/intersection_observer/IntersectionObserver.cpp b/third_party/WebKit/Source/core/intersection_observer/IntersectionObserver.cpp index 49e94415..e075155 100644 --- a/third_party/WebKit/Source/core/intersection_observer/IntersectionObserver.cpp +++ b/third_party/WebKit/Source/core/intersection_observer/IntersectionObserver.cpp
@@ -177,7 +177,7 @@ Element* root, const Vector<Length>& root_margin, const Vector<float>& thresholds) - : delegate_(this, &delegate), + : delegate_(&delegate), root_(root), thresholds_(thresholds), top_margin_(kFixed),
diff --git a/third_party/WebKit/Source/core/loader/modulescript/ModuleTreeLinker.cpp b/third_party/WebKit/Source/core/loader/modulescript/ModuleTreeLinker.cpp index 0af80648..f054d9ab 100644 --- a/third_party/WebKit/Source/core/loader/modulescript/ModuleTreeLinker.cpp +++ b/third_party/WebKit/Source/core/loader/modulescript/ModuleTreeLinker.cpp
@@ -83,8 +83,7 @@ registry_(registry), client_(client), ancestor_list_with_url_(ancestor_list_with_url), - level_(level), - module_script_(this, nullptr) { + level_(level) { CHECK(modulator); CHECK(reached_url_set_); CHECK(registry);
diff --git a/third_party/WebKit/Source/core/loader/modulescript/ModuleTreeLinkerRegistry.cpp b/third_party/WebKit/Source/core/loader/modulescript/ModuleTreeLinkerRegistry.cpp index 9fb1ebb..7bf7bfa 100644 --- a/third_party/WebKit/Source/core/loader/modulescript/ModuleTreeLinkerRegistry.cpp +++ b/third_party/WebKit/Source/core/loader/modulescript/ModuleTreeLinkerRegistry.cpp
@@ -29,8 +29,7 @@ ModuleTreeLinker* fetcher = ModuleTreeLinker::Fetch( request, ancestor_list, level, modulator, reached_url_set, this, client); DCHECK(fetcher->IsFetching()); - active_tree_linkers_.insert( - TraceWrapperMember<ModuleTreeLinker>(this, fetcher)); + active_tree_linkers_.insert(fetcher); return fetcher; } @@ -41,8 +40,7 @@ ModuleTreeLinker* fetcher = ModuleTreeLinker::FetchDescendantsForInlineScript( module_script, modulator, this, client); DCHECK(fetcher->IsFetching()); - active_tree_linkers_.insert( - TraceWrapperMember<ModuleTreeLinker>(this, fetcher)); + active_tree_linkers_.insert(fetcher); return fetcher; } @@ -50,8 +48,7 @@ ModuleTreeLinker* fetcher) { DCHECK(fetcher->HasFinished()); - auto it = active_tree_linkers_.find( - TraceWrapperMember<ModuleTreeLinker>(this, fetcher)); + auto it = active_tree_linkers_.find(fetcher); DCHECK_NE(it, active_tree_linkers_.end()); active_tree_linkers_.erase(it); }
diff --git a/third_party/WebKit/Source/core/mojo/MojoWatcher.cpp b/third_party/WebKit/Source/core/mojo/MojoWatcher.cpp index 6033a80..902c00b 100644 --- a/third_party/WebKit/Source/core/mojo/MojoWatcher.cpp +++ b/third_party/WebKit/Source/core/mojo/MojoWatcher.cpp
@@ -73,7 +73,7 @@ MojoWatcher::MojoWatcher(ExecutionContext* context, MojoWatchCallback* callback) : ContextLifecycleObserver(context), task_runner_(TaskRunnerHelper::Get(TaskType::kUnspecedTimer, context)), - callback_(this, callback) {} + callback_(callback) {} MojoResult MojoWatcher::Watch(mojo::Handle handle, const MojoHandleSignals& signals_dict) {
diff --git a/third_party/WebKit/Source/core/page/ContextMenuClient.cpp b/third_party/WebKit/Source/core/page/ContextMenuClient.cpp index 36e6717..f2f92c7a9 100644 --- a/third_party/WebKit/Source/core/page/ContextMenuClient.cpp +++ b/third_party/WebKit/Source/core/page/ContextMenuClient.cpp
@@ -302,6 +302,16 @@ data.selected_text = text; data.edit_flags |= WebContextMenuData::kCanCopy; } + bool plugin_can_edit_text = plugin->Plugin()->CanEditText(); + if (plugin_can_edit_text) { + data.is_editable = true; + if (!!(data.edit_flags & WebContextMenuData::kCanCopy)) + data.edit_flags |= WebContextMenuData::kCanCut; + data.edit_flags |= WebContextMenuData::kCanPaste; + // TODO(bug 753216): Implement "SelectAll" command and enable when + // focus is within an editable text area. + data.edit_flags &= ~WebContextMenuData::kCanSelectAll; + } data.edit_flags &= ~WebContextMenuData::kCanTranslate; data.link_url = plugin->Plugin()->LinkAtPosition(data.mouse_position); if (plugin->Plugin()->SupportsPaginatedPrint()) @@ -313,7 +323,9 @@ data.media_flags |= WebContextMenuData::kMediaCanSave; // Add context menu commands that are supported by the plugin. - if (plugin->Plugin()->CanRotateView()) + // Only show rotate view options if focus is not in an editable text + // area. + if (!plugin_can_edit_text && plugin->Plugin()->CanRotateView()) data.media_flags |= WebContextMenuData::kMediaCanRotate; } }
diff --git a/third_party/WebKit/Source/core/paint/BoxPainterBase.cpp b/third_party/WebKit/Source/core/paint/BoxPainterBase.cpp index 6d2205c..6030f85 100644 --- a/third_party/WebKit/Source/core/paint/BoxPainterBase.cpp +++ b/third_party/WebKit/Source/core/paint/BoxPainterBase.cpp
@@ -378,8 +378,7 @@ if (geometry.CellUsingContainerBackground()) return false; // Complex cases not handled on the fast path. - if (!info.is_bottom_layer || !info.is_border_fill || - info.is_clipped_with_local_scrolling) + if (!info.is_bottom_layer || !info.is_border_fill) return false; // Transparent layer, nothing to paint.
diff --git a/third_party/WebKit/Source/core/paint/ViewPainter.cpp b/third_party/WebKit/Source/core/paint/ViewPainter.cpp index 64f0ffa..b3fb6d7 100644 --- a/third_party/WebKit/Source/core/paint/ViewPainter.cpp +++ b/third_party/WebKit/Source/core/paint/ViewPainter.cpp
@@ -60,7 +60,8 @@ GraphicsContext& context = paint_info.context; // The background rect always includes at least the visible content size. - IntRect background_rect(IntRect(layout_view_.ViewRect())); + IntRect background_rect( + IntRect(layout_view_.OverflowClipRect(LayoutPoint()))); if (!RuntimeEnabledFeatures::RootLayerScrollingEnabled()) background_rect.Unite(layout_view_.DocumentRect());
diff --git a/third_party/WebKit/Source/core/paint/compositing/CompositedLayerMapping.cpp b/third_party/WebKit/Source/core/paint/compositing/CompositedLayerMapping.cpp index 9a8886b..074a9c2 100644 --- a/third_party/WebKit/Source/core/paint/compositing/CompositedLayerMapping.cpp +++ b/third_party/WebKit/Source/core/paint/compositing/CompositedLayerMapping.cpp
@@ -338,21 +338,19 @@ constraints.NearestStickyLayerShiftingStickyBox(); if (sticky_box_shifting_ancestor && sticky_box_shifting_ancestor->GetCompositedLayerMapping()) { - web_constraint.nearest_layer_shifting_sticky_box = + web_constraint.nearest_element_shifting_sticky_box = sticky_box_shifting_ancestor->GetCompositedLayerMapping() ->MainGraphicsLayer() - ->PlatformLayer() - ->Id(); + ->GetElementId(); } PaintLayer* containing_block_shifting_ancestor = constraints.NearestStickyLayerShiftingContainingBlock(); if (containing_block_shifting_ancestor && containing_block_shifting_ancestor->GetCompositedLayerMapping()) { - web_constraint.nearest_layer_shifting_containing_block = + web_constraint.nearest_element_shifting_containing_block = containing_block_shifting_ancestor->GetCompositedLayerMapping() ->MainGraphicsLayer() - ->PlatformLayer() - ->Id(); + ->GetElementId(); } graphics_layer_->SetStickyPositionConstraint(web_constraint);
diff --git a/third_party/WebKit/Source/core/resize_observer/ResizeObserver.cpp b/third_party/WebKit/Source/core/resize_observer/ResizeObserver.cpp index cc9e5ad..25ecb05 100644 --- a/third_party/WebKit/Source/core/resize_observer/ResizeObserver.cpp +++ b/third_party/WebKit/Source/core/resize_observer/ResizeObserver.cpp
@@ -24,7 +24,7 @@ ResizeObserver::ResizeObserver(ResizeObserverCallback* callback, Document& document) - : callback_(this, callback), + : callback_(callback), skipped_observations_(false), element_size_changed_(false) { DCHECK(callback_); @@ -33,8 +33,7 @@ } ResizeObserver::ResizeObserver(Delegate* delegate, Document& document) - : callback_(this, nullptr), - delegate_(delegate), + : delegate_(delegate), skipped_observations_(false), element_size_changed_(false) { DCHECK(delegate_);
diff --git a/third_party/WebKit/Source/core/svg/SVGMatrixTearOff.cpp b/third_party/WebKit/Source/core/svg/SVGMatrixTearOff.cpp index 1497831..8397b698 100644 --- a/third_party/WebKit/Source/core/svg/SVGMatrixTearOff.cpp +++ b/third_party/WebKit/Source/core/svg/SVGMatrixTearOff.cpp
@@ -38,10 +38,10 @@ namespace blink { SVGMatrixTearOff::SVGMatrixTearOff(const AffineTransform& static_value) - : static_value_(static_value), context_transform_(this, nullptr) {} + : static_value_(static_value) {} SVGMatrixTearOff::SVGMatrixTearOff(SVGTransformTearOff* transform) - : context_transform_(this, transform) { + : context_transform_(transform) { DCHECK(transform); }
diff --git a/third_party/WebKit/Source/core/svg/SVGScriptElement.cpp b/third_party/WebKit/Source/core/svg/SVGScriptElement.cpp index 41b555a..35c8f35 100644 --- a/third_party/WebKit/Source/core/svg/SVGScriptElement.cpp +++ b/third_party/WebKit/Source/core/svg/SVGScriptElement.cpp
@@ -37,8 +37,7 @@ bool already_started) : SVGElement(SVGNames::scriptTag, document), SVGURIReference(this), - loader_(this, - InitializeScriptLoader(was_inserted_by_parser, + loader_(InitializeScriptLoader(was_inserted_by_parser, already_started, false)) {}
diff --git a/third_party/WebKit/Source/core/testing/DeathAwareScriptWrappable.h b/third_party/WebKit/Source/core/testing/DeathAwareScriptWrappable.h index 743ef0a..02a38e2 100644 --- a/third_party/WebKit/Source/core/testing/DeathAwareScriptWrappable.h +++ b/third_party/WebKit/Source/core/testing/DeathAwareScriptWrappable.h
@@ -68,17 +68,16 @@ } void AddWrappedVectorDependency(DeathAwareScriptWrappable* dependency) { - wrapped_vector_dependency_.push_back(Wrapper(this, dependency)); + wrapped_vector_dependency_.push_back(dependency); } void AddWrappedHashMapDependency(DeathAwareScriptWrappable* key, DeathAwareScriptWrappable* value) { - wrapped_hash_map_dependency_.insert(Wrapper(this, key), - Wrapper(this, value)); + wrapped_hash_map_dependency_.insert(key, value); } private: - DeathAwareScriptWrappable() : wrapped_dependency_(this, nullptr) {} + DeathAwareScriptWrappable() {} Member<DeathAwareScriptWrappable> raw_dependency_; Wrapper wrapped_dependency_;
diff --git a/third_party/WebKit/Source/core/timing/PerformanceObserver.cpp b/third_party/WebKit/Source/core/timing/PerformanceObserver.cpp index 7efae8a..596f2277 100644 --- a/third_party/WebKit/Source/core/timing/PerformanceObserver.cpp +++ b/third_party/WebKit/Source/core/timing/PerformanceObserver.cpp
@@ -50,7 +50,7 @@ PerformanceObserverCallback* callback) : ContextClient(execution_context), execution_context_(execution_context), - callback_(this, callback), + callback_(callback), performance_(performance), filter_options_(PerformanceEntry::kInvalid), is_registered_(false) {
diff --git a/third_party/WebKit/Source/core/workers/WorkletGlobalScope.cpp b/third_party/WebKit/Source/core/workers/WorkletGlobalScope.cpp index 788d89e..99e935b 100644 --- a/third_party/WebKit/Source/core/workers/WorkletGlobalScope.cpp +++ b/third_party/WebKit/Source/core/workers/WorkletGlobalScope.cpp
@@ -26,8 +26,7 @@ WorkerClients* worker_clients) : WorkerOrWorkletGlobalScope(isolate, worker_clients), url_(url), - user_agent_(user_agent), - modulator_(this, nullptr) { + user_agent_(user_agent) { SetSecurityOrigin(std::move(security_origin)); }
diff --git a/third_party/WebKit/Source/core/xmlhttprequest/XMLHttpRequest.cpp b/third_party/WebKit/Source/core/xmlhttprequest/XMLHttpRequest.cpp index de90dc0..efea764 100644 --- a/third_party/WebKit/Source/core/xmlhttprequest/XMLHttpRequest.cpp +++ b/third_party/WebKit/Source/core/xmlhttprequest/XMLHttpRequest.cpp
@@ -286,11 +286,8 @@ RefPtr<SecurityOrigin> isolated_world_security_origin) : SuspendableObject(context), timeout_milliseconds_(0), - response_blob_(this, nullptr), state_(kUnsent), - response_document_(this, nullptr), length_downloaded_to_file_(0), - response_array_buffer_(this, nullptr), received_length_(0), exception_code_(0), progress_event_throttle_(
diff --git a/third_party/WebKit/Source/modules/compositorworker/AnimationWorkletGlobalScope.cpp b/third_party/WebKit/Source/modules/compositorworker/AnimationWorkletGlobalScope.cpp index 6f94703..bc8a13f 100644 --- a/third_party/WebKit/Source/modules/compositorworker/AnimationWorkletGlobalScope.cpp +++ b/third_party/WebKit/Source/modules/compositorworker/AnimationWorkletGlobalScope.cpp
@@ -150,13 +150,12 @@ AnimatorDefinition* definition = new AnimatorDefinition(isolate, constructor, animate); - animator_definitions_.Set( - name, TraceWrapperMember<AnimatorDefinition>(this, definition)); + animator_definitions_.Set(name, definition); // Immediately instantiate an animator for the registered definition. // TODO(majidvp): Remove this once you add alternative way to instantiate if (Animator* animator = CreateInstance(name)) - animators_.push_back(TraceWrapperMember<Animator>(this, animator)); + animators_.push_back(animator); } Animator* AnimationWorkletGlobalScope::CreateInstance(const String& name) {
diff --git a/third_party/WebKit/Source/modules/compositorworker/Animator.cpp b/third_party/WebKit/Source/modules/compositorworker/Animator.cpp index 0fa9dc6..373b22f3 100644 --- a/third_party/WebKit/Source/modules/compositorworker/Animator.cpp +++ b/third_party/WebKit/Source/modules/compositorworker/Animator.cpp
@@ -15,7 +15,7 @@ Animator::Animator(v8::Isolate* isolate, AnimatorDefinition* definition, v8::Local<v8::Object> instance) - : definition_(this, definition), instance_(isolate, this, instance) {} + : definition_(definition), instance_(isolate, this, instance) {} Animator::~Animator() {}
diff --git a/third_party/WebKit/Source/modules/csspaint/PaintWorkletGlobalScope.cpp b/third_party/WebKit/Source/modules/csspaint/PaintWorkletGlobalScope.cpp index cb4fb7f..eba1519 100644 --- a/third_party/WebKit/Source/modules/csspaint/PaintWorkletGlobalScope.cpp +++ b/third_party/WebKit/Source/modules/csspaint/PaintWorkletGlobalScope.cpp
@@ -200,8 +200,7 @@ ScriptController()->GetScriptState(), constructor, paint, native_invalidation_properties, custom_invalidation_properties, input_argument_types, has_alpha); - paint_definitions_.Set( - name, TraceWrapperMember<CSSPaintDefinition>(this, definition)); + paint_definitions_.Set(name, definition); // TODO(xidachen): the following steps should be done with a postTask when // we move PaintWorklet off main thread. @@ -233,9 +232,7 @@ } else { DocumentPaintDefinition* document_definition = new DocumentPaintDefinition(definition); - document_definition_map.Set( - name, - TraceWrapperMember<DocumentPaintDefinition>(this, document_definition)); + document_definition_map.Set(name, document_definition); } }
diff --git a/third_party/WebKit/Source/modules/mediasession/MediaSession.cpp b/third_party/WebKit/Source/modules/mediasession/MediaSession.cpp index 2e650b0..1ae8faf 100644 --- a/third_party/WebKit/Source/modules/mediasession/MediaSession.cpp +++ b/third_party/WebKit/Source/modules/mediasession/MediaSession.cpp
@@ -153,8 +153,7 @@ void MediaSession::setActionHandler(const String& action, MediaSessionActionHandler* handler) { if (handler) { - auto add_result = action_handlers_.Set( - action, TraceWrapperMember<MediaSessionActionHandler>(this, handler)); + auto add_result = action_handlers_.Set(action, handler); if (!add_result.is_new_entry) return;
diff --git a/third_party/WebKit/Source/modules/remoteplayback/AvailabilityCallbackWrapper.cpp b/third_party/WebKit/Source/modules/remoteplayback/AvailabilityCallbackWrapper.cpp index c889db3..b2a2bf4 100644 --- a/third_party/WebKit/Source/modules/remoteplayback/AvailabilityCallbackWrapper.cpp +++ b/third_party/WebKit/Source/modules/remoteplayback/AvailabilityCallbackWrapper.cpp
@@ -11,10 +11,10 @@ AvailabilityCallbackWrapper::AvailabilityCallbackWrapper( RemotePlaybackAvailabilityCallback* callback) - : bindings_cb_(this, callback) {} + : bindings_cb_(callback) {} AvailabilityCallbackWrapper::AvailabilityCallbackWrapper(WTF::Closure callback) - : bindings_cb_(nullptr, nullptr), internal_cb_(std::move(callback)) {} + : internal_cb_(std::move(callback)) {} void AvailabilityCallbackWrapper::Run(RemotePlayback* remote_playback, bool new_availability) {
diff --git a/third_party/WebKit/Source/modules/remoteplayback/RemotePlayback.cpp b/third_party/WebKit/Source/modules/remoteplayback/RemotePlayback.cpp index 71c6b5b..7f12c1c 100644 --- a/third_party/WebKit/Source/modules/remoteplayback/RemotePlayback.cpp +++ b/third_party/WebKit/Source/modules/remoteplayback/RemotePlayback.cpp
@@ -270,10 +270,7 @@ int id; do { id = GetExecutionContext()->CircularSequentialID(); - } while (!availability_callbacks_ - .insert(id, TraceWrapperMember<AvailabilityCallbackWrapper>( - this, callback)) - .is_new_entry); + } while (!availability_callbacks_.insert(id, callback).is_new_entry); // Report the current availability via the callback. // TODO(yuryu): Wrapping notifyInitialAvailability with WTF::Closure as
diff --git a/third_party/WebKit/Source/modules/webaudio/AudioWorkletGlobalScope.cpp b/third_party/WebKit/Source/modules/webaudio/AudioWorkletGlobalScope.cpp index 325d95f..358d129 100644 --- a/third_party/WebKit/Source/modules/webaudio/AudioWorkletGlobalScope.cpp +++ b/third_party/WebKit/Source/modules/webaudio/AudioWorkletGlobalScope.cpp
@@ -139,9 +139,7 @@ definition->SetAudioParamDescriptors(audio_param_descriptors); } - processor_definition_map_.Set( - name, - TraceWrapperMember<AudioWorkletProcessorDefinition>(this, definition)); + processor_definition_map_.Set(name, definition); } AudioWorkletProcessor* AudioWorkletGlobalScope::CreateInstance( @@ -166,8 +164,7 @@ DCHECK(processor); processor->SetInstance(isolate, instance_local); - processor_instances_.push_back( - TraceWrapperMember<AudioWorkletProcessor>(this, processor)); + processor_instances_.push_back(processor); return processor; }
diff --git a/third_party/WebKit/Source/modules/webaudio/BaseAudioContext.cpp b/third_party/WebKit/Source/modules/webaudio/BaseAudioContext.cpp index 92349db..a50a9a8 100644 --- a/third_party/WebKit/Source/modules/webaudio/BaseAudioContext.cpp +++ b/third_party/WebKit/Source/modules/webaudio/BaseAudioContext.cpp
@@ -342,10 +342,10 @@ // they don't get collected prematurely before decodeAudioData // calls them. if (success_callback) { - success_callbacks_.emplace_back(this, success_callback); + success_callbacks_.emplace_back(success_callback); } if (error_callback) { - error_callbacks_.emplace_back(this, error_callback); + error_callbacks_.emplace_back(error_callback); } audio_decoder_.DecodeAsync(audio, rate, success_callback, error_callback,
diff --git a/third_party/WebKit/Source/modules/webdatabase/Database.cpp b/third_party/WebKit/Source/modules/webdatabase/Database.cpp index f3d2844..b50f332 100644 --- a/third_party/WebKit/Source/modules/webdatabase/Database.cpp +++ b/third_party/WebKit/Source/modules/webdatabase/Database.cpp
@@ -236,7 +236,7 @@ guid_(0), opened_(0), new_(false), - creation_callback_(this, creation_callback), + creation_callback_(creation_callback), transaction_in_progress_(false), is_transaction_queue_enabled_(true) { DCHECK(IsMainThread());
diff --git a/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContextBase.cpp b/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContextBase.cpp index ed81f39f..8774f175 100644 --- a/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContextBase.cpp +++ b/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContextBase.cpp
@@ -147,17 +147,7 @@ : WebGLRenderingContextBase(host, std::move(context_provider), requested_attributes, - 2), - read_framebuffer_binding_(this, nullptr), - transform_feedback_binding_(this, nullptr), - bound_copy_read_buffer_(this, nullptr), - bound_copy_write_buffer_(this, nullptr), - bound_pixel_pack_buffer_(this, nullptr), - bound_pixel_unpack_buffer_(this, nullptr), - bound_uniform_buffer_(this, nullptr), - current_boolean_occlusion_query_(this, nullptr), - current_transform_feedback_primitives_written_query_(this, nullptr), - current_elapsed_query_(this, nullptr) { + 2) { supported_internal_formats_storage_.insert( kSupportedInternalFormatsStorage, kSupportedInternalFormatsStorage + @@ -3908,7 +3898,7 @@ return; } - sampler_units_[unit] = TraceWrapperMember<WebGLSampler>(this, sampler); + sampler_units_[unit] = sampler; ContextGL()->BindSampler(unit, ObjectOrZero(sampler)); } @@ -5125,8 +5115,7 @@ "index out of range"); return false; } - bound_indexed_uniform_buffers_[index] = - TraceWrapperMember<WebGLBuffer>(this, buffer); + bound_indexed_uniform_buffers_[index] = buffer; bound_uniform_buffer_ = buffer; // Keep track of what the maximum bound uniform buffer index is
diff --git a/third_party/WebKit/Source/modules/webgl/WebGLContextGroup.cpp b/third_party/WebKit/Source/modules/webgl/WebGLContextGroup.cpp index bafb9ad7..7fe6968 100644 --- a/third_party/WebKit/Source/modules/webgl/WebGLContextGroup.cpp +++ b/third_party/WebKit/Source/modules/webgl/WebGLContextGroup.cpp
@@ -35,8 +35,7 @@ } void WebGLContextGroup::AddContext(WebGLRenderingContextBase* context) { - contexts_.insert( - TraceWrapperMember<WebGLRenderingContextBase>(this, context)); + contexts_.insert(context); } void WebGLContextGroup::LoseContextGroup(
diff --git a/third_party/WebKit/Source/modules/webgl/WebGLContextObject.cpp b/third_party/WebKit/Source/modules/webgl/WebGLContextObject.cpp index defeecc6..3582cd1 100644 --- a/third_party/WebKit/Source/modules/webgl/WebGLContextObject.cpp +++ b/third_party/WebKit/Source/modules/webgl/WebGLContextObject.cpp
@@ -30,7 +30,7 @@ namespace blink { WebGLContextObject::WebGLContextObject(WebGLRenderingContextBase* context) - : WebGLObject(context), context_(this, context) {} + : WebGLObject(context), context_(context) {} bool WebGLContextObject::Validate( const WebGLContextGroup*,
diff --git a/third_party/WebKit/Source/modules/webgl/WebGLFramebuffer.cpp b/third_party/WebKit/Source/modules/webgl/WebGLFramebuffer.cpp index 2bbaf7e..ed43eb9 100644 --- a/third_party/WebKit/Source/modules/webgl/WebGLFramebuffer.cpp +++ b/third_party/WebKit/Source/modules/webgl/WebGLFramebuffer.cpp
@@ -73,7 +73,7 @@ WebGLRenderbufferAttachment::WebGLRenderbufferAttachment( WebGLRenderbuffer* renderbuffer) - : renderbuffer_(this, renderbuffer) {} + : renderbuffer_(renderbuffer) {} WebGLSharedObject* WebGLRenderbufferAttachment::Object() const { return renderbuffer_->Object() ? renderbuffer_.Get() : 0; @@ -155,7 +155,7 @@ GLenum target, GLint level, GLint layer) - : texture_(this, texture), target_(target), level_(level), layer_(layer) {} + : texture_(texture), target_(target), level_(level), layer_(layer) {} WebGLSharedObject* WebGLTextureAttachment::Object() const { return texture_->Object() ? texture_.Get() : 0; @@ -433,10 +433,8 @@ DCHECK(object_); RemoveAttachmentInternal(target, attachment); if (texture && texture->Object()) { - attachments_.insert(attachment, - TraceWrapperMember<WebGLAttachment>( - this, WebGLTextureAttachment::Create( - texture, tex_target, level, layer))); + attachments_.insert(attachment, WebGLTextureAttachment::Create( + texture, tex_target, level, layer)); DrawBuffersIfNecessary(false); texture->OnAttached(); } @@ -449,10 +447,8 @@ DCHECK(object_); RemoveAttachmentInternal(target, attachment); if (renderbuffer && renderbuffer->Object()) { - attachments_.insert( - attachment, - TraceWrapperMember<WebGLAttachment>( - this, WebGLRenderbufferAttachment::Create(renderbuffer))); + attachments_.insert(attachment, + WebGLRenderbufferAttachment::Create(renderbuffer)); DrawBuffersIfNecessary(false); renderbuffer->OnAttached(); }
diff --git a/third_party/WebKit/Source/modules/webgl/WebGLProgram.cpp b/third_party/WebKit/Source/modules/webgl/WebGLProgram.cpp index ead9fc11..4505dd7b 100644 --- a/third_party/WebKit/Source/modules/webgl/WebGLProgram.cpp +++ b/third_party/WebKit/Source/modules/webgl/WebGLProgram.cpp
@@ -40,8 +40,6 @@ link_status_(false), link_count_(0), active_transform_feedback_count_(0), - vertex_shader_(this, nullptr), - fragment_shader_(this, nullptr), info_valid_(true) { SetObject(ctx->ContextGL()->CreateProgram()); }
diff --git a/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.cpp b/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.cpp index bdb0c063..d818073b 100644 --- a/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.cpp +++ b/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.cpp
@@ -993,7 +993,7 @@ const CanvasContextCreationAttributes& requested_attributes, unsigned version) : CanvasRenderingContext(host, requested_attributes), - context_group_(this, new WebGLContextGroup()), + context_group_(new WebGLContextGroup()), is_hidden_(false), context_lost_mode_(kNotLostContext), auto_recovery_method_(kManual), @@ -1005,11 +1005,6 @@ restore_timer_(task_runner, this, &WebGLRenderingContextBase::MaybeRestoreContext), - bound_array_buffer_(this, nullptr), - bound_vertex_array_object_(this, nullptr), - current_program_(this, nullptr), - framebuffer_binding_(this, nullptr), - renderbuffer_binding_(this, nullptr), generated_image_cache_(4), synthesized_errors_to_console_(true), num_gl_errors_to_console_allowed_(kMaxGLErrorsAllowedToConsole), @@ -1735,17 +1730,13 @@ } if (target == GL_TEXTURE_2D) { - texture_units_[active_texture_unit_].texture2d_binding_ = - TraceWrapperMember<WebGLTexture>(this, texture); + texture_units_[active_texture_unit_].texture2d_binding_ = texture; } else if (target == GL_TEXTURE_CUBE_MAP) { - texture_units_[active_texture_unit_].texture_cube_map_binding_ = - TraceWrapperMember<WebGLTexture>(this, texture); + texture_units_[active_texture_unit_].texture_cube_map_binding_ = texture; } else if (IsWebGL2OrHigher() && target == GL_TEXTURE_2D_ARRAY) { - texture_units_[active_texture_unit_].texture2d_array_binding_ = - TraceWrapperMember<WebGLTexture>(this, texture); + texture_units_[active_texture_unit_].texture2d_array_binding_ = texture; } else if (IsWebGL2OrHigher() && target == GL_TEXTURE_3D) { - texture_units_[active_texture_unit_].texture3d_binding_ = - TraceWrapperMember<WebGLTexture>(this, texture); + texture_units_[active_texture_unit_].texture3d_binding_ = texture; } else { SynthesizeGLError(GL_INVALID_ENUM, "bindTexture", "invalid target"); return;
diff --git a/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.h b/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.h index 5e0b7952..5076744 100644 --- a/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.h +++ b/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.h
@@ -877,8 +877,7 @@ ExtensionFlags flags, const char* const* prefixes) : ExtensionTracker(flags, prefixes), - extension_field_(extension_field), - extension_(this, nullptr) {} + extension_field_(extension_field) {} GC_PLUGIN_IGNORE("http://crbug.com/519953") Member<T>& extension_field_; @@ -894,9 +893,8 @@ void RegisterExtension(Member<T>& extension_ptr, ExtensionFlags flags = kApprovedExtension, const char* const* prefixes = nullptr) { - extensions_.push_back(TraceWrapperMember<ExtensionTracker>( - this, - TypedExtensionTracker<T>::Create(extension_ptr, flags, prefixes))); + extensions_.push_back( + TypedExtensionTracker<T>::Create(extension_ptr, flags, prefixes)); } bool ExtensionSupportedAndAllowed(const ExtensionTracker*);
diff --git a/third_party/WebKit/Source/modules/webgl/WebGLSharedObject.cpp b/third_party/WebKit/Source/modules/webgl/WebGLSharedObject.cpp index 5cb1f2f..d9224f4 100644 --- a/third_party/WebKit/Source/modules/webgl/WebGLSharedObject.cpp +++ b/third_party/WebKit/Source/modules/webgl/WebGLSharedObject.cpp
@@ -31,7 +31,7 @@ namespace blink { WebGLSharedObject::WebGLSharedObject(WebGLRenderingContextBase* context) - : WebGLObject(context), context_group_(this, context->ContextGroup()) {} + : WebGLObject(context), context_group_(context->ContextGroup()) {} bool WebGLSharedObject::Validate(const WebGLContextGroup* context_group, const WebGLRenderingContextBase*) const {
diff --git a/third_party/WebKit/Source/modules/webgl/WebGLTransformFeedback.cpp b/third_party/WebKit/Source/modules/webgl/WebGLTransformFeedback.cpp index 5a230d3..196f518 100644 --- a/third_party/WebKit/Source/modules/webgl/WebGLTransformFeedback.cpp +++ b/third_party/WebKit/Source/modules/webgl/WebGLTransformFeedback.cpp
@@ -21,7 +21,6 @@ object_(0), type_(type), target_(0), - bound_transform_feedback_buffer_(this, nullptr), program_(nullptr) { GLint max_attribs = ctx->GetMaxTransformFeedbackSeparateAttribs(); DCHECK_GE(max_attribs, 0); @@ -107,8 +106,7 @@ bound_indexed_transform_feedback_buffers_[index]->OnDetached( Context()->ContextGL()); } - bound_indexed_transform_feedback_buffers_[index] = - TraceWrapperMember<WebGLBuffer>(this, buffer); + bound_indexed_transform_feedback_buffers_[index] = buffer; // This also sets the generic binding point in the OpenGL state. SetBoundTransformFeedbackBuffer(buffer); return true;
diff --git a/third_party/WebKit/Source/modules/webgl/WebGLVertexArrayObjectBase.cpp b/third_party/WebKit/Source/modules/webgl/WebGLVertexArrayObjectBase.cpp index d9bf8f87..56681254 100644 --- a/third_party/WebKit/Source/modules/webgl/WebGLVertexArrayObjectBase.cpp +++ b/third_party/WebKit/Source/modules/webgl/WebGLVertexArrayObjectBase.cpp
@@ -16,7 +16,6 @@ object_(0), type_(type), has_ever_been_bound_(false), - bound_element_array_buffer_(this, nullptr), is_all_enabled_attrib_buffer_bound_(true) { array_buffer_list_.resize(ctx->MaxVertexAttribs()); attrib_enabled_.resize(ctx->MaxVertexAttribs()); @@ -87,7 +86,7 @@ if (array_buffer_list_[index]) array_buffer_list_[index]->OnDetached(Context()->ContextGL()); - array_buffer_list_[index] = TraceWrapperMember<WebGLBuffer>(this, buffer); + array_buffer_list_[index] = buffer; UpdateAttribBufferBoundStatus(); }
diff --git a/third_party/WebKit/Source/modules/webmidi/MIDIPort.cpp b/third_party/WebKit/Source/modules/webmidi/MIDIPort.cpp index 11aa48f..8a617f731 100644 --- a/third_party/WebKit/Source/modules/webmidi/MIDIPort.cpp +++ b/third_party/WebKit/Source/modules/webmidi/MIDIPort.cpp
@@ -55,7 +55,7 @@ name_(name), type_(type), version_(version), - access_(this, access), + access_(access), connection_(kConnectionStateClosed) { DCHECK(access); DCHECK(type == kTypeInput || type == kTypeOutput);
diff --git a/third_party/WebKit/Source/platform/bindings/TraceWrapperMember.h b/third_party/WebKit/Source/platform/bindings/TraceWrapperMember.h index e4c968c6..54bf8e2 100644 --- a/third_party/WebKit/Source/platform/bindings/TraceWrapperMember.h +++ b/third_party/WebKit/Source/platform/bindings/TraceWrapperMember.h
@@ -22,19 +22,12 @@ DISALLOW_NEW_EXCEPT_PLACEMENT_NEW(); public: - // TODO(mlippautz): Remove constructor taking |parent|. - TraceWrapperMember(void* parent, T* raw) : Member<T>(raw) {} + TraceWrapperMember() : Member<T>(nullptr) {} TraceWrapperMember(T* raw) : Member<T>(raw) { - // We don't require a write barrier here as TraceWrapperMember is used for - // the following scenarios: - // - Initial initialization: The write barrier will not fire as the parent - // is initially white. - // - Wrapping when inserting into a container: The write barrier will fire - // upon establishing the move into the container. - // - Assignment to a field: The regular assignment operator will fire the - // write barrier. - // Note that support for black allocation would require a barrier here. + // We have to use a write barrier here because of in-place construction + // in containers, such as HeapVector::push_back. + ScriptWrappableVisitor::WriteBarrier(raw); } TraceWrapperMember(WTF::HashTableDeletedValueType x) : Member<T>(x) {}
diff --git a/third_party/WebKit/Source/platform/heap/HeapAllocator.h b/third_party/WebKit/Source/platform/heap/HeapAllocator.h index 9e7113d..42dd648 100644 --- a/third_party/WebKit/Source/platform/heap/HeapAllocator.h +++ b/third_party/WebKit/Source/platform/heap/HeapAllocator.h
@@ -690,9 +690,7 @@ return value; } - static blink::TraceWrapperMember<T> EmptyValue() { - return blink::TraceWrapperMember<T>(nullptr, nullptr); - } + static blink::TraceWrapperMember<T> EmptyValue() { return nullptr; } }; template <typename T>
diff --git a/third_party/WebKit/Source/platform/mojo/FetchAPIRequestStructTraits.cpp b/third_party/WebKit/Source/platform/mojo/FetchAPIRequestStructTraits.cpp index aa67d0c..ccb34a29 100644 --- a/third_party/WebKit/Source/platform/mojo/FetchAPIRequestStructTraits.cpp +++ b/third_party/WebKit/Source/platform/mojo/FetchAPIRequestStructTraits.cpp
@@ -14,19 +14,6 @@ namespace mojo { -namespace { - -// Struct traits context for the FetchAPIRequest type. Since getters are invoked -// twice when serializing the type, this reduces the load for heavy members. -struct FetchAPIRequestStructTraitsContext { - FetchAPIRequestStructTraitsContext() = default; - ~FetchAPIRequestStructTraitsContext() = default; - - WTF::HashMap<WTF::String, WTF::String> headers; -}; - -} // namespace - using blink::mojom::FetchCredentialsMode; using blink::mojom::FetchRedirectMode; using blink::mojom::FetchRequestMode; @@ -380,26 +367,6 @@ } // static -void* StructTraits<blink::mojom::FetchAPIRequestDataView, - blink::WebServiceWorkerRequest>:: - SetUpContext(const blink::WebServiceWorkerRequest& request) { - FetchAPIRequestStructTraitsContext* context = - new FetchAPIRequestStructTraitsContext(); - for (const auto& pair : request.Headers()) - context->headers.insert(pair.key, pair.value); - - return context; -} - -// static -void StructTraits<blink::mojom::FetchAPIRequestDataView, - blink::WebServiceWorkerRequest>:: - TearDownContext(const blink::WebServiceWorkerRequest& request, - void* context) { - delete static_cast<FetchAPIRequestStructTraitsContext*>(context); -} - -// static blink::KURL StructTraits<blink::mojom::FetchAPIRequestDataView, blink::WebServiceWorkerRequest>:: url(const blink::WebServiceWorkerRequest& request) { @@ -414,12 +381,14 @@ } // static -const WTF::HashMap<WTF::String, WTF::String>& +WTF::HashMap<WTF::String, WTF::String> StructTraits<blink::mojom::FetchAPIRequestDataView, blink::WebServiceWorkerRequest>:: - headers(const blink::WebServiceWorkerRequest& request, void* context) { - DCHECK(context); - return static_cast<FetchAPIRequestStructTraitsContext*>(context)->headers; + headers(const blink::WebServiceWorkerRequest& request) { + WTF::HashMap<WTF::String, WTF::String> header_map; + for (const auto& pair : request.Headers()) + header_map.insert(pair.key, pair.value); + return header_map; } // static
diff --git a/third_party/WebKit/Source/platform/mojo/FetchAPIRequestStructTraits.h b/third_party/WebKit/Source/platform/mojo/FetchAPIRequestStructTraits.h index a28b1e5c..e054128 100644 --- a/third_party/WebKit/Source/platform/mojo/FetchAPIRequestStructTraits.h +++ b/third_party/WebKit/Source/platform/mojo/FetchAPIRequestStructTraits.h
@@ -68,10 +68,6 @@ template <> struct StructTraits<blink::mojom::FetchAPIRequestDataView, blink::WebServiceWorkerRequest> { - static void* SetUpContext(const blink::WebServiceWorkerRequest&); - static void TearDownContext(const blink::WebServiceWorkerRequest&, - void* context); - static blink::WebURLRequest::FetchRequestMode mode( const blink::WebServiceWorkerRequest& request) { return request.Mode(); @@ -96,9 +92,8 @@ static WTF::String method(const blink::WebServiceWorkerRequest&); - static const WTF::HashMap<WTF::String, WTF::String>& headers( - const blink::WebServiceWorkerRequest&, - void* context); + static WTF::HashMap<WTF::String, WTF::String> headers( + const blink::WebServiceWorkerRequest&); static WTF::String blob_uuid(const blink::WebServiceWorkerRequest&);
diff --git a/third_party/WebKit/Source/platform/wtf/BUILD.gn b/third_party/WebKit/Source/platform/wtf/BUILD.gn index cfd461f2..0d1d76ea 100644 --- a/third_party/WebKit/Source/platform/wtf/BUILD.gn +++ b/third_party/WebKit/Source/platform/wtf/BUILD.gn
@@ -275,6 +275,7 @@ public_deps = [ "//base", + "//sandbox", "//third_party/icu", ]
diff --git a/third_party/WebKit/Source/platform/wtf/DEPS b/third_party/WebKit/Source/platform/wtf/DEPS index a6f31d9..2454af23 100644 --- a/third_party/WebKit/Source/platform/wtf/DEPS +++ b/third_party/WebKit/Source/platform/wtf/DEPS
@@ -23,5 +23,6 @@ # platform files. Think carefully if you want to relax this restriction. "-platform", "+platform/wtf", + "+sandbox/linux/services/resource_limits.h", "-v8", ]
diff --git a/third_party/WebKit/Source/platform/wtf/typed_arrays/ArrayBufferContents.cpp b/third_party/WebKit/Source/platform/wtf/typed_arrays/ArrayBufferContents.cpp index 336a685..900324a 100644 --- a/third_party/WebKit/Source/platform/wtf/typed_arrays/ArrayBufferContents.cpp +++ b/third_party/WebKit/Source/platform/wtf/typed_arrays/ArrayBufferContents.cpp
@@ -25,8 +25,12 @@ */ #include "platform/wtf/typed_arrays/ArrayBufferContents.h" +#include "build/build_config.h" #include <string.h> +#if defined(OS_LINUX) +#include "sandbox/linux/services/resource_limits.h" +#endif #include "base/allocator/partition_allocator/partition_alloc.h" #include "platform/wtf/Assertions.h" #include "platform/wtf/allocator/Partitions.h" @@ -129,6 +133,14 @@ void* ArrayBufferContents::ReserveMemory(size_t size) { void* const hint = nullptr; const size_t align = 64 << 10; // Wasm page size + +#if defined(OS_LINUX) + // Linux by default has a small address space limit, which we chew up pretty + // quickly with large memory reservations. To mitigate this, we bump up the + // limit for array buffer reservations. See https://crbug.com/750378 + CHECK(sandbox::ResourceLimits::AdjustCurrent(RLIMIT_AS, size)); +#endif + // TODO(crbug.com/735209): On Windows this commits all the memory, rather than // just reserving it. This is very bad and should be fixed, but we don't use // this feature on Windows at all yet. @@ -140,6 +152,13 @@ } void ArrayBufferContents::ReleaseReservedMemory(void* data, size_t size) { +#if defined(OS_LINUX) + // Linux by default has a small address space limit, which we chew up pretty + // quickly with large memory reservations. To mitigate this, we bump up the + // limit for array buffer reservations. Here we need to lower it back down. + // See https://crbug.com/750378 + CHECK(sandbox::ResourceLimits::AdjustCurrent(RLIMIT_AS, -size)); +#endif base::FreePages(data, size); }
diff --git a/third_party/WebKit/public/platform/WebLayer.h b/third_party/WebKit/public/platform/WebLayer.h index 2727efc..bca2777 100644 --- a/third_party/WebKit/public/platform/WebLayer.h +++ b/third_party/WebKit/public/platform/WebLayer.h
@@ -62,8 +62,6 @@ public: virtual ~WebLayer() {} - static constexpr int kInvalidLayerId = cc::Layer::INVALID_ID; - // Returns a positive ID that will be unique across all WebLayers allocated in // this process. virtual int Id() const = 0;
diff --git a/third_party/WebKit/public/platform/WebLayerStickyPositionConstraint.h b/third_party/WebKit/public/platform/WebLayerStickyPositionConstraint.h index 798083a..456f6b66 100644 --- a/third_party/WebKit/public/platform/WebLayerStickyPositionConstraint.h +++ b/third_party/WebKit/public/platform/WebLayerStickyPositionConstraint.h
@@ -59,10 +59,11 @@ // element should not be shifted beyond. WebRect scroll_container_relative_containing_block_rect; - // The nearest ancestor sticky layers that affect the sticky box constraint - // rect and the containing block constraint rect respectively. - int nearest_layer_shifting_sticky_box; - int nearest_layer_shifting_containing_block; + // The element ids of the nearest ancestor sticky layers which affect the + // sticky box constraint rect and the containing block constraint rect + // respectively. + cc::ElementId nearest_element_shifting_sticky_box; + cc::ElementId nearest_element_shifting_containing_block; WebLayerStickyPositionConstraint() : is_sticky(false), @@ -73,9 +74,7 @@ left_offset(0.f), right_offset(0.f), top_offset(0.f), - bottom_offset(0.f), - nearest_layer_shifting_sticky_box(WebLayer::kInvalidLayerId), - nearest_layer_shifting_containing_block(WebLayer::kInvalidLayerId) {} + bottom_offset(0.f) {} }; } // namespace blink
diff --git a/third_party/android_system_sdk/LICENSE b/third_party/android_system_sdk/LICENSE new file mode 100644 index 0000000..3c84bc6 --- /dev/null +++ b/third_party/android_system_sdk/LICENSE
@@ -0,0 +1,350 @@ +GNU General Public License, version 2, +with the Classpath Exception + +The GNU General Public License (GPL) + +Version 2, June 1991 + +Copyright (C) 1989, 1991 Free Software Foundation, Inc. +59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +Everyone is permitted to copy and distribute verbatim copies of this license +document, but changing it is not allowed. + +Preamble + +The licenses for most software are designed to take away your freedom to share +and change it. By contrast, the GNU General Public License is intended to +guarantee your freedom to share and change free software--to make sure the +software is free for all its users. This General Public License applies to +most of the Free Software Foundation's software and to any other program whose +authors commit to using it. (Some other Free Software Foundation software is +covered by the GNU Library General Public License instead.) You can apply it to +your programs, too. + +When we speak of free software, we are referring to freedom, not price. Our +General Public Licenses are designed to make sure that you have the freedom to +distribute copies of free software (and charge for this service if you wish), +that you receive source code or can get it if you want it, that you can change +the software or use pieces of it in new free programs; and that you know you +can do these things. + +To protect your rights, we need to make restrictions that forbid anyone to deny +you these rights or to ask you to surrender the rights. These restrictions +translate to certain responsibilities for you if you distribute copies of the +software, or if you modify it. + +For example, if you distribute copies of such a program, whether gratis or for +a fee, you must give the recipients all the rights that you have. You must +make sure that they, too, receive or can get the source code. And you must +show them these terms so they know their rights. + +We protect your rights with two steps: (1) copyright the software, and (2) +offer you this license which gives you legal permission to copy, distribute +and/or modify the software. + +Also, for each author's protection and ours, we want to make certain that +everyone understands that there is no warranty for this free software. If the +software is modified by someone else and passed on, we want its recipients to +know that what they have is not the original, so that any problems introduced +by others will not reflect on the original authors' reputations. + +Finally, any free program is threatened constantly by software patents. We +wish to avoid the danger that redistributors of a free program will +individually obtain patent licenses, in effect making the program proprietary. +To prevent this, we have made it clear that any patent must be licensed for +everyone's free use or not licensed at all. + +The precise terms and conditions for copying, distribution and modification +follow. + +TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + +0. This License applies to any program or other work which contains a notice +placed by the copyright holder saying it may be distributed under the terms of +this General Public License. The "Program", below, refers to any such program +or work, and a "work based on the Program" means either the Program or any +derivative work under copyright law: that is to say, a work containing the +Program or a portion of it, either verbatim or with modifications and/or +translated into another language. (Hereinafter, translation is included +without limitation in the term "modification".) Each licensee is addressed as +"you". + +Activities other than copying, distribution and modification are not covered by +this License; they are outside its scope. The act of running the Program is +not restricted, and the output from the Program is covered only if its contents +constitute a work based on the Program (independent of having been made by +running the Program). Whether that is true depends on what the Program does. + +1. You may copy and distribute verbatim copies of the Program's source code as +you receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice and +disclaimer of warranty; keep intact all the notices that refer to this License +and to the absence of any warranty; and give any other recipients of the +Program a copy of this License along with the Program. + +You may charge a fee for the physical act of transferring a copy, and you may +at your option offer warranty protection in exchange for a fee. + +2. You may modify your copy or copies of the Program or any portion of it, thus +forming a work based on the Program, and copy and distribute such modifications +or work under the terms of Section 1 above, provided that you also meet all of +these conditions: + + a) You must cause the modified files to carry prominent notices stating + that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in whole or + in part contains or is derived from the Program or any part thereof, to be + licensed as a whole at no charge to all third parties under the terms of + this License. + + c) If the modified program normally reads commands interactively when run, + you must cause it, when started running for such interactive use in the + most ordinary way, to print or display an announcement including an + appropriate copyright notice and a notice that there is no warranty (or + else, saying that you provide a warranty) and that users may redistribute + the program under these conditions, and telling the user how to view a copy + of this License. (Exception: if the Program itself is interactive but does + not normally print such an announcement, your work based on the Program is + not required to print an announcement.) + +These requirements apply to the modified work as a whole. If identifiable +sections of that work are not derived from the Program, and can be reasonably +considered independent and separate works in themselves, then this License, and +its terms, do not apply to those sections when you distribute them as separate +works. But when you distribute the same sections as part of a whole which is a +work based on the Program, the distribution of the whole must be on the terms +of this License, whose permissions for other licensees extend to the entire +whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest your +rights to work written entirely by you; rather, the intent is to exercise the +right to control the distribution of derivative or collective works based on +the Program. + +In addition, mere aggregation of another work not based on the Program with the +Program (or with a work based on the Program) on a volume of a storage or +distribution medium does not bring the other work under the scope of this +License. + +3. You may copy and distribute the Program (or a work based on it, under +Section 2) in object code or executable form under the terms of Sections 1 and +2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable source + code, which must be distributed under the terms of Sections 1 and 2 above + on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three years, to + give any third party, for a charge no more than your cost of physically + performing source distribution, a complete machine-readable copy of the + corresponding source code, to be distributed under the terms of Sections 1 + and 2 above on a medium customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer to + distribute corresponding source code. (This alternative is allowed only + for noncommercial distribution and only if you received the program in + object code or executable form with such an offer, in accord with + Subsection b above.) + +The source code for a work means the preferred form of the work for making +modifications to it. For an executable work, complete source code means all +the source code for all modules it contains, plus any associated interface +definition files, plus the scripts used to control compilation and installation +of the executable. However, as a special exception, the source code +distributed need not include anything that is normally distributed (in either +source or binary form) with the major components (compiler, kernel, and so on) +of the operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the source +code from the same place counts as distribution of the source code, even though +third parties are not compelled to copy the source along with the object code. + +4. You may not copy, modify, sublicense, or distribute the Program except as +expressly provided under this License. Any attempt otherwise to copy, modify, +sublicense or distribute the Program is void, and will automatically terminate +your rights under this License. However, parties who have received copies, or +rights, from you under this License will not have their licenses terminated so +long as such parties remain in full compliance. + +5. You are not required to accept this License, since you have not signed it. +However, nothing else grants you permission to modify or distribute the Program +or its derivative works. These actions are prohibited by law if you do not +accept this License. Therefore, by modifying or distributing the Program (or +any work based on the Program), you indicate your acceptance of this License to +do so, and all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + +6. Each time you redistribute the Program (or any work based on the Program), +the recipient automatically receives a license from the original licensor to +copy, distribute or modify the Program subject to these terms and conditions. +You may not impose any further restrictions on the recipients' exercise of the +rights granted herein. You are not responsible for enforcing compliance by +third parties to this License. + +7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), conditions +are imposed on you (whether by court order, agreement or otherwise) that +contradict the conditions of this License, they do not excuse you from the +conditions of this License. If you cannot distribute so as to satisfy +simultaneously your obligations under this License and any other pertinent +obligations, then as a consequence you may not distribute the Program at all. +For example, if a patent license would not permit royalty-free redistribution +of the Program by all those who receive copies directly or indirectly through +you, then the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply and +the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any patents or +other property right claims or to contest validity of any such claims; this +section has the sole purpose of protecting the integrity of the free software +distribution system, which is implemented by public license practices. Many +people have made generous contributions to the wide range of software +distributed through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing to +distribute software through any other system and a licensee cannot impose that +choice. + +This section is intended to make thoroughly clear what is believed to be a +consequence of the rest of this License. + +8. If the distribution and/or use of the Program is restricted in certain +countries either by patents or by copyrighted interfaces, the original +copyright holder who places the Program under this License may add an explicit +geographical distribution limitation excluding those countries, so that +distribution is permitted only in or among countries not thus excluded. In +such case, this License incorporates the limitation as if written in the body +of this License. + +9. The Free Software Foundation may publish revised and/or new versions of the +General Public License from time to time. Such new versions will be similar in +spirit to the present version, but may differ in detail to address new problems +or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any later +version", you have the option of following the terms and conditions either of +that version or of any later version published by the Free Software Foundation. +If the Program does not specify a version number of this License, you may +choose any version ever published by the Free Software Foundation. + +10. If you wish to incorporate parts of the Program into other free programs +whose distribution conditions are different, write to the author to ask for +permission. For software which is copyrighted by the Free Software Foundation, +write to the Free Software Foundation; we sometimes make exceptions for this. +Our decision will be guided by the two goals of preserving the free status of +all derivatives of our free software and of promoting the sharing and reuse of +software generally. + +NO WARRANTY + +11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR +THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE +STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE +PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND +PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, +YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + +12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL +ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE +PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR +INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA +BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER +OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + +END OF TERMS AND CONDITIONS + +How to Apply These Terms to Your New Programs + +If you develop a new program, and you want it to be of the greatest possible +use to the public, the best way to achieve this is to make it free software +which everyone can redistribute and change under these terms. + +To do so, attach the following notices to the program. It is safest to attach +them to the start of each source file to most effectively convey the exclusion +of warranty; and each file should have at least the "copyright" line and a +pointer to where the full notice is found. + + One line to give the program's name and a brief idea of what it does. + + Copyright (C) <year> <name of author> + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., 59 + Temple Place, Suite 330, Boston, MA 02111-1307 USA + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this when it +starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author Gnomovision comes + with ABSOLUTELY NO WARRANTY; for details type 'show w'. This is free + software, and you are welcome to redistribute it under certain conditions; + type 'show c' for details. + +The hypothetical commands 'show w' and 'show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may be +called something other than 'show w' and 'show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your school, +if any, to sign a "copyright disclaimer" for the program, if necessary. Here +is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + 'Gnomovision' (which makes passes at compilers) written by James Hacker. + + signature of Ty Coon, 1 April 1989 + + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General Public +License instead of this License. + + +"CLASSPATH" EXCEPTION TO THE GPL + +Certain source files distributed by Oracle America and/or its affiliates are +subject to the following clarification and special exception to the GPL, but +only where Oracle has expressly included in the particular source file's header +the words "Oracle designates this particular file as subject to the "Classpath" +exception as provided by Oracle in the LICENSE file that accompanied this code." + + Linking this library statically or dynamically with other modules is making + a combined work based on this library. Thus, the terms and conditions of + the GNU General Public License cover the whole combination. + + As a special exception, the copyright holders of this library give you + permission to link this library with independent modules to produce an + executable, regardless of the license terms of these independent modules, + and to copy and distribute the resulting executable under terms of your + choice, provided that you also meet, for each linked independent module, + the terms and conditions of the license of that module. An independent + module is a module which is not derived from or based on this library. If + you modify this library, you may extend this exception to your version of + the library, but you are not obligated to do so. If you do not wish to do + so, delete this exception statement from your version.
diff --git a/third_party/android_system_sdk/OWNERS b/third_party/android_system_sdk/OWNERS new file mode 100644 index 0000000..7db1875 --- /dev/null +++ b/third_party/android_system_sdk/OWNERS
@@ -0,0 +1,6 @@ +sgurun@chromium.org +torne@chromium.org +tobiasjs@chromium.org + +# TEAM: android-webview-dev@chromium.org +# COMPONENT: Mobile>WebView
diff --git a/third_party/android_system_sdk/README.chromium b/third_party/android_system_sdk/README.chromium new file mode 100644 index 0000000..4674a80 --- /dev/null +++ b/third_party/android_system_sdk/README.chromium
@@ -0,0 +1,14 @@ +Name: Android System SDK +Short Name: Android System SDK +Version: 0 +Revision: 3562008 +License: GPL v2 +License File: LICENSE +Security Critical: No + +Description: +System SDK stubs for compiling Android Webview and Monochrome targets. +Revision is the BUILD ID of the Android release build. + +Local Modifications: +None
diff --git a/third_party/android_system_sdk/android-stubs-src.jar.sha1 b/third_party/android_system_sdk/android-stubs-src.jar.sha1 new file mode 100644 index 0000000..10316dc --- /dev/null +++ b/third_party/android_system_sdk/android-stubs-src.jar.sha1
@@ -0,0 +1 @@ +b75f623c98f2b671b3ddedc14c7f94818b969bc7
diff --git a/third_party/android_system_sdk/android_system.jar.sha1 b/third_party/android_system_sdk/android_system.jar.sha1 new file mode 100644 index 0000000..e85537e --- /dev/null +++ b/third_party/android_system_sdk/android_system.jar.sha1
@@ -0,0 +1 @@ +797f9a2146d33272fafb8582c3aea0550ac20891
diff --git a/tools/memory_inspector/chrome_app/template/main_window.html b/tools/memory_inspector/chrome_app/template/main_window.html index a876e03..a919c82f 100644 --- a/tools/memory_inspector/chrome_app/template/main_window.html +++ b/tools/memory_inspector/chrome_app/template/main_window.html
@@ -20,9 +20,9 @@ <div id="load_overlay"> <div id="load_message"> <div id="load_animation"> - <img id="load_animation_body" src="images/body.png" alt=""></img> - <img id="load_animation_cog1" src="images/cog1.png" alt=""></img> - <img id="load_animation_cog2" src="images/cog2.png" alt=""></img> + <img id="load_animation_body" src="images/body.png" alt=""> + <img id="load_animation_cog1" src="images/cog1.png" alt=""> + <img id="load_animation_cog2" src="images/cog2.png" alt=""> </div> <div id="load_message_title"> <span id="phantom_load_dots"></span>Loading<span id="load_dots"></span>
diff --git a/tools/metrics/actions/actions.xml b/tools/metrics/actions/actions.xml index 58c83e0..78abe36 100644 --- a/tools/metrics/actions/actions.xml +++ b/tools/metrics/actions/actions.xml
@@ -1237,6 +1237,14 @@ </description> </action> +<action name="Android.ChromeHome.OpenedByStartup"> + <owner>thildebr@chromium.org</owner> + <description> + The Chrome Home bottom sheet was automatically opened on startup after a + period of inactivity. + </description> +</action> + <action name="Android.ChromeHome.OpenedBySwipe"> <owner>mdjones@chromium.org</owner> <owner>twellington@chromium.org</owner>
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index 45bcd10..a2250a4 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -35798,6 +35798,7 @@ <int value="8" label="SHOW_BAD_CLOCK"/> <int value="9" label="CAPTIVE_PORTAL_CERT_FOUND"/> <int value="10" label="WWW_MISMATCH_FOUND_IN_SAN"/> + <int value="11" label="SHOW_MITM_SOFTWARE_INTERSTITIAL"/> </enum> <enum name="SSLErrorTypes">
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index 1a64d98..f42bdddd 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -80540,6 +80540,39 @@ </summary> </histogram> +<histogram + name="TabManager.Experimental.SessionRestore.ForegroundTab.FirstContentfulPaint" + units="ms"> + <owner>fmeawad@chromium.org</owner> + <owner>ducbui@google.com</owner> + <summary> + Elapsed time between the start of the loading and the first contentful paint + of foreground tabs when the browser loads tabs in session restore. + </summary> +</histogram> + +<histogram + name="TabManager.Experimental.SessionRestore.ForegroundTab.FirstMeaningfulPaint" + units="ms"> + <owner>fmeawad@chromium.org</owner> + <owner>ducbui@google.com</owner> + <summary> + Elapsed time between the start of the loading and the first meaningful paint + of foreground tabs when the browser loads tabs in session restore. + </summary> +</histogram> + +<histogram + name="TabManager.Experimental.SessionRestore.ForegroundTab.FirstPaint" + units="ms"> + <owner>fmeawad@chromium.org</owner> + <owner>ducbui@google.com</owner> + <summary> + Elapsed time between the start of the loading and the first paint of + foreground tabs when the browser loads tabs in session restore. + </summary> +</histogram> + <histogram name="TabManager.Heuristics.FromBackgroundedToFirstAudioStarts" units="ms"> <owner>chrisha@chromium.org</owner>
diff --git a/tools/metrics/ukm/ukm.xml b/tools/metrics/ukm/ukm.xml index d470c01..4ef64bd5 100644 --- a/tools/metrics/ukm/ukm.xml +++ b/tools/metrics/ukm/ukm.xml
@@ -8,6 +8,9 @@ This file is used to generate a comprehensive list of Chrome UKM metrics along with a detailed description for each metric. +See the following doc for details on how to add entries to this file: +https://chromium.googlesource.com/chromium/src.git/+/master/services/metrics/ukm_api.md + Events may be marked with the attribute singular="True" to indicate that the event will only occur once per source, and multiple entries will just be describing additional metrics about the same event.
diff --git a/ui/aura/env.cc b/ui/aura/env.cc index 4493d68..5c040ed 100644 --- a/ui/aura/env.cc +++ b/ui/aura/env.cc
@@ -174,7 +174,13 @@ // The ozone platform can provide its own event source. So initialize the // platform before creating the default event source. If running inside mus // let the mus process initialize ozone instead. - ui::OzonePlatform::InitializeForUI(); + ui::OzonePlatform::InitParams params; + base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); + // TODO(kylechar): Pass in single process information to Env::CreateInstance() + // instead of checking flags here. + params.single_process = command_line->HasSwitch("single-process") || + command_line->HasSwitch("in-process-gpu"); + ui::OzonePlatform::InitializeForUI(params); gfx::ClientNativePixmapFactory::SetInstance(native_pixmap_factory_.get()); #endif if (!ui::PlatformEventSource::GetInstance())
diff --git a/ui/events/ozone/evdev/device_event_dispatcher_evdev.cc b/ui/events/ozone/evdev/device_event_dispatcher_evdev.cc index a299af3..7819568 100644 --- a/ui/events/ozone/evdev/device_event_dispatcher_evdev.cc +++ b/ui/events/ozone/evdev/device_event_dispatcher_evdev.cc
@@ -121,13 +121,15 @@ EventType type, const gfx::PointF& location, const PointerDetails& details, - const base::TimeTicks& timestamp) + const base::TimeTicks& timestamp, + int flags) : device_id(device_id), slot(slot), type(type), location(location), pointer_details(details), - timestamp(timestamp) {} + timestamp(timestamp), + flags(flags) {} TouchEventParams::TouchEventParams(const TouchEventParams& other) = default;
diff --git a/ui/events/ozone/evdev/device_event_dispatcher_evdev.h b/ui/events/ozone/evdev/device_event_dispatcher_evdev.h index 4bf3fdf..f37d66b7 100644 --- a/ui/events/ozone/evdev/device_event_dispatcher_evdev.h +++ b/ui/events/ozone/evdev/device_event_dispatcher_evdev.h
@@ -138,7 +138,8 @@ EventType type, const gfx::PointF& location, const PointerDetails& pointer_details, - const base::TimeTicks& timestamp); + const base::TimeTicks& timestamp, + int flags); TouchEventParams(const TouchEventParams& other); TouchEventParams() {} ~TouchEventParams(); @@ -149,6 +150,7 @@ gfx::PointF location; PointerDetails pointer_details; base::TimeTicks timestamp; + int flags; }; // Interface used by device objects for event dispatch.
diff --git a/ui/events/ozone/evdev/event_device_test_util.cc b/ui/events/ozone/evdev/event_device_test_util.cc index 2477945..5f032d9d 100644 --- a/ui/events/ozone/evdev/event_device_test_util.cc +++ b/ui/events/ozone/evdev/event_device_test_util.cc
@@ -520,6 +520,36 @@ arraysize(kWilsonBeachActiveStylusAbsAxes), }; +// Captured from Eve Chromebook +const DeviceAbsoluteAxis kEveStylusAbsAxes[] = { + {ABS_X, {0, 0, 25920, 0, 0, 100}}, {ABS_Y, {0, 0, 17280, 0, 0, 100}}, + {ABS_PRESSURE, {0, 0, 2047, 0, 0, 0}}, {ABS_TILT_X, {0, -90, 90, 0, 0, 57}}, + {ABS_TILT_Y, {0, -90, 90, 0, 0, 57}}, {ABS_MISC, {0, 0, 255, 0, 0, 0}}, +}; +const DeviceCapabilities kEveStylus = { + /* path */ + "/sys/devices/pci0000:00/0000:00:15.0/i2c_designware.0/i2c-6/" + "i2c-WCOM50C1:00/0018:2D1F:5134.0001/input/input7/event7", + /* name */ "WCOM50C1:00 2D1F:5134 Pen", + /* phys */ "", + /* uniq */ "", + /* bustype */ "0018", + /* vendor */ "2d1f", + /* product */ "5134", + /* version */ "0100", + /* prop */ "0", + /* ev */ "1b", + /* key */ "1c03 1 0 0 0 0", + /* rel */ "0", + /* abs */ "1000d000003", + /* msc */ "11", + /* sw */ "0", + /* led */ "0", + /* ff */ "0", + kEveStylusAbsAxes, + arraysize(kEveStylusAbsAxes), +}; + ui::InputDeviceType InputDeviceTypeFromBusType(int bustype) { switch (bustype) { case BUS_I8042:
diff --git a/ui/events/ozone/evdev/event_device_test_util.h b/ui/events/ozone/evdev/event_device_test_util.h index a8de08f0..145ca4b 100644 --- a/ui/events/ozone/evdev/event_device_test_util.h +++ b/ui/events/ozone/evdev/event_device_test_util.h
@@ -74,6 +74,7 @@ extern const DeviceCapabilities kLogitechTouchKeyboardK400; extern const DeviceCapabilities kElo_TouchSystems_2700; extern const DeviceCapabilities kWilsonBeachActiveStylus; +extern const DeviceCapabilities kEveStylus; } // namspace ui
diff --git a/ui/events/ozone/evdev/event_factory_evdev.cc b/ui/events/ozone/evdev/event_factory_evdev.cc index 26fbb47..6d5aeb6 100644 --- a/ui/events/ozone/evdev/event_factory_evdev.cc +++ b/ui/events/ozone/evdev/event_factory_evdev.cc
@@ -350,7 +350,8 @@ params.device_id * kNumTouchEvdevSlots + params.slot); details.id = touch_id; TouchEvent touch_event(params.type, gfx::Point(), params.timestamp, details, - modifiers_.GetModifierFlags(), /* angle */ 0.f); + modifiers_.GetModifierFlags() | params.flags, + /* angle */ 0.f); touch_event.set_location_f(location); touch_event.set_root_location_f(location); touch_event.set_source_device_id(params.device_id);
diff --git a/ui/events/ozone/evdev/touch_evdev_types.h b/ui/events/ozone/evdev/touch_evdev_types.h index cd54f74..edb9add 100644 --- a/ui/events/ozone/evdev/touch_evdev_types.h +++ b/ui/events/ozone/evdev/touch_evdev_types.h
@@ -57,9 +57,7 @@ bool down = false; bool changed = false; }; - ButtonState btn_left; - ButtonState btn_right; - ButtonState btn_middle; + ButtonState btn_stylus; }; } // namespace ui
diff --git a/ui/events/ozone/evdev/touch_event_converter_evdev.cc b/ui/events/ozone/evdev/touch_event_converter_evdev.cc index f27da19b..ca5a9a0 100644 --- a/ui/events/ozone/evdev/touch_event_converter_evdev.cc +++ b/ui/events/ozone/evdev/touch_event_converter_evdev.cc
@@ -359,19 +359,10 @@ void TouchEventConverterEvdev::ProcessKey(const input_event& input) { switch (input.code) { - case BTN_TOUCH: - case BTN_LEFT: - case BTN_0: - events_[current_slot_].btn_left.down = input.value; - events_[current_slot_].btn_left.changed = true; - break; case BTN_STYLUS: - events_[current_slot_].btn_right.down = input.value; - events_[current_slot_].btn_right.changed = true; - break; - case BTN_STYLUS2: - events_[current_slot_].btn_middle.down = input.value; - events_[current_slot_].btn_middle.changed = true; + events_[current_slot_].btn_stylus.down = input.value; + events_[current_slot_].btn_stylus.changed = true; + events_[current_slot_].altered = true; break; case BTN_TOOL_PEN: case BTN_TOOL_RUBBER: @@ -382,6 +373,11 @@ } events_[current_slot_].altered = true; break; + case BTN_LEFT: + case BTN_0: + case BTN_STYLUS2: + case BTN_TOUCH: + break; default: NOTIMPLEMENTED() << "invalid code for EV_KEY: " << input.code; } @@ -494,9 +490,10 @@ ui::PointerDetails details(event.reported_tool_type, /* pointer_id*/ 0, event.radius_x, event.radius_y, event.pressure, event.tilt_x, event.tilt_y); - dispatcher_->DispatchTouchEvent( - TouchEventParams(input_device_.id, event.slot, event_type, - gfx::PointF(event.x, event.y), details, timestamp)); + int flags = event.btn_stylus.down ? ui::EventFlags::EF_LEFT_MOUSE_BUTTON : 0; + dispatcher_->DispatchTouchEvent(TouchEventParams( + input_device_.id, event.slot, event_type, gfx::PointF(event.x, event.y), + details, timestamp, flags)); } void TouchEventConverterEvdev::CancelAllTouches() { @@ -552,9 +549,7 @@ event->was_touching = event->touching; event->was_delayed = event->delayed; event->altered = false; - event->btn_left.changed = false; - event->btn_right.changed = false; - event->btn_middle.changed = false; + event->btn_stylus.changed = false; } } @@ -587,17 +582,9 @@ for (size_t slot = 0; slot < events_.size(); slot++) { InProgressTouchEvdev* event = &events_[slot]; - if (event->btn_left.down) { - event->btn_left.down = false; - event->btn_left.changed = true; - } - if (event->btn_right.down) { - event->btn_right.down = false; - event->btn_right.changed = true; - } - if (event->btn_middle.down) { - event->btn_middle.down = false; - event->btn_middle.changed = true; + if (event->btn_stylus.down) { + event->btn_stylus.down = false; + event->btn_stylus.changed = true; } }
diff --git a/ui/events/ozone/evdev/touch_event_converter_evdev_unittest.cc b/ui/events/ozone/evdev/touch_event_converter_evdev_unittest.cc index cc6b3c6b..4ae3d4f0 100644 --- a/ui/events/ozone/evdev/touch_event_converter_evdev_unittest.cc +++ b/ui/events/ozone/evdev/touch_event_converter_evdev_unittest.cc
@@ -1115,4 +1115,114 @@ EXPECT_EQ(0.f / 1024, event.pointer_details.force); } +TEST_F(TouchEventConverterEvdevTest, ActiveStylusBarrelButtonWhileHovering) { + ui::MockTouchEventConverterEvdev* dev = device(); + EventDeviceInfo devinfo; + EXPECT_TRUE(CapabilitiesToDeviceInfo(kEveStylus, &devinfo)); + dev->Initialize(devinfo); + + struct input_event mock_kernel_queue[]{ + // Hover + {{0, 0}, EV_KEY, BTN_TOOL_PEN, 1}, + {{0, 0}, EV_SYN, SYN_REPORT, 0}, + + // Button pressed + {{0, 0}, EV_KEY, BTN_STYLUS, 1}, + {{0, 0}, EV_SYN, SYN_REPORT, 0}, + + // Touching down + {{0, 0}, EV_KEY, BTN_TOUCH, 1}, + {{0, 0}, EV_SYN, SYN_REPORT, 0}, + + // Releasing touch + {{0, 0}, EV_KEY, BTN_TOUCH, 0}, + {{0, 0}, EV_SYN, SYN_REPORT, 0}, + + // Releasing button + {{0, 0}, EV_KEY, BTN_STYLUS, 0}, + {{0, 0}, EV_SYN, SYN_REPORT, 0}, + + // Leaving hover + {{0, 0}, EV_KEY, BTN_TOOL_PEN, 0}, + {{0, 0}, EV_SYN, SYN_REPORT, 0}, + }; + + dev->ConfigureReadMock(mock_kernel_queue, arraysize(mock_kernel_queue), 0); + dev->ReadNow(); + EXPECT_EQ(2u, size()); + + auto down_event = dispatched_touch_event(0); + EXPECT_EQ(ET_TOUCH_PRESSED, down_event.type); + EXPECT_TRUE(down_event.flags & ui::EventFlags::EF_LEFT_MOUSE_BUTTON); + EXPECT_EQ(EventPointerType::POINTER_TYPE_PEN, + down_event.pointer_details.pointer_type); + + auto up_event = dispatched_touch_event(1); + EXPECT_EQ(ET_TOUCH_RELEASED, up_event.type); + EXPECT_TRUE(down_event.flags & ui::EventFlags::EF_LEFT_MOUSE_BUTTON); + EXPECT_EQ(EventPointerType::POINTER_TYPE_PEN, + up_event.pointer_details.pointer_type); +} + +TEST_F(TouchEventConverterEvdevTest, ActiveStylusBarrelButton) { + ui::MockTouchEventConverterEvdev* dev = device(); + EventDeviceInfo devinfo; + EXPECT_TRUE(CapabilitiesToDeviceInfo(kEveStylus, &devinfo)); + dev->Initialize(devinfo); + + struct input_event mock_kernel_queue[]{ + // Hover + {{0, 0}, EV_KEY, BTN_TOOL_PEN, 1}, + {{0, 0}, EV_SYN, SYN_REPORT, 0}, + + // Touching down + {{0, 0}, EV_KEY, BTN_TOUCH, 1}, + {{0, 0}, EV_SYN, SYN_REPORT, 0}, + + // Button pressed + {{0, 0}, EV_KEY, BTN_STYLUS, 1}, + {{0, 0}, EV_SYN, SYN_REPORT, 0}, + + // Releasing button + {{0, 0}, EV_KEY, BTN_STYLUS, 0}, + {{0, 0}, EV_SYN, SYN_REPORT, 0}, + + // Releasing touch + {{0, 0}, EV_KEY, BTN_TOUCH, 0}, + {{0, 0}, EV_SYN, SYN_REPORT, 0}, + + // Leaving hover + {{0, 0}, EV_KEY, BTN_TOOL_PEN, 0}, + {{0, 0}, EV_SYN, SYN_REPORT, 0}, + }; + + dev->ConfigureReadMock(mock_kernel_queue, arraysize(mock_kernel_queue), 0); + dev->ReadNow(); + EXPECT_EQ(4u, size()); + + auto down_event = dispatched_touch_event(0); + EXPECT_EQ(ET_TOUCH_PRESSED, down_event.type); + EXPECT_FALSE(down_event.flags & ui::EventFlags::EF_LEFT_MOUSE_BUTTON); + EXPECT_EQ(EventPointerType::POINTER_TYPE_PEN, + down_event.pointer_details.pointer_type); + + auto button_down_event = dispatched_touch_event(1); + EXPECT_EQ(ET_TOUCH_MOVED, button_down_event.type); + EXPECT_TRUE(button_down_event.flags & ui::EventFlags::EF_LEFT_MOUSE_BUTTON); + EXPECT_EQ(EventPointerType::POINTER_TYPE_PEN, + button_down_event.pointer_details.pointer_type); + + auto button_up_event = dispatched_touch_event(2); + EXPECT_EQ(ET_TOUCH_MOVED, button_up_event.type); + EXPECT_FALSE(button_up_event.flags & ui::EventFlags::EF_LEFT_MOUSE_BUTTON); + EXPECT_EQ(EventPointerType::POINTER_TYPE_PEN, + button_up_event.pointer_details.pointer_type); + + auto up_event = dispatched_touch_event(3); + EXPECT_EQ(ET_TOUCH_RELEASED, up_event.type); + EXPECT_FALSE(down_event.flags & ui::EventFlags::EF_LEFT_MOUSE_BUTTON); + EXPECT_EQ(EventPointerType::POINTER_TYPE_PEN, + up_event.pointer_details.pointer_type); +} + } // namespace ui
diff --git a/ui/gfx/image/mojo/image_skia_struct_traits.cc b/ui/gfx/image/mojo/image_skia_struct_traits.cc index 98ef823..cb9487f 100644 --- a/ui/gfx/image/mojo/image_skia_struct_traits.cc +++ b/ui/gfx/image/mojo/image_skia_struct_traits.cc
@@ -107,32 +107,12 @@ } // static -void* StructTraits<gfx::mojom::ImageSkiaDataView, gfx::ImageSkia>::SetUpContext( +std::vector<gfx::ImageSkiaRep> +StructTraits<gfx::mojom::ImageSkiaDataView, gfx::ImageSkia>::image_reps( const gfx::ImageSkia& input) { // Trigger the image to load everything. input.EnsureRepsForSupportedScales(); - - // Use a context to return a stable list of ImageSkiaRep objects. That is, - // multiple calls of image_reps() should return exactly the same list of - // ImageSkiaRep objects. So that ImageSkiaRep with the same backing pixel - // buffer is properly serialized and only once. - return new std::vector<gfx::ImageSkiaRep>(input.image_reps()); -} - -// static -void StructTraits<gfx::mojom::ImageSkiaDataView, - gfx::ImageSkia>::TearDownContext(const gfx::ImageSkia& input, - void* context) { - delete static_cast<std::vector<gfx::ImageSkiaRep>*>(context); -} - -// static -const std::vector<gfx::ImageSkiaRep>& -StructTraits<gfx::mojom::ImageSkiaDataView, gfx::ImageSkia>::image_reps( - const gfx::ImageSkia& input, - void* context) { - // See the comment in SetUpContext regarding context usage. - return *(static_cast<std::vector<gfx::ImageSkiaRep>*>(context)); + return input.image_reps(); } // static
diff --git a/ui/gfx/image/mojo/image_skia_struct_traits.h b/ui/gfx/image/mojo/image_skia_struct_traits.h index 974ec9c..0b9cfecf 100644 --- a/ui/gfx/image/mojo/image_skia_struct_traits.h +++ b/ui/gfx/image/mojo/image_skia_struct_traits.h
@@ -56,11 +56,7 @@ template <> struct StructTraits<gfx::mojom::ImageSkiaDataView, gfx::ImageSkia> { - static void* SetUpContext(const gfx::ImageSkia& input); - static void TearDownContext(const gfx::ImageSkia& input, void* context); - static const std::vector<gfx::ImageSkiaRep>& image_reps( - const gfx::ImageSkia& input, - void* context); + static std::vector<gfx::ImageSkiaRep> image_reps(const gfx::ImageSkia& input); static bool IsNull(const gfx::ImageSkia& input) { return input.image_reps().empty();
diff --git a/ui/gfx/mojo/buffer_types_struct_traits.cc b/ui/gfx/mojo/buffer_types_struct_traits.cc index 186e2eb5..e9aea16 100644 --- a/ui/gfx/mojo/buffer_types_struct_traits.cc +++ b/ui/gfx/mojo/buffer_types_struct_traits.cc
@@ -8,30 +8,17 @@ namespace mojo { -void* StructTraits<gfx::mojom::NativePixmapHandleDataView, - gfx::NativePixmapHandle>:: - SetUpContext(const gfx::NativePixmapHandle& pixmap_handle) { - auto* handles = new std::vector<mojo::ScopedHandle>(); +std::vector<mojo::ScopedHandle> +StructTraits<gfx::mojom::NativePixmapHandleDataView, gfx::NativePixmapHandle>:: + fds(const gfx::NativePixmapHandle& pixmap_handle) { + std::vector<mojo::ScopedHandle> handles; #if defined(OS_LINUX) for (const base::FileDescriptor& fd : pixmap_handle.fds) - handles->emplace_back(mojo::WrapPlatformFile(fd.fd)); + handles.emplace_back(mojo::WrapPlatformFile(fd.fd)); #endif // defined(OS_LINUX) return handles; } -void StructTraits<gfx::mojom::NativePixmapHandleDataView, - gfx::NativePixmapHandle>:: - TearDownContext(const gfx::NativePixmapHandle& handle, void* context) { - delete static_cast<std::vector<mojo::ScopedHandle>*>(context); -} - -std::vector<mojo::ScopedHandle>& StructTraits< - gfx::mojom::NativePixmapHandleDataView, - gfx::NativePixmapHandle>::fds(const gfx::NativePixmapHandle& pixmap_handle, - void* context) { - return *static_cast<std::vector<mojo::ScopedHandle>*>(context); -} - bool StructTraits< gfx::mojom::NativePixmapHandleDataView, gfx::NativePixmapHandle>::Read(gfx::mojom::NativePixmapHandleDataView data,
diff --git a/ui/gfx/mojo/buffer_types_struct_traits.h b/ui/gfx/mojo/buffer_types_struct_traits.h index 0fdf909..fadb17a8 100644 --- a/ui/gfx/mojo/buffer_types_struct_traits.h +++ b/ui/gfx/mojo/buffer_types_struct_traits.h
@@ -239,10 +239,6 @@ template <> struct StructTraits<gfx::mojom::NativePixmapHandleDataView, gfx::NativePixmapHandle> { - static void* SetUpContext(const gfx::NativePixmapHandle& handle); - static void TearDownContext(const gfx::NativePixmapHandle& handle, - void* context); - static bool IsNull(const gfx::NativePixmapHandle& handle) { #if defined(OS_LINUX) return false; @@ -251,9 +247,8 @@ return true; #endif } - static std::vector<mojo::ScopedHandle>& fds( - const gfx::NativePixmapHandle& pixmap_handle, - void* context); + static std::vector<mojo::ScopedHandle> fds( + const gfx::NativePixmapHandle& pixmap_handle); static const std::vector<gfx::NativePixmapPlane>& planes( const gfx::NativePixmapHandle& pixmap_handle) {
diff --git a/ui/ozone/platform/drm/ozone_platform_gbm.cc b/ui/ozone/platform/drm/ozone_platform_gbm.cc index 109c5a97..2f265424 100644 --- a/ui/ozone/platform/drm/ozone_platform_gbm.cc +++ b/ui/ozone/platform/drm/ozone_platform_gbm.cc
@@ -151,7 +151,8 @@ // future CL. single_process_ = args.single_process; using_mojo_ = args.connector != nullptr; - DCHECK(!(using_mojo_ && single_process_)); + DCHECK(!(using_mojo_ && !single_process_)) + << "Multiprocess Mojo is not supported yet."; device_manager_ = CreateDeviceManager(); window_manager_.reset(new DrmWindowHostManager());
diff --git a/ui/ozone/platform/x11/ozone_platform_x11.cc b/ui/ozone/platform/x11/ozone_platform_x11.cc index 072c5b02..58176cc 100644 --- a/ui/ozone/platform/x11/ozone_platform_x11.cc +++ b/ui/ozone/platform/x11/ozone_platform_x11.cc
@@ -9,7 +9,6 @@ #include <memory> #include <utility> -#include "base/command_line.h" #include "base/memory/ptr_util.h" #include "base/message_loop/message_loop.h" #include "base/strings/utf_string_conversions.h" @@ -32,16 +31,6 @@ namespace { -// Returns true if a flag is present that will cause Ozone UI and GPU to run in -// the same process. -// TODO(kylechar): Remove --mojo-platform-channel-handle when mus-ws process -// split happens. -bool HasSingleProcessFlag() { - base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); - return command_line->HasSwitch("mojo-platform-channel-handle") || - command_line->HasSwitch("single-process"); -} - // Singleton OzonePlatform implementation for X11 platform. class OzonePlatformX11 : public OzonePlatform { public: @@ -106,7 +95,7 @@ // In single process mode either the UI thread will create an event source // or it's a test and an event source isn't desired. - if (!params.single_process && !HasSingleProcessFlag()) + if (!params.single_process) CreatePlatformEventSource(); surface_factory_ozone_ = base::MakeUnique<X11SurfaceFactory>(); @@ -127,7 +116,7 @@ return; // In single process mode XInitThreads() must be the first Xlib call. - if (params.single_process || HasSingleProcessFlag()) + if (params.single_process) XInitThreads(); ui::SetDefaultX11ErrorHandlers();
diff --git a/ui/views/animation/flood_fill_ink_drop_ripple.cc b/ui/views/animation/flood_fill_ink_drop_ripple.cc index 33b5c69b..7f2c4c1 100644 --- a/ui/views/animation/flood_fill_ink_drop_ripple.cc +++ b/ui/views/animation/flood_fill_ink_drop_ripple.cc
@@ -213,8 +213,10 @@ } break; case InkDropState::ACTION_PENDING: { - DCHECK_EQ(InkDropState::HIDDEN, old_ink_drop_state) - << " old_ink_drop_state=" << ToString(old_ink_drop_state); + DLOG_IF(WARNING, InkDropState::HIDDEN != old_ink_drop_state) + << "Invalid InkDropState transition. old_ink_drop_state=" + << ToString(old_ink_drop_state) + << " new_ink_drop_state=" << ToString(new_ink_drop_state); AnimateToOpacity(visible_opacity_, GetAnimationDuration(ACTION_PENDING_FADE_IN), @@ -232,9 +234,12 @@ break; } case InkDropState::ACTION_TRIGGERED: { - DCHECK(old_ink_drop_state == InkDropState::HIDDEN || - old_ink_drop_state == InkDropState::ACTION_PENDING) - << " old_ink_drop_state=" << ToString(old_ink_drop_state); + DLOG_IF(WARNING, old_ink_drop_state != InkDropState::HIDDEN && + old_ink_drop_state != InkDropState::ACTION_PENDING) + << "Invalid InkDropState transition. old_ink_drop_state=" + << ToString(old_ink_drop_state) + << " new_ink_drop_state=" << ToString(new_ink_drop_state); + if (old_ink_drop_state == InkDropState::HIDDEN) { AnimateStateChange(old_ink_drop_state, InkDropState::ACTION_PENDING, animation_observer); @@ -246,8 +251,11 @@ break; } case InkDropState::ALTERNATE_ACTION_PENDING: { - DCHECK_EQ(InkDropState::ACTION_PENDING, old_ink_drop_state) - << " old_ink_drop_state=" << ToString(old_ink_drop_state); + DLOG_IF(WARNING, InkDropState::ACTION_PENDING != old_ink_drop_state) + << "Invalid InkDropState transition. old_ink_drop_state=" + << ToString(old_ink_drop_state) + << " new_ink_drop_state=" << ToString(new_ink_drop_state); + AnimateToOpacity(visible_opacity_, GetAnimationDuration(ALTERNATE_ACTION_PENDING), ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET, @@ -259,8 +267,12 @@ break; } case InkDropState::ALTERNATE_ACTION_TRIGGERED: - DCHECK_EQ(InkDropState::ALTERNATE_ACTION_PENDING, old_ink_drop_state) - << " old_ink_drop_state=" << ToString(old_ink_drop_state); + DLOG_IF(WARNING, + InkDropState::ALTERNATE_ACTION_PENDING != old_ink_drop_state) + << "Invalid InkDropState transition. old_ink_drop_state=" + << ToString(old_ink_drop_state) + << " new_ink_drop_state=" << ToString(new_ink_drop_state); + AnimateToOpacity(kHiddenOpacity, GetAnimationDuration( ALTERNATE_ACTION_TRIGGERED_FADE_OUT), ui::LayerAnimator::ENQUEUE_NEW_ANIMATION,
diff --git a/ui/views/animation/ink_drop_ripple.cc b/ui/views/animation/ink_drop_ripple.cc index 22306a93..f6360a8 100644 --- a/ui/views/animation/ink_drop_ripple.cc +++ b/ui/views/animation/ink_drop_ripple.cc
@@ -38,7 +38,8 @@ // 1. The attached observers must be notified of all animations started and // ended. // 2. Not all state transitions is are valid, especially no-op transitions, - // and these should be detected by DCHECKs in AnimateStateChange(). + // and these invalid transitions will be logged as warnings in + // AnimateStateChange(). // |animation_observer| will be deleted when AnimationEndedCallback() returns // true.
diff --git a/ui/views/animation/square_ink_drop_ripple.cc b/ui/views/animation/square_ink_drop_ripple.cc index fffc856..276b5d5 100644 --- a/ui/views/animation/square_ink_drop_ripple.cc +++ b/ui/views/animation/square_ink_drop_ripple.cc
@@ -240,8 +240,11 @@ case InkDropState::ACTION_PENDING: if (old_ink_drop_state == new_ink_drop_state) return; - DCHECK_EQ(InkDropState::HIDDEN, old_ink_drop_state) - << " old_ink_drop_state=" << ToString(old_ink_drop_state); + DLOG_IF(WARNING, InkDropState::HIDDEN != old_ink_drop_state) + << "Invalid InkDropState transition. old_ink_drop_state=" + << ToString(old_ink_drop_state) + << " new_ink_drop_state=" << ToString(new_ink_drop_state); + AnimateToOpacity(visible_opacity_, GetAnimationDuration(ACTION_PENDING_FADE_IN), ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET, @@ -257,9 +260,12 @@ gfx::Tween::EASE_IN_OUT, animation_observer); break; case InkDropState::ACTION_TRIGGERED: { - DCHECK(old_ink_drop_state == InkDropState::HIDDEN || - old_ink_drop_state == InkDropState::ACTION_PENDING) - << " old_ink_drop_state=" << ToString(old_ink_drop_state); + DLOG_IF(WARNING, old_ink_drop_state != InkDropState::HIDDEN && + old_ink_drop_state != InkDropState::ACTION_PENDING) + << "Invalid InkDropState transition. old_ink_drop_state=" + << ToString(old_ink_drop_state) + << " new_ink_drop_state=" << ToString(new_ink_drop_state); + if (old_ink_drop_state == InkDropState::HIDDEN) { AnimateStateChange(old_ink_drop_state, InkDropState::ACTION_PENDING, animation_observer); @@ -277,8 +283,11 @@ break; } case InkDropState::ALTERNATE_ACTION_PENDING: - DCHECK_EQ(InkDropState::ACTION_PENDING, old_ink_drop_state) - << " old_ink_drop_state=" << ToString(old_ink_drop_state); + DLOG_IF(WARNING, InkDropState::ACTION_PENDING != old_ink_drop_state) + << "Invalid InkDropState transition. old_ink_drop_state=" + << ToString(old_ink_drop_state) + << " new_ink_drop_state=" << ToString(new_ink_drop_state); + AnimateToOpacity(visible_opacity_, GetAnimationDuration(ALTERNATE_ACTION_PENDING), ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET, @@ -290,8 +299,12 @@ gfx::Tween::EASE_IN_OUT, animation_observer); break; case InkDropState::ALTERNATE_ACTION_TRIGGERED: { - DCHECK_EQ(InkDropState::ALTERNATE_ACTION_PENDING, old_ink_drop_state) - << " old_ink_drop_state=" << ToString(old_ink_drop_state); + DLOG_IF(WARNING, + InkDropState::ALTERNATE_ACTION_PENDING != old_ink_drop_state) + << "Invalid InkDropState transition. old_ink_drop_state=" + << ToString(old_ink_drop_state) + << " new_ink_drop_state=" << ToString(new_ink_drop_state); + base::TimeDelta visible_duration = GetAnimationDuration(ALTERNATE_ACTION_TRIGGERED_TRANSFORM) - GetAnimationDuration(ALTERNATE_ACTION_TRIGGERED_FADE_OUT);
diff --git a/ui/webui/resources/cr_elements/OWNERS b/ui/webui/resources/cr_elements/OWNERS index 057813143..5fd1662 100644 --- a/ui/webui/resources/cr_elements/OWNERS +++ b/ui/webui/resources/cr_elements/OWNERS
@@ -1,2 +1,3 @@ michaelpg@chromium.org +scottchen@chromium.org stevenjb@chromium.org