diff --git a/DEPS b/DEPS index dc4abdd1..419c4057 100644 --- a/DEPS +++ b/DEPS
@@ -138,11 +138,11 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling Skia # and whatever else without interference from each other. - 'skia_revision': 'e08b443f9bda453c016d0cc4f73ad93352d539f3', + 'skia_revision': 'b9ca863abadf980efa142c6ed7c83a42e547d2ce', # 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': 'ab5fb228bcaf387cc72dfd93cdc62c1db4867ebf', + 'v8_revision': 'd705884e5e49d607bb5695aec6892b828d67aa6c', # 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. @@ -150,7 +150,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': '8b227a3b707d676fab6186384378c35ef3fefc14', + 'angle_revision': 'c5c937e1e8bdaa4c0a02483af81e5fecd280ec9a', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling SwiftShader # and whatever else without interference from each other. @@ -158,7 +158,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling PDFium # and whatever else without interference from each other. - 'pdfium_revision': '215adebfd4d0bfc67e018eebcaffd6cf581657e7', + 'pdfium_revision': '99cfd6bbb447e1143c2717cb274a07141400c7c5', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling BoringSSL # and whatever else without interference from each other. @@ -201,7 +201,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling catapult # and whatever else without interference from each other. - 'catapult_revision': '26377fc5ea907d3242cfdb8e1b4b9af11bbb486e', + 'catapult_revision': '4a5c435597fa9808dc2a1019cae412916e5c120c', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libFuzzer # and whatever else without interference from each other. @@ -807,7 +807,7 @@ # Build tools for Chrome OS. Note: This depends on third_party/pyelftools. 'src/third_party/chromite': { - 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + 'ee08c785ae2217380beef4122ae9fe13e9e20755', + 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '90b7c4838a288a12e8eedff7571366422cf2c1bc', 'condition': 'checkout_linux', }, @@ -822,7 +822,7 @@ # For Linux and Chromium OS. 'src/third_party/cros_system_api': { - 'url': Var('chromium_git') + '/chromiumos/platform2/system_api.git' + '@' + 'dfcfcfc36723154f1c574d1885b98d698b2587ac', + 'url': Var('chromium_git') + '/chromiumos/platform2/system_api.git' + '@' + 'd8ac0c37a3b2b13e26c458cc6efcceebbe52b3c7', 'condition': 'checkout_linux', }, @@ -832,7 +832,7 @@ }, 'src/third_party/depot_tools': - Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + 'b1a3e411d38e2a8da3ba7ec81a4b9b95cde0993e', + Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '53ea429070b1d8c359f90309fd340b26d149a143', 'src/third_party/devtools-node-modules': Var('chromium_git') + '/external/github.com/ChromeDevTools/devtools-node-modules' + '@' + Var('devtools_node_modules_revision'), @@ -1187,7 +1187,7 @@ }, 'src/third_party/perfetto': - Var('android_git') + '/platform/external/perfetto.git' + '@' + '2c923646c7d3e0694acedb656b2e1cacf46bb6dd', + Var('android_git') + '/platform/external/perfetto.git' + '@' + 'c47d62b1e095a28a1e0e941a14ee7ebaa8ceb3e5', 'src/third_party/perl': { 'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + '6f3e5028eb65d0b4c5fdd792106ac4c84eee1eb3', @@ -1355,7 +1355,7 @@ Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + '6f0b34abee8dba611c253738d955c59f703c147a', 'src/third_party/webrtc': - Var('webrtc_git') + '/src.git' + '@' + 'e3cc4895c26c3cc6ab901ac236ba355aa49e5c35', + Var('webrtc_git') + '/src.git' + '@' + '775c02ea0cd2684cd8ec5055dda7f2c2e882758d', 'src/third_party/xdg-utils': { 'url': Var('chromium_git') + '/chromium/deps/xdg-utils.git' + '@' + 'd80274d5869b17b8c9067a1022e4416ee7ed5e0d', @@ -1396,7 +1396,7 @@ Var('chromium_git') + '/v8/v8.git' + '@' + Var('v8_revision'), 'src-internal': { - 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@16559b057d78e87b73f2e98258deb87fd192d27e', + 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@a682bfc0ae99fc88dca3f01cd498a990695ac12d', 'condition': 'checkout_src_internal', },
diff --git a/android_webview/glue/java/src/com/android/webview/chromium/SharedWebViewContentsClientAdapter.java b/android_webview/glue/java/src/com/android/webview/chromium/SharedWebViewContentsClientAdapter.java index f3b69c4..668db70 100644 --- a/android_webview/glue/java/src/com/android/webview/chromium/SharedWebViewContentsClientAdapter.java +++ b/android_webview/glue/java/src/com/android/webview/chromium/SharedWebViewContentsClientAdapter.java
@@ -14,6 +14,7 @@ import com.android.webview.chromium.WebViewDelegateFactory.WebViewDelegate; import org.chromium.android_webview.AwContentsClient; +import org.chromium.android_webview.AwHistogramRecorder; import org.chromium.android_webview.AwRenderProcess; import org.chromium.android_webview.AwSafeBrowsingResponse; import org.chromium.android_webview.AwWebResourceResponse; @@ -102,6 +103,11 @@ result = mWebViewClient.shouldOverrideUrlLoading(mWebView, request.url); } if (TRACE) Log.i(TAG, "shouldOverrideUrlLoading result=" + result); + + // Record UMA for shouldOverrideUrlLoading. + AwHistogramRecorder.recordCallbackInvocation( + AwHistogramRecorder.WebViewCallbackType.SHOULD_OVERRIDE_URL_LOADING); + return result; } finally { TraceEvent.end("WebViewContentsClientAdapter.shouldOverrideUrlLoading"); @@ -121,6 +127,11 @@ } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { ApiHelperForM.onPageCommitVisible(mWebViewClient, mWebView, url); } + + // Record UMA for onPageCommitVisible. + AwHistogramRecorder.recordCallbackInvocation( + AwHistogramRecorder.WebViewCallbackType.ON_PAGE_COMMIT_VISIBLE); + // Otherwise, the API does not exist, so do nothing. } finally { TraceEvent.end("WebViewContentsClientAdapter.onPageCommitVisible");
diff --git a/android_webview/glue/java/src/com/android/webview/chromium/WebViewContentsClientAdapter.java b/android_webview/glue/java/src/com/android/webview/chromium/WebViewContentsClientAdapter.java index c1ba2d99d..bded5066 100644 --- a/android_webview/glue/java/src/com/android/webview/chromium/WebViewContentsClientAdapter.java +++ b/android_webview/glue/java/src/com/android/webview/chromium/WebViewContentsClientAdapter.java
@@ -41,6 +41,7 @@ import org.chromium.android_webview.AwContentsClient; import org.chromium.android_webview.AwContentsClientBridge; import org.chromium.android_webview.AwGeolocationPermissions; +import org.chromium.android_webview.AwHistogramRecorder; import org.chromium.android_webview.AwHttpAuthHandler; import org.chromium.android_webview.AwRenderProcessGoneDetail; import org.chromium.android_webview.AwWebResourceResponse; @@ -311,6 +312,10 @@ TraceEvent.begin("WebViewContentsClientAdapter.onLoadResource"); if (TRACE) Log.i(TAG, "onLoadResource=" + url); mWebViewClient.onLoadResource(mWebView, url); + + // Record UMA for onLoadResource. + AwHistogramRecorder.recordCallbackInvocation( + AwHistogramRecorder.WebViewCallbackType.ON_LOAD_RESOURCE); } finally { TraceEvent.end("WebViewContentsClientAdapter.onLoadResource"); } @@ -408,6 +413,11 @@ TraceEvent.begin("WebViewContentsClientAdapter.onPageStarted"); if (TRACE) Log.i(TAG, "onPageStarted=" + url); mWebViewClient.onPageStarted(mWebView, url, mWebView.getFavicon()); + + // Record UMA for onPageStarted. + AwHistogramRecorder.recordCallbackInvocation( + AwHistogramRecorder.WebViewCallbackType.ON_PAGE_STARTED); + } finally { TraceEvent.end("WebViewContentsClientAdapter.onPageStarted"); } @@ -423,6 +433,10 @@ if (TRACE) Log.i(TAG, "onPageFinished=" + url); mWebViewClient.onPageFinished(mWebView, url); + // Record UMA for onPageFinished. + AwHistogramRecorder.recordCallbackInvocation( + AwHistogramRecorder.WebViewCallbackType.ON_PAGE_FINISHED); + // See b/8208948 // This fakes an onNewPicture callback after onPageFinished to allow // CTS tests to run in an un-flaky manner. This is required as the
diff --git a/android_webview/java/src/org/chromium/android_webview/AwHistogramRecorder.java b/android_webview/java/src/org/chromium/android_webview/AwHistogramRecorder.java index 17b44fc5..499bb221 100644 --- a/android_webview/java/src/org/chromium/android_webview/AwHistogramRecorder.java +++ b/android_webview/java/src/org/chromium/android_webview/AwHistogramRecorder.java
@@ -19,15 +19,23 @@ @IntDef({WebViewCallbackType.ON_RECEIVED_LOGIN_REQUEST, WebViewCallbackType.ON_RECEIVED_CLIENT_CERT_REQUEST, WebViewCallbackType.ON_RECEIVED_HTTP_AUTH_REQUEST, - WebViewCallbackType.ON_DOWNLOAD_START}) - @interface WebViewCallbackType { + WebViewCallbackType.ON_DOWNLOAD_START, WebViewCallbackType.ON_PAGE_STARTED, + WebViewCallbackType.ON_PAGE_FINISHED, WebViewCallbackType.ON_LOAD_RESOURCE, + WebViewCallbackType.ON_PAGE_COMMIT_VISIBLE, + WebViewCallbackType.SHOULD_OVERRIDE_URL_LOADING}) + public @interface WebViewCallbackType { // These values are used for UMA. Don't reuse or reorder values. // If you add something, update NUM_ENTRIES. int ON_RECEIVED_LOGIN_REQUEST = 0; int ON_RECEIVED_CLIENT_CERT_REQUEST = 1; int ON_RECEIVED_HTTP_AUTH_REQUEST = 2; int ON_DOWNLOAD_START = 3; - int NUM_ENTRIES = 4; + int ON_PAGE_STARTED = 4; + int ON_PAGE_FINISHED = 5; + int ON_LOAD_RESOURCE = 6; + int ON_PAGE_COMMIT_VISIBLE = 7; + int SHOULD_OVERRIDE_URL_LOADING = 8; + int NUM_ENTRIES = 9; } // not meant to be instantiated
diff --git a/ash/accessibility/accessibility_highlight_controller.cc b/ash/accessibility/accessibility_highlight_controller.cc index 03d406f..99b7f79 100644 --- a/ash/accessibility/accessibility_highlight_controller.cc +++ b/ash/accessibility/accessibility_highlight_controller.cc
@@ -12,7 +12,6 @@ #include "ash/shell.h" #include "ui/base/ime/input_method.h" #include "ui/base/ime/text_input_client.h" -#include "ui/base/ui_base_features.h" #include "ui/events/event.h" #include "ui/wm/core/coordinate_conversion.h" #include "ui/wm/core/cursor_manager.h" @@ -49,10 +48,7 @@ Shell::Get()->AddPreTargetHandler(this); Shell::Get()->cursor_manager()->AddObserver(this); - // In-process ash uses the InputMethod shared between ash and browser. Mash - // receives caret updates from the browser over mojo. - if (!::features::IsMultiProcessMash()) - GetSharedInputMethod()->AddObserver(this); + GetSharedInputMethod()->AddObserver(this); } AccessibilityHighlightController::~AccessibilityHighlightController() { @@ -62,8 +58,7 @@ controller->HideCaretRing(); controller->HideCursorRing(); - if (!::features::IsMultiProcessMash()) - GetSharedInputMethod()->RemoveObserver(this); + GetSharedInputMethod()->RemoveObserver(this); Shell::Get()->cursor_manager()->RemoveObserver(this); Shell::Get()->RemovePreTargetHandler(this); }
diff --git a/ash/components/shortcut_viewer/views/keyboard_shortcut_view.cc b/ash/components/shortcut_viewer/views/keyboard_shortcut_view.cc index 1c33baf..77c11de 100644 --- a/ash/components/shortcut_viewer/views/keyboard_shortcut_view.cc +++ b/ash/components/shortcut_viewer/views/keyboard_shortcut_view.cc
@@ -207,6 +207,14 @@ return "KeyboardShortcutView"; } +ax::mojom::Role KeyboardShortcutView::GetAccessibleWindowRole() { + return ax::mojom::Role::kWindow; +} + +base::string16 KeyboardShortcutView::GetAccessibleWindowTitle() const { + return l10n_util::GetStringUTF16(IDS_KSV_TITLE); +} + bool KeyboardShortcutView::AcceleratorPressed( const ui::Accelerator& accelerator) { DCHECK_EQ(ui::VKEY_W, accelerator.key_code());
diff --git a/ash/components/shortcut_viewer/views/keyboard_shortcut_view.h b/ash/components/shortcut_viewer/views/keyboard_shortcut_view.h index bcd14be..9a983dfb6 100644 --- a/ash/components/shortcut_viewer/views/keyboard_shortcut_view.h +++ b/ash/components/shortcut_viewer/views/keyboard_shortcut_view.h
@@ -45,6 +45,8 @@ // views::View: const char* GetClassName() const override; + ax::mojom::Role GetAccessibleWindowRole() override; + base::string16 GetAccessibleWindowTitle() const override; bool AcceleratorPressed(const ui::Accelerator& accelerator) override; void Layout() override; gfx::Size CalculatePreferredSize() const override;
diff --git a/ash/display/display_color_manager.cc b/ash/display/display_color_manager.cc index b892ba78..345bee3 100644 --- a/ash/display/display_color_manager.cc +++ b/ash/display/display_color_manager.cc
@@ -19,7 +19,6 @@ #include "base/threading/scoped_blocking_call.h" #include "components/quirks/quirks_manager.h" #include "third_party/qcms/src/qcms.h" -#include "ui/base/ui_base_features.h" #include "ui/display/display.h" #include "ui/display/types/display_constants.h" #include "ui/display/types/display_snapshot.h" @@ -324,12 +323,6 @@ return false; } - // TODO: enable QuirksManager for mash. http://crbug.com/728748. Some tests - // don't create the Shell when running this code, hence the - // Shell::HasInstance() conditional. - if (Shell::HasInstance() && features::IsMultiProcessMash()) - return false; - const bool valid_product_code = display->product_code() != display::DisplaySnapshot::kInvalidProductCode; // TODO(mcasas): correct UMA s/Id/Code/, https://crbug.com/821393.
diff --git a/ash/display/window_tree_host_manager.cc b/ash/display/window_tree_host_manager.cc index 7364e2a..b54e556f 100644 --- a/ash/display/window_tree_host_manager.cc +++ b/ash/display/window_tree_host_manager.cc
@@ -824,19 +824,15 @@ AshWindowTreeHost* ash_host = AshWindowTreeHost::Create(params_with_bounds).release(); aura::WindowTreeHost* host = ash_host->AsWindowTreeHost(); - // Out-of-process ash uses the IME mojo service. In-process ash uses a single - // input method shared between ash and browser code. - if (!::features::IsMultiProcessMash()) { - DCHECK(!host->has_input_method()); - if (!input_method_) { // Singleton input method instance for Ash. - input_method_ = ui::CreateInputMethod(this, host->GetAcceleratedWidget()); - // Makes sure the input method is focused by default when created, because - // Ash uses singleton InputMethod and it won't call OnFocus/OnBlur when - // the active window changed. - input_method_->OnFocus(); - } - host->SetSharedInputMethod(input_method_.get()); + DCHECK(!host->has_input_method()); + if (!input_method_) { // Singleton input method instance for Ash. + input_method_ = ui::CreateInputMethod(this, host->GetAcceleratedWidget()); + // Makes sure the input method is focused by default when created, because + // Ash uses singleton InputMethod and it won't call OnFocus/OnBlur when + // the active window changed. + input_method_->OnFocus(); } + host->SetSharedInputMethod(input_method_.get()); host->window()->SetName(base::StringPrintf( "%sRootWindow-%d", params_with_bounds.offscreen ? "Offscreen" : "",
diff --git a/ash/drag_drop/drag_drop_controller.cc b/ash/drag_drop/drag_drop_controller.cc index 9142611..c9bf89f 100644 --- a/ash/drag_drop/drag_drop_controller.cc +++ b/ash/drag_drop/drag_drop_controller.cc
@@ -376,20 +376,12 @@ case ui::ET_SCROLL_FLING_START: Drop(translated_target, *translated_event.get()); break; - case ui::ET_GESTURE_END: - // This case occurs when IsUsingWindowService() is true and the user - // presses, pauses, and releases a touch without any movement between. - // That gesture should be interpreted as a long tap and show a menu, etc. - // Classic Ash handles this scenario below via ET_GESTURE_LONG_TAP, while - // Mash handles it in DragDropControllerMus::OnPerformDragDropCompleted. - DoDragCancel(kTouchCancelAnimationDuration); - break; case ui::ET_GESTURE_LONG_TAP: // Ideally we would want to just forward this long tap event to the // |drag_source_window_|. However, webkit does not accept events while a // drag drop is still in progress. The drag drop ends only when the nested // message loop ends. Due to this stupidity, we have to defer forwarding - // the long tap. This only occurs when IsUsingWindowService() is false. + // the long tap. pending_long_tap_.reset(new ui::GestureEvent( *event, static_cast<aura::Window*>(drag_drop_tracker_->capture_window()),
diff --git a/ash/login/ui/lock_contents_view.cc b/ash/login/ui/lock_contents_view.cc index 40e8947..ba615ba 100644 --- a/ash/login/ui/lock_contents_view.cc +++ b/ash/login/ui/lock_contents_view.cc
@@ -44,7 +44,6 @@ #include "components/user_manager/user_type.h" #include "ui/accessibility/ax_node_data.h" #include "ui/base/l10n/l10n_util.h" -#include "ui/base/ui_base_features.h" #include "ui/base/user_activity/user_activity_detector.h" #include "ui/base/user_activity/user_activity_observer.h" #include "ui/display/display.h" @@ -967,8 +966,6 @@ for (int i = 0; i < 3; ++i) system_info_->AddChildView(create_info_label()); } - if (::features::IsSingleProcessMash()) - system_info_->AddChildView(create_info_label()); if (show) system_info_->SetVisible(true); @@ -982,8 +979,6 @@ update_label(0, os_version_label_text); update_label(1, enterprise_info_text); update_label(2, bluetooth_name); - if (::features::IsSingleProcessMash()) - update_label(3, "SingleProcessMash"); LayoutTopHeader(); }
diff --git a/ash/main.cc b/ash/main.cc deleted file mode 100644 index 79a08b1..0000000 --- a/ash/main.cc +++ /dev/null
@@ -1,65 +0,0 @@ -// 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. - -#include "ash/ash_service.h" -#include "base/feature_list.h" -#include "base/files/file_path.h" -#include "base/logging.h" -#include "base/path_service.h" -#include "base/run_loop.h" -#include "base/task/single_thread_task_executor.h" -#include "ui/base/material_design/material_design_controller.h" -#include "ui/base/resource/resource_bundle.h" -#include "ui/base/ui_base_features.h" - -// This path is only hit in testing, not production. Production launches ash by -// way of the utility process, which does not use this. -void ServiceMain(service_manager::mojom::ServiceRequest request) { - logging::SetLogPrefix("ash"); - // Load ash resources and strings. - // TODO: investigate nuking ash_service_resources and use the same resources - // that are used when AshService is launched via the utility process. - base::FilePath path; - base::PathService::Get(base::DIR_MODULE, &path); - base::FilePath ash_resources = - path.Append(FILE_PATH_LITERAL("ash_service_resources.pak")); - ui::ResourceBundle::InitSharedInstanceWithPakPath(ash_resources); - ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); - if (ui::ResourceBundle::IsScaleFactorSupported(ui::SCALE_FACTOR_200P)) { - base::FilePath ash_resources_200 = - path.Append(FILE_PATH_LITERAL("ash_service_resources_200.pak")); - rb.AddDataPackFromPath(ash_resources_200, ui::SCALE_FACTOR_200P); - } - - // AshService has a distinct code path when running out of process. The out of - // process code path is triggered by way of |kMash|. As this code is only run - // when ash is out of process it has to force |kMash| to be enabled - // (otherwise AshService thinks it's running in process, which does not make - // sense, nor work). - DCHECK(base::FeatureList::GetInstance()); - std::string enabled_features; - std::string disabled_features; - base::FeatureList::GetInstance()->GetCommandLineFeatureOverrides( - &enabled_features, &disabled_features); - if (!enabled_features.empty()) - enabled_features += ","; - enabled_features += features::kMash.name; - // Disable SingleProcessMash, even if it's on by default in the test suite. - if (!disabled_features.empty()) - disabled_features += ","; - disabled_features += features::kSingleProcessMash.name; - // This code path is really only for testing (production code uses the utility - // process to launch AshService), so it's ok to use a for-testing function. - base::FeatureList::ClearInstanceForTesting(); - CHECK(base::FeatureList::InitializeInstance(enabled_features, - disabled_features)); - CHECK(base::FeatureList::IsEnabled(features::kMash)); - CHECK(!base::FeatureList::IsEnabled(features::kSingleProcessMash)); - - ui::MaterialDesignController::Initialize(); - - base::SingleThreadTaskExecutor main_task_executor( - base::MessagePump::Type::UI); - ash::AshService(std::move(request)).RunUntilTermination(); -}
diff --git a/ash/metrics/demo_session_metrics_recorder.cc b/ash/metrics/demo_session_metrics_recorder.cc index 25450e76..a4067dd 100644 --- a/ash/metrics/demo_session_metrics_recorder.cc +++ b/ash/metrics/demo_session_metrics_recorder.cc
@@ -145,18 +145,10 @@ if (app_id == extension_misc::kChromeAppId) return DemoModeApp::kBrowser; - auto is_default = [](const std::string& app_id) { - if (!features::IsMultiProcessMash()) - return app_id.empty(); - - return base::StartsWith(app_id, ShelfWindowWatcher::kDefaultShelfIdPrefix, - base::CompareCase::SENSITIVE); - }; - // If the window is the "browser" type, having an app ID other than the // default indicates a hosted/bookmark app. if (app_type == AppType::CHROME_APP || - (app_type == AppType::BROWSER && !is_default(app_id))) { + (app_type == AppType::BROWSER && !app_id.empty())) { return GetAppFromAppId(app_id); }
diff --git a/ash/shelf/shelf_window_watcher.cc b/ash/shelf/shelf_window_watcher.cc index 7b36a92e..7f2c6b5 100644 --- a/ash/shelf/shelf_window_watcher.cc +++ b/ash/shelf/shelf_window_watcher.cc
@@ -19,7 +19,6 @@ #include "ui/aura/client/aura_constants.h" #include "ui/aura/window.h" #include "ui/base/resource/resource_bundle.h" -#include "ui/base/ui_base_features.h" #include "ui/resources/grit/ui_resources.h" #include "ui/wm/public/activation_client.h" @@ -27,26 +26,12 @@ namespace { // Returns the window's shelf item type property value. -// MultiProcessMash also experimentally returns TYPE_DIALOG for some windows. ShelfItemType GetShelfItemType(aura::Window* window) { - if (features::IsMultiProcessMash() && - window->GetProperty(kShelfItemTypeKey) == TYPE_UNDEFINED && - window->type() == aura::client::WINDOW_TYPE_NORMAL) { - return TYPE_DIALOG; - } return static_cast<ShelfItemType>(window->GetProperty(kShelfItemTypeKey)); } // Returns the window's shelf id property value. -// MultiProcessMash also experimentally sets and returns default ids values. ShelfID GetShelfID(aura::Window* window) { - if (features::IsMultiProcessMash() && !window->GetProperty(kShelfIDKey)) { - static int id = 0; - const ash::ShelfID shelf_id(ShelfWindowWatcher::kDefaultShelfIdPrefix + - std::to_string(id++)); - window->SetProperty(kShelfIDKey, shelf_id.Serialize()); - return shelf_id; - } return ShelfID::Deserialize(window->GetProperty(kShelfIDKey)); } @@ -116,20 +101,6 @@ aura::Window* window, const void* key, intptr_t old) { - // ShelfIDs should rarely change beyond replacing Mash temporary defaults. - // Support ShelfID changes by removing the item; it will be re-added below. - if (features::IsMultiProcessMash() && key == kShelfIDKey && - window_watcher_->user_windows_with_items_.count(window) > 0) { - ShelfID old_id = ShelfID::Deserialize(reinterpret_cast<std::string*>(old)); - ShelfID new_id = ShelfID::Deserialize(window->GetProperty(kShelfIDKey)); - if (old_id != new_id && !old_id.IsNull() && !new_id.IsNull() && - window_watcher_->model_->ItemIndexByID(old_id) >= 0) { - window_watcher_->user_windows_with_items_.erase(window); - const int index = window_watcher_->model_->ItemIndexByID(old_id); - window_watcher_->model_->RemoveItemAt(index); - } - } - if (key == kShelfIDKey && window == wm::GetActiveWindow()) { window_watcher_->model_->SetActiveShelfID( ShelfID::Deserialize(window->GetProperty(kShelfIDKey)));
diff --git a/ash/shelf/shelf_window_watcher.h b/ash/shelf/shelf_window_watcher.h index 0eca483..4e5764c 100644 --- a/ash/shelf/shelf_window_watcher.h +++ b/ash/shelf/shelf_window_watcher.h
@@ -20,9 +20,6 @@ // ShelfWindowWatcher manages ShelfItems for dialogs in the default container // with valid ShelfItemType and ShelfID window properties (ie. task manager). // ShelfWindowWatcher also tracks the active shelf item via window activation. -// -// Some windows are experimentally given default properties in MultiProcessMash. -// TODO(crbug.com/722496|887156): Resolve, KSV etc. tracking approach for Mash. class ShelfWindowWatcher : public ::wm::ActivationChangeObserver, public ShellObserver { public:
diff --git a/ash/shell.cc b/ash/shell.cc index 9e42f75..ecc719e6 100644 --- a/ash/shell.cc +++ b/ash/shell.cc
@@ -845,10 +845,8 @@ shell_delegate_.reset(); - if (!::features::IsMultiProcessMash()) { - // Must be shut down after detachable_base_handler_. - chromeos::HammerdClient::Shutdown(); - } + // Must be shut down after detachable_base_handler_. + chromeos::HammerdClient::Shutdown(); for (auto& observer : shell_observers_) observer.OnShellDestroyed(); @@ -1156,8 +1154,7 @@ user_metrics_recorder_->OnShellInitialized(); // Initialize the D-Bus bus and services for ash. - if (!::features::IsMultiProcessMash()) - ash_dbus_helper_ = AshDBusHelper::CreateWithExistingBus(dbus_bus); + ash_dbus_helper_ = AshDBusHelper::CreateWithExistingBus(dbus_bus); ash_dbus_services_ = std::make_unique<AshDBusServices>(dbus_bus.get()); // By this point ash shell should have initialized its D-Bus signal
diff --git a/ash/shell/content/embedded_browser.cc b/ash/shell/content/embedded_browser.cc index 9127df26..47301df8 100644 --- a/ash/shell/content/embedded_browser.cc +++ b/ash/shell/content/embedded_browser.cc
@@ -10,7 +10,6 @@ #include "base/strings/string16.h" #include "base/strings/utf_string_conversions.h" #include "content/public/browser/web_contents.h" -#include "ui/base/ui_base_features.h" #include "ui/views/controls/label.h" #include "ui/views/controls/native/native_view_host.h" #include "ui/views/layout/fill_layout.h" @@ -37,9 +36,6 @@ private: HostWidget(gfx::NativeWindow native_window) { - // Note this does not work under multi process mash. - DCHECK(!features::IsMultiProcessMash()); - SetLayoutManager(std::make_unique<views::FillLayout>()); auto* widget = new views::Widget;
diff --git a/ash/system/ime_menu/ime_menu_tray.cc b/ash/system/ime_menu/ime_menu_tray.cc index 2323d44..ea384b0b 100644 --- a/ash/system/ime_menu/ime_menu_tray.cc +++ b/ash/system/ime_menu/ime_menu_tray.cc
@@ -37,7 +37,6 @@ #include "ui/base/ime/text_input_client.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/resource/resource_bundle.h" -#include "ui/base/ui_base_features.h" #include "ui/gfx/geometry/insets.h" #include "ui/gfx/paint_vector_icon.h" #include "ui/gfx/range/range.h" @@ -80,12 +79,8 @@ // Returns true if the current input context type is password. bool IsInPasswordInputContext() { - // Avoid getting IMEBridge instance if ash is not in browser. - // This is to temporarily mute the crash (http://crbug.com/867084). - // TODO(shuchen): This will be eventually be solved by the Mojo-based IMF. - return !::features::IsMultiProcessMash() && - ui::IMEBridge::Get()->GetCurrentInputContext().type == - ui::TEXT_INPUT_TYPE_PASSWORD; + return ui::IMEBridge::Get()->GetCurrentInputContext().type == + ui::TEXT_INPUT_TYPE_PASSWORD; } class ImeMenuLabel : public views::Label {
diff --git a/base/android/library_loader/library_prefetcher_unittest.cc b/base/android/library_loader/library_prefetcher_unittest.cc index 697cd07..67ae24c 100644 --- a/base/android/library_loader/library_prefetcher_unittest.cc +++ b/base/android/library_loader/library_prefetcher_unittest.cc
@@ -22,7 +22,7 @@ const size_t kPageSize = 4096; } // namespace -TEST(NativeLibraryPrefetcherTest, DISABLED_TestPercentageOfResidentCode) { +TEST(NativeLibraryPrefetcherTest, TestPercentageOfResidentCode) { size_t length = 4 * kPageSize; auto shared_region = base::WritableSharedMemoryRegion::Create(length); ASSERT_TRUE(shared_region.IsValid());
diff --git a/build/fuchsia/linux.sdk.sha1 b/build/fuchsia/linux.sdk.sha1 index dd6c1ac..a3c2135 100644 --- a/build/fuchsia/linux.sdk.sha1 +++ b/build/fuchsia/linux.sdk.sha1
@@ -1 +1 @@ -8910186499721502448 \ No newline at end of file +8910159406036687024 \ No newline at end of file
diff --git a/build/fuchsia/mac.sdk.sha1 b/build/fuchsia/mac.sdk.sha1 index 8355f76c6..3116fec2 100644 --- a/build/fuchsia/mac.sdk.sha1 +++ b/build/fuchsia/mac.sdk.sha1
@@ -1 +1 @@ -8910186980098289872 \ No newline at end of file +8910161519679062064 \ No newline at end of file
diff --git a/cc/BUILD.gn b/cc/BUILD.gn index 786cd2b..b34ea29 100644 --- a/cc/BUILD.gn +++ b/cc/BUILD.gn
@@ -132,6 +132,8 @@ "layers/texture_layer_client.h", "layers/texture_layer_impl.cc", "layers/texture_layer_impl.h", + "layers/tile_size_calculator.cc", + "layers/tile_size_calculator.h", "layers/touch_action_region.cc", "layers/touch_action_region.h", "layers/ui_resource_layer.cc",
diff --git a/cc/benchmarks/rasterize_and_record_benchmark_impl.cc b/cc/benchmarks/rasterize_and_record_benchmark_impl.cc index a1f8b53f..261141d 100644 --- a/cc/benchmarks/rasterize_and_record_benchmark_impl.cc +++ b/cc/benchmarks/rasterize_and_record_benchmark_impl.cc
@@ -95,7 +95,7 @@ return base_client_->CreateTile(info); } - gfx::Size CalculateTileSize(const gfx::Size& content_bounds) const override { + gfx::Size CalculateTileSize(const gfx::Size& content_bounds) override { return base_client_->CalculateTileSize(content_bounds); }
diff --git a/cc/layers/picture_layer_impl.cc b/cc/layers/picture_layer_impl.cc index 1bae1c75..644a34b 100644 --- a/cc/layers/picture_layer_impl.cc +++ b/cc/layers/picture_layer_impl.cc
@@ -48,23 +48,6 @@ // tiling's scale if the desired scale is within this ratio. const float kSnapToExistingTilingRatio = 1.2f; -// Even for really wide viewports, at some point GPU raster should use -// less than 4 tiles to fill the viewport. This is set to 256 as a -// sane minimum for now, but we might want to tune this for low-end. -const int kMinHeightForGpuRasteredTile = 256; - -// When making odd-sized tiles, round them up to increase the chances -// of using the same tile size. -const int kTileRoundUp = 64; - -// Round GPU default tile sizes to a multiple of 32. This helps prevent -// rounding errors during compositing. -const int kGpuDefaultTileRoundUp = 32; - -// For performance reasons and to support compressed tile textures, tile -// width and height should be an even multiple of 4 in size. -const int kTileMinimalAlignment = 4; - // Large contents scale can cause overflow issues. Cap the ideal contents scale // by this constant, since scales larger than this are usually not correct or // their scale doesn't matter as long as it's large. Content scales usually @@ -92,55 +75,6 @@ static_cast<int>(rb - ry)); } -// This function converts the given |device_pixels_size| to the expected size -// of content which was generated to fill it at 100%. This takes into account -// the ceil operations that occur as device pixels are converted to/from DIPs -// (content size must be a whole number of DIPs). -gfx::Size ApplyDsfAdjustment(gfx::Size device_pixels_size, float dsf) { - gfx::Size content_size_in_dips = - gfx::ScaleToCeiledSize(device_pixels_size, 1.0f / dsf); - gfx::Size content_size_in_dps = - gfx::ScaleToCeiledSize(content_size_in_dips, dsf); - return content_size_in_dps; -} - -// For GPU rasterization, we pick an ideal tile size using the viewport so we -// don't need any settings. The current approach uses 4 tiles to cover the -// viewport vertically. -gfx::Size CalculateGpuTileSize(const gfx::Size& base_tile_size, - const gfx::Size& content_bounds, - const gfx::Size& max_tile_size) { - int tile_width = base_tile_size.width(); - - // Increase the height proportionally as the width decreases, and pad by our - // border texels to make the tiles exactly match the viewport. - int divisor = 4; - if (content_bounds.width() <= base_tile_size.width() / 2) - divisor = 2; - if (content_bounds.width() <= base_tile_size.width() / 4) - divisor = 1; - int tile_height = - MathUtil::UncheckedRoundUp(base_tile_size.height(), divisor) / divisor; - - // Grow default sizes to account for overlapping border texels. - tile_width += 2 * PictureLayerTiling::kBorderTexels; - tile_height += 2 * PictureLayerTiling::kBorderTexels; - - // Round GPU default tile sizes to a multiple of kGpuDefaultTileAlignment. - // This helps prevent rounding errors in our CA path. https://crbug.com/632274 - tile_width = MathUtil::UncheckedRoundUp(tile_width, kGpuDefaultTileRoundUp); - tile_height = MathUtil::UncheckedRoundUp(tile_height, kGpuDefaultTileRoundUp); - - tile_height = std::max(tile_height, kMinHeightForGpuRasteredTile); - - if (!max_tile_size.IsEmpty()) { - tile_width = std::min(tile_width, max_tile_size.width()); - tile_height = std::min(tile_height, max_tile_size.height()); - } - - return gfx::Size(tile_width, tile_height); -} - } // namespace PictureLayerImpl::PictureLayerImpl(LayerTreeImpl* tree_impl, @@ -164,7 +98,8 @@ nearest_neighbor_(false), use_transformed_rasterization_(false), is_directly_composited_image_(false), - can_use_lcd_text_(true) { + can_use_lcd_text_(true), + tile_size_calculator_(this) { layer_tree_impl()->RegisterPictureLayerImpl(this); } @@ -952,90 +887,9 @@ return false; } -gfx::Size PictureLayerImpl::CalculateTileSize( - const gfx::Size& content_bounds) const { - int max_texture_size = layer_tree_impl()->max_texture_size(); - - if (mask_type_ == Layer::LayerMaskType::SINGLE_TEXTURE_MASK) { - // Masks are not tiled, so if we can't cover the whole mask with one tile, - // we shouldn't have such a tiling at all. - DCHECK_LE(content_bounds.width(), max_texture_size); - DCHECK_LE(content_bounds.height(), max_texture_size); - return content_bounds; - } - - int default_tile_width = 0; - int default_tile_height = 0; - if (layer_tree_impl()->use_gpu_rasterization()) { - gfx::Size max_tile_size = - layer_tree_impl()->settings().max_gpu_raster_tile_size; - - // Calculate |base_tile_size based| on |gpu_raster_max_texture_size_|, - // adjusting for ceil operations that may occur due to DSF. - gfx::Size base_tile_size = ApplyDsfAdjustment( - gpu_raster_max_texture_size_, layer_tree_impl()->device_scale_factor()); - - // Set our initial size assuming a |base_tile_size| equal to our - // |viewport_size|. - gfx::Size default_tile_size = - CalculateGpuTileSize(base_tile_size, content_bounds, max_tile_size); - - // Use half-width GPU tiles when the content_width is greater than our - // calculated tile size. - if (content_bounds.width() > default_tile_size.width()) { - // Divide width by 2 and round up. - base_tile_size.set_width((base_tile_size.width() + 1) / 2); - default_tile_size = - CalculateGpuTileSize(base_tile_size, content_bounds, max_tile_size); - } - - default_tile_width = default_tile_size.width(); - default_tile_height = default_tile_size.height(); - } else { - // For CPU rasterization we use tile-size settings. - const LayerTreeSettings& settings = layer_tree_impl()->settings(); - int max_untiled_content_width = settings.max_untiled_layer_size.width(); - int max_untiled_content_height = settings.max_untiled_layer_size.height(); - default_tile_width = settings.default_tile_size.width(); - default_tile_height = settings.default_tile_size.height(); - - // If the content width is small, increase tile size vertically. - // If the content height is small, increase tile size horizontally. - // If both are less than the untiled-size, use a single tile. - if (content_bounds.width() < default_tile_width) - default_tile_height = max_untiled_content_height; - if (content_bounds.height() < default_tile_height) - default_tile_width = max_untiled_content_width; - if (content_bounds.width() < max_untiled_content_width && - content_bounds.height() < max_untiled_content_height) { - default_tile_height = max_untiled_content_height; - default_tile_width = max_untiled_content_width; - } - } - - int tile_width = default_tile_width; - int tile_height = default_tile_height; - - // Clamp the tile width/height to the content width/height to save space. - if (content_bounds.width() < default_tile_width) { - tile_width = std::min(tile_width, content_bounds.width()); - tile_width = MathUtil::UncheckedRoundUp(tile_width, kTileRoundUp); - tile_width = std::min(tile_width, default_tile_width); - } - if (content_bounds.height() < default_tile_height) { - tile_height = std::min(tile_height, content_bounds.height()); - tile_height = MathUtil::UncheckedRoundUp(tile_height, kTileRoundUp); - tile_height = std::min(tile_height, default_tile_height); - } - - // Ensure that tile width and height are properly aligned. - tile_width = MathUtil::UncheckedRoundUp(tile_width, kTileMinimalAlignment); - tile_height = MathUtil::UncheckedRoundUp(tile_height, kTileMinimalAlignment); - - // Under no circumstance should we be larger than the max texture size. - tile_width = std::min(tile_width, max_texture_size); - tile_height = std::min(tile_height, max_texture_size); - return gfx::Size(tile_width, tile_height); +gfx::Size PictureLayerImpl::CalculateTileSize(const gfx::Size& content_bounds) { + content_bounds_ = content_bounds; + return tile_size_calculator_.CalculateTileSize(); } void PictureLayerImpl::GetContentsResourceId(
diff --git a/cc/layers/picture_layer_impl.h b/cc/layers/picture_layer_impl.h index 40fab0ce..6d564e1 100644 --- a/cc/layers/picture_layer_impl.h +++ b/cc/layers/picture_layer_impl.h
@@ -15,6 +15,7 @@ #include "cc/cc_export.h" #include "cc/layers/layer.h" #include "cc/layers/layer_impl.h" +#include "cc/layers/tile_size_calculator.h" #include "cc/paint/image_id.h" #include "cc/tiles/picture_layer_tiling.h" #include "cc/tiles/picture_layer_tiling_set.h" @@ -60,7 +61,7 @@ // PictureLayerTilingClient overrides. std::unique_ptr<Tile> CreateTile(const Tile::CreateInfo& info) override; - gfx::Size CalculateTileSize(const gfx::Size& content_bounds) const override; + gfx::Size CalculateTileSize(const gfx::Size& content_bounds) override; const Region* GetPendingInvalidation() override; const PictureLayerTiling* GetPendingOrActiveTwinTiling( const PictureLayerTiling* tiling) const override; @@ -74,6 +75,11 @@ void set_gpu_raster_max_texture_size(gfx::Size gpu_raster_max_texture_size) { gpu_raster_max_texture_size_ = gpu_raster_max_texture_size; } + + gfx::Size gpu_raster_max_texture_size() { + return gpu_raster_max_texture_size_; + } + using PaintWorkletRecordMap = base::flat_map<scoped_refptr<PaintWorkletInput>, sk_sp<PaintRecord>>; void UpdateRasterSource( @@ -138,6 +144,8 @@ return paint_worklet_records_; } + gfx::Size content_bounds() { return content_bounds_; } + protected: PictureLayerImpl(LayerTreeImpl* tree_impl, int id, @@ -231,6 +239,9 @@ // asynchronously on a worklet thread, triggered from // |LayerTreeHostImpl::UpdateSyncTreeAfterCommitOrImplSideInvalidation|. PaintWorkletRecordMap paint_worklet_records_; + + gfx::Size content_bounds_; + TileSizeCalculator tile_size_calculator_; }; } // namespace cc
diff --git a/cc/layers/tile_size_calculator.cc b/cc/layers/tile_size_calculator.cc new file mode 100644 index 0000000..6c071ca --- /dev/null +++ b/cc/layers/tile_size_calculator.cc
@@ -0,0 +1,221 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "cc/layers/tile_size_calculator.h" + +#include "cc/base/math_util.h" +#include "cc/layers/picture_layer_impl.h" +#include "cc/trees/layer_tree_impl.h" + +namespace cc { +namespace { +// Even for really wide viewports, at some point GPU raster should use +// less than 4 tiles to fill the viewport. This is set to 256 as a +// sane minimum for now, but we might want to tune this for low-end. +const int kMinHeightForGpuRasteredTile = 256; + +// When making odd-sized tiles, round them up to increase the chances +// of using the same tile size. +const int kTileRoundUp = 64; + +// Round GPU default tile sizes to a multiple of 32. This helps prevent +// rounding errors during compositing. +const int kGpuDefaultTileRoundUp = 32; + +// For performance reasons and to support compressed tile textures, tile +// width and height should be an even multiple of 4 in size. +const int kTileMinimalAlignment = 4; + +// This function converts the given |device_pixels_size| to the expected size +// of content which was generated to fill it at 100%. This takes into account +// the ceil operations that occur as device pixels are converted to/from DIPs +// (content size must be a whole number of DIPs). +gfx::Size ApplyDsfAdjustment(const gfx::Size& device_pixels_size, float dsf) { + gfx::Size content_size_in_dips = + gfx::ScaleToCeiledSize(device_pixels_size, 1.0f / dsf); + gfx::Size content_size_in_dps = + gfx::ScaleToCeiledSize(content_size_in_dips, dsf); + return content_size_in_dps; +} + +// For GPU rasterization, we pick an ideal tile size using the viewport so we +// don't need any settings. The current approach uses 4 tiles to cover the +// viewport vertically. +gfx::Size CalculateGpuTileSize(const gfx::Size& base_tile_size, + const gfx::Size& content_bounds, + const gfx::Size& max_tile_size) { + int tile_width = base_tile_size.width(); + + // Increase the height proportionally as the width decreases, and pad by our + // border texels to make the tiles exactly match the viewport. + int divisor = 4; + if (content_bounds.width() <= base_tile_size.width() / 2) + divisor = 2; + if (content_bounds.width() <= base_tile_size.width() / 4) + divisor = 1; + int tile_height = + MathUtil::UncheckedRoundUp(base_tile_size.height(), divisor) / divisor; + + // Grow default sizes to account for overlapping border texels. + tile_width += 2 * PictureLayerTiling::kBorderTexels; + tile_height += 2 * PictureLayerTiling::kBorderTexels; + + // Round GPU default tile sizes to a multiple of kGpuDefaultTileAlignment. + // This helps prevent rounding errors in our CA path. https://crbug.com/632274 + tile_width = MathUtil::UncheckedRoundUp(tile_width, kGpuDefaultTileRoundUp); + tile_height = MathUtil::UncheckedRoundUp(tile_height, kGpuDefaultTileRoundUp); + + tile_height = std::max(tile_height, kMinHeightForGpuRasteredTile); + + if (!max_tile_size.IsEmpty()) { + tile_width = std::min(tile_width, max_tile_size.width()); + tile_height = std::min(tile_height, max_tile_size.height()); + } + + return gfx::Size(tile_width, tile_height); +} + +} // namespace + +// AffectingParams. +bool TileSizeCalculator::AffectingParams::operator==( + const AffectingParams& other) { + return max_texture_size == other.max_texture_size && + use_gpu_rasterization == other.use_gpu_rasterization && + device_scale_factor == other.device_scale_factor && + max_tile_size == other.max_tile_size && + gpu_raster_max_texture_size == other.gpu_raster_max_texture_size && + max_untiled_layer_size == other.max_untiled_layer_size && + default_tile_size == other.default_tile_size && + layer_content_bounds == other.layer_content_bounds; +} + +// TileSizeCalculator. +TileSizeCalculator::TileSizeCalculator(PictureLayerImpl* layer_impl) + : layer_impl_(layer_impl) {} + +bool TileSizeCalculator::IsAffectingParamsChanged() { + AffectingParams new_params = GetAffectingParams(); + + if (affecting_params_ == new_params) + return false; + + affecting_params_ = new_params; + return true; +} + +TileSizeCalculator::AffectingParams TileSizeCalculator::GetAffectingParams() { + AffectingParams params; + LayerTreeImpl* layer_tree_impl = layer_impl()->layer_tree_impl(); + params.max_texture_size = layer_tree_impl->max_texture_size(); + params.use_gpu_rasterization = layer_tree_impl->use_gpu_rasterization(); + params.max_tile_size = layer_tree_impl->settings().max_gpu_raster_tile_size; + params.gpu_raster_max_texture_size = + layer_impl()->gpu_raster_max_texture_size(); + params.device_scale_factor = layer_tree_impl->device_scale_factor(); + params.max_untiled_layer_size = + layer_tree_impl->settings().max_untiled_layer_size; + params.default_tile_size = layer_tree_impl->settings().default_tile_size; + params.layer_content_bounds = layer_impl()->content_bounds(); + return params; +} + +gfx::Size TileSizeCalculator::CalculateTileSize() { + gfx::Size content_bounds = layer_impl()->content_bounds(); + + if (layer_impl()->mask_type() == Layer::LayerMaskType::SINGLE_TEXTURE_MASK) { + // Masks are not tiled, so if we can't cover the whole mask with one tile, + // we shouldn't have such a tiling at all. + DCHECK_LE(content_bounds.width(), + layer_impl()->layer_tree_impl()->max_texture_size()); + DCHECK_LE(content_bounds.height(), + layer_impl()->layer_tree_impl()->max_texture_size()); + return content_bounds; + } + + // If |affecting_params_| is already computed and not changed, return + // pre-calculated tile size. + if (!IsAffectingParamsChanged()) + return tile_size_; + + int default_tile_width = 0; + int default_tile_height = 0; + if (affecting_params_.use_gpu_rasterization) { + gfx::Size max_tile_size = affecting_params_.max_tile_size; + + // Calculate |base_tile_size| based on |gpu_raster_max_texture_size|, + // adjusting for ceil operations that may occur due to DSF. + gfx::Size base_tile_size = + ApplyDsfAdjustment(affecting_params_.gpu_raster_max_texture_size, + affecting_params_.device_scale_factor); + + // Set our initial size assuming a |base_tile_size| equal to our + // |viewport_size|. + gfx::Size default_tile_size = + CalculateGpuTileSize(base_tile_size, content_bounds, max_tile_size); + + // Use half-width GPU tiles when the content_width is greater than our + // calculated tile size. + if (content_bounds.width() > default_tile_size.width()) { + // Divide width by 2 and round up. + base_tile_size.set_width((base_tile_size.width() + 1) / 2); + default_tile_size = + CalculateGpuTileSize(base_tile_size, content_bounds, max_tile_size); + } + + default_tile_width = default_tile_size.width(); + default_tile_height = default_tile_size.height(); + } else { + // For CPU rasterization we use tile-size settings. + int max_untiled_content_width = + affecting_params_.max_untiled_layer_size.width(); + int max_untiled_content_height = + affecting_params_.max_untiled_layer_size.height(); + default_tile_width = affecting_params_.default_tile_size.width(); + default_tile_height = affecting_params_.default_tile_size.height(); + + // If the content width is small, increase tile size vertically. + // If the content height is small, increase tile size horizontally. + // If both are less than the untiled-size, use a single tile. + if (content_bounds.width() < default_tile_width) + default_tile_height = max_untiled_content_height; + if (content_bounds.height() < default_tile_height) + default_tile_width = max_untiled_content_width; + if (content_bounds.width() < max_untiled_content_width && + content_bounds.height() < max_untiled_content_height) { + default_tile_height = max_untiled_content_height; + default_tile_width = max_untiled_content_width; + } + } + + int tile_width = default_tile_width; + int tile_height = default_tile_height; + + // Clamp the tile width/height to the content width/height to save space. + if (content_bounds.width() < default_tile_width) { + tile_width = std::min(tile_width, content_bounds.width()); + tile_width = MathUtil::UncheckedRoundUp(tile_width, kTileRoundUp); + tile_width = std::min(tile_width, default_tile_width); + } + if (content_bounds.height() < default_tile_height) { + tile_height = std::min(tile_height, content_bounds.height()); + tile_height = MathUtil::UncheckedRoundUp(tile_height, kTileRoundUp); + tile_height = std::min(tile_height, default_tile_height); + } + + // Ensure that tile width and height are properly aligned. + tile_width = MathUtil::UncheckedRoundUp(tile_width, kTileMinimalAlignment); + tile_height = MathUtil::UncheckedRoundUp(tile_height, kTileMinimalAlignment); + + // Under no circumstance should we be larger than the max texture size. + tile_width = std::min(tile_width, affecting_params_.max_texture_size); + tile_height = std::min(tile_height, affecting_params_.max_texture_size); + + // Store the calculated tile size. + tile_size_ = gfx::Size(tile_width, tile_height); + + return tile_size_; +} + +} // namespace cc
diff --git a/cc/layers/tile_size_calculator.h b/cc/layers/tile_size_calculator.h new file mode 100644 index 0000000..cd455b92 --- /dev/null +++ b/cc/layers/tile_size_calculator.h
@@ -0,0 +1,50 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CC_LAYERS_TILE_SIZE_CALCULATOR_H_ +#define CC_LAYERS_TILE_SIZE_CALCULATOR_H_ + +#include "cc/cc_export.h" +#include "ui/gfx/geometry/size.h" + +namespace cc { + +class PictureLayerImpl; + +// This class calculates the tile size only when the |affecting_params_| +// or |content_bounds_| is changed. +class CC_EXPORT TileSizeCalculator { + public: + explicit TileSizeCalculator(PictureLayerImpl* layer_impl); + + gfx::Size CalculateTileSize(); + + private: + struct AffectingParams { + int max_texture_size = 0; + bool use_gpu_rasterization = false; + float device_scale_factor = 0.0f; + gfx::Size max_tile_size; + gfx::Size gpu_raster_max_texture_size; + gfx::Size max_untiled_layer_size; + gfx::Size default_tile_size; + gfx::Size layer_content_bounds; + + bool operator==(const AffectingParams& other); + }; + + PictureLayerImpl* layer_impl() const { return layer_impl_; } + AffectingParams GetAffectingParams(); + bool IsAffectingParamsChanged(); + + PictureLayerImpl* layer_impl_; + + AffectingParams affecting_params_; + + gfx::Size tile_size_; +}; + +} // namespace cc + +#endif // CC_LAYERS_TILE_SIZE_CALCULATOR_H_
diff --git a/cc/test/fake_picture_layer_impl.cc b/cc/test/fake_picture_layer_impl.cc index 73f05851..d6b54221 100644 --- a/cc/test/fake_picture_layer_impl.cc +++ b/cc/test/fake_picture_layer_impl.cc
@@ -60,7 +60,7 @@ } gfx::Size FakePictureLayerImpl::CalculateTileSize( - const gfx::Size& content_bounds) const { + const gfx::Size& content_bounds) { if (fixed_tile_size_.IsEmpty()) { return PictureLayerImpl::CalculateTileSize(content_bounds); }
diff --git a/cc/test/fake_picture_layer_impl.h b/cc/test/fake_picture_layer_impl.h index bf1d81ec..703821cd 100644 --- a/cc/test/fake_picture_layer_impl.h +++ b/cc/test/fake_picture_layer_impl.h
@@ -85,7 +85,7 @@ void PushPropertiesTo(LayerImpl* layer_impl) override; void AppendQuads(viz::RenderPass* render_pass, AppendQuadsData* append_quads_data) override; - gfx::Size CalculateTileSize(const gfx::Size& content_bounds) const override; + gfx::Size CalculateTileSize(const gfx::Size& content_bounds) override; void DidBecomeActive() override; size_t did_become_active_call_count() {
diff --git a/cc/test/fake_picture_layer_tiling_client.cc b/cc/test/fake_picture_layer_tiling_client.cc index d2637665..7acb267e 100644 --- a/cc/test/fake_picture_layer_tiling_client.cc +++ b/cc/test/fake_picture_layer_tiling_client.cc
@@ -49,7 +49,7 @@ } gfx::Size FakePictureLayerTilingClient::CalculateTileSize( - const gfx::Size& /* content_bounds */) const { + const gfx::Size& /* content_bounds */) { return tile_size_; }
diff --git a/cc/test/fake_picture_layer_tiling_client.h b/cc/test/fake_picture_layer_tiling_client.h index aa38db905..2ebdf1d 100644 --- a/cc/test/fake_picture_layer_tiling_client.h +++ b/cc/test/fake_picture_layer_tiling_client.h
@@ -29,7 +29,7 @@ // PictureLayerTilingClient implementation. std::unique_ptr<Tile> CreateTile(const Tile::CreateInfo& info) override; - gfx::Size CalculateTileSize(const gfx::Size& content_bounds) const override; + gfx::Size CalculateTileSize(const gfx::Size& content_bounds) override; bool HasValidTilePriorities() const override; void SetTileSize(const gfx::Size& tile_size);
diff --git a/cc/tiles/picture_layer_tiling.h b/cc/tiles/picture_layer_tiling.h index 4f66d99..417fb14 100644 --- a/cc/tiles/picture_layer_tiling.h +++ b/cc/tiles/picture_layer_tiling.h
@@ -40,8 +40,7 @@ // Create a tile at the given content_rect (in the contents scale of the // tiling) This might return null if the client cannot create such a tile. virtual std::unique_ptr<Tile> CreateTile(const Tile::CreateInfo& info) = 0; - virtual gfx::Size CalculateTileSize( - const gfx::Size& content_bounds) const = 0; + virtual gfx::Size CalculateTileSize(const gfx::Size& content_bounds) = 0; // This invalidation region defines the area (if any, it can by null) that // tiles can not be shared between pending and active trees. virtual const Region* GetPendingInvalidation() = 0;
diff --git a/chrome/BUILD.gn b/chrome/BUILD.gn index 329983c..1516c9b2 100644 --- a/chrome/BUILD.gn +++ b/chrome/BUILD.gn
@@ -170,7 +170,7 @@ "$root_out_dir/locales/en-US.pak", "$root_out_dir/locales/fr.pak", ] - if (enable_hidpi || enable_mus) { + if (enable_hidpi) { data += [ "$root_out_dir/chrome_200_percent.pak" ] } } @@ -373,20 +373,6 @@ sources += [ "app/chrome_exe_main_aura.cc" ] } } - - # TODO(jonross): remove this once telemetry can differentiate between linux - # and linux chromiumos. - if (enable_mus) { - chrome_binary("chrome_test") { - # Note that the output name needs to end with "chrome", because that's - # what telemetry test-runner expects. - output_name = "test_chrome" - sources = [] - if (!is_win && use_aura) { - sources += [ "app/chrome_exe_main_aura.cc" ] - } - } - } } # !is_android && !is_mac if (is_win) {
diff --git a/chrome/VERSION b/chrome/VERSION index 128a7e8..0edb812 100644 --- a/chrome/VERSION +++ b/chrome/VERSION
@@ -1,4 +1,4 @@ MAJOR=77 MINOR=0 -BUILD=3831 +BUILD=3832 PATCH=0
diff --git a/chrome/android/features/autofill_assistant/BUILD.gn b/chrome/android/features/autofill_assistant/BUILD.gn index 8e39e99..6f17ceb 100644 --- a/chrome/android/features/autofill_assistant/BUILD.gn +++ b/chrome/android/features/autofill_assistant/BUILD.gn
@@ -65,6 +65,7 @@ java_files = [ "java/src/org/chromium/chrome/browser/autofill_assistant/AbstractListObserver.java", "java/src/org/chromium/chrome/browser/autofill_assistant/AssistantBottomBarCoordinator.java", + "java/src/org/chromium/chrome/browser/autofill_assistant/AssistantBottomSheetContent.java", "java/src/org/chromium/chrome/browser/autofill_assistant/AssistantCoordinator.java", "java/src/org/chromium/chrome/browser/autofill_assistant/AssistantKeyboardCoordinator.java", "java/src/org/chromium/chrome/browser/autofill_assistant/AssistantModel.java", @@ -75,6 +76,7 @@ "java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiController.java", "java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantClient.java", "java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantModuleEntryFactoryImpl.java", + "java/src/org/chromium/chrome/browser/autofill_assistant/BottomSheetUtils.java", "java/src/org/chromium/chrome/browser/autofill_assistant/EditDistance.java", "java/src/org/chromium/chrome/browser/autofill_assistant/FeedbackContext.java", "java/src/org/chromium/chrome/browser/autofill_assistant/SizeListenableLinearLayout.java",
diff --git a/chrome/android/features/autofill_assistant/java/res/layout/autofill_assistant_bottom_sheet_content.xml b/chrome/android/features/autofill_assistant/java/res/layout/autofill_assistant_bottom_sheet_content.xml index 40e8182..1496545 100644 --- a/chrome/android/features/autofill_assistant/java/res/layout/autofill_assistant_bottom_sheet_content.xml +++ b/chrome/android/features/autofill_assistant/java/res/layout/autofill_assistant_bottom_sheet_content.xml
@@ -2,7 +2,7 @@ <!-- Copyright 2018 The Chromium Authors. All rights reserved. Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. --> -<org.chromium.chrome.browser.autofill_assistant.SizeListenableLinearLayout +<LinearLayout xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/autofill_assistant" @@ -62,4 +62,4 @@ android:clipChildren="false" android:clipToPadding="false" /> </org.chromium.chrome.browser.widget.FadingEdgeScrollView> -</org.chromium.chrome.browser.autofill_assistant.SizeListenableLinearLayout> +</LinearLayout>
diff --git a/chrome/android/features/autofill_assistant/java/res/layout/autofill_assistant_onboarding.xml b/chrome/android/features/autofill_assistant/java/res/layout/autofill_assistant_onboarding.xml index 95df51e..8ff7526 100644 --- a/chrome/android/features/autofill_assistant/java/res/layout/autofill_assistant_onboarding.xml +++ b/chrome/android/features/autofill_assistant/java/res/layout/autofill_assistant_onboarding.xml
@@ -3,124 +3,127 @@ Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. --> -<LinearLayout +<ScrollView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" - android:id="@+id/assistant_onboarding" android:layout_width="match_parent" - android:layout_height="wrap_content" - android:paddingTop="12dp" - android:paddingBottom="14dp" - android:paddingStart="24dp" - android:paddingEnd="24dp" - android:gravity="center_horizontal" - android:orientation="vertical"> - - <!-- Image background --> - <ImageView - android:id="@+id/onboarding_image" - tools:ignore="contentDescription" - android:layout_width="250dp" - android:layout_height="wrap_content" - android:scaleType="centerCrop" - android:src="@drawable/autofill_assistant_onboarding_bg" - android:layout_marginTop="12dp" /> - - <!-- "Try Google Assistant in Chrome" --> - <ImageView - android:id="@+id/onboarding_try_assistant" - tools:ignore="contentDescription" - android:layout_width="185dp" - android:layout_height="wrap_content" - android:layout_marginTop="16dp" - android:src="@drawable/autofill_assistant_onboarding_try" /> - - <!-- Subtitle (e.g., 'Google Assistant saves you time...')--> + android:layout_height="wrap_content"> <LinearLayout android:layout_width="match_parent" - android:layout_height="wrap_content"> - <Space - android:layout_width="0dp" - android:layout_height="1dp" - android:layout_weight="1"/> - <!-- The subtitle takes 4/6 of the screen width. --> - <TextView - android:id="@+id/onboarding_subtitle" - android:layout_width="0dp" - android:layout_height="wrap_content" - android:layout_weight="4" - android:layout_marginTop="24dp" - android:textAppearance="@style/TextAppearance.AssistantBlackBody" - android:gravity="center_horizontal" - android:text="@string/autofill_assistant_init_message" /> - <Space - android:layout_width="0dp" - android:layout_height="1dp" - android:layout_weight="1"/> - </LinearLayout> - - <!-- Separator --> - <LinearLayout - android:id="@+id/onboarding_separator" - android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_marginTop="24dp" + android:paddingTop="12dp" + android:paddingBottom="14dp" + android:paddingStart="24dp" + android:paddingEnd="24dp" android:gravity="center_horizontal" - android:orientation="horizontal" - android:weightSum="1.0"> - <View style="@style/HorizontalDivider" - android:layout_width="0dp" - android:layout_height="1dp" - android:layout_weight="0.33"/> - </LinearLayout> - <Space android:layout_width="0dp" android:layout_height="24dp"/> + android:orientation="vertical"> - <!-- Terms and Conditions message and link --> - <LinearLayout - android:layout_height="wrap_content" + <!-- Image background --> + <ImageView + android:id="@+id/onboarding_image" + tools:ignore="contentDescription" + android:layout_width="250dp" + android:layout_height="wrap_content" + android:scaleType="centerCrop" + android:src="@drawable/autofill_assistant_onboarding_bg" + android:layout_marginTop="12dp" /> + + <!-- "Try Google Assistant in Chrome" --> + <ImageView + android:id="@+id/onboarding_try_assistant" + tools:ignore="contentDescription" + android:layout_width="185dp" + android:layout_height="wrap_content" + android:layout_marginTop="16dp" + android:src="@drawable/autofill_assistant_onboarding_try" /> + + <!-- Subtitle (e.g., 'Google Assistant saves you time...')--> + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content"> + <Space + android:layout_width="0dp" + android:layout_height="1dp" + android:layout_weight="1"/> + <!-- The subtitle takes 4/6 of the screen width. --> + <TextView + android:id="@+id/onboarding_subtitle" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_weight="4" + android:layout_marginTop="24dp" + android:textAppearance="@style/TextAppearance.AssistantBlackBody" + android:gravity="center_horizontal" + android:text="@string/autofill_assistant_init_message" /> + <Space + android:layout_width="0dp" + android:layout_height="1dp" + android:layout_weight="1"/> + </LinearLayout> + + <!-- Separator --> + <LinearLayout + android:id="@+id/onboarding_separator" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginTop="24dp" + android:gravity="center_horizontal" + android:orientation="horizontal" + android:weightSum="1.0"> + <View style="@style/HorizontalDivider" + android:layout_width="0dp" + android:layout_height="1dp" + android:layout_weight="0.33"/> + </LinearLayout> + <Space android:layout_width="0dp" android:layout_height="24dp"/> + + <!-- Terms and Conditions message and link --> + <LinearLayout + android:layout_height="wrap_content" + android:layout_width="match_parent" + android:paddingBottom="9dp"> + <TextView + android:id="@+id/google_terms_message" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_margin="0dp" + android:layout_gravity="center" + android:textAppearance="@style/TextAppearance.AssistantBlackCaption" + android:text="@string/autofill_assistant_google_terms_description" /> + </LinearLayout> + + <!-- Layout for the buttons --> + <Space android:layout_width="0dp" android:layout_height="18dp"/> + <LinearLayout android:layout_width="match_parent" - android:paddingBottom="9dp"> - <TextView - android:id="@+id/google_terms_message" + android:layout_height="wrap_content" + android:gravity="bottom|center" + android:orientation="horizontal"> + + <!-- 'No' button --> + <org.chromium.ui.widget.ButtonCompat + android:id="@+id/button_init_not_ok" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_margin="0dp" - android:layout_gravity="center" - android:textAppearance="@style/TextAppearance.AssistantBlackCaption" - android:text="@string/autofill_assistant_google_terms_description" /> + android:singleLine="true" + android:gravity="center" + android:text="@string/cancel" + style="@style/TextButton" /> + + <Space + android:layout_weight="1" + android:layout_width="0dp" + android:layout_height="match_parent"/> + + <!-- 'Yes' button --> + <org.chromium.ui.widget.ButtonCompat + android:id="@+id/button_init_ok" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:singleLine="true" + android:gravity="center" + android:text="@string/init_ok" + style="FilledButton.Flat" /> + </LinearLayout> </LinearLayout> - - <!-- Layout for the buttons --> - <Space android:layout_width="0dp" android:layout_height="18dp"/> - <LinearLayout - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:gravity="bottom|center" - android:orientation="horizontal"> - - <!-- 'No' button --> - <org.chromium.ui.widget.ButtonCompat - android:id="@+id/button_init_not_ok" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:singleLine="true" - android:gravity="center" - android:text="@string/cancel" - style="@style/TextButton" /> - - <Space - android:layout_weight="1" - android:layout_width="0dp" - android:layout_height="match_parent"/> - - <!-- 'Yes' button --> - <org.chromium.ui.widget.ButtonCompat - android:id="@+id/button_init_ok" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:singleLine="true" - android:gravity="center" - android:text="@string/init_ok" - style="@style/FilledButton.Flat" /> - </LinearLayout> -</LinearLayout> \ No newline at end of file +</ScrollView> \ No newline at end of file
diff --git a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AssistantBottomBarCoordinator.java b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AssistantBottomBarCoordinator.java index 8761ac5..1396985 100644 --- a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AssistantBottomBarCoordinator.java +++ b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AssistantBottomBarCoordinator.java
@@ -4,7 +4,6 @@ package org.chromium.chrome.browser.autofill_assistant; -import android.content.Context; import android.support.annotation.Nullable; import android.transition.ChangeBounds; import android.transition.Fade; @@ -16,7 +15,6 @@ import android.widget.LinearLayout; import android.widget.ScrollView; -import org.chromium.base.Callback; import org.chromium.base.ObserverList; import org.chromium.base.VisibleForTesting; import org.chromium.chrome.autofill_assistant.R; @@ -30,8 +28,6 @@ import org.chromium.chrome.browser.autofill_assistant.header.AssistantHeaderCoordinator; import org.chromium.chrome.browser.autofill_assistant.header.AssistantHeaderModel; import org.chromium.chrome.browser.autofill_assistant.infobox.AssistantInfoBoxCoordinator; -import org.chromium.chrome.browser.autofill_assistant.overlay.AssistantOverlayModel; -import org.chromium.chrome.browser.autofill_assistant.overlay.AssistantOverlayState; import org.chromium.chrome.browser.autofill_assistant.payment.AssistantPaymentRequestCoordinator; import org.chromium.chrome.browser.autofill_assistant.payment.AssistantPaymentRequestModel; import org.chromium.chrome.browser.compositor.CompositorViewResizer; @@ -52,6 +48,7 @@ private final AssistantModel mModel; private final BottomSheetController mBottomSheetController; private final AssistantBottomSheetContent mContent; + private final ScrollView mScrollableContent; // Child coordinators. private final AssistantHeaderCoordinator mHeaderCoordinator; @@ -79,7 +76,22 @@ ChromeActivity activity, AssistantModel model, BottomSheetController controller) { mModel = model; mBottomSheetController = controller; - mContent = new AssistantBottomSheetContent(activity); + + BottomSheet.BottomSheetContent currentSheetContent = + controller.getBottomSheet().getCurrentSheetContent(); + if (currentSheetContent instanceof AssistantBottomSheetContent) { + mContent = (AssistantBottomSheetContent) currentSheetContent; + } else { + mContent = new AssistantBottomSheetContent(activity); + } + + // Replace or set the content to the actual Autofill Assistant views. + ViewGroup bottomBarView = (ViewGroup) LayoutInflater.from(activity).inflate( + R.layout.autofill_assistant_bottom_sheet_content, /* root= */ null); + mScrollableContent = bottomBarView.findViewById(R.id.scrollable_content); + ViewGroup scrollableContentContainer = + mScrollableContent.findViewById(R.id.scrollable_content_container); + mContent.setContent(bottomBarView, mScrollableContent); // Set up animations. We need to setup them before initializing the child coordinators as we // want our observers to be triggered before the coordinators/view binders observers. @@ -90,8 +102,8 @@ setupAnimations(model, rootView); // Instantiate child components. - mHeaderCoordinator = new AssistantHeaderCoordinator( - activity, mContent.mBottomBarView, model.getHeaderModel()); + mHeaderCoordinator = + new AssistantHeaderCoordinator(activity, bottomBarView, model.getHeaderModel()); mInfoBoxCoordinator = new AssistantInfoBoxCoordinator(activity, model.getInfoBoxModel()); mDetailsCoordinator = new AssistantDetailsCoordinator(activity, model.getDetailsModel()); mPaymentRequestCoordinator = @@ -103,7 +115,7 @@ new AssistantActionsCarouselCoordinator(activity, model.getActionsModel()); BottomSheet bottomSheet = controller.getBottomSheet(); mPeekHeightCoordinator = new AssistantPeekHeightCoordinator(activity, this, bottomSheet, - mContent.mToolbarView, mContent.mBottomBarView, mSuggestionsCoordinator.getView(), + mContent.getToolbarView(), bottomBarView, mSuggestionsCoordinator.getView(), mActionsCoordinator.getView(), AssistantPeekHeightCoordinator.PeekMode.HANDLE); // We don't want to animate the carousels children views as they are already animated by the @@ -113,12 +125,12 @@ // Add child views to bottom bar container. We put all child views in the scrollable // container, except the actions and suggestions. - mContent.mScrollableContentContainer.addView(mInfoBoxCoordinator.getView()); - mContent.mScrollableContentContainer.addView(mDetailsCoordinator.getView()); - mContent.mScrollableContentContainer.addView(mPaymentRequestCoordinator.getView()); - mContent.mScrollableContentContainer.addView(mFormCoordinator.getView()); - mContent.mBottomBarView.addView(mSuggestionsCoordinator.getView()); - mContent.mBottomBarView.addView(mActionsCoordinator.getView()); + scrollableContentContainer.addView(mInfoBoxCoordinator.getView()); + scrollableContentContainer.addView(mDetailsCoordinator.getView()); + scrollableContentContainer.addView(mPaymentRequestCoordinator.getView()); + scrollableContentContainer.addView(mFormCoordinator.getView()); + bottomBarView.addView(mSuggestionsCoordinator.getView()); + bottomBarView.addView(mActionsCoordinator.getView()); // Set children top margins to have a spacing between them. int childSpacing = activity.getResources().getDimensionPixelSize( @@ -142,31 +154,9 @@ setHorizontalMargins(mDetailsCoordinator.getView()); setHorizontalMargins(mFormCoordinator.getView()); - View bottomSheetContainer = bottomSheet.findViewById(R.id.bottom_sheet_content); bottomSheet.addObserver(new EmptyBottomSheetObserver() { @Override - public void onSheetClosed(int reason) { - // When scrolling with y < peekHeight, the BottomSheet will make the content - // invisible. This is a workaround to prevent that as our toolbar is transparent and - // we want to sheet content to stay visible. - if ((bottomSheet.getSheetState() == BottomSheet.SheetState.SCROLLING - || bottomSheet.getSheetState() == BottomSheet.SheetState.PEEK) - && bottomSheet.getCurrentSheetContent() == mContent - && model.get(AssistantModel.VISIBLE)) { - bottomSheetContainer.setVisibility(View.VISIBLE); - } - } - - @Override public void onSheetStateChanged(int newState) { - if (newState == BottomSheet.SheetState.PEEK - && bottomSheet.getCurrentSheetContent() == mContent) { - // When in the peek state, the BottomSheet hides the content view. We override - // that because we artificially increase the height of the transparent toolbar - // to show parts of the content view. - bottomSheetContainer.setVisibility(View.VISIBLE); - } - maybeShowHeaderChip(); } @@ -200,13 +190,13 @@ // (i.e. details shadow and carousel cancel button shadow) but we need to clip the children // when the ScrollView is scrollable, otherwise scrolled content will overlap with the // header and carousels. - ScrollView scrollView = mContent.mScrollableContent; + ScrollView scrollView = mScrollableContent; scrollView.addOnLayoutChangeListener( (v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> { boolean canScroll = scrollView.canScrollVertically(-1) || scrollView.canScrollVertically(1); - mContent.mScrollableContent.setClipChildren(canScroll); - mContent.mBottomBarView.setClipChildren(canScroll); + mScrollableContent.setClipChildren(canScroll); + bottomBarView.setClipChildren(canScroll); }); } @@ -264,38 +254,9 @@ mHeaderCoordinator.destroy(); } - /** - * Show the onboarding screen and call {@code callback} with {@code true} if the user agreed to - * proceed, false otherwise. - */ - public void showOnboarding(String experimentIds, Callback<Boolean> callback) { - mModel.getHeaderModel().set(AssistantHeaderModel.VISIBLE, false); - - // Show overlay to prevent user from interacting with the page during onboarding. - mModel.getOverlayModel().set(AssistantOverlayModel.STATE, AssistantOverlayState.FULL); - - AssistantOnboardingCoordinator.show(experimentIds, mContent.mBottomBarView.getContext(), - mContent.mScrollableContentContainer, accepted -> { - if (!accepted) { - callback.onResult(false); - return; - } - - mModel.getHeaderModel().set(AssistantHeaderModel.VISIBLE, true); - - // Hide overlay. - mModel.getOverlayModel().set( - AssistantOverlayModel.STATE, AssistantOverlayState.HIDDEN); - - callback.onResult(true); - }); - } - /** Request showing the Assistant bottom bar view and expand the sheet. */ public void showAndExpand() { - if (mBottomSheetController.requestShowContent(mContent, /* animate= */ true)) { - mBottomSheetController.expandSheet(); - } + BottomSheetUtils.showContentAndExpand(mBottomSheetController, mContent); } /** Hide the Assistant bottom bar view. */ @@ -318,7 +279,7 @@ @Override public void setShowOnlyCarousels(boolean showOnlyCarousels) { - mContent.mScrollableContent.setVisibility(showOnlyCarousels ? View.GONE : View.VISIBLE); + mScrollableContent.setVisibility(showOnlyCarousels ? View.GONE : View.VISIBLE); } @Override @@ -396,102 +357,4 @@ public void removeObserver(Observer observer) { mSizeObservers.removeObserver(observer); } - - // TODO(crbug.com/806868): Move this class at the top of the file once it is a static class. - private static class AssistantBottomSheetContent implements BottomSheet.BottomSheetContent { - private final ViewGroup mToolbarView; - private final SizeListenableLinearLayout mBottomBarView; - private final ScrollView mScrollableContent; - private final LinearLayout mScrollableContentContainer; - - public AssistantBottomSheetContent(Context context) { - mToolbarView = (ViewGroup) LayoutInflater.from(context).inflate( - R.layout.autofill_assistant_bottom_sheet_toolbar, /* root= */ null); - mBottomBarView = (SizeListenableLinearLayout) LayoutInflater.from(context).inflate( - R.layout.autofill_assistant_bottom_sheet_content, /* root= */ null); - mScrollableContent = mBottomBarView.findViewById(R.id.scrollable_content); - mScrollableContentContainer = - mScrollableContent.findViewById(R.id.scrollable_content_container); - } - - @Override - public View getContentView() { - return mBottomBarView; - } - - @Nullable - @Override - public View getToolbarView() { - return mToolbarView; - } - - @Override - public int getVerticalScrollOffset() { - return mScrollableContent.getScrollY(); - } - - @Override - public void destroy() {} - - @Override - public int getPriority() { - return BottomSheet.ContentPriority.HIGH; - } - - @Override - public boolean swipeToDismissEnabled() { - return false; - } - - @Override - public boolean isPeekStateEnabled() { - return true; - } - - @Override - public boolean wrapContentEnabled() { - return true; - } - - @Override - public boolean hasCustomLifecycle() { - return true; - } - - @Override - public boolean hasCustomScrimLifecycle() { - return true; - } - - @Override - public boolean setContentSizeListener(@Nullable BottomSheet.ContentSizeListener listener) { - mBottomBarView.setContentSizeListener(listener); - return true; - } - - @Override - public boolean hideOnScroll() { - return false; - } - - @Override - public int getSheetContentDescriptionStringId() { - return R.string.autofill_assistant_sheet_content_description; - } - - @Override - public int getSheetHalfHeightAccessibilityStringId() { - return R.string.autofill_assistant_sheet_half_height; - } - - @Override - public int getSheetFullHeightAccessibilityStringId() { - return R.string.autofill_assistant_sheet_full_height; - } - - @Override - public int getSheetClosedAccessibilityStringId() { - return R.string.autofill_assistant_sheet_closed; - } - } }
diff --git a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AssistantBottomSheetContent.java b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AssistantBottomSheetContent.java new file mode 100644 index 0000000..bbfb174 --- /dev/null +++ b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AssistantBottomSheetContent.java
@@ -0,0 +1,130 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.autofill_assistant; + +import android.content.Context; +import android.support.annotation.Nullable; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ScrollView; + +import org.chromium.chrome.autofill_assistant.R; +import org.chromium.chrome.browser.widget.bottomsheet.BottomSheet; + +/** + * The {@link BottomSheet.BottomSheetContent} for the Autofill Assistant. It supports notifying the + * BottomSheet when its size changes and allows to dynamically set its scrollable content (in + * practice, this allows to replace the onboarding by the actual Autofill Assistant content). + */ +class AssistantBottomSheetContent implements BottomSheet.BottomSheetContent { + private final View mToolbarView; + private final SizeListenableLinearLayout mContentView; + @Nullable + private ScrollView mContentScrollableView; + + public AssistantBottomSheetContent(Context context) { + mToolbarView = LayoutInflater.from(context).inflate( + R.layout.autofill_assistant_bottom_sheet_toolbar, /* root= */ null); + mContentView = new SizeListenableLinearLayout(context); + mContentView.setLayoutParams(new ViewGroup.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)); + } + + public void setContent(View content, ScrollView scrollableView) { + if (mContentView.getChildCount() > 0) { + mContentView.removeAllViews(); + } + + content.setLayoutParams(new ViewGroup.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)); + mContentView.addView(content); + mContentScrollableView = scrollableView; + } + + @Override + public View getContentView() { + return mContentView; + } + + @Nullable + @Override + public View getToolbarView() { + return mToolbarView; + } + + @Override + public int getVerticalScrollOffset() { + if (mContentScrollableView != null) { + return mContentScrollableView.getScrollY(); + } + + return 0; + } + + @Override + public boolean setContentSizeListener(@Nullable BottomSheet.ContentSizeListener listener) { + mContentView.setContentSizeListener(listener); + return true; + } + + @Override + public void destroy() {} + + @Override + public int getPriority() { + return BottomSheet.ContentPriority.HIGH; + } + + @Override + public boolean swipeToDismissEnabled() { + return false; + } + + @Override + public boolean isPeekStateEnabled() { + return true; + } + + @Override + public boolean wrapContentEnabled() { + return true; + } + + @Override + public boolean hasCustomLifecycle() { + return true; + } + + @Override + public boolean hasCustomScrimLifecycle() { + return true; + } + + @Override + public boolean hideOnScroll() { + return false; + } + + @Override + public int getSheetContentDescriptionStringId() { + return R.string.autofill_assistant_sheet_content_description; + } + + @Override + public int getSheetHalfHeightAccessibilityStringId() { + return R.string.autofill_assistant_sheet_half_height; + } + + @Override + public int getSheetFullHeightAccessibilityStringId() { + return R.string.autofill_assistant_sheet_full_height; + } + + @Override + public int getSheetClosedAccessibilityStringId() { + return R.string.autofill_assistant_sheet_closed; + } +}
diff --git a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AssistantCoordinator.java b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AssistantCoordinator.java index f8db8e8..11fc9d43 100644 --- a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AssistantCoordinator.java +++ b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AssistantCoordinator.java
@@ -4,8 +4,9 @@ package org.chromium.chrome.browser.autofill_assistant; +import android.support.annotation.Nullable; + import org.chromium.chrome.browser.ChromeActivity; -import org.chromium.chrome.browser.autofill_assistant.metrics.DropOutReason; import org.chromium.chrome.browser.autofill_assistant.overlay.AssistantOverlayCoordinator; import org.chromium.chrome.browser.help.HelpAndFeedback; import org.chromium.chrome.browser.profiles.Profile; @@ -16,35 +17,31 @@ * sub-components and shutting down the Autofill Assistant. */ class AssistantCoordinator { - interface Delegate { - /** Completely stop the Autofill Assistant. */ - void stop(@DropOutReason int reason); - - // TODO(crbug.com/806868): Move onboarding and snackbar out of this class and remove the - // delegate. - } - private static final String FEEDBACK_CATEGORY_TAG = "com.android.chrome.USER_INITIATED_FEEDBACK_REPORT_AUTOFILL_ASSISTANT"; private final ChromeActivity mActivity; - private final Delegate mDelegate; private final AssistantModel mModel; private AssistantBottomBarCoordinator mBottomBarCoordinator; private final AssistantKeyboardCoordinator mKeyboardCoordinator; private final AssistantOverlayCoordinator mOverlayCoordinator; - AssistantCoordinator( - ChromeActivity activity, Delegate delegate, BottomSheetController controller) { + AssistantCoordinator(ChromeActivity activity, BottomSheetController controller, + @Nullable AssistantOverlayCoordinator overlayCoordinator) { mActivity = activity; - mDelegate = delegate; - mModel = new AssistantModel(); - // Instantiate child components. + if (overlayCoordinator != null) { + mModel = new AssistantModel(overlayCoordinator.getModel()); + mOverlayCoordinator = overlayCoordinator; + } else { + mModel = new AssistantModel(); + mOverlayCoordinator = + new AssistantOverlayCoordinator(activity, mModel.getOverlayModel()); + } + mBottomBarCoordinator = new AssistantBottomBarCoordinator(activity, mModel, controller); mKeyboardCoordinator = new AssistantKeyboardCoordinator(activity, mModel); - mOverlayCoordinator = new AssistantOverlayCoordinator(activity, mModel.getOverlayModel()); activity.getCompositorViewHolder().addCompositorViewResizer(mBottomBarCoordinator); mModel.setVisible(true); @@ -63,20 +60,6 @@ } /** - * Show the onboarding screen and call {@code onAccept} if the user agreed to proceed, shutdown - * otherwise. - */ - public void showOnboarding(String experimentIds, Runnable onAccept) { - mBottomBarCoordinator.showOnboarding(experimentIds, accepted -> { - if (accepted) { - onAccept.run(); - } else { - mDelegate.stop(DropOutReason.DECLINED); - } - }); - } - - /** * Get the model representing the current state of the UI. */
diff --git a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AssistantModel.java b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AssistantModel.java index 7b89cd5..064ee59a 100644 --- a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AssistantModel.java +++ b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AssistantModel.java
@@ -25,7 +25,7 @@ new WritableBooleanPropertyKey(); static final WritableBooleanPropertyKey VISIBLE = new WritableBooleanPropertyKey(); - private final AssistantOverlayModel mOverlayModel = new AssistantOverlayModel(); + private final AssistantOverlayModel mOverlayModel; private final AssistantHeaderModel mHeaderModel = new AssistantHeaderModel(); private final AssistantDetailsModel mDetailsModel = new AssistantDetailsModel(); private final AssistantInfoBoxModel mInfoBoxModel = new AssistantInfoBoxModel(); @@ -36,7 +36,12 @@ private final AssistantCarouselModel mActionsModel = new AssistantCarouselModel(); AssistantModel() { + this(new AssistantOverlayModel()); + } + + AssistantModel(AssistantOverlayModel overlayModel) { super(ALLOW_SOFT_KEYBOARD, VISIBLE, ALLOW_TALKBACK_ON_WEBSITE); + mOverlayModel = overlayModel; } @CalledByNative
diff --git a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AssistantOnboardingCoordinator.java b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AssistantOnboardingCoordinator.java index ddd3211..6ceb41d 100644 --- a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AssistantOnboardingCoordinator.java +++ b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AssistantOnboardingCoordinator.java
@@ -9,12 +9,11 @@ import android.text.method.LinkMovementMethod; import android.view.LayoutInflater; import android.view.View; -import android.view.ViewGroup; +import android.widget.ScrollView; import android.widget.TextView; import org.chromium.base.Callback; import org.chromium.chrome.autofill_assistant.R; -import org.chromium.chrome.browser.autofill_assistant.metrics.OnBoarding; import org.chromium.chrome.browser.customtabs.CustomTabActivity; import org.chromium.ui.text.NoUnderlineClickableSpan; import org.chromium.ui.text.SpanApplier; @@ -29,15 +28,14 @@ private static final String SMALL_ONBOARDING_EXPERIMENT_ID = "4257013"; /** - * Shows the onboarding screen and returns whether we should proceed. + * Set the content of {@code bottomSheetContent} to be the Autofill Assistant onboarding. {@code + * callback} will be called with true or false when the user accepts or cancels the onboarding + * (respectively). */ - static View show( - String experimentIds, Context context, ViewGroup root, Callback<Boolean> callback) { - AutofillAssistantMetrics.recordOnBoarding(OnBoarding.OB_SHOWN); - - View initView = LayoutInflater.from(context) - .inflate(R.layout.autofill_assistant_onboarding, root) - .findViewById(R.id.assistant_onboarding); + static void setOnboardingContent(String experimentIds, Context context, + AssistantBottomSheetContent bottomSheetContent, Callback<Boolean> callback) { + ScrollView initView = (ScrollView) LayoutInflater.from(context).inflate( + R.layout.autofill_assistant_onboarding, /* root= */ null); TextView termsTextView = initView.findViewById(R.id.google_terms_message); String termsString = context.getApplicationContext().getString( @@ -57,9 +55,9 @@ initView.setFocusable(true); initView.findViewById(R.id.button_init_ok) - .setOnClickListener(unusedView -> onClicked(true, root, initView, callback)); + .setOnClickListener(unusedView -> onClicked(true, callback)); initView.findViewById(R.id.button_init_not_ok) - .setOnClickListener(unusedView -> onClicked(false, root, initView, callback)); + .setOnClickListener(unusedView -> onClicked(false, callback)); initView.announceForAccessibility( context.getString(R.string.autofill_assistant_first_run_accessibility)); @@ -70,22 +68,15 @@ hide(initView, R.id.onboarding_separator); } - return initView; + bottomSheetContent.setContent(initView, initView); } private static void hide(View root, int resId) { root.findViewById(resId).setVisibility(View.GONE); } - private static void onClicked( - boolean accept, ViewGroup root, View initView, Callback<Boolean> callback) { + private static void onClicked(boolean accept, Callback<Boolean> callback) { AutofillAssistantPreferencesUtil.setInitialPreferences(accept); - root.removeView(initView); - if (accept) { - AutofillAssistantMetrics.recordOnBoarding(OnBoarding.OB_ACCEPTED); - } else { - AutofillAssistantMetrics.recordOnBoarding(OnBoarding.OB_CANCELLED); - } callback.onResult(accept); } }
diff --git a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantClient.java b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantClient.java index c3c20c3d..9fd64b7 100644 --- a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantClient.java +++ b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantClient.java
@@ -13,6 +13,7 @@ import org.chromium.base.ContextUtils; import org.chromium.base.annotations.CalledByNative; import org.chromium.base.annotations.JNINamespace; +import org.chromium.chrome.browser.autofill_assistant.overlay.AssistantOverlayCoordinator; import org.chromium.components.signin.AccountManagerFacade; import org.chromium.components.signin.OAuth2TokenService; import org.chromium.content_public.browser.WebContents; @@ -26,7 +27,7 @@ * This mainly a bridge to autofill_assistant::ClientAndroid. */ @JNINamespace("autofill_assistant") -class AutofillAssistantClient implements AutofillAssistantModuleEntry { +class AutofillAssistantClient { /** OAuth2 scope that RPCs require. */ private static final String AUTH_TOKEN_TYPE = "oauth2:https://www.googleapis.com/auth/userinfo.profile"; @@ -66,25 +67,18 @@ mNativeClientAndroid = nativeClientAndroid; } - @Override - public void showOnboarding(String experimentIds, Runnable onAccept) { - checkNativeClientIsAliveOrThrow(); - nativeShowOnboarding(mNativeClientAndroid, experimentIds, onAccept); - } - private void checkNativeClientIsAliveOrThrow() { if (mNativeClientAndroid == 0) { throw new IllegalStateException("Native instance is dead"); } } - @Override - public void start(String initialUrl, Map<String, String> parameters, String experimentIds, - Bundle intentExtras) { + void start(String initialUrl, Map<String, String> parameters, String experimentIds, + Bundle intentExtras, @Nullable AssistantOverlayCoordinator overlayCoordinator) { checkNativeClientIsAliveOrThrow(); nativeStart(mNativeClientAndroid, initialUrl, experimentIds, parameters.keySet().toArray(new String[parameters.size()]), - parameters.values().toArray(new String[parameters.size()])); + parameters.values().toArray(new String[parameters.size()]), overlayCoordinator); chooseAccountAsync(parameters.get(PARAMETER_USER_EMAIL), intentExtras); } @@ -246,10 +240,9 @@ } private static native AutofillAssistantClient nativeFromWebContents(WebContents webContents); - private native void nativeShowOnboarding( - long nativeClientAndroid, String experimentIds, Object onAccept); private native void nativeStart(long nativeClientAndroid, String initialUrl, - String experimentIds, String[] parameterNames, String[] parameterValues); + String experimentIds, String[] parameterNames, String[] parameterValues, + @Nullable AssistantOverlayCoordinator overlayCoordinator); private native void nativeOnAccessToken( long nativeClientAndroid, boolean success, String accessToken); private native String nativeGetPrimaryAccountName(long nativeClientAndroid);
diff --git a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantModuleEntryFactoryImpl.java b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantModuleEntryFactoryImpl.java index a36a25f..2eba277e1 100644 --- a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantModuleEntryFactoryImpl.java +++ b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantModuleEntryFactoryImpl.java
@@ -4,9 +4,22 @@ package org.chromium.chrome.browser.autofill_assistant; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; + import org.chromium.base.annotations.UsedByReflection; +import org.chromium.chrome.browser.ChromeActivity; +import org.chromium.chrome.browser.autofill_assistant.metrics.DropOutReason; +import org.chromium.chrome.browser.autofill_assistant.metrics.OnBoarding; +import org.chromium.chrome.browser.autofill_assistant.overlay.AssistantOverlayCoordinator; +import org.chromium.chrome.browser.autofill_assistant.overlay.AssistantOverlayModel; +import org.chromium.chrome.browser.autofill_assistant.overlay.AssistantOverlayState; +import org.chromium.chrome.browser.widget.bottomsheet.BottomSheetController; import org.chromium.content_public.browser.WebContents; +import java.util.Map; + /** * Factory implementation to create AutofillAssistantClient as * as AutofillAssistantModuleEntry to serve as interface between @@ -16,7 +29,61 @@ public class AutofillAssistantModuleEntryFactoryImpl implements AutofillAssistantModuleEntryFactory { @Override - public AutofillAssistantModuleEntry createEntry(WebContents webContents) { - return AutofillAssistantClient.fromWebContents(webContents); + public AutofillAssistantModuleEntry createEntry( + @NonNull ChromeActivity activity, @NonNull WebContents webContents) { + return new AutofillAssistantModuleEntryImpl(activity, webContents); + } + + private static class AutofillAssistantModuleEntryImpl implements AutofillAssistantModuleEntry { + private final ChromeActivity mActivity; + private final WebContents mWebContents; + + private AutofillAssistantModuleEntryImpl(ChromeActivity activity, WebContents webContents) { + mActivity = activity; + mWebContents = webContents; + } + + @Override + public void start(boolean skipOnboarding, String initialUrl, Map<String, String> parameters, + String experimentIds, Bundle intentExtras) { + if (skipOnboarding) { + AutofillAssistantMetrics.recordOnBoarding(OnBoarding.OB_NOT_SHOWN); + + start(initialUrl, parameters, experimentIds, intentExtras, null); + } else { + AutofillAssistantMetrics.recordOnBoarding(OnBoarding.OB_SHOWN); + + BottomSheetController controller = mActivity.getBottomSheetController(); + AssistantBottomSheetContent content = new AssistantBottomSheetContent(mActivity); + AssistantOverlayModel overlayModel = new AssistantOverlayModel(); + AssistantOverlayCoordinator overlayCoordinator = + new AssistantOverlayCoordinator(mActivity, overlayModel); + overlayModel.set(AssistantOverlayModel.STATE, AssistantOverlayState.FULL); + AssistantOnboardingCoordinator.setOnboardingContent( + experimentIds, mActivity, content, accepted -> { + if (accepted) { + AutofillAssistantMetrics.recordOnBoarding(OnBoarding.OB_ACCEPTED); + + // We transfer the ownership of the overlay to #start() and the + // bottom sheet content will be replaced. + start(initialUrl, parameters, experimentIds, intentExtras, + overlayCoordinator); + } else { + AutofillAssistantMetrics.recordOnBoarding(OnBoarding.OB_CANCELLED); + overlayCoordinator.destroy(); + controller.hideContent(content, /* animate= */ true); + AutofillAssistantMetrics.recordDropOut(DropOutReason.DECLINED); + } + }); + + BottomSheetUtils.showContentAndExpand(controller, content); + } + } + + private void start(String initialUrl, Map<String, String> parameters, String experimentIds, + Bundle intentExtras, @Nullable AssistantOverlayCoordinator overlayCoordinator) { + AutofillAssistantClient client = AutofillAssistantClient.fromWebContents(mWebContents); + client.start(initialUrl, parameters, experimentIds, intentExtras, overlayCoordinator); + } } } \ No newline at end of file
diff --git a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiController.java b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiController.java index 416693d..86d8638 100644 --- a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiController.java +++ b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiController.java
@@ -17,6 +17,7 @@ import org.chromium.chrome.browser.autofill_assistant.carousel.AssistantChip.Type; import org.chromium.chrome.browser.autofill_assistant.header.AssistantHeaderModel; import org.chromium.chrome.browser.autofill_assistant.metrics.DropOutReason; +import org.chromium.chrome.browser.autofill_assistant.overlay.AssistantOverlayCoordinator; import org.chromium.chrome.browser.customtabs.CustomTabActivity; import org.chromium.chrome.browser.snackbar.SnackbarManager.SnackbarController; import org.chromium.chrome.browser.tab.Tab; @@ -38,7 +39,7 @@ @JNINamespace("autofill_assistant") // TODO(crbug.com/806868): This class should be removed once all logic is in native side and the // model is directly modified by the native AssistantMediator. -class AutofillAssistantUiController implements AssistantCoordinator.Delegate { +class AutofillAssistantUiController { private static Set<ChromeActivity> sActiveChromeActivities; private long mNativeUiController; @@ -81,8 +82,9 @@ } @CalledByNative - private static AutofillAssistantUiController create( - ChromeActivity activity, boolean allowTabSwitching, long nativeUiController) { + private static AutofillAssistantUiController create(ChromeActivity activity, + boolean allowTabSwitching, long nativeUiController, + @Nullable AssistantOverlayCoordinator overlayCoordinator) { assert activity != null; assert activity.getBottomSheetController() != null; @@ -92,14 +94,15 @@ sActiveChromeActivities.add(activity); return new AutofillAssistantUiController(activity, activity.getBottomSheetController(), - allowTabSwitching, nativeUiController); + allowTabSwitching, nativeUiController, overlayCoordinator); } private AutofillAssistantUiController(ChromeActivity activity, BottomSheetController controller, - boolean allowTabSwitching, long nativeUiController) { + boolean allowTabSwitching, long nativeUiController, + @Nullable AssistantOverlayCoordinator overlayCoordinator) { mNativeUiController = nativeUiController; mActivity = activity; - mCoordinator = new AssistantCoordinator(activity, this, controller); + mCoordinator = new AssistantCoordinator(activity, controller, overlayCoordinator); mActivityTabObserver = new ActivityTabProvider.ActivityTabTabObserver(activity.getActivityTabProvider()) { @Override @@ -150,14 +153,6 @@ }; } - // Java => native methods. - - /** Shut down the Autofill Assistant immediately, without showing a message. */ - @Override - public void stop(@DropOutReason int reason) { - safeNativeStop(reason); - } - // Native => Java methods. // TODO(crbug.com/806868): Some of these functions still have a little bit of logic (e.g. make @@ -196,11 +191,6 @@ } @CalledByNative - private void onShowOnboarding(String experimentIds, Runnable onAccept) { - mCoordinator.showOnboarding(experimentIds, onAccept); - } - - @CalledByNative private void expandBottomSheet() { mCoordinator.getBottomBarCoordinator().showAndExpand(); }
diff --git a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/BottomSheetUtils.java b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/BottomSheetUtils.java new file mode 100644 index 0000000..3c2d6dd --- /dev/null +++ b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/BottomSheetUtils.java
@@ -0,0 +1,83 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.autofill_assistant; + +import android.view.View; + +import org.chromium.chrome.autofill_assistant.R; +import org.chromium.chrome.browser.widget.bottomsheet.BottomSheet; +import org.chromium.chrome.browser.widget.bottomsheet.BottomSheetController; +import org.chromium.chrome.browser.widget.bottomsheet.EmptyBottomSheetObserver; + +class BottomSheetUtils { + /** Request {@code controller} to show {@code content} and expand the sheet when it is shown. */ + static void showContentAndExpand( + BottomSheetController controller, AssistantBottomSheetContent content) { + // Add an observer that makes sure the bottom sheet content is always shown, even in the + // peek state. + BottomSheet bottomSheet = controller.getBottomSheet(); + View bottomSheetContainer = bottomSheet.findViewById(R.id.bottom_sheet_content); + bottomSheet.addObserver(new EmptyBottomSheetObserver() { + private boolean mEnabled; + + @Override + public void onSheetContentChanged(BottomSheet.BottomSheetContent newContent) { + if (newContent == content) { + mEnabled = true; + } else if (mEnabled) { + // Content was shown then hidden: remove this observer. + mEnabled = false; + bottomSheet.removeObserver(this); + } + } + + @Override + public void onSheetClosed(int reason) { + if (!mEnabled) return; + + // When scrolling with y < peekHeight, the BottomSheet will make the content + // invisible. This is a workaround to prevent that as our toolbar is transparent and + // we want to sheet content to stay visible. + if ((bottomSheet.getSheetState() == BottomSheet.SheetState.SCROLLING + || bottomSheet.getSheetState() == BottomSheet.SheetState.PEEK) + && bottomSheet.getCurrentSheetContent() == content) { + bottomSheetContainer.setVisibility(View.VISIBLE); + } + } + + @Override + public void onSheetStateChanged(int newState) { + if (!mEnabled) return; + + if (newState == BottomSheet.SheetState.PEEK + && bottomSheet.getCurrentSheetContent() == content) { + // When in the peek state, the BottomSheet hides the content view. We override + // that because we artificially increase the height of the transparent toolbar + // to show parts of the content view. + bottomSheetContainer.setVisibility(View.VISIBLE); + } + } + }); + + // Show the content. + if (controller.requestShowContent(content, /* animate= */ true)) { + controller.expandSheet(); + } else { + // If the content is not directly shown, add an observer that will expand the sheet when + // it is. + bottomSheet.addObserver(new EmptyBottomSheetObserver() { + @Override + public void onSheetContentChanged(BottomSheet.BottomSheetContent newContent) { + if (newContent == content) { + bottomSheet.removeObserver(this); + controller.expandSheet(); + } + } + }); + } + } + + private BottomSheetUtils() {} +}
diff --git a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/header/AssistantHeaderCoordinator.java b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/header/AssistantHeaderCoordinator.java index d019f87b..be9cbe54 100644 --- a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/header/AssistantHeaderCoordinator.java +++ b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/header/AssistantHeaderCoordinator.java
@@ -50,7 +50,6 @@ AssistantHeaderViewBinder viewBinder = new AssistantHeaderViewBinder(); PropertyModelChangeProcessor.create(model, viewHolder, viewBinder); - model.set(AssistantHeaderModel.VISIBLE, true); model.set(AssistantHeaderModel.PROGRESS_VISIBLE, true); }
diff --git a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/header/AssistantHeaderModel.java b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/header/AssistantHeaderModel.java index e5022a80..cd2870f 100644 --- a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/header/AssistantHeaderModel.java +++ b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/header/AssistantHeaderModel.java
@@ -15,8 +15,6 @@ */ @JNINamespace("autofill_assistant") public class AssistantHeaderModel extends PropertyModel { - public static final WritableBooleanPropertyKey VISIBLE = new WritableBooleanPropertyKey(); - @VisibleForTesting public static final WritableObjectPropertyKey<String> STATUS_MESSAGE = new WritableObjectPropertyKey<>(); @@ -38,8 +36,8 @@ public static final WritableBooleanPropertyKey CHIP_VISIBLE = new WritableBooleanPropertyKey(); public AssistantHeaderModel() { - super(VISIBLE, STATUS_MESSAGE, PROGRESS, PROGRESS_VISIBLE, SPIN_POODLE, - FEEDBACK_BUTTON_CALLBACK, CHIP, CHIP_VISIBLE); + super(STATUS_MESSAGE, PROGRESS, PROGRESS_VISIBLE, SPIN_POODLE, FEEDBACK_BUTTON_CALLBACK, + CHIP, CHIP_VISIBLE); } @CalledByNative
diff --git a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/header/AssistantHeaderViewBinder.java b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/header/AssistantHeaderViewBinder.java index ddc9b96..4db357b 100644 --- a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/header/AssistantHeaderViewBinder.java +++ b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/header/AssistantHeaderViewBinder.java
@@ -54,18 +54,18 @@ @Override public void bind(AssistantHeaderModel model, ViewHolder view, PropertyKey propertyKey) { - if (AssistantHeaderModel.VISIBLE == propertyKey) { - view.mHeader.setVisibility( - model.get(AssistantHeaderModel.VISIBLE) ? View.VISIBLE : View.GONE); - setProgressBarVisibility(view, model); - } else if (AssistantHeaderModel.STATUS_MESSAGE == propertyKey) { + if (AssistantHeaderModel.STATUS_MESSAGE == propertyKey) { String message = model.get(AssistantHeaderModel.STATUS_MESSAGE); view.mStatusMessage.setText(message); view.mStatusMessage.announceForAccessibility(message); } else if (AssistantHeaderModel.PROGRESS == propertyKey) { view.mProgressBar.setProgress(model.get(AssistantHeaderModel.PROGRESS)); } else if (AssistantHeaderModel.PROGRESS_VISIBLE == propertyKey) { - setProgressBarVisibility(view, model); + if (model.get(AssistantHeaderModel.PROGRESS_VISIBLE)) { + view.mProgressBar.show(); + } else { + view.mProgressBar.hide(); + } } else if (AssistantHeaderModel.SPIN_POODLE == propertyKey) { view.mPoodle.setSpinEnabled(model.get(AssistantHeaderModel.SPIN_POODLE)); } else if (AssistantHeaderModel.FEEDBACK_BUTTON_CALLBACK == propertyKey) { @@ -118,15 +118,6 @@ view.mChip.bind(chip); } - private void setProgressBarVisibility(ViewHolder view, AssistantHeaderModel model) { - if (model.get(AssistantHeaderModel.VISIBLE) - && model.get(AssistantHeaderModel.PROGRESS_VISIBLE)) { - view.mProgressBar.show(); - } else { - view.mProgressBar.hide(); - } - } - private void setProfileMenuListener(ViewHolder view, @Nullable Runnable feedbackCallback) { view.mProfileIconMenu.setOnMenuItemClickListener(item -> { int itemId = item.getItemId();
diff --git a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/overlay/AssistantOverlayCoordinator.java b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/overlay/AssistantOverlayCoordinator.java index 54ee845..a648f8d 100644 --- a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/overlay/AssistantOverlayCoordinator.java +++ b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/overlay/AssistantOverlayCoordinator.java
@@ -19,6 +19,7 @@ */ public class AssistantOverlayCoordinator { private final ChromeActivity mActivity; + private final AssistantOverlayModel mModel; private final AssistantOverlayEventFilter mEventFilter; private final AssistantOverlayDrawable mDrawable; private final ScrimView mScrim; @@ -26,6 +27,7 @@ public AssistantOverlayCoordinator(ChromeActivity activity, AssistantOverlayModel model) { mActivity = activity; + mModel = model; mScrim = mActivity.getScrim(); mEventFilter = new AssistantOverlayEventFilter( mActivity, mActivity.getFullscreenManager(), mActivity.getCompositorViewHolder()); @@ -44,6 +46,10 @@ List<RectF> area = model.get(AssistantOverlayModel.TOUCHABLE_AREA); mEventFilter.setTouchableArea(area); mDrawable.setTransparentArea(area); + } else if (AssistantOverlayModel.RESTRICTED_AREA == propertyKey) { + List<RectF> area = model.get(AssistantOverlayModel.RESTRICTED_AREA); + mEventFilter.setRestrictedArea(area); + mDrawable.setRestrictedArea(area); } else if (AssistantOverlayModel.DELEGATE == propertyKey) { AssistantOverlayDelegate delegate = model.get(AssistantOverlayModel.DELEGATE); mEventFilter.setDelegate(delegate); @@ -57,6 +63,11 @@ }); } + /** Return the model observed by this coordinator. */ + public AssistantOverlayModel getModel() { + return mModel; + } + /** * Destroy this coordinator. */
diff --git a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/overlay/AssistantOverlayDrawable.java b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/overlay/AssistantOverlayDrawable.java index 91ecf96..a2b3e3a1 100644 --- a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/overlay/AssistantOverlayDrawable.java +++ b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/overlay/AssistantOverlayDrawable.java
@@ -18,6 +18,7 @@ import android.graphics.PorterDuffXfermode; import android.graphics.Rect; import android.graphics.RectF; +import android.graphics.Region; import android.graphics.drawable.Drawable; import android.support.annotation.IntDef; import android.support.annotation.Nullable; @@ -33,6 +34,7 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; +import java.util.Collections; import java.util.Iterator; import java.util.List; @@ -85,6 +87,7 @@ private final RectF mVisualViewport = new RectF(); private final List<Box> mTransparentArea = new ArrayList<>(); + private List<RectF> mRestrictedArea = Collections.emptyList(); /** Padding added between the element area and the grayed-out area. */ private final float mPaddingPx; @@ -226,6 +229,12 @@ invalidateSelf(); } + /** Set or update the restricted area. */ + void setRestrictedArea(List<RectF> restrictedArea) { + mRestrictedArea = restrictedArea; + invalidateSelf(); + } + @Override public void setAlpha(int alpha) { // Alpha is ignored. @@ -260,6 +269,16 @@ float cssPixelsToPhysical = ((float) width) / mVisualViewport.width(); int yTop = mFullscreenManager.getContentOffset(); + + // Don't draw on top of the restricted area. + for (RectF rect : mRestrictedArea) { + mDrawRect.left = (rect.left - mVisualViewport.left) * cssPixelsToPhysical; + mDrawRect.top = yTop + (rect.top - mVisualViewport.top) * cssPixelsToPhysical; + mDrawRect.right = (rect.right - mVisualViewport.left) * cssPixelsToPhysical; + mDrawRect.bottom = yTop + (rect.bottom - mVisualViewport.top) * cssPixelsToPhysical; + canvas.clipRect(mDrawRect, Region.Op.DIFFERENCE); + } + for (Box box : mTransparentArea) { RectF rect = box.getRectToDraw(); if (rect.isEmpty() || (!mPartial && box.mAnimationType != AnimationType.FADE_IN)) {
diff --git a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/overlay/AssistantOverlayEventFilter.java b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/overlay/AssistantOverlayEventFilter.java index aff95267..6cededa 100644 --- a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/overlay/AssistantOverlayEventFilter.java +++ b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/overlay/AssistantOverlayEventFilter.java
@@ -71,6 +71,9 @@ /** Touchable area, expressed in CSS pixels relative to the layout viewport. */ private List<RectF> mTouchableArea = Collections.emptyList(); + /** Restricted area, expressed in CSS pixels relative to the layout viewport. */ + private List<RectF> mRestrictedArea = Collections.emptyList(); + /** * Detects taps: {@link GestureDetector#onTouchEvent} returns {@code true} after a tap event. */ @@ -151,6 +154,13 @@ mTouchableArea = touchableArea; } + /** + * Set the restricted area. This only applies if current state is AssistantOverlayState.PARTIAL. + */ + void setRestrictedArea(List<RectF> restrictedArea) { + mRestrictedArea = restrictedArea; + } + /** Sets the visual viewport. */ void setVisualViewport(RectF visualViewport) { mVisualViewport.set(visualViewport); @@ -341,6 +351,11 @@ ((float) mVisualViewport.width()) / ((float) mCompositorView.getWidth()); float absoluteXCss = (x * physicalPixelsToCss) + mVisualViewport.left; float absoluteYCss = (y * physicalPixelsToCss) + mVisualViewport.top; + + for (RectF rect : mRestrictedArea) { + if (rect.contains(absoluteXCss, absoluteYCss)) return false; + } + for (RectF rect : mTouchableArea) { if (rect.contains(absoluteXCss, absoluteYCss)) return true; }
diff --git a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/overlay/AssistantOverlayModel.java b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/overlay/AssistantOverlayModel.java index e2124893..492a744 100644 --- a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/overlay/AssistantOverlayModel.java +++ b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/overlay/AssistantOverlayModel.java
@@ -25,6 +25,9 @@ public static final WritableObjectPropertyKey<List<RectF>> TOUCHABLE_AREA = new WritableObjectPropertyKey<>(); + public static final WritableObjectPropertyKey<List<RectF>> RESTRICTED_AREA = + new WritableObjectPropertyKey<>(); + public static final WritableObjectPropertyKey<RectF> VISUAL_VIEWPORT = new WritableObjectPropertyKey<>(); @@ -38,7 +41,7 @@ new WritableObjectPropertyKey<>(); public AssistantOverlayModel() { - super(STATE, TOUCHABLE_AREA, VISUAL_VIEWPORT, DELEGATE, BACKGROUND_COLOR, + super(STATE, TOUCHABLE_AREA, RESTRICTED_AREA, VISUAL_VIEWPORT, DELEGATE, BACKGROUND_COLOR, HIGHLIGHT_BORDER_COLOR); } @@ -54,12 +57,21 @@ @CalledByNative private void setTouchableArea(float[] coords) { + set(TOUCHABLE_AREA, toRectangles(coords)); + } + + private static List<RectF> toRectangles(float[] coords) { List<RectF> boxes = new ArrayList<>(); for (int i = 0; i < coords.length; i += 4) { boxes.add(new RectF(/* left= */ coords[i], /* top= */ coords[i + 1], /* right= */ coords[i + 2], /* bottom= */ coords[i + 3])); } - set(TOUCHABLE_AREA, boxes); + return boxes; + } + + @CalledByNative + private void setRestrictedArea(float[] coords) { + set(RESTRICTED_AREA, toRectangles(coords)); } @CalledByNative
diff --git a/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiTest.java b/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiTest.java index 8c3271d..7d1f674 100644 --- a/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiTest.java +++ b/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiTest.java
@@ -5,8 +5,11 @@ package org.chromium.chrome.browser.autofill_assistant; import static org.mockito.Mockito.inOrder; +import static org.mockito.Mockito.verify; +import android.content.Context; import android.content.Intent; +import android.support.annotation.IdRes; import android.support.test.InstrumentationRegistry; import android.support.test.filters.MediumTest; import android.support.v7.widget.RecyclerView; @@ -69,9 +72,6 @@ public MockitoRule mMockitoRule = MockitoJUnit.rule(); @Mock - public AssistantCoordinator.Delegate mCoordinatorDelegateMock; - - @Mock public Runnable mRunnableMock; @Rule @@ -123,6 +123,37 @@ /* suppressSheetForContextualSearch= */ false); } + @Test + @MediumTest + public void testAcceptOnboarding() throws Exception { + testOnboarding(true, R.id.button_init_ok); + } + + @Test + @MediumTest + public void testDeclineOnboarding() throws Exception { + testOnboarding(false, R.id.button_init_not_ok); + } + + private void testOnboarding(boolean expectedAccepted, @IdRes int buttonToClick) + throws Exception { + mCustomTabActivityTestRule.startCustomTabActivityWithIntent(createMinimalCustomTabIntent()); + Context context = getActivity(); + AssistantBottomSheetContent bottomSheetContent = new AssistantBottomSheetContent(context); + + AssistantOnboardingCoordinator.setOnboardingContent( + /* experimentIds= */ "", context, bottomSheetContent, accepted -> { + Assert.assertEquals(expectedAccepted, accepted); + mRunnableMock.run(); + }); + + View button = bottomSheetContent.getContentView().findViewById(buttonToClick); + Assert.assertNotNull(button); + + TestThreadUtils.runOnUiThreadBlocking(button::performClick); + TestThreadUtils.runOnUiThreadBlocking(() -> verify(mRunnableMock).run()); + } + // TODO(crbug.com/806868): Add more UI details test and check, like payment request UI, // highlight chips and so on. @Test @@ -135,8 +166,8 @@ ThreadUtils.runOnUiThreadBlocking(this::initializeBottomSheet); AssistantCoordinator assistantCoordinator = ThreadUtils.runOnUiThreadBlocking( () - -> new AssistantCoordinator( - getActivity(), mCoordinatorDelegateMock, bottomSheetController)); + -> new AssistantCoordinator(getActivity(), bottomSheetController, + /* overlayCoordinator= */ null)); // Bottom sheet is shown in the BottomSheet when creating the AssistantCoordinator. ViewGroup bottomSheetContent = @@ -146,16 +177,6 @@ // Disable bottom sheet content animations. This is a workaround for http://crbug/943483. TestThreadUtils.runOnUiThreadBlocking(() -> bottomSheetContent.setLayoutTransition(null)); - // Show onboarding. - ThreadUtils.runOnUiThreadBlocking( - () -> assistantCoordinator.showOnboarding(/* experimentIds= */ "", mRunnableMock)); - View onboardingView = bottomSheetContent.findViewById(R.id.assistant_onboarding); - Assert.assertNotNull(onboardingView); - View initOkButton = onboardingView.findViewById(R.id.button_init_ok); - Assert.assertNotNull(initOkButton); - ThreadUtils.runOnUiThreadBlocking(() -> { initOkButton.performClick(); }); - ThreadUtils.runOnUiThreadBlocking(() -> inOrder.verify(mRunnableMock).run()); - // Show and check status message. String testStatusMessage = "test message"; ThreadUtils.runOnUiThreadBlocking(
diff --git a/chrome/android/features/autofill_assistant/public/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantFacade.java b/chrome/android/features/autofill_assistant/public/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantFacade.java index 271f3b1..0816db2 100644 --- a/chrome/android/features/autofill_assistant/public/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantFacade.java +++ b/chrome/android/features/autofill_assistant/public/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantFacade.java
@@ -11,7 +11,6 @@ import org.chromium.chrome.browser.ChromeActivity; import org.chromium.chrome.browser.autofill_assistant.metrics.DropOutReason; -import org.chromium.chrome.browser.autofill_assistant.metrics.OnBoarding; import org.chromium.chrome.browser.metrics.UmaSessionStats; import org.chromium.chrome.browser.util.IntentUtils; @@ -90,8 +89,8 @@ } // Early exit if autofill assistant should not be triggered. - if (!canStart(activity.getInitialIntent()) - && !AutofillAssistantPreferencesUtil.getShowOnboarding()) { + boolean canStartWithoutOnboarding = canStart(activity.getInitialIntent()); + if (!canStartWithoutOnboarding && !AutofillAssistantPreferencesUtil.getShowOnboarding()) { return; } @@ -99,22 +98,16 @@ AutofillAssistantMetrics.recordDropOut(DropOutReason.AA_START); AutofillAssistantModuleEntryProvider.getModuleEntry(activity, (moduleEntry) -> { if (moduleEntry == null) { - AutofillAssistantMetrics.recordDropOut(DropOutReason.DFM_CANCELLED); + AutofillAssistantMetrics.recordDropOut(DropOutReason.DFM_INSTALL_FAILED); return; } - // Starting autofill assistant without onboarding. - if (canStart(activity.getInitialIntent())) { - AutofillAssistantMetrics.recordOnBoarding(OnBoarding.OB_NOT_SHOWN); - startNow(activity, moduleEntry); - return; - } - // Starting autofill assistant with onboarding. - if (AutofillAssistantPreferencesUtil.getShowOnboarding()) { - moduleEntry.showOnboarding( - getExperimentIds(activity.getInitialIntent().getExtras()), - () -> startNow(activity, moduleEntry)); - return; - } + + Bundle bundleExtras = activity.getInitialIntent().getExtras(); + Map<String, String> parameters = extractParameters(bundleExtras); + parameters.remove(PARAMETER_ENABLED); + String initialUrl = activity.getInitialIntent().getDataString(); + moduleEntry.start(canStartWithoutOnboarding, initialUrl, parameters, experimentIds, + activity.getInitialIntent().getExtras()); }); } @@ -144,16 +137,6 @@ return experiments.toString(); } - private static void startNow(ChromeActivity activity, AutofillAssistantModuleEntry entry) { - Bundle bundleExtras = activity.getInitialIntent().getExtras(); - Map<String, String> parameters = extractParameters(bundleExtras); - parameters.remove(PARAMETER_ENABLED); - String initialUrl = activity.getInitialIntent().getDataString(); - - entry.start(initialUrl, parameters, getExperimentIds(bundleExtras), - activity.getInitialIntent().getExtras()); - } - /** Return the value if the given boolean parameter from the extras. */ private static boolean getBooleanParameter(@Nullable Bundle extras, String parameterName) { return extras != null
diff --git a/chrome/android/features/autofill_assistant/public/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantModuleEntry.java b/chrome/android/features/autofill_assistant/public/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantModuleEntry.java index 0aaf6df..44b802e2 100644 --- a/chrome/android/features/autofill_assistant/public/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantModuleEntry.java +++ b/chrome/android/features/autofill_assistant/public/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantModuleEntry.java
@@ -14,13 +14,10 @@ */ interface AutofillAssistantModuleEntry { /** - * Show the onboarding screen and run {@code onAccept} if user agreed to proceed. + * Launches Autofill Assistant on the current web contents, expecting autostart. If {@code + * skipOnboarding} is false, the onboarding will first be shown and the Autofill Assistant will + * start only if the user accepts to proceed. */ - void showOnboarding(String experimentIds, Runnable onAccept); - - /** - * Launches Autofill Assistant on the current web contents, expecting autostart. - */ - void start(String initialUrl, Map<String, String> parameters, String experimentIds, - Bundle intentExtras); + void start(boolean skipOnboarding, String initialUrl, Map<String, String> parameters, + String experimentIds, Bundle intentExtras); } \ No newline at end of file
diff --git a/chrome/android/features/autofill_assistant/public/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantModuleEntryFactory.java b/chrome/android/features/autofill_assistant/public/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantModuleEntryFactory.java index 045c6b8..214ce76 100644 --- a/chrome/android/features/autofill_assistant/public/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantModuleEntryFactory.java +++ b/chrome/android/features/autofill_assistant/public/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantModuleEntryFactory.java
@@ -4,6 +4,9 @@ package org.chromium.chrome.browser.autofill_assistant; +import android.support.annotation.NonNull; + +import org.chromium.chrome.browser.ChromeActivity; import org.chromium.components.module_installer.ModuleInterface; import org.chromium.content_public.browser.WebContents; @@ -15,5 +18,6 @@ impl = "org.chromium.chrome.browser.autofill_assistant." + "AutofillAssistantModuleEntryFactoryImpl") interface AutofillAssistantModuleEntryFactory { - AutofillAssistantModuleEntry createEntry(WebContents webContents); + AutofillAssistantModuleEntry createEntry( + @NonNull ChromeActivity activity, @NonNull WebContents webContents); } \ No newline at end of file
diff --git a/chrome/android/features/autofill_assistant/public/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantModuleEntryProvider.java b/chrome/android/features/autofill_assistant/public/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantModuleEntryProvider.java index ac99548..517615c9 100644 --- a/chrome/android/features/autofill_assistant/public/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantModuleEntryProvider.java +++ b/chrome/android/features/autofill_assistant/public/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantModuleEntryProvider.java
@@ -6,6 +6,7 @@ import org.chromium.base.BundleUtils; import org.chromium.base.Callback; +import org.chromium.base.Log; import org.chromium.base.SysUtils; import org.chromium.chrome.R; import org.chromium.chrome.browser.ActivityTabProvider; @@ -19,6 +20,8 @@ * AutofillAssistantModuleEntry. */ public class AutofillAssistantModuleEntryProvider { + private static final String TAG = "AutofillAssistant"; + /** * Returns AutofillAssistantModuleEntry by using it as argument to the * passed in callback, or null if DFM loading fails. @@ -50,16 +53,26 @@ * </ul> */ public static void maybeInstallDeferred() { - if (!BundleUtils.isBundle()) return; - if (AutofillAssistantModule.isInstalled()) return; - if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.LOLLIPOP) return; - if (!SysUtils.isHighEndDiskDevice()) return; + boolean isNotBundle = !BundleUtils.isBundle(); + boolean isInstalled = AutofillAssistantModule.isInstalled(); + boolean isVersionBeforeLollipop = + android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.LOLLIPOP; + boolean isNotHighEndDiskDevice = !SysUtils.isHighEndDiskDevice(); + if (isNotBundle || isInstalled || isVersionBeforeLollipop || isNotHighEndDiskDevice) { + Log.v(TAG, + "Deferred install not triggered: not_bundle=" + isNotBundle + + ", already_installed=" + isInstalled + + ", before_lollipop=" + isVersionBeforeLollipop + + ", not_high_end_device=" + isNotHighEndDiskDevice); + return; + } + Log.v(TAG, "Deferred install triggered."); AutofillAssistantModule.installDeferred(); } private static AutofillAssistantModuleEntry createEntry(Tab tab) { AutofillAssistantModuleEntryFactory factory = AutofillAssistantModule.getImpl(); - return factory.createEntry(tab.getWebContents()); + return factory.createEntry(tab.getActivity(), tab.getWebContents()); } private static void loadDynamicModuleWithUi(
diff --git a/chrome/android/features/tab_ui/java/res/drawable/tab_grid_card_background_grey.xml b/chrome/android/features/tab_ui/java/res/drawable/tab_grid_card_background_grey.xml new file mode 100644 index 0000000..0bd6ef9 --- /dev/null +++ b/chrome/android/features/tab_ui/java/res/drawable/tab_grid_card_background_grey.xml
@@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright 2019 The Chromium Authors. All rights reserved. + Use of this source code is governed by a BSD-style license that can be + found in the LICENSE file. --> + +<shape xmlns:android="http://schemas.android.com/apk/res/android"> + <solid android:color="@color/modern_grey_200"/> + <corners android:radius="@dimen/default_rounded_corner_radius" /> +</shape> \ No newline at end of file
diff --git a/chrome/android/features/tab_ui/java/res/layout/tab_grid_card_item.xml b/chrome/android/features/tab_ui/java/res/layout/tab_grid_card_item.xml index 1c9aae6..6cb71de 100644 --- a/chrome/android/features/tab_ui/java/res/layout/tab_grid_card_item.xml +++ b/chrome/android/features/tab_ui/java/res/layout/tab_grid_card_item.xml
@@ -13,6 +13,7 @@ android:layout_margin="3dp" android:visibility="visible"/> <RelativeLayout + android:id="@+id/content_view" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_gravity="center"
diff --git a/chrome/android/features/tab_ui/java/res/values/dimens.xml b/chrome/android/features/tab_ui/java/res/values/dimens.xml index fcd70d2..57d14d416 100644 --- a/chrome/android/features/tab_ui/java/res/values/dimens.xml +++ b/chrome/android/features/tab_ui/java/res/values/dimens.xml
@@ -7,6 +7,7 @@ <dimen name="tab_list_selected_inset">7dp</dimen> <dimen name="tab_list_selected_inset_kitkat">2dp</dimen> <dimen name="tab_list_card_padding">8dp</dimen> + <dimen name="tab_list_card_background_margin">3dp</dimen> <dimen name="tab_list_mini_card_radius">4dp</dimen> <dimen name="tab_list_mini_card_frame_size">1dp</dimen> <dimen name="tab_grid_close_button_size">18dp</dimen>
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridItemTouchHelperCallback.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridItemTouchHelperCallback.java index d538feae..f4ac5b5 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridItemTouchHelperCallback.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridItemTouchHelperCallback.java
@@ -24,7 +24,6 @@ /** * A {@link ItemTouchHelper.SimpleCallback} implementation to host the logic for swipe and drag * related actions in grid related layouts. - * TODO(yuezhanggg): Get rid of using notifyDataSetChanged in adapter. */ public class TabGridItemTouchHelperCallback extends ItemTouchHelper.SimpleCallback { @@ -143,18 +142,22 @@ } if (mHoveredTabIndex != TabModel.INVALID_TAB_INDEX && mActionsOnAllRelatedTabs) { onTabMergeToGroup(mSelectedTabIndex, mHoveredTabIndex); - mRecyclerView.getAdapter().notifyDataSetChanged(); + mRecyclerView.removeViewAt(mSelectedTabIndex); RecordUserAction.record("GridTabSwitcher.Drag.AddToGroupOrCreateGroup"); } - if (mHoveredTabIndex == TabModel.INVALID_TAB_INDEX) { - mModel.updateSelectedTabForMergeToGroup(mSelectedTabIndex, false); + mModel.updateSelectedTabForMergeToGroup(mSelectedTabIndex, false); + if (mHoveredTabIndex != TabModel.INVALID_TAB_INDEX) { + mModel.updateHoveredTabForMergeToGroup(mSelectedTabIndex > mHoveredTabIndex + ? mHoveredTabIndex + : mHoveredTabIndex - 1, + false); } if (mUnGroupTabIndex != TabModel.INVALID_TAB_INDEX) { TabGroupModelFilter filter = (TabGroupModelFilter) mTabModelSelector.getTabModelFilterProvider() .getCurrentTabModelFilter(); filter.moveTabOutOfGroup(mModel.get(mUnGroupTabIndex).get(TabProperties.TAB_ID)); - mRecyclerView.getAdapter().notifyDataSetChanged(); + mRecyclerView.removeViewAt(mUnGroupTabIndex); RecordUserAction.record("TabGridDialog.Drag.RemoveFromGroup"); } mHoveredTabIndex = TabModel.INVALID_TAB_INDEX; @@ -214,7 +217,6 @@ } private void onTabMergeToGroup(int selectedCardIndex, int hoveredCardIndex) { - mModel.updateHoveredTabForMergeToGroup(hoveredCardIndex, false); TabGroupModelFilter filter = (TabGroupModelFilter) mTabModelSelector.getTabModelFilterProvider() .getCurrentTabModelFilter();
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediator.java index 57dfe68..5fbe1f7 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediator.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediator.java
@@ -718,7 +718,6 @@ mModel.get(modelIndex).set(TabProperties.FAVICON, drawable); } }; - mTabListFaviconProvider.getFaviconForUrlAsync( tab.getUrl(), tab.isIncognito(), faviconCallback); if (mThumbnailProvider != null @@ -814,7 +813,7 @@ getCreateGroupButtonListener(tab, isSelected)) .with(TabProperties.ALPHA, 1f) .with(TabProperties.CARD_ANIMATION_STATUS, - TabListRecyclerView.ANIMATION_STATUS_RESTORE) + TabListRecyclerView.AnimationStatus.CARD_RESTORE) .with(TabProperties.SELECTABLE_TAB_CLICKED_LISTENER, mSelectableTabOnClickListener) .with(TabProperties.TAB_SELECTION_DELEGATE, getTabSelectionDelegate())
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListModel.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListModel.java index 17dde61..92f2041 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListModel.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListModel.java
@@ -78,8 +78,8 @@ * state. If not, restore it to original state. */ void updateSelectedTabForMergeToGroup(int index, boolean isSelected) { - int status = isSelected ? TabListRecyclerView.ANIMATION_STATUS_ZOOM_IN - : TabListRecyclerView.ANIMATION_STATUS_ZOOM_OUT; + int status = isSelected ? TabListRecyclerView.AnimationStatus.SELECTED_CARD_ZOOM_IN + : TabListRecyclerView.AnimationStatus.SELECTED_CARD_ZOOM_OUT; if (index < 0 || index >= size() || get(index).get(TabProperties.CARD_ANIMATION_STATUS) == status) return; @@ -97,12 +97,11 @@ * If not, restore it to original state. */ void updateHoveredTabForMergeToGroup(int index, boolean isHovered) { - int status = isHovered ? TabListRecyclerView.ANIMATION_STATUS_ZOOM_IN - : TabListRecyclerView.ANIMATION_STATUS_ZOOM_OUT; + int status = isHovered ? TabListRecyclerView.AnimationStatus.HOVERED_CARD_ZOOM_IN + : TabListRecyclerView.AnimationStatus.HOVERED_CARD_ZOOM_OUT; if (index < 0 || index >= size() || get(index).get(TabProperties.CARD_ANIMATION_STATUS) == status) return; - get(index).set(TabProperties.CARD_ANIMATION_STATUS, status); } }
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListRecyclerView.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListRecyclerView.java index 9ec1f22d..73ff78e5 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListRecyclerView.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListRecyclerView.java
@@ -13,7 +13,9 @@ import android.content.Context; import android.content.res.Resources; import android.graphics.Rect; +import android.graphics.drawable.Drawable; import android.os.SystemClock; +import android.support.annotation.IntDef; import android.support.annotation.Nullable; import android.support.v7.content.res.AppCompatResources; import android.support.v7.widget.RecyclerView; @@ -24,12 +26,15 @@ import android.widget.FrameLayout; import android.widget.ImageView; -import org.chromium.chrome.R; import org.chromium.chrome.browser.ChromeFeatureList; +import org.chromium.chrome.tab_ui.R; import org.chromium.ui.interpolators.BakedBezierInterpolator; import org.chromium.ui.resources.dynamics.DynamicResourceLoader; import org.chromium.ui.resources.dynamics.ViewResourceAdapter; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + /** * A custom RecyclerView implementation for the tab grid, to handle show/hide logic in class. */ @@ -37,9 +42,17 @@ public static final long BASE_ANIMATION_DURATION_MS = 218; public static final long FINAL_FADE_IN_DURATION_MS = 50; public static final long RESTORE_ANIMATION_DURATION_MS = 10; - public static final int ANIMATION_STATUS_RESTORE = 0; - public static final int ANIMATION_STATUS_ZOOM_OUT = 1; - public static final int ANIMATION_STATUS_ZOOM_IN = 2; + @IntDef({AnimationStatus.SELECTED_CARD_ZOOM_IN, AnimationStatus.SELECTED_CARD_ZOOM_OUT, + AnimationStatus.HOVERED_CARD_ZOOM_IN, AnimationStatus.HOVERED_CARD_ZOOM_OUT, + AnimationStatus.CARD_RESTORE}) + @Retention(RetentionPolicy.SOURCE) + public @interface AnimationStatus { + int CARD_RESTORE = 0; + int SELECTED_CARD_ZOOM_OUT = 1; + int SELECTED_CARD_ZOOM_IN = 2; + int HOVERED_CARD_ZOOM_OUT = 3; + int HOVERED_CARD_ZOOM_IN = 4; + } /** * Field trial parameter for downsampling scaling factor. @@ -180,12 +193,13 @@ if (mShadowImageView == null) { Context context = getContext(); mShadowImageView = new ImageView(context); - mShadowImageView.setImageDrawable( - AppCompatResources.getDrawable(context, R.drawable.modern_toolbar_shadow)); + mShadowImageView.setImageDrawable(AppCompatResources.getDrawable( + context, org.chromium.chrome.R.drawable.modern_toolbar_shadow)); Resources res = context.getResources(); - FrameLayout.LayoutParams params = - new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT, - res.getDimensionPixelSize(R.dimen.toolbar_shadow_height), Gravity.TOP); + FrameLayout.LayoutParams params = new FrameLayout.LayoutParams( + LayoutParams.MATCH_PARENT, + res.getDimensionPixelSize(org.chromium.chrome.R.dimen.toolbar_shadow_height), + Gravity.TOP); params.topMargin = mShadowTopMargin; mShadowImageView.setScaleType(ImageView.ScaleType.FIT_XY); mShadowImageView.setLayoutParams(params); @@ -364,15 +378,56 @@ return rect; } - static void scaleTabGridCardView(View view, int status) { + /** + * Play the zoom-in and zoom-out animations for tab grid card. + * @param view The view of the {@link TabGridViewHolder} that is playing animations. + * @param status The target animation status in {@link AnimationStatus}. + * + */ + static void scaleTabGridCardView(View view, @AnimationStatus int status) { + Context context = view.getContext(); + final View backgroundView = view.findViewById(R.id.background_view); + final View contentView = view.findViewById(R.id.content_view); + final int cardNormalMargin = + (int) context.getResources().getDimension(R.dimen.tab_list_card_padding); + final int cardBackgroundMargin = + (int) context.getResources().getDimension(R.dimen.tab_list_card_background_margin); + final Drawable greyBackground = + AppCompatResources.getDrawable(context, R.drawable.tab_grid_card_background_grey); + final Drawable normalBackground = + AppCompatResources.getDrawable(context, R.drawable.popup_bg); + boolean isZoomIn = status == AnimationStatus.SELECTED_CARD_ZOOM_IN + || status == AnimationStatus.HOVERED_CARD_ZOOM_IN; + boolean isHovered = status == AnimationStatus.HOVERED_CARD_ZOOM_IN + || status == AnimationStatus.HOVERED_CARD_ZOOM_OUT; + boolean isRestore = status == AnimationStatus.CARD_RESTORE; + long duration = isRestore ? RESTORE_ANIMATION_DURATION_MS : BASE_ANIMATION_DURATION_MS; + float scale = isZoomIn ? 0.8f : 1f; + MarginLayoutParams backgroundParams = (MarginLayoutParams) backgroundView.getLayoutParams(); + View animateView = isHovered ? contentView : view; + + if (status == AnimationStatus.HOVERED_CARD_ZOOM_IN) { + backgroundParams.setMargins( + cardNormalMargin, cardNormalMargin, cardNormalMargin, cardNormalMargin); + backgroundView.setBackground(greyBackground); + } + AnimatorSet scaleAnimator = new AnimatorSet(); - float scale = status == ANIMATION_STATUS_ZOOM_IN ? 0.8f : 1f; - ObjectAnimator scaleX = ObjectAnimator.ofFloat(view, "scaleX", scale); - ObjectAnimator scaleY = ObjectAnimator.ofFloat(view, "scaleY", scale); - scaleX.setDuration(status == ANIMATION_STATUS_RESTORE ? RESTORE_ANIMATION_DURATION_MS - : BASE_ANIMATION_DURATION_MS); - scaleY.setDuration(status == ANIMATION_STATUS_RESTORE ? RESTORE_ANIMATION_DURATION_MS - : BASE_ANIMATION_DURATION_MS); + if (!isZoomIn) { + scaleAnimator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + // Restore normal background status. + backgroundParams.setMargins(cardBackgroundMargin, cardBackgroundMargin, + cardBackgroundMargin, cardBackgroundMargin); + backgroundView.setBackground(normalBackground); + } + }); + } + ObjectAnimator scaleX = ObjectAnimator.ofFloat(animateView, "scaleX", scale); + ObjectAnimator scaleY = ObjectAnimator.ofFloat(animateView, "scaleY", scale); + scaleX.setDuration(duration); + scaleY.setDuration(duration); scaleAnimator.play(scaleX).with(scaleY); scaleAnimator.start(); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadUtils.java index 92932ff..99d8efc9 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadUtils.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadUtils.java
@@ -255,6 +255,10 @@ * @param isOffTheRecord Whether to check downloads for the off the record profile. */ public static void checkForExternallyRemovedDownloads(boolean isOffTheRecord) { + if (ChromeFeatureList.isEnabled(ChromeFeatureList.DOWNLOAD_OFFLINE_CONTENT_PROVIDER)) { + return; + } + if (isOffTheRecord) { DownloadManagerService.getDownloadManagerService().checkForExternallyRemovedDownloads( true);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/home/glue/DownloadGlue.java b/chrome/android/java/src/org/chromium/chrome/browser/download/home/glue/DownloadGlue.java index b178b9e74..bfff758e 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/download/home/glue/DownloadGlue.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/home/glue/DownloadGlue.java
@@ -65,7 +65,12 @@ @Override public void onDownloadItemUpdated(DownloadItem item) { if (!canShowDownloadItem(item)) return; - mDelegate.onItemUpdated(DownloadItem.createOfflineItem(item), null); + OfflineItem offlineItem = DownloadItem.createOfflineItem(item); + mDelegate.onItemUpdated(offlineItem, null); + + if (offlineItem.externallyRemoved) { + new Handler().post(() -> removeItem(offlineItem)); + } } /** @see OfflineContentProvider.Observer#onItemRemoved(ContentId) */
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/TabSwitcherModeTTPhone.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/TabSwitcherModeTTPhone.java index d08b04a8f..446fd69 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/TabSwitcherModeTTPhone.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/TabSwitcherModeTTPhone.java
@@ -385,7 +385,7 @@ .getFieldTrialParamByFeature(ChromeFeatureList.TAB_GRID_LAYOUT_ANDROID, "tab_grid_layout_android_new_tab") .equals("NewTabVariation") - || ChromeFeatureList.isEnabled(ChromeFeatureList.CHROME_DUET)) { + || FeatureUtilities.isBottomToolbarEnabled()) { return; } boolean hasIncognitoTabs =
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarPhone.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarPhone.java index 7e50fa7..737e9c76 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarPhone.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarPhone.java
@@ -937,9 +937,9 @@ // toolbar is not visible (e.g. in tab switcher mode). if (isInTabSwitcherMode()) return; + int toolbarButtonVisibility = getToolbarButtonVisibility(); + mToolbarButtonsContainer.setVisibility(toolbarButtonVisibility); if (!mIsBottomToolbarVisible && !getToolbarDataProvider().isInOverviewAndShowingOmnibox()) { - int toolbarButtonVisibility = getToolbarButtonVisibility(); - mToolbarButtonsContainer.setVisibility(toolbarButtonVisibility); if (mHomeButton != null && mHomeButton.getVisibility() != GONE) { mHomeButton.setVisibility(toolbarButtonVisibility); }
diff --git a/chrome/android/java/strings/android_chrome_strings.grd b/chrome/android/java/strings/android_chrome_strings.grd index 092fda70..d85d798f 100644 --- a/chrome/android/java/strings/android_chrome_strings.grd +++ b/chrome/android/java/strings/android_chrome_strings.grd
@@ -3912,17 +3912,17 @@ <message name="IDS_SEND_TAB_TO_SELF_INFOBAR_MESSAGE_URL" desc="Clickable text displayed as part of a URL in the inforbar displayed when a user receives a shared tab from another device."> Open </message> - <message name="IDS_SEND_TAB_TO_SELF_CONTENT_DESCRIPTION" desc="Content description for the target device picker."> - Device picker to share a tab with. + <message name="IDS_SEND_TAB_TO_SELF_CONTENT_DESCRIPTION" desc="Accessibility string read when the bottom sheet is opened. It describes the bottom sheet where a user can pick a device to share the tab with."> + List of devices to share a tab with. </message> - <message name="IDS_SEND_TAB_TO_SELF_SHEET_HALF_HEIGHT" desc="Accessibility string read when the target device picker sheet is opened at half height. The sheet will occupy the bottom half the screen."> - Device picker to share a tab with is opened at half height. + <message name="IDS_SEND_TAB_TO_SELF_SHEET_HALF_HEIGHT" desc="Accessibility string read when the bottom sheet showing a list of the user's devices is opened at half height. The sheet will occupy the bottom half the screen."> + List of devices to share a tab with opened at half height. </message> - <message name="IDS_SEND_TAB_TO_SELF_SHEET_FULL_HEIGHT" desc="Accessibility string read when the target device picker sheet is opened at full height. The sheet will occupy the entire screen."> - Device picker to share a tab with is opened at full height. + <message name="IDS_SEND_TAB_TO_SELF_SHEET_FULL_HEIGHT" desc="Accessibility string read when the bottom sheet showing a list of the user's devices is opened at full height. The sheet will occupy the entire screen."> + List of devices to share a tab with opened at full height. </message> - <message name="IDS_SEND_TAB_TO_SELF_SHEET_CLOSED" desc="Accessibility string read when the target device picker sheet is closed."> - Device picker to share a tab with is closed. + <message name="IDS_SEND_TAB_TO_SELF_SHEET_CLOSED" desc="Accessibility string read when the bottom sheet showing a list of the user's devices is closed."> + List of devices to share a tab with is closed. </message> <message name="IDS_SEND_TAB_TO_SELF_SHEET_TOOLBAR" desc="Header for device picker sheet where users can pick a device to send a tab to."> Send to
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/OmniboxTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/OmniboxTest.java index 5bfe280..5f9a5e4 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/OmniboxTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/OmniboxTest.java
@@ -781,6 +781,7 @@ @Feature({"Omnibox"}) @RetryOnFailure @MinAndroidSdkLevel(Build.VERSION_CODES.JELLY_BEAN_MR1) + @DisabledTest // https://crbug.com/950556 public void testSuggestionDirectionSwitching() throws InterruptedException { final TextView urlBarView = (TextView) mActivityTestRule.getActivity().findViewById(R.id.url_bar);
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index b79a4cd..d7ba61f 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -1424,12 +1424,12 @@ {"shelf-dense-clamshell", flag_descriptions::kShelfDenseClamshellName, flag_descriptions::kShelfDenseClamshellDescription, kOsCrOS, SINGLE_VALUE_TYPE(chromeos::switches::kShelfDenseClamshell)}, + {"shelf-hotseat", flag_descriptions::kShelfHotseatName, + flag_descriptions::kShelfHotseatDescription, kOsCrOS, + SINGLE_VALUE_TYPE(chromeos::switches::kShelfHotseat)}, {"shelf-hover-previews", flag_descriptions::kShelfHoverPreviewsName, flag_descriptions::kShelfHoverPreviewsDescription, kOsCrOS, SINGLE_VALUE_TYPE(chromeos::switches::kShelfHoverPreviews)}, - {"shelf-new-ui", flag_descriptions::kShelfNewUiName, - flag_descriptions::kShelfNewUiDescription, kOsCrOS, - SINGLE_VALUE_TYPE(chromeos::switches::kShelfNewUi)}, {"shelf-scrollable", flag_descriptions::kShelfScrollableName, flag_descriptions::kShelfScrollableDescription, kOsCrOS, SINGLE_VALUE_TYPE(chromeos::switches::kShelfScrollable)},
diff --git a/chrome/browser/android/autofill_assistant/client_android.cc b/chrome/browser/android/autofill_assistant/client_android.cc index ce8b01c..8e450ff 100644 --- a/chrome/browser/android/autofill_assistant/client_android.cc +++ b/chrome/browser/android/autofill_assistant/client_android.cc
@@ -103,15 +103,6 @@ java_object_); } -void ClientAndroid::ShowOnboarding( - JNIEnv* env, - const base::android::JavaParamRef<jobject>& jcaller, - const JavaParamRef<jstring>& jexperiment_ids, - const JavaParamRef<jobject>& on_accept) { - ShowUI(); - ui_controller_android_->ShowOnboarding(env, jexperiment_ids, on_accept); -} - base::android::ScopedJavaLocalRef<jobject> ClientAndroid::GetJavaObject() { return base::android::ScopedJavaLocalRef<jobject>(java_object_); } @@ -121,8 +112,15 @@ const JavaParamRef<jstring>& jinitial_url, const JavaParamRef<jstring>& jexperiment_ids, const JavaParamRef<jobjectArray>& parameterNames, - const JavaParamRef<jobjectArray>& parameterValues) { + const JavaParamRef<jobjectArray>& parameterValues, + const JavaParamRef<jobject>& joverlay_coordinator) { CreateController(); + + // If an overlay is already shown, then show the rest of the UI. + if (joverlay_coordinator) { + CreateUI(joverlay_coordinator); + } + GURL initial_url(base::android::ConvertJavaStringToUTF8(env, jinitial_url)); std::map<std::string, std::string> parameters; FillParametersFromJava(env, parameterNames, parameterValues, ¶meters); @@ -191,13 +189,19 @@ // onboarding. } if (!ui_controller_android_) { - std::unique_ptr<UiControllerAndroid> ui_ptr = - UiControllerAndroid::CreateFromWebContents(web_contents_); - if (ui_ptr) - SetUI(std::move(ui_ptr)); + CreateUI(nullptr); } } +void ClientAndroid::CreateUI( + const JavaParamRef<jobject>& joverlay_coordinator) { + std::unique_ptr<UiControllerAndroid> ui_ptr = + UiControllerAndroid::CreateFromWebContents(web_contents_, + joverlay_coordinator); + if (ui_ptr) + SetUI(std::move(ui_ptr)); +} + void ClientAndroid::DestroyUI() { ui_controller_android_.reset(); }
diff --git a/chrome/browser/android/autofill_assistant/client_android.h b/chrome/browser/android/autofill_assistant/client_android.h index fac273d..478fd24 100644 --- a/chrome/browser/android/autofill_assistant/client_android.h +++ b/chrome/browser/android/autofill_assistant/client_android.h
@@ -38,19 +38,13 @@ // Returns the corresponding Java AutofillAssistantClient. base::android::ScopedJavaLocalRef<jobject> GetJavaObject(); - // Called from the Java side: - void ShowOnboarding( - JNIEnv* env, - const base::android::JavaParamRef<jobject>& jcaller, - const base::android::JavaParamRef<jstring>& jexperiment_ids, - const base::android::JavaParamRef<jobject>& on_accept); - void Start(JNIEnv* env, const base::android::JavaParamRef<jobject>& jcaller, const base::android::JavaParamRef<jstring>& jinitial_url, const base::android::JavaParamRef<jstring>& jexperiment_ids, const base::android::JavaParamRef<jobjectArray>& parameterNames, - const base::android::JavaParamRef<jobjectArray>& parameterValues); + const base::android::JavaParamRef<jobjectArray>& parameterValues, + const base::android::JavaParamRef<jobject>& joverlay_coordinator); void DestroyUI(JNIEnv* env, const base::android::JavaParamRef<jobject>& jcaller); void TransferUITo( @@ -90,6 +84,8 @@ explicit ClientAndroid(content::WebContents* web_contents); void CreateController(); void DestroyController(); + void CreateUI( + const base::android::JavaParamRef<jobject>& joverlay_coordinator); bool NeedsUI(); void SetUI(std::unique_ptr<UiControllerAndroid> ui_controller_android);
diff --git a/chrome/browser/android/autofill_assistant/ui_controller_android.cc b/chrome/browser/android/autofill_assistant/ui_controller_android.cc index 94ca49e..d931a43 100644 --- a/chrome/browser/android/autofill_assistant/ui_controller_android.cc +++ b/chrome/browser/android/autofill_assistant/ui_controller_android.cc
@@ -62,23 +62,37 @@ static constexpr base::TimeDelta kGracefulShutdownDelay = base::TimeDelta::FromSeconds(5); +std::vector<float> ToFloatVector(const std::vector<RectF>& areas) { + std::vector<float> flattened; + for (const auto& rect : areas) { + flattened.emplace_back(rect.left); + flattened.emplace_back(rect.top); + flattened.emplace_back(rect.right); + flattened.emplace_back(rect.bottom); + } + return flattened; +} + } // namespace // static std::unique_ptr<UiControllerAndroid> UiControllerAndroid::CreateFromWebContents( - content::WebContents* web_contents) { + content::WebContents* web_contents, + const base::android::JavaParamRef<jobject>& joverlay_coordinator) { JNIEnv* env = AttachCurrentThread(); auto jactivity = Java_AutofillAssistantUiController_findAppropriateActivity( env, web_contents->GetJavaWebContents()); if (!jactivity) { return nullptr; } - return std::make_unique<UiControllerAndroid>(env, jactivity); + return std::make_unique<UiControllerAndroid>(env, jactivity, + joverlay_coordinator); } UiControllerAndroid::UiControllerAndroid( JNIEnv* env, - const base::android::JavaRef<jobject>& jactivity) + const base::android::JavaRef<jobject>& jactivity, + const base::android::JavaParamRef<jobject>& joverlay_coordinator) : overlay_delegate_(this), header_delegate_(this), payment_request_delegate_(this), @@ -88,7 +102,7 @@ env, jactivity, /* allowTabSwitching= */ base::FeatureList::IsEnabled(features::kAutofillAssistantChromeEntry), - reinterpret_cast<intptr_t>(this)); + reinterpret_cast<intptr_t>(this), joverlay_coordinator); // Register overlay_delegate_ as delegate for the overlay. Java_AssistantOverlayModel_setDelegate(env, GetOverlayModel(), @@ -135,9 +149,11 @@ std::vector<RectF> area; ui_delegate->GetTouchableArea(&area); + std::vector<RectF> restricted_area; + ui_delegate->GetRestrictedArea(&restricted_area); RectF visual_viewport; ui_delegate->GetVisualViewport(&visual_viewport); - OnTouchableAreaChanged(visual_viewport, area); + OnTouchableAreaChanged(visual_viewport, area, restricted_area); OnResizeViewportChanged(ui_delegate->GetResizeViewport()); OnPeekModeChanged(ui_delegate->GetPeekMode()); OnFormChanged(ui_delegate->GetForm()); @@ -530,21 +546,20 @@ void UiControllerAndroid::OnTouchableAreaChanged( const RectF& visual_viewport, - const std::vector<RectF>& areas) { + const std::vector<RectF>& touchable_areas, + const std::vector<RectF>& restricted_areas) { JNIEnv* env = AttachCurrentThread(); Java_AssistantOverlayModel_setVisualViewport( env, GetOverlayModel(), visual_viewport.left, visual_viewport.top, visual_viewport.right, visual_viewport.bottom); - std::vector<float> flattened; - for (const auto& rect : areas) { - flattened.emplace_back(rect.left); - flattened.emplace_back(rect.top); - flattened.emplace_back(rect.right); - flattened.emplace_back(rect.bottom); - } Java_AssistantOverlayModel_setTouchableArea( - env, GetOverlayModel(), base::android::ToJavaFloatArray(env, flattened)); + env, GetOverlayModel(), + base::android::ToJavaFloatArray(env, ToFloatVector(touchable_areas))); + + Java_AssistantOverlayModel_setRestrictedArea( + AttachCurrentThread(), GetOverlayModel(), + base::android::ToJavaFloatArray(env, ToFloatVector(restricted_areas))); } void UiControllerAndroid::OnUnexpectedTaps() { @@ -566,14 +581,6 @@ // Other methods. -void UiControllerAndroid::ShowOnboarding( - JNIEnv* env, - const base::android::JavaParamRef<jstring>& jexperiment_ids, - const base::android::JavaParamRef<jobject>& on_accept) { - Java_AutofillAssistantUiController_onShowOnboarding( - env, java_object_, jexperiment_ids, on_accept); -} - void UiControllerAndroid::WillShutdown(Metrics::DropOutReason reason) { if (reason == Metrics::CUSTOM_TAB_CLOSED) { Java_AutofillAssistantUiController_scheduleCloseCustomTab(
diff --git a/chrome/browser/android/autofill_assistant/ui_controller_android.h b/chrome/browser/android/autofill_assistant/ui_controller_android.h index cabcf97..4c5ae6a9 100644 --- a/chrome/browser/android/autofill_assistant/ui_controller_android.h +++ b/chrome/browser/android/autofill_assistant/ui_controller_android.h
@@ -31,15 +31,18 @@ class UiControllerAndroid : public UiController { public: static std::unique_ptr<UiControllerAndroid> CreateFromWebContents( - content::WebContents* web_contents); + content::WebContents* web_contents, + const base::android::JavaParamRef<jobject>& joverlay_coordinator); // pointers to |web_contents|, |client| must remain valid for the lifetime of // this instance. // // Pointer to |ui_delegate| must remain valid for the lifetime of this // instance or until WillShutdown is called. - UiControllerAndroid(JNIEnv* env, - const base::android::JavaRef<jobject>& jactivity); + UiControllerAndroid( + JNIEnv* env, + const base::android::JavaRef<jobject>& jactivity, + const base::android::JavaParamRef<jobject>& joverlay_coordinator); ~UiControllerAndroid() override; // Attaches the UI to the given client, its web contents and delegate. @@ -53,12 +56,6 @@ Client* client, UiDelegate* ui_delegate); - // Called by ClientAndroid. - void ShowOnboarding( - JNIEnv* env, - const base::android::JavaParamRef<jstring>& jexperiment_ids, - const base::android::JavaParamRef<jobject>& on_accept); - // Overrides UiController: void OnStateChanged(AutofillAssistantState new_state) override; void OnStatusMessageChanged(const std::string& message) override; @@ -73,8 +70,10 @@ void OnInfoBoxChanged(const InfoBox* info_box) override; void OnProgressChanged(int progress) override; void OnProgressVisibilityChanged(bool visible) override; - void OnTouchableAreaChanged(const RectF& visual_viewport, - const std::vector<RectF>& areas) override; + void OnTouchableAreaChanged( + const RectF& visual_viewport, + const std::vector<RectF>& touchable_areas, + const std::vector<RectF>& restricted_areas) override; void OnResizeViewportChanged(bool resize_viewport) override; void OnPeekModeChanged( ConfigureBottomSheetProto::PeekMode peek_mode) override;
diff --git a/chrome/browser/apps/app_service/app_service_proxy_impl.cc b/chrome/browser/apps/app_service/app_service_proxy_impl.cc index d786ea5..a600b9ea 100644 --- a/chrome/browser/apps/app_service/app_service_proxy_impl.cc +++ b/chrome/browser/apps/app_service/app_service_proxy_impl.cc
@@ -74,17 +74,29 @@ AppServiceProxyFactory::GetForProfile(profile)); } +// static +AppServiceProxyImpl* AppServiceProxyImpl::CreateForTesting( + Profile* profile, + service_manager::Connector* connector) { + return new AppServiceProxyImpl(profile, connector); +} + AppServiceProxyImpl::AppServiceProxyImpl(Profile* profile) + : AppServiceProxyImpl(profile, nullptr) {} + +AppServiceProxyImpl::AppServiceProxyImpl(Profile* profile, + service_manager::Connector* connector) : inner_icon_loader_(this), outer_icon_loader_(&inner_icon_loader_, apps::IconCache::GarbageCollectionPolicy::kEager) { if (!profile) { return; } - service_manager::Connector* connector = - content::BrowserContext::GetConnectorFor(profile); if (!connector) { - return; + connector = content::BrowserContext::GetConnectorFor(profile); + if (!connector) { + return; + } } connector->BindInterface(apps::mojom::kServiceName, mojo::MakeRequest(&app_service_));
diff --git a/chrome/browser/apps/app_service/app_service_proxy_impl.h b/chrome/browser/apps/app_service/app_service_proxy_impl.h index 721bec5..b914842 100644 --- a/chrome/browser/apps/app_service/app_service_proxy_impl.h +++ b/chrome/browser/apps/app_service/app_service_proxy_impl.h
@@ -21,6 +21,10 @@ class Profile; +namespace service_manager { +class Connector; +} + namespace apps { // Singleton (per Profile) proxy and cache of an App Service's apps. @@ -41,6 +45,10 @@ // instead. static AppServiceProxyImpl* GetImplForTesting(Profile* profile); + static AppServiceProxyImpl* CreateForTesting( + Profile* profile, + service_manager::Connector* connector); + explicit AppServiceProxyImpl(Profile* profile); ~AppServiceProxyImpl() override; @@ -132,6 +140,8 @@ apps::IconLoader* overriding_icon_loader_for_testing_; }; + AppServiceProxyImpl(Profile* profile, service_manager::Connector* connector); + // KeyedService overrides. void Shutdown() override;
diff --git a/chrome/browser/apps/app_service/arc_apps.cc b/chrome/browser/apps/app_service/arc_apps.cc index 4fc0ce60..71c65ab 100644 --- a/chrome/browser/apps/app_service/arc_apps.cc +++ b/chrome/browser/apps/app_service/arc_apps.cc
@@ -161,15 +161,25 @@ return ArcAppsFactory::GetForProfile(profile); } -ArcApps::ArcApps(Profile* profile) +// static +ArcApps* ArcApps::CreateForTesting(Profile* profile, + apps::AppServiceProxy* proxy) { + return new ArcApps(profile, proxy); +} + +ArcApps::ArcApps(Profile* profile) : ArcApps(profile, nullptr) {} + +ArcApps::ArcApps(Profile* profile, apps::AppServiceProxy* proxy) : binding_(this), profile_(profile), prefs_(nullptr) { if (!arc::IsArcAllowedForProfile(profile_) || (arc::ArcServiceManager::Get() == nullptr)) { return; } - apps::mojom::AppServicePtr& app_service = - apps::AppServiceProxyFactory::GetForProfile(profile)->AppService(); + if (!proxy) { + proxy = apps::AppServiceProxyFactory::GetForProfile(profile); + } + apps::mojom::AppServicePtr& app_service = proxy->AppService(); if (!app_service.is_bound()) { return; }
diff --git a/chrome/browser/apps/app_service/arc_apps.h b/chrome/browser/apps/app_service/arc_apps.h index 43e75f3..28de1334 100644 --- a/chrome/browser/apps/app_service/arc_apps.h +++ b/chrome/browser/apps/app_service/arc_apps.h
@@ -25,6 +25,8 @@ namespace apps { +class AppServiceProxy; + // An app publisher (in the App Service sense) of ARC++ apps, // // See chrome/services/app_service/README.md. @@ -38,11 +40,16 @@ static ArcApps* Get(Profile* profile); + static ArcApps* CreateForTesting(Profile* profile, + apps::AppServiceProxy* proxy); + explicit ArcApps(Profile* profile); ~ArcApps() override; private: + ArcApps(Profile* profile, apps::AppServiceProxy* proxy); + // apps::mojom::Publisher overrides. void Connect(apps::mojom::SubscriberPtr subscriber, apps::mojom::ConnectOptionsPtr opts) override;
diff --git a/chrome/browser/browser_keyevents_browsertest.cc b/chrome/browser/browser_keyevents_browsertest.cc index 7895c76..580b3b4 100644 --- a/chrome/browser/browser_keyevents_browsertest.cc +++ b/chrome/browser/browser_keyevents_browsertest.cc
@@ -25,7 +25,6 @@ #include "content/public/browser/web_contents.h" #include "content/public/test/browser_test_utils.h" #include "net/test/embedded_test_server/embedded_test_server.h" -#include "ui/base/ui_base_features.h" #include "ui/events/keycodes/keyboard_codes.h" // TODO(kbr): remove: http://crbug.com/222296 @@ -528,14 +527,6 @@ #define MAYBE_AccessKeys AccessKeys #endif IN_PROC_BROWSER_TEST_F(BrowserKeyEventsTest, MAYBE_AccessKeys) { - // TODO(crbug.com/916379): this test fails in mash because of differences in - // timing. In particular, in classic mode an accelerator that moves focus is - // processed *after* text is inserted, where as now the accelerator runs - // first, resulting in text going to the wrong place. The right fix likely - // entails updating the test for mash. - if (features::IsSingleProcessMash()) - return; - #if defined(OS_MACOSX) // On Mac, access keys use ctrl+alt modifiers. static const KeyEventTestData kTestAccessA = {
diff --git a/chrome/browser/chrome_content_browser_client_browsertest_chromeos.cc b/chrome/browser/chrome_content_browser_client_browsertest_chromeos.cc deleted file mode 100644 index 80aa8eb..0000000 --- a/chrome/browser/chrome_content_browser_client_browsertest_chromeos.cc +++ /dev/null
@@ -1,90 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/chrome_content_browser_client.h" - -#include "base/base_switches.h" -#include "base/bind.h" -#include "base/command_line.h" -#include "base/files/file_path.h" -#include "base/files/file_util.h" -#include "base/run_loop.h" -#include "base/task/post_task.h" -#include "base/threading/thread_restrictions.h" -#include "chrome/common/chrome_switches.h" -#include "chrome/test/base/in_process_browser_test.h" -#include "content/public/browser/browser_child_process_host_iterator.h" -#include "content/public/browser/browser_task_traits.h" -#include "content/public/browser/browser_thread.h" -#include "content/public/browser/child_process_data.h" -#include "content/public/common/process_type.h" -#include "ui/base/ui_base_features.h" - -using content::BrowserChildProcessHostIterator; -using content::BrowserThread; - -namespace { - -void GetUtilityProcessPidsOnIOThread(std::vector<pid_t>* pids) { - for (BrowserChildProcessHostIterator it(content::PROCESS_TYPE_UTILITY); - !it.Done(); ++it) { - pid_t pid = it.GetData().GetProcess().Pid(); - pids->push_back(pid); - } -} - -std::string ReadCmdLine(pid_t pid) { - // Files in "/proc" are in-memory, so it's safe to do IO. - base::ScopedAllowBlockingForTesting allow_io; - base::FilePath cmdline_file = base::FilePath("/proc") - .Append(base::NumberToString(pid)) - .Append("cmdline"); - std::string cmdline; - base::ReadFileToString(cmdline_file, &cmdline); - return cmdline; -} - -// We don't seem to have a string utility or STL utility for this. -bool HasSubstring(base::StringPiece str, base::StringPiece sub) { - return str.find(sub) != base::StringPiece::npos; -} - -} // namespace - -using ChromeContentBrowserClientMashTest = InProcessBrowserTest; - -// Verifies that mash service child processes use in-process breakpad crash -// dumping. -IN_PROC_BROWSER_TEST_F(ChromeContentBrowserClientMashTest, CrashReporter) { - // Test only applies to out-of-process. - if (!features::IsMultiProcessMash()) - return; - - // Child process management lives on the IO thread. - std::vector<pid_t> pids; - base::RunLoop loop; - base::PostTaskWithTraitsAndReply( - FROM_HERE, {BrowserThread::IO}, - base::Bind(&GetUtilityProcessPidsOnIOThread, &pids), loop.QuitClosure()); - loop.Run(); - ASSERT_FALSE(pids.empty()); - - // Iterate through all utility processes looking for mash services. We are - // guaranteed at least ash and mus have launched because we block during - // startup waiting for mus. - int mash_service_count = 0; - for (pid_t pid : pids) { - std::string cmdline = ReadCmdLine(pid); - ASSERT_FALSE(cmdline.empty()); - // Subprocess command lines may have their null separators replaced with - // spaces, which makes them hard to tokenize. Just search the whole string. - if (HasSubstring(cmdline, switches::kMashServiceName)) { - ++mash_service_count; - // Mash services use in-process breakpad crash dumping. - EXPECT_TRUE(HasSubstring(cmdline, switches::kEnableCrashReporter)); - } - } - // There's at least one mash service, for ash. - EXPECT_GT(mash_service_count, 0); -}
diff --git a/chrome/browser/chromeos/accessibility/accessibility_manager.cc b/chrome/browser/chromeos/accessibility/accessibility_manager.cc index 237eeb3cb..977131e 100644 --- a/chrome/browser/chromeos/accessibility/accessibility_manager.cc +++ b/chrome/browser/chromeos/accessibility/accessibility_manager.cc
@@ -90,7 +90,6 @@ #include "ui/accessibility/ax_enum_util.h" #include "ui/base/ime/chromeos/extension_ime_util.h" #include "ui/base/resource/resource_bundle.h" -#include "ui/base/ui_base_features.h" #include "ui/views/widget/widget.h" #include "ui/views/widget/widget_observer.h" #include "url/gurl.h" @@ -394,10 +393,6 @@ if (!profile_) return; - // TODO(crbug.com/594887): Fix for mash by moving pref into ash. - if (features::IsMultiProcessMash()) - return; - // Update system tray menu visibility. ash::Shell::Get() ->accessibility_controller() @@ -991,13 +986,9 @@ input_method::InputMethodManager* manager, Profile* /* profile */, bool show_message) { - // Sticky keys is implemented only in ash. - // TODO(crbug.com/678820): Mash support. - if (!features::IsMultiProcessMash()) { ash::Shell::Get()->sticky_keys_controller()->SetModifiersEnabled( manager->IsISOLevel5ShiftUsedByCurrentInputMethod(), manager->IsAltGrUsedByCurrentInputMethod()); - } const chromeos::input_method::InputMethodDescriptor descriptor = manager->GetActiveIMEState()->GetCurrentInputMethod(); braille_ime_current_ = @@ -1162,10 +1153,6 @@ const AccessibilityStatusEventDetails& details) { callback_list_.Notify(details); - // TODO(crbug.com/594887): Fix for mash by moving pref into ash. - if (features::IsMultiProcessMash()) - return; - if (details.notification_type == ACCESSIBILITY_TOGGLE_DICTATION) { ash::Shell::Get()->accessibility_controller()->SetDictationActive( details.enabled);
diff --git a/chrome/browser/chromeos/accessibility/accessibility_panel.cc b/chrome/browser/chromeos/accessibility/accessibility_panel.cc index fa174187..1241c80c 100644 --- a/chrome/browser/chromeos/accessibility/accessibility_panel.cc +++ b/chrome/browser/chromeos/accessibility/accessibility_panel.cc
@@ -14,7 +14,6 @@ #include "content/public/common/service_manager_connection.h" #include "extensions/browser/view_type_utils.h" #include "services/service_manager/public/cpp/connector.h" -#include "ui/base/ui_base_features.h" #include "ui/display/display.h" #include "ui/display/screen.h" #include "ui/views/controls/webview/webview.h" @@ -70,14 +69,6 @@ params.name = widget_name; params.shadow_elevation = wm::kShadowElevationInactiveWindow; widget_->Init(params); - - // WebContentsObserver::DidFirstVisuallyNonEmptyPaint is not called under - // mash. Work around this by showing the window immediately. - // TODO(jamescook|fsamuel): Fix this. It causes a white flash when opening the - // window. The underlying problem is FrameToken plumbing, see - // ui::ws::ServerWindow::OnFrameTokenChanged. https://crbug.com/771331 - if (features::IsMultiProcessMash()) - widget_->Show(); } AccessibilityPanel::~AccessibilityPanel() = default;
diff --git a/chrome/browser/chromeos/arc/fileapi/arc_file_system_bridge.cc b/chrome/browser/chromeos/arc/fileapi/arc_file_system_bridge.cc index 61803df3..d81cede1 100644 --- a/chrome/browser/chromeos/arc/fileapi/arc_file_system_bridge.cc +++ b/chrome/browser/chromeos/arc/fileapi/arc_file_system_bridge.cc
@@ -342,6 +342,7 @@ } void ArcFileSystemBridge::GetFileSelectorElements( + mojom::GetFileSelectorElementsRequestPtr request, GetFileSelectorElementsCallback callback) { if (!IsTestImageBuild()) { LOG(ERROR) @@ -349,7 +350,8 @@ std::move(callback).Run(mojom::FileSelectorElements::New()); return; } - select_files_handler_->GetFileSelectorElements(std::move(callback)); + select_files_handler_->GetFileSelectorElements(std::move(request), + std::move(callback)); } void ArcFileSystemBridge::OpenFileToReadAfterGetFileSize(
diff --git a/chrome/browser/chromeos/arc/fileapi/arc_file_system_bridge.h b/chrome/browser/chromeos/arc/fileapi/arc_file_system_bridge.h index c746c1e..a128068 100644 --- a/chrome/browser/chromeos/arc/fileapi/arc_file_system_bridge.h +++ b/chrome/browser/chromeos/arc/fileapi/arc_file_system_bridge.h
@@ -92,6 +92,7 @@ void OnFileSelectorEvent(mojom::FileSelectorEventPtr event, OnFileSelectorEventCallback callback) override; void GetFileSelectorElements( + mojom::GetFileSelectorElementsRequestPtr request, GetFileSelectorElementsCallback callback) override; private:
diff --git a/chrome/browser/chromeos/arc/fileapi/arc_select_files_handler.cc b/chrome/browser/chromeos/arc/fileapi/arc_select_files_handler.cc index 2cc0da4e..474d632 100644 --- a/chrome/browser/chromeos/arc/fileapi/arc_select_files_handler.cc +++ b/chrome/browser/chromeos/arc/fileapi/arc_select_files_handler.cc
@@ -186,7 +186,7 @@ request->action_type == mojom::SelectFilesActionType::GET_CONTENT; dialog_holder_->SelectFile(dialog_type, default_path, &file_type_info, - show_android_picker_apps); + request->task_id, show_android_picker_apps); } void ArcSelectFilesHandler::FileSelected(const base::FilePath& path, @@ -275,6 +275,7 @@ } void ArcSelectFilesHandler::GetFileSelectorElements( + mojom::GetFileSelectorElementsRequestPtr request, mojom::FileSystemHost::GetFileSelectorElementsCallback callback) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); @@ -304,6 +305,7 @@ ui::SelectFileDialog::Type type, const base::FilePath& default_path, const ui::SelectFileDialog::FileTypeInfo* file_types, + int task_id, bool show_android_picker_apps) { select_file_dialog_->SelectFileWithFileManagerParams( type,
diff --git a/chrome/browser/chromeos/arc/fileapi/arc_select_files_handler.h b/chrome/browser/chromeos/arc/fileapi/arc_select_files_handler.h index e215cc0..112df25 100644 --- a/chrome/browser/chromeos/arc/fileapi/arc_select_files_handler.h +++ b/chrome/browser/chromeos/arc/fileapi/arc_select_files_handler.h
@@ -46,6 +46,7 @@ mojom::FileSystemHost::OnFileSelectorEventCallback callback); void GetFileSelectorElements( + mojom::GetFileSelectorElementsRequestPtr request, mojom::FileSystemHost::GetFileSelectorElementsCallback callback); // ui::SelectFileDialog::Listener overrides: @@ -84,6 +85,7 @@ virtual void SelectFile(ui::SelectFileDialog::Type type, const base::FilePath& default_path, const ui::SelectFileDialog::FileTypeInfo* file_types, + int task_id, bool show_android_picker_apps); virtual void ExecuteJavaScript(
diff --git a/chrome/browser/chromeos/arc/fileapi/arc_select_files_handler_unittest.cc b/chrome/browser/chromeos/arc/fileapi/arc_select_files_handler_unittest.cc index 7b90241..f15dcc49 100644 --- a/chrome/browser/chromeos/arc/fileapi/arc_select_files_handler_unittest.cc +++ b/chrome/browser/chromeos/arc/fileapi/arc_select_files_handler_unittest.cc
@@ -79,10 +79,11 @@ explicit MockSelectFileDialogHolder(ui::SelectFileDialog::Listener* listener) : SelectFileDialogHolder(listener) {} ~MockSelectFileDialogHolder() override = default; - MOCK_METHOD4(SelectFile, + MOCK_METHOD5(SelectFile, void(ui::SelectFileDialog::Type type, const base::FilePath& default_path, const ui::SelectFileDialog::FileTypeInfo* file_types, + int task_id, bool show_android_picker_apps)); MOCK_METHOD2(ExecuteJavaScript, void(const std::string&, JavaScriptResultCallback)); @@ -128,7 +129,7 @@ request->allow_multiple = request_allow_multiple; EXPECT_CALL(*mock_dialog_holder_, - SelectFile(expected_dialog_type, _, _, + SelectFile(expected_dialog_type, _, _, _, expected_show_android_picker_apps)) .Times(1); @@ -185,6 +186,7 @@ SelectFilesRequestPtr request = SelectFilesRequest::New(); request->action_type = SelectFilesActionType::OPEN_DOCUMENT; request->mime_types.push_back("text/plain"); + request->task_id = 1234; SelectFileDialog::FileTypeInfo expected_file_type_info; expected_file_type_info.allowed_paths = @@ -198,7 +200,7 @@ *mock_dialog_holder_, SelectFile(_, _, testing::Pointee(FileTypeInfoMatcher(expected_file_type_info)), - _)) + 1234, _)) .Times(1); base::MockCallback<SelectFilesCallback> callback; @@ -217,7 +219,7 @@ "/special/arc-documents-provider/testing.provider/doc:root"); EXPECT_CALL(*mock_dialog_holder_, - SelectFile(_, FilePathMatcher(expected_file_path), _, _)) + SelectFile(_, FilePathMatcher(expected_file_path), _, _, _)) .Times(1); base::MockCallback<SelectFilesCallback> callback; @@ -309,7 +311,8 @@ Run(FileSelectorElementsMatcher(expectedElements.get()))) .Times(1); - arc_select_files_handler_->GetFileSelectorElements(callback.Get()); + arc_select_files_handler_->GetFileSelectorElements( + arc::mojom::GetFileSelectorElementsRequest::New(), callback.Get()); } } // namespace arc
diff --git a/chrome/browser/chromeos/chrome_browser_main_chromeos.cc b/chrome/browser/chromeos/chrome_browser_main_chromeos.cc index 96644cfc..97b4d28a 100644 --- a/chrome/browser/chromeos/chrome_browser_main_chromeos.cc +++ b/chrome/browser/chromeos/chrome_browser_main_chromeos.cc
@@ -288,9 +288,7 @@ class DBusServices { public: explicit DBusServices(const content::MainFunctionParams& parameters) { - // In Mash, power policy is sent to powerd by ash. - if (!::features::IsMultiProcessMash()) - PowerPolicyController::Initialize(PowerManagerClient::Get()); + PowerPolicyController::Initialize(PowerManagerClient::Get()); dbus::Bus* system_bus = DBusThreadManager::Get()->IsUsingFakes() ? nullptr @@ -406,8 +404,7 @@ drive_file_stream_service_.reset(); ProcessDataCollector::Shutdown(); PowerDataCollector::Shutdown(); - if (!::features::IsMultiProcessMash()) - PowerPolicyController::Shutdown(); + PowerPolicyController::Shutdown(); device::BluetoothAdapterFactory::Shutdown(); } @@ -754,12 +751,9 @@ AccessibilityManager::Initialize(); - if (!::features::IsMultiProcessMash()) { - // Initialize magnification manager before ash tray is created. And this - // must be placed after UserManager::SessionStarted(); - // TODO(crbug.com/821551): Mash support. - MagnificationManager::Initialize(); - } + // Initialize magnification manager before ash tray is created. And this + // must be placed after UserManager::SessionStarted(); + MagnificationManager::Initialize(); base::PostTaskWithTraitsAndReplyWithResult( FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT}, @@ -1122,8 +1116,7 @@ if (LoginScreenExtensionUiHandler::Get(false /*can_create*/)) LoginScreenExtensionUiHandler::Shutdown(); - if (!::features::IsMultiProcessMash()) - MagnificationManager::Shutdown(); + MagnificationManager::Shutdown(); audio::SoundsManager::Shutdown(); @@ -1189,9 +1182,7 @@ // ChromeBrowserMainPartsLinux::PostMainMessageLoopRun(). arc_service_launcher_.reset(); - // TODO(crbug.com/594887): Mash support. - if (!::features::IsMultiProcessMash()) - AccessibilityManager::Shutdown(); + AccessibilityManager::Shutdown(); input_method::Shutdown();
diff --git a/chrome/browser/chromeos/crostini/crostini_export_import_notification.h b/chrome/browser/chromeos/crostini/crostini_export_import_notification.h index c4cdc5ff..436ccf3 100644 --- a/chrome/browser/chromeos/crostini/crostini_export_import_notification.h +++ b/chrome/browser/chromeos/crostini/crostini_export_import_notification.h
@@ -62,7 +62,7 @@ base::FilePath path_; Status status_ = Status::RUNNING; // Time when the operation started. Used for estimating time remaining. - base::Time started_ = base::Time::Now(); + base::TimeTicks started_ = base::TimeTicks::Now(); base::string16 title_running_; base::string16 title_done_; base::string16 message_done_;
diff --git a/chrome/browser/chromeos/crostini/crostini_package_notification.cc b/chrome/browser/chromeos/crostini/crostini_package_notification.cc index 0d12b0a..c52bf6b 100644 --- a/chrome/browser/chromeos/crostini/crostini_package_notification.cc +++ b/chrome/browser/chromeos/crostini/crostini_package_notification.cc
@@ -45,7 +45,7 @@ visible_(true), weak_ptr_factory_(this) { if (status == PackageOperationStatus::RUNNING) { - running_start_time_ = base::Time::Now(); + running_start_time_ = base::TimeTicks::Now(); } message_center::RichNotificationData rich_notification_data; rich_notification_data.vector_small_image = &ash::kNotificationLinuxIcon; @@ -135,7 +135,7 @@ int progress_percent) { if (status == PackageOperationStatus::RUNNING && current_status_ != PackageOperationStatus::RUNNING) { - running_start_time_ = base::Time::Now(); + running_start_time_ = base::TimeTicks::Now(); } current_status_ = status;
diff --git a/chrome/browser/chromeos/crostini/crostini_package_notification.h b/chrome/browser/chromeos/crostini/crostini_package_notification.h index 44429d4..7675643 100644 --- a/chrome/browser/chromeos/crostini/crostini_package_notification.h +++ b/chrome/browser/chromeos/crostini/crostini_package_notification.h
@@ -81,7 +81,7 @@ // The most-recent time we entered the "RUNNING" state. Used for // guesstimating when we'll be done. - base::Time running_start_time_; + base::TimeTicks running_start_time_; // These notifications are owned by the package service. CrostiniPackageService* package_service_;
diff --git a/chrome/browser/chromeos/crostini/crostini_util.cc b/chrome/browser/chromeos/crostini/crostini_util.cc index d634079..f8c675e 100644 --- a/chrome/browser/chromeos/crostini/crostini_util.cc +++ b/chrome/browser/chromeos/crostini/crostini_util.cc
@@ -465,14 +465,14 @@ vm_name, container_name); } -base::string16 GetTimeRemainingMessage(base::Time start, int percent) { +base::string16 GetTimeRemainingMessage(base::TimeTicks start, int percent) { // Only estimate once we've spent at least 3 seconds OR gotten 10% of the way // through. constexpr base::TimeDelta kMinTimeForEstimate = base::TimeDelta::FromSeconds(3); constexpr base::TimeDelta kTimeDeltaZero = base::TimeDelta::FromSeconds(0); constexpr int kMinPercentForEstimate = 10; - base::TimeDelta elapsed = base::Time::Now() - start; + base::TimeDelta elapsed = base::TimeTicks::Now() - start; if ((elapsed >= kMinTimeForEstimate && percent > 0) || (percent >= kMinPercentForEstimate && elapsed > kTimeDeltaZero)) { base::TimeDelta total_time_expected = (elapsed * 100) / percent;
diff --git a/chrome/browser/chromeos/crostini/crostini_util.h b/chrome/browser/chromeos/crostini/crostini_util.h index 45ef41c..fbfe5da 100644 --- a/chrome/browser/chromeos/crostini/crostini_util.h +++ b/chrome/browser/chromeos/crostini/crostini_util.h
@@ -171,7 +171,7 @@ // Returns a string to be displayed in a notification with the estimated time // left for an operation to run which started and time |start| and is current // at |percent| way through. -base::string16 GetTimeRemainingMessage(base::Time start, int percent); +base::string16 GetTimeRemainingMessage(base::TimeTicks start, int percent); } // namespace crostini
diff --git a/chrome/browser/chromeos/extensions/info_private_apitest.cc b/chrome/browser/chromeos/extensions/info_private_apitest.cc index e24d0b24..8125bb0 100644 --- a/chrome/browser/chromeos/extensions/info_private_apitest.cc +++ b/chrome/browser/chromeos/extensions/info_private_apitest.cc
@@ -21,7 +21,6 @@ #include "components/arc/arc_util.h" #include "components/prefs/pref_service.h" #include "ui/aura/window.h" -#include "ui/base/ui_base_features.h" #include "ui/events/devices/device_data_manager_test_api.h" #include "ui/events/devices/input_device.h" #include "ui/events/devices/touchscreen_device.h" @@ -191,9 +190,7 @@ test_api.SetTouchscreenDevices({touchscreen}); ui::test::EventGenerator generator( - features::IsUsingWindowService() - ? nullptr - : browser()->window()->GetNativeWindow()->GetRootWindow()); + browser()->window()->GetNativeWindow()->GetRootWindow()); generator.EnterPenPointerMode(); generator.PressTouch(); generator.ReleaseTouch();
diff --git a/chrome/browser/chromeos/input_method/candidate_window_controller_impl.cc b/chrome/browser/chromeos/input_method/candidate_window_controller_impl.cc index 416faa2f..b20689b 100644 --- a/chrome/browser/chromeos/input_method/candidate_window_controller_impl.cc +++ b/chrome/browser/chromeos/input_method/candidate_window_controller_impl.cc
@@ -12,7 +12,6 @@ #include "ash/wm/window_util.h" // mash-ok #include "base/logging.h" #include "ui/base/ime/ime_bridge.h" -#include "ui/base/ui_base_features.h" #include "ui/chromeos/ime/infolist_window.h" #include "ui/views/widget/widget.h" @@ -41,16 +40,13 @@ gfx::NativeView parent = nullptr; - // NOTE: CandidateWindowView takes care of the mash (window-service) case. + aura::Window* active_window = ash::wm::GetActiveWindow(); // Use VirtualKeyboardContainer so that it works even with a system modal // dialog. - if (!features::IsUsingWindowService()) { - aura::Window* active_window = ash::wm::GetActiveWindow(); - parent = ash::Shell::GetContainer( - active_window ? active_window->GetRootWindow() - : ash::Shell::GetRootWindowForNewWindows(), - ash::kShellWindowId_VirtualKeyboardContainer); - } + parent = ash::Shell::GetContainer( + active_window ? active_window->GetRootWindow() + : ash::Shell::GetRootWindowForNewWindows(), + ash::kShellWindowId_VirtualKeyboardContainer); candidate_window_view_ = new ui::ime::CandidateWindowView( parent, ash::kShellWindowId_VirtualKeyboardContainer); candidate_window_view_->AddObserver(this);
diff --git a/chrome/browser/chromeos/input_method/input_method_manager_impl.cc b/chrome/browser/chromeos/input_method/input_method_manager_impl.cc index dae91e670..5b92a0a 100644 --- a/chrome/browser/chromeos/input_method/input_method_manager_impl.cc +++ b/chrome/browser/chromeos/input_method/input_method_manager_impl.cc
@@ -47,7 +47,6 @@ #include "ui/base/ime/chromeos/ime_keyboard_impl.h" #include "ui/base/ime/chromeos/input_method_delegate.h" #include "ui/base/ime/ime_bridge.h" -#include "ui/base/ui_base_features.h" #include "ui/chromeos/ime/input_method_menu_item.h" #include "ui/chromeos/ime/input_method_menu_manager.h" @@ -1372,9 +1371,6 @@ ui::InputMethodKeyboardController* InputMethodManagerImpl::GetInputMethodKeyboardController() { - // TODO(stevenjb/shuchen): Fix this for Mash. https://crbug.com/756059 - if (features::IsMultiProcessMash()) - return nullptr; // Callers expect a nullptr when the keyboard is disabled. See // https://crbug.com/850020. if (!keyboard::KeyboardController::HasInstance() ||
diff --git a/chrome/browser/chromeos/login/lock/screen_locker_browsertest.cc b/chrome/browser/chromeos/login/lock/screen_locker_browsertest.cc index 322050b..9e6f762 100644 --- a/chrome/browser/chromeos/login/lock/screen_locker_browsertest.cc +++ b/chrome/browser/chromeos/login/lock/screen_locker_browsertest.cc
@@ -28,7 +28,6 @@ #include "components/user_manager/user_names.h" #include "content/public/test/test_utils.h" #include "testing/gtest/include/gtest/gtest.h" -#include "ui/base/ui_base_features.h" #include "ui/compositor/scoped_animation_duration_scale_mode.h" namespace chromeos { @@ -136,11 +135,6 @@ // Test how locking the screen affects an active fullscreen window. IN_PROC_BROWSER_TEST_F(ScreenLockerTest, TestFullscreenExit) { - // WebUiScreenLockerTest fails with Mash because of unexpected window - // structure. Fortunately we will deprecate the WebUI-based screen locker - // soon, so it is okay to skip it. See https://crbug.com/888779 - if (features::IsUsingWindowService()) - return; // 1) If the active browser window is in fullscreen and the fullscreen window // does not have all the pixels (e.g. the shelf is auto hidden instead of // hidden), locking the screen should not exit fullscreen. The shelf is
diff --git a/chrome/browser/chromeos/login/login_browsertest.cc b/chrome/browser/chromeos/login/login_browsertest.cc index 03a387a3..fed8f91 100644 --- a/chrome/browser/chromeos/login/login_browsertest.cc +++ b/chrome/browser/chromeos/login/login_browsertest.cc
@@ -23,7 +23,6 @@ #include "chromeos/constants/chromeos_switches.h" #include "components/user_manager/user_names.h" #include "testing/gmock/include/gmock/gmock.h" -#include "ui/base/ui_base_features.h" #include "ui/gfx/geometry/test/rect_test_util.h" using ::gfx::test::RectContains; @@ -97,11 +96,7 @@ EXPECT_TRUE(tray->GetVisible()); // This check flakes for LoginGuestTest: https://crbug.com/693106. - // This check is suppressed for Mash since the warning button of Mash changes - // the tray bounds which triggers the failure. See: https://crbug.com/892730 - // TODO(jamescook): remove this when Mash is on by default or the button is - // removed. - if (!otr && !features::IsUsingWindowService()) + if (!otr) EXPECT_TRUE(RectContains(primary_win->bounds(), tray->GetBoundsInScreen())); }
diff --git a/chrome/browser/chromeos/login/login_utils_browsertest.cc b/chrome/browser/chromeos/login/login_utils_browsertest.cc index 322a7ff..f1bf38b 100644 --- a/chrome/browser/chromeos/login/login_utils_browsertest.cc +++ b/chrome/browser/chromeos/login/login_utils_browsertest.cc
@@ -34,7 +34,6 @@ #include "net/test/embedded_test_server/embedded_test_server.h" #include "net/test/embedded_test_server/http_response.h" #include "rlz/buildflags/buildflags.h" -#include "ui/base/ui_base_features.h" #if BUILDFLAG(ENABLE_RLZ) #include "base/task/post_task.h" @@ -83,24 +82,6 @@ DISALLOW_COPY_AND_ASSIGN(LoginUtilsTest); }; -// Exercises login, like the desktopui_MashLogin Chrome OS autotest. -// Test is flaky, see https://crbug.com/957584. -#if defined(MEMORY_SANITIZER) -#define MAYBE_MashLogin DISABLED_MashLogin -#else -#define MAYBE_MashLogin MashLogin -#endif -IN_PROC_BROWSER_TEST_F(LoginUtilsTest, MAYBE_MashLogin) { - // Test is relevant for both SingleProcessMash and MultiProcessMash, but - // not classic ash. - if (!features::IsUsingWindowService()) - return; - - WaitForSigninScreen(); - Login("username"); - // Login did not time out and did not crash. -} - #if BUILDFLAG(ENABLE_RLZ) IN_PROC_BROWSER_TEST_F(LoginUtilsTest, RlzInitialized) { WaitForSigninScreen();
diff --git a/chrome/browser/chromeos/login/ui/input_events_blocker.cc b/chrome/browser/chromeos/login/ui/input_events_blocker.cc index cc2aad8..ba315ea8 100644 --- a/chrome/browser/chromeos/login/ui/input_events_blocker.cc +++ b/chrome/browser/chromeos/login/ui/input_events_blocker.cc
@@ -6,31 +6,20 @@ #include "ash/shell.h" #include "base/logging.h" -#include "ui/base/ui_base_features.h" #include "ui/events/event.h" namespace chromeos { InputEventsBlocker::InputEventsBlocker() { - // TODO(crbug.com/854323): Mash support. Needs mojo API, or to move to ash. - if (!features::IsMultiProcessMash()) { - ash::Shell::Get()->AddPreTargetHandler(this, - ui::EventTarget::Priority::kSystem); - VLOG(1) << "InputEventsBlocker " << this << " created."; - } else { - NOTIMPLEMENTED(); - } + ash::Shell::Get()->AddPreTargetHandler(this, + ui::EventTarget::Priority::kSystem); + VLOG(1) << "InputEventsBlocker " << this << " created."; } InputEventsBlocker::~InputEventsBlocker() { - if (!features::IsMultiProcessMash()) { - if (ash::Shell::HasInstance()) - ash::Shell::Get()->RemovePreTargetHandler(this); - - VLOG(1) << "InputEventsBlocker " << this << " destroyed."; - } else { - NOTIMPLEMENTED(); - } + if (ash::Shell::HasInstance()) + ash::Shell::Get()->RemovePreTargetHandler(this); + VLOG(1) << "InputEventsBlocker " << this << " destroyed."; } void InputEventsBlocker::OnKeyEvent(ui::KeyEvent* event) {
diff --git a/chrome/browser/chromeos/login/ui/login_display_host_webui.cc b/chrome/browser/chromeos/login/ui/login_display_host_webui.cc index 11a8dcb..0768a71 100644 --- a/chrome/browser/chromeos/login/ui/login_display_host_webui.cc +++ b/chrome/browser/chromeos/login/ui/login_display_host_webui.cc
@@ -90,7 +90,6 @@ #include "ui/base/ime/chromeos/input_method_manager.h" #include "ui/base/ime/chromeos/input_method_util.h" #include "ui/base/resource/resource_bundle.h" -#include "ui/base/ui_base_features.h" #include "ui/compositor/compositor_observer.h" #include "ui/compositor/layer.h" #include "ui/compositor/layer_animation_observer.h" @@ -595,15 +594,11 @@ // We should emit this signal only at login screen (after reboot or sign out). login_view_->set_should_emit_login_prompt_visible(false); - if (!features::IsMultiProcessMash()) { - // Lock container can be transparent after lock screen animation. - aura::Window* lock_container = ash::Shell::GetContainer( - ash::Shell::GetPrimaryRootWindow(), - ash::kShellWindowId_LockScreenContainersContainer); - lock_container->layer()->SetOpacity(1.0); - } else { - NOTIMPLEMENTED(); - } + // Lock container can be transparent after lock screen animation. + aura::Window* lock_container = ash::Shell::GetContainer( + ash::Shell::GetPrimaryRootWindow(), + ash::kShellWindowId_LockScreenContainersContainer); + lock_container->layer()->SetOpacity(1.0); CreateExistingUserController(); @@ -874,13 +869,6 @@ // LoginDisplayHostWebUI, private void LoginDisplayHostWebUI::ScheduleWorkspaceAnimation() { - // TODO(mash): Support finalize animations without reaching directly into - // ash::Shell. - if (features::IsMultiProcessMash()) { - NOTIMPLEMENTED(); - return; - } - if (!base::CommandLine::ForCurrentProcess()->HasSwitch( switches::kDisableLoginAnimations)) { ash::Shell::Get()->DoInitialWorkspaceAnimation(); @@ -963,9 +951,7 @@ if (login_window_) return; - // TODO(crbug.com/881390): Mash support for keyboard driven OOBE. - if (!features::IsMultiProcessMash() && - system::InputDeviceSettings::ForceKeyboardDrivenUINavigation()) { + if (system::InputDeviceSettings::ForceKeyboardDrivenUINavigation()) { views::FocusManager::set_arrow_key_traversal_enabled(true); focus_ring_controller_ = std::make_unique<ash::FocusRingController>(); focus_ring_controller_->SetVisible(true); @@ -1023,16 +1009,10 @@ } if (login_window_) { - if (features::IsUsingWindowService()) { - // TODO(mash): CompositorObserver::OnCompositingDidCommit() doesn't fire - // for either SingleProcessMash or MultiProcessMash. - login_window_->Close(); - } else { - login_window_->Hide(); - // This CompositorObserver becomes "owned" by login_window_ after - // construction and will delete itself once login_window_ is destroyed. - new CloseAfterCommit(login_window_); - } + login_window_->Hide(); + // This CompositorObserver becomes "owned" by login_window_ after + // construction and will delete itself once login_window_ is destroyed. + new CloseAfterCommit(login_window_); login_window_->RemoveRemovalsObserver(this); login_window_->RemoveObserver(this); login_window_ = nullptr;
diff --git a/chrome/browser/chromeos/power/ml/adaptive_screen_brightness_manager.cc b/chrome/browser/chromeos/power/ml/adaptive_screen_brightness_manager.cc index 3bf6b81..2891acf 100644 --- a/chrome/browser/chromeos/power/ml/adaptive_screen_brightness_manager.cc +++ b/chrome/browser/chromeos/power/ml/adaptive_screen_brightness_manager.cc
@@ -37,7 +37,6 @@ #include "services/metrics/public/cpp/ukm_source_id.h" #include "services/viz/public/interfaces/compositing/video_detector_observer.mojom.h" #include "ui/aura/env.h" -#include "ui/base/ui_base_features.h" #include "ui/base/user_activity/user_activity_detector.h" namespace chromeos { @@ -160,13 +159,8 @@ std::unique_ptr<AdaptiveScreenBrightnessManager> AdaptiveScreenBrightnessManager::CreateInstance() { - // TODO(jiameng): video detector below doesn't work with MASH. Temporary - // solution is to disable logging if we're under MASH env. - // https://crbug.com/871914 - if (chromeos::GetDeviceType() != chromeos::DeviceType::kChromebook || - features::IsMultiProcessMash()) { + if (chromeos::GetDeviceType() != chromeos::DeviceType::kChromebook) return nullptr; - } chromeos::PowerManagerClient* const power_manager_client = chromeos::PowerManagerClient::Get();
diff --git a/chrome/browser/chromeos/power/ml/user_activity_controller.cc b/chrome/browser/chromeos/power/ml/user_activity_controller.cc index 8506ecc..32345e5 100644 --- a/chrome/browser/chromeos/power/ml/user_activity_controller.cc +++ b/chrome/browser/chromeos/power/ml/user_activity_controller.cc
@@ -11,7 +11,6 @@ #include "components/viz/host/host_frame_sink_manager.h" #include "services/viz/public/interfaces/compositing/video_detector_observer.mojom.h" #include "ui/aura/env.h" -#include "ui/base/ui_base_features.h" #include "ui/compositor/compositor.h" namespace chromeos { @@ -19,13 +18,8 @@ namespace ml { UserActivityController::UserActivityController() { - // TODO(jiameng): video detector below doesn't work with MASH. Temporary - // solution is to disable logging if we're under MASH env. - // https://crbug.com/871914 - if (chromeos::GetDeviceType() != chromeos::DeviceType::kChromebook || - features::IsMultiProcessMash()) { + if (chromeos::GetDeviceType() != chromeos::DeviceType::kChromebook) return; - } chromeos::PowerManagerClient* power_manager_client = chromeos::PowerManagerClient::Get();
diff --git a/chrome/browser/chromeos/settings/device_oauth2_token_service.cc b/chrome/browser/chromeos/settings/device_oauth2_token_service.cc index 8a73e49..8c7bc9b 100644 --- a/chrome/browser/chromeos/settings/device_oauth2_token_service.cc +++ b/chrome/browser/chromeos/settings/device_oauth2_token_service.cc
@@ -48,11 +48,11 @@ DeviceOAuth2TokenService::DeviceOAuth2TokenService( std::unique_ptr<DeviceOAuth2TokenServiceDelegate> delegate) : OAuth2TokenService(std::move(delegate)) { - GetDeviceDelegate()->SetValidationStatusDelegate(this); + GetDeviceDelegate()->InitializeWithValidationStatusDelegate(this); } DeviceOAuth2TokenService::~DeviceOAuth2TokenService() { - GetDeviceDelegate()->SetValidationStatusDelegate(nullptr); + GetDeviceDelegate()->ClearValidationStatusDelegate(); FlushPendingRequests(false, GoogleServiceAuthError::REQUEST_CANCELED); }
diff --git a/chrome/browser/chromeos/settings/device_oauth2_token_service_delegate.cc b/chrome/browser/chromeos/settings/device_oauth2_token_service_delegate.cc index cad84e0..997e68f8 100644 --- a/chrome/browser/chromeos/settings/device_oauth2_token_service_delegate.cc +++ b/chrome/browser/chromeos/settings/device_oauth2_token_service_delegate.cc
@@ -196,14 +196,12 @@ LOG(ERROR) << "Failed to get system salt."; FlushTokenSaveCallbacks(false); state_ = STATE_NO_TOKEN; - FireRefreshTokensLoaded(); return; } // If the token has been set meanwhile, write it to |local_state_|. if (!refresh_token_.empty()) { EncryptAndSaveToken(); - FireRefreshTokensLoaded(); return; } @@ -216,7 +214,6 @@ if (refresh_token_.empty()) { LOG(ERROR) << "Failed to decrypt refresh token."; state_ = STATE_NO_TOKEN; - FireRefreshTokensLoaded(); return; } } @@ -231,7 +228,6 @@ if (!GetRobotAccountId().empty()) { FireRefreshTokenAvailable(GetRobotAccountId()); } - FireRefreshTokensLoaded(); } void DeviceOAuth2TokenServiceDelegate::CheckRobotAccountId( @@ -324,9 +320,20 @@ validation_requested_ = true; } -void DeviceOAuth2TokenServiceDelegate::SetValidationStatusDelegate( +void DeviceOAuth2TokenServiceDelegate::InitializeWithValidationStatusDelegate( ValidationStatusDelegate* delegate) { validation_status_delegate_ = delegate; + + // Now that |delegate| (i.e., DeviceOAuth2TokenService) has been initialized + // and is listening to this object as an observer, fire the notification that + // refresh tokens were loaded; otherwise, + // OAuth2TokenService::{GetAccounts(), RefreshTokenIsAvailable()} will short- + // circuit out to match O2TS semantics. + FireRefreshTokensLoaded(); +} + +void DeviceOAuth2TokenServiceDelegate::ClearValidationStatusDelegate() { + validation_status_delegate_ = nullptr; } void DeviceOAuth2TokenServiceDelegate::ReportServiceError(
diff --git a/chrome/browser/chromeos/settings/device_oauth2_token_service_delegate.h b/chrome/browser/chromeos/settings/device_oauth2_token_service_delegate.h index 0c3d58f..5c547151 100644 --- a/chrome/browser/chromeos/settings/device_oauth2_token_service_delegate.h +++ b/chrome/browser/chromeos/settings/device_oauth2_token_service_delegate.h
@@ -124,7 +124,9 @@ void RequestValidation(); - void SetValidationStatusDelegate(ValidationStatusDelegate* delegate); + void InitializeWithValidationStatusDelegate( + ValidationStatusDelegate* delegate); + void ClearValidationStatusDelegate(); void ReportServiceError(GoogleServiceAuthError::State error);
diff --git a/chrome/browser/chromeos/system_logs/touch_log_source.cc b/chrome/browser/chromeos/system_logs/touch_log_source.cc index f951e49..d0f2856 100644 --- a/chrome/browser/chromeos/system_logs/touch_log_source.cc +++ b/chrome/browser/chromeos/system_logs/touch_log_source.cc
@@ -18,7 +18,6 @@ #include "base/process/launch.h" #include "base/task/post_task.h" #include "content/public/browser/browser_thread.h" -#include "ui/base/ui_base_features.h" #include "ui/ozone/public/input_controller.h" #include "ui/ozone/public/ozone_platform.h" @@ -168,11 +167,6 @@ // Collect touch HUD debug logs. This needs to be done on the UI thread. void CollectTouchHudDebugLog(system_logs::SystemLogsResponse* response) { - // TODO(crbug.com/807408): Collect this data from window server over mojo. - if (features::IsMultiProcessMash()) { - NOTIMPLEMENTED(); - return; - } std::unique_ptr<base::DictionaryValue> dictionary = ash::TouchHudDebug::GetAllAsDictionary(); if (!dictionary->empty()) {
diff --git a/chrome/browser/download/download_offline_content_provider.cc b/chrome/browser/download/download_offline_content_provider.cc index 2b97166..e9d8312 100644 --- a/chrome/browser/download/download_offline_content_provider.cc +++ b/chrome/browser/download/download_offline_content_provider.cc
@@ -41,6 +41,11 @@ // Thumbnail size used for generating thumbnails for image files. const int kThumbnailSizeInDP = 64; +// The delay to wait after loading history and before starting the check for +// externally removed downloads. +const base::TimeDelta kCheckExternallyRemovedDownloadsDelay = + base::TimeDelta::FromMilliseconds(100); + bool ShouldShowDownloadItem(const DownloadItem* item) { return !item->IsTemporary() && !item->IsTransient() && !item->IsDangerous() && !item->GetTargetFilePath().empty(); @@ -60,6 +65,61 @@ return share_info; } +// Observes the all downloads, primrarily responsible for cleaning up the +// externally removed downloads, and notifying the provider about download +// deletions. +class AllDownloadObserver + : public download::AllDownloadEventNotifier::Observer { + public: + explicit AllDownloadObserver(DownloadOfflineContentProvider* provider); + ~AllDownloadObserver() override; + + void OnDownloadUpdated(SimpleDownloadManagerCoordinator* manager, + DownloadItem* item) override; + void OnDownloadRemoved(SimpleDownloadManagerCoordinator* manager, + DownloadItem* item) override; + + private: + void DeleteDownloadItem(SimpleDownloadManagerCoordinator* manager, + const std::string& guid); + + DownloadOfflineContentProvider* provider_; + base::WeakPtrFactory<AllDownloadObserver> weak_ptr_factory_; + + DISALLOW_COPY_AND_ASSIGN(AllDownloadObserver); +}; + +AllDownloadObserver::AllDownloadObserver( + DownloadOfflineContentProvider* provider) + : provider_(provider), weak_ptr_factory_(this) {} + +AllDownloadObserver::~AllDownloadObserver() {} + +void AllDownloadObserver::OnDownloadUpdated( + SimpleDownloadManagerCoordinator* manager, + DownloadItem* item) { + if (item->GetFileExternallyRemoved()) { + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::BindOnce(&AllDownloadObserver::DeleteDownloadItem, + weak_ptr_factory_.GetWeakPtr(), manager, + item->GetGuid())); + } +} + +void AllDownloadObserver::OnDownloadRemoved( + SimpleDownloadManagerCoordinator* manager, + DownloadItem* item) { + provider_->OnDownloadRemoved(item); +} + +void AllDownloadObserver::DeleteDownloadItem( + SimpleDownloadManagerCoordinator* manager, + const std::string& guid) { + DownloadItem* item = manager->GetDownloadByGuid(guid); + if (item) + item->Remove(); +} + } // namespace DownloadOfflineContentProvider::DownloadOfflineContentProvider( @@ -70,12 +130,15 @@ manager_(nullptr), weak_ptr_factory_(this) { aggregator_->RegisterProvider(name_space_, this); + all_download_observer_.reset(new AllDownloadObserver(this)); } DownloadOfflineContentProvider::~DownloadOfflineContentProvider() { aggregator_->UnregisterProvider(name_space_); - if (manager_) + if (manager_) { manager_->RemoveObserver(this); + manager_->GetNotifier()->RemoveObserver(all_download_observer_.get()); + } } void DownloadOfflineContentProvider::SetSimpleDownloadManagerCoordinator( @@ -84,6 +147,7 @@ DCHECK(!manager_); manager_ = manager; manager_->AddObserver(this); + manager_->GetNotifier()->AddObserver(all_download_observer_.get()); } // TODO(shaktisahu) : Pass DownloadOpenSource. @@ -96,8 +160,10 @@ void DownloadOfflineContentProvider::RemoveItem(const ContentId& id) { DownloadItem* item = GetDownload(id.id); - if (item) + if (item) { + item->DeleteFile(base::DoNothing()); item->Remove(); + } } void DownloadOfflineContentProvider::CancelDownload(const ContentId& id) { @@ -249,6 +315,19 @@ observers_.RemoveObserver(observer); } +void DownloadOfflineContentProvider::OnDownloadsInitialized( + bool active_downloads_only) { + if (active_downloads_only) + return; + + base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( + FROM_HERE, + base::BindOnce( + &DownloadOfflineContentProvider::CheckForExternallyRemovedDownloads, + weak_ptr_factory_.GetWeakPtr()), + kCheckExternallyRemovedDownloadsDelay); +} + void DownloadOfflineContentProvider::OnManagerGoingDown() { std::vector<DownloadItem*> all_items; GetAllDownloads(&all_items); @@ -351,3 +430,11 @@ for (auto& observer : observers_) observer.OnItemUpdated(item, update_delta); } + +void DownloadOfflineContentProvider::CheckForExternallyRemovedDownloads() { + if (checked_for_externally_removed_downloads_ || !manager_) + return; + + checked_for_externally_removed_downloads_ = true; + manager_->CheckForExternallyRemovedDownloads(); +}
diff --git a/chrome/browser/download/download_offline_content_provider.h b/chrome/browser/download/download_offline_content_provider.h index cc8af56..d54b253 100644 --- a/chrome/browser/download/download_offline_content_provider.h +++ b/chrome/browser/download/download_offline_content_provider.h
@@ -10,6 +10,7 @@ #include <vector> #include "base/macros.h" +#include "components/download/public/common/all_download_event_notifier.h" #include "components/download/public/common/download_item.h" #include "components/download/public/common/simple_download_manager_coordinator.h" #include "components/offline_items_collection/core/offline_content_aggregator.h" @@ -72,13 +73,14 @@ // observing the given download. void OnDownloadStarted(DownloadItem* download_item); - private: // DownloadItem::Observer overrides void OnDownloadUpdated(DownloadItem* item) override; void OnDownloadRemoved(DownloadItem* item) override; void OnDownloadDestroyed(DownloadItem* download) override; + private: // SimpleDownloadManagerCoordinator::Observer overrides + void OnDownloadsInitialized(bool active_downloads_only) override; void OnManagerGoingDown() override; void GetAllDownloads(std::vector<DownloadItem*>* all_items); @@ -95,6 +97,7 @@ DownloadItem::DownloadRenameResult result); void UpdateObservers(const OfflineItem& item, const base::Optional<UpdateDelta>& update_delta); + void CheckForExternallyRemovedDownloads(); base::ObserverList<OfflineContentProvider::Observer>::Unchecked observers_; OfflineContentAggregator* aggregator_; @@ -103,6 +106,9 @@ // Tracks the completed downloads in the current session. std::set<std::string> completed_downloads_; + std::unique_ptr<download::AllDownloadEventNotifier::Observer> + all_download_observer_; + bool checked_for_externally_removed_downloads_ = false; base::WeakPtrFactory<DownloadOfflineContentProvider> weak_ptr_factory_;
diff --git a/chrome/browser/exo_parts.cc b/chrome/browser/exo_parts.cc index 6029e489c..5bf4d0e 100644 --- a/chrome/browser/exo_parts.cc +++ b/chrome/browser/exo_parts.cc
@@ -22,7 +22,6 @@ #include "content/public/common/drop_data.h" #include "storage/browser/fileapi/file_system_context.h" #include "storage/browser/fileapi/file_system_url.h" -#include "ui/base/ui_base_features.h" namespace { @@ -105,9 +104,6 @@ // static std::unique_ptr<ExoParts> ExoParts::CreateIfNecessary() { - // For mash, exosphere will not run in the browser process. - if (features::IsMultiProcessMash()) - return nullptr; if (!base::CommandLine::ForCurrentProcess()->HasSwitch( ash::switches::kAshEnableWaylandServer)) { return nullptr; @@ -121,7 +117,6 @@ } ExoParts::ExoParts() { - DCHECK(!features::IsMultiProcessMash()); std::unique_ptr<ChromeFileHelper> file_helper = std::make_unique<ChromeFileHelper>(); ash::Shell::Get()->InitWaylandServer(std::move(file_helper));
diff --git a/chrome/browser/extensions/api/downloads/downloads_api_browsertest.cc b/chrome/browser/extensions/api/downloads/downloads_api_browsertest.cc index fec35ae..e389b4b5 100644 --- a/chrome/browser/extensions/api/downloads/downloads_api_browsertest.cc +++ b/chrome/browser/extensions/api/downloads/downloads_api_browsertest.cc
@@ -4390,7 +4390,6 @@ ASSERT_TRUE(result->GetAsInteger(&result_id)); DownloadItem* item = GetCurrentManager()->GetDownload(result_id); ASSERT_TRUE(item); - ScopedCancellingItem canceller(item); ASSERT_EQ(download_url, item->GetOriginalUrl().spec()); ASSERT_TRUE(WaitFor(downloads::OnCreated::kEventName, @@ -4416,6 +4415,8 @@ R"( "previous": true,)" R"( "current": false}}])", result_id))); + EXPECT_EQ(static_cast<DownloadItem*>(NULL), + GetCurrentManager()->GetDownload(result_id)); } class DownloadsApiTest : public ExtensionApiTest {
diff --git a/chrome/browser/extensions/api/messaging/chrome_messaging_delegate.cc b/chrome/browser/extensions/api/messaging/chrome_messaging_delegate.cc index 37f434a3..b19df51e 100644 --- a/chrome/browser/extensions/api/messaging/chrome_messaging_delegate.cc +++ b/chrome/browser/extensions/api/messaging/chrome_messaging_delegate.cc
@@ -127,6 +127,7 @@ std::unique_ptr<MessagePort> ChromeMessagingDelegate::CreateReceiverForNativeApp( + content::BrowserContext* browser_context, base::WeakPtr<MessagePort::ChannelDelegate> channel_delegate, content::RenderFrameHost* source, const std::string& extension_id, @@ -136,8 +137,9 @@ std::string* error_out) { DCHECK(error_out); gfx::NativeView native_view = source ? source->GetNativeView() : nullptr; - std::unique_ptr<NativeMessageHost> native_host = NativeMessageHost::Create( - native_view, extension_id, native_app_name, allow_user_level, error_out); + std::unique_ptr<NativeMessageHost> native_host = + NativeMessageHost::Create(browser_context, native_view, extension_id, + native_app_name, allow_user_level, error_out); if (!native_host.get()) return nullptr; return std::make_unique<NativeMessagePort>(channel_delegate, receiver_port_id,
diff --git a/chrome/browser/extensions/api/messaging/chrome_messaging_delegate.h b/chrome/browser/extensions/api/messaging/chrome_messaging_delegate.h index 04734169..050786e 100644 --- a/chrome/browser/extensions/api/messaging/chrome_messaging_delegate.h +++ b/chrome/browser/extensions/api/messaging/chrome_messaging_delegate.h
@@ -31,6 +31,7 @@ content::WebContents* receiver_contents, int receiver_frame_id) override; std::unique_ptr<MessagePort> CreateReceiverForNativeApp( + content::BrowserContext* browser_context, base::WeakPtr<MessagePort::ChannelDelegate> channel_delegate, content::RenderFrameHost* source, const std::string& extension_id,
diff --git a/chrome/browser/extensions/api/messaging/native_message_host_chromeos.cc b/chrome/browser/extensions/api/messaging/native_message_host_chromeos.cc index e4116adad..1ba3053c 100644 --- a/chrome/browser/extensions/api/messaging/native_message_host_chromeos.cc +++ b/chrome/browser/extensions/api/messaging/native_message_host_chromeos.cc
@@ -146,6 +146,7 @@ } // namespace std::unique_ptr<NativeMessageHost> NativeMessageHost::Create( + content::BrowserContext* browser_context, gfx::NativeView native_view, const std::string& source_extension_id, const std::string& native_host_name,
diff --git a/chrome/browser/extensions/api/messaging/native_message_process_host.cc b/chrome/browser/extensions/api/messaging/native_message_process_host.cc index 7b713364..94b83a3e 100644 --- a/chrome/browser/extensions/api/messaging/native_message_process_host.cc +++ b/chrome/browser/extensions/api/messaging/native_message_process_host.cc
@@ -6,6 +6,7 @@ #include <stddef.h> #include <stdint.h> + #include <utility> #include "base/bind.h" @@ -16,6 +17,8 @@ #include "build/build_config.h" #include "chrome/browser/extensions/api/messaging/native_messaging_host_manifest.h" #include "chrome/browser/extensions/api/messaging/native_process_launcher.h" +#include "chrome/browser/profiles/profile.h" +#include "content/public/browser/browser_context.h" #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_thread.h" #include "extensions/common/constants.h" @@ -38,6 +41,14 @@ // Size of the buffer to be allocated for each read. const size_t kReadBufferSize = 4096; +base::FilePath GetProfilePathIfEnabled(Profile* profile, + const std::string& extension_id, + const std::string& host_id) { + // TODO(crbug.com/967262): Return an empty path if the extension would not + // accept an inbound native messaging connection. + return profile->GetPath(); +} + } // namespace namespace extensions { @@ -82,15 +93,18 @@ // static std::unique_ptr<NativeMessageHost> NativeMessageHost::Create( + content::BrowserContext* browser_context, gfx::NativeView native_view, const std::string& source_extension_id, const std::string& native_host_name, bool allow_user_level, std::string* error_message) { return NativeMessageProcessHost::CreateWithLauncher( - source_extension_id, - native_host_name, - NativeProcessLauncher::CreateDefault(allow_user_level, native_view)); + source_extension_id, native_host_name, + NativeProcessLauncher::CreateDefault( + allow_user_level, native_view, + GetProfilePathIfEnabled(Profile::FromBrowserContext(browser_context), + source_extension_id, native_host_name))); } // static
diff --git a/chrome/browser/extensions/api/messaging/native_message_process_host_unittest.cc b/chrome/browser/extensions/api/messaging/native_message_process_host_unittest.cc index 4e27254..702ac7c 100644 --- a/chrome/browser/extensions/api/messaging/native_message_process_host_unittest.cc +++ b/chrome/browser/extensions/api/messaging/native_message_process_host_unittest.cc
@@ -10,23 +10,33 @@ #include <memory> #include <utility> +#include "base/base_paths.h" +#include "base/base_switches.h" #include "base/bind.h" +#include "base/command_line.h" #include "base/files/file.h" #include "base/files/file_path.h" #include "base/files/file_util.h" #include "base/files/scoped_file.h" #include "base/files/scoped_temp_dir.h" #include "base/json/json_reader.h" +#include "base/path_service.h" #include "base/process/process_metrics.h" #include "base/rand_util.h" #include "base/run_loop.h" #include "base/strings/stringprintf.h" +#include "base/strings/utf_string_conversions.h" +#include "base/test/scoped_feature_list.h" #include "base/test/test_timeouts.h" #include "base/threading/platform_thread.h" #include "base/time/time.h" #include "build/build_config.h" #include "chrome/browser/extensions/api/messaging/native_messaging_test_util.h" #include "chrome/browser/extensions/api/messaging/native_process_launcher.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/common/chrome_features.h" +#include "chrome/common/chrome_switches.h" +#include "chrome/test/base/testing_profile.h" #include "components/version_info/version_info.h" #include "content/public/browser/browser_thread.h" #include "content/public/test/test_browser_thread_bundle.h" @@ -167,6 +177,7 @@ std::unique_ptr<NativeMessageHost> native_message_host_; std::unique_ptr<base::RunLoop> run_loop_; content::TestBrowserThreadBundle thread_bundle_; + TestingProfile profile_; std::string last_message_; std::unique_ptr<base::DictionaryValue> last_message_parsed_; @@ -267,11 +278,8 @@ ASSERT_NO_FATAL_FAILURE(test_host.RegisterTestHost(false)); std::string error_message; native_message_host_ = NativeMessageProcessHost::Create( - NULL, - ScopedTestNativeMessagingHost::kExtensionId, - ScopedTestNativeMessagingHost::kHostName, - false, - &error_message); + &profile_, NULL, ScopedTestNativeMessagingHost::kExtensionId, + ScopedTestNativeMessagingHost::kHostName, false, &error_message); native_message_host_->Start(this); ASSERT_TRUE(native_message_host_); @@ -302,6 +310,91 @@ EXPECT_EQ("bar", text); EXPECT_TRUE(last_message_parsed_->GetString("caller_url", &url)); EXPECT_EQ(expected_url, url); + + const base::Value* args = nullptr; + ASSERT_TRUE(last_message_parsed_->Get("args", &args)); + EXPECT_TRUE(args->is_none()); +} + +// Test send message with a real client. The args passed when launching the +// native messaging host should contain reconnect args. +TEST_F(NativeMessagingTest, ReconnectArgs) { + base::test::ScopedFeatureList feature_list; + feature_list.InitAndEnableFeature(features::kOnConnectNative); + ScopedTestNativeMessagingHost test_host; + ASSERT_NO_FATAL_FAILURE(test_host.RegisterTestHost(false)); + std::string error_message; + native_message_host_ = NativeMessageProcessHost::Create( + &profile_, NULL, ScopedTestNativeMessagingHost::kExtensionId, + ScopedTestNativeMessagingHost:: + kSupportsNativeInitiatedConnectionsHostName, + false, &error_message); + native_message_host_->Start(this); + ASSERT_TRUE(native_message_host_); + + native_message_host_->OnMessage("{\"text\": \"Hello.\"}"); + run_loop_.reset(new base::RunLoop()); + run_loop_->Run(); + ASSERT_FALSE(last_message_.empty()); + ASSERT_TRUE(last_message_parsed_); + + const base::ListValue* args_value = nullptr; + ASSERT_TRUE(last_message_parsed_->GetList("args", &args_value)); + std::vector<base::CommandLine::StringType> args; + args.reserve(args_value->GetSize()); + for (auto& arg : args_value->GetList()) { + ASSERT_TRUE(arg.is_string()); +#if defined(OS_WIN) + args.push_back(base::UTF8ToUTF16(arg.GetString())); +#else + args.push_back(arg.GetString()); +#endif + } + base::CommandLine cmd_line(args); + base::FilePath exe_path; + ASSERT_TRUE(base::PathService::Get(base::FILE_EXE, &exe_path)); + EXPECT_EQ(exe_path, cmd_line.GetProgram()); + EXPECT_TRUE(cmd_line.HasSwitch(switches::kNoStartupWindow)); + EXPECT_EQ( + ScopedTestNativeMessagingHost:: + kSupportsNativeInitiatedConnectionsHostName, + cmd_line.GetSwitchValueASCII(switches::kNativeMessagingConnectHost)); + EXPECT_EQ( + ScopedTestNativeMessagingHost::kExtensionId, + cmd_line.GetSwitchValueASCII(switches::kNativeMessagingConnectExtension)); + EXPECT_EQ(features::kOnConnectNative.name, + cmd_line.GetSwitchValueASCII(switches::kEnableFeatures)); + EXPECT_EQ(profile_.GetPath().BaseName(), + cmd_line.GetSwitchValuePath(switches::kProfileDirectory)); + EXPECT_EQ(profile_.GetPath().DirName(), + cmd_line.GetSwitchValuePath(switches::kUserDataDir)); +} + +// Test send message with a real client. The args passed when launching the +// native messaging host should not contain reconnect args. +TEST_F(NativeMessagingTest, ReconnectArgs_Disabled) { + base::test::ScopedFeatureList feature_list; + feature_list.InitAndDisableFeature(features::kOnConnectNative); + ScopedTestNativeMessagingHost test_host; + ASSERT_NO_FATAL_FAILURE(test_host.RegisterTestHost(false)); + std::string error_message; + native_message_host_ = NativeMessageProcessHost::Create( + &profile_, NULL, ScopedTestNativeMessagingHost::kExtensionId, + ScopedTestNativeMessagingHost:: + kSupportsNativeInitiatedConnectionsHostName, + false, &error_message); + native_message_host_->Start(this); + ASSERT_TRUE(native_message_host_); + + native_message_host_->OnMessage("{\"text\": \"Hello.\"}"); + run_loop_.reset(new base::RunLoop()); + run_loop_->Run(); + ASSERT_FALSE(last_message_.empty()); + ASSERT_TRUE(last_message_parsed_); + + const base::Value* args = nullptr; + ASSERT_TRUE(last_message_parsed_->Get("args", &args)); + EXPECT_TRUE(args->is_none()); } TEST_F(NativeMessagingTest, UserLevel) { @@ -310,11 +403,8 @@ std::string error_message; native_message_host_ = NativeMessageProcessHost::Create( - NULL, - ScopedTestNativeMessagingHost::kExtensionId, - ScopedTestNativeMessagingHost::kHostName, - true, - &error_message); + &profile_, NULL, ScopedTestNativeMessagingHost::kExtensionId, + ScopedTestNativeMessagingHost::kHostName, true, &error_message); native_message_host_->Start(this); ASSERT_TRUE(native_message_host_); @@ -331,11 +421,8 @@ std::string error_message; native_message_host_ = NativeMessageProcessHost::Create( - NULL, - ScopedTestNativeMessagingHost::kExtensionId, - ScopedTestNativeMessagingHost::kHostName, - false, - &error_message); + &profile_, NULL, ScopedTestNativeMessagingHost::kExtensionId, + ScopedTestNativeMessagingHost::kHostName, false, &error_message); native_message_host_->Start(this); ASSERT_TRUE(native_message_host_); run_loop_.reset(new base::RunLoop());
diff --git a/chrome/browser/extensions/api/messaging/native_messaging_test_util.cc b/chrome/browser/extensions/api/messaging/native_messaging_test_util.cc index 1acf4ae..34d944d 100644 --- a/chrome/browser/extensions/api/messaging/native_messaging_test_util.cc +++ b/chrome/browser/extensions/api/messaging/native_messaging_test_util.cc
@@ -29,12 +29,15 @@ void WriteTestNativeHostManifest(const base::FilePath& target_dir, const std::string& host_name, const base::FilePath& host_path, - bool user_level) { + bool user_level, + bool supports_native_initiated_connections) { std::unique_ptr<base::DictionaryValue> manifest(new base::DictionaryValue()); manifest->SetString("name", host_name); manifest->SetString("description", "Native Messaging Echo Test"); manifest->SetString("type", "stdio"); manifest->SetString("path", host_path.AsUTF8Unsafe()); + manifest->SetBoolean("supports_native_initiated_connections", + supports_native_initiated_connections); std::unique_ptr<base::ListValue> origins(new base::ListValue()); origins->AppendString(base::StringPrintf( @@ -63,6 +66,9 @@ "com.google.chrome.test.echo"; const char ScopedTestNativeMessagingHost::kBinaryMissingHostName[] = "com.google.chrome.test.host_binary_missing"; +const char ScopedTestNativeMessagingHost:: + kSupportsNativeInitiatedConnectionsHostName[] = + "com.google.chrome.test.inbound_native_echo"; const char ScopedTestNativeMessagingHost::kExtensionId[] = "knldjmfmopnpolahpmmgbagdohdnhkik"; @@ -95,11 +101,16 @@ base::FilePath host_path = test_user_data_dir.AppendASCII("echo.bat"); #endif ASSERT_NO_FATAL_FAILURE(WriteTestNativeHostManifest( - temp_dir_.GetPath(), kHostName, host_path, user_level)); + temp_dir_.GetPath(), kHostName, host_path, user_level, false)); ASSERT_NO_FATAL_FAILURE(WriteTestNativeHostManifest( temp_dir_.GetPath(), kBinaryMissingHostName, - test_user_data_dir.AppendASCII("missing_nm_binary.exe"), user_level)); + test_user_data_dir.AppendASCII("missing_nm_binary.exe"), user_level, + false)); + + ASSERT_NO_FATAL_FAILURE(WriteTestNativeHostManifest( + temp_dir_.GetPath(), kSupportsNativeInitiatedConnectionsHostName, + host_path, user_level, true)); } ScopedTestNativeMessagingHost::~ScopedTestNativeMessagingHost() {
diff --git a/chrome/browser/extensions/api/messaging/native_messaging_test_util.h b/chrome/browser/extensions/api/messaging/native_messaging_test_util.h index 0757bf7..b5ccbdc 100644 --- a/chrome/browser/extensions/api/messaging/native_messaging_test_util.h +++ b/chrome/browser/extensions/api/messaging/native_messaging_test_util.h
@@ -29,6 +29,8 @@ public: static const char kHostName[]; static const char kBinaryMissingHostName[]; + static const char kSupportsNativeInitiatedConnectionsHostName[]; + static const char kExtensionId[]; ScopedTestNativeMessagingHost();
diff --git a/chrome/browser/extensions/api/messaging/native_process_launcher.cc b/chrome/browser/extensions/api/messaging/native_process_launcher.cc index a281b85..03c3e3009 100644 --- a/chrome/browser/extensions/api/messaging/native_process_launcher.cc +++ b/chrome/browser/extensions/api/messaging/native_process_launcher.cc
@@ -5,20 +5,30 @@ #include "chrome/browser/extensions/api/messaging/native_process_launcher.h" #include <inttypes.h> + #include <utility> +#include "base/base64.h" +#include "base/base_paths.h" +#include "base/base_switches.h" #include "base/bind.h" #include "base/callback.h" #include "base/command_line.h" #include "base/files/file_util.h" +#include "base/json/json_writer.h" #include "base/logging.h" #include "base/macros.h" #include "base/memory/ref_counted.h" +#include "base/path_service.h" +#include "base/strings/strcat.h" #include "base/strings/stringprintf.h" #include "base/task/post_task.h" +#include "base/values.h" #include "build/build_config.h" #include "chrome/browser/extensions/api/messaging/native_messaging_host_manifest.h" +#include "chrome/common/chrome_features.h" #include "chrome/common/chrome_paths.h" +#include "chrome/common/chrome_switches.h" #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_thread.h" #include "url/gurl.h" @@ -35,7 +45,8 @@ class NativeProcessLauncherImpl : public NativeProcessLauncher { public: NativeProcessLauncherImpl(bool allow_user_level_hosts, - intptr_t native_window); + intptr_t native_window, + const base::FilePath& profile_directory); ~NativeProcessLauncherImpl() override; void Launch(const GURL& origin, @@ -45,7 +56,9 @@ private: class Core : public base::RefCountedThreadSafe<Core> { public: - Core(bool allow_user_level_hosts, intptr_t native_window); + Core(bool allow_user_level_hosts, + intptr_t native_window, + const base::FilePath& profile_directory); void Launch(const GURL& origin, const std::string& native_host_name, const LaunchedCallback& callback); @@ -73,6 +86,8 @@ bool allow_user_level_hosts_; + base::FilePath profile_directory_; + #if defined(OS_WIN) // Handle of the native window corresponding to the extension. intptr_t window_handle_; @@ -87,11 +102,14 @@ }; NativeProcessLauncherImpl::Core::Core(bool allow_user_level_hosts, - intptr_t window_handle) + intptr_t window_handle, + const base::FilePath& profile_directory) : detached_(false), - allow_user_level_hosts_(allow_user_level_hosts) + allow_user_level_hosts_(allow_user_level_hosts), + profile_directory_(profile_directory) #if defined(OS_WIN) - , window_handle_(window_handle) + , + window_handle_(window_handle) #endif // OS_WIN {} @@ -196,6 +214,41 @@ base::StringPrintf("--parent-window=%" PRIdPTR, window_handle_)); #endif // !defined(OS_WIN) + if (manifest->supports_native_initiated_connections() && + !profile_directory_.empty()) { + base::FilePath exe_path; + base::PathService::Get(base::FILE_EXE, &exe_path); + + base::CommandLine reconnect_command_line(exe_path); + reconnect_command_line.AppendSwitch(switches::kNoStartupWindow); + reconnect_command_line.AppendSwitchASCII( + switches::kNativeMessagingConnectHost, native_host_name); + reconnect_command_line.AppendSwitchASCII( + switches::kNativeMessagingConnectExtension, origin.host()); + reconnect_command_line.AppendSwitchASCII(switches::kEnableFeatures, + features::kOnConnectNative.name); + reconnect_command_line.AppendSwitchPath(switches::kProfileDirectory, + profile_directory_.BaseName()); + reconnect_command_line.AppendSwitchPath(switches::kUserDataDir, + profile_directory_.DirName()); +#if defined(OS_WIN) + reconnect_command_line.AppendArg( + switches::kPrefetchArgumentBrowserBackground); +#endif + base::Value args(base::Value::Type::LIST); + args.GetList().reserve(reconnect_command_line.argv().size()); + for (const auto& arg : reconnect_command_line.argv()) { + args.GetList().emplace_back(arg); + } + std::string encoded_reconnect_command; + bool success = + base::JSONWriter::Write(std::move(args), &encoded_reconnect_command); + DCHECK(success); + base::Base64Encode(encoded_reconnect_command, &encoded_reconnect_command); + command_line.AppendArg( + base::StrCat({"--reconnect-command=", encoded_reconnect_command})); + } + base::Process process; base::File read_file; base::File write_file; @@ -246,9 +299,10 @@ NativeProcessLauncherImpl::NativeProcessLauncherImpl( bool allow_user_level_hosts, - intptr_t window_handle) - : core_(new Core(allow_user_level_hosts, window_handle)) { -} + intptr_t window_handle, + const base::FilePath& profile_directory) + : core_( + new Core(allow_user_level_hosts, window_handle, profile_directory)) {} NativeProcessLauncherImpl::~NativeProcessLauncherImpl() { core_->Detach(); @@ -265,14 +319,15 @@ // static std::unique_ptr<NativeProcessLauncher> NativeProcessLauncher::CreateDefault( bool allow_user_level_hosts, - gfx::NativeView native_view) { + gfx::NativeView native_view, + const base::FilePath& profile_directory) { intptr_t window_handle = 0; #if defined(OS_WIN) window_handle = reinterpret_cast<intptr_t>( views::HWNDForNativeView(native_view)); #endif - return std::unique_ptr<NativeProcessLauncher>( - new NativeProcessLauncherImpl(allow_user_level_hosts, window_handle)); + return std::make_unique<NativeProcessLauncherImpl>( + allow_user_level_hosts, window_handle, profile_directory); } } // namespace extensions
diff --git a/chrome/browser/extensions/api/messaging/native_process_launcher.h b/chrome/browser/extensions/api/messaging/native_process_launcher.h index 8ebf09c..68032648 100644 --- a/chrome/browser/extensions/api/messaging/native_process_launcher.h +++ b/chrome/browser/extensions/api/messaging/native_process_launcher.h
@@ -42,10 +42,13 @@ // Creates default launcher for the current OS. |native_view| refers to the // window that contains calling page. Can be nullptr, e.g. for background - // pages. + // pages. If |profile_directory| is non-empty and the host supports + // native-initiated connections, additional reconnect args will be passed to + // the host. static std::unique_ptr<NativeProcessLauncher> CreateDefault( bool allow_user_level_hosts, - gfx::NativeView native_view); + gfx::NativeView native_view, + const base::FilePath& profile_directory); NativeProcessLauncher() {} virtual ~NativeProcessLauncher() {}
diff --git a/chrome/browser/extensions/api/tabs/tabs_util_chromeos.cc b/chrome/browser/extensions/api/tabs/tabs_util_chromeos.cc index 5705f21..0a076f31 100644 --- a/chrome/browser/extensions/api/tabs/tabs_util_chromeos.cc +++ b/chrome/browser/extensions/api/tabs/tabs_util_chromeos.cc
@@ -20,7 +20,6 @@ #include "ui/aura/window.h" #include "ui/base/clipboard/clipboard.h" #include "ui/base/clipboard/clipboard_types.h" -#include "ui/base/ui_base_features.h" namespace extensions { namespace tabs_util { @@ -47,10 +46,7 @@ browser->command_controller()->LockedFullscreenStateChanged(); // Disallow screenshots in locked fullscreen mode. - // TODO(isandrk, 816900): ChromeScreenshotGrabber isn't implemented in Mash - // yet, remove this conditional when it becomes available. - if (!features::IsMultiProcessMash()) - ChromeScreenshotGrabber::Get()->set_screenshots_allowed(!locked); + ChromeScreenshotGrabber::Get()->set_screenshots_allowed(!locked); // Reset the clipboard and kill dev tools when entering or exiting locked // fullscreen (security concerns).
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json index 8416b4cc..ff0f502 100644 --- a/chrome/browser/flag-metadata.json +++ b/chrome/browser/flag-metadata.json
@@ -2702,16 +2702,16 @@ "expiry_milestone": 82 }, { + "name": "shelf-hotseat", + "owners": [ "manucornet", "newcomer" ], + "expiry_milestone": 82 + }, + { "name": "shelf-hover-previews", "owners": [ "manucornet" ], "expiry_milestone": 77 }, { - "name": "shelf-new-ui", - "owners": [ "manucornet", "newcomer" ], - "expiry_milestone": 82 - }, - { "name": "shelf-scrollable", "owners": [ "andrewxu", "manucornet" ], "expiry_milestone": 82
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc index 5116734..258cea4 100644 --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc
@@ -1661,17 +1661,18 @@ const char kShelfDenseClamshellDescription[] = "Reduces the size of the shelf and its apps when in laptop mode."; +const char kShelfHotseatName[] = "Enable a modular design for the shelf."; +const char kShelfHotseatDescription[] = + "Shows a modular design for the shelf where the apps are shown separately " + "in a 'hotseat' interface when in tablet mode, and where various pieces " + "are separate and behave independently."; + const char kShelfHoverPreviewsName[] = "Show previews of running apps when hovering over the shelf."; const char kShelfHoverPreviewsDescription[] = "Shows previews of the open windows for a given running app when hovering " "over the shelf."; -const char kShelfNewUiName[] = "Enable a new modular design for the shelf."; -const char kShelfNewUiDescription[] = - "Shows a new modular design for the shelf where the various pieces are " - "separate and behave independently, especially in tablet mode."; - const char kShelfScrollableName[] = "Enable a scrollable list of apps on the shelf"; const char kShelfScrollableDescription[] =
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h index 81bb1b7..f250824 100644 --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h
@@ -983,12 +983,12 @@ extern const char kShelfDenseClamshellName[]; extern const char kShelfDenseClamshellDescription[]; +extern const char kShelfHotseatName[]; +extern const char kShelfHotseatDescription[]; + extern const char kShelfHoverPreviewsName[]; extern const char kShelfHoverPreviewsDescription[]; -extern const char kShelfNewUiName[]; -extern const char kShelfNewUiDescription[]; - extern const char kShelfScrollableName[]; extern const char kShelfScrollableDescription[];
diff --git a/chrome/browser/media/cast_mirroring_service_host_browsertest.cc b/chrome/browser/media/cast_mirroring_service_host_browsertest.cc index 07453b96..ab6ddf2f 100644 --- a/chrome/browser/media/cast_mirroring_service_host_browsertest.cc +++ b/chrome/browser/media/cast_mirroring_service_host_browsertest.cc
@@ -6,7 +6,6 @@ #include "base/containers/flat_map.h" #include "base/run_loop.h" -#include "base/test/scoped_feature_list.h" #include "base/test/test_timeouts.h" #include "build/build_config.h" #include "chrome/browser/ui/browser.h" @@ -27,7 +26,6 @@ #include "media/mojo/interfaces/audio_input_stream.mojom.h" #include "mojo/public/cpp/bindings/binding.h" #include "testing/gmock/include/gmock/gmock.h" -#include "ui/base/ui_base_features.h" using testing::_; using testing::InvokeWithoutArgs; @@ -206,9 +204,6 @@ // InProcessBrowserTest override. void SetUp() override { -#if defined(OS_CHROMEOS) - scoped_feature_list_.InitWithFeatures({}, {features::kMash}); -#endif InProcessBrowserTest::SetUp(); } @@ -233,10 +228,6 @@ OnAudioStreamCreated(); } -#if defined(OS_CHROMEOS) - base::test::ScopedFeatureList scoped_feature_list_; -#endif - mojo::Binding<mojom::SessionObserver> observer_binding_; mojo::Binding<mojom::CastMessageChannel> outbound_channel_binding_; mojo::Binding<mojom::AudioStreamCreatorClient> audio_client_binding_;
diff --git a/chrome/browser/media/webrtc/desktop_capture_access_handler.cc b/chrome/browser/media/webrtc/desktop_capture_access_handler.cc index 9fe0127..6b9128f 100644 --- a/chrome/browser/media/webrtc/desktop_capture_access_handler.cc +++ b/chrome/browser/media/webrtc/desktop_capture_access_handler.cc
@@ -180,15 +180,6 @@ blink::mojom::MediaStreamRequestResult result = blink::mojom::MediaStreamRequestResult::INVALID_STATE; -#if defined(OS_CHROMEOS) - if (features::IsMultiProcessMash()) { - // TODO(crbug.com/806366): Screen capture support for mash. - NOTIMPLEMENTED() << "Screen capture not yet implemented in --mash"; - screen_capture_enabled = false; - result = blink::mojom::MediaStreamRequestResult::NOT_SUPPORTED; - } -#endif // defined(OS_CHROMEOS) - // Approve request only when the following conditions are met: // 1. Screen capturing is enabled via command line switch or white-listed for // the given origin.
diff --git a/chrome/browser/memory/oom_memory_details.cc b/chrome/browser/memory/oom_memory_details.cc index 4a0f24a..5d7f6bfee 100644 --- a/chrome/browser/memory/oom_memory_details.cc +++ b/chrome/browser/memory/oom_memory_details.cc
@@ -5,7 +5,6 @@ #include "chrome/browser/memory/oom_memory_details.h" #include "base/logging.h" -#include "base/metrics/histogram_macros.h" #include "base/process/process_metrics.h" #include "base/strings/utf_string_conversions.h" #include "build/build_config.h" @@ -42,7 +41,6 @@ log_string += base::UTF16ToASCII(ui::FormatBytes(memory.gem_size)); } #endif - UMA_HISTOGRAM_MEDIUM_TIMES("TabManager.Discarding.LogMemoryTime", delta); LOG(WARNING) << title_ << " (" << delta.InMilliseconds() << " ms):\n" << log_string; // Delete ourselves so we don't have to worry about OomPriorityManager
diff --git a/chrome/browser/platform_util_chromeos.cc b/chrome/browser/platform_util_chromeos.cc index 11391d2..259c1ace 100644 --- a/chrome/browser/platform_util_chromeos.cc +++ b/chrome/browser/platform_util_chromeos.cc
@@ -20,7 +20,6 @@ #include "content/public/browser/browser_thread.h" #include "ui/aura/window.h" #include "ui/base/l10n/l10n_util.h" -#include "ui/base/ui_base_features.h" #include "ui/chromeos/strings/grit/ui_chromeos_strings.h" #include "url/gurl.h" @@ -129,8 +128,6 @@ // |window| can be nullptr inside of unit tests. if (!window) return false; - if (features::IsUsingWindowService()) - window = window->GetRootWindow(); return window->GetProperty(ash::kWindowPinTypeKey) == ash::WindowPinType::kTrustedPinned; }
diff --git a/chrome/browser/push_messaging/push_messaging_browsertest.cc b/chrome/browser/push_messaging/push_messaging_browsertest.cc index f8e216d..d3ee033 100644 --- a/chrome/browser/push_messaging/push_messaging_browsertest.cc +++ b/chrome/browser/push_messaging/push_messaging_browsertest.cc
@@ -16,6 +16,7 @@ #include "base/run_loop.h" #include "base/strings/utf_string_conversions.h" #include "base/test/metrics/histogram_tester.h" +#include "base/test/scoped_feature_list.h" #include "build/build_config.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/browsing_data/browsing_data_helper.h" @@ -54,6 +55,7 @@ #include "content/public/browser/browsing_data_remover.h" #include "content/public/browser/notification_service.h" #include "content/public/browser/web_contents.h" +#include "content/public/common/content_features.h" #include "content/public/common/content_switches.h" #include "content/public/test/browser_test_utils.h" #include "content/public/test/browsing_data_remover_test_util.h" @@ -1600,6 +1602,56 @@ } IN_PROC_BROWSER_TEST_F(PushMessagingBrowserTest, + PushEventIgnoresScheduledNotificationsForEnforcement) { + base::test::ScopedFeatureList scoped_feature_list; + scoped_feature_list.InitAndEnableFeature(features::kNotificationTriggers); + + std::string script_result; + + ASSERT_NO_FATAL_FAILURE(SubscribeSuccessfully()); + PushMessagingAppIdentifier app_identifier = + GetAppIdentifierForServiceWorkerRegistration(0LL); + + LoadTestPage(); // Reload to become controlled. + + RemoveAllNotifications(); + + // We'll need to specify the web_contents in which to eval script, since we're + // going to run script in a background tab. + content::WebContents* web_contents = + GetBrowser()->tab_strip_model()->GetActiveWebContents(); + + // Initialize site engagement score to have no budget for silent pushes. + SetSiteEngagementScore(web_contents->GetURL(), 0); + + ui_test_utils::NavigateToURLWithDisposition( + GetBrowser(), GURL("about:blank"), + WindowOpenDisposition::NEW_FOREGROUND_TAB, + ui_test_utils::BROWSER_TEST_WAIT_FOR_TAB); + + gcm::IncomingMessage message; + message.sender_id = GetTestApplicationServerKey(); + message.raw_data = "shownotification-with-showtrigger"; + message.decrypted = true; + + // If the Service Worker push event handler only schedules a notification, we + // should show a forced one providing there is no foreground tab and the + // origin ran out of budget. + SendMessageAndWaitUntilHandled(app_identifier, message); + ASSERT_TRUE(RunScript("resultQueue.pop()", &script_result, web_contents)); + EXPECT_EQ("shownotification-with-showtrigger", script_result); + + // Because scheduled notifications do not count as displayed notifications, + // this should have shown a default notification. + std::vector<message_center::Notification> notifications = + GetDisplayedNotifications(); + ASSERT_EQ(notifications.size(), 1u); + + EXPECT_TRUE(TagEquals(notifications[0], kPushMessagingForcedNotificationTag)); + EXPECT_TRUE(notifications[0].silent()); +} + +IN_PROC_BROWSER_TEST_F(PushMessagingBrowserTest, PushEventEnforcesUserVisibleNotificationAfterQueue) { std::string script_result;
diff --git a/chrome/browser/push_messaging/push_messaging_notification_manager.cc b/chrome/browser/push_messaging/push_messaging_notification_manager.cc index ed5026d..22260185 100644 --- a/chrome/browser/push_messaging/push_messaging_notification_manager.cc +++ b/chrome/browser/push_messaging/push_messaging_notification_manager.cc
@@ -11,6 +11,7 @@ #include "base/bind.h" #include "base/bind_helpers.h" +#include "base/feature_list.h" #include "base/metrics/histogram_macros.h" #include "base/strings/utf_string_conversions.h" #include "base/task/post_task.h" @@ -33,6 +34,7 @@ #include "content/public/browser/render_frame_host.h" #include "content/public/browser/storage_partition.h" #include "content/public/browser/web_contents.h" +#include "content/public/common/content_features.h" #include "content/public/common/url_constants.h" #include "net/base/registry_controlled_domains/registry_controlled_domain.h" #include "third_party/blink/public/common/notifications/notification_resources.h" @@ -95,6 +97,19 @@ return database_data; } +int CountVisibleNotifications( + const std::vector<NotificationDatabaseData>& data) { + if (!base::FeatureList::IsEnabled(features::kNotificationTriggers)) + return data.size(); + + return std::count_if( + data.begin(), data.end(), + [](const NotificationDatabaseData& notification) { + return notification.has_triggered || + !notification.notification_data.show_trigger_timestamp; + }); +} + } // namespace PushMessagingNotificationManager::PushMessagingNotificationManager( @@ -140,7 +155,10 @@ // user-visible action done in response to a push message - but make sure that // sending two messages in rapid succession which show then hide a // notification doesn't count. - int notification_count = success ? data.size() : 0; + // TODO(knollr): Scheduling a notification should count as a user-visible + // action, if it is not immediately cancelled or the |origin| schedules too + // many notifications too far in the future. + int notification_count = success ? CountVisibleNotifications(data) : 0; bool notification_shown = notification_count > 0; bool notification_needed = true;
diff --git a/chrome/browser/resources/chromeos/login/sync_consent.css b/chrome/browser/resources/chromeos/login/sync_consent.css index 5686783..08c1fe2 100644 --- a/chrome/browser/resources/chromeos/login/sync_consent.css +++ b/chrome/browser/resources/chromeos/login/sync_consent.css
@@ -34,12 +34,10 @@ } cr-checkbox { - --cr-checkbox-label-container: { - padding-inline-start: 12px; - }; align-self: start; /* Prevent label from spanning the whole width. */ margin-top: 28px; /* 40 to label base line => 40 - 16/2 - 13/3 = 28 */ padding-inline-start: 8px; + --cr-checkbox-label-padding-start: 12px; } #syncConsentOverviewDialog [slot='bottom-buttons'] {
diff --git a/chrome/browser/resources/media_router/elements/route_controls/route_controls.css b/chrome/browser/resources/media_router/elements/route_controls/route_controls.css index 811d8db7..371416a 100644 --- a/chrome/browser/resources/media_router/elements/route_controls/route_controls.css +++ b/chrome/browser/resources/media_router/elements/route_controls/route_controls.css
@@ -88,10 +88,8 @@ } #hangouts-local-present-checkbox { - --cr-checkbox-label-container: { - padding-inline-start: 14px; - } align-items: start; + --cr-checkbox-label-padding-start: 14px; } #hangouts-local-present-checkbox-subtitle {
diff --git a/chrome/browser/resources/print_preview/ui/print_preview_shared_css.html b/chrome/browser/resources/print_preview/ui/print_preview_shared_css.html index 3cfa753..c2a865f 100644 --- a/chrome/browser/resources/print_preview/ui/print_preview_shared_css.html +++ b/chrome/browser/resources/print_preview/ui/print_preview_shared_css.html
@@ -28,10 +28,11 @@ .checkbox cr-checkbox { min-height: var(--print-preview-row-height); --cr-checkbox-ripple-size: var(--print-preview-row-height); - --cr-checkbox-label-container: { - overflow: hidden; - padding-inline-start: 16px; - }; + } + + .checkbox cr-checkbox::part(label-container) { + overflow: hidden; + padding-inline-start: 16px; } cr-input {
diff --git a/chrome/browser/resources/settings/appearance_page/appearance_page.html b/chrome/browser/resources/settings/appearance_page/appearance_page.html index f06a9f69..fd6ed00a 100644 --- a/chrome/browser/resources/settings/appearance_page/appearance_page.html +++ b/chrome/browser/resources/settings/appearance_page/appearance_page.html
@@ -23,11 +23,10 @@ <style include="settings-shared md-select iron-flex"> /* Lines up with cr-input. */ #custom-input { - --cr-radio-button-disc: { - /* (cr-input line-height + cr-input top/bottom padding) / 2 - - cr-radio disc-wrapper height / 2 */ - margin-top: calc((1.54em + 12px) / 2 - 8px); - } + /* (cr-input line-height + cr-input top/bottom padding) / 2 - + cr-radio disc-wrapper height / 2 */ + --cr-radio-button-disc-margin-block-start: calc( + (1.54em + 12px) / 2 - 8px); align-items: start; }
diff --git a/chrome/browser/resources/settings/chromeos/os_languages_page/os_add_languages_dialog.html b/chrome/browser/resources/settings/chromeos/os_languages_page/os_add_languages_dialog.html index 28ed776..e0a8a82 100644 --- a/chrome/browser/resources/settings/chromeos/os_languages_page/os_add_languages_dialog.html +++ b/chrome/browser/resources/settings/chromeos/os_languages_page/os_add_languages_dialog.html
@@ -35,10 +35,8 @@ padding-inline-start: 20px; } - cr-checkbox { - --cr-checkbox-label-container: { - white-space: nowrap; - }; + cr-checkbox::part(label-container) { + white-space: nowrap; } </style> <cr-dialog id="dialog" close-text="$i18n{close}">
diff --git a/chrome/browser/resources/settings/languages_page/add_languages_dialog.html b/chrome/browser/resources/settings/languages_page/add_languages_dialog.html index bdb4c7200..9611202 100644 --- a/chrome/browser/resources/settings/languages_page/add_languages_dialog.html +++ b/chrome/browser/resources/settings/languages_page/add_languages_dialog.html
@@ -35,10 +35,8 @@ padding-inline-start: 20px; } - cr-checkbox { - --cr-checkbox-label-container: { - white-space: nowrap; - }; + cr-checkbox::part(label-container) { + white-space: nowrap; } </style> <cr-dialog id="dialog" close-text="$i18n{close}">
diff --git a/chrome/browser/resources/settings/languages_page/languages_page.html b/chrome/browser/resources/settings/languages_page/languages_page.html index 73fe939..c220332e 100644 --- a/chrome/browser/resources/settings/languages_page/languages_page.html +++ b/chrome/browser/resources/settings/languages_page/languages_page.html
@@ -147,10 +147,9 @@ .spell-check-radio-button.enhanced { align-items: start; - --cr-radio-button-disc: { - /* Align with just the first line of text */ - margin-top: calc((1.5em - var(--cr-radio-button-size)) / 2); - } + /* Align with just the first line of text */ + --cr-radio-button-disc-margin-block-start: calc( + (1.5em - var(--cr-radio-button-size)) / 2); } .enhanced-spellcheck-description {
diff --git a/chrome/browser/resources/settings/people_page/lock_screen.html b/chrome/browser/resources/settings/people_page/lock_screen.html index bdd84b5e..a2ce568 100644 --- a/chrome/browser/resources/settings/people_page/lock_screen.html +++ b/chrome/browser/resources/settings/people_page/lock_screen.html
@@ -36,16 +36,15 @@ display: block; } - cr-radio-button { - --cr-radio-button-slot: { - display: flex; - line-height: 154%; /* Apply 20px line-height to paper radio button - text to match rest of settings line-heights. */ - width: 100%; - }; + #pinPasswordDiv { + display: flex; } - #pinPasswordDiv, + #pinPasswordLabel { + flex: 1; + } + + #pinPasswordLabel, #pinPasswordSecondaryActionDiv { margin: auto; } @@ -92,23 +91,25 @@ </div> </cr-radio-button> <cr-radio-button name="pin+password" class="list-item"> - <div id="pinPasswordDiv" class="start"> - $i18n{lockScreenPinOrPassword} - </div> - <template is="dom-if" - if="[[showConfigurePinButton_(selectedUnlockType)]]"> - <div class="separator"></div> - <div id="pinPasswordSecondaryActionDiv" - class="secondary-action"> - <!-- Use stop-keyboard-event-propagation to prevent - triggering this when focused after closing the - dialog. --> - <cr-button id="setupPinButton" on-click="onConfigurePin_" - stop-keyboard-event-propagation> - [[getSetupPinText_(hasPin)]] - </cr-button> + <div id="pinPasswordDiv"> + <div id="pinPasswordLabel"> + $i18n{lockScreenPinOrPassword} </div> - </template> + <template is="dom-if" + if="[[showConfigurePinButton_(selectedUnlockType)]]"> + <div class="separator"></div> + <div id="pinPasswordSecondaryActionDiv" + class="secondary-action"> + <!-- Use stop-keyboard-event-propagation to prevent + triggering this when focused after closing the + dialog. --> + <cr-button id="setupPinButton" on-click="onConfigurePin_" + stop-keyboard-event-propagation> + [[getSetupPinText_(hasPin)]] + </cr-button> + </div> + </template> + </div> </cr-radio-button> </cr-radio-group> </div>
diff --git a/chrome/browser/sync/sessions/sync_sessions_router_tab_helper.cc b/chrome/browser/sync/sessions/sync_sessions_router_tab_helper.cc index 4d6ed91..904043e 100644 --- a/chrome/browser/sync/sessions/sync_sessions_router_tab_helper.cc +++ b/chrome/browser/sync/sessions/sync_sessions_router_tab_helper.cc
@@ -4,14 +4,18 @@ #include "chrome/browser/sync/sessions/sync_sessions_router_tab_helper.h" +#include "base/feature_list.h" #include "base/memory/ptr_util.h" #include "chrome/browser/sessions/session_tab_helper.h" #include "chrome/browser/sync/sessions/sync_sessions_web_contents_router.h" +#include "components/favicon/content/content_favicon_driver.h" +#include "components/favicon/core/features.h" #include "components/language/core/common/language_experiments.h" #include "components/sync_sessions/synced_tab_delegate.h" #include "content/public/browser/navigation_entry.h" #include "content/public/browser/navigation_handle.h" #include "content/public/browser/render_frame_host.h" +#include "ui/gfx/image/image_skia.h" namespace sync_sessions { @@ -38,6 +42,11 @@ // A translate client is not always attached to web contents (e.g. tests). if (chrome_translate_client_) chrome_translate_client_->translate_driver().AddObserver(this); + + favicon_driver_ = + favicon::ContentFaviconDriver::FromWebContents(web_contents); + if (favicon_driver_) + favicon_driver_->AddObserver(this); } SyncSessionsRouterTabHelper::~SyncSessionsRouterTabHelper() {} @@ -56,6 +65,8 @@ NotifyRouter(); if (chrome_translate_client_) chrome_translate_client_->translate_driver().RemoveObserver(this); + if (favicon_driver_) + favicon_driver_->RemoveObserver(this); } void SyncSessionsRouterTabHelper::DidFinishLoad( @@ -102,6 +113,19 @@ router_->NotifyTabModified(web_contents(), page_load_completed); } +void SyncSessionsRouterTabHelper::OnFaviconUpdated( + favicon::FaviconDriver* favicon_driver, + FaviconDriverObserver::NotificationIconType notification_icon_type, + const GURL& icon_url, + bool icon_url_changed, + const gfx::Image& image) { + if (icon_url_changed && + base::FeatureList::IsEnabled( + favicon::kNotifySessionsOfMostRecentIconUrlChange)) { + NotifyRouter(); + } +} + WEB_CONTENTS_USER_DATA_KEY_IMPL(SyncSessionsRouterTabHelper) } // namespace sync_sessions
diff --git a/chrome/browser/sync/sessions/sync_sessions_router_tab_helper.h b/chrome/browser/sync/sessions/sync_sessions_router_tab_helper.h index 93756a4..b76434b 100644 --- a/chrome/browser/sync/sessions/sync_sessions_router_tab_helper.h +++ b/chrome/browser/sync/sessions/sync_sessions_router_tab_helper.h
@@ -6,11 +6,16 @@ #define CHROME_BROWSER_SYNC_SESSIONS_SYNC_SESSIONS_ROUTER_TAB_HELPER_H_ #include "chrome/browser/translate/chrome_translate_client.h" +#include "components/favicon/core/favicon_driver_observer.h" #include "components/sessions/core/session_id.h" #include "components/translate/content/browser/content_translate_driver.h" #include "content/public/browser/web_contents_observer.h" #include "content/public/browser/web_contents_user_data.h" +namespace favicon { +class FaviconDriver; +} + namespace sync_sessions { class SyncSessionsWebContentsRouter; @@ -25,7 +30,8 @@ class SyncSessionsRouterTabHelper : public content::WebContentsUserData<SyncSessionsRouterTabHelper>, public content::WebContentsObserver, - public translate::ContentTranslateDriver::Observer { + public translate::ContentTranslateDriver::Observer, + public favicon::FaviconDriverObserver { public: ~SyncSessionsRouterTabHelper() override; @@ -53,6 +59,14 @@ void OnLanguageDetermined( const translate::LanguageDetectionDetails& details) override; + // favicon::FaviconDriverObserver implementation. + void OnFaviconUpdated( + favicon::FaviconDriver* favicon_driver, + FaviconDriverObserver::NotificationIconType notification_icon_type, + const GURL& icon_url, + bool icon_url_changed, + const gfx::Image& image) override; + // Sets the source tab id for the given child WebContents to the id of the // WebContents that owns this helper. void SetSourceTabIdForChild(content::WebContents* child_contents); @@ -85,6 +99,8 @@ ChromeTranslateClient* chrome_translate_client_; + favicon::FaviconDriver* favicon_driver_; + WEB_CONTENTS_USER_DATA_KEY_DECL(); DISALLOW_COPY_AND_ASSIGN(SyncSessionsRouterTabHelper);
diff --git a/chrome/browser/sync/test/integration/single_client_sessions_sync_test.cc b/chrome/browser/sync/test/integration/single_client_sessions_sync_test.cc index 550ed9e..ea55ece 100644 --- a/chrome/browser/sync/test/integration/single_client_sessions_sync_test.cc +++ b/chrome/browser/sync/test/integration/single_client_sessions_sync_test.cc
@@ -21,11 +21,13 @@ #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/common/url_constants.h" +#include "components/favicon/core/features.h" #include "components/history/core/browser/history_types.h" #include "components/sessions/core/session_types.h" #include "components/signin/core/browser/account_info.h" #include "components/sync/base/time.h" #include "components/sync/protocol/proto_value_conversions.h" +#include "components/sync/protocol/session_specifics.pb.h" #include "components/sync/test/fake_server/sessions_hierarchy.h" #include "components/sync_sessions/session_store.h" #include "components/sync_sessions/session_sync_service.h" @@ -110,6 +112,49 @@ fake_server::FakeServer* fake_server_; }; +class IsIconURLSyncedChecker : public SingleClientStatusChangeChecker { + public: + IsIconURLSyncedChecker(const std::string& page_url, + const std::string& icon_url, + fake_server::FakeServer* fake_server, + syncer::ProfileSyncService* service) + : SingleClientStatusChangeChecker(service), + page_url_(page_url), + icon_url_(icon_url), + fake_server_(fake_server) {} + + // StatusChangeChecker implementation. + bool IsExitConditionSatisfied() override { + std::vector<sync_pb::SyncEntity> sessions = + fake_server_->GetSyncEntitiesByModelType(syncer::SESSIONS); + for (const auto& entity : sessions) { + const sync_pb::SessionSpecifics& session_specifics = + entity.specifics().session(); + if (!session_specifics.has_tab()) { + continue; + } + for (int i = 0; i < session_specifics.tab().navigation_size(); i++) { + const sync_pb::TabNavigation& nav = + session_specifics.tab().navigation(i); + if (nav.has_virtual_url() && nav.has_favicon_url() && + nav.virtual_url() == page_url_ && nav.favicon_url() == icon_url_) { + return true; + } + } + } + return false; + } + + std::string GetDebugMessage() const override { + return "Waiting for URLs to be commited to the server"; + } + + private: + const std::string page_url_; + const std::string icon_url_; + fake_server::FakeServer* fake_server_; +}; + class SingleClientSessionsSyncTest : public SyncTest { public: SingleClientSessionsSyncTest() : SyncTest(SINGLE_CLIENT) {} @@ -748,4 +793,29 @@ } } +IN_PROC_BROWSER_TEST_F(SingleClientSessionsSyncTest, + ShouldNotifyLoadedIconUrl) { + base::test::ScopedFeatureList scoped_feature_list; + scoped_feature_list.InitAndEnableFeature( + favicon::kNotifySessionsOfMostRecentIconUrlChange); + + ASSERT_TRUE(SetupSync()) << "SetupSync() failed."; + ASSERT_TRUE(CheckInitialState(0)); + + // Url with endoded 1 pixel icon. + std::string icon_url = + "data:image/png;base64," + "R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7"; + std::string page_url = + "data:text/html,<html><title>TestWithFavicon</title><link rel=icon " + "href=" + + icon_url + " /></html>"; + + ASSERT_TRUE(OpenTab(0, GURL(page_url))); + + IsIconURLSyncedChecker checker(page_url, icon_url, GetFakeServer(), + GetSyncService(0)); + EXPECT_TRUE(checker.Wait()); +} + } // namespace
diff --git a/chrome/browser/ui/app_list/app_service_app_model_builder.cc b/chrome/browser/ui/app_list/app_service_app_model_builder.cc index 5a0f4a4c..3eb20e5 100644 --- a/chrome/browser/ui/app_list/app_service_app_model_builder.cc +++ b/chrome/browser/ui/app_list/app_service_app_model_builder.cc
@@ -5,12 +5,17 @@ #include "chrome/browser/ui/app_list/app_service_app_model_builder.h" #include "chrome/browser/apps/app_service/app_service_proxy_factory.h" +#include "chrome/browser/chromeos/arc/arc_util.h" #include "chrome/browser/chromeos/crostini/crostini_util.h" #include "chrome/browser/ui/app_list/app_service_app_item.h" #include "chrome/grit/generated_resources.h" #include "chrome/services/app_service/public/cpp/app_service_proxy.h" #include "ui/base/l10n/l10n_util.h" +// static +apps::AppServiceProxy* + AppServiceAppModelBuilder::app_service_proxy_for_testing_ = nullptr; + // Folder items are created by the Ash process and their existence is // communicated to chrome via the AppListClient. Therefore, Crostini has an // observer that listens for the creation of its folder, and updates the @@ -56,9 +61,19 @@ } } +// static +apps::AppServiceProxy* AppServiceAppModelBuilder::SetAppServiceProxyForTesting( + apps::AppServiceProxy* proxy) { + apps::AppServiceProxy* old = app_service_proxy_for_testing_; + app_service_proxy_for_testing_ = proxy; + return old; +} + void AppServiceAppModelBuilder::BuildModel() { apps::AppServiceProxy* proxy = - apps::AppServiceProxyFactory::GetForProfile(profile()); + app_service_proxy_for_testing_ + ? app_service_proxy_for_testing_ + : apps::AppServiceProxyFactory::GetForProfile(profile()); if (proxy) { proxy->AppRegistryCache().ForEachApp( [this](const apps::AppUpdate& update) { OnAppUpdate(update); }); @@ -97,7 +112,13 @@ } } else { - RemoveApp(update.AppId(), false /* unsynced_change */); + bool unsynced_change = false; + if (update.AppType() == apps::mojom::AppType::kArc) { + // Don't sync app removal in case it was caused by disabling Google + // Play Store. + unsynced_change = !arc::IsArcPlayStoreEnabledForProfile(profile()); + } + RemoveApp(update.AppId(), unsynced_change); } } else if (show) {
diff --git a/chrome/browser/ui/app_list/app_service_app_model_builder.h b/chrome/browser/ui/app_list/app_service_app_model_builder.h index c3a2a5b..beb6cb2 100644 --- a/chrome/browser/ui/app_list/app_service_app_model_builder.h +++ b/chrome/browser/ui/app_list/app_service_app_model_builder.h
@@ -11,6 +11,10 @@ class AppListControllerDelegate; +namespace apps { +class AppServiceProxy; +} + class AppServiceAppModelBuilder : public AppListModelBuilder, public apps::AppRegistryCache::Observer { public: @@ -18,9 +22,14 @@ ~AppServiceAppModelBuilder() override; + static apps::AppServiceProxy* SetAppServiceProxyForTesting( + apps::AppServiceProxy* proxy); + private: class CrostiniFolderObserver; + static apps::AppServiceProxy* app_service_proxy_for_testing_; + // AppListModelBuilder overrides: void BuildModel() override;
diff --git a/chrome/browser/ui/app_list/search/search_result_ranker/ranking_item_util.cc b/chrome/browser/ui/app_list/search/search_result_ranker/ranking_item_util.cc index 8cb964e..0d5be3b9 100644 --- a/chrome/browser/ui/app_list/search/search_result_ranker/ranking_item_util.cc +++ b/chrome/browser/ui/app_list/search/search_result_ranker/ranking_item_util.cc
@@ -8,6 +8,7 @@ #include "ash/public/cpp/app_list/app_list_types.h" #include "base/macros.h" #include "base/metrics/field_trial_params.h" +#include "base/strings/string_util.h" #include "chrome/browser/ui/app_list/chrome_app_list_item.h" #include "chrome/browser/ui/app_list/search/chrome_search_result.h" #include "components/omnibox/browser/autocomplete_match_type.h" @@ -89,4 +90,35 @@ return RankingItemType::kApp; } +std::string SimplifyUrlId(const std::string& url_id) { + std::string result(url_id); + + std::size_t query_index = result.find("?"); + if (query_index != std::string::npos) + result.erase(query_index); + + std::size_t fragment_index = result.find("#"); + if (fragment_index != std::string::npos) + result.erase(fragment_index); + + if (!result.empty() && result.back() == '/' && + result.find("://") != result.size() - 3) + result.pop_back(); + + return result; +} + +std::string SimplifyGoogleDocsUrlId(const std::string& url_id) { + std::string result = SimplifyUrlId(url_id); + + // URLs that end with /view or /edit point to the same document, so should be + // the same for ranking purposes. + if (base::EndsWith(result, "/view", base::CompareCase::INSENSITIVE_ASCII) || + base::EndsWith(result, "/edit", base::CompareCase::INSENSITIVE_ASCII)) { + result = result.substr(0, result.length() - 5); + } + + return result; +} + } // namespace app_list
diff --git a/chrome/browser/ui/app_list/search/search_result_ranker/ranking_item_util.h b/chrome/browser/ui/app_list/search/search_result_ranker/ranking_item_util.h index f8d274a2..9f11f118 100644 --- a/chrome/browser/ui/app_list/search/search_result_ranker/ranking_item_util.h +++ b/chrome/browser/ui/app_list/search/search_result_ranker/ranking_item_util.h
@@ -5,6 +5,8 @@ #ifndef CHROME_BROWSER_UI_APP_LIST_SEARCH_SEARCH_RESULT_RANKER_RANKING_ITEM_UTIL_H_ #define CHROME_BROWSER_UI_APP_LIST_SEARCH_SEARCH_RESULT_RANKER_RANKING_ITEM_UTIL_H_ +#include <string> + class ChromeAppListItem; class ChromeSearchResult; @@ -37,6 +39,15 @@ RankingItemType RankingItemTypeFromChromeAppListItem( const ChromeAppListItem& item); +// Given a search result ID representing a URL, removes some components of the +// URL such as the query and fragment. This is intended to normalize URLs that +// should be considered the same for the purposes of ranking. +std::string SimplifyUrlId(const std::string& url_id); + +// Given a search result ID representing a google docs file, remove parts of the +// URL that can vary without affecting what doc the URL resolves to. +std::string SimplifyGoogleDocsUrlId(const std::string& url_id); + } // namespace app_list #endif // CHROME_BROWSER_UI_APP_LIST_SEARCH_SEARCH_RESULT_RANKER_RANKING_ITEM_UTIL_H_
diff --git a/chrome/browser/ui/app_list/search/search_result_ranker/ranking_item_util_unittest.cc b/chrome/browser/ui/app_list/search/search_result_ranker/ranking_item_util_unittest.cc index 4b4dcf6..0dd6086 100644 --- a/chrome/browser/ui/app_list/search/search_result_ranker/ranking_item_util_unittest.cc +++ b/chrome/browser/ui/app_list/search/search_result_ranker/ranking_item_util_unittest.cc
@@ -66,4 +66,40 @@ EXPECT_EQ(type, RankingItemType::kOmniboxHistory); } +TEST_F(RankingItemUtilTest, SimplifyUrlId) { + // Test handling different kinds of scheme, domain, and path. These should all + // be no-ops. + EXPECT_EQ(SimplifyUrlId("scheme://domain.com/path"), + "scheme://domain.com/path"); + EXPECT_EQ(SimplifyUrlId("://domain.com"), "://domain.com"); + EXPECT_EQ(SimplifyUrlId("domain.com/path"), "domain.com/path"); + EXPECT_EQ(SimplifyUrlId("domain.com:1123/path"), "domain.com:1123/path"); + EXPECT_EQ(SimplifyUrlId("://"), "://"); + + // Test removing trailing slash. + EXPECT_EQ(SimplifyUrlId("scheme://domain.com/"), "scheme://domain.com"); + EXPECT_EQ(SimplifyUrlId("scheme:///"), "scheme://"); + EXPECT_EQ(SimplifyUrlId("scheme://"), "scheme://"); + + // Test removing queries and fragments. + EXPECT_EQ(SimplifyUrlId("domain.com/path?query=query"), "domain.com/path"); + EXPECT_EQ(SimplifyUrlId("scheme://path?query=query#fragment"), + "scheme://path"); + EXPECT_EQ(SimplifyUrlId("scheme://?query=query#fragment"), "scheme://"); +} + +TEST_F(RankingItemUtilTest, SimplifyGoogleDocsUrlId) { + EXPECT_EQ(SimplifyGoogleDocsUrlId("docs.google.com/hash/edit?"), + "docs.google.com/hash"); + EXPECT_EQ(SimplifyGoogleDocsUrlId( + "http://docs.google.com/hash/view?query#fragment"), + "http://docs.google.com/hash"); + EXPECT_EQ(SimplifyGoogleDocsUrlId("https://docs.google.com/d/document/hash/"), + "https://docs.google.com/d/document/hash"); + + // We only want to remove one /view or /edit from the end of the URL. + EXPECT_EQ(SimplifyGoogleDocsUrlId("docs.google.com/edit/hash/view/view"), + "docs.google.com/edit/hash/view"); +} + } // namespace app_list
diff --git a/chrome/browser/ui/app_list/search/search_result_ranker/search_result_ranker.cc b/chrome/browser/ui/app_list/search/search_result_ranker/search_result_ranker.cc index 901ac576..c040272 100644 --- a/chrome/browser/ui/app_list/search/search_result_ranker/search_result_ranker.cc +++ b/chrome/browser/ui/app_list/search/search_result_ranker/search_result_ranker.cc
@@ -22,6 +22,7 @@ #include "chrome/browser/ui/app_list/search/chrome_search_result.h" #include "chrome/browser/ui/app_list/search/search_result_ranker/ranking_item_util.h" #include "chrome/browser/ui/app_list/search/search_result_ranker/recurrence_ranker.h" +#include "url/gurl.h" namespace app_list { namespace { @@ -81,6 +82,27 @@ } } +// Performs any per-type normalization required on a search result ID. This is +// meant to simplify the space of IDs in cases where they are too sparse. +std::string NormalizeId(const std::string& id, RankingItemType type) { + // Put any further normalizations here. + switch (type) { + case RankingItemType::kOmniboxGeneric: + case RankingItemType::kOmniboxBookmark: + case RankingItemType::kOmniboxDocument: + case RankingItemType::kOmniboxHistory: + case RankingItemType::kOmniboxSearch: + // Heuristically check if the URL points to a Drive file. If so, strip + // some extra information from it. + if (GURL(id).host() == "docs.google.com") + return SimplifyGoogleDocsUrlId(id); + else + return SimplifyUrlId(id); + default: + return id; + } +} + } // namespace SearchResultRanker::SearchResultRanker(Profile* profile) @@ -202,8 +224,8 @@ 3.0); } } else if (query_based_mixed_types_ranker_) { - // TODO(931149): Add some normalization for URLs. - const auto& rank_it = query_mixed_ranks_.find(result.result->id()); + const auto& rank_it = + query_mixed_ranks_.find(NormalizeId(result.result->id(), type)); if (rank_it != query_mixed_ranks_.end()) { result.score = std::min( result.score + rank_it->second * results_list_boost_coefficient_, @@ -216,12 +238,11 @@ void SearchResultRanker::Train(const std::string& id, RankingItemType type) { if (ModelForType(type) == Model::MIXED_TYPES) { - // TODO(931149): Add some normalization for URLs. if (results_list_group_ranker_) { results_list_group_ranker_->Record( base::NumberToString(static_cast<int>(type))); } else if (query_based_mixed_types_ranker_) { - query_based_mixed_types_ranker_->Record(id); + query_based_mixed_types_ranker_->Record(NormalizeId(id, type)); } } }
diff --git a/chrome/browser/ui/app_list/search/search_result_ranker/search_result_ranker_unittest.cc b/chrome/browser/ui/app_list/search/search_result_ranker/search_result_ranker_unittest.cc index 41578438..c1ea9fd 100644 --- a/chrome/browser/ui/app_list/search/search_result_ranker/search_result_ranker_unittest.cc +++ b/chrome/browser/ui/app_list/search/search_result_ranker/search_result_ranker_unittest.cc
@@ -191,5 +191,34 @@ HasId("A"), HasId("B")))); } +// URL IDs should ignore the query and fragment, and URLs for google docs should +// ignore a trailing /view or /edit. +TEST_F(SearchResultRankerTest, ItemModelNormalizesUrlIds) { + // We want |url_1| and |_3| to be equivalent to |url_2| and |_4|. So, train on + // 1 and 3 but rank 2 and 4. Even with zero relevance, they should be at the + // top of the rankings. + const std::string& url_1 = "http://docs.google.com/mydoc/edit?query"; + const std::string& url_2 = "http://docs.google.com/mydoc/view#fragment"; + const std::string& url_3 = "some.domain.com?query#edit"; + const std::string& url_4 = "some.domain.com"; + + auto ranker = MakeRanker(true, {{"boost_coefficient", "1.0"}}); + + for (int i = 0; i < 5; ++i) { + ranker->Train(url_1, RankingItemType::kOmniboxHistory); + ranker->Train(url_3, RankingItemType::kOmniboxHistory); + } + ranker->FetchRankings(base::string16()); + + auto results = MakeSearchResults( + {url_2, url_4, "untrained id"}, + {ResultType::kOmnibox, ResultType::kOmnibox, ResultType::kOmnibox}, + {0.0f, 0.0f, 0.1f}); + + ranker->Rank(&results); + EXPECT_THAT(results, WhenSorted(ElementsAre(HasId(url_4), HasId(url_2), + HasId("untrained id")))); +} + } // namespace test } // namespace app_list
diff --git a/chrome/browser/ui/ash/accelerator_commands_browsertest.cc b/chrome/browser/ui/ash/accelerator_commands_browsertest.cc index b9ed8080..99048491 100644 --- a/chrome/browser/ui/ash/accelerator_commands_browsertest.cc +++ b/chrome/browser/ui/ash/accelerator_commands_browsertest.cc
@@ -25,7 +25,6 @@ #include "ui/aura/client/aura_constants.h" #include "ui/aura/window.h" #include "ui/aura/window_observer.h" -#include "ui/base/ui_base_features.h" #include "ui/views/widget/widget.h" #include "ui/views/widget/widget_delegate.h" @@ -48,9 +47,7 @@ }; bool IsInImmersive(aura::Window* window) { - aura::Window* toplevel = - features::IsUsingWindowService() ? window->GetRootWindow() : window; - return toplevel->GetProperty(ash::kImmersiveIsActive); + return window->GetProperty(ash::kImmersiveIsActive); } } // namespace @@ -107,10 +104,8 @@ // 2) ash::ShellTestApi().ToggleFullscreen() should have no effect on windows // which cannot be maximized. - aura::Window* toplevel = - features::IsUsingWindowService() ? window->GetRootWindow() : window; - toplevel->SetProperty(aura::client::kResizeBehaviorKey, - aura::client::kResizeBehaviorNone); + window->SetProperty(aura::client::kResizeBehaviorKey, + aura::client::kResizeBehaviorNone); ash::ShellTestApi().ToggleFullscreen(); EXPECT_TRUE(IsInitialShowState(widget));
diff --git a/chrome/browser/ui/ash/chrome_browser_main_extra_parts_ash.cc b/chrome/browser/ui/ash/chrome_browser_main_extra_parts_ash.cc index d85fcac..ca32cb3 100644 --- a/chrome/browser/ui/ash/chrome_browser_main_extra_parts_ash.cc +++ b/chrome/browser/ui/ash/chrome_browser_main_extra_parts_ash.cc
@@ -60,7 +60,6 @@ #include "services/network/public/cpp/shared_url_loader_factory.h" #include "services/service_manager/public/cpp/connector.h" #include "ui/base/ime/chromeos/input_method_manager.h" -#include "ui/base/ui_base_features.h" #if BUILDFLAG(ENABLE_WAYLAND_SERVER) #include "chrome/browser/exo_parts.h" @@ -197,12 +196,8 @@ detector); } - // TODO(mash): Port TabScrubber. This depends on where gesture recognition - // happens because TabScrubber uses 3-finger scrolls. https://crbug.com/796366 - if (!features::IsMultiProcessMash()) { - // Initialize TabScrubber after the Ash Shell has been initialized. - TabScrubber::GetInstance(); - } + // Initialize TabScrubber after the Ash Shell has been initialized. + TabScrubber::GetInstance(); if (base::FeatureList::IsEnabled(ash::features::kKioskNextShell)) { kiosk_next_shell_client_ = std::make_unique<KioskNextShellClient>();
diff --git a/chrome/browser/ui/ash/keyboard/DEPS b/chrome/browser/ui/ash/keyboard/DEPS index 9de64e94..b24cb41 100644 --- a/chrome/browser/ui/ash/keyboard/DEPS +++ b/chrome/browser/ui/ash/keyboard/DEPS
@@ -1,13 +1,10 @@ specific_include_rules = { - # Only for !features::IsUsingWindowService(). "chrome_keyboard_bounds_observer\.cc": [ "+ash/root_window_controller.h", ], - # For classic Ash mode. "chrome_keyboard_controller_client\.cc": [ "+ui/keyboard", ], - # This code is only used in classic Ash mode. "chrome_keyboard_ui.*": [ "+ash/shell.h", "+ui/keyboard",
diff --git a/chrome/browser/ui/ash/keyboard/chrome_keyboard_controller_client.cc b/chrome/browser/ui/ash/keyboard/chrome_keyboard_controller_client.cc index 3bf14a96..2ac63f5 100644 --- a/chrome/browser/ui/ash/keyboard/chrome_keyboard_controller_client.cc +++ b/chrome/browser/ui/ash/keyboard/chrome_keyboard_controller_client.cc
@@ -32,7 +32,6 @@ #include "ui/base/ime/ime_bridge.h" #include "ui/base/ime/input_method.h" #include "ui/base/ime/text_input_client.h" -#include "ui/base/ui_base_features.h" #include "ui/gfx/geometry/rect.h" #include "ui/wm/core/coordinate_conversion.h" @@ -116,8 +115,7 @@ if (session_manager::SessionManager::Get()) session_manager::SessionManager::Get()->RemoveObserver(this); pref_change_registrar_.RemoveAll(); - if (!::features::IsUsingWindowService() && - keyboard::KeyboardController::HasInstance()) { + if (keyboard::KeyboardController::HasInstance()) { // In classic Ash, keyboard::KeyboardController owns ChromeKeyboardUI which // accesses this class, so make sure that the UI has been destroyed. keyboard::KeyboardController::Get()->Shutdown(); @@ -246,11 +244,6 @@ } aura::Window* ChromeKeyboardControllerClient::GetKeyboardWindow() const { - if (::features::IsUsingWindowService()) { - content::WebContents* contents = - keyboard_contents_ ? keyboard_contents_->web_contents() : nullptr; - return contents ? contents->GetNativeView() : nullptr; - } return keyboard::KeyboardController::Get()->GetKeyboardWindow(); }
diff --git a/chrome/browser/ui/ash/keyboard/chrome_keyboard_ui.cc b/chrome/browser/ui/ash/keyboard/chrome_keyboard_ui.cc index d5fc1eb..e20f0a3 100644 --- a/chrome/browser/ui/ash/keyboard/chrome_keyboard_ui.cc +++ b/chrome/browser/ui/ash/keyboard/chrome_keyboard_ui.cc
@@ -21,7 +21,6 @@ #include "ui/aura/window.h" #include "ui/aura/window_tree_host.h" #include "ui/base/ime/ime_bridge.h" -#include "ui/base/ui_base_features.h" #include "ui/compositor/layer.h" #include "ui/compositor_extra/shadow.h" #include "ui/gfx/geometry/rect.h" @@ -35,7 +34,6 @@ ChromeKeyboardUI::ChromeKeyboardUI(content::BrowserContext* context) : browser_context_(context) { - DCHECK(!::features::IsUsingWindowService()); } ChromeKeyboardUI::~ChromeKeyboardUI() {
diff --git a/chrome/browser/ui/ash/keyboard/chrome_keyboard_ui_unittest.cc b/chrome/browser/ui/ash/keyboard/chrome_keyboard_ui_unittest.cc index c92b633..cea1003c 100644 --- a/chrome/browser/ui/ash/keyboard/chrome_keyboard_ui_unittest.cc +++ b/chrome/browser/ui/ash/keyboard/chrome_keyboard_ui_unittest.cc
@@ -13,7 +13,6 @@ #include "chrome/test/base/testing_profile.h" #include "content/public/browser/web_ui.h" #include "content/public/browser/web_ui_controller.h" -#include "ui/base/ui_base_features.h" #include "url/gurl.h" // NOTE: ChromeKeyboardUITest is not used with the Window Service. @@ -27,8 +26,6 @@ void SetUp() override { ChromeRenderViewHostTestHarness::SetUp(); - if (::features::IsUsingWindowService()) - return; chrome_keyboard_controller_client_ = ChromeKeyboardControllerClient::CreateForTest(); chrome_keyboard_ui_ = std::make_unique<ChromeKeyboardUI>(profile()); @@ -51,8 +48,6 @@ // Ensure ChromeKeyboardContentsDelegate is successfully constructed and has // a valid aura::Window after calling LoadKeyboardWindow(). TEST_F(ChromeKeyboardUITest, ChromeKeyboardContentsDelegate) { - if (::features::IsUsingWindowService()) - return; aura::Window* window = chrome_keyboard_ui_->LoadKeyboardWindow(base::DoNothing()); EXPECT_TRUE(window);
diff --git a/chrome/browser/ui/ash/keyboard/keyboard_controller_browsertest.cc b/chrome/browser/ui/ash/keyboard/keyboard_controller_browsertest.cc index fdb441f9..fd17cda6 100644 --- a/chrome/browser/ui/ash/keyboard/keyboard_controller_browsertest.cc +++ b/chrome/browser/ui/ash/keyboard/keyboard_controller_browsertest.cc
@@ -25,7 +25,6 @@ #include "ui/base/ime/dummy_text_input_client.h" #include "ui/base/ime/init/input_method_factory.h" #include "ui/base/ime/input_method.h" -#include "ui/base/ui_base_features.h" #include "ui/display/display.h" #include "ui/display/screen.h" #include "ui/events/test/event_generator.h" @@ -208,9 +207,6 @@ // TODO(stevenjb/shend): Investigate/fix. IN_PROC_BROWSER_TEST_F(KeyboardControllerWebContentTest, CanDragFloatingKeyboardWithMouse) { - if (::features::IsMultiProcessMash()) - return; - ChromeKeyboardControllerClient::Get()->SetContainerType( keyboard::ContainerType::kFloating, base::nullopt, base::DoNothing()); @@ -379,9 +375,6 @@ // whether this needs to be tested in a keyboard::KeyboardController unit test. IN_PROC_BROWSER_TEST_F(KeyboardControllerStateTest, StateResolvesAfterPreload) { - if (::features::IsMultiProcessMash()) - return; - auto* controller = keyboard::KeyboardController::Get(); EXPECT_EQ(controller->GetStateForTest(), keyboard::KeyboardUIState::kLoading); KeyboardLoadedWaiter().Wait(); @@ -390,9 +383,6 @@ IN_PROC_BROWSER_TEST_F(KeyboardControllerStateTest, OpenAndCloseAndOpenInternal) { - if (::features::IsMultiProcessMash()) - return; - auto* controller = keyboard::KeyboardController::Get(); controller->ShowKeyboard(false); // Need to wait the extension to be loaded. Hence LOADING_EXTENSION. @@ -410,9 +400,6 @@ // See crbug.com/755354. IN_PROC_BROWSER_TEST_F(KeyboardControllerStateTest, DisablingKeyboardGoesToInitialState) { - if (::features::IsMultiProcessMash()) - return; - auto* controller = keyboard::KeyboardController::Get(); EXPECT_EQ(controller->GetStateForTest(), keyboard::KeyboardUIState::kLoading);
diff --git a/chrome/browser/ui/ash/kiosk_next_shell_client_browsertest.cc b/chrome/browser/ui/ash/kiosk_next_shell_client_browsertest.cc index 4b91f7b..5f61dd9 100644 --- a/chrome/browser/ui/ash/kiosk_next_shell_client_browsertest.cc +++ b/chrome/browser/ui/ash/kiosk_next_shell_client_browsertest.cc
@@ -77,26 +77,6 @@ base::test::ScopedFeatureList feature_list_; }; -IN_PROC_BROWSER_TEST_F(KioskNextShellClientTest, PRE_KioskNextShellLaunch) { - LoginAndEnableKioskNextShellPref(); -} - -// Checks that the Kiosk Next Home window is launched on sign-in when the -// feature is enabled and its pref allows it. -IN_PROC_BROWSER_TEST_F(KioskNextShellClientTest, KioskNextShellLaunch) { - // Enable all component extensions. - extensions::ComponentLoader::EnableBackgroundExtensionsForTesting(); - - Login("username"); - - // Wait for the app to launch. - apps::AppWindowWaiter waiter( - extensions::AppWindowRegistry::Get(ProfileHelper::Get()->GetProfileByUser( - user_manager::UserManager::Get()->GetActiveUser())), - extension_misc::kKioskNextHomeAppId); - EXPECT_TRUE(waiter.WaitForShownWithTimeout(TestTimeouts::action_timeout())); -} - IN_PROC_BROWSER_TEST_F(KioskNextShellClientTest, PRE_BrowserNotLaunched) { LoginAndEnableKioskNextShellPref(); } @@ -134,30 +114,13 @@ EXPECT_FALSE(waiter.WaitForShownWithTimeout(TestTimeouts::action_timeout())); } -// Variant of KioskNextShellClientTest that disables Mash in order to test the -// Ash container of the Chrome app window. -// TODO(crbug.com/945704): Once we can identify the app window's container with -// SingleProcessMash enabled, remove this test class and add the container check -// to the KioskNextShellLaunch test. -class KioskNextShellClientMashDisabledTest : public KioskNextShellClientTest { - public: - KioskNextShellClientMashDisabledTest() : KioskNextShellClientTest() { - feature_list_.InitAndDisableFeature(features::kSingleProcessMash); - } - - private: - base::test::ScopedFeatureList feature_list_; -}; - -IN_PROC_BROWSER_TEST_F(KioskNextShellClientMashDisabledTest, - PRE_KioskNextShellLaunch) { +IN_PROC_BROWSER_TEST_F(KioskNextShellClientTest, PRE_KioskNextShellLaunch) { LoginAndEnableKioskNextShellPref(); } // Checks that the Kiosk Next Home window is launched on sign-in when the // feature is enabled and its pref allows it. -IN_PROC_BROWSER_TEST_F(KioskNextShellClientMashDisabledTest, - KioskNextShellLaunch) { +IN_PROC_BROWSER_TEST_F(KioskNextShellClientTest, KioskNextShellLaunch) { // Enable all component extensions. extensions::ComponentLoader::EnableBackgroundExtensionsForTesting();
diff --git a/chrome/browser/ui/ash/launcher/DEPS b/chrome/browser/ui/ash/launcher/DEPS index 865f493..232c1c9 100644 --- a/chrome/browser/ui/ash/launcher/DEPS +++ b/chrome/browser/ui/ash/launcher/DEPS
@@ -3,9 +3,11 @@ "app_window_launcher_controller\.cc": [ "+ash/shell.h", ], - # https://crbug.com/875111 "chrome_launcher_controller_unittest\.cc": [ + # https://crbug.com/875111 "+ash/multi_user/multi_user_window_manager_impl.h", + # https://crbug.com/826982 + "+chrome/services/app_service/app_service.h", ], "browser_shortcut_launcher_item_controller\.cc": [ "+ash/wm/desks/desks_util.h",
diff --git a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_unittest.cc b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_unittest.cc index e2644f1d..57bba6d 100644 --- a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_unittest.cc +++ b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_unittest.cc
@@ -27,6 +27,7 @@ #include "base/bind_helpers.h" #include "base/command_line.h" #include "base/compiler_specific.h" +#include "base/feature_list.h" #include "base/files/file_path.h" #include "base/json/json_string_value_serializer.h" #include "base/location.h" @@ -37,6 +38,8 @@ #include "base/strings/utf_string_conversions.h" #include "base/values.h" #include "build/build_config.h" +#include "chrome/browser/apps/app_service/app_service_proxy_impl.h" +#include "chrome/browser/apps/app_service/arc_apps.h" #include "chrome/browser/chromeos/arc/arc_util.h" #include "chrome/browser/chromeos/crostini/crostini_test_helper.h" #include "chrome/browser/chromeos/crostini/crostini_util.h" @@ -48,6 +51,7 @@ #include "chrome/browser/prefs/browser_prefs.h" #include "chrome/browser/ui/app_icon_loader.h" #include "chrome/browser/ui/app_list/app_list_syncable_service_factory.h" +#include "chrome/browser/ui/app_list/app_service_app_model_builder.h" #include "chrome/browser/ui/app_list/arc/arc_app_list_prefs.h" #include "chrome/browser/ui/app_list/arc/arc_app_test.h" #include "chrome/browser/ui/app_list/arc/arc_app_utils.h" @@ -77,9 +81,12 @@ #include "chrome/browser/ui/browser_tabstrip.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/common/chrome_constants.h" +#include "chrome/common/chrome_features.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/extensions/extension_constants.h" #include "chrome/common/pref_names.h" +#include "chrome/services/app_service/app_service.h" +#include "chrome/services/app_service/public/mojom/constants.mojom.h" #include "chrome/test/base/browser_with_test_window_test.h" #include "chrome/test/base/test_browser_window_aura.h" #include "chrome/test/base/testing_profile.h" @@ -113,6 +120,7 @@ #include "extensions/common/manifest_constants.h" #include "extensions/grit/extensions_browser_resources.h" #include "services/network/test/test_network_connection_tracker.h" +#include "services/service_manager/public/cpp/test/test_connector_factory.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/aura/client/window_parenting_client.h" #include "ui/aura/window.h" @@ -305,6 +313,15 @@ base::CommandLine::ForCurrentProcess(), base::FilePath(), false); extension_service_->Init(); + if (app_service_proxy_connector_) { + DCHECK(profile()); + app_service_proxy_impl_.reset(apps::AppServiceProxyImpl::CreateForTesting( + profile(), app_service_proxy_connector_)); + old_app_service_proxy_for_testing_ = + AppServiceAppModelBuilder::SetAppServiceProxyForTesting( + app_service_proxy_impl_.get()); + } + if (auto_start_arc_test_) arc_test_.SetUp(profile()); @@ -437,6 +454,11 @@ void TearDown() override { arc_test_.TearDown(); + if (app_service_proxy_impl_) { + AppServiceAppModelBuilder::SetAppServiceProxyForTesting( + old_app_service_proxy_for_testing_); + app_service_proxy_impl_.reset(nullptr); + } launcher_controller_ = nullptr; BrowserWithTestWindowTest::TearDown(); } @@ -905,6 +927,10 @@ app_list::AppListSyncableService* app_list_syncable_service_ = nullptr; + service_manager::Connector* app_service_proxy_connector_ = nullptr; + std::unique_ptr<apps::AppServiceProxyImpl> app_service_proxy_impl_; + apps::AppServiceProxy* old_app_service_proxy_for_testing_ = nullptr; + private: TestBrowserWindow* CreateTestBrowserWindowAura() { std::unique_ptr<aura::Window> window( @@ -923,7 +949,23 @@ class ChromeLauncherControllerWithArcTest : public ChromeLauncherControllerTest { protected: - ChromeLauncherControllerWithArcTest() { auto_start_arc_test_ = true; } + ChromeLauncherControllerWithArcTest() { + auto_start_arc_test_ = true; + if (!base::FeatureList::IsEnabled(features::kAppServiceAsh)) { + return; + } + // We set some state in the ChromeLauncherControllerTest superclass to + // affect what ChromeLauncherControllerTest::SetUp does, making it call + // AppServiceAppModelBuilder::SetAppServiceProxyForTesting (ASAMB::SASPFT). + // We can only call SASPFT after the TestingProfile is created (which + // happens in the superclass' SetUp) but before the ASAMB is constructed + // (which also happens in the superclass' SetUp). + app_service_ = std::make_unique<apps::AppService>( + test_connector_factory_.RegisterInstance(apps::mojom::kServiceName)); + app_service_proxy_connector_ = + test_connector_factory_.GetDefaultConnector(); + } + ~ChromeLauncherControllerWithArcTest() override {} void SetUp() override { @@ -931,9 +973,24 @@ ArcAppIcon::DisableSafeDecodingForTesting(); ChromeLauncherControllerTest::SetUp(); + if (app_service_proxy_connector_) { + arc_apps_.reset(apps::ArcApps::CreateForTesting( + profile(), app_service_proxy_impl_.get())); + } + } + + void TearDown() override { + if (app_service_proxy_connector_) { + arc_apps_.reset(nullptr); + } + ChromeLauncherControllerTest::TearDown(); } private: + service_manager::TestConnectorFactory test_connector_factory_; + std::unique_ptr<service_manager::Service> app_service_; + std::unique_ptr<apps::ArcApps> arc_apps_; + DISALLOW_COPY_AND_ASSIGN(ChromeLauncherControllerWithArcTest); }; @@ -2188,6 +2245,8 @@ SendListOfArcApps(); extension_service_->AddExtension(extension1_.get()); extension_service_->AddExtension(extension2_.get()); + // Allow async callbacks to run. + base::RunLoop().RunUntilIdle(); EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id())); EXPECT_FALSE(launcher_controller_->IsAppPinned(arc_app_id)); @@ -2204,9 +2263,16 @@ EXPECT_EQ("Chrome, App1, Fake App 0, App2", GetPinnedAppStatus()); UninstallArcApps(); + // Allow async callbacks to run. + base::RunLoop().RunUntilIdle(); + EXPECT_FALSE(launcher_controller_->IsAppPinned(arc_app_id)); EXPECT_EQ("Chrome, App1, App2", GetPinnedAppStatus()); + SendListOfArcApps(); + // Allow async callbacks to run. + base::RunLoop().RunUntilIdle(); + EXPECT_FALSE(launcher_controller_->IsAppPinned(arc_app_id)); EXPECT_EQ("Chrome, App1, App2", GetPinnedAppStatus()); @@ -2217,7 +2283,11 @@ EXPECT_EQ("Chrome, App1, App2", GetPinnedAppStatus()); EnablePlayStore(true); EXPECT_EQ("Chrome, App1, App2", GetPinnedAppStatus()); + SendListOfArcApps(); + // Allow async callbacks to run. + base::RunLoop().RunUntilIdle(); + EXPECT_EQ("Chrome, App1, App2, Fake App 0", GetPinnedAppStatus()); }
diff --git a/chrome/browser/ui/ash/multi_user/multi_profile_support_unittest.cc b/chrome/browser/ui/ash/multi_user/multi_profile_support_unittest.cc index 3590419..d14fcba7 100644 --- a/chrome/browser/ui/ash/multi_user/multi_profile_support_unittest.cc +++ b/chrome/browser/ui/ash/multi_user/multi_profile_support_unittest.cc
@@ -63,7 +63,6 @@ #include "ui/aura/test/env_test_helper.h" #include "ui/aura/window.h" #include "ui/aura/window_event_dispatcher.h" -#include "ui/base/ui_base_features.h" #include "ui/base/ui_base_types.h" #include "ui/display/manager/display_manager.h" #include "ui/display/test/display_manager_test_api.h" @@ -1443,12 +1442,7 @@ SwitchActiveUser(user1); - // This ternary doesn't make a lot of sense because the windows in this - // AshTest aren't created via the window service, but it's necessary to mirror - // the code in MultiProfileSupport, where the content window's - // root window is the Ash host window. - aura::Window* property_window = - features::IsUsingWindowService() ? window(0)->GetRootWindow() : window(0); + aura::Window* property_window = window(0); // Window #0 has no kAvatarIconKey property before teleporting. EXPECT_FALSE(property_window->GetProperty(aura::client::kAvatarIconKey));
diff --git a/chrome/browser/ui/ash/overview_window_drag_interactive_uitest.cc b/chrome/browser/ui/ash/overview_window_drag_interactive_uitest.cc index 77293b0..454d7432 100644 --- a/chrome/browser/ui/ash/overview_window_drag_interactive_uitest.cc +++ b/chrome/browser/ui/ash/overview_window_drag_interactive_uitest.cc
@@ -19,7 +19,6 @@ #include "ui/aura/window.h" #include "ui/aura/window_observer.h" #include "ui/base/test/ui_controls.h" -#include "ui/base/ui_base_features.h" #include "ui/display/display.h" #include "ui/display/screen.h" #include "ui/gfx/animation/tween.h" @@ -197,13 +196,8 @@ generator.Wait(); Browser* active = chrome::FindLastActive(); - LeftSnapWaiter waiter( - features::IsUsingWindowService() - ? active->window()->GetNativeWindow()->GetRootWindow() - : active->window()->GetNativeWindow()); - // Wait for the window to be snapped. - waiter.Wait(); + LeftSnapWaiter(active->window()->GetNativeWindow()).Wait(); } INSTANTIATE_TEST_SUITE_P(,
diff --git a/chrome/browser/ui/ash/tab_scrubber_browsertest.cc b/chrome/browser/ui/ash/tab_scrubber_browsertest.cc index f5c0d64e..b88b99d 100644 --- a/chrome/browser/ui/ash/tab_scrubber_browsertest.cc +++ b/chrome/browser/ui/ash/tab_scrubber_browsertest.cc
@@ -26,7 +26,6 @@ #include "content/public/common/url_constants.h" #include "content/public/test/test_utils.h" #include "ui/aura/window.h" -#include "ui/base/ui_base_features.h" #include "ui/events/event_utils.h" #include "ui/events/test/event_generator.h" @@ -287,8 +286,7 @@ Browser* browser) { aura::Window* window = browser->window()->GetNativeWindow(); aura::Window* root = window->GetRootWindow(); - return std::make_unique<ui::test::EventGenerator>( - features::IsUsingWindowService() ? nullptr : root, window); + return std::make_unique<ui::test::EventGenerator>(root, window); }
diff --git a/chrome/browser/ui/aura/accessibility/automation_manager_aura.cc b/chrome/browser/ui/aura/accessibility/automation_manager_aura.cc index fff0134..7663453 100644 --- a/chrome/browser/ui/aura/accessibility/automation_manager_aura.cc +++ b/chrome/browser/ui/aura/accessibility/automation_manager_aura.cc
@@ -30,7 +30,6 @@ #include "ash/public/cpp/shell_window_ids.h" #include "ash/shell.h" #include "ash/wm/window_util.h" -#include "ui/base/ui_base_features.h" #endif #if DCHECK_IS_ON() @@ -61,14 +60,11 @@ cache_->SetDelegate(this); #if defined(OS_CHROMEOS) - // TODO(crbug.com/756054): Support MultiProcessMash. - if (!features::IsMultiProcessMash()) { - aura::Window* active_window = ash::wm::GetActiveWindow(); - if (active_window) { - views::AXAuraObjWrapper* focus = cache_->GetOrCreate(active_window); - if (focus) - SendEvent(focus, ax::mojom::Event::kChildrenChanged); - } + aura::Window* active_window = ash::wm::GetActiveWindow(); + if (active_window) { + views::AXAuraObjWrapper* focus = cache_->GetOrCreate(active_window); + if (focus) + SendEvent(focus, ax::mojom::Event::kChildrenChanged); } #endif }
diff --git a/chrome/browser/ui/browser_navigator_browsertest_chromeos.cc b/chrome/browser/ui/browser_navigator_browsertest_chromeos.cc index 4b0a321..a83a05c 100644 --- a/chrome/browser/ui/browser_navigator_browsertest_chromeos.cc +++ b/chrome/browser/ui/browser_navigator_browsertest_chromeos.cc
@@ -28,7 +28,6 @@ #include "content/public/browser/notification_types.h" #include "content/public/browser/web_contents.h" #include "ui/aura/window.h" -#include "ui/base/ui_base_features.h" namespace { @@ -72,8 +71,6 @@ NavigationBlockedInLockedFullscreen) { // Set locked fullscreen state. aura::Window* window = browser()->window()->GetNativeWindow(); - if (features::IsUsingWindowService()) - window = window->GetRootWindow(); window->SetProperty(ash::kWindowPinTypeKey, ash::WindowPinType::kTrustedPinned);
diff --git a/chrome/browser/ui/settings_window_manager_chromeos.cc b/chrome/browser/ui/settings_window_manager_chromeos.cc index 6924138..fcfeca8 100644 --- a/chrome/browser/ui/settings_window_manager_chromeos.cc +++ b/chrome/browser/ui/settings_window_manager_chromeos.cc
@@ -22,7 +22,6 @@ #include "chromeos/constants/chromeos_features.h" #include "content/public/browser/web_contents.h" #include "ui/aura/client/aura_constants.h" -#include "ui/base/ui_base_features.h" #include "url/gurl.h" namespace chrome { @@ -101,11 +100,8 @@ auto* window = browser->window()->GetNativeWindow(); window->SetProperty(kOverrideWindowIconResourceIdKey, IDR_SETTINGS_LOGO_192); - // For Mash, this is set by BrowserFrameMash. - if (!features::IsUsingWindowService()) { - window->SetProperty(aura::client::kAppType, - static_cast<int>(ash::AppType::CHROME_APP)); - } + window->SetProperty(aura::client::kAppType, + static_cast<int>(ash::AppType::CHROME_APP)); for (SettingsWindowManagerObserver& observer : observers_) observer.OnNewSettingsWindow(browser);
diff --git a/chrome/browser/ui/test/test_browser_dialog.cc b/chrome/browser/ui/test/test_browser_dialog.cc index 3bff53d3..6a6cb50 100644 --- a/chrome/browser/ui/test/test_browser_dialog.cc +++ b/chrome/browser/ui/test/test_browser_dialog.cc
@@ -14,7 +14,6 @@ #if defined(OS_CHROMEOS) #include "ash/shell.h" // mash-ok -#include "ui/base/ui_base_features.h" #endif #if defined(OS_MACOSX) @@ -146,15 +145,8 @@ void TestBrowserDialog::UpdateWidgets() { widgets_.clear(); #if defined(OS_CHROMEOS) - // Under mash, GetAllWidgets() uses MusClient to get the list of root windows. - // Otherwise, GetAllWidgets() relies on AuraTestHelper to get the root window, - // but that is not available in browser_tests, so use ash::Shell directly. - if (features::IsUsingWindowService()) { - widgets_ = views::test::WidgetTest::GetAllWidgets(); - } else { - for (aura::Window* root_window : ash::Shell::GetAllRootWindows()) - views::Widget::GetAllChildWidgets(root_window, &widgets_); - } + for (aura::Window* root_window : ash::Shell::GetAllRootWindows()) + views::Widget::GetAllChildWidgets(root_window, &widgets_); #elif defined(TOOLKIT_VIEWS) widgets_ = views::test::WidgetTest::GetAllWidgets(); #else
diff --git a/chrome/browser/ui/views/chrome_views_delegate_chromeos.cc b/chrome/browser/ui/views/chrome_views_delegate_chromeos.cc index f9ffa17..5e70b80 100644 --- a/chrome/browser/ui/views/chrome_views_delegate_chromeos.cc +++ b/chrome/browser/ui/views/chrome_views_delegate_chromeos.cc
@@ -9,7 +9,6 @@ #include "base/bind.h" #include "base/message_loop/message_loop.h" #include "base/threading/thread_task_runner_handle.h" -#include "ui/base/ui_base_features.h" #include "ui/display/display.h" #include "ui/display/screen.h" @@ -28,10 +27,6 @@ const ui::Accelerator& accelerator) { DCHECK(base::MessageLoopCurrentForUI::IsSet()); - // Early return because mash chrome does not have access to ash::Shell - if (features::IsMultiProcessMash()) - return views::ViewsDelegate::ProcessMenuAcceleratorResult::LEAVE_MENU_OPEN; - if (ash::AcceleratorController::Get()->OnMenuAccelerator(accelerator)) { base::ThreadTaskRunnerHandle::Get()->PostTask( FROM_HERE, base::BindOnce(ProcessAcceleratorNow, accelerator));
diff --git a/chrome/browser/ui/views/content_test_utils.cc b/chrome/browser/ui/views/content_test_utils.cc index ac5d7b9..ca0c829 100644 --- a/chrome/browser/ui/views/content_test_utils.cc +++ b/chrome/browser/ui/views/content_test_utils.cc
@@ -8,7 +8,6 @@ #include "base/threading/thread_task_runner_handle.h" #include "content/public/test/browser_test_utils.h" #include "testing/gtest/include/gtest/gtest.h" -#include "ui/base/ui_base_features.h" #include "ui/events/test/event_generator.h" #if defined(USE_AURA) @@ -42,9 +41,6 @@ #if defined(USE_AURA) event_window = event_window->GetRootWindow(); #endif - if (features::IsUsingWindowService()) - event_window = nullptr; - ui::test::EventGenerator generator(event_window); generator.PressKey(ui::VKEY_A, ui::EF_NONE);
diff --git a/chrome/browser/ui/views/media_router/presentation_receiver_window_view.cc b/chrome/browser/ui/views/media_router/presentation_receiver_window_view.cc index 33aaea7..2a617c6 100644 --- a/chrome/browser/ui/views/media_router/presentation_receiver_window_view.cc +++ b/chrome/browser/ui/views/media_router/presentation_receiver_window_view.cc
@@ -48,7 +48,6 @@ #include "ui/aura/client/aura_constants.h" #include "ui/aura/window.h" #include "ui/aura/window_observer.h" -#include "ui/base/ui_base_features.h" #include "ui/gfx/native_widget_types.h" #endif @@ -63,8 +62,6 @@ FullscreenWindowObserver(aura::Window* observed_window, base::RepeatingClosure on_fullscreen_change) : on_fullscreen_change_(on_fullscreen_change) { - if (features::IsUsingWindowService()) - observed_window = observed_window->GetRootWindow(); observed_window_.Add(observed_window); }
diff --git a/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view_browsertest.cc b/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view_browsertest.cc index c5b06085..7f631ea 100644 --- a/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view_browsertest.cc +++ b/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view_browsertest.cc
@@ -26,7 +26,6 @@ #include "components/omnibox/browser/omnibox_field_trial.h" #include "components/omnibox/browser/omnibox_popup_model.h" #include "content/public/test/test_utils.h" -#include "ui/base/ui_base_features.h" #include "ui/compositor/layer_animator.h" #include "ui/events/test/event_generator.h" #include "ui/views/accessibility/ax_event_manager.h" @@ -290,10 +289,6 @@ #if defined(USE_AURA) event_window = event_window->GetRootWindow(); #endif -#if defined(OS_CHROMEOS) - if (features::IsUsingWindowService()) - event_window = nullptr; -#endif ui::test::EventGenerator generator(event_window); OmniboxResultView* result = GetResultViewAt(0);
diff --git a/chrome/browser/ui/views/omnibox/omnibox_view_views_browsertest.cc b/chrome/browser/ui/views/omnibox/omnibox_view_views_browsertest.cc index 033b5ed..b528600 100644 --- a/chrome/browser/ui/views/omnibox/omnibox_view_views_browsertest.cc +++ b/chrome/browser/ui/views/omnibox/omnibox_view_views_browsertest.cc
@@ -34,7 +34,6 @@ #include "ui/base/ime/text_edit_commands.h" #include "ui/base/ime/text_input_client.h" #include "ui/base/test/ui_controls.h" -#include "ui/base/ui_base_features.h" #include "ui/base/ui_base_switches.h" #include "ui/events/event_processor.h" #include "ui/events/event_utils.h" @@ -97,10 +96,6 @@ void Tap(const gfx::Point& press_location, const gfx::Point& release_location) { gfx::NativeWindow window = GetRootWindow(); -#if defined(OS_CHROMEOS) - if (features::IsUsingWindowService()) - window = nullptr; -#endif ui::test::EventGenerator generator(window); if (press_location == release_location) { generator.GestureTapAt(press_location);
diff --git a/chrome/browser/ui/views/omnibox/omnibox_view_views_unittest.cc b/chrome/browser/ui/views/omnibox/omnibox_view_views_unittest.cc index 1f3f0b9a..a9b788a 100644 --- a/chrome/browser/ui/views/omnibox/omnibox_view_views_unittest.cc +++ b/chrome/browser/ui/views/omnibox/omnibox_view_views_unittest.cc
@@ -34,7 +34,6 @@ #include "ui/base/clipboard/scoped_clipboard_writer.h" #include "ui/base/ime/input_method.h" #include "ui/base/ime/text_edit_commands.h" -#include "ui/base/ui_base_features.h" #include "ui/events/event_utils.h" #include "ui/events/keycodes/dom/dom_code.h" #include "ui/gfx/geometry/rect.h" @@ -698,13 +697,6 @@ const GURL kFullUrl = GURL("https://www.example.com/"); void SetUp() override { -#if defined(OS_CHROMEOS) - // This is necessary in Mash because the touch handles which get created - // during GestureTaps require a MusClient. - if (features::IsUsingWindowService()) - set_native_widget_type(NativeWidgetType::kDesktop); -#endif - OmniboxViewViewsTest::SetUp(); // Advance 5 seconds from epoch so the time is not considered null.
diff --git a/chrome/browser/ui/views/omnibox/rounded_omnibox_results_frame.cc b/chrome/browser/ui/views/omnibox/rounded_omnibox_results_frame.cc index 5fecfa9..d351da7c 100644 --- a/chrome/browser/ui/views/omnibox/rounded_omnibox_results_frame.cc +++ b/chrome/browser/ui/views/omnibox/rounded_omnibox_results_frame.cc
@@ -17,7 +17,6 @@ #if defined(USE_AURA) #include "ui/aura/window.h" #include "ui/aura/window_targeter.h" -#include "ui/base/ui_base_features.h" #endif #if defined(OS_WIN) @@ -234,13 +233,7 @@ // portion of the Widget to pass through to the omnibox beneath it. auto results_targeter = std::make_unique<aura::WindowTargeter>(); results_targeter->SetInsets(GetInsets() + GetContentInsets()); - aura::Window* window = GetWidget()->GetNativeWindow(); - if (features::IsUsingWindowService()) { - // The WindowService ends up creating an additional window (by way of - // DesktopNativeWidgetAura). The targeter needs to be installed on it. - window = window->GetRootWindow(); - } - window->SetEventTargeter(std::move(results_targeter)); + GetWidget()->GetNativeWindow()->SetEventTargeter(std::move(results_targeter)); #endif // USE_AURA }
diff --git a/chrome/browser/ui/views/tabs/tab_drag_controller.cc b/chrome/browser/ui/views/tabs/tab_drag_controller.cc index 69f270b..82a6874 100644 --- a/chrome/browser/ui/views/tabs/tab_drag_controller.cc +++ b/chrome/browser/ui/views/tabs/tab_drag_controller.cc
@@ -51,7 +51,6 @@ #include "ash/public/cpp/window_properties.h" // nogncheck #include "ash/public/cpp/window_state_type.h" // nogncheck #include "chrome/browser/ui/ash/tablet_mode_client.h" -#include "ui/base/ui_base_features.h" #include "ui/wm/core/coordinate_conversion.h" #endif @@ -88,15 +87,8 @@ #if defined(OS_CHROMEOS) // Returns the aura::Window which stores the window properties for tab-dragging. -// It should return the root window when WindowService is used, since it is -// corresponded with a widget in Ash. aura::Window* GetWindowForTabDraggingProperties(const TabDragContext* context) { - if (!context) - return nullptr; - aura::Window* window = context->AsView()->GetWidget()->GetNativeWindow(); - if (features::IsUsingWindowService()) - return window->GetRootWindow(); - return window; + return context ? context->AsView()->GetWidget()->GetNativeWindow() : nullptr; } // Returns true if |context| browser window is snapped. @@ -849,13 +841,6 @@ // Only Aura windows are gesture consumers. gfx::NativeView attached_native_view = GetAttachedBrowserWidget()->GetNativeView(); -#if defined(OS_CHROMEOS) - // When using WindowService, the touch events for the window move have - // happened on the root window, so the transfer should happen from the root of - // the currently attached window to the target. - if (features::IsUsingWindowService()) - attached_native_view = attached_native_view->GetRootWindow(); -#endif GetAttachedBrowserWidget()->GetGestureRecognizer()->TransferEventsTo( attached_native_view, target_context->AsView()->GetWidget()->GetNativeView(), @@ -1383,16 +1368,6 @@ attached_context_->AsView()->GetWidget()->ReleaseCapture(); attached_context_->OwnDragController(this); } -#if defined(OS_CHROMEOS) - // When the window service is used, there's some chance of having gesture - // events in the attached (moving) widget during the window move loop. Without - // setting the mouse handler, such gestures might arrive to a wrong view. See - // https://crbug.com/943316. - if (features::IsUsingWindowService()) { - attached_context_->AsView()->GetWidget()->GetRootView()->SetMouseHandler( - attached_context_->AsView()); - } -#endif const views::Widget::MoveLoopSource move_loop_source = event_source_ == EVENT_SOURCE_MOUSE ? views::Widget::MOVE_LOOP_SOURCE_MOUSE : @@ -2024,13 +1999,8 @@ if (exclude_dragged_view) { gfx::NativeWindow dragged_window = attached_context_->AsView()->GetWidget()->GetNativeWindow(); - if (dragged_window) { -#if defined(OS_CHROMEOS) - if (features::IsUsingWindowService()) - dragged_window = dragged_window->GetRootWindow(); -#endif + if (dragged_window) exclude.insert(dragged_window); - } } #if defined(OS_LINUX) && !defined(OS_CHROMEOS) // Exclude windows which are pending deletion via Browser::TabStripEmpty().
diff --git a/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc b/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc index f62b556..f05ba587 100644 --- a/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc +++ b/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc
@@ -83,7 +83,6 @@ #include "ui/aura/client/cursor_client.h" #include "ui/aura/client/screen_position_client.h" #include "ui/aura/window_event_dispatcher.h" -#include "ui/base/ui_base_features.h" #include "ui/display/manager/display_manager.h" #include "ui/events/base_event_utils.h" #include "ui/events/gesture_detection/gesture_configuration.h" @@ -116,18 +115,8 @@ }; #if defined(OS_CHROMEOS) -// Returns the window which stores window properties for this test. In mash, the -// properties are stored in the root window of the browser window. -aura::Window* GetWindowForProperties(aura::Window* window) { - if (features::IsUsingWindowService()) - return window->GetRootWindow(); - return window; -} - aura::Window* GetWindowForTabStrip(TabStrip* tab_strip) { - return tab_strip - ? GetWindowForProperties(tab_strip->GetWidget()->GetNativeWindow()) - : nullptr; + return tab_strip ? tab_strip->GetWidget()->GetNativeWindow() : nullptr; } #endif @@ -281,11 +270,8 @@ bool GetIsDragged(Browser* browser) { #if defined(OS_CHROMEOS) - if (!features::IsUsingWindowService()) { - return ash::wm::GetWindowState(browser->window()->GetNativeWindow()) - ->is_dragged(); - } - // TODO(mukai): support for Mash. + return ash::wm::GetWindowState(browser->window()->GetNativeWindow()) + ->is_dragged(); #endif return false; } @@ -830,14 +816,10 @@ #if defined(OS_CHROMEOS) bool IsWindowPositionManaged(aura::Window* window) { - return test::GetWindowForProperties(window)->GetProperty( - ash::kWindowPositionManagedTypeKey); + return window->GetProperty(ash::kWindowPositionManagedTypeKey); } bool HasUserChangedWindowPositionOrSize(aura::Window* window) { - if (!features::IsUsingWindowService()) - return ash::wm::GetWindowState(window)->bounds_changed_by_user(); - // TODO(mukai): support Mash. - return false; + return ash::wm::GetWindowState(window)->bounds_changed_by_user(); } #else bool IsWindowPositionManaged(gfx::NativeWindow window) { @@ -2007,8 +1989,8 @@ EXPECT_EQ(3u, test->browser_list->size()); // Get this new created window and set it to non-attachable. Browser* new_browser = test->browser_list->get(2); - test::GetWindowForProperties(new_browser->window()->GetNativeWindow()) - ->SetProperty(ash::kCanAttachToAnotherWindowKey, false); + new_browser->window()->GetNativeWindow()->SetProperty( + ash::kCanAttachToAnotherWindowKey, false); // Now drag to target_tab_strip. ASSERT_TRUE(
diff --git a/chrome/browser/ui/webui/chromeos/login/core_oobe_handler.cc b/chrome/browser/ui/webui/chromeos/login/core_oobe_handler.cc index 1cb4180b..e4983b92 100644 --- a/chrome/browser/ui/webui/chromeos/login/core_oobe_handler.cc +++ b/chrome/browser/ui/webui/chromeos/login/core_oobe_handler.cc
@@ -56,7 +56,6 @@ #include "services/service_manager/public/cpp/connector.h" #include "ui/accessibility/accessibility_switches.h" #include "ui/aura/window_tree_host.h" -#include "ui/base/ui_base_features.h" #include "ui/display/screen.h" #include "ui/events/event_sink.h" #include "ui/gfx/geometry/size.h" @@ -482,18 +481,11 @@ "enableExperimentalA11yFeatures", base::CommandLine::ForCurrentProcess()->HasSwitch( ::switches::kEnableExperimentalAccessibilityFeatures)); - if (!features::IsMultiProcessMash()) { - DCHECK(MagnificationManager::Get()); - a11y_info.SetBoolean("screenMagnifierEnabled", - MagnificationManager::Get()->IsMagnifierEnabled()); - a11y_info.SetBoolean( - "dockedMagnifierEnabled", - MagnificationManager::Get()->IsDockedMagnifierEnabled()); - } else { - // TODO: get MagnificationManager working with mash. - // https://crbug.com/817157 - NOTIMPLEMENTED_LOG_ONCE(); - } + DCHECK(MagnificationManager::Get()); + a11y_info.SetBoolean("screenMagnifierEnabled", + MagnificationManager::Get()->IsMagnifierEnabled()); + a11y_info.SetBoolean("dockedMagnifierEnabled", + MagnificationManager::Get()->IsDockedMagnifierEnabled()); a11y_info.SetBoolean("virtualKeyboardEnabled", AccessibilityManager::Get()->IsVirtualKeyboardEnabled()); CallJS("cr.ui.Oobe.refreshA11yInfo", a11y_info); @@ -555,13 +547,9 @@ } void CoreOobeHandler::UpdateKeyboardState() { - // TODO(crbug.com/646565): Support virtual keyboard under MASH. There is no - // KeyboardController in the browser process under MASH. - if (!features::IsUsingWindowService()) { - const bool is_keyboard_shown = - ChromeKeyboardControllerClient::Get()->is_keyboard_visible(); - SetVirtualKeyboardShown(is_keyboard_shown); - } + const bool is_keyboard_shown = + ChromeKeyboardControllerClient::Get()->is_keyboard_visible(); + SetVirtualKeyboardShown(is_keyboard_shown); } void CoreOobeHandler::OnTabletModeToggled(bool enabled) {
diff --git a/chrome/browser/ui/webui/chromeos/system_web_dialog_browsertest.cc b/chrome/browser/ui/webui/chromeos/system_web_dialog_browsertest.cc index f5205f4..b3af756 100644 --- a/chrome/browser/ui/webui/chromeos/system_web_dialog_browsertest.cc +++ b/chrome/browser/ui/webui/chromeos/system_web_dialog_browsertest.cc
@@ -23,7 +23,6 @@ #include "content/public/common/web_preferences.h" #include "services/service_manager/public/cpp/connector.h" #include "ui/aura/client/aura_constants.h" -#include "ui/base/ui_base_features.h" #include "url/gurl.h" namespace chromeos { @@ -82,9 +81,6 @@ dialog->ShowSystemDialog(); EXPECT_FALSE(ash::ShellTestApi().IsSystemModalWindowOpen()); aura::Window* window_to_test = dialog->dialog_window(); - // In Mash, the AlwaysOnTop property will be set on the parent. - if (::features::IsUsingWindowService()) - window_to_test = window_to_test->parent(); EXPECT_TRUE(window_to_test->GetProperty(aura::client::kAlwaysOnTopKey)); }
diff --git a/chrome/browser/ui/webui/settings/settings_ui.cc b/chrome/browser/ui/webui/settings/settings_ui.cc index 8e5a417..fb274159b 100644 --- a/chrome/browser/ui/webui/settings/settings_ui.cc +++ b/chrome/browser/ui/webui/settings/settings_ui.cc
@@ -508,14 +508,9 @@ arc::IsArcAllowedForProfile(profile)); html_source->AddBoolean("havePlayStoreApp", arc::IsPlayStoreAvailable()); - // TODO(mash): Support Chrome power settings in Mash. https://crbug.com/644348 - bool enable_power_settings = !::features::IsMultiProcessMash(); - html_source->AddBoolean("enablePowerSettings", enable_power_settings); - if (enable_power_settings) { - web_ui->AddMessageHandler( - std::make_unique<chromeos::settings::PowerHandler>( - profile->GetPrefs())); - } + html_source->AddBoolean("enablePowerSettings", true); + web_ui->AddMessageHandler( + std::make_unique<chromeos::settings::PowerHandler>(profile->GetPrefs())); html_source->AddBoolean( "showApps", base::FeatureList::IsEnabled(features::kAppManagement));
diff --git a/chrome/browser/ui/webui/version_handler_chromeos.cc b/chrome/browser/ui/webui/version_handler_chromeos.cc index 501e27d..0791701 100644 --- a/chrome/browser/ui/webui/version_handler_chromeos.cc +++ b/chrome/browser/ui/webui/version_handler_chromeos.cc
@@ -9,7 +9,6 @@ #include "chrome/common/channel_info.h" #include "components/version_info/channel.h" #include "content/public/browser/web_ui.h" -#include "ui/base/ui_base_features.h" VersionHandlerChromeOS::VersionHandlerChromeOS() : weak_factory_(this) {} @@ -40,15 +39,7 @@ } void VersionHandlerChromeOS::OnVersion(const std::string& version) { - std::string os_version = version; - // Put a string in about:version so it's easy to copy/paste into bug reports, - // similar to the OS label on the login/lock screen in canary and dev. - // String does not need to be localized since it is a feature name. - if (chrome::GetChannel() <= version_info::Channel::DEV && - ::features::IsSingleProcessMash()) { - os_version += " SingleProcessMash"; - } - base::Value arg(os_version); + base::Value arg(version); web_ui()->CallJavascriptFunctionUnsafe("returnOsVersion", arg); }
diff --git a/chrome/common/chrome_switches.cc b/chrome/common/chrome_switches.cc index a926a5c..ed23bc4 100644 --- a/chrome/common/chrome_switches.cc +++ b/chrome/common/chrome_switches.cc
@@ -402,6 +402,17 @@ // messages. Useful when running against a non-prod management server. const char kMonitoringDestinationID[] = "monitoring-destination-id"; +// Requests a native messaging connection be established between the native +// messaging host named by this switch and the extension with ID specified by +// kNativeMessagingConnectExtension. +const char kNativeMessagingConnectHost[] = "native-messaging-connect-host"; + +// Requests a native messaging connection be established between the extension +// with ID specified by this switch and the native messaging host named by the +// kNativeMessagingConnectHost switch. +const char kNativeMessagingConnectExtension[] = + "native-messaging-connect-extension"; + // Disables the default browser check. Useful for UI/browser tests where we // want to avoid having the default browser info-bar displayed. const char kNoDefaultBrowserCheck[] = "no-default-browser-check";
diff --git a/chrome/common/chrome_switches.h b/chrome/common/chrome_switches.h index 99b23b7..a4a52df 100644 --- a/chrome/common/chrome_switches.h +++ b/chrome/common/chrome_switches.h
@@ -125,6 +125,8 @@ extern const char kMakeDefaultBrowser[]; extern const char kMediaCacheSize[]; extern const char kMonitoringDestinationID[]; +extern const char kNativeMessagingConnectHost[]; +extern const char kNativeMessagingConnectExtension[]; extern const char kNewNetErrorPageUI[]; extern const char kNoDefaultBrowserCheck[]; extern const char kNoExperiments[];
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index d4ccef0..4477ee4 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -780,7 +780,6 @@ "../browser/browsing_data/counters/sync_aware_counter_browsertest.cc", "../browser/browsing_data/navigation_entry_remover_browsertest.cc", "../browser/chrome_content_browser_client_browsertest.cc", - "../browser/chrome_content_browser_client_browsertest_chromeos.cc", "../browser/chrome_do_not_track_browsertest.cc", "../browser/chrome_find_request_manager_browsertest.cc", "../browser/chrome_main_browsertest.cc", @@ -2557,13 +2556,6 @@ "//build/android/pylib/", "//tools/swarming_client/", ] - - if (enable_mus) { - deps += [ "//chrome:chrome_test" ] - data_deps = [ - "//chrome:chrome_test", - ] - } } group("telemetry_perf_tests") { @@ -6120,13 +6112,6 @@ "//testing/xvfb.py", "//testing/scripts/run_telemetry_as_googletest.py", ] - - if (enable_mus) { - deps += [ "//chrome:chrome_test" ] - data_deps = [ - "//chrome:chrome_test", - ] - } } group("telemetry_gpu_unittests_run") {
diff --git a/chrome/test/data/native_messaging/native_hosts/echo.py b/chrome/test/data/native_messaging/native_hosts/echo.py index a611051..5e36ea6 100755 --- a/chrome/test/data/native_messaging/native_hosts/echo.py +++ b/chrome/test/data/native_messaging/native_hosts/echo.py
@@ -6,6 +6,9 @@ # A simple native client in python. # All this client does is echo the text it receives back at the extension. +import argparse +import base64 +import json import os import platform import sys @@ -20,22 +23,24 @@ except IOError: return False + +def ParseArgs(): + parser = argparse.ArgumentParser() + parser.add_argument('--parent-window', type=int) + parser.add_argument('--reconnect-command') + parser.add_argument('origin') + return parser.parse_args() + def Main(): message_number = 0 - parent_window = None + args = ParseArgs() + caller_url = args.origin - if len(sys.argv) < 2: - sys.stderr.write("URL of the calling application is not specified.\n") + if sys.argv[1] != args.origin: + sys.stderr.write( + "URL of the calling application is not specified as the first arg.\n") return 1 - caller_url = sys.argv[1] - - # TODO(sergeyu): Use argparse module to parse the arguments (not available in - # Python 2.6). - for arg in sys.argv[2:]: - if arg.startswith('--'): - if arg.startswith('--parent-window='): - parent_window = long(arg[len('--parent-window='):]) # Verify that the process was started in the correct directory. cwd = os.getcwd() @@ -45,12 +50,15 @@ return 1 # Verify that --parent-window parameter is correct. - if platform.system() == 'Windows' and parent_window: + if platform.system() == 'Windows' and args.parent_window: import win32gui - if not win32gui.IsWindow(parent_window): + if not win32gui.IsWindow(args.parent_window): sys.stderr.write('Invalid --parent-window.\n') return 1 + reconnect_args = json.loads(base64.b64decode( + args.reconnect_command)) if args.reconnect_command else None + while 1: # Read the message type (first 4 bytes). text_length_bytes = sys.stdin.read(4) @@ -62,13 +70,13 @@ text_length = struct.unpack('i', text_length_bytes)[0] # Read the text (JSON object) of the message. - text = sys.stdin.read(text_length).decode('utf-8') + text = json.loads(sys.stdin.read(text_length).decode('utf-8')) # bigMessage() test sends a special message that is sent to verify that # chrome rejects messages that are too big. Try sending a message bigger # than 1MB after receiving a message that contains 'bigMessageTest'. if 'bigMessageTest' in text: - text = '{"key": "' + ("x" * 1024 * 1024) + '"}' + text = {"key": "x" * 1024 * 1024} # "stopHostTest" verifies that Chrome properly handles the case when the # host quits before port is closed. When the test receives response it @@ -84,8 +92,10 @@ message_number += 1 - message = '{{"id": {0}, "echo": {1}, "caller_url": "{2}"}}'.format( - message_number, text, caller_url).encode('utf-8') + message = json.dumps({ + 'id': message_number, 'echo': text, 'caller_url': caller_url, + 'args': reconnect_args + }).encode('utf-8') if not WriteMessage(message): break
diff --git a/chrome/test/data/push_messaging/service_worker.js b/chrome/test/data/push_messaging/service_worker.js index 19eadffa..2afead3 100644 --- a/chrome/test/data/push_messaging/service_worker.js +++ b/chrome/test/data/push_messaging/service_worker.js
@@ -9,13 +9,16 @@ // Don't wait for clients of old SW to close before activating. self.addEventListener('install', () => skipWaiting()); -// The "onpush" event currently understands two values as message payload -// data coming from the test. Any other input is passed through to the +// The "onpush" event currently understands the following values as message +// payload data coming from the test. Any other input is passed through to the // document unchanged. // -// "shownotification" - Display a Web Notification with event.waitUntil(). +// "shownotification" +// - Display a Web Notification with event.waitUntil(). // "shownotification-without-waituntil" // - Display a Web Notification without using event.waitUntil(). +// "shownotification-with-showtrigger" +// - Display a Web Notification with a showTrigger. this.onpush = function(event) { if (event.data === null) { sendMessageToClients('push', '[NULL]'); @@ -28,12 +31,19 @@ return; } - var result = registration.showNotification('Push test title', { + var notificationOptions = { body: 'Push test body', tag: 'push_test_tag' - }); + }; - if (data == 'shownotification-without-waituntil') { + if (data === 'shownotification-with-showtrigger') { + notificationOptions.showTrigger = new TimestampTrigger(Date.now() + 60000); + } + + var result = + registration.showNotification('Push test title', notificationOptions); + + if (data === 'shownotification-without-waituntil') { sendMessageToClients('push', 'immediate:' + data); return; } @@ -49,14 +59,15 @@ let pushSubscriptionOptions = { userVisibleOnly: true }; - if (event.data.command == 'workerSubscribe') { + if (event.data.command === 'workerSubscribe') { pushSubscriptionOptions.applicationServerKey = kApplicationServerKey.buffer; - } else if (event.data.command == 'workerSubscribeWithNumericKey') { + } else if (event.data.command === 'workerSubscribeWithNumericKey') { pushSubscriptionOptions.applicationServerKey = new TextEncoder().encode(event.data.key); - } else if (event.data.command == 'workerSubscribePushWithBase64URLEncodedString') { + } else if ( + event.data.command === 'workerSubscribePushWithBase64URLEncodedString') { pushSubscriptionOptions.applicationServerKey = kBase64URLEncodedKey; - } else if (event.data.command == 'workerSubscribeNoKey') { + } else if (event.data.command === 'workerSubscribeNoKey') { // Nothing to set up } else { sendMessageToClients('message', 'error - unknown message request');
diff --git a/chromeos/audio/audio_device.cc b/chromeos/audio/audio_device.cc index 416d7b3e..d17d9aff 100644 --- a/chromeos/audio/audio_device.cc +++ b/chromeos/audio/audio_device.cc
@@ -190,11 +190,21 @@ return false; if (is_input) { - return (type != AUDIO_TYPE_INTERNAL_MIC && type != AUDIO_TYPE_FRONT_MIC && - type != AUDIO_TYPE_REAR_MIC); + return !IsInternalMic(); } else { return (type != AUDIO_TYPE_INTERNAL_SPEAKER); } } +bool AudioDevice::IsInternalMic() const { + switch (type) { + case AUDIO_TYPE_INTERNAL_MIC: + case AUDIO_TYPE_FRONT_MIC: + case AUDIO_TYPE_REAR_MIC: + return true; + default: + return false; + } +} + } // namespace chromeos
diff --git a/chromeos/audio/audio_device.h b/chromeos/audio/audio_device.h index 647ff06..7b12088 100644 --- a/chromeos/audio/audio_device.h +++ b/chromeos/audio/audio_device.h
@@ -65,6 +65,8 @@ bool IsExternalDevice() const; + bool IsInternalMic() const; + bool is_input = false; // Id of this audio device. The legacy |id| is assigned to be unique everytime
diff --git a/chromeos/constants/chromeos_switches.cc b/chromeos/constants/chromeos_switches.cc index fd7bb9b4..e22a651 100644 --- a/chromeos/constants/chromeos_switches.cc +++ b/chromeos/constants/chromeos_switches.cc
@@ -474,12 +474,12 @@ // Smaller, denser shelf in clamshell mode. const char kShelfDenseClamshell[] = "shelf-dense-clamshell"; +// New modular design for the shelf with apps separated into a hotseat UI. +const char kShelfHotseat[] = "shelf-hotseat"; + // App window previews when hovering over the shelf. const char kShelfHoverPreviews[] = "shelf-hover-previews"; -// New modular UI design for the shelf. -const char kShelfNewUi[] = "shelf-new-ui"; - // Scrollable list of apps on the shelf. const char kShelfScrollable[] = "shelf-scrollable"; @@ -615,12 +615,12 @@ kShelfDenseClamshell); } -bool ShouldShowShelfHoverPreviews() { - return base::CommandLine::ForCurrentProcess()->HasSwitch(kShelfHoverPreviews); +bool ShouldShowShelfHotseat() { + return base::CommandLine::ForCurrentProcess()->HasSwitch(kShelfHotseat); } -bool ShouldShowShelfNewUi() { - return base::CommandLine::ForCurrentProcess()->HasSwitch(kShelfNewUi); +bool ShouldShowShelfHoverPreviews() { + return base::CommandLine::ForCurrentProcess()->HasSwitch(kShelfHoverPreviews); } bool ShouldShowScrollableShelf() {
diff --git a/chromeos/constants/chromeos_switches.h b/chromeos/constants/chromeos_switches.h index eb496ee..731a3ba 100644 --- a/chromeos/constants/chromeos_switches.h +++ b/chromeos/constants/chromeos_switches.h
@@ -178,7 +178,7 @@ COMPONENT_EXPORT(CHROMEOS_CONSTANTS) extern const char kSamlPasswordChangeUrl[]; COMPONENT_EXPORT(CHROMEOS_CONSTANTS) extern const char kShelfDenseClamshell[]; COMPONENT_EXPORT(CHROMEOS_CONSTANTS) extern const char kShelfHoverPreviews[]; -COMPONENT_EXPORT(CHROMEOS_CONSTANTS) extern const char kShelfNewUi[]; +COMPONENT_EXPORT(CHROMEOS_CONSTANTS) extern const char kShelfHotseat[]; COMPONENT_EXPORT(CHROMEOS_CONSTANTS) extern const char kShelfScrollable[]; COMPONENT_EXPORT(CHROMEOS_CONSTANTS) extern const char kShowAndroidFilesInFilesApp[]; @@ -267,13 +267,13 @@ // Returns true if we should show a smaller, denser shelf in clamshell mode. COMPONENT_EXPORT(CHROMEOS_CONSTANTS) bool ShouldShowShelfDenseClamshell(); +// Returns true if we should show the modular shelf with the hotseat UI. +COMPONENT_EXPORT(CHROMEOS_CONSTANTS) bool ShouldShowShelfHotseat(); + // Returns true if we should show window previews when hovering over an app // on the shelf. COMPONENT_EXPORT(CHROMEOS_CONSTANTS) bool ShouldShowShelfHoverPreviews(); -// Returns true if we should show the new modular shelf UI. -COMPONENT_EXPORT(CHROMEOS_CONSTANTS) bool ShouldShowShelfNewUi(); - // Returns true if we should show a scrollable list of apps in the main shelf. COMPONENT_EXPORT(CHROMEOS_CONSTANTS) bool ShouldShowScrollableShelf();
diff --git a/components/arc/common/file_system.mojom b/components/arc/common/file_system.mojom index 50d7fd4..8b237704 100644 --- a/components/arc/common/file_system.mojom +++ b/components/arc/common/file_system.mojom
@@ -164,6 +164,9 @@ // Filled only when DocumentsContract.EXTRA_INITIAL_URI points to a document // served by a DocumentsProvider. DocumentPath? initial_document_path; + + // Android task ID of the request sender. + int32 task_id; }; // Represents a path to a document served by a DocumentsProvider. @@ -195,6 +198,10 @@ // Specifies the target directory/file for CLICK_DIRECTORY/CLICK_FILE. FileSelectorElement click_target; + + // Android task ID of the activity that created the file selector by sending + // a SelectFilesRequest. + int32 creator_task_id; }; // Types of UI events for FileSelectorEvent. @@ -206,6 +213,13 @@ CLICK_CANCEL, // Clicks Cancel button. }; +// Request for GetFileSelectorElements. +struct GetFileSelectorElementsRequest { + // Android task ID of the activity that created the file selector by sending + // a SelectFilesRequest. + int32 creator_task_id; +}; + // Represents a clickable UI element shown on ChromeOS file selector. struct FileSelectorElement { // User-visible label of the element (e.g. button text). @@ -259,7 +273,8 @@ // Returns UI elements shown on the ChromeOS file selector previously opened // by SelectFiles@5. This exists for running Android UI tests (CTS) on // ChromeOS file selector, and thus it is only allowed under test conditions. - [MinVersion=11] GetFileSelectorElements@8() => + [MinVersion=11] GetFileSelectorElements@8( + GetFileSelectorElementsRequest request) => (FileSelectorElements elements); };
diff --git a/components/arc/ime/arc_ime_service.cc b/components/arc/ime/arc_ime_service.cc index bdafd0b0..0f86e8c 100644 --- a/components/arc/ime/arc_ime_service.cc +++ b/components/arc/ime/arc_ime_service.cc
@@ -20,7 +20,6 @@ #include "ui/aura/window_tree_host.h" #include "ui/base/ime/input_method.h" #include "ui/base/ime/text_input_flags.h" -#include "ui/base/ui_base_features.h" #include "ui/events/base_event_utils.h" #include "ui/events/event.h" #include "ui/events/keycodes/keyboard_codes.h" @@ -203,10 +202,7 @@ // Overridden from aura::EnvObserver: void ArcImeService::OnWindowInitialized(aura::Window* new_window) { - // TODO(mash): Support virtual keyboard under MASH. There is no - // KeyboardController in the browser process under MASH. - if (!features::IsMultiProcessMash() && - keyboard::KeyboardController::HasInstance()) { + if (keyboard::KeyboardController::HasInstance()) { auto* keyboard_controller = keyboard::KeyboardController::Get(); if (keyboard_controller->IsEnabled() && !keyboard_controller->HasObserver(this)) { @@ -358,10 +354,7 @@ if (!focused_arc_window_) return; - // TODO(mash): Support virtual keyboard under MASH. There is no - // KeyboardController in the browser process under MASH. - if (!features::IsMultiProcessMash() && - keyboard::KeyboardController::HasInstance()) { + if (keyboard::KeyboardController::HasInstance()) { auto* keyboard_controller = keyboard::KeyboardController::Get(); if (keyboard_controller->IsEnabled()) keyboard_controller->HideKeyboardImplicitlyBySystem();
diff --git a/components/autofill_assistant/browser/controller.cc b/components/autofill_assistant/browser/controller.cc index 343ac46..4d24004 100644 --- a/components/autofill_assistant/browser/controller.cc +++ b/components/autofill_assistant/browser/controller.cc
@@ -945,7 +945,12 @@ void Controller::GetTouchableArea(std::vector<RectF>* area) const { if (touchable_element_area_) - touchable_element_area_->GetRectangles(area); + touchable_element_area_->GetTouchableRectangles(area); +} + +void Controller::GetRestrictedArea(std::vector<RectF>* area) const { + if (touchable_element_area_) + touchable_element_area_->GetRestrictedRectangles(area); } void Controller::GetVisualViewport(RectF* visual_viewport) const { @@ -1126,9 +1131,12 @@ iter->second == "1"; } -void Controller::OnTouchableAreaChanged(const RectF& visual_viewport, - const std::vector<RectF>& areas) { - GetUiController()->OnTouchableAreaChanged(visual_viewport, areas); +void Controller::OnTouchableAreaChanged( + const RectF& visual_viewport, + const std::vector<RectF>& touchable_areas, + const std::vector<RectF>& restricted_areas) { + GetUiController()->OnTouchableAreaChanged(visual_viewport, touchable_areas, + restricted_areas); } void Controller::SetPaymentRequestOptions(
diff --git a/components/autofill_assistant/browser/controller.h b/components/autofill_assistant/browser/controller.h index 2455ae14a..11445752 100644 --- a/components/autofill_assistant/browser/controller.h +++ b/components/autofill_assistant/browser/controller.h
@@ -127,6 +127,7 @@ void SetTermsAndConditions( TermsAndConditionsState terms_and_conditions) override; void GetTouchableArea(std::vector<RectF>* area) const override; + void GetRestrictedArea(std::vector<RectF>* area) const override; void GetVisualViewport(RectF* visual_viewport) const override; void OnFatalError(const std::string& error_message, Metrics::DropOutReason reason) override; @@ -208,7 +209,8 @@ content::RenderWidgetHost* render_widget_host) override; void OnTouchableAreaChanged(const RectF& visual_viewport, - const std::vector<RectF>& areas); + const std::vector<RectF>& touchable_areas, + const std::vector<RectF>& restricted_areas); void SelectChip(std::vector<Chip>* chips, int chip_index); void SetOverlayColors(std::unique_ptr<OverlayColors> colors);
diff --git a/components/autofill_assistant/browser/element_area.cc b/components/autofill_assistant/browser/element_area.cc index 8a31f6b..14f7819 100644 --- a/components/autofill_assistant/browser/element_area.cc +++ b/components/autofill_assistant/browser/element_area.cc
@@ -29,19 +29,8 @@ void ElementArea::SetFromProto(const ElementAreaProto& proto) { rectangles_.clear(); - for (const auto& rectangle_proto : proto.rectangles()) { - rectangles_.emplace_back(); - Rectangle& rectangle = rectangles_.back(); - rectangle.full_width = rectangle_proto.full_width(); - DVLOG(3) << "Touchable Rectangle" - << (rectangle.full_width ? " (full_width)" : "") << ":"; - for (const auto& element_proto : rectangle_proto.elements()) { - rectangle.positions.emplace_back(); - ElementPosition& position = rectangle.positions.back(); - position.selector = Selector(element_proto).MustBeVisible(); - DVLOG(3) << " " << position.selector; - } - } + AddRectangles(proto.touchable(), /* restricted= */ false); + AddRectangles(proto.restricted(), /* restricted= */ true); if (rectangles_.empty()) { timer_.Stop(); @@ -60,6 +49,27 @@ } } +void ElementArea::AddRectangles( + const ::google::protobuf::RepeatedPtrField<ElementAreaProto::Rectangle>& + rectangles_proto, + bool restricted) { + for (const auto& rectangle_proto : rectangles_proto) { + rectangles_.emplace_back(); + Rectangle& rectangle = rectangles_.back(); + rectangle.full_width = rectangle_proto.full_width(); + rectangle.restricted = restricted; + DVLOG(3) << "Rectangle (full_width=" + << (rectangle.full_width ? "true" : "false") + << ", restricted=" << (restricted ? "true" : "false") << "):"; + for (const auto& element_proto : rectangle_proto.elements()) { + rectangle.positions.emplace_back(); + ElementPosition& position = rectangle.positions.back(); + position.selector = Selector(element_proto).MustBeVisible(); + DVLOG(3) << " " << position.selector; + } + } +} + void ElementArea::Update() { if (rectangles_.empty()) return; @@ -102,10 +112,21 @@ } } -void ElementArea::GetRectangles(std::vector<RectF>* area) { +void ElementArea::GetTouchableRectangles(std::vector<RectF>* area) { for (auto& rectangle : rectangles_) { - area->emplace_back(); - rectangle.FillRect(&area->back(), visual_viewport_); + if (!rectangle.restricted) { + area->emplace_back(); + rectangle.FillRect(&area->back(), visual_viewport_); + } + } +} + +void ElementArea::GetRestrictedRectangles(std::vector<RectF>* area) { + for (auto& rectangle : rectangles_) { + if (rectangle.restricted) { + area->emplace_back(); + rectangle.FillRect(&area->back(), visual_viewport_); + } } } @@ -192,7 +213,7 @@ if (rectangles_.empty()) { // Reporting of visual viewport is best effort when reporting empty // rectangles. It might also be empty. - on_update_.Run(visual_viewport_, {}); + on_update_.Run(visual_viewport_, {}, {}); return; } @@ -209,10 +230,12 @@ } } - std::vector<RectF> area; - GetRectangles(&area); + std::vector<RectF> touchable_area; + std::vector<RectF> restricted_area; + GetTouchableRectangles(&touchable_area); + GetRestrictedRectangles(&restricted_area); - on_update_.Run(visual_viewport_, area); + on_update_.Run(visual_viewport_, touchable_area, restricted_area); } } // namespace autofill_assistant
diff --git a/components/autofill_assistant/browser/element_area.h b/components/autofill_assistant/browser/element_area.h index cf13880..fe9e2f20 100644 --- a/components/autofill_assistant/browser/element_area.h +++ b/components/autofill_assistant/browser/element_area.h
@@ -53,7 +53,9 @@ // elements, which might be empty. void SetOnUpdate( base::RepeatingCallback<void(const RectF& visual_viewport, - const std::vector<RectF>& rectangles)> cb) { + const std::vector<RectF>& touchable_area, + const std::vector<RectF>& restricted_area)> + cb) { on_update_ = cb; } @@ -64,7 +66,8 @@ // not be empty. // // Note that the vector is not cleared before rectangles are added. - void GetRectangles(std::vector<RectF>* area); + void GetTouchableRectangles(std::vector<RectF>* area); + void GetRestrictedRectangles(std::vector<RectF>* area); // Gets the coordinates of the visual viewport, in CSS pixels relative to the // layout viewport. Empty if the size of the visual viewport is not known. @@ -96,6 +99,7 @@ struct Rectangle { std::vector<ElementPosition> positions; bool full_width = false; + bool restricted = false; Rectangle(); Rectangle(const Rectangle& orig); @@ -108,6 +112,9 @@ void FillRect(RectF* rect, const RectF& visual_viewport) const; }; + void AddRectangles(const ::google::protobuf::RepeatedPtrField< + ElementAreaProto::Rectangle>& rectangles_proto, + bool restricted); void OnGetElementPosition(const Selector& selector, bool found, const RectF& rect); @@ -128,7 +135,8 @@ base::RepeatingTimer timer_; base::RepeatingCallback<void(const RectF& visual_viewport, - const std::vector<RectF>& rectangles)> + const std::vector<RectF>& touchable_area, + const std::vector<RectF>& restricted_area)> on_update_; base::WeakPtrFactory<ElementArea> weak_ptr_factory_;
diff --git a/components/autofill_assistant/browser/element_area_unittest.cc b/components/autofill_assistant/browser/element_area_unittest.cc index d6686ac..1a8fc9b 100644 --- a/components/autofill_assistant/browser/element_area_unittest.cc +++ b/components/autofill_assistant/browser/element_area_unittest.cc
@@ -85,15 +85,23 @@ } void SetElement(const std::string& selector) { + SetElement(selector, /* restricted= */ false); + } + + void SetElement(const std::string& selector, bool restricted) { ElementAreaProto area; - area.add_rectangles()->add_elements()->add_selectors(selector); + auto* rectangle = restricted ? area.add_restricted() : area.add_touchable(); + rectangle->add_elements()->add_selectors(selector); element_area_.SetFromProto(area); } - void OnUpdate(const RectF& visual_viewport, const std::vector<RectF>& area) { + void OnUpdate(const RectF& visual_viewport, + const std::vector<RectF>& touchable_area, + const std::vector<RectF>& restricted_area) { on_update_call_count_++; reported_visual_viewport_ = visual_viewport; - reported_area_ = area; + reported_area_ = touchable_area; + reported_restricted_area_ = restricted_area; } // scoped_task_environment_ must be first to guarantee other field @@ -106,13 +114,14 @@ int on_update_call_count_ = 0; RectF reported_visual_viewport_; std::vector<RectF> reported_area_; + std::vector<RectF> reported_restricted_area_; }; TEST_F(ElementAreaTest, Empty) { EXPECT_THAT(reported_area_, IsEmpty()); std::vector<RectF> rectangles; - element_area_.GetRectangles(&rectangles); + element_area_.GetTouchableRectangles(&rectangles); EXPECT_THAT(rectangles, IsEmpty()); RectF viewport; @@ -125,7 +134,7 @@ EXPECT_THAT(reported_area_, ElementsAre(EmptyRectF())); std::vector<RectF> rectangles; - element_area_.GetRectangles(&rectangles); + element_area_.GetTouchableRectangles(&rectangles); EXPECT_THAT(rectangles, ElementsAre(EmptyRectF())); } @@ -143,7 +152,7 @@ SetElement("#found"); std::vector<RectF> rectangles; - element_area_.GetRectangles(&rectangles); + element_area_.GetTouchableRectangles(&rectangles); EXPECT_THAT(rectangles, ElementsAre(MatchingRectF(25, 25, 75, 75))); } @@ -197,12 +206,12 @@ .WillOnce(RunOnceCallback<1>(true, RectF(25, 25, 100, 100))); ElementAreaProto area_proto; - area_proto.add_rectangles()->add_elements()->add_selectors("#top_left"); - area_proto.add_rectangles()->add_elements()->add_selectors("#bottom_right"); + area_proto.add_touchable()->add_elements()->add_selectors("#top_left"); + area_proto.add_touchable()->add_elements()->add_selectors("#bottom_right"); element_area_.SetFromProto(area_proto); std::vector<RectF> rectangles; - element_area_.GetRectangles(&rectangles); + element_area_.GetTouchableRectangles(&rectangles); EXPECT_THAT(rectangles, ElementsAre(MatchingRectF(0, 0, 25, 25), MatchingRectF(25, 25, 100, 100))); } @@ -218,13 +227,13 @@ .WillOnce(RunOnceCallback<1>(true, RectF(5, 2, 6, 5))); ElementAreaProto area_proto; - auto* rectangle_proto = area_proto.add_rectangles(); + auto* rectangle_proto = area_proto.add_touchable(); rectangle_proto->add_elements()->add_selectors("#element1"); rectangle_proto->add_elements()->add_selectors("#element2"); element_area_.SetFromProto(area_proto); std::vector<RectF> rectangles; - element_area_.GetRectangles(&rectangles); + element_area_.GetTouchableRectangles(&rectangles); EXPECT_THAT(rectangles, ElementsAre(MatchingRectF(1, 2, 6, 5))); } @@ -242,7 +251,7 @@ .WillOnce(DoNothing()); // overrides default action ElementAreaProto area_proto; - auto* rectangle_proto = area_proto.add_rectangles(); + auto* rectangle_proto = area_proto.add_touchable(); rectangle_proto->add_elements()->add_selectors("#element1"); rectangle_proto->add_elements()->add_selectors("#element2"); element_area_.SetFromProto(area_proto); @@ -250,7 +259,7 @@ EXPECT_THAT(reported_area_, IsEmpty()); std::vector<RectF> rectangles; - element_area_.GetRectangles(&rectangles); + element_area_.GetTouchableRectangles(&rectangles); EXPECT_THAT(rectangles, ElementsAre(MatchingRectF(1, 3, 2, 4))); } @@ -273,7 +282,7 @@ .WillOnce(RunOnceCallback<1>(true, RectF(9, 0, 100, 1))); ElementAreaProto area_proto; - auto* rectangle_proto = area_proto.add_rectangles(); + auto* rectangle_proto = area_proto.add_touchable(); rectangle_proto->add_elements()->add_selectors("#element1"); rectangle_proto->add_elements()->add_selectors("#element2"); rectangle_proto->add_elements()->add_selectors("#element3"); @@ -281,7 +290,7 @@ element_area_.SetFromProto(area_proto); std::vector<RectF> rectangles; - element_area_.GetRectangles(&rectangles); + element_area_.GetTouchableRectangles(&rectangles); EXPECT_THAT(rectangles, ElementsAre(MatchingRectF(0, 0, 100, 100))); } @@ -296,13 +305,13 @@ .WillOnce(RunOnceCallback<1>(false, RectF())); ElementAreaProto area_proto; - auto* rectangle_proto = area_proto.add_rectangles(); + auto* rectangle_proto = area_proto.add_touchable(); rectangle_proto->add_elements()->add_selectors("#element1"); rectangle_proto->add_elements()->add_selectors("#element2"); element_area_.SetFromProto(area_proto); std::vector<RectF> rectangles; - element_area_.GetRectangles(&rectangles); + element_area_.GetTouchableRectangles(&rectangles); EXPECT_THAT(rectangles, ElementsAre(MatchingRectF(1, 1, 2, 2))); EXPECT_THAT(reported_area_, ElementsAre(MatchingRectF(1, 1, 2, 2))); @@ -321,14 +330,14 @@ .WillRepeatedly(RunOnceCallback<0>(true, RectF(100, 0, 200, 400))); ElementAreaProto area_proto; - auto* rectangle_proto = area_proto.add_rectangles(); + auto* rectangle_proto = area_proto.add_touchable(); rectangle_proto->add_elements()->add_selectors("#element1"); rectangle_proto->add_elements()->add_selectors("#element2"); rectangle_proto->set_full_width(true); element_area_.SetFromProto(area_proto); std::vector<RectF> rectangles; - element_area_.GetRectangles(&rectangles); + element_area_.GetTouchableRectangles(&rectangles); // left and right of the box come from the visual viewport, top from the 1st // element, bottom from the 2nd. @@ -346,7 +355,7 @@ SetElement("#element"); std::vector<RectF> original; - element_area_.GetRectangles(&original); + element_area_.GetTouchableRectangles(&original); EXPECT_THAT(original, ElementsAre(MatchingRectF(0, 25, 100, 50))); EXPECT_THAT(reported_area_, ElementsAre(MatchingRectF(0, 25, 100, 50))); @@ -354,7 +363,7 @@ // Updated area is available std::vector<RectF> updated; - element_area_.GetRectangles(&updated); + element_area_.GetTouchableRectangles(&updated); EXPECT_THAT(updated, ElementsAre(MatchingRectF(0, 50, 100, 75))); // Updated area is reported @@ -378,11 +387,34 @@ // Updated area is available std::vector<RectF> rectangles; - element_area_.GetRectangles(&rectangles); + element_area_.GetTouchableRectangles(&rectangles); EXPECT_THAT(rectangles, ElementsAre(MatchingRectF(0, 50, 100, 75))); // Updated area is reported EXPECT_THAT(reported_area_, ElementsAre(MatchingRectF(0, 50, 100, 75))); } + +TEST_F(ElementAreaTest, RestrictedElement) { + EXPECT_CALL(mock_web_controller_, + OnGetElementPosition( + Eq(Selector({"#restricted_element"}).MustBeVisible()), _)) + .WillOnce(RunOnceCallback<1>(true, RectF(25, 25, 75, 75))); + + SetElement("#restricted_element", /* restricted= */ true); + + EXPECT_EQ(on_update_call_count_, 1); + EXPECT_THAT(reported_area_, IsEmpty()); + EXPECT_THAT(reported_restricted_area_, + ElementsAre(MatchingRectF(25, 25, 75, 75))); + + std::vector<RectF> touchable_rectangles; + std::vector<RectF> restricted_rectangles; + element_area_.GetTouchableRectangles(&touchable_rectangles); + element_area_.GetRestrictedRectangles(&restricted_rectangles); + + EXPECT_THAT(touchable_rectangles, IsEmpty()); + EXPECT_THAT(restricted_rectangles, + ElementsAre(MatchingRectF(25, 25, 75, 75))); +} } // namespace } // namespace autofill_assistant
diff --git a/components/autofill_assistant/browser/metrics.h b/components/autofill_assistant/browser/metrics.h index f10c736..fa5608a 100644 --- a/components/autofill_assistant/browser/metrics.h +++ b/components/autofill_assistant/browser/metrics.h
@@ -43,7 +43,7 @@ GET_SCRIPTS_FAILED = 17, GET_SCRIPTS_UNPARSABLE = 18, NO_INITIAL_SCRIPTS = 19, - DFM_CANCELLED = 19, + DFM_INSTALL_FAILED = 20, NUM_ENTRIES = 21, }; @@ -145,6 +145,12 @@ case NO_INITIAL_SCRIPTS: out << "NO_INITIAL_SCRIPTS"; + break; + + case DFM_INSTALL_FAILED: + out << "DFM_INSTALL_FAILED"; + break; + // Intentionally no default case to make compilation fail if a new value // was added to the enum but not to this list. }
diff --git a/components/autofill_assistant/browser/mock_ui_controller.h b/components/autofill_assistant/browser/mock_ui_controller.h index 71f9762..b312c3c 100644 --- a/components/autofill_assistant/browser/mock_ui_controller.h +++ b/components/autofill_assistant/browser/mock_ui_controller.h
@@ -34,8 +34,10 @@ MOCK_METHOD1(OnInfoBoxChanged, void(const InfoBox* info_box)); MOCK_METHOD1(OnProgressChanged, void(int progress)); MOCK_METHOD1(OnProgressVisibilityChanged, void(bool visible)); - MOCK_METHOD2(OnTouchableAreaChanged, - void(const RectF&, const std::vector<RectF>& areas)); + MOCK_METHOD3(OnTouchableAreaChanged, + void(const RectF&, + const std::vector<RectF>& touchable_areas, + const std::vector<RectF>& restricted_areas)); MOCK_CONST_METHOD0(Terminate, bool()); MOCK_CONST_METHOD0(GetDropOutReason, Metrics::DropOutReason()); MOCK_METHOD1(OnResizeViewportChanged, void(bool resize_viewport));
diff --git a/components/autofill_assistant/browser/service.proto b/components/autofill_assistant/browser/service.proto index eeb5422..c24aa88 100644 --- a/components/autofill_assistant/browser/service.proto +++ b/components/autofill_assistant/browser/service.proto
@@ -753,7 +753,13 @@ // the screen. optional bool full_width = 2; } - repeated Rectangle rectangles = 1; + + // The rectangles that will be highlighted and touchable. + repeated Rectangle touchable = 1; + + // The rectangles that should be neither highlighted nor touchable. Those + // rectangles have precedence over the |touchable| rectangles. + repeated Rectangle restricted = 2; } // Fill a form with an address if there is, otherwise fail this action.
diff --git a/components/autofill_assistant/browser/ui_controller.cc b/components/autofill_assistant/browser/ui_controller.cc index a2819e78..3c77a5ca 100644 --- a/components/autofill_assistant/browser/ui_controller.cc +++ b/components/autofill_assistant/browser/ui_controller.cc
@@ -25,8 +25,10 @@ void UiController::OnInfoBoxChanged(const InfoBox* info_box) {} void UiController::OnProgressChanged(int progress) {} void UiController::OnProgressVisibilityChanged(bool visible) {} -void UiController::OnTouchableAreaChanged(const RectF& visual_viewport, - const std::vector<RectF>& areas) {} +void UiController::OnTouchableAreaChanged( + const RectF& visual_viewport, + const std::vector<RectF>& touchable_areas, + const std::vector<RectF>& restricted_areas) {} void UiController::OnResizeViewportChanged(bool resize_viewport) {} void UiController::OnPeekModeChanged( ConfigureBottomSheetProto::PeekMode peek_mode) {}
diff --git a/components/autofill_assistant/browser/ui_controller.h b/components/autofill_assistant/browser/ui_controller.h index adb0342..808ec13 100644 --- a/components/autofill_assistant/browser/ui_controller.h +++ b/components/autofill_assistant/browser/ui_controller.h
@@ -80,12 +80,18 @@ // the layout viewport. It might be empty if not known or the touchable area // is empty. // - // |rectangles| contains one element per configured rectangles, though these - // can correspond to empty rectangles. + // |touchable_areas| contains one element per configured rectangle that should + // be visible/touchable, though these can correspond to empty rectangles. + // + // |restricted_areas| contains one element per configured rectangle that + // shouldn't be visible nor touchable. Those rectangles have precedence over + // |touchable_areas|. // // All rectangles are expressed in absolute CSS coordinates. - virtual void OnTouchableAreaChanged(const RectF& visual_viewport, - const std::vector<RectF>& rectangles); + virtual void OnTouchableAreaChanged( + const RectF& visual_viewport, + const std::vector<RectF>& touchable_areas, + const std::vector<RectF>& restricted_areas); // Called when the viewport resize flag has changed. virtual void OnResizeViewportChanged(bool resize_viewport);
diff --git a/components/autofill_assistant/browser/ui_delegate.h b/components/autofill_assistant/browser/ui_delegate.h index 288dd0fc..1931600 100644 --- a/components/autofill_assistant/browser/ui_delegate.h +++ b/components/autofill_assistant/browser/ui_delegate.h
@@ -113,6 +113,7 @@ // // Note that the vector is not cleared before rectangles are added. virtual void GetTouchableArea(std::vector<RectF>* rectangles) const = 0; + virtual void GetRestrictedArea(std::vector<RectF>* rectangles) const = 0; // Returns the current size of the visual viewport. May be empty if unknown. //
diff --git a/components/download/internal/common/simple_download_manager_coordinator.cc b/components/download/internal/common/simple_download_manager_coordinator.cc index bf1a4f4..4bfd24b 100644 --- a/components/download/internal/common/simple_download_manager_coordinator.cc +++ b/components/download/internal/common/simple_download_manager_coordinator.cc
@@ -106,4 +106,8 @@ return notifier_.get(); } +void SimpleDownloadManagerCoordinator::CheckForExternallyRemovedDownloads() { + simple_download_manager_->CheckForHistoryFilesRemoval(); +} + } // namespace download
diff --git a/components/download/public/common/simple_download_manager.h b/components/download/public/common/simple_download_manager.h index 8a3bd82..ef9f5907 100644 --- a/components/download/public/common/simple_download_manager.h +++ b/components/download/public/common/simple_download_manager.h
@@ -56,6 +56,11 @@ // Get the download item for |guid|. virtual DownloadItem* GetDownloadByGuid(const std::string& guid) = 0; + // Checks whether downloaded files still exist. Updates state of downloads + // that refer to removed files. The check runs in the background and may + // finish asynchronously after this method returns. + virtual void CheckForHistoryFilesRemoval() {} + protected: // Called when the manager is initailized. void OnInitialized();
diff --git a/components/download/public/common/simple_download_manager_coordinator.h b/components/download/public/common/simple_download_manager_coordinator.h index c610486e..6c82535 100644 --- a/components/download/public/common/simple_download_manager_coordinator.h +++ b/components/download/public/common/simple_download_manager_coordinator.h
@@ -75,6 +75,11 @@ bool has_all_history_downloads() const { return has_all_history_downloads_; } + // Checks whether downloaded files still exist. Updates state of downloads + // that refer to removed files. The check runs in the background and may + // finish asynchronously after this method returns. + void CheckForExternallyRemovedDownloads(); + private: // SimpleDownloadManager::Observer implementation. void OnDownloadsInitialized() override;
diff --git a/components/exo/wayland/fuzzer/BUILD.gn b/components/exo/wayland/fuzzer/BUILD.gn index 0f0a6433..262c116 100644 --- a/components/exo/wayland/fuzzer/BUILD.gn +++ b/components/exo/wayland/fuzzer/BUILD.gn
@@ -49,6 +49,16 @@ protocols = kDefaultWaylandProtocols } +# We make the seed corpus by enumerating call sequences to all requests +# using the wayland_sequencer script. +wayland_templater("corpus") { + sources = [ + "corpus.tmpl", + ] + protocols = kDefaultWaylandProtocols + script_override = "wayland_sequencer.py" +} + if (use_libfuzzer) { fuzzer_test("wayland_fuzzer") { sources = [ @@ -64,6 +74,10 @@ ] libfuzzer_options = [ "len_control=0" ] + + corpus_target_outputs = get_target_outputs(":corpus") + seed_corpus = corpus_target_outputs[0] + seed_corpus_deps = [ ":corpus" ] } }
diff --git a/components/exo/wayland/fuzzer/corpus.tmpl b/components/exo/wayland/fuzzer/corpus.tmpl new file mode 100644 index 0000000..82e207b --- /dev/null +++ b/components/exo/wayland/fuzzer/corpus.tmpl
@@ -0,0 +1,15 @@ +# Copyright 2019 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{% for interface, method, args in sequence %} + acts{ + {% if interface %} + act_{{ interface }}_{{ method }} { + {% for name, literal in args %} + {{ name }} : {{ literal }} + {% endfor %} + } + {% endif %} + } +{% endfor %}
diff --git a/components/exo/wayland/fuzzer/harness.cc.tmpl b/components/exo/wayland/fuzzer/harness.cc.tmpl index e1151aec..fa394b85 100644 --- a/components/exo/wayland/fuzzer/harness.cc.tmpl +++ b/components/exo/wayland/fuzzer/harness.cc.tmpl
@@ -71,13 +71,22 @@ ::{{interface.name}}* receiver = harness->get_{{interface.name}}(action.receiver()); if (!receiver) return; + {% for arg in request.args %} + {% if arg.type == 'object' %} + {{arg.cpp_type}} {{arg.name}} = harness->get_{{arg.interface}}(action.{{arg.name}}()); + {% if not arg.nullable %} + if (!{{arg.name}}) + return; + {% endif %} + {% endif %} + {% endfor %} {% if request.is_constructor %} ::{{request.constructed}}* new_object = {% endif %} {{interface.name}}_{{request.name}}(receiver {% for arg in request.args %} {% if arg.type == 'object' %} - , harness->get_{{arg.interface}}(action.{{arg.name}}()) + , {{arg.name}} {% elif arg.type != 'new_id' %} , action.{{arg.name}}(){% if arg.type == 'string' %}.c_str(){% endif %} {% endif %}
diff --git a/components/exo/wayland/fuzzer/wayland_sequencer.py b/components/exo/wayland/fuzzer/wayland_sequencer.py new file mode 100644 index 0000000..47cde1da --- /dev/null +++ b/components/exo/wayland/fuzzer/wayland_sequencer.py
@@ -0,0 +1,177 @@ +# Copyright (c) 2019 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +"""Generate sequences of valid wayland instructions. + +Determines sequences of calls necessary to instantiate and invoke a given +message of one of the wayland interfaces. The procedure is as follows: + - Get a dependency graph between messages, and the interfaces you need in + order to invoke them. + - The list of messages you need to invoke is the sum of transitive + dependencies for the target message. +""" + +from __future__ import absolute_import +from __future__ import print_function + +import os +import sys + +import wayland_templater +import wayland_utils as wlu + +# To prevent the fuzzer from exploring too-much space, we limit it to binding at +# most a small number of each interface. So the index has to be in this map. +small_value = {0: 'ZERO', 1: 'ONE', 2: 'TWO', 3: 'THREE'} + +# The default (empty) message is a wl_display_roundtrip. +round_trip = ('', '', []) + + +def ToNode(interface, message): + return (interface.attrib['name'], message.attrib['name']) + + +def GetDependencyGraph(protocols): + """Determine the dependencies between interfaces and their messages. + + Args: + protocols: the list of wayland xml protocols you want the dependencies of. + + Returns: + A bipartite graph where messages (i, m) depend on interfaces (i) and + vice-versa. An edge from (i,m) to (i') indicates an i' instance is needed to + invoke m, whereas (i) to (i',m') indicates m' is a constructor for i + instances. + """ + dep_graph = {} + constructed_interfaces = set() + for _, i, m in wlu.AllMessages(protocols): + dep_graph[ToNode(i, m)] = [('receiver', i.attrib['name'])] + [ + (a.attrib['name'], a.attrib.get('interface', '?')) + for a in m.findall('arg') + if a.attrib['type'] == 'object' + ] + constructed = wlu.GetConstructedInterface(m) + if constructed: + constructed_interfaces.add(constructed) + dep_graph[constructed] = ToNode(i, m) + for _, i in wlu.AllInterfaces(protocols): + if i.attrib['name'] not in constructed_interfaces: + dep_graph[i.attrib['name']] = ('wl_registry', 'bind') + return dep_graph + + +class SequenceContext(object): + """Store for data used when building one sequence. + + This class is used to store the data which will help build the sequences but + which does not actually appear in the sequences. You should make a new + SequenceContext for every sequence you want to generate. + """ + + def __init__(self, dep_graph): + self.counts = {} + self.prevented = set() + self.dep_graph = dep_graph + # To simulate what the harness itself does, we make a singleton wl_display. + self.RecordInterfaceCreated('wl_display') + self.Prevent('wl_display') + + def IsPrevented(self, interface_name): + return interface_name in self.prevented + + def Prevent(self, interface_name): + self.prevented.add(interface_name) + + def RecordInterfaceCreated(self, interface_name): + self.counts[interface_name] = self.counts.get(interface_name, -1) + 1 + + def GetLastInterfaceCreated(self, interface_name): + """Return the small_value index for the currently available interface. + + Args: + interface_name: the name of the interface you want an index of. + + Returns: + A small_value index for the topmost-version of the interface. + """ + return small_value[self.counts[interface_name]] + + +def GetSequenceForInterface(i_name, context): + if context.IsPrevented(i_name): + return [] + if i_name == 'wl_registry' or context.dep_graph[i_name] == ('wl_registry', + 'bind'): + context.Prevent(i_name) + (cons_i, cons_m) = context.dep_graph[i_name] + seq = GetSequenceForMessage(cons_i, cons_m, context, i_name) + context.RecordInterfaceCreated(i_name) + return seq + + +def GetSequenceForMessage(i_name, m_name, context, target_i): + """Return the message sequence up to and including the supplied message. + + Args: + i_name: the name of the interface that defines the message you want to + send. + m_name: the name of the message you want to send. + context: the global context state, + target_i: the interface you expect to be created by this message (if there + is one, otherwise use ''). + + Returns: + A list of (i, m, [args...]) tuples, each having an interface name, message + name, and arguments for invoking that message. The ('', '', []) tuple + indicates the default message (which sends wl_display_roundtrip()). + """ + seq = [] + args = [] + # get the message sequence needed to create each argument for the target + # message. + for arg_n, arg_t in context.dep_graph[(i_name, m_name)]: + seq += GetSequenceForInterface(arg_t, context) + args.append((arg_n, context.GetLastInterfaceCreated(arg_t))) + if i_name == 'wl_registry' and m_name == 'bind' and target_i: + args.append(('global', target_i)) + seq.append((i_name, m_name, args)) + # We need to do a round-trip after binding the registry so that we have the + # globals available for binding. + if i_name == 'wl_display' and m_name == 'get_registry' and target_i: + seq.append(round_trip) + return seq + + +def Main(argv): + """Instantiate the group of message-sequences used to seed the fuzzer. + + Args: + argv: command-line arguments used to run the sequencer. + """ + parsed = wlu.ParseOpts(argv) + out_dir = parsed.output + if not os.path.exists(out_dir): + os.mkdir(out_dir) + + protocols = wlu.ReadProtocols(parsed.spec) + dep_graph = GetDependencyGraph(protocols) + for _, interface in wlu.AllInterfaces(protocols): + for req in interface.findall('request'): + interface_name = interface.attrib['name'] + message_name = req.attrib['name'] + sequence = GetSequenceForMessage(interface_name, message_name, + SequenceContext(dep_graph), '') + # Add a round-trip to the sequence in case the server wants to do + # something funky. + sequence += [round_trip] + + out_path = os.path.join(out_dir, + '%s_%s.asciipb' % (interface_name, message_name)) + wayland_templater.InstantiateTemplate( + parsed.input, {'sequence': sequence}, out_path, parsed.directory) + + +if __name__ == '__main__': + Main(sys.argv)
diff --git a/components/exo/wayland/fuzzer/wayland_templater.gni b/components/exo/wayland/fuzzer/wayland_templater.gni index 0c59cc0..9a4c9de 100644 --- a/components/exo/wayland/fuzzer/wayland_templater.gni +++ b/components/exo/wayland/fuzzer/wayland_templater.gni
@@ -21,6 +21,9 @@ # ":foo_tmpl", # ] # } +# +# If needed, the user can set 'script_override=foo.py' to use a different +# templating script to the default (wayland_templater.py). template("wayland_templater") { assert(defined(invoker.sources), "Need sources for wayland_templater") assert(defined(invoker.protocols), "Need protocols for wayland_templater") @@ -34,6 +37,11 @@ template_outputs += [ "${target_gen_dir}/${dir}/${name}" ] } + templater_script_name = "wayland_templater.py" + if (defined(invoker.script_override)) { + templater_script_name = invoker.script_override + } + # Jinja2 doesnt like having ".." in the target path, so we give it the # source-tree's path rather than the build-directory's relative path (which # usually contains ".."). @@ -46,13 +54,13 @@ script = "//third_party/blink/renderer/build/scripts/run_with_pythonpath.py" sources = [ script, - "wayland_templater.py", + templater_script_name, ] + invoker.sources + invoker.protocols outputs = template_outputs args = [ "-I", rebase_path("//third_party", root_build_dir), - rebase_path("wayland_templater.py", root_build_dir), + rebase_path(templater_script_name, root_build_dir), "--directory", build_to_src_path, "--input",
diff --git a/components/exo/wayland/fuzzer/wayland_templater.py b/components/exo/wayland/fuzzer/wayland_templater.py index c87df3a..71ab881 100644 --- a/components/exo/wayland/fuzzer/wayland_templater.py +++ b/components/exo/wayland/fuzzer/wayland_templater.py
@@ -11,11 +11,10 @@ from __future__ import absolute_import from __future__ import print_function -import argparse import sys -from xml.etree import ElementTree import jinja2 +import wayland_utils as wlu proto_type_conversions = { 'object': 'small_value', @@ -35,84 +34,6 @@ } -def AllInterfaces(protocols): - """Get the interfaces in these protocols. - - Args: - protocols: the list of protocols you want the interfaces of. - - Yields: - Tuples (p, i) of (p)rotocol (i)nterface. - """ - for p in protocols: - for i in p.findall('interface'): - yield (p, i) - - -def AllMessages(protocols): - """Get the messages in these protocols. - - Args: - protocols: the list of protocols you want the messages of. - - Yields: - Tuples (p, i, m) of (p)rotocol, (i)nterface, and (m)essage. - """ - for (p, i) in AllInterfaces(protocols): - for r in i.findall('request'): - yield (p, i, r) - for e in i.findall('event'): - yield (p, i, e) - - -def GetConstructorArg(message): - """Get the argument that this message constructs, or None. - - Args: - message: the message which you want to find the constructor arg of. - - Returns: - The argument (as an ElementTree node) that constructs a new interface, or - None. - """ - return message.find('arg[@type="new_id"]') - - -def IsConstructor(message): - """Check if a message is a constructor. - - Args: - message: the message which you want to check. - - Returns: - True if the message constructs an object (via new_id), False otherwise. - """ - return GetConstructorArg(message) is not None - - -def GetConstructedInterface(message): - """Gets the interface constructed by a message. - - Note that even if IsConstructor(message) returns true, get_constructed can - still return None when the message constructs an unknown interface (e.g. - wl_registry.bind()). - - Args: - message: the event/request which may be a constructor. - - Returns: - The name of the constructed interface (if there is one), or None. - """ - cons_arg = GetConstructorArg(message) - if cons_arg is None: - return None - return cons_arg.attrib.get('interface') - - -def NeedsListener(interface): - return interface.find('event') is not None - - def GetCppType(arg): ty = arg.attrib['type'] if ty in ['object', 'new_id']: @@ -131,12 +52,12 @@ def __init__(self, protocols): self.non_global_names = { - GetConstructedInterface(m) for _, _, m in AllMessages(protocols) + wlu.GetConstructedInterface(m) for _, _, m in wlu.AllMessages(protocols) } - {None} self.interfaces_with_listeners = { i.attrib['name'] - for p, i in AllInterfaces(protocols) - if NeedsListener(i) + for p, i in wlu.AllInterfaces(protocols) + if wlu.NeedsListener(i) } self.counts = {} @@ -159,6 +80,7 @@ return { 'name': arg.attrib['name'], 'type': ty, + 'nullable': arg.attrib.get('allow-null', 'false') == 'true', 'proto_type': proto_type_conversions.get(ty), 'cpp_type': GetCppType(arg), 'interface': arg.attrib.get('interface'), @@ -167,7 +89,7 @@ def GetMessage(message, context): name = message.attrib['name'] - constructed = GetConstructedInterface(message) + constructed = wlu.GetConstructedInterface(message) return { 'name': name, @@ -175,7 +97,7 @@ context.GetAndIncrementCount('message_index'), 'args': [GetArg(a) for a in message.findall('arg')], 'is_constructor': - IsConstructor(message), + wlu.IsConstructor(message), 'constructed': constructed, 'constructed_has_listener': @@ -197,12 +119,12 @@ GetMessage(m, context) for m in interface.findall('request') ], 'has_listener': - NeedsListener(interface) + wlu.NeedsListener(interface) } def GetTemplateData(protocol_paths): - protocols = [ElementTree.parse(path).getroot() for path in protocol_paths] + protocols = wlu.ReadProtocols(protocol_paths) context = TemplaterContext(protocols) interfaces = [] for p in protocols: @@ -214,44 +136,26 @@ } +def InstantiateTemplate(in_tmpl, in_ctx, output, in_directory): + env = jinja2.Environment( + loader=jinja2.FileSystemLoader(in_directory), + keep_trailing_newline=True, # newline-terminate generated files + lstrip_blocks=True, + trim_blocks=True) # so don't need {%- -%} everywhere + template = env.get_template(in_tmpl) + with open(output, 'w') as out_fi: + out_fi.write(template.render(in_ctx)) + + def main(argv): """Execute the templater, based on the user provided args. Args: argv: the command line arguments (including the script name) """ - parser = argparse.ArgumentParser(description=__doc__) - parser.add_argument( - '-d', - '--directory', - help='treat input paths as relative to this directory', - default='.') - parser.add_argument( - '-i', - '--input', - help='path to the input template file (relative to -d)', - required=True) - parser.add_argument( - '-o', - '--output', - help='path to write the generated file to', - required=True) - parser.add_argument( - '-s', - '--spec', - help='path(s) to the wayland specification(s)', - nargs='+', - required=True) - parsed_args = parser.parse_args(argv[1:]) - - env = jinja2.Environment( - loader=jinja2.FileSystemLoader(parsed_args.directory), - keep_trailing_newline=True, # newline-terminate generated files - lstrip_blocks=True, - trim_blocks=True) # so don't need {%- -%} everywhere - template = env.get_template(parsed_args.input) - with open(parsed_args.output, 'w') as out_fi: - out_fi.write(template.render(GetTemplateData(parsed_args.spec))) + parsed_args = wlu.ParseOpts(argv) + InstantiateTemplate(parsed_args.input, GetTemplateData(parsed_args.spec), + parsed_args.output, parsed_args.directory) if __name__ == '__main__':
diff --git a/components/exo/wayland/fuzzer/wayland_utils.py b/components/exo/wayland/fuzzer/wayland_utils.py new file mode 100644 index 0000000..fe20b78d --- /dev/null +++ b/components/exo/wayland/fuzzer/wayland_utils.py
@@ -0,0 +1,130 @@ +# Copyright (c) 2019 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +"""Utilities for working with wayland protocols. + +A collection of all the generically useful wayland utilities. +""" + +from __future__ import absolute_import +from __future__ import print_function + +import argparse +from xml.etree import ElementTree + + +def ReadProtocols(protocol_paths): + return [ElementTree.parse(path).getroot() for path in protocol_paths] + + +def AllInterfaces(protocols): + """Get the interfaces in these protocols. + + Args: + protocols: the list of protocols you want the interfaces of. + + Yields: + Tuples (p, i) of (p)rotocol (i)nterface. + """ + for p in protocols: + for i in p.findall('interface'): + yield (p, i) + + +def AllMessages(protocols): + """Get the messages in these protocols. + + Args: + protocols: the list of protocols you want the messages of. + + Yields: + Tuples (p, i, m) of (p)rotocol, (i)nterface, and (m)essage. + """ + for (p, i) in AllInterfaces(protocols): + for r in i.findall('request'): + yield (p, i, r) + for e in i.findall('event'): + yield (p, i, e) + + +def GetConstructorArg(message): + """Get the argument that this message constructs, or None. + + Args: + message: the message which you want to find the constructor arg of. + + Returns: + The argument (as an ElementTree node) that constructs a new interface, or + None. + """ + return message.find('arg[@type="new_id"]') + + +def IsConstructor(message): + """Check if a message is a constructor. + + Args: + message: the message which you want to check. + + Returns: + True if the message constructs an object (via new_id), False otherwise. + """ + return GetConstructorArg(message) is not None + + +def GetConstructedInterface(message): + """Gets the interface constructed by a message. + + Note that even if IsConstructor(message) returns true, get_constructed can + still return None when the message constructs an unknown interface (e.g. + wl_registry.bind()). + + Args: + message: the event/request which may be a constructor. + + Returns: + The name of the constructed interface (if there is one), or None. + """ + cons_arg = GetConstructorArg(message) + if cons_arg is None: + return None + return cons_arg.attrib.get('interface') + + +def NeedsListener(interface): + return interface.find('event') is not None + + +def ParseOpts(argv): + """Parses the given command line arguments for the templater. + + Args: + argv: the arguments to be parsed. + + Returns: + An argparse.ArgumentParser which provides the user's chosen configuration + for this templater run. + """ + parser = argparse.ArgumentParser() + parser.add_argument( + '-d', + '--directory', + help='treat input paths as relative to this directory', + default='.') + parser.add_argument( + '-i', + '--input', + help='path to the input template file (relative to -d)', + required=True) + parser.add_argument( + '-o', + '--output', + help='path to write the generated file to', + required=True) + parser.add_argument( + '-s', + '--spec', + help='path(s) to the wayland specification(s)', + nargs='+', + required=True) + return parser.parse_args(argv[1:])
diff --git a/components/favicon/core/features.cc b/components/favicon/core/features.cc index 7532efa5..d018a51 100644 --- a/components/favicon/core/features.cc +++ b/components/favicon/core/features.cc
@@ -12,5 +12,8 @@ "kAllowPropagationOfFaviconCacheHits", base::FEATURE_ENABLED_BY_DEFAULT}; const base::Feature kEnableHistoryFaviconsGoogleServerQuery{ "EnableHistoryFaviconsGoogleServerQuery", base::FEATURE_DISABLED_BY_DEFAULT}; +const base::Feature kNotifySessionsOfMostRecentIconUrlChange{ + "NotifySessionsOfMostRecentIconUrlChange", + base::FEATURE_DISABLED_BY_DEFAULT}; } // namespace favicon
diff --git a/components/favicon/core/features.h b/components/favicon/core/features.h index db1fa24..88a5c71 100644 --- a/components/favicon/core/features.h +++ b/components/favicon/core/features.h
@@ -13,6 +13,7 @@ extern const base::Feature kAllowPropagationOfFaviconCacheHits; extern const base::Feature kEnableHistoryFaviconsGoogleServerQuery; +extern const base::Feature kNotifySessionsOfMostRecentIconUrlChange; } // namespace favicon
diff --git a/components/gwp_asan/client/sampling_malloc_shims_unittest.cc b/components/gwp_asan/client/sampling_malloc_shims_unittest.cc index 7dd943e..915ecf0 100644 --- a/components/gwp_asan/client/sampling_malloc_shims_unittest.cc +++ b/components/gwp_asan/client/sampling_malloc_shims_unittest.cc
@@ -243,6 +243,8 @@ } #endif // !defined(COMPONENT_BUILD) +// malloc_usable_size() is not currently used/shimmed on Android. +#if !defined(OS_ANDROID) MULTIPROCESS_TEST_MAIN_WITH_SETUP( GetSizeEstimate, SamplingMallocShimsTest::multiprocessTestSetup) { @@ -264,6 +266,7 @@ TEST_F(SamplingMallocShimsTest, GetSizeEstimate) { runTest("GetSizeEstimate"); } +#endif #if defined(OS_WIN) MULTIPROCESS_TEST_MAIN_WITH_SETUP(
diff --git a/components/gwp_asan/client/sampling_state.h b/components/gwp_asan/client/sampling_state.h index 933ed3f..1728a7a 100644 --- a/components/gwp_asan/client/sampling_state.h +++ b/components/gwp_asan/client/sampling_state.h
@@ -11,7 +11,8 @@ #include "base/rand_util.h" #include "build/build_config.h" -#if defined(OS_MACOSX) +#if defined(OS_MACOSX) || defined(OS_ANDROID) +#define USE_PTHREAD_TLS #include <pthread.h> #endif @@ -37,7 +38,7 @@ DCHECK_GT(sampling_frequency, 0U); sampling_frequency_ = sampling_frequency; -#if defined(OS_MACOSX) +#if defined(USE_PTHREAD_TLS) pthread_key_create(&tls_key_, nullptr); #endif } @@ -71,15 +72,15 @@ return next_sample; } -#if !defined(OS_MACOSX) +#if !defined(USE_PTHREAD_TLS) ALWAYS_INLINE size_t GetCounter() { return tls_counter_; } ALWAYS_INLINE void SetCounter(size_t value) { tls_counter_ = value; } static thread_local size_t tls_counter_; #else - // On macOS, the first use of a thread_local variable on a new thread will - // cause a malloc(), causing infinite recursion. Instead, use pthread TLS to - // store the counter. + // On macOS and Android (before Q), the first use of a thread_local variable + // on a new thread will cause an allocation, leading to infinite recursion. + // Instead, use pthread TLS to store the counter. // // TODO: This is not necessary for PartitionAlloc and likely slower, refactor // SamplingState to be able to use pthread TLS for malloc() and thread_local @@ -102,7 +103,7 @@ size_t increment_ = 0; }; -#if !defined(OS_MACOSX) +#if !defined(USE_PTHREAD_TLS) template <ParentAllocator PA> thread_local size_t SamplingState<PA>::tls_counter_ = 0; #endif
diff --git a/components/signin/core/browser/fake_profile_oauth2_token_service.cc b/components/signin/core/browser/fake_profile_oauth2_token_service.cc index a5a0ce1..e1898681 100644 --- a/components/signin/core/browser/fake_profile_oauth2_token_service.cc +++ b/components/signin/core/browser/fake_profile_oauth2_token_service.cc
@@ -128,7 +128,7 @@ bool scope_matches = all_scopes || it->scopes == scope; bool account_matches = account_id.empty() || account_id == it->account_id; if (account_matches && scope_matches) { - for (auto& diagnostic_observer : GetDiagnicsObservers()) { + for (auto& diagnostic_observer : GetAccessTokenDiagnosticsObservers()) { diagnostic_observer.OnFetchAccessTokenComplete( account_id, it->request->GetConsumerId(), scope, error, base::Time());
diff --git a/components/signin/core/browser/gaia_cookie_manager_service.cc b/components/signin/core/browser/gaia_cookie_manager_service.cc index f684359..fe84d14 100644 --- a/components/signin/core/browser/gaia_cookie_manager_service.cc +++ b/components/signin/core/browser/gaia_cookie_manager_service.cc
@@ -23,6 +23,7 @@ #include "base/values.h" #include "build/build_config.h" #include "components/signin/core/browser/account_tracker_service.h" +#include "components/signin/core/browser/oauth_multilogin_helper.h" #include "components/signin/core/browser/set_accounts_in_cookie_result.h" #include "components/signin/core/browser/signin_metrics.h" #include "components/signin/core/browser/ubertoken_fetcher_impl.h" @@ -61,6 +62,9 @@ namespace { +// The maximum number of retries for a fetcher used in this class. +constexpr int kMaxFetcherRetries = 8; + // In case of an error while fetching using the GaiaAuthFetcher or // SimpleURLLoader, retry with exponential backoff. Try up to 7 times within 15 // minutes. @@ -797,8 +801,7 @@ const std::string account_id = requests_.front().GetAccountID(); VLOG(1) << "Failed MergeSession" << " account=" << account_id << " error=" << error.ToString(); - if (++fetcher_retries_ < signin::kMaxFetcherRetries && - error.IsTransientError()) { + if (++fetcher_retries_ < kMaxFetcherRetries && error.IsTransientError()) { fetcher_backoff_.InformOfRequest(false); UMA_HISTOGRAM_ENUMERATION("OAuth2Login.MergeSessionRetry", error.state(), GoogleServiceAuthError::NUM_STATES); @@ -866,8 +869,7 @@ GaiaCookieRequestType::LIST_ACCOUNTS); RecordListAccountsRetryResult(error, fetcher_retries_); - if (++fetcher_retries_ < signin::kMaxFetcherRetries && - error.IsTransientError()) { + if (++fetcher_retries_ < kMaxFetcherRetries && error.IsTransientError()) { fetcher_backoff_.InformOfRequest(false); UMA_HISTOGRAM_ENUMERATION("Signin.ListAccountsRetry", error.state(), GoogleServiceAuthError::NUM_STATES); @@ -906,7 +908,7 @@ VLOG(1) << "GaiaCookieManagerService::OnLogOutFailure"; RecordLogoutRequestState(LogoutRequestState::kFailed); - if (++fetcher_retries_ < signin::kMaxFetcherRetries) { + if (++fetcher_retries_ < kMaxFetcherRetries) { fetcher_backoff_.InformOfRequest(false); fetcher_timer_.Start( FROM_HERE, fetcher_backoff_.GetTimeUntilRelease(), @@ -991,13 +993,8 @@ return; } - // TODO(triploblastic): remove this block in the second part of the fix. - std::vector<std::string> account_ids; - for (const auto& id : requests_.front().accounts()) - account_ids.push_back(id.first.id); - oauth_multilogin_helper_ = std::make_unique<signin::OAuthMultiloginHelper>( - signin_client_, token_service_, account_ids, + signin_client_, token_service_, requests_.front().accounts(), external_cc_result_fetcher_.GetExternalCcResult(), base::BindOnce(&GaiaCookieManagerService::OnSetAccountsFinished, weak_ptr_factory_.GetWeakPtr()));
diff --git a/components/signin/core/browser/gaia_cookie_manager_service.h b/components/signin/core/browser/gaia_cookie_manager_service.h index 4dbf82e..2cadfb1 100644 --- a/components/signin/core/browser/gaia_cookie_manager_service.h +++ b/components/signin/core/browser/gaia_cookie_manager_service.h
@@ -18,7 +18,6 @@ #include "base/memory/weak_ptr.h" #include "base/observer_list.h" #include "base/timer/timer.h" -#include "components/signin/core/browser/oauth_multilogin_helper.h" #include "components/signin/core/browser/signin_client.h" #include "google_apis/gaia/gaia_auth_consumer.h" #include "google_apis/gaia/gaia_auth_fetcher.h" @@ -39,12 +38,10 @@ namespace signin { +class OAuthMultiloginHelper; class UbertokenFetcherImpl; enum class SetAccountsInCookieResult; -// The maximum number of retries for a fetcher used in this class. -constexpr int kMaxFetcherRetries = 8; - struct MultiloginParameters { MultiloginParameters(gaia::MultiloginMode mode, const std::vector<std::string>& accounts_to_send);
diff --git a/components/signin/core/browser/oauth_multilogin_helper.cc b/components/signin/core/browser/oauth_multilogin_helper.cc index ab38dc09..a779cf4 100644 --- a/components/signin/core/browser/oauth_multilogin_helper.cc +++ b/components/signin/core/browser/oauth_multilogin_helper.cc
@@ -25,15 +25,26 @@ constexpr int kMaxFetcherRetries = 3; std::string FindTokenForAccount( - const std::vector<GaiaAuthFetcher::MultiloginTokenIDPair>& token_id_pairs, - const std::string& account_id) { - for (auto it = token_id_pairs.cbegin(); it != token_id_pairs.cend(); ++it) { - if (account_id == it->gaia_id_) - return it->token_; + const std::vector<GaiaAuthFetcher::MultiloginTokenIDPair>& + gaia_id_token_pairs, + const std::string& gaia_id) { + for (const auto& gaia_id_token : gaia_id_token_pairs) { + if (gaia_id == gaia_id_token.gaia_id_) + return gaia_id_token.token_; } return std::string(); } +CoreAccountId FindAccountIdForGaiaId( + const std::vector<GaiaCookieManagerService::AccountIdGaiaIdPair>& accounts, + const std::string& gaia_id) { + for (const auto& account : accounts) { + if (gaia_id == account.second) + return account.first; + } + return CoreAccountId(); +} + } // namespace namespace signin { @@ -41,25 +52,25 @@ OAuthMultiloginHelper::OAuthMultiloginHelper( SigninClient* signin_client, OAuth2TokenService* token_service, - const std::vector<std::string>& account_ids, + const std::vector<GaiaCookieManagerService::AccountIdGaiaIdPair>& accounts, const std::string& external_cc_result, base::OnceCallback<void(signin::SetAccountsInCookieResult)> callback) : signin_client_(signin_client), token_service_(token_service), - account_ids_(account_ids), + accounts_(accounts), external_cc_result_(external_cc_result), callback_(std::move(callback)), weak_ptr_factory_(this) { DCHECK(signin_client_); DCHECK(token_service_); - DCHECK(!account_ids_.empty()); + DCHECK(!accounts_.empty()); DCHECK(callback_); #ifndef NDEBUG // Check that there is no duplicate accounts. - std::set<std::string> accounts_no_duplicates(account_ids_.begin(), - account_ids_.end()); - DCHECK_EQ(account_ids_.size(), accounts_no_duplicates.size()); + std::set<GaiaCookieManagerService::AccountIdGaiaIdPair> + accounts_no_duplicates(accounts_.begin(), accounts_.end()); + DCHECK_EQ(accounts_.size(), accounts_no_duplicates.size()); #endif StartFetchingTokens(); @@ -69,9 +80,13 @@ void OAuthMultiloginHelper::StartFetchingTokens() { DCHECK(!token_fetcher_); - DCHECK(token_id_pairs_.empty()); + DCHECK(gaia_id_token_pairs_.empty()); + std::vector<CoreAccountId> account_ids; + for (const auto& account : accounts_) + account_ids.push_back(account.first); + token_fetcher_ = std::make_unique<signin::OAuthMultiloginTokenFetcher>( - signin_client_, token_service_, account_ids_, + signin_client_, token_service_, account_ids, base::BindOnce(&OAuthMultiloginHelper::OnAccessTokensSuccess, base::Unretained(this)), base::BindOnce(&OAuthMultiloginHelper::OnAccessTokensFailure, @@ -79,10 +94,17 @@ } void OAuthMultiloginHelper::OnAccessTokensSuccess( - const std::vector<GaiaAuthFetcher::MultiloginTokenIDPair>& token_id_pairs) { - DCHECK(token_id_pairs_.empty()); - token_id_pairs_ = token_id_pairs; - DCHECK_EQ(token_id_pairs_.size(), account_ids_.size()); + const std::vector<OAuthMultiloginTokenFetcher::AccountIdTokenPair>& + account_token_pairs) { + DCHECK(gaia_id_token_pairs_.empty()); + for (size_t index = 0; index < accounts_.size(); index++) { + // OAuthMultiloginTokenFetcher should return the tokens in the same order + // as the account_ids that was passed to it. + DCHECK_EQ(accounts_[index].first, account_token_pairs[index].account_id); + gaia_id_token_pairs_.emplace_back(accounts_[index].second, + account_token_pairs[index].token); + } + DCHECK_EQ(gaia_id_token_pairs_.size(), accounts_.size()); token_fetcher_.reset(); signin_client_->DelayNetworkCall( @@ -101,35 +123,38 @@ } void OAuthMultiloginHelper::StartFetchingMultiLogin() { - DCHECK_EQ(token_id_pairs_.size(), account_ids_.size()); + DCHECK_EQ(gaia_id_token_pairs_.size(), accounts_.size()); gaia_auth_fetcher_ = signin_client_->CreateGaiaAuthFetcher(this, gaia::GaiaSource::kChrome); - gaia_auth_fetcher_->StartOAuthMultilogin(token_id_pairs_, + gaia_auth_fetcher_->StartOAuthMultilogin(gaia_id_token_pairs_, external_cc_result_); } void OAuthMultiloginHelper::OnOAuthMultiloginFinished( const OAuthMultiloginResult& result) { if (result.status() == OAuthMultiloginResponseStatus::kOk) { + std::vector<std::string> account_ids; + for (const auto& account : accounts_) + account_ids.push_back(account.first.id); VLOG(1) << "Multilogin successful accounts=" - << base::JoinString(account_ids_, " "); + << base::JoinString(account_ids, " "); StartSettingCookies(result); return; } // If Gaia responded with kInvalidTokens, we have to mark tokens as invalid. if (result.status() == OAuthMultiloginResponseStatus::kInvalidTokens) { - for (const std::string& failed_account_id : result.failed_accounts()) { + for (const std::string& failed_gaia_id : result.failed_gaia_ids()) { std::string failed_token = - FindTokenForAccount(token_id_pairs_, failed_account_id); + FindTokenForAccount(gaia_id_token_pairs_, failed_gaia_id); if (failed_token.empty()) { LOG(ERROR) << "Unexpected failed token for account not present in request: " - << failed_account_id; + << failed_gaia_id; continue; } - token_service_->InvalidateTokenForMultilogin(failed_account_id, - failed_token); + token_service_->InvalidateTokenForMultilogin( + FindAccountIdForGaiaId(accounts_, failed_gaia_id), failed_token); } } @@ -138,7 +163,7 @@ result.status() == OAuthMultiloginResponseStatus::kRetry; if (is_transient_error && ++fetcher_retries_ < kMaxFetcherRetries) { - token_id_pairs_.clear(); + gaia_id_token_pairs_.clear(); StartFetchingTokens(); return; }
diff --git a/components/signin/core/browser/oauth_multilogin_helper.h b/components/signin/core/browser/oauth_multilogin_helper.h index 69064a9..176fb0e 100644 --- a/components/signin/core/browser/oauth_multilogin_helper.h +++ b/components/signin/core/browser/oauth_multilogin_helper.h
@@ -13,6 +13,9 @@ #include "base/callback_forward.h" #include "base/macros.h" #include "base/memory/weak_ptr.h" +#include "components/signin/core/browser/gaia_cookie_manager_service.h" +#include "components/signin/core/browser/oauth_multilogin_token_fetcher.h" +#include "google_apis/gaia/core_account_id.h" #include "google_apis/gaia/gaia_auth_consumer.h" #include "google_apis/gaia/gaia_auth_fetcher.h" #include "services/network/public/mojom/cookie_manager.mojom.h" @@ -24,7 +27,6 @@ namespace signin { -class OAuthMultiloginTokenFetcher; enum class SetAccountsInCookieResult; // This is a helper class that drives the OAuth multilogin process. @@ -38,7 +40,8 @@ OAuthMultiloginHelper( SigninClient* signin_client, OAuth2TokenService* token_service, - const std::vector<std::string>& account_ids, + const std::vector<GaiaCookieManagerService::AccountIdGaiaIdPair>& + accounts, const std::string& external_cc_result, base::OnceCallback<void(signin::SetAccountsInCookieResult)> callback); @@ -50,8 +53,8 @@ // Callbacks for OAuthMultiloginTokenFetcher. void OnAccessTokensSuccess( - const std::vector<GaiaAuthFetcher::MultiloginTokenIDPair>& - token_id_pairs); + const std::vector<OAuthMultiloginTokenFetcher::AccountIdTokenPair>& + account_token_pairs); void OnAccessTokensFailure(const GoogleServiceAuthError& error); // Actual call to the multilogin endpoint. @@ -74,11 +77,11 @@ int fetcher_retries_ = 0; // Account ids to set in the cookie. - const std::vector<std::string> account_ids_; + const std::vector<GaiaCookieManagerService::AccountIdGaiaIdPair> accounts_; // See GaiaCookieManagerService::ExternalCcResultFetcher for details. const std::string external_cc_result_; // Access tokens, in the same order as the account ids. - std::vector<GaiaAuthFetcher::MultiloginTokenIDPair> token_id_pairs_; + std::vector<GaiaAuthFetcher::MultiloginTokenIDPair> gaia_id_token_pairs_; base::OnceCallback<void(signin::SetAccountsInCookieResult)> callback_; std::unique_ptr<GaiaAuthFetcher> gaia_auth_fetcher_;
diff --git a/components/signin/core/browser/oauth_multilogin_helper_unittest.cc b/components/signin/core/browser/oauth_multilogin_helper_unittest.cc index e76e385..7e7642e 100644 --- a/components/signin/core/browser/oauth_multilogin_helper_unittest.cc +++ b/components/signin/core/browser/oauth_multilogin_helper_unittest.cc
@@ -23,6 +23,8 @@ const CoreAccountId kAccountId("account_id_1"); const CoreAccountId kAccountId2("account_id_2"); +const char kGaiaId[] = "gaia_id_1"; +const char kGaiaId2[] = "gaia_id_2"; const char kAccessToken[] = "access_token_1"; const char kAccessToken2[] = "access_token_2"; @@ -119,8 +121,8 @@ { "status": "INVALID_TOKENS", "failed_accounts": [ - { "obfuscated_id": "account_id_1", "status": "RECOVERABLE" }, - { "obfuscated_id": "account_id_2", "status": "OK" } + { "obfuscated_id": "gaia_id_1", "status": "RECOVERABLE" }, + { "obfuscated_id": "gaia_id_2", "status": "OK" } ] } )"; @@ -169,17 +171,19 @@ ~OAuthMultiloginHelperTest() override = default; std::unique_ptr<OAuthMultiloginHelper> CreateHelper( - const std::vector<std::string> account_ids) { + const std::vector<GaiaCookieManagerService::AccountIdGaiaIdPair> + accounts) { return std::make_unique<OAuthMultiloginHelper>( - &test_signin_client_, token_service(), account_ids, std::string(), + &test_signin_client_, token_service(), accounts, std::string(), base::BindOnce(&OAuthMultiloginHelperTest::OnOAuthMultiloginFinished, base::Unretained(this))); } std::unique_ptr<OAuthMultiloginHelper> CreateHelperWithExternalCcResult( - const std::vector<std::string> account_ids) { + const std::vector<GaiaCookieManagerService::AccountIdGaiaIdPair> + accounts) { return std::make_unique<OAuthMultiloginHelper>( - &test_signin_client_, token_service(), account_ids, kExternalCcResult, + &test_signin_client_, token_service(), accounts, kExternalCcResult, base::BindOnce(&OAuthMultiloginHelperTest::OnOAuthMultiloginFinished, base::Unretained(this))); } @@ -221,7 +225,8 @@ // Everything succeeds. TEST_F(OAuthMultiloginHelperTest, Success) { token_service()->AddAccount(kAccountId); - std::unique_ptr<OAuthMultiloginHelper> helper = CreateHelper({kAccountId}); + std::unique_ptr<OAuthMultiloginHelper> helper = + CreateHelper({{kAccountId, kGaiaId}}); // Configure mock cookie manager: // - check that the cookie is the expected one @@ -249,7 +254,8 @@ // Multiple cookies in the multilogin response. TEST_F(OAuthMultiloginHelperTest, MultipleCookies) { token_service()->AddAccount(kAccountId); - std::unique_ptr<OAuthMultiloginHelper> helper = CreateHelper({kAccountId}); + std::unique_ptr<OAuthMultiloginHelper> helper = + CreateHelper({{kAccountId, kGaiaId}}); // Configure mock cookie manager: // - check that the cookie is the expected one @@ -284,7 +290,7 @@ TEST_F(OAuthMultiloginHelperTest, SuccessWithExternalCcResult) { token_service()->AddAccount(kAccountId); std::unique_ptr<OAuthMultiloginHelper> helper = - CreateHelperWithExternalCcResult({kAccountId}); + CreateHelperWithExternalCcResult({{kAccountId, kGaiaId}}); // Configure mock cookie manager: // - check that the cookie is the expected one @@ -320,7 +326,8 @@ // Failure to get the access token. TEST_F(OAuthMultiloginHelperTest, OneAccountAccessTokenFailure) { token_service()->AddAccount(kAccountId); - std::unique_ptr<OAuthMultiloginHelper> helper = CreateHelper({kAccountId}); + std::unique_ptr<OAuthMultiloginHelper> helper = + CreateHelper({{kAccountId, kGaiaId}}); token_service()->IssueErrorForAllPendingRequestsForAccount( kAccountId, @@ -332,7 +339,8 @@ // Retry on transient errors in the multilogin call. TEST_F(OAuthMultiloginHelperTest, OneAccountTransientMultiloginError) { token_service()->AddAccount(kAccountId); - std::unique_ptr<OAuthMultiloginHelper> helper = CreateHelper({kAccountId}); + std::unique_ptr<OAuthMultiloginHelper> helper = + CreateHelper({{kAccountId, kGaiaId}}); // Configure mock cookie manager: // - check that the cookie is the expected one @@ -368,7 +376,8 @@ TEST_F(OAuthMultiloginHelperTest, OneAccountTransientMultiloginErrorMaxRetries) { token_service()->AddAccount(kAccountId); - std::unique_ptr<OAuthMultiloginHelper> helper = CreateHelper({kAccountId}); + std::unique_ptr<OAuthMultiloginHelper> helper = + CreateHelper({{kAccountId, kGaiaId}}); // Issue access token. OAuth2AccessTokenConsumer::TokenResponse success_response; @@ -391,7 +400,8 @@ // Persistent error in the multilogin call. TEST_F(OAuthMultiloginHelperTest, OneAccountPersistentMultiloginError) { token_service()->AddAccount(kAccountId); - std::unique_ptr<OAuthMultiloginHelper> helper = CreateHelper({kAccountId}); + std::unique_ptr<OAuthMultiloginHelper> helper = + CreateHelper({{kAccountId, kGaiaId}}); // Issue access token. OAuth2AccessTokenConsumer::TokenResponse success_response; @@ -412,7 +422,7 @@ token_service()->AddAccount(kAccountId); token_service()->AddAccount(kAccountId2); std::unique_ptr<OAuthMultiloginHelper> helper = - CreateHelper({kAccountId, kAccountId2}); + CreateHelper({{kAccountId, kGaiaId}, {kAccountId2, kGaiaId2}}); // Configure mock cookie manager: // - check that the cookie is the expected one @@ -460,7 +470,7 @@ token_service()->AddAccount(kAccountId); token_service()->AddAccount(kAccountId2); std::unique_ptr<OAuthMultiloginHelper> helper = - CreateHelper({kAccountId, kAccountId2}); + CreateHelper({{kAccountId, kGaiaId}, {kAccountId2, kGaiaId2}}); // The failed access token should be invalidated. EXPECT_CALL(*token_service(),
diff --git a/components/signin/core/browser/oauth_multilogin_token_fetcher.cc b/components/signin/core/browser/oauth_multilogin_token_fetcher.cc index d01a50aa..15782fd9 100644 --- a/components/signin/core/browser/oauth_multilogin_token_fetcher.cc +++ b/components/signin/core/browser/oauth_multilogin_token_fetcher.cc
@@ -28,7 +28,7 @@ OAuthMultiloginTokenFetcher::OAuthMultiloginTokenFetcher( SigninClient* signin_client, OAuth2TokenService* token_service, - const std::vector<std::string>& account_ids, + const std::vector<CoreAccountId>& account_ids, SuccessCallback success_callback, FailureCallback failure_callback) : OAuth2TokenService::Consumer("oauth_multilogin_token_fetcher"), @@ -46,19 +46,19 @@ #ifndef NDEBUG // Check that there is no duplicate accounts. - std::set<std::string> accounts_no_duplicates(account_ids_.begin(), - account_ids_.end()); + std::set<CoreAccountId> accounts_no_duplicates(account_ids_.begin(), + account_ids_.end()); DCHECK_EQ(account_ids_.size(), accounts_no_duplicates.size()); #endif - for (const std::string& account_id : account_ids_) + for (const CoreAccountId& account_id : account_ids_) StartFetchingToken(account_id); } OAuthMultiloginTokenFetcher::~OAuthMultiloginTokenFetcher() = default; void OAuthMultiloginTokenFetcher::StartFetchingToken( - const std::string& account_id) { + const CoreAccountId& account_id) { DCHECK(!account_id.empty()); token_requests_.push_back( token_service_->StartRequestForMultilogin(account_id, this)); @@ -67,7 +67,7 @@ void OAuthMultiloginTokenFetcher::OnGetTokenSuccess( const OAuth2TokenService::Request* request, const OAuth2AccessTokenConsumer::TokenResponse& token_response) { - std::string account_id = request->GetAccountId(); + CoreAccountId account_id = request->GetAccountId(); DCHECK(account_ids_.cend() != std::find(account_ids_.cbegin(), account_ids_.cend(), account_id)); @@ -82,16 +82,14 @@ DCHECK(inserted.second); // If this fires, we have a duplicate account. if (access_tokens_.size() == account_ids_.size()) { - std::vector<GaiaAuthFetcher::MultiloginTokenIDPair> token_id_pairs; + std::vector<AccountIdTokenPair> account_token_pairs; for (const auto& id : account_ids_) { const auto& it = access_tokens_.find(id); DCHECK(!it->second.empty()); - // TODO(https://crbug.com/956503): Don't assume that the account ID is the - // Gaia ID. - token_id_pairs.emplace_back(id, it->second); + account_token_pairs.emplace_back(id, it->second); } RecordGetAccessTokenFinished(GoogleServiceAuthError::AuthErrorNone()); - std::move(success_callback_).Run(token_id_pairs); + std::move(success_callback_).Run(account_token_pairs); // Do not add anything below this line, as this may be deleted. } } @@ -99,7 +97,7 @@ void OAuthMultiloginTokenFetcher::OnGetTokenFailure( const OAuth2TokenService::Request* request, const GoogleServiceAuthError& error) { - std::string account_id = request->GetAccountId(); + CoreAccountId account_id = request->GetAccountId(); VLOG(1) << "Failed to retrieve accesstoken account=" << account_id << " error=" << error.ToString(); if (error.IsTransientError() &&
diff --git a/components/signin/core/browser/oauth_multilogin_token_fetcher.h b/components/signin/core/browser/oauth_multilogin_token_fetcher.h index 168ba88..5831c00 100644 --- a/components/signin/core/browser/oauth_multilogin_token_fetcher.h +++ b/components/signin/core/browser/oauth_multilogin_token_fetcher.h
@@ -27,21 +27,29 @@ // It is safe to delete this object from within the callbacks. class OAuthMultiloginTokenFetcher : public OAuth2TokenService::Consumer { public: - using SuccessCallback = base::OnceCallback<void( - const std::vector<GaiaAuthFetcher::MultiloginTokenIDPair>&)>; + struct AccountIdTokenPair { + CoreAccountId account_id; + std::string token; + + AccountIdTokenPair(const CoreAccountId& account_id, + const std::string& token) + : account_id(account_id), token(token) {} + }; + using SuccessCallback = + base::OnceCallback<void(const std::vector<AccountIdTokenPair>&)>; using FailureCallback = base::OnceCallback<void(const GoogleServiceAuthError&)>; OAuthMultiloginTokenFetcher(SigninClient* signin_client, OAuth2TokenService* token_service, - const std::vector<std::string>& account_ids, + const std::vector<CoreAccountId>& account_ids, SuccessCallback success_callback, FailureCallback failure_callback); ~OAuthMultiloginTokenFetcher() override; private: - void StartFetchingToken(const std::string& account_id); + void StartFetchingToken(const CoreAccountId& account_id); // Overridden from OAuth2TokenService::Consumer. void OnGetTokenSuccess( @@ -55,14 +63,14 @@ SigninClient* signin_client_; OAuth2TokenService* token_service_; - const std::vector<std::string> account_ids_; + const std::vector<CoreAccountId> account_ids_; SuccessCallback success_callback_; FailureCallback failure_callback_; std::vector<std::unique_ptr<OAuth2TokenService::Request>> token_requests_; - std::map<std::string, std::string> access_tokens_; - std::set<std::string> retried_requests_; // Requests are retried once. + std::map<CoreAccountId, std::string> access_tokens_; + std::set<CoreAccountId> retried_requests_; // Requests are retried once. base::WeakPtrFactory<OAuthMultiloginTokenFetcher> weak_ptr_factory_;
diff --git a/components/signin/core/browser/oauth_multilogin_token_fetcher_unittest.cc b/components/signin/core/browser/oauth_multilogin_token_fetcher_unittest.cc index a40df52..d3bd9a3 100644 --- a/components/signin/core/browser/oauth_multilogin_token_fetcher_unittest.cc +++ b/components/signin/core/browser/oauth_multilogin_token_fetcher_unittest.cc
@@ -21,7 +21,7 @@ namespace { -const char kAccountId[] = "account_id"; +const CoreAccountId kAccountId("account_id"); const char kAccessToken[] = "access_token"; // Status of the token fetch. @@ -36,7 +36,7 @@ ~OAuthMultiloginTokenFetcherTest() override = default; std::unique_ptr<OAuthMultiloginTokenFetcher> CreateFetcher( - const std::vector<std::string> account_ids) { + const std::vector<CoreAccountId> account_ids) { return std::make_unique<OAuthMultiloginTokenFetcher>( &test_signin_client_, &token_service_, account_ids, base::BindOnce(&OAuthMultiloginTokenFetcherTest::OnSuccess, @@ -55,12 +55,13 @@ protected: // Success callback for OAuthMultiloginTokenFetcher. - void OnSuccess(const std::vector<GaiaAuthFetcher::MultiloginTokenIDPair>& - token_id_pairs) { + void OnSuccess( + const std::vector<OAuthMultiloginTokenFetcher::AccountIdTokenPair>& + account_id_token_pairs) { DCHECK(!success_callback_called_); - DCHECK(token_id_pairs_.empty()); + DCHECK(account_id_token_pairs_.empty()); success_callback_called_ = true; - token_id_pairs_ = token_id_pairs; + account_id_token_pairs_ = account_id_token_pairs; } // Failure callback for OAuthMultiloginTokenFetcher. @@ -75,7 +76,8 @@ bool success_callback_called_ = false; bool failure_callback_called_ = false; GoogleServiceAuthError error_; - std::vector<GaiaAuthFetcher::MultiloginTokenIDPair> token_id_pairs_; + std::vector<OAuthMultiloginTokenFetcher::AccountIdTokenPair> + account_id_token_pairs_; TestSigninClient test_signin_client_; FakeOAuth2TokenService token_service_; @@ -91,9 +93,9 @@ token_service_.IssueAllTokensForAccount(kAccountId, success_response); EXPECT_EQ(FetchStatus::kSuccess, GetFetchStatus()); // Check result. - EXPECT_EQ(1u, token_id_pairs_.size()); - EXPECT_EQ(kAccountId, token_id_pairs_[0].gaia_id_); - EXPECT_EQ(kAccessToken, token_id_pairs_[0].token_); + EXPECT_EQ(1u, account_id_token_pairs_.size()); + EXPECT_EQ(kAccountId, account_id_token_pairs_[0].account_id); + EXPECT_EQ(kAccessToken, account_id_token_pairs_[0].token); } TEST_F(OAuthMultiloginTokenFetcherTest, OneAccountPersistentError) { @@ -123,9 +125,9 @@ token_service_.IssueAllTokensForAccount(kAccountId, success_response); EXPECT_EQ(FetchStatus::kSuccess, GetFetchStatus()); // Check result. - EXPECT_EQ(1u, token_id_pairs_.size()); - EXPECT_EQ(kAccountId, token_id_pairs_[0].gaia_id_); - EXPECT_EQ(kAccessToken, token_id_pairs_[0].token_); + EXPECT_EQ(1u, account_id_token_pairs_.size()); + EXPECT_EQ(kAccountId, account_id_token_pairs_[0].account_id); + EXPECT_EQ(kAccessToken, account_id_token_pairs_[0].token); } TEST_F(OAuthMultiloginTokenFetcherTest, OneAccountTransientErrorMaxRetries) { @@ -147,76 +149,85 @@ // The flow succeeds even if requests are received out of order. TEST_F(OAuthMultiloginTokenFetcherTest, MultipleAccountsSuccess) { - token_service_.AddAccount("account_1"); - token_service_.AddAccount("account_2"); - token_service_.AddAccount("account_3"); + const CoreAccountId account_1("account_1"); + const CoreAccountId account_2("account_2"); + const CoreAccountId account_3("account_3"); + token_service_.AddAccount(account_1); + token_service_.AddAccount(account_2); + token_service_.AddAccount(account_3); std::unique_ptr<OAuthMultiloginTokenFetcher> fetcher = - CreateFetcher({"account_1", "account_2", "account_3"}); + CreateFetcher({account_1, account_2, account_3}); OAuth2AccessTokenConsumer::TokenResponse success_response; success_response.access_token = "token_3"; - token_service_.IssueAllTokensForAccount("account_3", success_response); + token_service_.IssueAllTokensForAccount(account_3, success_response); success_response.access_token = "token_1"; - token_service_.IssueAllTokensForAccount("account_1", success_response); + token_service_.IssueAllTokensForAccount(account_1, success_response); EXPECT_EQ(FetchStatus::kPending, GetFetchStatus()); success_response.access_token = "token_2"; - token_service_.IssueAllTokensForAccount("account_2", success_response); + token_service_.IssueAllTokensForAccount(account_2, success_response); EXPECT_EQ(FetchStatus::kSuccess, GetFetchStatus()); // Check result. - EXPECT_EQ(3u, token_id_pairs_.size()); - EXPECT_EQ("account_1", token_id_pairs_[0].gaia_id_); - EXPECT_EQ("account_2", token_id_pairs_[1].gaia_id_); - EXPECT_EQ("account_3", token_id_pairs_[2].gaia_id_); - EXPECT_EQ("token_1", token_id_pairs_[0].token_); - EXPECT_EQ("token_2", token_id_pairs_[1].token_); - EXPECT_EQ("token_3", token_id_pairs_[2].token_); + EXPECT_EQ(3u, account_id_token_pairs_.size()); + EXPECT_EQ(account_1, account_id_token_pairs_[0].account_id); + EXPECT_EQ(account_2, account_id_token_pairs_[1].account_id); + EXPECT_EQ(account_3, account_id_token_pairs_[2].account_id); + EXPECT_EQ("token_1", account_id_token_pairs_[0].token); + EXPECT_EQ("token_2", account_id_token_pairs_[1].token); + EXPECT_EQ("token_3", account_id_token_pairs_[2].token); } TEST_F(OAuthMultiloginTokenFetcherTest, MultipleAccountsTransientError) { - token_service_.AddAccount("account_1"); - token_service_.AddAccount("account_2"); - token_service_.AddAccount("account_3"); + const CoreAccountId account_1("account_1"); + const CoreAccountId account_2("account_2"); + const CoreAccountId account_3("account_3"); + token_service_.AddAccount(account_1); + token_service_.AddAccount(account_2); + token_service_.AddAccount(account_3); std::unique_ptr<OAuthMultiloginTokenFetcher> fetcher = - CreateFetcher({"account_1", "account_2", "account_3"}); + CreateFetcher({account_1, account_2, account_3}); // Connection failures will be retried. token_service_.IssueErrorForAllPendingRequestsForAccount( - "account_1", + account_1, GoogleServiceAuthError(GoogleServiceAuthError::CONNECTION_FAILED)); token_service_.IssueErrorForAllPendingRequestsForAccount( - "account_2", + account_2, GoogleServiceAuthError(GoogleServiceAuthError::CONNECTION_FAILED)); token_service_.IssueErrorForAllPendingRequestsForAccount( - "account_3", + account_3, GoogleServiceAuthError(GoogleServiceAuthError::CONNECTION_FAILED)); // Success on retry. OAuth2AccessTokenConsumer::TokenResponse success_response; success_response.access_token = kAccessToken; success_response.access_token = "token_1"; - token_service_.IssueAllTokensForAccount("account_1", success_response); + token_service_.IssueAllTokensForAccount(account_1, success_response); success_response.access_token = "token_2"; - token_service_.IssueAllTokensForAccount("account_2", success_response); + token_service_.IssueAllTokensForAccount(account_2, success_response); EXPECT_EQ(FetchStatus::kPending, GetFetchStatus()); success_response.access_token = "token_3"; - token_service_.IssueAllTokensForAccount("account_3", success_response); + token_service_.IssueAllTokensForAccount(account_3, success_response); EXPECT_EQ(FetchStatus::kSuccess, GetFetchStatus()); // Check result. - EXPECT_EQ(3u, token_id_pairs_.size()); - EXPECT_EQ("account_1", token_id_pairs_[0].gaia_id_); - EXPECT_EQ("account_2", token_id_pairs_[1].gaia_id_); - EXPECT_EQ("account_3", token_id_pairs_[2].gaia_id_); - EXPECT_EQ("token_1", token_id_pairs_[0].token_); - EXPECT_EQ("token_2", token_id_pairs_[1].token_); - EXPECT_EQ("token_3", token_id_pairs_[2].token_); + EXPECT_EQ(3u, account_id_token_pairs_.size()); + EXPECT_EQ(account_1, account_id_token_pairs_[0].account_id); + EXPECT_EQ(account_2, account_id_token_pairs_[1].account_id); + EXPECT_EQ(account_3, account_id_token_pairs_[2].account_id); + EXPECT_EQ("token_1", account_id_token_pairs_[0].token); + EXPECT_EQ("token_2", account_id_token_pairs_[1].token); + EXPECT_EQ("token_3", account_id_token_pairs_[2].token); } TEST_F(OAuthMultiloginTokenFetcherTest, MultipleAccountsPersistentError) { - token_service_.AddAccount("account_1"); - token_service_.AddAccount("account_2"); - token_service_.AddAccount("account_3"); + const CoreAccountId account_1("account_1"); + const CoreAccountId account_2("account_2"); + const CoreAccountId account_3("account_3"); + token_service_.AddAccount(account_1); + token_service_.AddAccount(account_2); + token_service_.AddAccount(account_3); std::unique_ptr<OAuthMultiloginTokenFetcher> fetcher = - CreateFetcher({"account_1", "account_2", "account_3"}); + CreateFetcher({account_1, account_2, account_3}); EXPECT_EQ(FetchStatus::kPending, GetFetchStatus()); token_service_.IssueErrorForAllPendingRequestsForAccount( - "account_2", + account_2, GoogleServiceAuthError(GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS)); // Fail as soon as one of the accounts is in error. EXPECT_EQ(FetchStatus::kFailure, GetFetchStatus());
diff --git a/components/signin/core/browser/profile_oauth2_token_service.cc b/components/signin/core/browser/profile_oauth2_token_service.cc index 07c6b1a9..a425e1f0 100644 --- a/components/signin/core/browser/profile_oauth2_token_service.cc +++ b/components/signin/core/browser/profile_oauth2_token_service.cc
@@ -156,7 +156,7 @@ is_valid, update_refresh_token_source_); std::string source_string = SourceToString(update_refresh_token_source_); - for (auto& diagnostic_observer : GetDiagnicsObservers()) { + for (auto& diagnostic_observer : GetDiagnosticsObservers()) { diagnostic_observer.OnRefreshTokenAvailableFromSource(account_id, is_valid, source_string); } @@ -175,7 +175,7 @@ signin_metrics::RecordRefreshTokenRevokedFromSource( update_refresh_token_source_); std::string source_string = SourceToString(update_refresh_token_source_); - for (auto& diagnostic_observer : GetDiagnicsObservers()) { + for (auto& diagnostic_observer : GetDiagnosticsObservers()) { diagnostic_observer.OnRefreshTokenRevokedFromSource(account_id, source_string); }
diff --git a/components/sync/syncable/directory_unittest.h b/components/sync/syncable/directory_unittest.h index 4f1faeeba..4227950 100644 --- a/components/sync/syncable/directory_unittest.h +++ b/components/sync/syncable/directory_unittest.h
@@ -10,7 +10,7 @@ #include <memory> #include <string> -#include "base/message_loop/message_loop.h" +#include "base/test/scoped_task_environment.h" #include "components/sync/base/fake_encryptor.h" #include "components/sync/base/test_unrecoverable_error_handler.h" #include "components/sync/syncable/in_memory_directory_backing_store.h" @@ -94,7 +94,7 @@ int64_t server_version, bool is_del); - base::MessageLoop message_loop_; + base::test::ScopedTaskEnvironment scoped_task_environment_; std::unique_ptr<Directory> dir_; NullDirectoryChangeDelegate delegate_; FakeEncryptor encryptor_;
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn index 9aa7ce7..8fa7fdc 100644 --- a/content/browser/BUILD.gn +++ b/content/browser/BUILD.gn
@@ -511,9 +511,13 @@ "background_sync/background_sync_network_observer.h", "background_sync/background_sync_registration.cc", "background_sync/background_sync_registration.h", - "background_sync/background_sync_service_impl.cc", - "background_sync/background_sync_service_impl.h", + "background_sync/background_sync_registration_helper.cc", + "background_sync/background_sync_registration_helper.h", "background_sync/background_sync_status.h", + "background_sync/one_shot_background_sync_service_impl.cc", + "background_sync/one_shot_background_sync_service_impl.h", + "background_sync/periodic_background_sync_service_impl.cc", + "background_sync/periodic_background_sync_service_impl.h", "bad_message.cc", "bad_message.h", "blob_storage/blob_dispatcher_host.cc",
diff --git a/content/browser/accessibility/accessibility_auralinux_browsertest.cc b/content/browser/accessibility/accessibility_auralinux_browsertest.cc index f5389ef..0b2d905d 100644 --- a/content/browser/accessibility/accessibility_auralinux_browsertest.cc +++ b/content/browser/accessibility/accessibility_auralinux_browsertest.cc
@@ -772,6 +772,64 @@ g_object_unref(list_item_1); } +IN_PROC_BROWSER_TEST_F(AccessibilityAuraLinuxBrowserTest, + TestTextSelectionChangedDuplicateSignals) { + LoadInitialAccessibilityTreeFromHtml( + R"HTML(<!DOCTYPE html> + <html> + <body> + <div> + Sufficiently long div content + </div> + </body> + </html>)HTML"); + + // Retrieve the AtkObject interface for the document node. + AtkObject* document = GetRendererAccessible(); + ASSERT_TRUE(ATK_IS_COMPONENT(document)); + + AtkObject* div = atk_object_ref_accessible_child(document, 0); + EXPECT_NE(div, nullptr); + + int selection_changed_signals = 0; + g_signal_connect(div, "text-selection-changed", + G_CALLBACK(+[](AtkText*, int* count) { *count += 1; }), + &selection_changed_signals); + + int caret_moved_signals = 0; + g_signal_connect(div, "text-caret-moved", + G_CALLBACK(+[](AtkText*, gint, int* count) { *count += 1; }), + &caret_moved_signals); + + auto waiter = std::make_unique<AccessibilityNotificationWaiter>( + shell()->web_contents(), ui::kAXModeComplete, + ax::mojom::Event::kTextSelectionChanged); + atk_text_set_caret_offset(ATK_TEXT(div), 0); + waiter->WaitForNotification(); + ASSERT_EQ(selection_changed_signals, 0); + ASSERT_EQ(caret_moved_signals, 1); + + caret_moved_signals = selection_changed_signals = 0; + atk_text_set_selection(ATK_TEXT(div), 0, 0, 3); + waiter->WaitForNotification(); + ASSERT_EQ(selection_changed_signals, 1); + ASSERT_EQ(caret_moved_signals, 1); + + caret_moved_signals = selection_changed_signals = 0; + atk_text_set_caret_offset(ATK_TEXT(div), 3); + waiter->WaitForNotification(); + ASSERT_EQ(selection_changed_signals, 1); + ASSERT_EQ(caret_moved_signals, 0); + + caret_moved_signals = selection_changed_signals = 0; + atk_text_set_caret_offset(ATK_TEXT(div), 2); + waiter->WaitForNotification(); + ASSERT_EQ(selection_changed_signals, 0); + ASSERT_EQ(caret_moved_signals, 1); + + g_object_unref(div); +} + IN_PROC_BROWSER_TEST_F( AccessibilityAuraLinuxBrowserTest, MAYBE_TestSetCaretSetsSequentialFocusNavigationStartingPoint) {
diff --git a/content/browser/appcache/appcache_quota_client.cc b/content/browser/appcache/appcache_quota_client.cc index c9266e4..2742e29 100644 --- a/content/browser/appcache/appcache_quota_client.cc +++ b/content/browser/appcache/appcache_quota_client.cc
@@ -87,13 +87,13 @@ return; } - const AppCacheStorage::UsageMap* map = GetUsageMap(); - auto found = map->find(origin); - if (found == map->end()) { + const std::map<url::Origin, int64_t>& map = GetUsageMap(); + auto it = map.find(origin); + if (it == map.end()) { std::move(callback).Run(0); return; } - std::move(callback).Run(found->second); + std::move(callback).Run(it->second); } void AppCacheQuotaClient::GetOriginsForType(StorageType type, @@ -182,7 +182,7 @@ } std::set<url::Origin> origins; - for (const auto& pair : *GetUsageMap()) { + for (const auto& pair : GetUsageMap()) { if (opt_host.empty() || pair.first.host() == opt_host) origins.insert(pair.first); } @@ -203,7 +203,7 @@ pending_serial_requests_.clear(); } -const AppCacheStorage::UsageMap* AppCacheQuotaClient::GetUsageMap() { +const std::map<url::Origin, int64_t>& AppCacheQuotaClient::GetUsageMap() const { DCHECK(service_); return service_->storage()->usage_map(); }
diff --git a/content/browser/appcache/appcache_quota_client.h b/content/browser/appcache/appcache_quota_client.h index a5dc1e6..39790d44 100644 --- a/content/browser/appcache/appcache_quota_client.h +++ b/content/browser/appcache/appcache_quota_client.h
@@ -66,7 +66,7 @@ GetOriginsCallback callback); void ProcessPendingRequests(); void DeletePendingRequests(); - const AppCacheStorage::UsageMap* GetUsageMap(); + const std::map<url::Origin, int64_t>& GetUsageMap() const; net::CancelableCompletionRepeatingCallback* GetServiceDeleteCallback(); // For use by appcache internals during initialization and shutdown.
diff --git a/content/browser/appcache/appcache_request_handler.cc b/content/browser/appcache/appcache_request_handler.cc index c508103..f97bbe40 100644 --- a/content/browser/appcache/appcache_request_handler.cc +++ b/content/browser/appcache/appcache_request_handler.cc
@@ -347,7 +347,7 @@ DCHECK(host_); if (storage()->IsInitialized() && - !base::Contains(*service_->storage()->usage_map(), + !base::Contains(service_->storage()->usage_map(), url::Origin::Create(request_->GetURL()))) { return nullptr; }
diff --git a/content/browser/appcache/appcache_storage.cc b/content/browser/appcache/appcache_storage.cc index 016a146..d0cf584 100644 --- a/content/browser/appcache/appcache_storage.cc +++ b/content/browser/appcache/appcache_storage.cc
@@ -35,7 +35,7 @@ Delegate* delegate, AppCacheStorage* storage) : delegate(delegate), storage(storage) { storage->delegate_references_.insert( - DelegateReferenceMap::value_type(delegate, this)); + std::map<Delegate*, DelegateReference*>::value_type(delegate, this)); } AppCacheStorage::DelegateReference::~DelegateReference() { @@ -54,8 +54,7 @@ storage_->pending_info_loads_[response_id] = base::WrapUnique(this); } -AppCacheStorage::ResponseInfoLoadTask::~ResponseInfoLoadTask() { -} +AppCacheStorage::ResponseInfoLoadTask::~ResponseInfoLoadTask() = default; void AppCacheStorage::ResponseInfoLoadTask::StartIfNeeded() { if (reader_) @@ -77,7 +76,10 @@ storage_->GetWeakPtr(), manifest_url_, response_id_, std::move(info_buffer_->http_info), info_buffer_->response_data_size); } - FOR_EACH_DELEGATE(delegates_, OnResponseInfoLoaded(info.get(), response_id_)); + AppCacheStorage::ForEachDelegate( + delegates_, [&](AppCacheStorage::Delegate* delegate) { + delegate->OnResponseInfoLoaded(info.get(), response_id_); + }); // returning deletes this }
diff --git a/content/browser/appcache/appcache_storage.h b/content/browser/appcache/appcache_storage.h index 296aa93..73f8fc4 100644 --- a/content/browser/appcache/appcache_storage.h +++ b/content/browser/appcache/appcache_storage.h
@@ -44,8 +44,6 @@ class CONTENT_EXPORT AppCacheStorage { public: - using UsageMap = std::map<url::Origin, int64_t>; - class CONTENT_EXPORT Delegate { public: Delegate(const Delegate&) = delete; @@ -217,7 +215,7 @@ AppCacheWorkingSet* working_set() { return &working_set_; } // A map of origins to usage. - const UsageMap* usage_map() { return &usage_map_; } + const std::map<url::Origin, int64_t>& usage_map() const { return usage_map_; } // Simple ptr back to the service object that owns us. AppCacheServiceImpl* service() { return service_; } @@ -230,15 +228,6 @@ friend class content::AppCacheResponseTest; friend class content::appcache_storage_unittest::AppCacheStorageTest; - // Helper to call a collection of delegates. -#define FOR_EACH_DELEGATE(delegates, func_and_args) \ - do { \ - for (const scoped_refptr<DelegateReference>& ref : delegates) { \ - if (ref.get()->delegate) \ - ref.get()->delegate->func_and_args; \ - } \ - } while (0) - // Helper used to manage multiple references to a 'delegate' and to // allow all pending callbacks to that delegate to be easily cancelled. struct CONTENT_EXPORT DelegateReference : @@ -250,17 +239,28 @@ void CancelReference() { storage->delegate_references_.erase(delegate); - storage = NULL; - delegate = NULL; + storage = nullptr; + delegate = nullptr; } private: friend class base::RefCounted<DelegateReference>; - - virtual ~DelegateReference(); + ~DelegateReference(); }; - using DelegateReferenceMap = std::map<Delegate*, DelegateReference*>; - using DelegateReferenceVector = std::vector<scoped_refptr<DelegateReference>>; + + // Helper for calling a function on a collection of delegates. + // + // ForEachCallable: (AppCacheStorage::Delegate*) -> void + template <typename ForEachCallable> + static void ForEachDelegate( + const std::vector<scoped_refptr<DelegateReference>>& delegates, + const ForEachCallable& callable) { + for (const scoped_refptr<DelegateReference>& delegate_ref : delegates) { + Delegate* delegate = delegate_ref->delegate; + if (delegate != nullptr) + callable(delegate); + } + } // Helper used to manage an async LoadResponseInfo calls on behalf of // multiple callers. @@ -287,12 +287,12 @@ GURL manifest_url_; int64_t response_id_; std::unique_ptr<AppCacheResponseReader> reader_; - DelegateReferenceVector delegates_; + std::vector<scoped_refptr<DelegateReference>> delegates_; scoped_refptr<HttpResponseInfoIOBuffer> info_buffer_; }; DelegateReference* GetDelegateReference(Delegate* delegate) { - DelegateReferenceMap::iterator iter = + std::map<Delegate*, DelegateReference*>::iterator iter = delegate_references_.find(delegate); if (iter != delegate_references_.end()) return iter->second; @@ -329,10 +329,10 @@ int64_t last_response_id_; // Maps origin to usage (includes padding, unless padding feature is disabled) - UsageMap usage_map_; + std::map<url::Origin, int64_t> usage_map_; AppCacheWorkingSet working_set_; AppCacheServiceImpl* service_; - DelegateReferenceMap delegate_references_; + std::map<Delegate*, DelegateReference*> delegate_references_; // Note that the ResponseInfoLoadTask items add themselves to this map. std::map<int64_t, std::unique_ptr<ResponseInfoLoadTask>> pending_info_loads_;
diff --git a/content/browser/appcache/appcache_storage_impl.cc b/content/browser/appcache/appcache_storage_impl.cc index cb02db3..4543bf3 100644 --- a/content/browser/appcache/appcache_storage_impl.cc +++ b/content/browser/appcache/appcache_storage_impl.cc
@@ -175,7 +175,7 @@ AppCacheStorageImpl* storage_; AppCacheDatabase* const database_; - DelegateReferenceVector delegates_; + std::vector<scoped_refptr<DelegateReference>> delegates_; private: void CallRun(); @@ -371,7 +371,10 @@ void AppCacheStorageImpl::GetAllInfoTask::RunCompleted() { DCHECK_EQ(1U, delegates_.size()); - FOR_EACH_DELEGATE(delegates_, OnAllInfo(info_collection_.get())); + AppCacheStorage::ForEachDelegate( + delegates_, [&](AppCacheStorage::Delegate* delegate) { + delegate->OnAllInfo(info_collection_.get()); + }); } // StoreOrLoadTask ------- @@ -517,7 +520,10 @@ DCHECK(cache_record_.cache_id == cache_id_); CreateCacheAndGroupFromRecords(&cache, &group); } - FOR_EACH_DELEGATE(delegates_, OnCacheLoaded(cache.get(), cache_id_)); + AppCacheStorage::ForEachDelegate( + delegates_, [&](AppCacheStorage::Delegate* delegate) { + delegate->OnCacheLoaded(cache.get(), cache_id_); + }); } // GroupLoadTask ------- @@ -569,7 +575,10 @@ } } } - FOR_EACH_DELEGATE(delegates_, OnGroupLoaded(group.get(), manifest_url_)); + AppCacheStorage::ForEachDelegate( + delegates_, [&](AppCacheStorage::Delegate* delegate) { + delegate->OnGroupLoaded(group.get(), manifest_url_); + }); } // StoreGroupAndCacheTask ------- @@ -782,10 +791,11 @@ group_->set_creation_time(group_record_.creation_time); group_->AddNewlyDeletableResponseIds(&newly_deletable_response_ids_); } - FOR_EACH_DELEGATE( - delegates_, - OnGroupAndNewestCacheStored( - group_.get(), cache_.get(), success_, would_exceed_quota_)); + AppCacheStorage::ForEachDelegate( + delegates_, [&](AppCacheStorage::Delegate* delegate) { + delegate->OnGroupAndNewestCacheStored(group_.get(), cache_.get(), + success_, would_exceed_quota_); + }); group_ = nullptr; cache_ = nullptr; @@ -1195,8 +1205,11 @@ storage_->working_set()->RemoveGroup(group_.get()); } } - FOR_EACH_DELEGATE( - delegates_, OnGroupMadeObsolete(group_.get(), success_, response_code_)); + + AppCacheStorage::ForEachDelegate( + delegates_, [&](AppCacheStorage::Delegate* delegate) { + delegate->OnGroupMadeObsolete(group_.get(), success_, response_code_); + }); group_ = nullptr; } @@ -1587,7 +1600,7 @@ scoped_refptr<AppCache> cache, scoped_refptr<DelegateReference> delegate_ref) { if (delegate_ref->delegate) { - DelegateReferenceVector delegates(1, delegate_ref); + std::vector<scoped_refptr<DelegateReference>> delegates(1, delegate_ref); CallOnMainResponseFound( &delegates, url, found_entry, GURL(), AppCacheEntry(), cache.get() ? cache->cache_id() : blink::mojom::kAppCacheNoCacheId, @@ -1597,7 +1610,7 @@ } void AppCacheStorageImpl::CallOnMainResponseFound( - DelegateReferenceVector* delegates, + std::vector<scoped_refptr<DelegateReference>>* delegates, const GURL& url, const AppCacheEntry& entry, const GURL& namespace_entry_url, @@ -1605,11 +1618,12 @@ int64_t cache_id, int64_t group_id, const GURL& manifest_url) { - FOR_EACH_DELEGATE( - (*delegates), - OnMainResponseFound(url, entry, - namespace_entry_url, fallback_entry, - cache_id, group_id, manifest_url)); + AppCacheStorage::ForEachDelegate( + *delegates, [&](AppCacheStorage::Delegate* delegate) { + delegate->OnMainResponseFound(url, entry, namespace_entry_url, + fallback_entry, cache_id, group_id, + manifest_url); + }); } void AppCacheStorageImpl::FindResponseForSubRequest(
diff --git a/content/browser/appcache/appcache_storage_impl.h b/content/browser/appcache/appcache_storage_impl.h index de16f25..4e9f73d 100644 --- a/content/browser/appcache/appcache_storage_impl.h +++ b/content/browser/appcache/appcache_storage_impl.h
@@ -147,14 +147,15 @@ scoped_refptr<AppCache> newest_cache, scoped_refptr<DelegateReference> delegate_ref); - void CallOnMainResponseFound(DelegateReferenceVector* delegates, - const GURL& url, - const AppCacheEntry& entry, - const GURL& namespace_entry_url, - const AppCacheEntry& fallback_entry, - int64_t cache_id, - int64_t group_id, - const GURL& manifest_url); + void CallOnMainResponseFound( + std::vector<scoped_refptr<DelegateReference>>* delegates, + const GURL& url, + const AppCacheEntry& entry, + const GURL& namespace_entry_url, + const AppCacheEntry& fallback_entry, + int64_t cache_id, + int64_t group_id, + const GURL& manifest_url); // Don't call this when |is_disabled_| is true. CONTENT_EXPORT AppCacheDiskCache* disk_cache();
diff --git a/content/browser/appcache/appcache_update_job.cc b/content/browser/appcache/appcache_update_job.cc index dcc1c518..49a6342 100644 --- a/content/browser/appcache/appcache_update_job.cc +++ b/content/browser/appcache/appcache_update_job.cc
@@ -264,14 +264,14 @@ void AppCacheUpdateJob::StartUpdate(AppCacheHost* host, const GURL& new_master_resource) { - DCHECK(group_->update_job() == this); + DCHECK_EQ(group_->update_job(), this); DCHECK(!group_->is_obsolete()); bool is_new_pending_master_entry = false; if (!new_master_resource.is_empty()) { - DCHECK(new_master_resource == host->pending_master_entry_url()); + DCHECK_EQ(new_master_resource, host->pending_master_entry_url()); DCHECK(!new_master_resource.has_ref()); - DCHECK(new_master_resource.GetOrigin() == manifest_url_.GetOrigin()); + DCHECK_EQ(new_master_resource.GetOrigin(), manifest_url_.GetOrigin()); if (base::Contains(failed_master_entries_, new_master_resource)) return; @@ -336,7 +336,7 @@ BrowserThread::PostBestEffortTask( FROM_HERE, base::ThreadTaskRunnerHandle::Get(), base::BindOnce(&AppCacheUpdateJob::FetchManifest, - weak_factory_.GetWeakPtr(), true)); + weak_factory_.GetWeakPtr())); } std::unique_ptr<AppCacheResponseWriter> @@ -392,31 +392,34 @@ DeleteSoon(); // To unwind the stack prior to deletion. } -void AppCacheUpdateJob::FetchManifest(bool is_first_fetch) { +void AppCacheUpdateJob::FetchManifest() { DCHECK(!manifest_fetcher_); manifest_fetcher_ = std::make_unique<URLFetcher>( - manifest_url_, - is_first_fetch ? URLFetcher::FetchType::kManifest - : URLFetcher::FetchType::kManifestRefetch, - this, kAppCacheFetchBufferSize); + manifest_url_, URLFetcher::FetchType::kManifest, this, + kAppCacheFetchBufferSize); - if (is_first_fetch) { - // Maybe load the cached headers to make a condiditional request. - AppCacheEntry* entry = - (update_type_ == UPGRADE_ATTEMPT) - ? group_->newest_complete_cache()->GetEntry(manifest_url_) - : nullptr; - if (entry && !doing_full_update_check_) { - // Asynchronously load response info for manifest from newest cache. - storage_->LoadResponseInfo(manifest_url_, entry->response_id(), this); - return; - } - manifest_fetcher_->Start(); + // Maybe load the cached headers to make a conditional request. + AppCacheEntry* entry = + (update_type_ == UPGRADE_ATTEMPT) + ? group_->newest_complete_cache()->GetEntry(manifest_url_) + : nullptr; + if (entry && !doing_full_update_check_) { + // Asynchronously load response info for manifest from newest cache. + storage_->LoadResponseInfo(manifest_url_, entry->response_id(), this); return; } + manifest_fetcher_->Start(); + return; +} - DCHECK(internal_state_ == REFETCH_MANIFEST); +void AppCacheUpdateJob::RefetchManifest() { + DCHECK(!manifest_fetcher_); + DCHECK_EQ(internal_state_, REFETCH_MANIFEST); DCHECK(manifest_response_info_.get()); + + manifest_fetcher_ = std::make_unique<URLFetcher>( + manifest_url_, URLFetcher::FetchType::kManifestRefetch, this, + kAppCacheFetchBufferSize); manifest_fetcher_->set_existing_response_headers( manifest_response_info_->headers.get()); manifest_fetcher_->Start(); @@ -492,10 +495,10 @@ } void AppCacheUpdateJob::ContinueHandleManifestFetchCompleted(bool changed) { - DCHECK(internal_state_ == FETCH_MANIFEST); + DCHECK_EQ(internal_state_, FETCH_MANIFEST); if (!changed) { - DCHECK(update_type_ == UPGRADE_ATTEMPT); + DCHECK_EQ(update_type_, UPGRADE_ATTEMPT); internal_state_ = NO_UPDATE; // Wait for pending master entries to download. @@ -564,7 +567,7 @@ void AppCacheUpdateJob::HandleResourceFetchCompleted(URLFetcher* url_fetcher, int net_error) { - DCHECK(internal_state_ == DOWNLOADING); + DCHECK_EQ(internal_state_, DOWNLOADING); UpdateURLLoaderRequest* request = url_fetcher->request(); const GURL& url = request->GetURL(); @@ -724,7 +727,7 @@ // In no-update case, associate host with the newest cache. if (!inprogress_cache_.get()) { // TODO(michaeln): defer until the updated cache has been stored - DCHECK(cache == group_->newest_complete_cache()); + DCHECK_EQ(cache, group_->newest_complete_cache()); for (AppCacheHost* host : hosts) host->AssociateCompleteCache(cache); } @@ -877,7 +880,7 @@ } void AppCacheUpdateJob::StoreGroupAndCache() { - DCHECK(stored_state_ == UNSTORED); + DCHECK_EQ(stored_state_, UNSTORED); stored_state_ = STORING; scoped_refptr<AppCache> newest_cache; @@ -898,7 +901,7 @@ AppCache* newest_cache, bool success, bool would_exceed_quota) { - DCHECK(stored_state_ == STORING); + DCHECK_EQ(stored_state_, STORING); if (success) { stored_state_ = STORED; MaybeCompleteUpdate(); // will definitely complete @@ -947,7 +950,7 @@ } void AppCacheUpdateJob::NotifyAllFinalProgress() { - DCHECK(url_file_list_.size() == url_fetches_completed_); + DCHECK_EQ(url_file_list_.size(), url_fetches_completed_); NotifyAllProgress(GURL()); } @@ -1001,7 +1004,7 @@ } void AppCacheUpdateJob::CheckIfManifestChanged() { - DCHECK(update_type_ == UPGRADE_ATTEMPT); + DCHECK_EQ(update_type_, UPGRADE_ATTEMPT); AppCacheEntry* entry = nullptr; if (group_->newest_complete_cache()) entry = group_->newest_complete_cache()->GetEntry(manifest_url_); @@ -1082,7 +1085,7 @@ } void AppCacheUpdateJob::FetchUrls() { - DCHECK(internal_state_ == DOWNLOADING); + DCHECK_EQ(internal_state_, DOWNLOADING); // Fetch each URL in the list according to section 6.9.4 step 17.1-17.3. // Fetch up to the concurrent limit. Other fetches will be triggered as each @@ -1113,8 +1116,8 @@ AppCacheEntry* existing_entry = group_->newest_complete_cache()->GetEntry(url_to_fetch.url); DCHECK(existing_entry); - DCHECK(existing_entry->response_id() == - url_to_fetch.existing_response_info->response_id()); + DCHECK_EQ(existing_entry->response_id(), + url_to_fetch.existing_response_info->response_id()); fetcher->set_existing_response_headers( url_to_fetch.existing_response_info->http_response_info() .headers.get()); @@ -1384,10 +1387,10 @@ break; case DOWNLOADING: internal_state_ = REFETCH_MANIFEST; - FetchManifest(false); + RefetchManifest(); break; case REFETCH_MANIFEST: - DCHECK(stored_state_ == STORED); + DCHECK_EQ(stored_state_, STORED); NotifyAllFinalProgress(); group_->SetUpdateAppCacheStatus(AppCacheGroup::IDLE); if (update_type_ == CACHE_ATTEMPT)
diff --git a/content/browser/appcache/appcache_update_job.h b/content/browser/appcache/appcache_update_job.h index 555af60..18a1a37 100644 --- a/content/browser/appcache/appcache_update_job.h +++ b/content/browser/appcache/appcache_update_job.h
@@ -140,7 +140,12 @@ ResultType result, const GURL& failed_resource_url); - void FetchManifest(bool is_first_fetch); + // Retrieves the cache's manifest. + // + // Called when a page referencing this job's manifest is loaded. This can + // result in a new cache getting created, or in an existing cache receiving a + // new master entry. + void FetchManifest(); void HandleManifestFetchCompleted(URLFetcher* url_fetcher, int net_error); void ContinueHandleManifestFetchCompleted(bool changed); @@ -148,7 +153,9 @@ void HandleNewMasterEntryFetchCompleted(URLFetcher* url_fetcher, int net_error); + void RefetchManifest(); void HandleManifestRefetchCompleted(URLFetcher* url_fetcher, int net_error); + void OnManifestInfoWriteComplete(int result); void OnManifestDataWriteComplete(int result);
diff --git a/content/browser/appcache/appcache_update_job_unittest.cc b/content/browser/appcache/appcache_update_job_unittest.cc index c741f1d8..8ddb1f1 100644 --- a/content/browser/appcache/appcache_update_job_unittest.cc +++ b/content/browser/appcache/appcache_update_job_unittest.cc
@@ -3126,7 +3126,7 @@ group_->update_status_ = AppCacheGroup::DOWNLOADING; update->manifest_response_info_ = std::move(response_info); update->internal_state_ = AppCacheUpdateJob::REFETCH_MANIFEST; - update->FetchManifest(false); // not first request + update->RefetchManifest(); // We need to wait for the URL load requests to make it to the // MockURLLoaderFactory. @@ -3165,7 +3165,7 @@ group_->update_status_ = AppCacheGroup::DOWNLOADING; update->manifest_response_info_ = std::move(response_info); update->internal_state_ = AppCacheUpdateJob::REFETCH_MANIFEST; - update->FetchManifest(false); // not first request + update->RefetchManifest(); // We need to wait for the URL load requests to make it to the // MockURLLoaderFactory. @@ -3336,7 +3336,7 @@ group_->update_status_ = AppCacheGroup::DOWNLOADING; update->manifest_response_info_ = std::move(response_info); update->internal_state_ = AppCacheUpdateJob::REFETCH_MANIFEST; - update->FetchManifest(false); // not first request + update->RefetchManifest(); // We need to wait for the URL load requests to make it to the // MockURLLoaderFactory. @@ -3377,7 +3377,7 @@ group_->update_status_ = AppCacheGroup::DOWNLOADING; update->manifest_response_info_ = std::move(response_info); update->internal_state_ = AppCacheUpdateJob::REFETCH_MANIFEST; - update->FetchManifest(false); // not first request + update->RefetchManifest(); // We need to wait for the URL load requests to make it to the // MockURLLoaderFactory.
diff --git a/content/browser/appcache/appcache_working_set.cc b/content/browser/appcache/appcache_working_set.cc index 144ffdc1..5182100 100644 --- a/content/browser/appcache/appcache_working_set.cc +++ b/content/browser/appcache/appcache_working_set.cc
@@ -36,7 +36,7 @@ DCHECK(cache->cache_id() != blink::mojom::kAppCacheNoCacheId); int64_t cache_id = cache->cache_id(); DCHECK(caches_.find(cache_id) == caches_.end()); - caches_.insert(CacheMap::value_type(cache_id, cache)); + caches_.emplace(cache_id, cache); } void AppCacheWorkingSet::RemoveCache(AppCache* cache) { @@ -48,9 +48,8 @@ return; const GURL& url = group->manifest_url(); DCHECK(groups_.find(url) == groups_.end()); - groups_.insert(GroupMap::value_type(url, group)); - groups_by_origin_[url::Origin::Create(url)].insert( - GroupMap::value_type(url, group)); + groups_.emplace(url, group); + groups_by_origin_[url::Origin::Create(url)].emplace(url, group); } void AppCacheWorkingSet::RemoveGroup(AppCacheGroup* group) { @@ -72,7 +71,7 @@ DCHECK(info->response_id() != blink::mojom::kAppCacheNoResponseId); int64_t response_id = info->response_id(); DCHECK(response_infos_.find(response_id) == response_infos_.end()); - response_infos_.insert(ResponseInfoMap::value_type(response_id, info)); + response_infos_.emplace(response_id, info); } void AppCacheWorkingSet::RemoveResponseInfo(AppCacheResponseInfo* info) {
diff --git a/content/browser/appcache/appcache_working_set.h b/content/browser/appcache/appcache_working_set.h index caede7c7..751ec57 100644 --- a/content/browser/appcache/appcache_working_set.h +++ b/content/browser/appcache/appcache_working_set.h
@@ -35,15 +35,15 @@ void AddCache(AppCache* cache); void RemoveCache(AppCache* cache); AppCache* GetCache(int64_t id) { - CacheMap::iterator it = caches_.find(id); - return (it != caches_.end()) ? it->second : NULL; + auto it = caches_.find(id); + return (it != caches_.end()) ? it->second : nullptr; } void AddGroup(AppCacheGroup* group); void RemoveGroup(AppCacheGroup* group); AppCacheGroup* GetGroup(const GURL& manifest_url) { - GroupMap::iterator it = groups_.find(manifest_url); - return (it != groups_.end()) ? it->second : NULL; + auto it = groups_.find(manifest_url); + return (it != groups_.end()) ? it->second : nullptr; } const GroupMap* GetGroupsInOrigin(const url::Origin& origin) { @@ -53,24 +53,21 @@ void AddResponseInfo(AppCacheResponseInfo* response_info); void RemoveResponseInfo(AppCacheResponseInfo* response_info); AppCacheResponseInfo* GetResponseInfo(int64_t id) { - ResponseInfoMap::iterator it = response_infos_.find(id); - return (it != response_infos_.end()) ? it->second : NULL; + auto it = response_infos_.find(id); + return (it != response_infos_.end()) ? it->second : nullptr; } private: - using CacheMap = std::unordered_map<int64_t, AppCache*>; - using GroupsByOriginMap = std::map<url::Origin, GroupMap>; - using ResponseInfoMap = std::unordered_map<int64_t, AppCacheResponseInfo*>; - GroupMap* GetMutableGroupsInOrigin(const url::Origin& origin) { - GroupsByOriginMap::iterator it = groups_by_origin_.find(origin); - return (it != groups_by_origin_.end()) ? &it->second : NULL; + auto it = groups_by_origin_.find(origin); + return (it != groups_by_origin_.end()) ? &it->second : nullptr; } - CacheMap caches_; + std::unordered_map<int64_t, AppCache*> caches_; GroupMap groups_; - GroupsByOriginMap groups_by_origin_; // origin -> (manifest -> group) - ResponseInfoMap response_infos_; + // origin -> (manifest -> group) + std::map<url::Origin, GroupMap> groups_by_origin_; + std::unordered_map<int64_t, AppCacheResponseInfo*> response_infos_; bool is_disabled_; };
diff --git a/content/browser/background_sync/background_sync_context_impl.cc b/content/browser/background_sync/background_sync_context_impl.cc index 66a9ed4..33b8b07 100644 --- a/content/browser/background_sync/background_sync_context_impl.cc +++ b/content/browser/background_sync/background_sync_context_impl.cc
@@ -12,7 +12,8 @@ #include "base/task/task_traits.h" #include "content/browser/background_sync/background_sync_launcher.h" #include "content/browser/background_sync/background_sync_manager.h" -#include "content/browser/background_sync/background_sync_service_impl.h" +#include "content/browser/background_sync/one_shot_background_sync_service_impl.h" +#include "content/browser/background_sync/periodic_background_sync_service_impl.h" #include "content/browser/devtools/devtools_background_services_context_impl.h" #include "content/browser/service_worker/service_worker_context_wrapper.h" #include "content/public/browser/browser_task_traits.h" @@ -31,7 +32,8 @@ DCHECK_CURRENTLY_ON(BrowserThread::IO); DCHECK(!background_sync_manager_); - DCHECK(services_.empty()); + DCHECK(one_shot_sync_services_.empty()); + DCHECK(periodic_sync_services_.empty()); } // static @@ -75,21 +77,44 @@ base::BindOnce(&BackgroundSyncContextImpl::ShutdownOnIO, this)); } -void BackgroundSyncContextImpl::CreateService( - blink::mojom::BackgroundSyncServiceRequest request) { +void BackgroundSyncContextImpl::CreateOneShotSyncService( + blink::mojom::OneShotBackgroundSyncServiceRequest request) { DCHECK_CURRENTLY_ON(BrowserThread::UI); base::PostTaskWithTraits( FROM_HERE, {BrowserThread::IO}, - base::BindOnce(&BackgroundSyncContextImpl::CreateServiceOnIOThread, this, - std::move(request))); + base::BindOnce( + &BackgroundSyncContextImpl::CreateOneShotSyncServiceOnIOThread, this, + std::move(request))); } -void BackgroundSyncContextImpl::ServiceHadConnectionError( - BackgroundSyncServiceImpl* service) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - DCHECK(base::Contains(services_, service)); +void BackgroundSyncContextImpl::CreatePeriodicSyncService( + blink::mojom::PeriodicBackgroundSyncServiceRequest request) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + base::PostTaskWithTraits( + FROM_HERE, {BrowserThread::IO}, + base::BindOnce( + &BackgroundSyncContextImpl::CreatePeriodicSyncServiceOnIOThread, this, + std::move(request))); +} - services_.erase(service); +void BackgroundSyncContextImpl::OneShotSyncServiceHadConnectionError( + OneShotBackgroundSyncServiceImpl* service) { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + DCHECK(service); + + auto iter = one_shot_sync_services_.find(service); + DCHECK(iter != one_shot_sync_services_.end()); + one_shot_sync_services_.erase(iter); +} + +void BackgroundSyncContextImpl::PeriodicSyncServiceHadConnectionError( + PeriodicBackgroundSyncServiceImpl* service) { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + DCHECK(service); + + auto iter = periodic_sync_services_.find(service); + DCHECK(iter != periodic_sync_services_.end()); + periodic_sync_services_.erase(iter); } BackgroundSyncManager* BackgroundSyncContextImpl::background_sync_manager() @@ -186,19 +211,31 @@ std::move(service_worker_context), std::move(devtools_context)); } -void BackgroundSyncContextImpl::CreateServiceOnIOThread( - mojo::InterfaceRequest<blink::mojom::BackgroundSyncService> request) { +void BackgroundSyncContextImpl::CreateOneShotSyncServiceOnIOThread( + mojo::InterfaceRequest<blink::mojom::OneShotBackgroundSyncService> + request) { DCHECK_CURRENTLY_ON(BrowserThread::IO); DCHECK(background_sync_manager_); - auto service = - std::make_unique<BackgroundSyncServiceImpl>(this, std::move(request)); - services_[service.get()] = std::move(service); + one_shot_sync_services_.insert( + std::make_unique<OneShotBackgroundSyncServiceImpl>(this, + std::move(request))); +} + +void BackgroundSyncContextImpl::CreatePeriodicSyncServiceOnIOThread( + mojo::InterfaceRequest<blink::mojom::PeriodicBackgroundSyncService> + request) { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + DCHECK(background_sync_manager_); + periodic_sync_services_.insert( + std::make_unique<PeriodicBackgroundSyncServiceImpl>(this, + std::move(request))); } void BackgroundSyncContextImpl::ShutdownOnIO() { DCHECK_CURRENTLY_ON(BrowserThread::IO); - services_.clear(); + one_shot_sync_services_.clear(); + periodic_sync_services_.clear(); background_sync_manager_.reset(); }
diff --git a/content/browser/background_sync/background_sync_context_impl.h b/content/browser/background_sync/background_sync_context_impl.h index 47fb476..b256e5a 100644 --- a/content/browser/background_sync/background_sync_context_impl.h +++ b/content/browser/background_sync/background_sync_context_impl.h
@@ -8,6 +8,7 @@ #include <map> #include <memory> +#include "base/containers/unique_ptr_adapters.h" #include "base/macros.h" #include "base/memory/ref_counted_delete_on_sequence.h" #include "base/memory/scoped_refptr.h" @@ -20,8 +21,9 @@ namespace content { class BackgroundSyncManager; -class BackgroundSyncServiceImpl; class DevToolsBackgroundServicesContextImpl; +class OneShotBackgroundSyncServiceImpl; +class PeriodicBackgroundSyncServiceImpl; class ServiceWorkerContextWrapper; // One instance of this exists per StoragePartition, and services multiple child @@ -45,13 +47,22 @@ // Shutdown must be called before deleting this. Call on the UI thread. void Shutdown(); - // Create a BackgroundSyncServiceImpl that is owned by this. Call on the UI - // thread. - void CreateService(blink::mojom::BackgroundSyncServiceRequest request); + // Create a OneShotBackgroundSyncServiceImpl that is owned by this. Call on + // the UI thread. + void CreateOneShotSyncService( + blink::mojom::OneShotBackgroundSyncServiceRequest request); - // Called by BackgroundSyncServiceImpl objects so that they can + // Create a PeriodicBackgroundSyncServiceImpl that is owned by this. Call on + // the UI thread. + void CreatePeriodicSyncService( + blink::mojom::PeriodicBackgroundSyncServiceRequest request); + + // Called by *BackgroundSyncServiceImpl objects so that they can // be deleted. Call on the IO thread. - void ServiceHadConnectionError(BackgroundSyncServiceImpl* service); + void OneShotSyncServiceHadConnectionError( + OneShotBackgroundSyncServiceImpl* service); + void PeriodicSyncServiceHadConnectionError( + PeriodicBackgroundSyncServiceImpl* service); // Call on the IO thread. BackgroundSyncManager* background_sync_manager() const; @@ -71,7 +82,8 @@ void set_wakeup_delta_for_testing(base::TimeDelta wakeup_delta); private: - friend class BackgroundSyncServiceImplTest; + friend class OneShotBackgroundSyncServiceImplTest; + friend class PeriodicBackgroundSyncServiceImplTest; friend class BackgroundSyncLauncherTest; void FireBackgroundSyncEventsOnIOThread(base::OnceClosure done_closure); @@ -80,8 +92,12 @@ scoped_refptr<ServiceWorkerContextWrapper> service_worker_context, scoped_refptr<DevToolsBackgroundServicesContextImpl> devtools_context); - void CreateServiceOnIOThread( - mojo::InterfaceRequest<blink::mojom::BackgroundSyncService> request); + void CreateOneShotSyncServiceOnIOThread( + mojo::InterfaceRequest<blink::mojom::OneShotBackgroundSyncService> + request); + void CreatePeriodicSyncServiceOnIOThread( + mojo::InterfaceRequest<blink::mojom::PeriodicBackgroundSyncService> + request); void ShutdownOnIO(); @@ -90,15 +106,19 @@ base::OnceCallback<void(base::TimeDelta)> callback, base::TimeDelta soonest_wakeup_delta); + // The services are owned by this. They're either deleted + // during ShutdownOnIO or when the channel is closed via + // *ServiceHadConnectionError. Only accessed on the IO thread. + std::set<std::unique_ptr<OneShotBackgroundSyncServiceImpl>, + base::UniquePtrComparator> + one_shot_sync_services_; + std::set<std::unique_ptr<PeriodicBackgroundSyncServiceImpl>, + base::UniquePtrComparator> + periodic_sync_services_; + // Only accessed on the IO thread. std::unique_ptr<BackgroundSyncManager> background_sync_manager_; - // The services are owned by this. They're either deleted - // during ShutdownOnIO or when the channel is closed via - // ServiceHadConnectionError. Only accessed on the IO thread. - std::map<BackgroundSyncServiceImpl*, - std::unique_ptr<BackgroundSyncServiceImpl>> - services_; base::TimeDelta test_wakeup_delta_ = base::TimeDelta::Max(); DISALLOW_COPY_AND_ASSIGN(BackgroundSyncContextImpl);
diff --git a/content/browser/background_sync/background_sync_manager.cc b/content/browser/background_sync/background_sync_manager.cc index 3b4c6fed..9c697555 100644 --- a/content/browser/background_sync/background_sync_manager.cc +++ b/content/browser/background_sync/background_sync_manager.cc
@@ -46,6 +46,28 @@ namespace content { +// TODO(crbug.com/932591): Use blink::mojom::BackgroundSyncError +// directly and eliminate these checks. +#define COMPILE_ASSERT_MATCHING_ENUM(mojo_name, manager_name) \ + static_assert(static_cast<int>(blink::mojo_name) == \ + static_cast<int>(content::manager_name), \ + "mojo and manager enums must match") + +COMPILE_ASSERT_MATCHING_ENUM(mojom::BackgroundSyncError::NONE, + BACKGROUND_SYNC_STATUS_OK); +COMPILE_ASSERT_MATCHING_ENUM(mojom::BackgroundSyncError::STORAGE, + BACKGROUND_SYNC_STATUS_STORAGE_ERROR); +COMPILE_ASSERT_MATCHING_ENUM(mojom::BackgroundSyncError::NOT_FOUND, + BACKGROUND_SYNC_STATUS_NOT_FOUND); +COMPILE_ASSERT_MATCHING_ENUM(mojom::BackgroundSyncError::NO_SERVICE_WORKER, + BACKGROUND_SYNC_STATUS_NO_SERVICE_WORKER); +COMPILE_ASSERT_MATCHING_ENUM(mojom::BackgroundSyncError::NOT_ALLOWED, + BACKGROUND_SYNC_STATUS_NOT_ALLOWED); +COMPILE_ASSERT_MATCHING_ENUM(mojom::BackgroundSyncError::PERMISSION_DENIED, + BACKGROUND_SYNC_STATUS_PERMISSION_DENIED); +COMPILE_ASSERT_MATCHING_ENUM(mojom::BackgroundSyncError::MAX, + BACKGROUND_SYNC_STATUS_PERMISSION_DENIED); + namespace { // The only allowed value of min_interval for one shot Background Sync
diff --git a/content/browser/background_sync/background_sync_registration_helper.cc b/content/browser/background_sync/background_sync_registration_helper.cc new file mode 100644 index 0000000..825bfe7d --- /dev/null +++ b/content/browser/background_sync/background_sync_registration_helper.cc
@@ -0,0 +1,94 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/browser/background_sync/background_sync_registration_helper.h" + +#include "base/memory/weak_ptr.h" +#include "content/browser/background_sync/background_sync_context_impl.h" +#include "content/browser/background_sync/background_sync_manager.h" +#include "content/browser/background_sync/background_sync_status.h" +#include "content/public/browser/browser_thread.h" + +namespace content { + +BackgroundSyncRegistrationHelper::BackgroundSyncRegistrationHelper( + BackgroundSyncContextImpl* background_sync_context) + : background_sync_context_(background_sync_context), + weak_ptr_factory_(this) { + DCHECK(background_sync_context_); +} + +BackgroundSyncRegistrationHelper::~BackgroundSyncRegistrationHelper() = default; + +void BackgroundSyncRegistrationHelper::Register( + blink::mojom::SyncRegistrationOptionsPtr options, + int64_t sw_registration_id, + RegisterCallback callback) { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + + BackgroundSyncManager* background_sync_manager = + background_sync_context_->background_sync_manager(); + DCHECK(background_sync_manager); + + background_sync_manager->Register( + sw_registration_id, *options, + base::BindOnce(&BackgroundSyncRegistrationHelper::OnRegisterResult, + weak_ptr_factory_.GetWeakPtr(), std::move(callback))); +} + +void BackgroundSyncRegistrationHelper::DidResolveRegistration( + blink::mojom::BackgroundSyncRegistrationInfoPtr registration_info) { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + + BackgroundSyncManager* background_sync_manager = + background_sync_context_->background_sync_manager(); + DCHECK(background_sync_manager); + + background_sync_manager->DidResolveRegistration(std::move(registration_info)); +} + +void BackgroundSyncRegistrationHelper::OnRegisterResult( + RegisterCallback callback, + BackgroundSyncStatus status, + std::unique_ptr<BackgroundSyncRegistration> result) { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + + // TODO(crbug.com/932591): Use blink::mojom::BackgroundSyncError + // directly. + if (status != BACKGROUND_SYNC_STATUS_OK) { + std::move(callback).Run( + static_cast<blink::mojom::BackgroundSyncError>(status), + /* options= */ nullptr); + return; + } + + DCHECK(result); + std::move(callback).Run( + static_cast<blink::mojom::BackgroundSyncError>(status), + result->options()->Clone()); +} + +void BackgroundSyncRegistrationHelper::OnGetRegistrationsResult( + GetRegistrationsCallback callback, + BackgroundSyncStatus status, + std::vector<std::unique_ptr<BackgroundSyncRegistration>> + result_registrations) { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + + std::vector<blink::mojom::SyncRegistrationOptionsPtr> mojo_registrations; + mojo_registrations.reserve(result_registrations.size()); + for (const auto& registration : result_registrations) + mojo_registrations.push_back(registration->options()->Clone()); + + std::move(callback).Run( + static_cast<blink::mojom::BackgroundSyncError>(status), + std::move(mojo_registrations)); +} + +base::WeakPtr<BackgroundSyncRegistrationHelper> +BackgroundSyncRegistrationHelper::GetWeakPtr() { + return weak_ptr_factory_.GetWeakPtr(); +} + +} // namespace content
diff --git a/content/browser/background_sync/background_sync_registration_helper.h b/content/browser/background_sync/background_sync_registration_helper.h new file mode 100644 index 0000000..04edbfe --- /dev/null +++ b/content/browser/background_sync/background_sync_registration_helper.h
@@ -0,0 +1,62 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_BROWSER_BACKGROUND_SYNC_BACKGROUND_SYNC_REGISTRATION_HELPER_H_ +#define CONTENT_BROWSER_BACKGROUND_SYNC_BACKGROUND_SYNC_REGISTRATION_HELPER_H_ + +#include <vector> + +#include "base/callback.h" +#include "base/macros.h" +#include "base/memory/weak_ptr.h" +#include "content/browser/background_sync/background_sync_registration.h" +#include "content/browser/background_sync/background_sync_status.h" +#include "third_party/blink/public/mojom/background_sync/background_sync.mojom.h" + +namespace content { + +class BackgroundSyncContextImpl; + +// Used by OneShotBackgroundSyncService and PeriodicBackgroundSyncService to +// create and get BackgroundSync registrations. +class BackgroundSyncRegistrationHelper { + public: + using RegisterCallback = + base::OnceCallback<void(blink::mojom::BackgroundSyncError status, + blink::mojom::SyncRegistrationOptionsPtr result)>; + using GetRegistrationsCallback = base::OnceCallback<void( + blink::mojom::BackgroundSyncError status, + std::vector<blink::mojom::SyncRegistrationOptionsPtr> results)>; + + explicit BackgroundSyncRegistrationHelper( + BackgroundSyncContextImpl* background_sync_context); + ~BackgroundSyncRegistrationHelper(); + + void Register(blink::mojom::SyncRegistrationOptionsPtr options, + int64_t sw_registration_id, + RegisterCallback callback); + void DidResolveRegistration( + blink::mojom::BackgroundSyncRegistrationInfoPtr registration_info); + void OnRegisterResult(RegisterCallback callback, + BackgroundSyncStatus status, + std::unique_ptr<BackgroundSyncRegistration> result); + void OnGetRegistrationsResult( + GetRegistrationsCallback callback, + BackgroundSyncStatus status, + std::vector<std::unique_ptr<BackgroundSyncRegistration>> + result_registrations); + + base::WeakPtr<BackgroundSyncRegistrationHelper> GetWeakPtr(); + + private: + // |background_sync_context_| (indirectly) owns |this|. + BackgroundSyncContextImpl* const background_sync_context_; + base::WeakPtrFactory<BackgroundSyncRegistrationHelper> weak_ptr_factory_; + + DISALLOW_COPY_AND_ASSIGN(BackgroundSyncRegistrationHelper); +}; + +} // namespace content + +#endif // CONTENT_BROWSER_BACKGROUND_SYNC_BACKGROUND_SYNC_REGISTRATION_HELPER_H_
diff --git a/content/browser/background_sync/background_sync_service_impl.cc b/content/browser/background_sync/background_sync_service_impl.cc deleted file mode 100644 index 0808e03..0000000 --- a/content/browser/background_sync/background_sync_service_impl.cc +++ /dev/null
@@ -1,139 +0,0 @@ -// 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. - -#include "content/browser/background_sync/background_sync_service_impl.h" - -#include <utility> - -#include "base/bind.h" -#include "base/memory/weak_ptr.h" -#include "base/stl_util.h" -#include "content/browser/background_sync/background_sync_context_impl.h" -#include "content/public/browser/browser_thread.h" - -namespace content { - -#define COMPILE_ASSERT_MATCHING_ENUM(mojo_name, manager_name) \ - static_assert(static_cast<int>(blink::mojo_name) == \ - static_cast<int>(content::manager_name), \ - "mojo and manager enums must match") - -// TODO(iclelland): Move these tests somewhere else -COMPILE_ASSERT_MATCHING_ENUM(mojom::BackgroundSyncError::NONE, - BACKGROUND_SYNC_STATUS_OK); -COMPILE_ASSERT_MATCHING_ENUM(mojom::BackgroundSyncError::STORAGE, - BACKGROUND_SYNC_STATUS_STORAGE_ERROR); -COMPILE_ASSERT_MATCHING_ENUM(mojom::BackgroundSyncError::NOT_FOUND, - BACKGROUND_SYNC_STATUS_NOT_FOUND); -COMPILE_ASSERT_MATCHING_ENUM(mojom::BackgroundSyncError::NO_SERVICE_WORKER, - BACKGROUND_SYNC_STATUS_NO_SERVICE_WORKER); -COMPILE_ASSERT_MATCHING_ENUM(mojom::BackgroundSyncError::NOT_ALLOWED, - BACKGROUND_SYNC_STATUS_NOT_ALLOWED); -COMPILE_ASSERT_MATCHING_ENUM(mojom::BackgroundSyncError::PERMISSION_DENIED, - BACKGROUND_SYNC_STATUS_PERMISSION_DENIED); -COMPILE_ASSERT_MATCHING_ENUM(mojom::BackgroundSyncError::MAX, - BACKGROUND_SYNC_STATUS_PERMISSION_DENIED); - -BackgroundSyncServiceImpl::~BackgroundSyncServiceImpl() { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - DCHECK(background_sync_context_->background_sync_manager()); -} - -BackgroundSyncServiceImpl::BackgroundSyncServiceImpl( - BackgroundSyncContextImpl* background_sync_context, - mojo::InterfaceRequest<blink::mojom::BackgroundSyncService> request) - : background_sync_context_(background_sync_context), - binding_(this, std::move(request)), - weak_ptr_factory_(this) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - DCHECK(background_sync_context); - - binding_.set_connection_error_handler(base::BindOnce( - &BackgroundSyncServiceImpl::OnConnectionError, - base::Unretained(this) /* the channel is owned by this */)); -} - -void BackgroundSyncServiceImpl::OnConnectionError() { - background_sync_context_->ServiceHadConnectionError(this); - // |this| is now deleted. -} - -void BackgroundSyncServiceImpl::Register( - blink::mojom::SyncRegistrationOptionsPtr options, - int64_t sw_registration_id, - RegisterCallback callback) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - - BackgroundSyncManager* background_sync_manager = - background_sync_context_->background_sync_manager(); - DCHECK(background_sync_manager); - background_sync_manager->Register( - sw_registration_id, *options, - base::BindOnce(&BackgroundSyncServiceImpl::OnRegisterResult, - weak_ptr_factory_.GetWeakPtr(), std::move(callback))); -} - -void BackgroundSyncServiceImpl::DidResolveRegistration( - blink::mojom::BackgroundSyncRegistrationInfoPtr registration_info) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - - BackgroundSyncManager* background_sync_manager = - background_sync_context_->background_sync_manager(); - DCHECK(background_sync_manager); - background_sync_manager->DidResolveRegistration(std::move(registration_info)); -} - -void BackgroundSyncServiceImpl::GetOneShotSyncRegistrations( - int64_t sw_registration_id, - GetOneShotSyncRegistrationsCallback callback) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - BackgroundSyncManager* background_sync_manager = - background_sync_context_->background_sync_manager(); - DCHECK(background_sync_manager); - background_sync_manager->GetOneShotSyncRegistrations( - sw_registration_id, - base::BindOnce(&BackgroundSyncServiceImpl::OnGetRegistrationsResult, - weak_ptr_factory_.GetWeakPtr(), std::move(callback))); -} - -void BackgroundSyncServiceImpl::OnRegisterResult( - RegisterCallback callback, - BackgroundSyncStatus status, - std::unique_ptr<BackgroundSyncRegistration> result) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - - if (status != BACKGROUND_SYNC_STATUS_OK) { - std::move(callback).Run( - static_cast<blink::mojom::BackgroundSyncError>(status), - blink::mojom::SyncRegistrationOptions::New()); - return; - } - - DCHECK(result); - blink::mojom::SyncRegistrationOptionsPtr mojo_options = - blink::mojom::SyncRegistrationOptions::New(*result->options()); - std::move(callback).Run( - static_cast<blink::mojom::BackgroundSyncError>(status), - std::move(mojo_options)); -} - -void BackgroundSyncServiceImpl::OnGetRegistrationsResult( - GetOneShotSyncRegistrationsCallback callback, - BackgroundSyncStatus status, - std::vector<std::unique_ptr<BackgroundSyncRegistration>> - result_registrations) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - - std::vector<blink::mojom::SyncRegistrationOptionsPtr> mojo_registrations; - for (const auto& registration : result_registrations) { - mojo_registrations.push_back( - blink::mojom::SyncRegistrationOptions::New(*registration->options())); - } - - std::move(callback).Run( - static_cast<blink::mojom::BackgroundSyncError>(status), - std::move(mojo_registrations)); -} - -} // namespace content
diff --git a/content/browser/background_sync/background_sync_service_impl.h b/content/browser/background_sync/background_sync_service_impl.h deleted file mode 100644 index 91cfefe..0000000 --- a/content/browser/background_sync/background_sync_service_impl.h +++ /dev/null
@@ -1,70 +0,0 @@ -// 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. - -#ifndef CONTENT_BROWSER_BACKGROUND_SYNC_BACKGROUND_SYNC_SERVICE_IMPL_H_ -#define CONTENT_BROWSER_BACKGROUND_SYNC_BACKGROUND_SYNC_SERVICE_IMPL_H_ - -#include <stdint.h> - -#include <memory> -#include <string> -#include <vector> - -#include "base/containers/id_map.h" -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "content/browser/background_sync/background_sync_manager.h" -#include "mojo/public/cpp/bindings/binding.h" -#include "third_party/blink/public/mojom/background_sync/background_sync.mojom.h" - -namespace content { - -class BackgroundSyncContextImpl; - -class CONTENT_EXPORT BackgroundSyncServiceImpl - : public blink::mojom::BackgroundSyncService { - public: - BackgroundSyncServiceImpl( - BackgroundSyncContextImpl* background_sync_context, - mojo::InterfaceRequest<blink::mojom::BackgroundSyncService> request); - - ~BackgroundSyncServiceImpl() override; - - private: - friend class BackgroundSyncServiceImplTest; - - // blink::mojom::BackgroundSyncService methods: - void Register(blink::mojom::SyncRegistrationOptionsPtr options, - int64_t sw_registration_id, - RegisterCallback callback) override; - void DidResolveRegistration(blink::mojom::BackgroundSyncRegistrationInfoPtr - registration_info) override; - void GetOneShotSyncRegistrations( - int64_t sw_registration_id, - GetOneShotSyncRegistrationsCallback callback) override; - - void OnRegisterResult(RegisterCallback callback, - BackgroundSyncStatus status, - std::unique_ptr<BackgroundSyncRegistration> result); - void OnGetRegistrationsResult( - GetOneShotSyncRegistrationsCallback callback, - BackgroundSyncStatus status, - std::vector<std::unique_ptr<BackgroundSyncRegistration>> result); - - // Called when an error is detected on binding_. - void OnConnectionError(); - - // |background_sync_context_| owns |this|. - BackgroundSyncContextImpl* background_sync_context_; - - mojo::Binding<blink::mojom::BackgroundSyncService> binding_; - - base::WeakPtrFactory<BackgroundSyncServiceImpl> weak_ptr_factory_; - - DISALLOW_COPY_AND_ASSIGN(BackgroundSyncServiceImpl); -}; - -} // namespace content - -#endif // CONTENT_BROWSER_BACKGROUND_SYNC_BACKGROUND_SYNC_SERVICE_IMPL_H_
diff --git a/content/browser/background_sync/background_sync_service_impl_test_harness.cc b/content/browser/background_sync/background_sync_service_impl_test_harness.cc new file mode 100644 index 0000000..2de0ca0 --- /dev/null +++ b/content/browser/background_sync/background_sync_service_impl_test_harness.cc
@@ -0,0 +1,179 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/browser/background_sync/background_sync_service_impl_test_harness.h" + +#include <stdint.h> +#include <utility> + +#include "base/bind.h" +#include "base/bind_helpers.h" +#include "base/run_loop.h" +#include "content/browser/background_sync/background_sync_manager.h" +#include "content/browser/background_sync/background_sync_network_observer.h" +#include "content/browser/service_worker/service_worker_context_wrapper.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/browser/permission_type.h" +#include "content/public/test/background_sync_test_util.h" +#include "content/public/test/mock_permission_manager.h" +#include "content/public/test/test_browser_context.h" +#include "content/test/test_background_sync_context.h" +#include "mojo/public/cpp/bindings/interface_ptr.h" +#include "third_party/blink/public/mojom/service_worker/service_worker_registration.mojom.h" + +namespace content { + +using ::testing::_; + +const char kServiceWorkerScope[] = "https://example.com/a"; +const char kServiceWorkerScript[] = "https://example.com/a/script.js"; + +void BackgroundSyncServiceImplTestHarness::RegisterServiceWorkerCallback( + bool* called, + int64_t* out_registration_id, + blink::ServiceWorkerStatusCode status, + const std::string& status_message, + int64_t registration_id) { + EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk, status) + << blink::ServiceWorkerStatusToString(status); + *called = true; + *out_registration_id = registration_id; +} + +void BackgroundSyncServiceImplTestHarness:: + FindServiceWorkerRegistrationCallback( + scoped_refptr<ServiceWorkerRegistration>* out_registration, + blink::ServiceWorkerStatusCode status, + scoped_refptr<ServiceWorkerRegistration> registration) { + EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk, status) + << blink::ServiceWorkerStatusToString(status); + *out_registration = std::move(registration); +} + +void BackgroundSyncServiceImplTestHarness::ErrorAndRegistrationCallback( + bool* called, + blink::mojom::BackgroundSyncError* out_error, + blink::mojom::SyncRegistrationOptionsPtr* out_registration, + blink::mojom::BackgroundSyncError error, + blink::mojom::SyncRegistrationOptionsPtr registration) { + *called = true; + *out_error = error; + *out_registration = registration.Clone(); +} + +void BackgroundSyncServiceImplTestHarness::ErrorAndRegistrationListCallback( + bool* called, + blink::mojom::BackgroundSyncError* out_error, + unsigned long* out_array_size, + blink::mojom::BackgroundSyncError error, + std::vector<blink::mojom::SyncRegistrationOptionsPtr> registrations) { + *called = true; + *out_error = error; + if (error == blink::mojom::BackgroundSyncError::NONE) + *out_array_size = registrations.size(); +} + +void BackgroundSyncServiceImplTestHarness::ErrorCallback( + bool* called, + blink::mojom::BackgroundSyncError* out_error, + blink::mojom::BackgroundSyncError error) { + *called = true; + *out_error = error; +} + +BackgroundSyncServiceImplTestHarness::BackgroundSyncServiceImplTestHarness() + : thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP) { + default_sync_registration_ = blink::mojom::SyncRegistrationOptions::New(); +} + +BackgroundSyncServiceImplTestHarness::~BackgroundSyncServiceImplTestHarness() = + default; + +void BackgroundSyncServiceImplTestHarness::SetUp() { + // Don't let the tests be confused by the real-world device connectivity + background_sync_test_util::SetIgnoreNetworkChanges(true); + + CreateTestHelper(); + CreateStoragePartition(); + CreateBackgroundSyncContext(); + ASSERT_NO_FATAL_FAILURE(CreateServiceWorkerRegistration()); +} + +void BackgroundSyncServiceImplTestHarness::TearDown() { + // This must be explicitly destroyed here to ensure that destruction + // of both the BackgroundSyncContextImpl and the BackgroundSyncManager + // occurs on the correct thread. + background_sync_context_->Shutdown(); + base::RunLoop().RunUntilIdle(); + background_sync_context_ = nullptr; + + // Restore the network observer functionality for subsequent tests + background_sync_test_util::SetIgnoreNetworkChanges(false); +} + +// SetUp helper methods +void BackgroundSyncServiceImplTestHarness::CreateTestHelper() { + embedded_worker_helper_ = + std::make_unique<EmbeddedWorkerTestHelper>((base::FilePath())); + std::unique_ptr<MockPermissionManager> mock_permission_manager = + std::make_unique<testing::NiceMock<MockPermissionManager>>(); + ON_CALL(*mock_permission_manager, + GetPermissionStatus(PermissionType::BACKGROUND_SYNC, _, _)) + .WillByDefault(testing::Return(blink::mojom::PermissionStatus::GRANTED)); + embedded_worker_helper_->browser_context()->SetPermissionControllerDelegate( + std::move(mock_permission_manager)); +} + +void BackgroundSyncServiceImplTestHarness::CreateStoragePartition() { + // Creates a StoragePartition so that the BackgroundSyncManager can + // use it to access the BrowserContext. + storage_partition_impl_ = StoragePartitionImpl::Create( + embedded_worker_helper_->browser_context(), /* in_memory= */ true, + base::FilePath(), /* partition_domain= */ ""); + embedded_worker_helper_->context_wrapper()->set_storage_partition( + storage_partition_impl_.get()); +} + +void BackgroundSyncServiceImplTestHarness::CreateBackgroundSyncContext() { + // Registering for background sync includes a check for having a same-origin + // main frame. Use a test context that allows control over that check. + background_sync_context_ = base::MakeRefCounted<TestBackgroundSyncContext>(); + background_sync_context_->Init( + embedded_worker_helper_->context_wrapper(), + storage_partition_impl_->GetDevToolsBackgroundServicesContext()); + + // Tests do not expect the sync event to fire immediately after + // register (and cleanup up the sync registrations). Prevent the sync + // event from firing by setting the network state to have no connection. + // NOTE: The setup of the network connection must happen after the + // BackgroundSyncManager has been setup, including any asynchronous + // initialization. + base::RunLoop().RunUntilIdle(); + BackgroundSyncNetworkObserver* network_observer = + background_sync_context_->background_sync_manager() + ->GetNetworkObserverForTesting(); + network_observer->NotifyManagerIfConnectionChangedForTesting( + network::mojom::ConnectionType::CONNECTION_NONE); + base::RunLoop().RunUntilIdle(); +} + +void BackgroundSyncServiceImplTestHarness::CreateServiceWorkerRegistration() { + bool called = false; + blink::mojom::ServiceWorkerRegistrationOptions options; + options.scope = GURL(kServiceWorkerScope); + embedded_worker_helper_->context()->RegisterServiceWorker( + GURL(kServiceWorkerScript), options, + base::BindOnce(&RegisterServiceWorkerCallback, &called, + &sw_registration_id_)); + base::RunLoop().RunUntilIdle(); + ASSERT_TRUE(called); + + embedded_worker_helper_->context_wrapper()->FindReadyRegistrationForId( + sw_registration_id_, GURL(kServiceWorkerScope).GetOrigin(), + base::BindOnce(FindServiceWorkerRegistrationCallback, &sw_registration_)); + base::RunLoop().RunUntilIdle(); + EXPECT_TRUE(sw_registration_); +} + +} // namespace content
diff --git a/content/browser/background_sync/background_sync_service_impl_test_harness.h b/content/browser/background_sync/background_sync_service_impl_test_harness.h new file mode 100644 index 0000000..c678da75 --- /dev/null +++ b/content/browser/background_sync/background_sync_service_impl_test_harness.h
@@ -0,0 +1,86 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_BROWSER_BACKGROUND_SYNC_BACKGROUND_SYNC_SERVICE_IMPL_TEST_HARNESS_H_ +#define CONTENT_BROWSER_BACKGROUND_SYNC_BACKGROUND_SYNC_SERVICE_IMPL_TEST_HARNESS_H_ + +#include <memory> + +#include "base/memory/scoped_refptr.h" +#include "content/browser/background_sync/background_sync_context_impl.h" +#include "content/browser/service_worker/embedded_worker_test_helper.h" +#include "content/browser/storage_partition_impl.h" +#include "content/public/test/test_browser_thread_bundle.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/blink/public/mojom/background_sync/background_sync.mojom.h" +#include "third_party/blink/public/mojom/service_worker/service_worker_registration.mojom.h" + +namespace content { + +class BackgroundSyncServiceImplTestHarness : public testing::Test { + public: + static void RegisterServiceWorkerCallback( + bool* called, + int64_t* store_registration_id, + blink::ServiceWorkerStatusCode status, + const std::string& status_message, + int64_t registration_id); + static void FindServiceWorkerRegistrationCallback( + scoped_refptr<ServiceWorkerRegistration>* out_registration, + blink::ServiceWorkerStatusCode status, + scoped_refptr<ServiceWorkerRegistration> registration); + static void ErrorAndRegistrationCallback( + bool* called, + blink::mojom::BackgroundSyncError* out_error, + blink::mojom::SyncRegistrationOptionsPtr* out_registration, + blink::mojom::BackgroundSyncError error, + blink::mojom::SyncRegistrationOptionsPtr registration); + static void ErrorAndRegistrationListCallback( + bool* called, + blink::mojom::BackgroundSyncError* out_error, + unsigned long* out_array_size, + blink::mojom::BackgroundSyncError error, + std::vector<blink::mojom::SyncRegistrationOptionsPtr> registrations); + static void ErrorCallback(bool* called, + blink::mojom::BackgroundSyncError* out_error, + blink::mojom::BackgroundSyncError error); + + BackgroundSyncServiceImplTestHarness(); + ~BackgroundSyncServiceImplTestHarness() override; + + void SetUp() override; + + void TearDown() override; + + protected: + scoped_refptr<BackgroundSyncContextImpl> background_sync_context_; + blink::mojom::SyncRegistrationOptionsPtr default_sync_registration_; + int64_t sw_registration_id_; + + private: + // SetUp helper methods + void CreateTestHelper(); + void CreateStoragePartition(); + void CreateBackgroundSyncContext(); + void CreateServiceWorkerRegistration(); + + // Helpers for testing *BackgroundSyncServiceImpl methods + void RegisterOneShotSync( + blink::mojom::SyncRegistrationOptionsPtr sync, + blink::mojom::OneShotBackgroundSyncService::RegisterCallback callback); + void GetOneShotSyncRegistrations( + blink::mojom::OneShotBackgroundSyncService::GetRegistrationsCallback + callback); + + TestBrowserThreadBundle thread_bundle_; + std::unique_ptr<EmbeddedWorkerTestHelper> embedded_worker_helper_; + std::unique_ptr<StoragePartitionImpl> storage_partition_impl_; + scoped_refptr<ServiceWorkerRegistration> sw_registration_; + + DISALLOW_COPY_AND_ASSIGN(BackgroundSyncServiceImplTestHarness); +}; + +} // namespace content + +#endif // CONTENT_BROWSER_BACKGROUND_SYNC_BACKGROUND_SYNC_SERVICE_IMPL_TEST_HARNESS_H_
diff --git a/content/browser/background_sync/background_sync_service_impl_unittest.cc b/content/browser/background_sync/background_sync_service_impl_unittest.cc deleted file mode 100644 index 45f6a28..0000000 --- a/content/browser/background_sync/background_sync_service_impl_unittest.cc +++ /dev/null
@@ -1,272 +0,0 @@ -// 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. - -#include "content/browser/background_sync/background_sync_service_impl.h" - -#include <stdint.h> - -#include <memory> -#include <utility> - -#include "base/bind.h" -#include "base/bind_helpers.h" -#include "base/run_loop.h" -#include "content/browser/background_sync/background_sync_context_impl.h" -#include "content/browser/background_sync/background_sync_network_observer.h" -#include "content/browser/service_worker/embedded_worker_test_helper.h" -#include "content/browser/service_worker/service_worker_context_wrapper.h" -#include "content/browser/storage_partition_impl.h" -#include "content/public/browser/browser_thread.h" -#include "content/public/browser/permission_type.h" -#include "content/public/test/background_sync_test_util.h" -#include "content/public/test/mock_permission_manager.h" -#include "content/public/test/test_browser_context.h" -#include "content/public/test/test_browser_thread_bundle.h" -#include "content/test/test_background_sync_context.h" -#include "mojo/public/cpp/bindings/interface_ptr.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/blink/public/mojom/service_worker/service_worker_registration.mojom.h" - -namespace content { - -namespace { - -using ::testing::_; - -const char kServiceWorkerScope[] = "https://example.com/a"; -const char kServiceWorkerScript[] = "https://example.com/a/script.js"; - -// Callbacks from SetUp methods -void RegisterServiceWorkerCallback(bool* called, - int64_t* store_registration_id, - blink::ServiceWorkerStatusCode status, - const std::string& status_message, - int64_t registration_id) { - EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk, status) - << blink::ServiceWorkerStatusToString(status); - *called = true; - *store_registration_id = registration_id; -} - -void FindServiceWorkerRegistrationCallback( - scoped_refptr<ServiceWorkerRegistration>* out_registration, - blink::ServiceWorkerStatusCode status, - scoped_refptr<ServiceWorkerRegistration> registration) { - EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk, status) - << blink::ServiceWorkerStatusToString(status); - *out_registration = std::move(registration); -} - -// Callbacks from BackgroundSyncServiceImpl methods - -void ErrorAndRegistrationCallback( - bool* called, - blink::mojom::BackgroundSyncError* out_error, - blink::mojom::SyncRegistrationOptionsPtr* out_registration, - blink::mojom::BackgroundSyncError error, - blink::mojom::SyncRegistrationOptionsPtr registration) { - *called = true; - *out_error = error; - *out_registration = registration.Clone(); -} - -void ErrorAndRegistrationListCallback( - bool* called, - blink::mojom::BackgroundSyncError* out_error, - unsigned long* out_array_size, - blink::mojom::BackgroundSyncError error, - std::vector<blink::mojom::SyncRegistrationOptionsPtr> registrations) { - *called = true; - *out_error = error; - if (error == blink::mojom::BackgroundSyncError::NONE) - *out_array_size = registrations.size(); -} - -} // namespace - -class BackgroundSyncServiceImplTest : public testing::Test { - public: - BackgroundSyncServiceImplTest() - : thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP) { - default_sync_registration_ = blink::mojom::SyncRegistrationOptions::New(); - } - - void SetUp() override { - // Don't let the tests be confused by the real-world device connectivity - background_sync_test_util::SetIgnoreNetworkChanges(true); - - CreateTestHelper(); - CreateStoragePartition(); - CreateBackgroundSyncContext(); - CreateServiceWorkerRegistration(); - CreateBackgroundSyncServiceImpl(); - } - - void TearDown() override { - // This must be explicitly destroyed here to ensure that destruction - // of both the BackgroundSyncContextImpl and the BackgroundSyncManager - // occurs on the correct thread. - background_sync_context_->Shutdown(); - base::RunLoop().RunUntilIdle(); - background_sync_context_ = nullptr; - - // Restore the network observer functionality for subsequent tests - background_sync_test_util::SetIgnoreNetworkChanges(false); - } - - // SetUp helper methods - void CreateTestHelper() { - embedded_worker_helper_ = - std::make_unique<EmbeddedWorkerTestHelper>((base::FilePath())); - std::unique_ptr<MockPermissionManager> mock_permission_manager = - std::make_unique<testing::NiceMock<MockPermissionManager>>(); - ON_CALL(*mock_permission_manager, - GetPermissionStatus(PermissionType::BACKGROUND_SYNC, _, _)) - .WillByDefault( - testing::Return(blink::mojom::PermissionStatus::GRANTED)); - embedded_worker_helper_->browser_context()->SetPermissionControllerDelegate( - std::move(mock_permission_manager)); - } - - void CreateStoragePartition() { - // Creates a StoragePartition so that the BackgroundSyncManager can - // use it to access the BrowserContext. - storage_partition_impl_ = StoragePartitionImpl::Create( - embedded_worker_helper_->browser_context(), /* in_memory= */ true, - base::FilePath(), /* partition_domain= */ ""); - embedded_worker_helper_->context_wrapper()->set_storage_partition( - storage_partition_impl_.get()); - } - - void CreateBackgroundSyncContext() { - // Registering for background sync includes a check for having a same-origin - // main frame. Use a test context that allows control over that check. - background_sync_context_ = - base::MakeRefCounted<TestBackgroundSyncContext>(); - background_sync_context_->Init( - embedded_worker_helper_->context_wrapper(), - storage_partition_impl_->GetDevToolsBackgroundServicesContext()); - - // Tests do not expect the sync event to fire immediately after - // register (and cleanup up the sync registrations). Prevent the sync - // event from firing by setting the network state to have no connection. - // NOTE: The setup of the network connection must happen after the - // BackgroundSyncManager has been setup, including any asynchronous - // initialization. - base::RunLoop().RunUntilIdle(); - BackgroundSyncNetworkObserver* network_observer = - background_sync_context_->background_sync_manager() - ->GetNetworkObserverForTesting(); - network_observer->NotifyManagerIfConnectionChangedForTesting( - network::mojom::ConnectionType::CONNECTION_NONE); - base::RunLoop().RunUntilIdle(); - } - - void CreateServiceWorkerRegistration() { - bool called = false; - blink::mojom::ServiceWorkerRegistrationOptions options; - options.scope = GURL(kServiceWorkerScope); - embedded_worker_helper_->context()->RegisterServiceWorker( - GURL(kServiceWorkerScript), options, - base::BindOnce(&RegisterServiceWorkerCallback, &called, - &sw_registration_id_)); - base::RunLoop().RunUntilIdle(); - EXPECT_TRUE(called); - - embedded_worker_helper_->context_wrapper()->FindReadyRegistrationForId( - sw_registration_id_, GURL(kServiceWorkerScope).GetOrigin(), - base::BindOnce(FindServiceWorkerRegistrationCallback, - &sw_registration_)); - base::RunLoop().RunUntilIdle(); - EXPECT_TRUE(sw_registration_); - } - - void CreateBackgroundSyncServiceImpl() { - // Create a dummy mojo channel so that the BackgroundSyncServiceImpl can be - // instantiated. - mojo::InterfaceRequest<blink::mojom::BackgroundSyncService> - service_request = mojo::MakeRequest(&service_ptr_); - // Create a new BackgroundSyncServiceImpl bound to the dummy channel. - background_sync_context_->CreateService(std::move(service_request)); - base::RunLoop().RunUntilIdle(); - - service_impl_ = background_sync_context_->services_.begin()->first; - ASSERT_TRUE(service_impl_); - } - - // Helpers for testing BackgroundSyncServiceImpl methods - void Register( - blink::mojom::SyncRegistrationOptionsPtr sync, - blink::mojom::BackgroundSyncService::RegisterCallback callback) { - service_impl_->Register(std::move(sync), sw_registration_id_, - std::move(callback)); - base::RunLoop().RunUntilIdle(); - } - - void GetRegistrations( - blink::mojom::BackgroundSyncService::GetOneShotSyncRegistrationsCallback - callback) { - service_impl_->GetOneShotSyncRegistrations(sw_registration_id_, - std::move(callback)); - base::RunLoop().RunUntilIdle(); - } - - TestBrowserThreadBundle thread_bundle_; - std::unique_ptr<EmbeddedWorkerTestHelper> embedded_worker_helper_; - std::unique_ptr<StoragePartitionImpl> storage_partition_impl_; - scoped_refptr<BackgroundSyncContextImpl> background_sync_context_; - int64_t sw_registration_id_; - scoped_refptr<ServiceWorkerRegistration> sw_registration_; - blink::mojom::BackgroundSyncServicePtr service_ptr_; - BackgroundSyncServiceImpl* - service_impl_; // Owned by background_sync_context_ - blink::mojom::SyncRegistrationOptionsPtr default_sync_registration_; -}; - -// Tests - -TEST_F(BackgroundSyncServiceImplTest, Register) { - bool called = false; - blink::mojom::BackgroundSyncError error; - blink::mojom::SyncRegistrationOptionsPtr reg; - Register( - default_sync_registration_.Clone(), - base::BindOnce(&ErrorAndRegistrationCallback, &called, &error, ®)); - EXPECT_TRUE(called); - EXPECT_EQ(blink::mojom::BackgroundSyncError::NONE, error); - EXPECT_EQ("", reg->tag); -} - -TEST_F(BackgroundSyncServiceImplTest, GetRegistrations) { - bool called = false; - blink::mojom::BackgroundSyncError error; - unsigned long array_size = 0UL; - GetRegistrations(base::BindOnce(&ErrorAndRegistrationListCallback, &called, - &error, &array_size)); - EXPECT_TRUE(called); - EXPECT_EQ(blink::mojom::BackgroundSyncError::NONE, error); - EXPECT_EQ(0UL, array_size); -} - -TEST_F(BackgroundSyncServiceImplTest, GetRegistrationsWithRegisteredSync) { - bool register_called = false; - bool get_registrations_called = false; - blink::mojom::BackgroundSyncError register_error; - blink::mojom::BackgroundSyncError getregistrations_error; - blink::mojom::SyncRegistrationOptionsPtr register_reg; - unsigned long array_size = 0UL; - Register(default_sync_registration_.Clone(), - base::BindOnce(&ErrorAndRegistrationCallback, ®ister_called, - ®ister_error, ®ister_reg)); - EXPECT_TRUE(register_called); - EXPECT_EQ(blink::mojom::BackgroundSyncError::NONE, register_error); - GetRegistrations(base::BindOnce(&ErrorAndRegistrationListCallback, - &get_registrations_called, - &getregistrations_error, &array_size)); - EXPECT_TRUE(get_registrations_called); - EXPECT_EQ(blink::mojom::BackgroundSyncError::NONE, getregistrations_error); - EXPECT_EQ(1UL, array_size); -} - -} // namespace content
diff --git a/content/browser/background_sync/one_shot_background_sync_service_impl.cc b/content/browser/background_sync/one_shot_background_sync_service_impl.cc new file mode 100644 index 0000000..3db6e37 --- /dev/null +++ b/content/browser/background_sync/one_shot_background_sync_service_impl.cc
@@ -0,0 +1,76 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/browser/background_sync/one_shot_background_sync_service_impl.h" + +#include <utility> + +#include "base/bind.h" +#include "base/memory/weak_ptr.h" +#include "base/stl_util.h" +#include "content/browser/background_sync/background_sync_context_impl.h" +#include "content/public/browser/browser_thread.h" + +namespace content { + +OneShotBackgroundSyncServiceImpl::OneShotBackgroundSyncServiceImpl( + BackgroundSyncContextImpl* background_sync_context, + mojo::InterfaceRequest<blink::mojom::OneShotBackgroundSyncService> request) + : background_sync_context_(background_sync_context), + binding_(this, std::move(request)), + weak_ptr_factory_(this) { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + DCHECK(background_sync_context_); + + registration_helper_ = std::make_unique<BackgroundSyncRegistrationHelper>( + background_sync_context_); + + binding_.set_connection_error_handler(base::BindOnce( + &OneShotBackgroundSyncServiceImpl::OnConnectionError, + base::Unretained(this) /* the channel is owned by |this| */)); +} + +OneShotBackgroundSyncServiceImpl::~OneShotBackgroundSyncServiceImpl() { + DCHECK_CURRENTLY_ON(BrowserThread::IO); +} + +void OneShotBackgroundSyncServiceImpl::OnConnectionError() { + background_sync_context_->OneShotSyncServiceHadConnectionError(this); + // |this| is now deleted. +} + +void OneShotBackgroundSyncServiceImpl::Register( + blink::mojom::SyncRegistrationOptionsPtr options, + int64_t sw_registration_id, + RegisterCallback callback) { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + + registration_helper_->Register(std::move(options), sw_registration_id, + std::move(callback)); +} + +void OneShotBackgroundSyncServiceImpl::DidResolveRegistration( + blink::mojom::BackgroundSyncRegistrationInfoPtr registration_info) { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + + registration_helper_->DidResolveRegistration(std::move(registration_info)); +} + +void OneShotBackgroundSyncServiceImpl::GetRegistrations( + int64_t sw_registration_id, + GetRegistrationsCallback callback) { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + + BackgroundSyncManager* background_sync_manager = + background_sync_context_->background_sync_manager(); + DCHECK(background_sync_manager); + + background_sync_manager->GetOneShotSyncRegistrations( + sw_registration_id, + base::BindOnce( + &BackgroundSyncRegistrationHelper::OnGetRegistrationsResult, + registration_helper_->GetWeakPtr(), std::move(callback))); +} + +} // namespace content
diff --git a/content/browser/background_sync/one_shot_background_sync_service_impl.h b/content/browser/background_sync/one_shot_background_sync_service_impl.h new file mode 100644 index 0000000..67ef7d1 --- /dev/null +++ b/content/browser/background_sync/one_shot_background_sync_service_impl.h
@@ -0,0 +1,64 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_BROWSER_BACKGROUND_SYNC_ONE_SHOT_BACKGROUND_SYNC_SERVICE_IMPL_H_ +#define CONTENT_BROWSER_BACKGROUND_SYNC_ONE_SHOT_BACKGROUND_SYNC_SERVICE_IMPL_H_ + +#include <stdint.h> + +#include <memory> +#include <string> +#include <vector> + +#include "base/macros.h" +#include "base/memory/weak_ptr.h" +#include "content/browser/background_sync/background_sync_manager.h" +#include "content/browser/background_sync/background_sync_registration_helper.h" +#include "mojo/public/cpp/bindings/binding.h" +#include "third_party/blink/public/mojom/background_sync/background_sync.mojom.h" + +namespace content { + +class BackgroundSyncContextImpl; + +class CONTENT_EXPORT OneShotBackgroundSyncServiceImpl + : public blink::mojom::OneShotBackgroundSyncService { + public: + OneShotBackgroundSyncServiceImpl( + BackgroundSyncContextImpl* background_sync_context, + mojo::InterfaceRequest<blink::mojom::OneShotBackgroundSyncService> + request); + + ~OneShotBackgroundSyncServiceImpl() override; + + private: + friend class OneShotBackgroundSyncServiceImplTest; + + // blink::mojom::OneShotBackgroundSyncService methods: + void Register(blink::mojom::SyncRegistrationOptionsPtr options, + int64_t sw_registration_id, + RegisterCallback callback) override; + void DidResolveRegistration(blink::mojom::BackgroundSyncRegistrationInfoPtr + registration_info) override; + void GetRegistrations(int64_t sw_registration_id, + GetRegistrationsCallback callback) override; + + // Called when an error is detected on |binding_|. + void OnConnectionError(); + + // |background_sync_context_| owns |this|. + BackgroundSyncContextImpl* const background_sync_context_; + + std::unique_ptr<BackgroundSyncRegistrationHelper> registration_helper_; + mojo::Binding<blink::mojom::OneShotBackgroundSyncService> binding_; + + base::WeakPtrFactory<blink::mojom::OneShotBackgroundSyncService> + weak_ptr_factory_; + + DISALLOW_COPY_AND_ASSIGN(OneShotBackgroundSyncServiceImpl); +}; + +} // namespace content + +#endif // CONTENT_BROWSER_BACKGROUND_SYNC_ONE_SHOT_BACKGROUND_SYNC_SERVICE_IMPL_H_
diff --git a/content/browser/background_sync/one_shot_background_sync_service_impl_unittest.cc b/content/browser/background_sync/one_shot_background_sync_service_impl_unittest.cc new file mode 100644 index 0000000..aff4b12 --- /dev/null +++ b/content/browser/background_sync/one_shot_background_sync_service_impl_unittest.cc
@@ -0,0 +1,111 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/browser/background_sync/one_shot_background_sync_service_impl.h" + +#include "content/browser/background_sync/background_sync_service_impl_test_harness.h" + +namespace content { + +class OneShotBackgroundSyncServiceImplTest + : public BackgroundSyncServiceImplTestHarness { + public: + OneShotBackgroundSyncServiceImplTest() = default; + ~OneShotBackgroundSyncServiceImplTest() override = default; + + void SetUp() override { + BackgroundSyncServiceImplTestHarness::SetUp(); + CreateOneShotBackgroundSyncServiceImpl(); + } + + protected: + void CreateOneShotBackgroundSyncServiceImpl() { + // Create a dummy mojo channel so that the OneShotBackgroundSyncServiceImpl + // can be instantiated. + mojo::InterfaceRequest<blink::mojom::OneShotBackgroundSyncService> + service_request = mojo::MakeRequest(&one_shot_sync_service_ptr_); + // Create a new OneShotBackgroundSyncServiceImpl bound to the dummy channel. + background_sync_context_->CreateOneShotSyncService( + std::move(service_request)); + base::RunLoop().RunUntilIdle(); + + // Since |background_sync_context_| is deleted after + // OneShotBackgroundSyncServiceImplTest is, this is safe. + one_shot_sync_service_impl_ = + background_sync_context_->one_shot_sync_services_.begin()->get(); + ASSERT_TRUE(one_shot_sync_service_impl_); + } + + // Helpers for testing *BackgroundSyncServiceImpl methods + void RegisterOneShotSync( + blink::mojom::SyncRegistrationOptionsPtr sync, + blink::mojom::OneShotBackgroundSyncService::RegisterCallback callback) { + one_shot_sync_service_impl_->Register(std::move(sync), sw_registration_id_, + std::move(callback)); + base::RunLoop().RunUntilIdle(); + } + + void GetOneShotSyncRegistrations( + blink::mojom::OneShotBackgroundSyncService::GetRegistrationsCallback + callback) { + one_shot_sync_service_impl_->GetRegistrations(sw_registration_id_, + std::move(callback)); + base::RunLoop().RunUntilIdle(); + } + + blink::mojom::OneShotBackgroundSyncServicePtr one_shot_sync_service_ptr_; + + // Owned by |background_sync_context_| + OneShotBackgroundSyncServiceImpl* one_shot_sync_service_impl_; +}; + +// Tests + +TEST_F(OneShotBackgroundSyncServiceImplTest, RegisterOneShotSync) { + bool called = false; + blink::mojom::BackgroundSyncError error; + blink::mojom::SyncRegistrationOptionsPtr reg; + RegisterOneShotSync( + default_sync_registration_.Clone(), + base::BindOnce(&ErrorAndRegistrationCallback, &called, &error, ®)); + ASSERT_TRUE(called); + EXPECT_EQ(blink::mojom::BackgroundSyncError::NONE, error); + EXPECT_EQ("", reg->tag); +} + +TEST_F(OneShotBackgroundSyncServiceImplTest, + GetOneShotSyncRegistrationsNoSyncRegistered) { + bool called = false; + blink::mojom::BackgroundSyncError error; + unsigned long array_size = 0UL; + GetOneShotSyncRegistrations(base::BindOnce(&ErrorAndRegistrationListCallback, + &called, &error, &array_size)); + ASSERT_TRUE(called); + EXPECT_EQ(blink::mojom::BackgroundSyncError::NONE, error); + EXPECT_EQ(0UL, array_size); +} + +TEST_F(OneShotBackgroundSyncServiceImplTest, + GetOneShotSyncRegistrationsWithRegisteredSync) { + bool register_called = false; + bool get_registrations_called = false; + blink::mojom::BackgroundSyncError register_error; + blink::mojom::BackgroundSyncError get_registrations_error; + blink::mojom::SyncRegistrationOptionsPtr registered_reg; + unsigned long array_size = 0UL; + RegisterOneShotSync( + default_sync_registration_.Clone(), + base::BindOnce(&ErrorAndRegistrationCallback, ®ister_called, + ®ister_error, ®istered_reg)); + ASSERT_TRUE(register_called); + EXPECT_EQ(blink::mojom::BackgroundSyncError::NONE, register_error); + GetOneShotSyncRegistrations(base::BindOnce( + &ErrorAndRegistrationListCallback, &get_registrations_called, + &get_registrations_error, &array_size)); + ASSERT_TRUE(get_registrations_called); + EXPECT_EQ(blink::mojom::BackgroundSyncError::NONE, get_registrations_error); + EXPECT_EQ(1UL, array_size); +} + +} // namespace content
diff --git a/content/browser/background_sync/periodic_background_sync_service_impl.cc b/content/browser/background_sync/periodic_background_sync_service_impl.cc new file mode 100644 index 0000000..a1436ed --- /dev/null +++ b/content/browser/background_sync/periodic_background_sync_service_impl.cc
@@ -0,0 +1,95 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/browser/background_sync/periodic_background_sync_service_impl.h" + +#include <utility> + +#include "base/bind.h" +#include "content/browser/background_sync/background_sync_context_impl.h" +#include "content/public/browser/browser_thread.h" + +namespace content { + +PeriodicBackgroundSyncServiceImpl::PeriodicBackgroundSyncServiceImpl( + BackgroundSyncContextImpl* background_sync_context, + mojo::InterfaceRequest<blink::mojom::PeriodicBackgroundSyncService> request) + : background_sync_context_(background_sync_context), + binding_(this, std::move(request)), + weak_ptr_factory_(this) { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + DCHECK(background_sync_context_); + + registration_helper_ = std::make_unique<BackgroundSyncRegistrationHelper>( + background_sync_context_); + DCHECK(registration_helper_); + + binding_.set_connection_error_handler(base::BindOnce( + &PeriodicBackgroundSyncServiceImpl::OnConnectionError, + base::Unretained(this) /* the channel is owned by this */)); +} + +PeriodicBackgroundSyncServiceImpl::~PeriodicBackgroundSyncServiceImpl() { + DCHECK_CURRENTLY_ON(BrowserThread::IO); +} + +void PeriodicBackgroundSyncServiceImpl::OnConnectionError() { + background_sync_context_->PeriodicSyncServiceHadConnectionError(this); + // |this| is now deleted. +} + +void PeriodicBackgroundSyncServiceImpl::Register( + blink::mojom::SyncRegistrationOptionsPtr options, + int64_t sw_registration_id, + RegisterCallback callback) { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + + registration_helper_->Register(std::move(options), sw_registration_id, + std::move(callback)); +} + +void PeriodicBackgroundSyncServiceImpl::Unregister( + int64_t sw_registration_id, + const std::string& tag, + UnregisterCallback callback) { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + + BackgroundSyncManager* background_sync_manager = + background_sync_context_->background_sync_manager(); + DCHECK(background_sync_manager); + background_sync_manager->UnregisterPeriodicSync( + sw_registration_id, tag, + base::BindOnce(&PeriodicBackgroundSyncServiceImpl::OnUnregisterResult, + weak_ptr_factory_.GetWeakPtr(), std::move(callback))); +} + +void PeriodicBackgroundSyncServiceImpl::GetRegistrations( + int64_t sw_registration_id, + GetRegistrationsCallback callback) { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + + BackgroundSyncManager* background_sync_manager = + background_sync_context_->background_sync_manager(); + DCHECK(background_sync_manager); + + // BackgroundSyncContextImpl owns both PeriodicBackgroundSyncServiceImpl and + // BackgroundSyncManager. The manager will be destroyed after the service, + // thus passing the |registration_helper_| pointer is safe here. + background_sync_manager->GetPeriodicSyncRegistrations( + sw_registration_id, + base::BindOnce( + &BackgroundSyncRegistrationHelper::OnGetRegistrationsResult, + registration_helper_->GetWeakPtr(), std::move(callback))); +} + +void PeriodicBackgroundSyncServiceImpl::OnUnregisterResult( + UnregisterCallback callback, + BackgroundSyncStatus status) { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + + std::move(callback).Run( + static_cast<blink::mojom::BackgroundSyncError>(status)); +} + +} // namespace content
diff --git a/content/browser/background_sync/periodic_background_sync_service_impl.h b/content/browser/background_sync/periodic_background_sync_service_impl.h new file mode 100644 index 0000000..d2d8b38 --- /dev/null +++ b/content/browser/background_sync/periodic_background_sync_service_impl.h
@@ -0,0 +1,68 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_BROWSER_BACKGROUND_SYNC_PERIODIC_BACKGROUND_SYNC_SERVICE_IMPL_H_ +#define CONTENT_BROWSER_BACKGROUND_SYNC_PERIODIC_BACKGROUND_SYNC_SERVICE_IMPL_H_ + +#include <stdint.h> + +#include <memory> +#include <string> +#include <vector> + +#include "base/macros.h" +#include "base/memory/ref_counted.h" +#include "base/memory/weak_ptr.h" +#include "content/browser/background_sync/background_sync_manager.h" +#include "content/browser/background_sync/background_sync_registration_helper.h" +#include "mojo/public/cpp/bindings/binding.h" +#include "third_party/blink/public/mojom/background_sync/background_sync.mojom.h" + +namespace content { + +class BackgroundSyncContextImpl; + +class CONTENT_EXPORT PeriodicBackgroundSyncServiceImpl + : public blink::mojom::PeriodicBackgroundSyncService { + public: + PeriodicBackgroundSyncServiceImpl( + BackgroundSyncContextImpl* background_sync_context, + mojo::InterfaceRequest<blink::mojom::PeriodicBackgroundSyncService> + request); + + ~PeriodicBackgroundSyncServiceImpl() override; + + private: + friend class PeriodicBackgroundSyncServiceImplTest; + + // blink::mojom::BackgroundSyncService methods: + void Register(blink::mojom::SyncRegistrationOptionsPtr options, + int64_t sw_registration_id, + RegisterCallback callback) override; + void Unregister(int64_t sw_registration_id, + const std::string& tag, + UnregisterCallback callback) override; + void GetRegistrations(int64_t sw_registration_id, + GetRegistrationsCallback callback) override; + + void OnUnregisterResult(UnregisterCallback callback, + BackgroundSyncStatus status); + + // Called when an error is detected on |binding_|. + void OnConnectionError(); + + // |background_sync_context_| owns |this|. + BackgroundSyncContextImpl* background_sync_context_; + + std::unique_ptr<BackgroundSyncRegistrationHelper> registration_helper_; + mojo::Binding<blink::mojom::PeriodicBackgroundSyncService> binding_; + + base::WeakPtrFactory<PeriodicBackgroundSyncServiceImpl> weak_ptr_factory_; + + DISALLOW_COPY_AND_ASSIGN(PeriodicBackgroundSyncServiceImpl); +}; + +} // namespace content + +#endif // CONTENT_BROWSER_BACKGROUND_SYNC_PERIODIC_BACKGROUND_SYNC_SERVICE_IMPL_H_
diff --git a/content/browser/background_sync/periodic_background_sync_service_impl_unittest.cc b/content/browser/background_sync/periodic_background_sync_service_impl_unittest.cc new file mode 100644 index 0000000..e8290dd --- /dev/null +++ b/content/browser/background_sync/periodic_background_sync_service_impl_unittest.cc
@@ -0,0 +1,177 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/browser/background_sync/periodic_background_sync_service_impl.h" + +#include "content/browser/background_sync/background_sync_service_impl_test_harness.h" + +namespace content { + +class PeriodicBackgroundSyncServiceImplTest + : public BackgroundSyncServiceImplTestHarness { + public: + PeriodicBackgroundSyncServiceImplTest() = default; + + void SetUp() override { + BackgroundSyncServiceImplTestHarness::SetUp(); + CreatePeriodicBackgroundSyncServiceImpl(); + } + + protected: + void CreatePeriodicBackgroundSyncServiceImpl() { + // Create a dummy mojo channel so that the PeriodicBackgroundSyncServiceImpl + // can be instantiated. + mojo::InterfaceRequest<blink::mojom::PeriodicBackgroundSyncService> + service_request = mojo::MakeRequest(&periodic_sync_service_ptr_); + // Create a new PeriodicBackgroundSyncServiceImpl bound to the dummy + // channel. + background_sync_context_->CreatePeriodicSyncService( + std::move(service_request)); + base::RunLoop().RunUntilIdle(); + + // Since |background_sync_context_| is deleted after + // PeriodicBackgroundSyncServiceImplTest is, this is safe. + periodic_sync_service_impl_ = + background_sync_context_->periodic_sync_services_.begin()->get(); + ASSERT_TRUE(periodic_sync_service_impl_); + } + + // Helpers for testing *BackgroundSyncServiceImpl methods + void RegisterPeriodicSync( + blink::mojom::SyncRegistrationOptionsPtr sync, + blink::mojom::PeriodicBackgroundSyncService::RegisterCallback callback) { + periodic_sync_service_impl_->Register(std::move(sync), sw_registration_id_, + std::move(callback)); + base::RunLoop().RunUntilIdle(); + } + + void UnregisterPeriodicSync( + const std::string& tag, + blink::mojom::PeriodicBackgroundSyncService::UnregisterCallback + callback) { + periodic_sync_service_impl_->Unregister(sw_registration_id_, tag, + std::move(callback)); + base::RunLoop().RunUntilIdle(); + } + + void GetPeriodicSyncRegistrations( + blink::mojom::PeriodicBackgroundSyncService::GetRegistrationsCallback + callback) { + periodic_sync_service_impl_->GetRegistrations(sw_registration_id_, + std::move(callback)); + base::RunLoop().RunUntilIdle(); + } + + blink::mojom::PeriodicBackgroundSyncServicePtr periodic_sync_service_ptr_; + + // Owned by |background_sync_context_| + PeriodicBackgroundSyncServiceImpl* periodic_sync_service_impl_; +}; + +// Tests + +TEST_F(PeriodicBackgroundSyncServiceImplTest, RegisterPeriodicSync) { + bool called = false; + blink::mojom::BackgroundSyncError error; + blink::mojom::SyncRegistrationOptionsPtr reg; + auto to_register = default_sync_registration_.Clone(); + to_register->min_interval = 3600; + RegisterPeriodicSync( + std::move(to_register), + base::BindOnce(&ErrorAndRegistrationCallback, &called, &error, ®)); + ASSERT_TRUE(called); + EXPECT_EQ(blink::mojom::BackgroundSyncError::NONE, error); + EXPECT_EQ("", reg->tag); + EXPECT_EQ(3600, reg->min_interval); +} + +TEST_F(PeriodicBackgroundSyncServiceImplTest, + GetPeriodicSyncRegistrationsNoSyncRegistered) { + bool called = false; + blink::mojom::BackgroundSyncError error; + unsigned long array_size = 0UL; + GetPeriodicSyncRegistrations(base::BindOnce(&ErrorAndRegistrationListCallback, + &called, &error, &array_size)); + ASSERT_TRUE(called); + EXPECT_EQ(blink::mojom::BackgroundSyncError::NONE, error); + EXPECT_EQ(0UL, array_size); +} + +TEST_F(PeriodicBackgroundSyncServiceImplTest, + GetPeriodicSyncRegistrationsWithRegisteredSync) { + { + bool called = false; + blink::mojom::BackgroundSyncError error; + blink::mojom::SyncRegistrationOptionsPtr registered_reg; + + auto to_register = default_sync_registration_.Clone(); + to_register->min_interval = 3600; + + RegisterPeriodicSync(std::move(to_register), + base::BindOnce(&ErrorAndRegistrationCallback, &called, + &error, ®istered_reg)); + ASSERT_TRUE(called); + EXPECT_EQ(blink::mojom::BackgroundSyncError::NONE, error); + } + + { + bool called = false; + blink::mojom::BackgroundSyncError error; + unsigned long array_size = 0UL; + GetPeriodicSyncRegistrations(base::BindOnce( + &ErrorAndRegistrationListCallback, &called, &error, &array_size)); + ASSERT_TRUE(called); + EXPECT_EQ(blink::mojom::BackgroundSyncError::NONE, error); + EXPECT_EQ(1UL, array_size); + } +} + +TEST_F(PeriodicBackgroundSyncServiceImplTest, Unregister) { + { + bool called = false; + blink::mojom::BackgroundSyncError error; + + UnregisterPeriodicSync("non_existent", + base::BindOnce(&ErrorCallback, &called, &error)); + ASSERT_TRUE(called); + EXPECT_EQ(blink::mojom::BackgroundSyncError::NONE, error); + } + + { + bool called = false; + blink::mojom::BackgroundSyncError error; + blink::mojom::SyncRegistrationOptionsPtr reg; + auto to_register = default_sync_registration_.Clone(); + to_register->tag = "shared_tag"; + to_register->min_interval = 3600; + RegisterPeriodicSync( + std::move(to_register), + base::BindOnce(&ErrorAndRegistrationCallback, &called, &error, ®)); + ASSERT_TRUE(called); + EXPECT_EQ(blink::mojom::BackgroundSyncError::NONE, error); + EXPECT_EQ("shared_tag", reg->tag); + EXPECT_EQ(3600, reg->min_interval); + } + { + bool called = false; + blink::mojom::BackgroundSyncError error; + + UnregisterPeriodicSync("shared_tag", + base::BindOnce(&ErrorCallback, &called, &error)); + ASSERT_TRUE(called); + EXPECT_EQ(blink::mojom::BackgroundSyncError::NONE, error); + } + { + bool called = false; + blink::mojom::BackgroundSyncError error; + unsigned long array_size = 0UL; + GetPeriodicSyncRegistrations(base::BindOnce( + &ErrorAndRegistrationListCallback, &called, &error, &array_size)); + ASSERT_TRUE(called); + EXPECT_EQ(blink::mojom::BackgroundSyncError::NONE, error); + EXPECT_EQ(0UL, array_size); + } +} + +} // namespace content
diff --git a/content/browser/devtools/protocol/tracing_handler.cc b/content/browser/devtools/protocol/tracing_handler.cc index 7c85d7f9..5748f64 100644 --- a/content/browser/devtools/protocol/tracing_handler.cc +++ b/content/browser/devtools/protocol/tracing_handler.cc
@@ -243,6 +243,7 @@ size_t approximate_event_count)> on_buffer_usage_callback) = 0; virtual bool HasTracingFailed() = 0; + virtual bool HasDataLossOccurred() = 0; private: DISALLOW_COPY_AND_ASSIGN(TracingSession); @@ -285,6 +286,7 @@ } bool HasTracingFailed() override { return false; } + bool HasDataLossOccurred() override { return false; } }; class TracingHandler::PerfettoTracingSession @@ -338,6 +340,8 @@ void ChangeTraceConfig( const base::trace_event::TraceConfig& chrome_config) override { + if (!tracing_session_host_) + return; auto perfetto_config = CreatePerfettoConfiguration(chrome_config); tracing_session_host_->ChangeTraceConfig(perfetto_config); } @@ -358,9 +362,10 @@ tracing_active_ = false; if (!tracing_session_host_) { - if (endpoint_) + if (endpoint_) { + // Will delete |this|. endpoint_->ReceiveTraceFinalContents(nullptr); - + } return; } @@ -391,28 +396,22 @@ void GetBufferUsage(base::OnceCallback<void(float percent_full, size_t approximate_event_count)> on_buffer_usage_callback) override { + if (!tracing_session_host_) { + std::move(on_buffer_usage_callback).Run(0.0f, 0); + return; + } DCHECK(on_buffer_usage_callback); tracing_session_host_->RequestBufferUsage(base::BindOnce( &PerfettoTracingSession::OnBufferUsage, base::Unretained(this), std::move(on_buffer_usage_callback))); } - void OnBufferUsage(base::OnceCallback<void(float percent_full, - size_t approximate_event_count)> - on_buffer_usage_callback, - bool success, - float percent_full) { - if (!success) { - std::move(on_buffer_usage_callback).Run(0.0f, 0); - return; - } - std::move(on_buffer_usage_callback).Run(percent_full, 0); - } - bool HasTracingFailed() override { return tracing_active_ && !tracing_session_host_; } + bool HasDataLossOccurred() override { return data_loss_; } + // tracing::mojom::TracingSessionClient implementation: void OnTracingEnabled() override { if (on_recording_enabled_callback_) { @@ -484,10 +483,25 @@ if (endpoint_) { // TODO(oysteine): Signal to the client that tracing failed. + // Will delete |this|. endpoint_->ReceiveTraceFinalContents(nullptr); } } + void OnBufferUsage(base::OnceCallback<void(float percent_full, + size_t approximate_event_count)> + on_buffer_usage_callback, + bool success, + float percent_full, + bool data_loss) { + if (!success) { + std::move(on_buffer_usage_callback).Run(0.0f, 0); + return; + } + data_loss_ |= data_loss; + std::move(on_buffer_usage_callback).Run(percent_full, 0); + } + // mojo::DataPipeDrainer::Client implementation: void OnDataAvailable(const void* data, size_t num_bytes) override { auto data_string = std::make_unique<std::string>( @@ -507,10 +521,19 @@ void MaybeTraceComplete() { if (read_buffers_complete_ && data_complete_ && endpoint_) { - endpoint_->ReceiveTraceFinalContents(nullptr); + // Request stats to check if data loss occurred. + GetBufferUsage(base::BindOnce(&PerfettoTracingSession::OnFinalBufferUsage, + base::Unretained(this))); } } + void OnFinalBufferUsage(float percent_full, size_t approximate_event_count) { + if (!endpoint_) + return; + // Will delete |this|. + endpoint_->ReceiveTraceFinalContents(nullptr); + } + mojo::Binding<tracing::mojom::TracingSessionClient> binding_{this}; tracing::mojom::TracingSessionHostPtr tracing_session_host_; @@ -526,6 +549,7 @@ bool data_complete_ = false; bool read_buffers_complete_ = false; bool tracing_active_ = false; + bool data_loss_ = false; #if DCHECK_IS_ON() base::trace_event::TraceConfig last_config_for_perfetto_; @@ -630,8 +654,9 @@ DCHECK(!trace_data_buffer_state_.in_string); DCHECK(!trace_data_buffer_state_.slashed); + bool data_loss = session_->HasDataLossOccurred(); session_.reset(); - frontend_->TracingComplete(); + frontend_->TracingComplete(data_loss); } std::string TracingHandler::UpdateTraceDataBuffer( @@ -693,13 +718,15 @@ } void TracingHandler::OnTraceToStreamComplete(const std::string& stream_handle) { + bool data_loss = session_->HasDataLossOccurred(); session_.reset(); std::string stream_format = (proto_format_ ? Tracing::StreamFormatEnum::Proto : Tracing::StreamFormatEnum::Json); std::string stream_compression = (gzip_compression_ ? Tracing::StreamCompressionEnum::Gzip : Tracing::StreamCompressionEnum::None); - frontend_->TracingComplete(stream_handle, stream_format, stream_compression); + frontend_->TracingComplete(data_loss, stream_handle, stream_format, + stream_compression); } void TracingHandler::Start(Maybe<std::string> categories,
diff --git a/content/browser/frame_host/navigation_controller_impl_browsertest.cc b/content/browser/frame_host/navigation_controller_impl_browsertest.cc index 639f749..ab14fcf 100644 --- a/content/browser/frame_host/navigation_controller_impl_browsertest.cc +++ b/content/browser/frame_host/navigation_controller_impl_browsertest.cc
@@ -9893,4 +9893,54 @@ shell()->web_contents()->GetLastCommittedURL()); } +// Tests a renderer aborting the navigation it started, while still waiting on a +// long cross-process subframe beforeunload handler. +// Regression test: https://crbug.com/972154 +IN_PROC_BROWSER_TEST_F( + NavigationControllerBrowserTest, + NavigationAbortDuringLongCrossProcessIframeBeforeUnload) { + // This test relies on the main frame and the iframe to live in different + // processes. This allows one renderer process to cancel a navigation while + // the other renderer process is busy executing its beforeunload handler. + if (!AreAllSitesIsolatedForTesting()) + return; + + const GURL main_url(embedded_test_server()->GetURL( + "a.com", "/cross_site_iframe_factory.html?a(b)")); + const GURL navigated_url( + embedded_test_server()->GetURL("a.com", "/title1.html")); + + WebContentsImpl* web_contents = + static_cast<WebContentsImpl*>(shell()->web_contents()); + FrameTreeNode* root = web_contents->GetFrameTree()->root(); + + // Have a first page with a cross process iframe. + // The iframe itself does have a dialog-showing beforeunload handler. + EXPECT_TRUE(NavigateToURL(shell(), main_url)); + std::string script = + "window.addEventListener('beforeunload', function (event) {" + " event.returnValue='blocked'" + "});"; + EXPECT_TRUE(ExecJs(root->child_at(0), script)); + + TestNavigationObserver load_observer(web_contents); + NavigationHandleObserver abort_observer(web_contents, navigated_url); + BeforeUnloadBlockingDelegate beforeunload_pauser(web_contents); + + // Navigate to any page, renderer initiated. + EXPECT_TRUE(ExecJs(shell(), "location.href = 'title1.html'")); + + // The previous navigation is paused while the beforeunloadhandler dialog is + // shown to the user. In the meantime, the navigation is aborted: + beforeunload_pauser.Wait(); + EXPECT_TRUE(ExecJs(shell(), "document.write()")); // Cancel the navigation. + + // Wait for javascript to get processed, and its consequences (aborting the + // navigation) to finish. To achieve that we simply wait for DidStopLoading. + load_observer.Wait(); + + // Verify that the navigation was aborted as expected. + EXPECT_FALSE(abort_observer.has_committed()); +} + } // namespace content
diff --git a/content/browser/frame_host/navigation_handle_impl.cc b/content/browser/frame_host/navigation_handle_impl.cc index d08ff01..5fb77b4 100644 --- a/content/browser/frame_host/navigation_handle_impl.cc +++ b/content/browser/frame_host/navigation_handle_impl.cc
@@ -264,10 +264,6 @@ return navigation_request_->auth_challenge_info(); } -bool NavigationHandleImpl::IsWaitingToCommit() { - return state() == NavigationRequest::READY_TO_COMMIT; -} - bool NavigationHandleImpl::HasCommitted() { return state() == NavigationRequest::DID_COMMIT || state() == NavigationRequest::DID_COMMIT_ERROR_PAGE;
diff --git a/content/browser/frame_host/navigation_handle_impl.h b/content/browser/frame_host/navigation_handle_impl.h index 6519d7a97..282c7f2 100644 --- a/content/browser/frame_host/navigation_handle_impl.h +++ b/content/browser/frame_host/navigation_handle_impl.h
@@ -216,11 +216,6 @@ return navigation_request_->GetDeferringThrottleForTesting(); } - // Whether the navigation was sent to be committed in a renderer by the - // RenderFrameHost. This can either be for the commit of a successful - // navigation or an error page. - bool IsWaitingToCommit(); - // Sets the READY_TO_COMMIT -> DID_COMMIT timeout. Resets the timeout to the // default value if |timeout| is zero. static void SetCommitTimeoutForTesting(const base::TimeDelta& timeout);
diff --git a/content/browser/frame_host/navigation_request.cc b/content/browser/frame_host/navigation_request.cc index 988e426..2948001c 100644 --- a/content/browser/frame_host/navigation_request.cc +++ b/content/browser/frame_host/navigation_request.cc
@@ -2335,7 +2335,7 @@ } void NavigationRequest::OnRendererAbortedNavigation() { - if (navigation_handle_->IsWaitingToCommit()) { + if (IsWaitingToCommit()) { render_frame_host_->NavigationRequestCancelled(this); } else { frame_tree_node_->navigator()->CancelNavigation(frame_tree_node_, false); @@ -2854,4 +2854,8 @@ return std::move(appcache_handle_); } +bool NavigationRequest::IsWaitingToCommit() { + return handle_state_ == NavigationRequest::READY_TO_COMMIT; +} + } // namespace content
diff --git a/content/browser/frame_host/navigation_request.h b/content/browser/frame_host/navigation_request.h index cb210ba..0048ff7 100644 --- a/content/browser/frame_host/navigation_request.h +++ b/content/browser/frame_host/navigation_request.h
@@ -708,6 +708,11 @@ // |handle_state_| and inform the delegate. void ReadyToCommitNavigation(bool is_error); + // Whether the navigation was sent to be committed in a renderer by the + // RenderFrameHost. This can either be for the commit of a successful + // navigation or an error page. + bool IsWaitingToCommit(); + FrameTreeNode* frame_tree_node_; // Invariant: At least one of |loader_| or |render_frame_host_| is null.
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc index bcd8236..644e87e9 100644 --- a/content/browser/frame_host/render_frame_host_impl.cc +++ b/content/browser/frame_host/render_frame_host_impl.cc
@@ -477,6 +477,9 @@ /* is_service_worker = */ false, process_id, frame_id); } +// TODO(crbug.com/977040): Remove when no longer needed. +const uint32_t kMaxCookieSameSiteDeprecationUrls = 20; + } // namespace class RenderFrameHostImpl::DroppedInterfaceRequestLogger @@ -6706,8 +6709,11 @@ std::move(navigation_request), is_same_document_navigation); - if (!is_same_document_navigation) + if (!is_same_document_navigation) { scheduler_tracked_features_ = 0; + cookie_no_samesite_deprecation_url_hashes_.clear(); + cookie_samesite_none_insecure_deprecation_url_hashes_.clear(); + } return true; } @@ -7157,4 +7163,64 @@ discard_duplicates)); } +void RenderFrameHostImpl::AddSameSiteCookieDeprecationMessage( + const std::string& cookie_url, + net::CanonicalCookie::CookieInclusionStatus status) { + std::string deprecation_message; + if (status == net::CanonicalCookie::CookieInclusionStatus:: + EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX) { + if (!ShouldAddCookieSameSiteDeprecationMessage( + cookie_url, &cookie_no_samesite_deprecation_url_hashes_)) { + return; + } + deprecation_message = + "[Deprecation] A cookie associated with a cross-site resource at " + + cookie_url + + " was set without the `SameSite` attribute. " + "A future release of Chrome will only deliver cookies with " + "cross-site requests if they are set with `SameSite=None`. You " + "can review cookies in developer tools under " + "Application>Storage>Cookies and see more details at " + "https://www.chromestatus.com/feature/5088147346030592."; + } + if (status == net::CanonicalCookie::CookieInclusionStatus:: + EXCLUDE_SAMESITE_NONE_INSECURE) { + if (!ShouldAddCookieSameSiteDeprecationMessage( + cookie_url, + &cookie_samesite_none_insecure_deprecation_url_hashes_)) { + return; + } + deprecation_message = + "[Deprecation] A cookie associated with a resource at " + cookie_url + + " was set with `SameSite=None` but without `Secure`. " + "A future release of Chrome will only deliver cookies marked " + "`SameSite=None` if they are also marked `Secure`. You " + "can review cookies in developer tools under " + "Application>Storage>Cookies and see more details at " + "https://www.chromestatus.com/feature/5633521622188032."; + } + + if (deprecation_message.empty()) + return; + + AddUniqueMessageToConsole(blink::mojom::ConsoleMessageLevel::kWarning, + deprecation_message); +} + +bool RenderFrameHostImpl::ShouldAddCookieSameSiteDeprecationMessage( + const std::string& cookie_url, + base::circular_deque<size_t>* already_seen_url_hashes) { + DCHECK_LE(already_seen_url_hashes->size(), kMaxCookieSameSiteDeprecationUrls); + size_t cookie_url_hash = base::FastHash(cookie_url); + if (base::Contains(*already_seen_url_hashes, cookie_url_hash)) + return false; + + // Put most recent ones at the front because we are likely to have multiple + // consecutive cookies with the same URL. + if (already_seen_url_hashes->size() == kMaxCookieSameSiteDeprecationUrls) + already_seen_url_hashes->pop_back(); + already_seen_url_hashes->push_front(cookie_url_hash); + return true; +} + } // namespace content
diff --git a/content/browser/frame_host/render_frame_host_impl.h b/content/browser/frame_host/render_frame_host_impl.h index 34ca3ed..2316121 100644 --- a/content/browser/frame_host/render_frame_host_impl.h +++ b/content/browser/frame_host/render_frame_host_impl.h
@@ -18,6 +18,7 @@ #include "base/callback.h" #include "base/compiler_specific.h" +#include "base/containers/circular_deque.h" #include "base/containers/flat_set.h" #include "base/containers/id_map.h" #include "base/gtest_prod_util.h" @@ -59,6 +60,7 @@ #include "mojo/public/cpp/bindings/binding_set.h" #include "mojo/public/cpp/system/data_pipe.h" #include "net/base/network_isolation_key.h" +#include "net/cookies/canonical_cookie.h" #include "net/http/http_response_headers.h" #include "services/device/public/mojom/wake_lock_context.mojom.h" #include "services/service_manager/public/cpp/binder_registry.h" @@ -948,6 +950,12 @@ blink::mojom::ConsoleMessageLevel level, const std::string& message); + // Add cookie SameSite deprecation messages to the DevTools console. + // TODO(crbug.com/977040): Remove when no longer needed. + void AddSameSiteCookieDeprecationMessage( + const std::string& cookie_url, + net::CanonicalCookie::CookieInclusionStatus status); + protected: friend class RenderFrameHostFactory; @@ -1653,6 +1661,13 @@ const std::string& message, bool discard_duplicates); + // Returns whether a cookie SameSite deprecation message should be sent for + // the given cookie url. + // TODO(crbug.com/977040): Remove when no longer needed. + bool ShouldAddCookieSameSiteDeprecationMessage( + const std::string& cookie_url, + base::circular_deque<size_t>* already_seen_url_hashes); + // For now, RenderFrameHosts indirectly keep RenderViewHosts alive via a // refcount that calls Shutdown when it reaches zero. This allows each // RenderFrameHostManager to just care about RenderFrameHosts, while ensuring @@ -2160,6 +2175,15 @@ // every document commit. net::NetworkIsolationKey network_isolation_key_; + // Hold onto hashes of the last |kMaxCookieSameSiteDeprecationUrls| cookie + // URLs that we have seen since the last committed navigation, in order to + // partially deduplicate the corresponding cookie SameSite deprecation + // messages. + // TODO(crbug.com/977040): Remove when no longer needed. + base::circular_deque<size_t> cookie_no_samesite_deprecation_url_hashes_; + base::circular_deque<size_t> + cookie_samesite_none_insecure_deprecation_url_hashes_; + // NOTE: This must be the last member. base::WeakPtrFactory<RenderFrameHostImpl> weak_ptr_factory_;
diff --git a/content/browser/frame_host/render_frame_message_filter.cc b/content/browser/frame_host/render_frame_message_filter.cc index 5548296..cf137f0 100644 --- a/content/browser/frame_host/render_frame_message_filter.cc +++ b/content/browser/frame_host/render_frame_message_filter.cc
@@ -201,6 +201,7 @@ // Send deprecation messages to the console about cookies that would be excluded // due to either SameSiteByDefaultCookies or CookiesWithoutSameSiteMustBeSecure. +// TODO(crbug.com/977040): Remove when no longer needed. void SendDeprecationMessagesForSameSiteCookiesOnUI( int render_process_id, int render_frame_id, @@ -234,39 +235,24 @@ base::FeatureList::IsEnabled(features::kCookieDeprecationMessages); for (const auto& cookie_with_status : deprecated_cookies) { + std::string cookie_url = net::cookie_util::CookieOriginToURL( + cookie_with_status.cookie.Domain(), + cookie_with_status.cookie.IsSecure()) + .possibly_invalid_spec(); if (cookie_with_status.status == net::CanonicalCookie::CookieInclusionStatus:: EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX) { log_unspecified_treated_as_lax_metric = true; - if (emit_messages) { - root_frame_host->AddUniqueMessageToConsole( - blink::mojom::ConsoleMessageLevel::kWarning, - "[Deprecation] A cookie associated with a cross-site resource at " + - url.possibly_invalid_spec() + - " was set without the `SameSite` attribute. " - "A future release of Chrome will only deliver cookies with " - "cross-site requests if they are set with `SameSite=None`. You " - "can review cookies in developer tools under " - "Application>Storage>Cookies and see more details at " - "https://www.chromestatus.com/feature/5088147346030592."); - } } if (cookie_with_status.status == net::CanonicalCookie::CookieInclusionStatus:: EXCLUDE_SAMESITE_NONE_INSECURE) { log_none_insecure_metric = true; - if (emit_messages) { - root_frame_host->AddUniqueMessageToConsole( - blink::mojom::ConsoleMessageLevel::kWarning, - "[Deprecation] A cookie associated with a resource at " + - url.possibly_invalid_spec() + - " was set with `SameSite=None` but without `Secure`. " - "A future release of Chrome will only deliver cookies marked " - "`SameSite=None` if they are also marked `Secure`. You " - "can review cookies in developer tools under " - "Application>Storage>Cookies and see more details at " - "https://www.chromestatus.com/feature/5633521622188032."); - } + } + + if (emit_messages) { + root_frame_host->AddSameSiteCookieDeprecationMessage( + cookie_url, cookie_with_status.status); } }
diff --git a/content/browser/network_service_client.cc b/content/browser/network_service_client.cc index 5ec9f0b..19ba39a 100644 --- a/content/browser/network_service_client.cc +++ b/content/browser/network_service_client.cc
@@ -427,6 +427,7 @@ } #endif +// TODO(crbug.com/977040): Remove when no longer needed. void DeprecateSameSiteCookies(int process_id, int routing_id, const net::CookieStatusList& excluded_cookies) { @@ -480,37 +481,14 @@ net::CanonicalCookie::CookieInclusionStatus:: EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX) { samesite_treated_as_lax_cookies = true; - - if (emit_messages) { - root_frame_host->AddUniqueMessageToConsole( - blink::mojom::ConsoleMessageLevel::kWarning, - "[Deprecation] A cookie associated with a cross-site resource at " + - cookie_url + - " was set without the `SameSite` attribute. " - "A future release of Chrome will only deliver cookies with " - "cross-site requests if they are set with `SameSite=None`. You " - "can review cookies in developer tools under " - "Application>Storage>Cookies and see more details at " - "https://www.chromestatus.com/feature/5088147346030592."); - } } - if (excluded_cookie.status == net::CanonicalCookie::CookieInclusionStatus:: EXCLUDE_SAMESITE_NONE_INSECURE) { samesite_none_insecure_cookies = true; - - if (emit_messages) { - root_frame_host->AddUniqueMessageToConsole( - blink::mojom::ConsoleMessageLevel::kWarning, - "[Deprecation] A cookie associated with a resource at " + - cookie_url + - " was set with `SameSite=None` but without `Secure`. " - "A future release of Chrome will only deliver cookies marked " - "`SameSite=None` if they are also marked `Secure`. You " - "can review cookies in developer tools under " - "Application>Storage>Cookies and see more details at " - "https://www.chromestatus.com/feature/5633521622188032."); - } + } + if (emit_messages) { + root_frame_host->AddSameSiteCookieDeprecationMessage( + cookie_url, excluded_cookie.status); } }
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc index 568f32799..3fd664133 100644 --- a/content/browser/renderer_host/render_process_host_impl.cc +++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -74,7 +74,8 @@ #include "content/browser/appcache/chrome_appcache_service.h" #include "content/browser/background_fetch/background_fetch_context.h" #include "content/browser/background_fetch/background_fetch_service_impl.h" -#include "content/browser/background_sync/background_sync_service_impl.h" +#include "content/browser/background_sync/one_shot_background_sync_service_impl.h" +#include "content/browser/background_sync/periodic_background_sync_service_impl.h" #include "content/browser/bad_message.h" #include "content/browser/blob_storage/blob_dispatcher_host.h" #include "content/browser/blob_storage/blob_registry_wrapper.h" @@ -2032,7 +2033,13 @@ AddUIThreadInterface( registry.get(), base::BindRepeating( - &BackgroundSyncContextImpl::CreateService, + &BackgroundSyncContextImpl::CreateOneShotSyncService, + base::Unretained( + storage_partition_impl_->GetBackgroundSyncContext()))); + AddUIThreadInterface( + registry.get(), + base::BindRepeating( + &BackgroundSyncContextImpl::CreatePeriodicSyncService, base::Unretained( storage_partition_impl_->GetBackgroundSyncContext()))); AddUIThreadInterface( @@ -3123,20 +3130,12 @@ renderer_cmd->AppendSwitch(switches::kDisableGpuCompositing); } #elif !defined(OS_CHROMEOS) -#if !BUILDFLAG(ENABLE_MUS) // If gpu compositing is not being used, tell the renderer at startup. This // is inherently racey, as it may change while the renderer is being launched, // but the renderer will hear about the correct state eventually. This // optimizes the common case to avoid wasted work. - // Note: There is no ImageTransportFactory with Mus, but there is also no - // software compositing on platforms where Mus is used, e.g. ChromeOS, so - // no need to check this state and forward it. if (ImageTransportFactory::GetInstance()->IsGpuCompositingDisabled()) renderer_cmd->AppendSwitch(switches::kDisableGpuCompositing); -#else // BUILDFLAG(ENABLE_MUS) -// TODO(tonikitoo): Check if renderer should use software compositing -// through some mechanism that isn't ImageTransportFactory with mus. -#endif // !BUILDFLAG(ENABLE_MUS) #endif // defined(OS_ANDROID) // Add kWaitForDebugger to let renderer process wait for a debugger.
diff --git a/content/browser/scheduler/browser_io_task_environment.cc b/content/browser/scheduler/browser_io_task_environment.cc index f899b38..75a18d9 100644 --- a/content/browser/scheduler/browser_io_task_environment.cc +++ b/content/browser/scheduler/browser_io_task_environment.cc
@@ -33,9 +33,7 @@ task_queues_ = std::make_unique<BrowserTaskQueues>( BrowserThread::IO, sequence_manager, sequence_manager->GetRealTimeDomain()); - default_task_queue_ = sequence_manager->CreateTaskQueue( - TaskQueue::Spec("browser_io_task_environment_default_tq")); - default_task_runner_ = default_task_queue_->task_runner(); + default_task_runner_ = task_queues_->CreateHandle().GetDefaultTaskRunner(); } scoped_refptr<base::SingleThreadTaskRunner>
diff --git a/content/browser/scheduler/browser_io_task_environment.h b/content/browser/scheduler/browser_io_task_environment.h index 9225196..7d47e10 100644 --- a/content/browser/scheduler/browser_io_task_environment.h +++ b/content/browser/scheduler/browser_io_task_environment.h
@@ -64,7 +64,6 @@ std::unique_ptr<base::sequence_manager::SequenceManager> sequence_manager_; std::unique_ptr<BrowserTaskQueues> task_queues_; - scoped_refptr<base::sequence_manager::TaskQueue> default_task_queue_; scoped_refptr<base::SingleThreadTaskRunner> default_task_runner_; };
diff --git a/content/browser/site_per_process_unload_browsertest.cc b/content/browser/site_per_process_unload_browsertest.cc index 639aa942..fa788b9 100644 --- a/content/browser/site_per_process_unload_browsertest.cc +++ b/content/browser/site_per_process_unload_browsertest.cc
@@ -29,7 +29,6 @@ #include "content/browser/renderer_host/render_widget_host_view_child_frame.h" #include "content/browser/web_contents/web_contents_impl.h" #include "content/common/frame_messages.h" -#include "content/public/browser/javascript_dialog_manager.h" #include "content/public/browser/navigation_handle.h" #include "content/public/common/url_constants.h" #include "content/public/test/browser_test_utils.h" @@ -308,73 +307,6 @@ EXPECT_TRUE(watcher.did_exit_normally()); } -class TestWCBeforeUnloadDelegate : public JavaScriptDialogManager, - public WebContentsDelegate { - public: - explicit TestWCBeforeUnloadDelegate(WebContentsImpl* web_contents) - : web_contents_(web_contents) { - web_contents_->SetDelegate(this); - } - - ~TestWCBeforeUnloadDelegate() override { - if (!callback_.is_null()) - std::move(callback_).Run(true, base::string16()); - - web_contents_->SetDelegate(nullptr); - web_contents_->SetJavaScriptDialogManagerForTesting(nullptr); - } - - void Wait() { - run_loop_->Run(); - run_loop_ = std::make_unique<base::RunLoop>(); - } - - // WebContentsDelegate - - JavaScriptDialogManager* GetJavaScriptDialogManager( - WebContents* source) override { - return this; - } - - // JavaScriptDialogManager - - void RunJavaScriptDialog(WebContents* web_contents, - RenderFrameHost* render_frame_host, - JavaScriptDialogType dialog_type, - const base::string16& message_text, - const base::string16& default_prompt_text, - DialogClosedCallback callback, - bool* did_suppress_message) override { - NOTREACHED(); - } - - void RunBeforeUnloadDialog(WebContents* web_contents, - RenderFrameHost* render_frame_host, - bool is_reload, - DialogClosedCallback callback) override { - callback_ = std::move(callback); - run_loop_->Quit(); - } - - bool HandleJavaScriptDialog(WebContents* web_contents, - bool accept, - const base::string16* prompt_override) override { - NOTREACHED(); - return true; - } - - void CancelDialogs(WebContents* web_contents, bool reset_state) override {} - - private: - WebContentsImpl* web_contents_; - - DialogClosedCallback callback_; - - std::unique_ptr<base::RunLoop> run_loop_ = std::make_unique<base::RunLoop>(); - - DISALLOW_COPY_AND_ASSIGN(TestWCBeforeUnloadDelegate); -}; - // This is a regression test for https://crbug.com/891423 in which tabs showing // beforeunload dialogs stalled navigation and triggered the "hung process" // dialog. @@ -407,7 +339,7 @@ base::string16()); // Hang the first contents in a beforeunload dialog. - TestWCBeforeUnloadDelegate test_delegate(web_contents); + BeforeUnloadBlockingDelegate test_delegate(web_contents); EXPECT_TRUE( ExecJs(web_contents, "window.onbeforeunload=function(e){ return 'x' }")); EXPECT_TRUE(ExecJs(web_contents,
diff --git a/content/browser/storage_partition_impl.h b/content/browser/storage_partition_impl.h index 264be9e0..8d28440 100644 --- a/content/browser/storage_partition_impl.h +++ b/content/browser/storage_partition_impl.h
@@ -239,7 +239,7 @@ class URLLoaderFactoryForBrowserProcess; friend class BackgroundSyncManagerTest; - friend class BackgroundSyncServiceImplTest; + friend class BackgroundSyncServiceImplTestHarness; friend class CookieStoreManagerTest; friend class PaymentAppContentUnitTestBase; friend class StoragePartitionImplMap;
diff --git a/content/browser/web_contents/web_contents_impl.h b/content/browser/web_contents/web_contents_impl.h index a6513ded..3b7c4a0c 100644 --- a/content/browser/web_contents/web_contents_impl.h +++ b/content/browser/web_contents/web_contents_impl.h
@@ -100,7 +100,7 @@ class SavePackage; class ScreenOrientationProvider; class SiteInstance; -class TestWCBeforeUnloadDelegate; // site_per_process_browsertest.cc +class BeforeUnloadBlockingDelegate; // content_browser_test_utils_internal.h class TestWCDelegateForDialogsAndFullscreen; // web_contents_impl_browsertest.cc class TestWebContents; @@ -1047,7 +1047,7 @@ friend class RenderFrameHostImplBeforeUnloadBrowserTest; friend class WebContentsImplBrowserTest; - friend class TestWCBeforeUnloadDelegate; + friend class BeforeUnloadBlockingDelegate; friend class TestWCDelegateForDialogsAndFullscreen; FRIEND_TEST_ALL_PREFIXES(WebContentsImplTest, NoJSMessageOnInterstitials);
diff --git a/content/public/app/BUILD.gn b/content/public/app/BUILD.gn index 98feda5..b31fcd54 100644 --- a/content/public/app/BUILD.gn +++ b/content/public/app/BUILD.gn
@@ -45,10 +45,6 @@ "//services/service_manager/public/cpp", ] -if (enable_mus) { - public_app_shared_deps += [ "//ui/aura" ] -} - if (is_component_build) { source_set("both_sources") { # Only the main content shared library can pull this in.
diff --git a/content/public/app/content_browser_manifest.cc b/content/public/app/content_browser_manifest.cc index 44a2e08..bd656493 100644 --- a/content/public/app/content_browser_manifest.cc +++ b/content/public/app/content_browser_manifest.cc
@@ -54,7 +54,6 @@ "renderer", std::set<const char*>{ "blink.mojom.AppCacheBackend", - "blink.mojom.BackgroundSyncService", "blink.mojom.BlobRegistry", "blink.mojom.BroadcastChannelProvider", "blink.mojom.ClipboardHost", @@ -66,6 +65,8 @@ "blink.mojom.Hyphenation", "blink.mojom.MediaStreamTrackMetricsHost", "blink.mojom.MimeRegistry", + "blink.mojom.OneShotBackgroundSyncService", + "blink.mojom.PeriodicBackgroundSyncService", "blink.mojom.PluginRegistry", "blink.mojom.PushMessaging", "blink.mojom.ReportingServiceProxy",
diff --git a/content/public/browser/download_manager.h b/content/public/browser/download_manager.h index 2a3db81..78eb41c 100644 --- a/content/public/browser/download_manager.h +++ b/content/public/browser/download_manager.h
@@ -213,11 +213,6 @@ virtual BrowserContext* GetBrowserContext() = 0; - // Checks whether downloaded files still exist. Updates state of downloads - // that refer to removed files. The check runs in the background and may - // finish asynchronously after this method returns. - virtual void CheckForHistoryFilesRemoval() = 0; - // Called when download history query completes. Call // |load_history_downloads_cb| to load all the history downloads. virtual void OnHistoryQueryComplete(
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn index 1c87c41..d605716 100644 --- a/content/test/BUILD.gn +++ b/content/test/BUILD.gn
@@ -1446,7 +1446,10 @@ "../browser/background_sync/background_sync_launcher_unittest.cc", "../browser/background_sync/background_sync_manager_unittest.cc", "../browser/background_sync/background_sync_network_observer_unittest.cc", - "../browser/background_sync/background_sync_service_impl_unittest.cc", + "../browser/background_sync/background_sync_service_impl_test_harness.cc", + "../browser/background_sync/background_sync_service_impl_test_harness.h", + "../browser/background_sync/one_shot_background_sync_service_impl_unittest.cc", + "../browser/background_sync/periodic_background_sync_service_impl_unittest.cc", "../browser/blob_storage/blob_url_unittest.cc", "../browser/bluetooth/bluetooth_allowed_devices_unittest.cc", "../browser/bluetooth/bluetooth_blocklist_unittest.cc",
diff --git a/content/test/content_browser_test_utils_internal.cc b/content/test/content_browser_test_utils_internal.cc index 20309b8..d411eb23 100644 --- a/content/test/content_browser_test_utils_internal.cc +++ b/content/test/content_browser_test_utils_internal.cc
@@ -25,6 +25,7 @@ #include "content/browser/frame_host/render_frame_host_delegate.h" #include "content/browser/frame_host/render_frame_proxy_host.h" #include "content/browser/renderer_host/delegated_frame_host.h" +#include "content/browser/web_contents/web_contents_impl.h" #include "content/common/frame_visual_properties.h" #include "content/common/view_messages.h" #include "content/public/browser/browser_task_traits.h" @@ -495,4 +496,56 @@ run_loop_.Quit(); } +BeforeUnloadBlockingDelegate::BeforeUnloadBlockingDelegate( + WebContentsImpl* web_contents) + : web_contents_(web_contents) { + web_contents_->SetDelegate(this); +} + +BeforeUnloadBlockingDelegate::~BeforeUnloadBlockingDelegate() { + if (!callback_.is_null()) + std::move(callback_).Run(true, base::string16()); + + web_contents_->SetDelegate(nullptr); + web_contents_->SetJavaScriptDialogManagerForTesting(nullptr); +} + +void BeforeUnloadBlockingDelegate::Wait() { + run_loop_->Run(); + run_loop_ = std::make_unique<base::RunLoop>(); +} + +JavaScriptDialogManager* +BeforeUnloadBlockingDelegate::GetJavaScriptDialogManager(WebContents* source) { + return this; +} + +void BeforeUnloadBlockingDelegate::RunJavaScriptDialog( + WebContents* web_contents, + RenderFrameHost* render_frame_host, + JavaScriptDialogType dialog_type, + const base::string16& message_text, + const base::string16& default_prompt_text, + DialogClosedCallback callback, + bool* did_suppress_message) { + NOTREACHED(); +} + +void BeforeUnloadBlockingDelegate::RunBeforeUnloadDialog( + WebContents* web_contents, + RenderFrameHost* render_frame_host, + bool is_reload, + DialogClosedCallback callback) { + callback_ = std::move(callback); + run_loop_->Quit(); +} + +bool BeforeUnloadBlockingDelegate::HandleJavaScriptDialog( + WebContents* web_contents, + bool accept, + const base::string16* prompt_override) { + NOTREACHED(); + return true; +} + } // namespace content
diff --git a/content/test/content_browser_test_utils_internal.h b/content/test/content_browser_test_utils_internal.h index 19a4cae0..07ff509 100644 --- a/content/test/content_browser_test_utils_internal.h +++ b/content/test/content_browser_test_utils_internal.h
@@ -24,6 +24,7 @@ #include "build/build_config.h" #include "content/browser/bad_message.h" #include "content/common/frame_messages.h" +#include "content/public/browser/javascript_dialog_manager.h" #include "content/public/browser/resource_dispatcher_host_delegate.h" #include "content/public/browser/web_contents_delegate.h" #include "content/public/test/browser_test_utils.h" @@ -294,6 +295,51 @@ DISALLOW_COPY_AND_ASSIGN(UnresponsiveRendererObserver); }; +// Helper class that overrides the JavaScriptDialogManager of a WebContents +// to endlessly block on beforeunload. +class BeforeUnloadBlockingDelegate : public JavaScriptDialogManager, + public WebContentsDelegate { + public: + explicit BeforeUnloadBlockingDelegate(WebContentsImpl* web_contents); + ~BeforeUnloadBlockingDelegate() override; + void Wait(); + + // WebContentsDelegate + + JavaScriptDialogManager* GetJavaScriptDialogManager( + WebContents* source) override; + + // JavaScriptDialogManager + + void RunJavaScriptDialog(WebContents* web_contents, + RenderFrameHost* render_frame_host, + JavaScriptDialogType dialog_type, + const base::string16& message_text, + const base::string16& default_prompt_text, + DialogClosedCallback callback, + bool* did_suppress_message) override; + + void RunBeforeUnloadDialog(WebContents* web_contents, + RenderFrameHost* render_frame_host, + bool is_reload, + DialogClosedCallback callback) override; + + bool HandleJavaScriptDialog(WebContents* web_contents, + bool accept, + const base::string16* prompt_override) override; + + void CancelDialogs(WebContents* web_contents, bool reset_state) override {} + + private: + WebContentsImpl* web_contents_; + + DialogClosedCallback callback_; + + std::unique_ptr<base::RunLoop> run_loop_ = std::make_unique<base::RunLoop>(); + + DISALLOW_COPY_AND_ASSIGN(BeforeUnloadBlockingDelegate); +}; + } // namespace content #endif // CONTENT_TEST_CONTENT_BROWSER_TEST_UTILS_INTERNAL_H_
diff --git a/content/test/gpu/gpu_tests/gpu_helper.py b/content/test/gpu/gpu_tests/gpu_helper.py index 4ec98cd..fd6231e 100644 --- a/content/test/gpu/gpu_tests/gpu_helper.py +++ b/content/test/gpu/gpu_tests/gpu_helper.py
@@ -3,6 +3,7 @@ # found in the LICENSE file. import re +import mock def _ParseANGLEGpuVendorString(device_string): if not device_string: @@ -95,3 +96,24 @@ if "UseSkiaRenderer" in o: return 'skia-renderer' return 'no-skia-renderer' + +# used by unittests to create a mock arguments object +def GetMockArgs(is_asan=False, webgl_version='1.0.0'): + args = mock.MagicMock() + args.is_asan = is_asan + args.webgl_conformance_version = webgl_version + args.webgl2_only = False + args.url = 'https://www.google.com' + args.duration = 10 + args.delay = 10 + args.resolution = 100 + args.fullscreen = False + args.underlay = False + args.logdir = '/tmp' + args.repeat = 1 + args.outliers = 0 + args.bypass_ipg = False + args.expected_vendor_id = 0 + args.expected_device_id = 0 + args.browser_options = [] + return args
diff --git a/content/test/gpu/gpu_tests/gpu_integration_test_unittest.py b/content/test/gpu/gpu_tests/gpu_integration_test_unittest.py index 5b0ae9e..03f4fdd 100644 --- a/content/test/gpu/gpu_tests/gpu_integration_test_unittest.py +++ b/content/test/gpu/gpu_tests/gpu_integration_test_unittest.py
@@ -11,47 +11,20 @@ import sys import run_gpu_integration_test import gpu_project_config -import inspect -import itertools -from collections import defaultdict +from gpu_tests import context_lost_integration_test +from gpu_tests import gpu_helper +from gpu_tests import gpu_integration_test +from gpu_tests import path_util +from gpu_tests import webgl_conformance_integration_test from telemetry.testing import browser_test_runner from telemetry.testing import fakes from telemetry.internal.platform import system_info -from gpu_tests import context_lost_integration_test -from gpu_tests import gpu_integration_test -from gpu_tests import path_util -from gpu_tests import pixel_integration_test -from gpu_tests import pixel_test_pages -from gpu_tests import webgl_conformance_integration_test -from gpu_tests import webgl_test_util - -from py_utils import discover -from typ import expectations_parser -from typ import json_results - path_util.AddDirToPathIfNeeded(path_util.GetChromiumSrcDir(), 'tools', 'perf') from chrome_telemetry_build import chromium_config -OS_CONDITIONS = ['win', 'mac', 'android'] -GPU_CONDITIONS = ['amd', 'arm', 'broadcom', 'hisilicon', 'intel', 'imagination', - 'nvidia', 'qualcomm', 'vivante'] -WIN_CONDITIONS = ['xp', 'vista', 'win7', 'win8', 'win10'] -MAC_CONDITIONS = ['leopard', 'snowleopard', 'lion', 'mountainlion', - 'mavericks', 'yosemite', 'sierra', 'highsierra', 'mojave'] -# These aren't expanded out into "lollipop", "marshmallow", etc. -ANDROID_CONDITIONS = ['l', 'm', 'n', 'o', 'p', 'q'] -GENERIC_CONDITIONS = OS_CONDITIONS + GPU_CONDITIONS - -_map_specific_to_generic = {sos:'win' for sos in WIN_CONDITIONS} -_map_specific_to_generic.update({sos:'mac' for sos in MAC_CONDITIONS}) -_map_specific_to_generic.update({sos:'android' for sos in ANDROID_CONDITIONS}) - -_get_generic = lambda tags: set( - [_map_specific_to_generic.get(tag, tag) for tag in tags]) - VENDOR_NVIDIA = 0x10DE VENDOR_AMD = 0x1002 VENDOR_INTEL = 0x8086 @@ -59,28 +32,6 @@ VENDOR_STRING_IMAGINATION = 'Imagination Technologies' DEVICE_STRING_SGX = 'PowerVR SGX 554' -ResultType = json_results.ResultType - -def _GetMockArgs(is_asan=False, webgl_version='1.0.0'): - args = mock.MagicMock() - args.is_asan = is_asan - args.webgl_conformance_version = webgl_version - args.webgl2_only = False - args.url = 'https://www.google.com' - args.duration = 10 - args.delay = 10 - args.resolution = 100 - args.fullscreen = False - args.underlay = False - args.logdir = '/tmp' - args.repeat = 1 - args.outliers = 0 - args.bypass_ipg = False - args.expected_vendor_id = 0 - args.expected_device_id = 0 - args.browser_options = [] - return args - def _GetSystemInfo( gpu='', device='', vendor_string='', @@ -108,7 +59,7 @@ try: possible_browser = fakes.FakePossibleBrowser() possible_browser._returned_browser = browser - args = args or _GetMockArgs() + args = args or gpu_helper.GetMockArgs() ret = set(gpu_tests.GenerateTags(args, possible_browser)) finally: gpu_tests.ExpectationsFiles = expectations_fn @@ -131,202 +82,6 @@ return ret -def _CheckTestExpectationsAreForExistingTests( - test_class, mock_options, test_names=None): - test_names = test_names or [ - args[0] for args in - test_class.GenerateGpuTests(mock_options)] - expectations_file = test_class.ExpectationsFiles()[0] - trie = {} - for test in test_names: - _trie = trie.setdefault(test[0], {}) - for l in test[1:]: - _trie = _trie.setdefault(l, {}) - f = open(expectations_file, 'r') - expectations_file = os.path.basename(expectations_file) - expectations = f.read() - f.close() - parser = expectations_parser.TaggedTestListParser(expectations) - for exp in parser.expectations: - _trie = trie - for l in exp.test: - if l == '*': - break - assert l in _trie, ( - "%s:%d: Glob '%s' does not match with any tests in the %s test suite" % - (expectations_file, exp.lineno, exp.test, test_class.Name())) - _trie = _trie[l] - - -def _IsCollision(s1, s2): - # s1 collides with s2 when s1 is a subset of s2 - # A tag is in both sets if its a generic tag - # and its in one set while a specifc tag covered by the generic tag is in - # the other set. - for tag in s1: - if (not tag in s2 and not ( - tag in GENERIC_CONDITIONS and - any(_map_specific_to_generic.get(t, t) == tag for t in s2)) and - not _map_specific_to_generic.get(tag, tag) in s2): - return False - return True - - -def _ConflictLeaksRegression(possible_collision, exp): - reason_template = ( - 'Pattern \'{0}\' on line {1} has the %s expectation however the ' - 'the pattern on \'{2}\' line {3} has the Pass expectation'). format( - possible_collision.test, possible_collision.lineno, exp.test, - exp.lineno) - causes_regression = not( - ResultType.Failure in exp.results or ResultType.Skip in exp.results) - if (ResultType.Skip in possible_collision.results and - causes_regression): - return reason_template % 'Skip' - if (ResultType.Failure in possible_collision.results and - causes_regression): - return reason_template % 'Failure' - return '' - - -def _MapGpuDevicesToVendors(tag_sets): - for tag_set in tag_sets: - if any(gpu in tag_set for gpu in GPU_CONDITIONS): - _map_specific_to_generic.update( - {t[0]: t[1] for t in - itertools.permutations(tag_set, 2) if (t[0] + '-').startswith(t[1])}) - break - - -def _CheckTestExpectationGlobsForCollision(expectations, file_name): - """This function looks for collisions between test expectations with patterns - that match with test expectation patterns that are globs. A test expectation - collides with another if its pattern matches with another's glob and if its - tags is a super set of the other expectation's tags. The less specific test - expectation must have a failure or skip expectation while the more specific - test expectation does not. The more specific test expectation will trump - the less specific test expectation and may cause an unexpected regression. - - Args: - expectations: A string containing test expectations in the new format - file_name: Name of the file that the test expectations came from - """ - master_conflicts_found = False - error_msg = '' - trie = {} - parser = expectations_parser.TaggedTestListParser(expectations) - globs_to_expectations = defaultdict(list) - - _MapGpuDevicesToVendors(parser.tag_sets) - - for exp in parser.expectations: - _trie = trie.setdefault(exp.test[0], {}) - for l in exp.test[1:]: - _trie = _trie.setdefault(l, {}) - _trie.setdefault('$', []).append(exp) - - for exp in parser.expectations: - _trie = trie - glob = '' - for l in exp.test: - if '*' in _trie: - globs_to_expectations[glob + '*'].append(exp) - glob += l - if l in _trie: - _trie = _trie[l] - else: - break - if '*' in _trie: - globs_to_expectations[glob + '*'].append(exp) - - for glob, expectations in globs_to_expectations.items(): - conflicts_found = False - globs_to_match = [e for e in expectations if e.test == glob] - matched_to_globs = [e for e in expectations if e.test != glob] - for match in matched_to_globs: - for possible_collision in globs_to_match: - reason = _ConflictLeaksRegression(possible_collision, match) - if (reason and - _IsCollision(possible_collision.tags, match.tags)): - if not conflicts_found: - error_msg += ('\n\nFound conflicts for pattern %s in %s:\n' % - (glob, file_name)) - master_conflicts_found = conflicts_found = True - error_msg += (' line %d conflicts with line %d: %s\n' % - (possible_collision.lineno, match.lineno, reason)) - assert not master_conflicts_found, error_msg - - -def _CheckTestExpectationPatternsForCollision(expectations, file_name): - """This function makes sure that any test expectations that have the same - pattern do not collide with each other. They collide when one expectation's - tags are a subset of the other expectation's tags. If the expectation with - the larger tag set is active during a test run, then the expectation's whose - tag set is a subset of the tags will be active as well. - - Args: - expectations: A string containing test expectations in the new format - file_name: Name of the file that the test expectations came from - """ - parser = expectations_parser.TaggedTestListParser(expectations) - tests_to_exps = defaultdict(list) - master_conflicts_found = False - error_msg = '' - _MapGpuDevicesToVendors(parser.tag_sets) - - for exp in parser.expectations: - tests_to_exps[exp.test].append(exp) - for pattern, exps in tests_to_exps.items(): - conflicts_found = False - for e1, e2 in itertools.combinations(exps, 2): - if _IsCollision(e1.tags, e2.tags) or _IsCollision(e2.tags, e1.tags): - if not conflicts_found: - error_msg += ('\n\nFound conflicts for test %s in %s:\n' % - (pattern, file_name)) - master_conflicts_found = conflicts_found = True - error_msg += (' line %d conflicts with line %d\n' % - (e1.lineno, e2.lineno)) - assert not master_conflicts_found, error_msg - - -def _CheckPatternIsValid(pattern): - if not '*' in pattern and not 'WebglExtension_' in pattern: - full_path = os.path.normpath(os.path.join( - webgl_test_util.conformance_path, pattern)) - if not os.path.exists(full_path): - raise Exception('The WebGL conformance test path specified in ' + - 'expectation does not exist: ' + full_path) - - -def _TestCheckTestExpectationsAreForExistingTests(expectations): - options = _GetMockArgs() - expectations_file = tempfile.NamedTemporaryFile(delete=False) - expectations_file.write(expectations) - expectations_file.close() - gpu_tests = gpu_integration_test.GpuIntegrationTest - generate_gpu_fn = gpu_tests.GenerateGpuTests - expectations_files_fn = gpu_tests.ExpectationsFiles - gpu_tests.GenerateGpuTests = mock.MagicMock(return_value=[('a/b/c', ())]) - gpu_tests.ExpectationsFiles = mock.MagicMock( - return_value=[expectations_file.name]) - try: - _CheckTestExpectationsAreForExistingTests(gpu_tests, options) - finally: - gpu_tests.GenerateGpuTests = generate_gpu_fn - gpu_tests.ExpectationsFiles = expectations_files_fn - - -def _FindTestCases(): - test_cases = [] - for start_dir in gpu_project_config.CONFIG.start_dirs: - modules_to_classes = discover.DiscoverClasses( - start_dir, - gpu_project_config.CONFIG.top_level_dir, - base_class=gpu_integration_test.GpuIntegrationTest) - test_cases.extend(modules_to_classes.values()) - return test_cases - - class GpuIntegrationTestUnittest(unittest.TestCase): def setUp(self): self._test_state = {} @@ -352,232 +107,6 @@ finally: temp_file.close() - def testCollisionInTestExpectationsWithSpecifcAndGenericOsTags(self): - test_expectations = '''# tags: [ mac win linux xp ] - # tags: [ intel amd nvidia ] - # tags: [ debug release ] - [ intel win ] a/b/c/d [ Failure ] - [ intel xp debug ] a/b/c/d [ Skip ] - ''' - with self.assertRaises(AssertionError): - _CheckTestExpectationPatternsForCollision(test_expectations, 'test.txt') - - def testNoCollisionBetweenSpecificOsTags(self): - test_expectations = '''# tags: [ mac win linux xp win7 ] - # tags: [ intel amd nvidia ] - # tags: [ debug release ] - [ intel win7 ] a/b/c/d [ Failure ] - [ intel xp debug ] a/b/c/d [ Skip ] - ''' - _CheckTestExpectationPatternsForCollision(test_expectations, 'test.txt') - - def testCollisionInTestExpectationsWithGpuVendorAndDeviceTags(self): - test_expectations = '''# tags: [ mac win linux xp ] - # tags: [ intel amd nvidia nvidia-0x01 ] - # tags: [ debug release ] - [ nvidia win ] a/b/c/d [ Failure ] - [ nvidia-0x01 xp debug ] a/b/c/d [ Skip ] - ''' - with self.assertRaises(AssertionError): - _CheckTestExpectationPatternsForCollision(test_expectations, 'test.txt') - - def testCollisionInTestExpectationsWithGpuVendorAndDeviceTags2(self): - test_expectations = '''# tags: [ mac win linux xp win7 ] - # tags: [ intel amd nvidia nvidia-0x01 nvidia-0x02 ] - # tags: [ debug release ] - [ nvidia-0x01 win ] a/b/c/* [ Failure ] - [ nvidia win7 debug ] a/b/c/* [ Skip ] - ''' - with self.assertRaises(AssertionError): - _CheckTestExpectationPatternsForCollision(test_expectations, 'test.txt') - - def testNoCollisionBetweenGpuDeviceTags(self): - test_expectations = '''# tags: [ mac win linux xp win7 ] - # tags: [ intel amd nvidia nvidia-0x01 nvidia-0x02 ] - # tags: [ debug release ] - [ nvidia-0x01 win7 ] a/b/c/d [ Failure ] - [ nvidia-0x02 win7 debug ] a/b/c/d [ Skip ] - [ nvidia win debug ] a/b/c/* [ Skip ] - ''' - _CheckTestExpectationPatternsForCollision(test_expectations, 'test.txt') - - def testMixGenericandSpecificTagsInCollidingSets(self): - test_expectations = '''# tags: [ mac win linux xp win7 ] - # tags: [ intel amd nvidia nvidia-0x01 ] - # tags: [ debug release ] - [ nvidia-0x01 win ] a/b/c/d [ Failure ] - [ nvidia win7 debug ] a/b/c/d [ Skip ] - ''' - with self.assertRaises(AssertionError): - _CheckTestExpectationPatternsForCollision(test_expectations, 'test.txt') - - def testCollisionInTestExpectationCausesAssertion(self): - test_expectations = '''# tags: [ mac win linux ] - # tags: [ intel amd nvidia ] - # tags: [ debug release ] - [ intel win ] a/b/c/d [ Failure ] - [ intel win debug ] a/b/c/d [ Skip ] - [ intel ] a/b/c/d [ Failure ] - [ amd mac ] a/b [ RetryOnFailure ] - [ mac ] a/b [ Skip ] - [ amd mac ] a/b/c [ Failure ] - [ intel mac ] a/b/c [ Failure ] - ''' - with self.assertRaises(AssertionError) as context: - _CheckTestExpectationPatternsForCollision(test_expectations, 'test.txt') - self.assertIn("Found conflicts for test a/b/c/d in test.txt:", - str(context.exception)) - self.assertIn('line 4 conflicts with line 5', - str(context.exception)) - self.assertIn('line 4 conflicts with line 6', - str(context.exception)) - self.assertIn('line 5 conflicts with line 6', - str(context.exception)) - self.assertIn("Found conflicts for test a/b in test.txt:", - str(context.exception)) - self.assertIn('line 7 conflicts with line 8', - str(context.exception)) - self.assertNotIn("Found conflicts for test a/b/c in test.txt:", - str(context.exception)) - - def testCollisionWithGlobsWithFailureExpectation(self): - test_expectations = '''# tags: [ mac win linux ] - # tags: [ intel amd nvidia ] - # tags: [ debug release ] - [ intel debug ] a/b/c/d* [ Failure ] - [ intel debug mac ] a/b/c/d [ RetryOnFailure ] - [ intel debug mac ] a/b/c/d/e [ Failure ] - ''' - with self.assertRaises(AssertionError) as context: - _CheckTestExpectationGlobsForCollision(test_expectations, 'test.txt') - self.assertIn('Found conflicts for pattern a/b/c/d* in test.txt:', - str(context.exception)) - self.assertIn(("line 4 conflicts with line 5: Pattern 'a/b/c/d*' on line 4 " - "has the Failure expectation however the the pattern on 'a/b/c/d'" - " line 5 has the Pass expectation"), - str(context.exception)) - self.assertNotIn('line 4 conflicts with line 6', - str(context.exception)) - - def testNoCollisionWithGlobsWithFailureExpectation(self): - test_expectations = '''# tags: [ mac win linux ] - # tags: [ intel amd nvidia ] - # tags: [ debug release ] - [ intel debug mac ] a/b/c/* [ Failure ] - [ intel debug ] a/b/c/d [ Failure ] - [ intel debug ] a/b/c/d [ Skip ] - ''' - _CheckTestExpectationGlobsForCollision(test_expectations, 'test.txt') - - def testCollisionWithGlobsWithSkipExpectation(self): - test_expectations = '''# tags: [ mac win linux ] - # tags: [ intel amd nvidia ] - # tags: [ debug release ] - [ intel debug ] a/b/c/d* [ Skip ] - [ intel debug mac ] a/b/c/d [ Failure ] - [ intel debug mac ] a/b/c/d/e [ RetryOnFailure ] - ''' - with self.assertRaises(AssertionError) as context: - _CheckTestExpectationGlobsForCollision(test_expectations, 'test.txt') - self.assertIn('Found conflicts for pattern a/b/c/d* in test.txt:', - str(context.exception)) - self.assertNotIn('line 4 conflicts with line 5', - str(context.exception)) - self.assertIn('line 4 conflicts with line 6', - str(context.exception)) - self.assertIn(("line 4 conflicts with line 6: Pattern 'a/b/c/d*' on line 4 " - "has the Skip expectation however the the pattern on 'a/b/c/d/e'" - " line 6 has the Pass expectation"), - str(context.exception)) - - def testNoCollisionWithGlobsWithSkipExpectation(self): - test_expectations = '''# tags: [ mac win linux ] - # tags: [ intel amd nvidia ] - # tags: [ debug release ] - [ intel debug mac ] a/b/c/* [ Skip ] - [ intel debug ] a/b/c/d [ Skip ] - [ intel debug ] a/b/c/d [ Skip ] - ''' - _CheckTestExpectationGlobsForCollision(test_expectations, 'test.txt') - - def testNoCollisionInTestExpectations(self): - test_expectations = '''# tags: [ mac win linux ] - # tags: [ intel amd nvidia ] - # tags: [ debug release ] - [ intel win release ] a/b/* [ Failure ] - [ intel debug ] a/b/c/d [ Failure ] - [ nvidia debug ] a/b/c/d [ Failure ] - ''' - _CheckTestExpectationPatternsForCollision(test_expectations, 'test.txt') - - def testNoCollisionsForSameTestsInGpuTestExpectations(self): - webgl_conformance_test_class = ( - webgl_conformance_integration_test.WebGLConformanceIntegrationTest) - for test_case in _FindTestCases(): - if 'gpu_tests.gpu_integration_test_unittest' not in test_case.__module__: - for i in xrange(1, 2 + (test_case == webgl_conformance_test_class)): - _ = list(test_case.GenerateGpuTests( - _GetMockArgs(webgl_version=('%d.0.0' % i)))) - if test_case.ExpectationsFiles(): - with open(test_case.ExpectationsFiles()[0]) as f: - _CheckTestExpectationPatternsForCollision(f.read(), - os.path.basename(f.name)) - - def testNoCollisionsWithGlobsInGpuTestExpectations(self): - webgl_conformance_test_class = ( - webgl_conformance_integration_test.WebGLConformanceIntegrationTest) - for test_case in _FindTestCases(): - if 'gpu_tests.gpu_integration_test_unittest' not in test_case.__module__: - for i in xrange(1, 2 + (test_case == webgl_conformance_test_class)): - _ = list(test_case.GenerateGpuTests( - _GetMockArgs(webgl_version=('%d.0.0' % i)))) - if test_case.ExpectationsFiles(): - with open(test_case.ExpectationsFiles()[0]) as f: - _CheckTestExpectationGlobsForCollision(f.read(), - os.path.basename(f.name)) - - def testGpuTestExpectationsAreForExistingTests(self): - options = _GetMockArgs() - for test_case in _FindTestCases(): - if 'gpu_tests.gpu_integration_test_unittest' not in test_case.__module__: - if (test_case.Name() not in ('pixel', 'webgl_conformance') - and test_case.ExpectationsFiles()): - _CheckTestExpectationsAreForExistingTests(test_case, options) - - def testWebglTestPathsExist(self): - webgl_test_class = ( - webgl_conformance_integration_test.WebGLConformanceIntegrationTest) - for test_case in _FindTestCases(): - if test_case == webgl_test_class: - for i in xrange(1, 3): - _ = list(test_case.GenerateGpuTests( - _GetMockArgs(webgl_version='%d.0.0' % i))) - with open(test_case.ExpectationsFiles()[0], 'r') as f: - expectations = expectations_parser.TaggedTestListParser(f.read()) - for exp in expectations.expectations: - _CheckPatternIsValid(exp.test) - - def testPixelTestsExpectationsAreForExistingTests(self): - pixel_test_names = [] - for _, method in inspect.getmembers( - pixel_test_pages.PixelTestPages, predicate=inspect.isfunction): - pixel_test_names.extend( - [p.name for p in method( - pixel_integration_test.PixelIntegrationTest.test_base_name)]) - _CheckTestExpectationsAreForExistingTests( - pixel_integration_test.PixelIntegrationTest, - _GetMockArgs(), pixel_test_names) - - def testExpectationPatternNotInGeneratedTests(self): - with self.assertRaises(AssertionError) as context: - _TestCheckTestExpectationsAreForExistingTests('a/b/d [ Failure ]') - self.assertIn(("1: Glob 'a/b/d' does not match with any" - " tests in the GpuIntegrationTest test suite"), - str(context.exception)) - - def testGlobMatchesTestName(self): - _TestCheckTestExpectationsAreForExistingTests('a/b* [ Failure ]') - def testOverrideDefaultRetryArgumentsinRunGpuIntegrationTests(self): self._RunGpuIntegrationTests( 'run_tests_with_expectations_files', ['--retry-limit=1']) @@ -600,7 +129,7 @@ # we need to make sure that GenerateTags() returns an empty list if # there are no expectations files returned from ExpectationsFiles() or # else Typ will raise an exception - args = _GetMockArgs() + args = gpu_helper.GetMockArgs() possible_browser = mock.MagicMock() self.assertFalse(gpu_integration_test.GpuIntegrationTest.GenerateTags( args, possible_browser)) @@ -615,7 +144,7 @@ return tag_set def testGenerateContextLostExampleTagsForAsan(self): - args = _GetMockArgs(is_asan=True) + args = gpu_helper.GetMockArgs(is_asan=True) tag_set = self._TestTagGenerationForMockPlatform( context_lost_integration_test.ContextLostIntegrationTest, args) @@ -623,7 +152,7 @@ self.assertNotIn('no-asan', tag_set) def testGenerateContextLostExampleTagsForNoAsan(self): - args = _GetMockArgs() + args = gpu_helper.GetMockArgs() tag_set = self._TestTagGenerationForMockPlatform( context_lost_integration_test.ContextLostIntegrationTest, args) @@ -631,7 +160,7 @@ self.assertNotIn('asan', tag_set) def testGenerateWebglConformanceExampleTagsForWebglVersion1andAsan(self): - args = _GetMockArgs(is_asan=True, webgl_version='1.0.0') + args = gpu_helper.GetMockArgs(is_asan=True, webgl_version='1.0.0') tag_set = self._TestTagGenerationForMockPlatform( webgl_conformance_integration_test.WebGLConformanceIntegrationTest, args) @@ -639,7 +168,7 @@ self.assertFalse(set(['no-asan', 'webgl-version-2']) & tag_set) def testGenerateWebglConformanceExampleTagsForWebglVersion2andNoAsan(self): - args = _GetMockArgs(is_asan=False, webgl_version='2.0.0') + args = gpu_helper.GetMockArgs(is_asan=False, webgl_version='2.0.0') tag_set = self._TestTagGenerationForMockPlatform( webgl_conformance_integration_test.WebGLConformanceIntegrationTest, args)
diff --git a/content/test/gpu/gpu_tests/test_expectations_unittest.py b/content/test/gpu/gpu_tests/test_expectations_unittest.py new file mode 100644 index 0000000..1e29b9b --- /dev/null +++ b/content/test/gpu/gpu_tests/test_expectations_unittest.py
@@ -0,0 +1,469 @@ +# Copyright 2019 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import gpu_project_config +import inspect +import itertools +import mock +import os +import tempfile +import unittest + +from collections import defaultdict + +from gpu_tests import gpu_helper +from gpu_tests import gpu_integration_test +from gpu_tests import pixel_integration_test +from gpu_tests import pixel_test_pages +from gpu_tests import webgl_conformance_integration_test +from gpu_tests import webgl_test_util + +from py_utils import discover + +from typ import expectations_parser +from typ import json_results + +OS_CONDITIONS = ['win', 'mac', 'android'] +GPU_CONDITIONS = ['amd', 'arm', 'broadcom', 'hisilicon', 'intel', 'imagination', + 'nvidia', 'qualcomm', 'vivante'] +WIN_CONDITIONS = ['xp', 'vista', 'win7', 'win8', 'win10'] +MAC_CONDITIONS = ['leopard', 'snowleopard', 'lion', 'mountainlion', + 'mavericks', 'yosemite', 'sierra', 'highsierra', 'mojave'] +# These aren't expanded out into "lollipop", "marshmallow", etc. +ANDROID_CONDITIONS = ['l', 'm', 'n', 'o', 'p', 'q'] +GENERIC_CONDITIONS = OS_CONDITIONS + GPU_CONDITIONS + +_map_specific_to_generic = {sos:'win' for sos in WIN_CONDITIONS} +_map_specific_to_generic.update({sos:'mac' for sos in MAC_CONDITIONS}) +_map_specific_to_generic.update({sos:'android' for sos in ANDROID_CONDITIONS}) + +_get_generic = lambda tags: set( + [_map_specific_to_generic.get(tag, tag) for tag in tags]) + +ResultType = json_results.ResultType + +def _ConflictLeaksRegression(possible_collision, exp): + reason_template = ( + 'Pattern \'{0}\' on line {1} has the %s expectation however the ' + 'the pattern on \'{2}\' line {3} has the Pass expectation'). format( + possible_collision.test, possible_collision.lineno, exp.test, + exp.lineno) + causes_regression = not( + ResultType.Failure in exp.results or ResultType.Skip in exp.results) + if (ResultType.Skip in possible_collision.results and + causes_regression): + return reason_template % 'Skip' + if (ResultType.Failure in possible_collision.results and + causes_regression): + return reason_template % 'Failure' + return '' + + +def _IsCollision(s1, s2): + # s1 collides with s2 when s1 is a subset of s2 + # A tag is in both sets if its a generic tag + # and its in one set while a specifc tag covered by the generic tag is in + # the other set. + for tag in s1: + if (not tag in s2 and not ( + tag in GENERIC_CONDITIONS and + any(_map_specific_to_generic.get(t, t) == tag for t in s2)) and + not _map_specific_to_generic.get(tag, tag) in s2): + return False + return True + + +def _MapGpuDevicesToVendors(tag_sets): + for tag_set in tag_sets: + if any(gpu in tag_set for gpu in GPU_CONDITIONS): + _map_specific_to_generic.update( + {t[0]: t[1] for t in + itertools.permutations(tag_set, 2) if (t[0] + '-').startswith(t[1])}) + break + + +def CheckTestExpectationsAreForExistingTests( + test_class, mock_options, test_names=None): + test_names = test_names or [ + args[0] for args in + test_class.GenerateGpuTests(mock_options)] + expectations_file = test_class.ExpectationsFiles()[0] + trie = {} + for test in test_names: + _trie = trie.setdefault(test[0], {}) + for l in test[1:]: + _trie = _trie.setdefault(l, {}) + f = open(expectations_file, 'r') + expectations_file = os.path.basename(expectations_file) + expectations = f.read() + f.close() + parser = expectations_parser.TaggedTestListParser(expectations) + for exp in parser.expectations: + _trie = trie + for l in exp.test: + if l == '*': + break + assert l in _trie, ( + "%s:%d: Glob '%s' does not match with any tests in the %s test suite" % + (expectations_file, exp.lineno, exp.test, test_class.Name())) + _trie = _trie[l] + + +def CheckTestExpectationGlobsForCollision(expectations, file_name): + """This function looks for collisions between test expectations with patterns + that match with test expectation patterns that are globs. A test expectation + collides with another if its pattern matches with another's glob and if its + tags is a super set of the other expectation's tags. The less specific test + expectation must have a failure or skip expectation while the more specific + test expectation does not. The more specific test expectation will trump + the less specific test expectation and may cause an unexpected regression. + + Args: + expectations: A string containing test expectations in the new format + file_name: Name of the file that the test expectations came from + """ + master_conflicts_found = False + error_msg = '' + trie = {} + parser = expectations_parser.TaggedTestListParser(expectations) + globs_to_expectations = defaultdict(list) + + _MapGpuDevicesToVendors(parser.tag_sets) + + for exp in parser.expectations: + _trie = trie.setdefault(exp.test[0], {}) + for l in exp.test[1:]: + _trie = _trie.setdefault(l, {}) + _trie.setdefault('$', []).append(exp) + + for exp in parser.expectations: + _trie = trie + glob = '' + for l in exp.test: + if '*' in _trie: + globs_to_expectations[glob + '*'].append(exp) + glob += l + if l in _trie: + _trie = _trie[l] + else: + break + if '*' in _trie: + globs_to_expectations[glob + '*'].append(exp) + + for glob, expectations in globs_to_expectations.items(): + conflicts_found = False + globs_to_match = [e for e in expectations if e.test == glob] + matched_to_globs = [e for e in expectations if e.test != glob] + for match in matched_to_globs: + for possible_collision in globs_to_match: + reason = _ConflictLeaksRegression(possible_collision, match) + if (reason and + _IsCollision(possible_collision.tags, match.tags)): + if not conflicts_found: + error_msg += ('\n\nFound conflicts for pattern %s in %s:\n' % + (glob, file_name)) + master_conflicts_found = conflicts_found = True + error_msg += (' line %d conflicts with line %d: %s\n' % + (possible_collision.lineno, match.lineno, reason)) + assert not master_conflicts_found, error_msg + + +def CheckTestExpectationPatternsForCollision(expectations, file_name): + """This function makes sure that any test expectations that have the same + pattern do not collide with each other. They collide when one expectation's + tags are a subset of the other expectation's tags. If the expectation with + the larger tag set is active during a test run, then the expectation's whose + tag set is a subset of the tags will be active as well. + + Args: + expectations: A string containing test expectations in the new format + file_name: Name of the file that the test expectations came from + """ + parser = expectations_parser.TaggedTestListParser(expectations) + tests_to_exps = defaultdict(list) + master_conflicts_found = False + error_msg = '' + _MapGpuDevicesToVendors(parser.tag_sets) + + for exp in parser.expectations: + tests_to_exps[exp.test].append(exp) + for pattern, exps in tests_to_exps.items(): + conflicts_found = False + for e1, e2 in itertools.combinations(exps, 2): + if _IsCollision(e1.tags, e2.tags) or _IsCollision(e2.tags, e1.tags): + if not conflicts_found: + error_msg += ('\n\nFound conflicts for test %s in %s:\n' % + (pattern, file_name)) + master_conflicts_found = conflicts_found = True + error_msg += (' line %d conflicts with line %d\n' % + (e1.lineno, e2.lineno)) + assert not master_conflicts_found, error_msg + + +def _TestCheckTestExpectationsAreForExistingTests(expectations): + options = gpu_helper.GetMockArgs() + expectations_file = tempfile.NamedTemporaryFile(delete=False) + expectations_file.write(expectations) + expectations_file.close() + gpu_tests = gpu_integration_test.GpuIntegrationTest + generate_gpu_fn = gpu_tests.GenerateGpuTests + expectations_files_fn = gpu_tests.ExpectationsFiles + gpu_tests.GenerateGpuTests = mock.MagicMock(return_value=[('a/b/c', ())]) + gpu_tests.ExpectationsFiles = mock.MagicMock( + return_value=[expectations_file.name]) + try: + CheckTestExpectationsAreForExistingTests(gpu_tests, options) + finally: + gpu_tests.GenerateGpuTests = generate_gpu_fn + gpu_tests.ExpectationsFiles = expectations_files_fn + + +def _CheckPatternIsValid(pattern): + if not '*' in pattern and not 'WebglExtension_' in pattern: + full_path = os.path.normpath(os.path.join( + webgl_test_util.conformance_path, pattern)) + if not os.path.exists(full_path): + raise Exception('The WebGL conformance test path specified in ' + + 'expectation does not exist: ' + full_path) + + +def _FindTestCases(): + test_cases = [] + for start_dir in gpu_project_config.CONFIG.start_dirs: + modules_to_classes = discover.DiscoverClasses( + start_dir, + gpu_project_config.CONFIG.top_level_dir, + base_class=gpu_integration_test.GpuIntegrationTest) + test_cases.extend(modules_to_classes.values()) + return test_cases + + +class GpuTestExpectationsValidation(unittest.TestCase): + def testNoCollisionsForSameTestsInGpuTestExpectations(self): + webgl_conformance_test_class = ( + webgl_conformance_integration_test.WebGLConformanceIntegrationTest) + for test_case in _FindTestCases(): + if 'gpu_tests.gpu_integration_test_unittest' not in test_case.__module__: + for i in xrange(1, 2 + (test_case == webgl_conformance_test_class)): + _ = list(test_case.GenerateGpuTests( + gpu_helper.GetMockArgs(webgl_version=('%d.0.0' % i)))) + if test_case.ExpectationsFiles(): + with open(test_case.ExpectationsFiles()[0]) as f: + CheckTestExpectationPatternsForCollision(f.read(), + os.path.basename(f.name)) + + def testNoCollisionsWithGlobsInGpuTestExpectations(self): + webgl_conformance_test_class = ( + webgl_conformance_integration_test.WebGLConformanceIntegrationTest) + for test_case in _FindTestCases(): + if 'gpu_tests.gpu_integration_test_unittest' not in test_case.__module__: + for i in xrange(1, 2 + (test_case == webgl_conformance_test_class)): + _ = list(test_case.GenerateGpuTests( + gpu_helper.GetMockArgs(webgl_version=('%d.0.0' % i)))) + if test_case.ExpectationsFiles(): + with open(test_case.ExpectationsFiles()[0]) as f: + CheckTestExpectationGlobsForCollision(f.read(), + os.path.basename(f.name)) + + def testGpuTestExpectationsAreForExistingTests(self): + options = gpu_helper.GetMockArgs() + for test_case in _FindTestCases(): + if 'gpu_tests.gpu_integration_test_unittest' not in test_case.__module__: + if (test_case.Name() not in ('pixel', 'webgl_conformance') + and test_case.ExpectationsFiles()): + CheckTestExpectationsAreForExistingTests(test_case, options) + + def testWebglTestPathsExist(self): + webgl_test_class = ( + webgl_conformance_integration_test.WebGLConformanceIntegrationTest) + for test_case in _FindTestCases(): + if test_case == webgl_test_class: + for i in xrange(1, 3): + _ = list(test_case.GenerateGpuTests( + gpu_helper.GetMockArgs(webgl_version='%d.0.0' % i))) + with open(test_case.ExpectationsFiles()[0], 'r') as f: + expectations = expectations_parser.TaggedTestListParser(f.read()) + for exp in expectations.expectations: + _CheckPatternIsValid(exp.test) + + def testPixelTestsExpectationsAreForExistingTests(self): + pixel_test_names = [] + for _, method in inspect.getmembers( + pixel_test_pages.PixelTestPages, predicate=inspect.isfunction): + pixel_test_names.extend( + [p.name for p in method( + pixel_integration_test.PixelIntegrationTest.test_base_name)]) + CheckTestExpectationsAreForExistingTests( + pixel_integration_test.PixelIntegrationTest, + gpu_helper.GetMockArgs(), pixel_test_names) + + +class TestGpuTestExpectationsValidators(unittest.TestCase): + def testCollisionInTestExpectationsWithSpecifcAndGenericOsTags(self): + test_expectations = '''# tags: [ mac win linux xp ] + # tags: [ intel amd nvidia ] + # tags: [ debug release ] + [ intel win ] a/b/c/d [ Failure ] + [ intel xp debug ] a/b/c/d [ Skip ] + ''' + with self.assertRaises(AssertionError): + CheckTestExpectationPatternsForCollision(test_expectations, 'test.txt') + + def testNoCollisionBetweenSpecificOsTags(self): + test_expectations = '''# tags: [ mac win linux xp win7 ] + # tags: [ intel amd nvidia ] + # tags: [ debug release ] + [ intel win7 ] a/b/c/d [ Failure ] + [ intel xp debug ] a/b/c/d [ Skip ] + ''' + CheckTestExpectationPatternsForCollision(test_expectations, 'test.txt') + + def testCollisionInTestExpectationsWithGpuVendorAndDeviceTags(self): + test_expectations = '''# tags: [ mac win linux xp ] + # tags: [ intel amd nvidia nvidia-0x01 ] + # tags: [ debug release ] + [ nvidia win ] a/b/c/d [ Failure ] + [ nvidia-0x01 xp debug ] a/b/c/d [ Skip ] + ''' + with self.assertRaises(AssertionError): + CheckTestExpectationPatternsForCollision(test_expectations, 'test.txt') + + def testCollisionInTestExpectationsWithGpuVendorAndDeviceTags2(self): + test_expectations = '''# tags: [ mac win linux xp win7 ] + # tags: [ intel amd nvidia nvidia-0x01 nvidia-0x02 ] + # tags: [ debug release ] + [ nvidia-0x01 win ] a/b/c/* [ Failure ] + [ nvidia win7 debug ] a/b/c/* [ Skip ] + ''' + with self.assertRaises(AssertionError): + CheckTestExpectationPatternsForCollision(test_expectations, 'test.txt') + + def testNoCollisionBetweenGpuDeviceTags(self): + test_expectations = '''# tags: [ mac win linux xp win7 ] + # tags: [ intel amd nvidia nvidia-0x01 nvidia-0x02 ] + # tags: [ debug release ] + [ nvidia-0x01 win7 ] a/b/c/d [ Failure ] + [ nvidia-0x02 win7 debug ] a/b/c/d [ Skip ] + [ nvidia win debug ] a/b/c/* [ Skip ] + ''' + CheckTestExpectationPatternsForCollision(test_expectations, 'test.txt') + + def testMixGenericandSpecificTagsInCollidingSets(self): + test_expectations = '''# tags: [ mac win linux xp win7 ] + # tags: [ intel amd nvidia nvidia-0x01 ] + # tags: [ debug release ] + [ nvidia-0x01 win ] a/b/c/d [ Failure ] + [ nvidia win7 debug ] a/b/c/d [ Skip ] + ''' + with self.assertRaises(AssertionError): + CheckTestExpectationPatternsForCollision(test_expectations, 'test.txt') + + def testCollisionInTestExpectationCausesAssertion(self): + test_expectations = '''# tags: [ mac win linux ] + # tags: [ intel amd nvidia ] + # tags: [ debug release ] + [ intel win ] a/b/c/d [ Failure ] + [ intel win debug ] a/b/c/d [ Skip ] + [ intel ] a/b/c/d [ Failure ] + [ amd mac ] a/b [ RetryOnFailure ] + [ mac ] a/b [ Skip ] + [ amd mac ] a/b/c [ Failure ] + [ intel mac ] a/b/c [ Failure ] + ''' + with self.assertRaises(AssertionError) as context: + CheckTestExpectationPatternsForCollision(test_expectations, 'test.txt') + self.assertIn("Found conflicts for test a/b/c/d in test.txt:", + str(context.exception)) + self.assertIn('line 4 conflicts with line 5', + str(context.exception)) + self.assertIn('line 4 conflicts with line 6', + str(context.exception)) + self.assertIn('line 5 conflicts with line 6', + str(context.exception)) + self.assertIn("Found conflicts for test a/b in test.txt:", + str(context.exception)) + self.assertIn('line 7 conflicts with line 8', + str(context.exception)) + self.assertNotIn("Found conflicts for test a/b/c in test.txt:", + str(context.exception)) + + def testCollisionWithGlobsWithFailureExpectation(self): + test_expectations = '''# tags: [ mac win linux ] + # tags: [ intel amd nvidia ] + # tags: [ debug release ] + [ intel debug ] a/b/c/d* [ Failure ] + [ intel debug mac ] a/b/c/d [ RetryOnFailure ] + [ intel debug mac ] a/b/c/d/e [ Failure ] + ''' + with self.assertRaises(AssertionError) as context: + CheckTestExpectationGlobsForCollision(test_expectations, 'test.txt') + self.assertIn('Found conflicts for pattern a/b/c/d* in test.txt:', + str(context.exception)) + self.assertIn(("line 4 conflicts with line 5: Pattern 'a/b/c/d*' on line 4 " + "has the Failure expectation however the the pattern on 'a/b/c/d'" + " line 5 has the Pass expectation"), + str(context.exception)) + self.assertNotIn('line 4 conflicts with line 6', + str(context.exception)) + + def testNoCollisionWithGlobsWithFailureExpectation(self): + test_expectations = '''# tags: [ mac win linux ] + # tags: [ intel amd nvidia ] + # tags: [ debug release ] + [ intel debug mac ] a/b/c/* [ Failure ] + [ intel debug ] a/b/c/d [ Failure ] + [ intel debug ] a/b/c/d [ Skip ] + ''' + CheckTestExpectationGlobsForCollision(test_expectations, 'test.txt') + + def testCollisionWithGlobsWithSkipExpectation(self): + test_expectations = '''# tags: [ mac win linux ] + # tags: [ intel amd nvidia ] + # tags: [ debug release ] + [ intel debug ] a/b/c/d* [ Skip ] + [ intel debug mac ] a/b/c/d [ Failure ] + [ intel debug mac ] a/b/c/d/e [ RetryOnFailure ] + ''' + with self.assertRaises(AssertionError) as context: + CheckTestExpectationGlobsForCollision(test_expectations, 'test.txt') + self.assertIn('Found conflicts for pattern a/b/c/d* in test.txt:', + str(context.exception)) + self.assertNotIn('line 4 conflicts with line 5', + str(context.exception)) + self.assertIn('line 4 conflicts with line 6', + str(context.exception)) + self.assertIn(("line 4 conflicts with line 6: Pattern 'a/b/c/d*' on line 4 " + "has the Skip expectation however the the pattern on 'a/b/c/d/e'" + " line 6 has the Pass expectation"), + str(context.exception)) + + def testNoCollisionWithGlobsWithSkipExpectation(self): + test_expectations = '''# tags: [ mac win linux ] + # tags: [ intel amd nvidia ] + # tags: [ debug release ] + [ intel debug mac ] a/b/c/* [ Skip ] + [ intel debug ] a/b/c/d [ Skip ] + [ intel debug ] a/b/c/d [ Skip ] + ''' + CheckTestExpectationGlobsForCollision(test_expectations, 'test.txt') + + def testNoCollisionInTestExpectations(self): + test_expectations = '''# tags: [ mac win linux ] + # tags: [ intel amd nvidia ] + # tags: [ debug release ] + [ intel win release ] a/b/* [ Failure ] + [ intel debug ] a/b/c/d [ Failure ] + [ nvidia debug ] a/b/c/d [ Failure ] + ''' + CheckTestExpectationPatternsForCollision(test_expectations, 'test.txt') + + def testExpectationPatternNotInGeneratedTests(self): + with self.assertRaises(AssertionError) as context: + _TestCheckTestExpectationsAreForExistingTests('a/b/d [ Failure ]') + self.assertIn(("1: Glob 'a/b/d' does not match with any" + " tests in the GpuIntegrationTest test suite"), + str(context.exception)) + + def testGlobMatchesTestName(self): + _TestCheckTestExpectationsAreForExistingTests('a/b* [ Failure ]')
diff --git a/extensions/browser/api/messaging/message_service.cc b/extensions/browser/api/messaging/message_service.cc index fdcf326e4..cba5581 100644 --- a/extensions/browser/api/messaging/message_service.cc +++ b/extensions/browser/api/messaging/message_service.cc
@@ -416,7 +416,7 @@ // any issues arise from it. std::unique_ptr<MessagePort> receiver( messaging_delegate_->CreateReceiverForNativeApp( - weak_factory_.GetWeakPtr(), source_rfh, extension->id(), + context_, weak_factory_.GetWeakPtr(), source_rfh, extension->id(), receiver_port_id, native_app_name, policy_permission == MessagingDelegate::PolicyPermission::ALLOW_ALL, &error));
diff --git a/extensions/browser/api/messaging/messaging_delegate.cc b/extensions/browser/api/messaging/messaging_delegate.cc index 1714908c..56ead44 100644 --- a/extensions/browser/api/messaging/messaging_delegate.cc +++ b/extensions/browser/api/messaging/messaging_delegate.cc
@@ -41,6 +41,7 @@ } std::unique_ptr<MessagePort> MessagingDelegate::CreateReceiverForNativeApp( + content::BrowserContext* browser_context, base::WeakPtr<MessagePort::ChannelDelegate> channel_delegate, content::RenderFrameHost* source, const std::string& extension_id,
diff --git a/extensions/browser/api/messaging/messaging_delegate.h b/extensions/browser/api/messaging/messaging_delegate.h index 7acae22..36d448b 100644 --- a/extensions/browser/api/messaging/messaging_delegate.h +++ b/extensions/browser/api/messaging/messaging_delegate.h
@@ -68,6 +68,7 @@ // Creates a MessagePort for a native app. If the port cannot be created, // returns nullptr and may populate |error_out|. virtual std::unique_ptr<MessagePort> CreateReceiverForNativeApp( + content::BrowserContext* browser_context, base::WeakPtr<MessagePort::ChannelDelegate> channel_delegate, content::RenderFrameHost* source, const std::string& extension_id,
diff --git a/extensions/browser/api/messaging/native_message_host.h b/extensions/browser/api/messaging/native_message_host.h index 094083e..ebabefc 100644 --- a/extensions/browser/api/messaging/native_message_host.h +++ b/extensions/browser/api/messaging/native_message_host.h
@@ -11,6 +11,10 @@ #include "base/single_thread_task_runner.h" #include "ui/gfx/native_widget_types.h" +namespace content { +class BrowserContext; +} // namespace content + namespace extensions { // An interface for receiving messages from MessageService (Chrome) using the @@ -38,6 +42,7 @@ // Creates the NativeMessageHost based on the |native_host_name|. static std::unique_ptr<NativeMessageHost> Create( + content::BrowserContext* browser_context, gfx::NativeView native_view, const std::string& source_extension_id, const std::string& native_host_name,
diff --git a/extensions/renderer/BUILD.gn b/extensions/renderer/BUILD.gn index 364bd6e..c7a450a 100644 --- a/extensions/renderer/BUILD.gn +++ b/extensions/renderer/BUILD.gn
@@ -26,8 +26,6 @@ "api_definitions_natives.h", "app_window_custom_bindings.cc", "app_window_custom_bindings.h", - "async_scripts_run_info.cc", - "async_scripts_run_info.h", "binding_generating_native_handler.cc", "binding_generating_native_handler.h", "bindings/api_binding.cc",
diff --git a/extensions/renderer/async_scripts_run_info.cc b/extensions/renderer/async_scripts_run_info.cc deleted file mode 100644 index 508518d2..0000000 --- a/extensions/renderer/async_scripts_run_info.cc +++ /dev/null
@@ -1,46 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "extensions/renderer/async_scripts_run_info.h" - -#include "base/metrics/histogram_macros.h" -#include "content/public/renderer/render_frame.h" -#include "extensions/renderer/scripts_run_info.h" - -namespace extensions { - -AsyncScriptsRunInfo::AsyncScriptsRunInfo(UserScript::RunLocation location) - : run_location_(location) {} - -AsyncScriptsRunInfo::~AsyncScriptsRunInfo() {} - -void AsyncScriptsRunInfo::WillExecute(const base::TimeTicks& timestamp) { - if (!last_completed_time_.is_null()) { - switch (run_location_) { - case UserScript::DOCUMENT_END: - UMA_HISTOGRAM_TIMES( - "Extensions.TimeYieldedBetweenContentScriptRuns.DocumentEnd", - timestamp - last_completed_time_); - break; - case UserScript::DOCUMENT_IDLE: - UMA_HISTOGRAM_TIMES( - "Extensions.TimeYieldedBetweenContentScriptRuns.DocumentIdle", - timestamp - last_completed_time_); - break; - // Currently document_start scripts are not async. - default: - break; - } - } -} - -void AsyncScriptsRunInfo::OnCompleted(const base::TimeTicks& timestamp, - base::Optional<base::TimeDelta> elapsed) { - last_completed_time_ = timestamp; - if (elapsed) { - ScriptsRunInfo::LogLongInjectionTaskTime(run_location_, *elapsed); - } -} - -} // namespace extensions
diff --git a/extensions/renderer/async_scripts_run_info.h b/extensions/renderer/async_scripts_run_info.h deleted file mode 100644 index d48d42c0..0000000 --- a/extensions/renderer/async_scripts_run_info.h +++ /dev/null
@@ -1,38 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef EXTENSIONS_RENDERER_ASYNC_SCRIPTS_RUN_INFO_H_ -#define EXTENSIONS_RENDERER_ASYNC_SCRIPTS_RUN_INFO_H_ - -#include "base/memory/ref_counted.h" -#include "base/optional.h" - -#include "extensions/common/user_script.h" - -namespace extensions { - -// Collects information about asynchronously injected script runs for a -// run_location. -class AsyncScriptsRunInfo : public base::RefCounted<AsyncScriptsRunInfo> { - public: - AsyncScriptsRunInfo(UserScript::RunLocation location); - void WillExecute(const base::TimeTicks& timestamp); - void OnCompleted(const base::TimeTicks& timestamp, - base::Optional<base::TimeDelta> elapsed); - - private: - friend class base::RefCounted<AsyncScriptsRunInfo>; - ~AsyncScriptsRunInfo(); - - UserScript::RunLocation run_location_; - - // Time stamp of the last OnCompleted() call. - base::TimeTicks last_completed_time_; - - DISALLOW_COPY_AND_ASSIGN(AsyncScriptsRunInfo); -}; - -} // namespace extensions - -#endif // EXTENSIONS_RENDERER_SCRIPTS_RUN_INFO_H_
diff --git a/extensions/renderer/script_injection.cc b/extensions/renderer/script_injection.cc index 4f8edf5..c54f9ea 100644 --- a/extensions/renderer/script_injection.cc +++ b/extensions/renderer/script_injection.cc
@@ -19,7 +19,6 @@ #include "extensions/common/extension_features.h" #include "extensions/common/extension_messages.h" #include "extensions/common/host_id.h" -#include "extensions/renderer/async_scripts_run_info.h" #include "extensions/renderer/dom_activity_logger.h" #include "extensions/renderer/extension_frame_helper.h" #include "extensions/renderer/extensions_renderer_client.h" @@ -88,14 +87,11 @@ // This class manages its own lifetime. class TimedScriptInjectionCallback : public ScriptInjectionCallback { public: - TimedScriptInjectionCallback( - base::WeakPtr<ScriptInjection> injection, - scoped_refptr<AsyncScriptsRunInfo> async_run_info) + TimedScriptInjectionCallback(base::WeakPtr<ScriptInjection> injection) : ScriptInjectionCallback( base::Bind(&TimedScriptInjectionCallback::OnCompleted, base::Unretained(this))), - injection_(injection), - async_run_info_(async_run_info) {} + injection_(injection) {} ~TimedScriptInjectionCallback() override {} void OnCompleted(const std::vector<v8::Local<v8::Value>>& result) { @@ -105,25 +101,19 @@ // If the script will never execute (such as if the context is destroyed), // willExecute() will not be called, but OnCompleted() will. Only log a // time for execution if the script, in fact, executed. - if (!start_time_.is_null()) { + if (!start_time_.is_null()) elapsed = timestamp - start_time_; - if (async_run_info_) - async_run_info_->OnCompleted(timestamp, elapsed); - } injection_->OnJsInjectionCompleted(result, elapsed); } } void WillExecute() override { start_time_ = base::TimeTicks::Now(); - if (async_run_info_) - async_run_info_->WillExecute(start_time_); } private: base::WeakPtr<ScriptInjection> injection_; base::TimeTicks start_time_; - scoped_refptr<AsyncScriptsRunInfo> async_run_info_; }; } // namespace @@ -190,7 +180,6 @@ ScriptInjection::InjectionResult ScriptInjection::TryToInject( UserScript::RunLocation current_location, ScriptsRunInfo* scripts_run_info, - scoped_refptr<AsyncScriptsRunInfo> async_run_info, const CompletionCallback& async_completion_callback) { if (current_location < run_location_) return INJECTION_WAITING; // Wait for the right location. @@ -216,8 +205,7 @@ RequestPermissionFromBrowser(); return INJECTION_WAITING; // Wait around for permission. case PermissionsData::PageAccess::kAllowed: - InjectionResult result = - Inject(scripts_run_info, std::move(async_run_info)); + InjectionResult result = Inject(scripts_run_info); // If the injection is blocked, we need to set the manager so we can // notify it upon completion. if (result == INJECTION_BLOCKED) @@ -236,7 +224,7 @@ return INJECTION_FINISHED; } - return Inject(scripts_run_info, nullptr); + return Inject(scripts_run_info); } void ScriptInjection::OnHostRemoved() { @@ -259,8 +247,7 @@ } ScriptInjection::InjectionResult ScriptInjection::Inject( - ScriptsRunInfo* scripts_run_info, - scoped_refptr<AsyncScriptsRunInfo> async_run_info) { + ScriptsRunInfo* scripts_run_info) { DCHECK(injection_host_); DCHECK(scripts_run_info); DCHECK(!complete_); @@ -278,7 +265,7 @@ if (should_inject_js) InjectJs(&(scripts_run_info->executing_scripts[host_id().id()]), - &(scripts_run_info->num_js), std::move(async_run_info)); + &(scripts_run_info->num_js)); if (should_inject_css) InjectCss(&(scripts_run_info->injected_stylesheets[host_id().id()]), &(scripts_run_info->num_css)); @@ -295,10 +282,8 @@ return complete_ ? INJECTION_FINISHED : INJECTION_BLOCKED; } -void ScriptInjection::InjectJs( - std::set<std::string>* executing_scripts, - size_t* num_injected_js_scripts, - scoped_refptr<AsyncScriptsRunInfo> async_run_info) { +void ScriptInjection::InjectJs(std::set<std::string>* executing_scripts, + size_t* num_injected_js_scripts) { DCHECK(!did_inject_js_); blink::WebLocalFrame* web_frame = render_frame_->GetWebFrame(); std::vector<blink::WebScriptSource> sources = injector_->GetJsSources( @@ -312,8 +297,7 @@ bool is_user_gesture = injector_->IsUserGesture(); std::unique_ptr<blink::WebScriptExecutionCallback> callback( - new TimedScriptInjectionCallback(weak_ptr_factory_.GetWeakPtr(), - std::move(async_run_info))); + new TimedScriptInjectionCallback(weak_ptr_factory_.GetWeakPtr())); base::ElapsedTimer exec_timer; if (injection_host_->id().type() == HostID::EXTENSIONS && log_activity_)
diff --git a/extensions/renderer/script_injection.h b/extensions/renderer/script_injection.h index 66a1c0a..3070e7a5 100644 --- a/extensions/renderer/script_injection.h +++ b/extensions/renderer/script_injection.h
@@ -30,7 +30,6 @@ } namespace extensions { -class AsyncScriptsRunInfo; struct ScriptsRunInfo; // A script wrapper which is aware of whether or not it is allowed to execute, @@ -69,7 +68,6 @@ InjectionResult TryToInject( UserScript::RunLocation current_location, ScriptsRunInfo* scripts_run_info, - scoped_refptr<AsyncScriptsRunInfo> async_run_info, const CompletionCallback& async_completion_callback); // Called when permission for the given injection has been granted. @@ -100,13 +98,11 @@ // Injects the script. Returns INJECTION_FINISHED if injection has finished, // otherwise INJECTION_BLOCKED. - InjectionResult Inject(ScriptsRunInfo* scripts_run_info, - scoped_refptr<AsyncScriptsRunInfo> async_run_info); + InjectionResult Inject(ScriptsRunInfo* scripts_run_info); // Inject any JS scripts into the frame for the injection. void InjectJs(std::set<std::string>* executing_scripts, - size_t* num_injected_js_scripts, - scoped_refptr<AsyncScriptsRunInfo> async_run_info); + size_t* num_injected_js_scripts); // Inject any CSS source into the frame for the injection. void InjectCss(std::set<std::string>* injected_stylesheets,
diff --git a/extensions/renderer/script_injection_manager.cc b/extensions/renderer/script_injection_manager.cc index 6f42300a..e395f32a 100644 --- a/extensions/renderer/script_injection_manager.cc +++ b/extensions/renderer/script_injection_manager.cc
@@ -20,7 +20,6 @@ #include "extensions/common/extension_features.h" #include "extensions/common/extension_messages.h" #include "extensions/common/extension_set.h" -#include "extensions/renderer/async_scripts_run_info.h" #include "extensions/renderer/extension_frame_helper.h" #include "extensions/renderer/extension_injection_host.h" #include "extensions/renderer/programmatic_script_injector.h" @@ -404,8 +403,6 @@ active_injection_frames_.insert(frame); ScriptsRunInfo scripts_run_info(frame, run_location); - scoped_refptr<AsyncScriptsRunInfo> async_run_info = - base::MakeRefCounted<AsyncScriptsRunInfo>(run_location); for (auto iter = frame_injections.begin(); iter != frame_injections.end();) { // It's possible for the frame to be invalidated in the course of injection @@ -414,8 +411,7 @@ break; std::unique_ptr<ScriptInjection> injection(std::move(*iter)); iter = frame_injections.erase(iter); - TryToInject(std::move(injection), run_location, &scripts_run_info, - async_run_info); + TryToInject(std::move(injection), run_location, &scripts_run_info); } // We are done running in the frame. @@ -427,15 +423,14 @@ void ScriptInjectionManager::TryToInject( std::unique_ptr<ScriptInjection> injection, UserScript::RunLocation run_location, - ScriptsRunInfo* scripts_run_info, - scoped_refptr<AsyncScriptsRunInfo> async_run_info) { + ScriptsRunInfo* scripts_run_info) { // Try to inject the script. If the injection is waiting (i.e., for // permission), add it to the list of pending injections. If the injection // has blocked, add it to the list of running injections. // The Unretained below is safe because this object owns all the // ScriptInjections, so is guaranteed to outlive them. switch (injection->TryToInject( - run_location, scripts_run_info, std::move(async_run_info), + run_location, scripts_run_info, base::Bind(&ScriptInjectionManager::OnInjectionFinished, base::Unretained(this)))) { case ScriptInjection::INJECTION_WAITING: @@ -472,7 +467,7 @@ iter == frame_statuses_.end() ? UserScript::UNDEFINED : iter->second; ScriptsRunInfo scripts_run_info(render_frame, run_location); - TryToInject(std::move(injection), run_location, &scripts_run_info, nullptr); + TryToInject(std::move(injection), run_location, &scripts_run_info); } void ScriptInjectionManager::HandleExecuteDeclarativeScript( @@ -488,7 +483,7 @@ ScriptsRunInfo scripts_run_info(render_frame, UserScript::BROWSER_DRIVEN); // TODO(markdittmer): Use return value of TryToInject for error handling. TryToInject(std::move(injection), UserScript::BROWSER_DRIVEN, - &scripts_run_info, nullptr); + &scripts_run_info); scripts_run_info.LogRun(activity_logging_enabled_); }
diff --git a/extensions/renderer/script_injection_manager.h b/extensions/renderer/script_injection_manager.h index ef00d56..fb01535 100644 --- a/extensions/renderer/script_injection_manager.h +++ b/extensions/renderer/script_injection_manager.h
@@ -81,8 +81,7 @@ // Try to inject and store injection if it has not finished. void TryToInject(std::unique_ptr<ScriptInjection> injection, UserScript::RunLocation run_location, - ScriptsRunInfo* scripts_run_info, - scoped_refptr<AsyncScriptsRunInfo> async_run_info); + ScriptsRunInfo* scripts_run_info); // Handle the ExecuteCode extension message. void HandleExecuteCode(const ExtensionMsg_ExecuteCode_Params& params,
diff --git a/extensions/renderer/scripts_run_info.cc b/extensions/renderer/scripts_run_info.cc index 8bd717c..087b406 100644 --- a/extensions/renderer/scripts_run_info.cc +++ b/extensions/renderer/scripts_run_info.cc
@@ -45,7 +45,6 @@ num_blocking_js); } else if (num_css || num_js) { UMA_HISTOGRAM_TIMES("Extensions.InjectStart_Time", elapsed); - LogLongInjectionTaskTime(run_location_, elapsed); } break; case UserScript::DOCUMENT_END: @@ -55,7 +54,6 @@ num_blocking_js); } else if (num_js) { UMA_HISTOGRAM_TIMES("Extensions.InjectEnd_Time", elapsed); - LogLongInjectionTaskTime(run_location_, elapsed); } break; case UserScript::DOCUMENT_IDLE: @@ -65,7 +63,6 @@ num_blocking_js); } else if (num_js) { UMA_HISTOGRAM_TIMES("Extensions.InjectIdle_Time", elapsed); - LogLongInjectionTaskTime(run_location_, elapsed); } break; case UserScript::RUN_DEFERRED: @@ -78,33 +75,4 @@ } } -void ScriptsRunInfo::LogLongInjectionTaskTime( - UserScript::RunLocation run_location, - const base::TimeDelta& elapsed) { - // We only record tasks longer than 50 milliseconds. This threshold aligns - // with the definition of "long task" in Long Tasks API - // (https://w3c.github.io/longtasks/). - const base::TimeDelta kLongTaskThreshold = - base::TimeDelta::FromMilliseconds(50); - if (elapsed < kLongTaskThreshold) - return; - - switch (run_location) { - case UserScript::DOCUMENT_START: - UMA_HISTOGRAM_TIMES("Extensions.LongInjectionTaskTime.DocumentStart", - elapsed); - break; - case UserScript::DOCUMENT_END: - UMA_HISTOGRAM_TIMES("Extensions.LongInjectionTaskTime.DocumentEnd", - elapsed); - break; - case UserScript::DOCUMENT_IDLE: - UMA_HISTOGRAM_TIMES("Extensions.LongInjectionTaskTime.DocumentIdle", - elapsed); - break; - default: - break; - } -} - } // namespace extensions
diff --git a/extensions/shell/test/shell_test.cc b/extensions/shell/test/shell_test.cc index 888a5351..c7e70435 100644 --- a/extensions/shell/test/shell_test.cc +++ b/extensions/shell/test/shell_test.cc
@@ -14,7 +14,6 @@ #include "extensions/shell/browser/desktop_controller.h" #include "extensions/shell/browser/shell_content_browser_client.h" #include "extensions/shell/browser/shell_extension_system.h" -#include "ui/base/ui_base_features.h" #if defined(OS_CHROMEOS) #include "content/public/test/network_connection_change_simulator.h" @@ -22,14 +21,7 @@ namespace extensions { -AppShellTest::AppShellTest() - : browser_context_(nullptr), - extension_system_(nullptr) { - // Disable mash until app_shell test infra is updated to use Window Service. - scoped_feature_list_.InitWithFeatures( - {} /* enabled */, - {features::kMash, features::kSingleProcessMash} /* disabled */); - +AppShellTest::AppShellTest() { CreateTestServer(base::FilePath(FILE_PATH_LITERAL("extensions/test/data"))); }
diff --git a/extensions/shell/test/shell_test.h b/extensions/shell/test/shell_test.h index 8d85a01..ead304c 100644 --- a/extensions/shell/test/shell_test.h +++ b/extensions/shell/test/shell_test.h
@@ -7,7 +7,6 @@ #include <memory> -#include "base/test/scoped_feature_list.h" #include "content/public/test/browser_test.h" #include "content/public/test/browser_test_base.h" @@ -33,9 +32,8 @@ content::BrowserContext* browser_context() { return browser_context_; } protected: - base::test::ScopedFeatureList scoped_feature_list_; - content::BrowserContext* browser_context_; - ShellExtensionSystem* extension_system_; + content::BrowserContext* browser_context_ = nullptr; + ShellExtensionSystem* extension_system_ = nullptr; }; } // namespace extensions
diff --git a/google_apis/BUILD.gn b/google_apis/BUILD.gn index 84abf02..ef0da3d 100644 --- a/google_apis/BUILD.gn +++ b/google_apis/BUILD.gn
@@ -112,6 +112,7 @@ "gaia/oauth2_access_token_fetcher_impl.h", "gaia/oauth2_access_token_manager.cc", "gaia/oauth2_access_token_manager.h", + "gaia/oauth2_access_token_manager_diagnostics_observer.h", "gaia/oauth2_api_call_flow.cc", "gaia/oauth2_api_call_flow.h", "gaia/oauth2_id_token_decoder.cc",
diff --git a/google_apis/gaia/oauth2_access_token_manager.cc b/google_apis/gaia/oauth2_access_token_manager.cc index c6cef64..c0769a1 100644 --- a/google_apis/gaia/oauth2_access_token_manager.cc +++ b/google_apis/gaia/oauth2_access_token_manager.cc
@@ -14,6 +14,16 @@ OAuth2AccessTokenManager::~OAuth2AccessTokenManager() = default; +void OAuth2AccessTokenManager::AddDiagnosticsObserver( + AccessTokenDiagnosticsObserver* observer) { + diagnostics_observer_list_.AddObserver(observer); +} + +void OAuth2AccessTokenManager::RemoveDiagnosticsObserver( + AccessTokenDiagnosticsObserver* observer) { + diagnostics_observer_list_.RemoveObserver(observer); +} + void OAuth2AccessTokenManager::RegisterTokenResponse( const std::string& client_id, const CoreAccountId& account_id, @@ -43,7 +53,7 @@ void OAuth2AccessTokenManager::ClearCache() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); for (const auto& entry : token_cache_) { - for (auto& observer : token_service_->GetDiagnicsObservers()) + for (auto& observer : diagnostics_observer_list_) observer.OnAccessTokenRemoved(entry.first.account_id, entry.first.scopes); } @@ -57,7 +67,7 @@ iter != token_cache_.end(); /* iter incremented in body */) { if (iter->first.account_id == account_id) { - for (auto& observer : token_service_->GetDiagnicsObservers()) + for (auto& observer : diagnostics_observer_list_) observer.OnAccessTokenRemoved(account_id, iter->first.scopes); token_cache_.erase(iter++); } else { @@ -74,7 +84,7 @@ token_cache_.find(request_parameters); if (token_iterator != token_cache_.end() && token_iterator->second.access_token == token_to_remove) { - for (auto& observer : token_service_->GetDiagnicsObservers()) { + for (auto& observer : diagnostics_observer_list_) { observer.OnAccessTokenRemoved(request_parameters.account_id, request_parameters.scopes); }
diff --git a/google_apis/gaia/oauth2_access_token_manager.h b/google_apis/gaia/oauth2_access_token_manager.h index 95bda00..58ae62e 100644 --- a/google_apis/gaia/oauth2_access_token_manager.h +++ b/google_apis/gaia/oauth2_access_token_manager.h
@@ -21,6 +21,10 @@ explicit OAuth2AccessTokenManager(OAuth2TokenService* token_service); virtual ~OAuth2AccessTokenManager(); + // Add or remove observers of this token manager. + void AddDiagnosticsObserver(AccessTokenDiagnosticsObserver* observer); + void RemoveDiagnosticsObserver(AccessTokenDiagnosticsObserver* observer); + // Add a new entry to the cache. void RegisterTokenResponse( const std::string& client_id, @@ -58,6 +62,9 @@ // The cache of currently valid tokens. OAuth2TokenService::TokenCache token_cache_; + // List of observers to notify when access token status changes. + base::ObserverList<AccessTokenDiagnosticsObserver, true>::Unchecked + diagnostics_observer_list_; // TODO(https://crbug.com/967598): Remove this once OAuth2AccessTokenManager // fully manages access tokens independently of OAuth2TokenService. OAuth2TokenService* token_service_;
diff --git a/google_apis/gaia/oauth2_access_token_manager_diagnostics_observer.h b/google_apis/gaia/oauth2_access_token_manager_diagnostics_observer.h new file mode 100644 index 0000000..fec1189e --- /dev/null +++ b/google_apis/gaia/oauth2_access_token_manager_diagnostics_observer.h
@@ -0,0 +1,42 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef GOOGLE_APIS_GAIA_OAUTH2_ACCESS_TOKEN_MANAGER_DIAGNOSTICS_OBSERVER_H_ +#define GOOGLE_APIS_GAIA_OAUTH2_ACCESS_TOKEN_MANAGER_DIAGNOSTICS_OBSERVER_H_ + +#include "base/time/time.h" +#include "google_apis/gaia/core_account_id.h" +#include "google_apis/gaia/google_service_auth_error.h" + +// TODO(https://crbug.com/967598): Move this class to OAuth2AccessTokenManager +// and discard this file once it's not referred by OAuth2TokenService. + +// Classes that want to monitor status of access token and access token +// request should implement this interface and register with the +// AddOAccessTokenDiagnosticsObserver() call. +class AccessTokenDiagnosticsObserver { + public: + // A set of scopes in OAuth2 authentication. + typedef std::set<std::string> ScopeSet; + + // Called when receiving request for access token. + virtual void OnAccessTokenRequested(const CoreAccountId& account_id, + const std::string& consumer_id, + const ScopeSet& scopes) {} + + // Called when access token fetching finished successfully or + // unsuccessfully. |expiration_time| are only valid with + // successful completion. + virtual void OnFetchAccessTokenComplete(const CoreAccountId& account_id, + const std::string& consumer_id, + const ScopeSet& scopes, + GoogleServiceAuthError error, + base::Time expiration_time) {} + + // Called when an access token was removed. + virtual void OnAccessTokenRemoved(const CoreAccountId& account_id, + const ScopeSet& scopes) {} +}; + +#endif // GOOGLE_APIS_GAIA_OAUTH2_ACCESS_TOKEN_MANAGER_DIAGNOSTICS_OBSERVER_H_
diff --git a/google_apis/gaia/oauth2_token_service.cc b/google_apis/gaia/oauth2_token_service.cc index cda4d8b..38ab53e 100644 --- a/google_apis/gaia/oauth2_token_service.cc +++ b/google_apis/gaia/oauth2_token_service.cc
@@ -412,6 +412,11 @@ return delegate_.get(); } +const base::ObserverList<AccessTokenDiagnosticsObserver, true>::Unchecked& +OAuth2TokenService::GetAccessTokenDiagnosticsObservers() { + return token_manager_->diagnostics_observer_list_; +} + OAuth2TokenService::TokenCache& OAuth2TokenService::token_cache() { return token_manager_->token_cache(); } @@ -433,6 +438,16 @@ diagnostics_observer_list_.RemoveObserver(observer); } +void OAuth2TokenService::AddAccessTokenDiagnosticsObserver( + AccessTokenDiagnosticsObserver* observer) { + token_manager_->AddDiagnosticsObserver(observer); +} + +void OAuth2TokenService::RemoveAccessTokenDiagnosticsObserver( + AccessTokenDiagnosticsObserver* observer) { + token_manager_->RemoveDiagnosticsObserver(observer); +} + std::unique_ptr<OAuth2TokenService::Request> OAuth2TokenService::StartRequestForMultilogin( const CoreAccountId& account_id, @@ -510,13 +525,13 @@ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); std::unique_ptr<RequestImpl> request(new RequestImpl(account_id, consumer)); - for (auto& observer : diagnostics_observer_list_) + for (auto& observer : token_manager_->diagnostics_observer_list_) observer.OnAccessTokenRequested(account_id, consumer->id(), scopes); if (!RefreshTokenIsAvailable(account_id)) { GoogleServiceAuthError error(GoogleServiceAuthError::USER_NOT_SIGNED_UP); - for (auto& observer : diagnostics_observer_list_) { + for (auto& observer : token_manager_->diagnostics_observer_list_) { observer.OnFetchAccessTokenComplete(account_id, consumer->id(), scopes, error, base::Time()); } @@ -581,7 +596,7 @@ RequestImpl* request, const RequestParameters& request_parameters) { DCHECK(cache_token_response && cache_token_response->access_token.length()); - for (auto& observer : diagnostics_observer_list_) { + for (auto& observer : token_manager_->diagnostics_observer_list_) { observer.OnFetchAccessTokenComplete( request_parameters.account_id, request->GetConsumerId(), request_parameters.scopes, GoogleServiceAuthError::AuthErrorNone(), @@ -704,7 +719,7 @@ GetCachedTokenResponse(request_param); for (const base::WeakPtr<RequestImpl>& req : fetcher->waiting_requests()) { if (req) { - for (auto& observer : diagnostics_observer_list_) { + for (auto& observer : token_manager_->diagnostics_observer_list_) { observer.OnFetchAccessTokenComplete( req->GetAccountId(), req->GetConsumerId(), fetcher->GetScopeSet(), fetcher->error(), entry ? entry->expiration_time : base::Time());
diff --git a/google_apis/gaia/oauth2_token_service.h b/google_apis/gaia/oauth2_token_service.h index 47c7c2e7..13e2378 100644 --- a/google_apis/gaia/oauth2_token_service.h +++ b/google_apis/gaia/oauth2_token_service.h
@@ -24,6 +24,7 @@ #include "google_apis/gaia/google_service_auth_error.h" #include "google_apis/gaia/oauth2_access_token_consumer.h" #include "google_apis/gaia/oauth2_access_token_fetcher.h" +#include "google_apis/gaia/oauth2_access_token_manager_diagnostics_observer.h" #include "google_apis/gaia/oauth2_token_service_observer.h" namespace network { @@ -92,27 +93,11 @@ std::string id_; }; - // Classes that want to monitor status of access token and access token + // Classes that want to monitor status of refresh token and refresh token // request should implement this interface and register with the // AddDiagnosticsObserver() call. class DiagnosticsObserver { public: - // Called when receiving request for access token. - virtual void OnAccessTokenRequested(const CoreAccountId& account_id, - const std::string& consumer_id, - const ScopeSet& scopes) {} - // Called when access token fetching finished successfully or - // unsuccessfully. |expiration_time| are only valid with - // successful completion. - virtual void OnFetchAccessTokenComplete(const CoreAccountId& account_id, - const std::string& consumer_id, - const ScopeSet& scopes, - GoogleServiceAuthError error, - base::Time expiration_time) {} - // Called when an access token was removed. - virtual void OnAccessTokenRemoved(const CoreAccountId& account_id, - const ScopeSet& scopes) {} - // Caled when a new refresh token is available. Contains diagnostic // information about the source of the update credentials operation. virtual void OnRefreshTokenAvailableFromSource( @@ -158,6 +143,14 @@ void AddDiagnosticsObserver(DiagnosticsObserver* observer); void RemoveDiagnosticsObserver(DiagnosticsObserver* observer); + // TODO(https://crbug.com/967598): Remove these APIs once we can use + // OAuth2AccessTokenManager without OAuth2TokenService. + // Add or remove observers of access token manager. + void AddAccessTokenDiagnosticsObserver( + AccessTokenDiagnosticsObserver* observer); + void RemoveAccessTokenDiagnosticsObserver( + AccessTokenDiagnosticsObserver* observer); + // Checks in the cache for a valid access token for a specified |account_id| // and |scopes|, and if not found starts a request for an OAuth2 access token // using the OAuth2 refresh token maintained by this instance for that @@ -260,10 +253,13 @@ OAuth2TokenService::TokenCache& token_cache(); const base::ObserverList<DiagnosticsObserver, true>::Unchecked& - GetDiagnicsObservers() { + GetDiagnosticsObservers() { return diagnostics_observer_list_; } + const base::ObserverList<AccessTokenDiagnosticsObserver, true>::Unchecked& + GetAccessTokenDiagnosticsObservers(); + protected: // Implements a cancelable |OAuth2TokenService::Request|, which should be // operated on the UI thread.
diff --git a/google_apis/gaia/oauth_multilogin_result.cc b/google_apis/gaia/oauth_multilogin_result.cc index 42d2b0c..312679e 100644 --- a/google_apis/gaia/oauth_multilogin_result.cc +++ b/google_apis/gaia/oauth_multilogin_result.cc
@@ -39,14 +39,14 @@ const OAuthMultiloginResult& other) { status_ = other.status(); cookies_ = other.cookies(); - failed_accounts_ = other.failed_accounts(); + failed_gaia_ids_ = other.failed_gaia_ids(); } OAuthMultiloginResult& OAuthMultiloginResult::operator=( const OAuthMultiloginResult& other) { status_ = other.status(); cookies_ = other.cookies(); - failed_accounts_ = other.failed_accounts(); + failed_gaia_ids_ = other.failed_gaia_ids(); return *this; } @@ -74,9 +74,9 @@ const std::string* gaia_id = account.FindStringKey("obfuscated_id"); const std::string* status = account.FindStringKey("status"); if (status && gaia_id && *status != "OK") - failed_accounts_.push_back(*gaia_id); + failed_gaia_ids_.push_back(*gaia_id); } - if (failed_accounts_.empty()) + if (failed_gaia_ids_.empty()) status_ = OAuthMultiloginResponseStatus::kUnknownStatus; } @@ -97,6 +97,7 @@ base::Optional<bool> is_http_only = cookie.FindBoolKey("isHttpOnly"); const std::string* priority = cookie.FindStringKey("priority"); base::Optional<double> expiration_delta = cookie.FindDoubleKey("maxAge"); + const std::string* same_site = cookie.FindStringKey("sameSite"); base::TimeDelta before_expiration = base::TimeDelta::FromSecondsD(expiration_delta.value_or(0.0)); @@ -113,7 +114,8 @@ path ? *path : "", /*creation=*/base::Time::Now(), base::Time::Now() + before_expiration, /*last_access=*/base::Time::Now(), is_secure.value_or(true), - is_http_only.value_or(true), net::CookieSameSite::NO_RESTRICTION, + is_http_only.value_or(true), + net::StringToCookieSameSite(same_site ? *same_site : ""), net::StringToCookiePriority(priority ? *priority : "medium")); if (new_cookie.IsCanonical()) { cookies_.push_back(std::move(new_cookie));
diff --git a/google_apis/gaia/oauth_multilogin_result.h b/google_apis/gaia/oauth_multilogin_result.h index 8fb264a..dc019c0 100644 --- a/google_apis/gaia/oauth_multilogin_result.h +++ b/google_apis/gaia/oauth_multilogin_result.h
@@ -67,7 +67,7 @@ ~OAuthMultiloginResult(); std::vector<net::CanonicalCookie> cookies() const { return cookies_; } - std::vector<std::string> failed_accounts() const { return failed_accounts_; } + std::vector<std::string> failed_gaia_ids() const { return failed_gaia_ids_; } OAuthMultiloginResponseStatus status() const { return status_; } private: @@ -84,7 +84,7 @@ void TryParseFailedAccountsFromValue(base::Value* json_value); std::vector<net::CanonicalCookie> cookies_; - std::vector<std::string> failed_accounts_; + std::vector<std::string> failed_gaia_ids_; OAuthMultiloginResponseStatus status_; };
diff --git a/google_apis/gaia/oauth_multilogin_result_unittest.cc b/google_apis/gaia/oauth_multilogin_result_unittest.cc index 674f0a13..3cd83ed 100644 --- a/google_apis/gaia/oauth_multilogin_result_unittest.cc +++ b/google_apis/gaia/oauth_multilogin_result_unittest.cc
@@ -45,17 +45,18 @@ "value":"vAlUe2", "host":"google.com", "path":"/", - "isSecure":true, - "isHttpOnly":false, + "isSecure":false, + "isHttpOnly":true, "priority":"HIGH", - "maxAge":63070000 + "maxAge":63070000, + "sameSite":"Lax" }, { "name":"SSID", "value":"vAlUe3", "domain":".google.de", "path":"path", - "sSecure":true, + "isSecure":true, "isHttpOnly":false, "priority":"HIGH", "maxAge":63070000 @@ -65,10 +66,9 @@ "value":"vAlUe4", "host":".google.fr", "path":"/", - "isSecure":true, - "isHttpOnly":false, "priority":"HIGH", - "maxAge":0 + "maxAge":0, + "sameSite":"Strict" } ] } @@ -85,15 +85,16 @@ double expiration = expiration_time.ToDoubleT(); const std::vector<CanonicalCookie> cookies = { CanonicalCookie("SID", "vAlUe1", ".google.ru", "/", time_now, time_now, - expiration_time, true, false, - net::CookieSameSite::NO_RESTRICTION, + expiration_time, /*is_secure=*/true, + /*is_http_only=*/false, net::CookieSameSite::UNSPECIFIED, net::CookiePriority::COOKIE_PRIORITY_HIGH), CanonicalCookie("APISID", "vAlUe2", "google.com", "/", time_now, time_now, - expiration_time, true, false, - net::CookieSameSite::NO_RESTRICTION, + expiration_time, /*is_secure=*/false, + /*is_http_only=*/true, net::CookieSameSite::LAX_MODE, net::CookiePriority::COOKIE_PRIORITY_HIGH), CanonicalCookie("HSID", "vAlUe4", "", "/", time_now, time_now, time_now, - true, false, net::CookieSameSite::NO_RESTRICTION, + /*is_secure=*/true, /*is_http_only=*/true, + net::CookieSameSite::STRICT_MODE, net::CookiePriority::COOKIE_PRIORITY_HIGH)}; EXPECT_EQ((int)result.cookies().size(), 3); @@ -117,19 +118,19 @@ Property(&CanonicalCookie::IsCanonical, Eq(true)))); EXPECT_THAT(result.cookies(), ElementsAre(Property(&CanonicalCookie::IsHttpOnly, Eq(false)), - Property(&CanonicalCookie::IsHttpOnly, Eq(false)), - Property(&CanonicalCookie::IsHttpOnly, Eq(false)))); + Property(&CanonicalCookie::IsHttpOnly, Eq(true)), + Property(&CanonicalCookie::IsHttpOnly, Eq(true)))); EXPECT_THAT(result.cookies(), ElementsAre(Property(&CanonicalCookie::IsSecure, Eq(true)), - Property(&CanonicalCookie::IsSecure, Eq(true)), + Property(&CanonicalCookie::IsSecure, Eq(false)), Property(&CanonicalCookie::IsSecure, Eq(true)))); EXPECT_THAT(result.cookies(), ElementsAre(Property(&CanonicalCookie::SameSite, - Eq(net::CookieSameSite::NO_RESTRICTION)), + Eq(net::CookieSameSite::UNSPECIFIED)), Property(&CanonicalCookie::SameSite, - Eq(net::CookieSameSite::NO_RESTRICTION)), + Eq(net::CookieSameSite::LAX_MODE)), Property(&CanonicalCookie::SameSite, - Eq(net::CookieSameSite::NO_RESTRICTION)))); + Eq(net::CookieSameSite::STRICT_MODE)))); EXPECT_THAT( result.cookies(), ElementsAre(Property(&CanonicalCookie::Priority, @@ -303,7 +304,7 @@ )"; OAuthMultiloginResult result4(data_error_invalid_credentials); EXPECT_EQ(result4.status(), OAuthMultiloginResponseStatus::kInvalidTokens); - EXPECT_THAT(result4.failed_accounts(), ElementsAre(Eq("account1"))); + EXPECT_THAT(result4.failed_gaia_ids(), ElementsAre(Eq("account1"))); // Unknown status. OAuthMultiloginResult unknown_status(R"()]}'
diff --git a/infra/config/cr-buildbucket.cfg b/infra/config/cr-buildbucket.cfg index a5d1001..dbc42c2 100644 --- a/infra/config/cr-buildbucket.cfg +++ b/infra/config/cr-buildbucket.cfg
@@ -2752,9 +2752,10 @@ } builders { name: "Libfuzzer Upload Linux UBSan" - dimensions: "os:Ubuntu-14.04" mixins: "fuzz-ci" mixins: "libfuzzer" + mixins: "linux-xenial" + mixins: "builderless" } builders { name: "VR Linux" @@ -2784,15 +2785,17 @@ } builders { name: "Libfuzzer Upload Linux ASan Debug" - dimensions: "os:Ubuntu-14.04" mixins: "fuzz-ci" mixins: "libfuzzer" + mixins: "linux-xenial" + mixins: "builderless" } builders { name: "Libfuzzer Upload Linux V8-ARM64 ASan Debug" - dimensions: "os:Ubuntu-14.04" mixins: "fuzz-ci" mixins: "libfuzzer" + mixins: "linux-xenial" + mixins: "builderless" } builders { name: "Closure Compilation Linux" @@ -2831,39 +2834,45 @@ } builders { name: "Libfuzzer Upload Linux V8-ARM64 ASan" - dimensions: "os:Ubuntu-14.04" mixins: "fuzz-ci" mixins: "libfuzzer" + mixins: "linux-xenial" + mixins: "builderless" } builders { name: "Libfuzzer Upload Linux32 ASan Debug" - dimensions: "os:Ubuntu-14.04" mixins: "fuzz-ci" mixins: "libfuzzer" + mixins: "linux-xenial" + mixins: "builderless" } builders { name: "Libfuzzer Upload Linux32 ASan" - dimensions: "os:Ubuntu-14.04" mixins: "fuzz-ci" mixins: "libfuzzer" + mixins: "linux-xenial" + mixins: "builderless" } builders { name: "Libfuzzer Upload Linux32 V8-ARM ASan Debug" - dimensions: "os:Ubuntu-14.04" mixins: "fuzz-ci" mixins: "libfuzzer" + mixins: "linux-xenial" + mixins: "builderless" } builders { name: "Libfuzzer Upload Linux32 V8-ARM ASan" - dimensions: "os:Ubuntu-14.04" mixins: "fuzz-ci" mixins: "libfuzzer" + mixins: "linux-xenial" + mixins: "builderless" } builders { name: "Libfuzzer Upload Chrome OS ASan" - dimensions: "os:Ubuntu-14.04" mixins: "fuzz-ci" mixins: "libfuzzer" + mixins: "linux-xenial" + mixins: "builderless" } builders { name: "Android CFI"
diff --git a/ios/web/favicon/BUILD.gn b/ios/web/favicon/BUILD.gn index f39a52b8..d8a81cb 100644 --- a/ios/web/favicon/BUILD.gn +++ b/ios/web/favicon/BUILD.gn
@@ -8,8 +8,11 @@ configs += [ "//build/config/compiler:enable_arc" ] deps = [ "//ios/web/public", + "//ios/web/web_state:web_state_impl_header", ] sources = [ + "favicon_manager.h", + "favicon_manager.mm", "favicon_status.cc", "favicon_url.cc", "favicon_util.h",
diff --git a/ios/web/favicon/favicon_manager.h b/ios/web/favicon/favicon_manager.h new file mode 100644 index 0000000..d1044f5 --- /dev/null +++ b/ios/web/favicon/favicon_manager.h
@@ -0,0 +1,37 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_WEB_FAVICON_FAVICON_MANAGER_H_ +#define IOS_WEB_FAVICON_FAVICON_MANAGER_H_ + +#include "base/macros.h" +#include "base/values.h" + +class GURL; +namespace web { +class WebStateImpl; +class WebFrame; + +// Handles "favicon.favicons" message from injected JavaScript and notifies +// WebStateImpl if message contains favicon URLs. +class FaviconManager final { + public: + explicit FaviconManager(WebStateImpl* web_state); + ~FaviconManager(); + + private: + bool OnJsMessage(const base::DictionaryValue& message, + const GURL& page_url, + bool has_user_gesture, + bool in_main_frame, + WebFrame* sender_frame); + + WebStateImpl* web_state_impl_ = nullptr; + + DISALLOW_COPY_AND_ASSIGN(FaviconManager); +}; + +} // namespace web + +#endif // IOS_WEB_FAVICON_FAVICON_MANAGER_H_
diff --git a/ios/web/favicon/favicon_manager.mm b/ios/web/favicon/favicon_manager.mm new file mode 100644 index 0000000..be68f98 --- /dev/null +++ b/ios/web/favicon/favicon_manager.mm
@@ -0,0 +1,52 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ios/web/favicon/favicon_manager.h" + +#import "ios/web/favicon/favicon_util.h" +#import "ios/web/web_state/web_state_impl.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +namespace { +const char kCommandPrefix[] = "favicon"; +} + +namespace web { + +FaviconManager::FaviconManager(WebStateImpl* web_state) + : web_state_impl_(web_state) { + web_state_impl_->AddScriptCommandCallback( + base::BindRepeating(&FaviconManager::OnJsMessage, base::Unretained(this)), + kCommandPrefix); +} + +FaviconManager::~FaviconManager() { + web_state_impl_->RemoveScriptCommandCallback(kCommandPrefix); +} + +bool FaviconManager::OnJsMessage(const base::DictionaryValue& message, + const GURL& page_url, + bool has_user_gesture, + bool form_in_main_frame, + WebFrame* sender_frame) { + DCHECK(sender_frame->IsMainFrame()); + + const std::string* command = message.FindStringKey("command"); + if (!command) { + return false; + } + + std::vector<FaviconURL> URLs; + if (!ExtractFaviconURL(&message, page_url, &URLs)) + return false; + + if (!URLs.empty()) + web_state_impl_->OnFaviconUrlUpdated(URLs); + return true; +} + +} // namespace web
diff --git a/ios/web/favicon/resources/favicon.js b/ios/web/favicon/resources/favicon.js index 8ccb890a..7834440 100644 --- a/ios/web/favicon/resources/favicon.js +++ b/ios/web/favicon/resources/favicon.js
@@ -16,7 +16,7 @@ (function() { __gCrWeb.message.invokeOnHost({ - 'command': 'document.favicons', + 'command': 'favicon.favicons', 'favicons': __gCrWeb.common.getFavicons() }); }()); // End of anonymous object
diff --git a/ios/web/navigation/resources/restore_session.html b/ios/web/navigation/resources/restore_session.html index cd4d85c..6301e793 100644 --- a/ios/web/navigation/resources/restore_session.html +++ b/ios/web/navigation/resources/restore_session.html
@@ -120,15 +120,10 @@ } /** - * Sends error message to native controller. + * print error and show blank page. */ function handleError(message) { console.log("Error: " + message); - if (__gCrWeb.message) { - __gCrWeb.message.invokeOnHost( - {"command": "restoresession.error", "message": message}); - __gCrWeb.message.invokeQueues(); - } window.location.replace("about:blank"); } </script>
diff --git a/ios/web/web_state/js/resources/navigation.js b/ios/web/web_state/js/resources/navigation.js index fe50f56..b7770d4 100644 --- a/ios/web/web_state/js/resources/navigation.js +++ b/ios/web/web_state/js/resources/navigation.js
@@ -109,7 +109,7 @@ // Because hash changes don't trigger __gCrWeb.didFinishNavigation, so fetch // favicons for the new page manually. __gCrWeb.message.invokeOnHost({ - 'command': 'document.favicons', + 'command': 'favicon.favicons', 'favicons': __gCrWeb.common.getFavicons() });
diff --git a/ios/web/web_state/ui/crw_web_controller.mm b/ios/web/web_state/ui/crw_web_controller.mm index e4577ed..5f2e9077 100644 --- a/ios/web/web_state/ui/crw_web_controller.mm +++ b/ios/web/web_state/ui/crw_web_controller.mm
@@ -48,7 +48,7 @@ #include "ios/web/common/features.h" #include "ios/web/common/referrer_util.h" #include "ios/web/common/url_util.h" -#import "ios/web/favicon/favicon_util.h" +#import "ios/web/favicon/favicon_manager.h" #import "ios/web/find_in_page/find_in_page_manager_impl.h" #include "ios/web/history_state_util.h" #import "ios/web/js_messaging/crw_js_injector.h" @@ -78,7 +78,6 @@ #import "ios/web/public/deprecated/crw_native_content_provider.h" #include "ios/web/public/deprecated/url_verification_constants.h" #import "ios/web/public/download/download_controller.h" -#include "ios/web/public/favicon/favicon_url.h" #import "ios/web/public/java_script_dialog_presenter.h" #include "ios/web/public/js_messaging/web_frame.h" #include "ios/web/public/js_messaging/web_frame_util.h" @@ -217,6 +216,9 @@ // State of user interaction with web content. web::UserInteractionState _userInteractionState; + + // Manager for favicon JavaScript messages. + std::unique_ptr<web::FaviconManager> _faviconManager; } // The WKNavigationDelegate handler class. @@ -403,6 +405,7 @@ web::BrowsingDataRemover::FromBrowserState(browserState)->AddObserver(self); web::WebFramesManagerImpl::CreateForWebState(_webStateImpl); web::FindInPageManagerImpl::CreateForWebState(_webStateImpl); + _faviconManager = std::make_unique<web::FaviconManager>(_webStateImpl); _legacyNativeController = [[CRWLegacyNativeContentController alloc] initWithWebState:webState]; _legacyNativeController.delegate = self; @@ -711,6 +714,7 @@ _SSLStatusUpdater = nil; [self.UIHandler close]; [self.JSNavigationHandler close]; + _faviconManager.reset(); self.swipeRecognizerProvider = nil; [self.legacyNativeController close]; @@ -955,96 +959,21 @@ - (void)loadData:(NSData*)data MIMEType:(NSString*)MIMEType forURL:(const GURL&)URL { - [self stopLoading]; - web::NavigationItemImpl* item = - self.navigationManagerImpl->GetLastCommittedItemImpl(); - auto navigationContext = web::NavigationContextImpl::CreateNavigationContext( - self.webStateImpl, URL, - /*has_user_gesture=*/true, item->GetTransitionType(), - /*is_renderer_initiated=*/false); - self.navigationHandler.navigationState = web::WKNavigationState::REQUESTED; - navigationContext->SetNavigationItemUniqueID(item->GetUniqueID()); - - item->SetNavigationInitiationType( - web::NavigationInitiationType::BROWSER_INITIATED); - // The error_retry_state_machine may still be in the - // |kDisplayingWebErrorForFailedNavigation| from the navigation that is being - // replaced. As the navigation is now successful, the error can be cleared. - item->error_retry_state_machine().SetNoNavigationError(); - // The load data call will replace the current navigation and the webView URL - // of the navigation will be replaced by |URL|. Set the URL of the - // navigationItem to keep them synced. - // Note: it is possible that the URL in item already match |url|. But item can - // also contain a placeholder URL intended to be replaced. - item->SetURL(URL); - navigationContext->SetMimeType(MIMEType); - if (item->GetUserAgentType() == web::UserAgentType::NONE && - URLNeedsUserAgentType(URL)) { - item->SetUserAgentType(web::UserAgentType::MOBILE); - } - - WKNavigation* navigation = - [self.webView loadData:data - MIMEType:MIMEType - characterEncodingName:base::SysUTF8ToNSString(base::kCodepageUTF8) - baseURL:net::NSURLWithGURL(URL)]; - - [self.navigationHandler.navigationStates - setContext:std::move(navigationContext) - forNavigation:navigation]; - [self.navigationHandler.navigationStates - setState:web::WKNavigationState::REQUESTED - forNavigation:navigation]; + [_requestController loadData:data + webView:self.webView + MIMEType:MIMEType + forURL:URL]; } // Loads the HTML into the page at the given URL. Only for testing purpose. - (void)loadHTML:(NSString*)HTML forURL:(const GURL&)URL { - DCHECK(HTML.length); - // Remove the transient content view. - self.webStateImpl->ClearTransientContent(); - - self.navigationHandler.navigationState = web::WKNavigationState::REQUESTED; - // Web View should not be created for App Specific URLs. if (!web::GetWebClient()->IsAppSpecificURL(URL)) { [self ensureWebViewCreated]; DCHECK(self.webView) << "self.webView null while trying to load HTML"; } - WKNavigation* navigation = - [self.webView loadHTMLString:HTML baseURL:net::NSURLWithGURL(URL)]; - [self.navigationHandler.navigationStates - setState:web::WKNavigationState::REQUESTED - forNavigation:navigation]; - std::unique_ptr<web::NavigationContextImpl> context; - const ui::PageTransition loadHTMLTransition = - ui::PageTransition::PAGE_TRANSITION_TYPED; - if (self.webStateImpl->HasWebUI()) { - // WebUI uses |loadHTML:forURL:| to feed the content to web view. This - // should not be treated as a navigation, but WKNavigationDelegate callbacks - // still expect a valid context. - context = web::NavigationContextImpl::CreateNavigationContext( - self.webStateImpl, URL, /*has_user_gesture=*/true, loadHTMLTransition, - /*is_renderer_initiated=*/false); - context->SetNavigationItemUniqueID(self.currentNavItem->GetUniqueID()); - if (web::features::StorePendingItemInContext()) { - // Transfer pending item ownership to NavigationContext. - // NavigationManager owns pending item after navigation is requested and - // until navigation context is created. - context->SetItem(self.navigationManagerImpl->ReleasePendingItem()); - } - } else { - context = [self registerLoadRequestForURL:URL - referrer:web::Referrer() - transition:loadHTMLTransition - sameDocumentNavigation:NO - hasUserGesture:YES - rendererInitiated:NO - placeholderNavigation:NO]; - } - context->SetLoadingHtmlString(true); - context->SetMimeType(@"text/html"); - [self.navigationHandler.navigationStates setContext:std::move(context) - forNavigation:navigation]; + + [_requestController loadHTML:HTML webView:self.webView forURL:URL]; } - (void)requirePageReconstruction { @@ -1806,11 +1735,7 @@ dispatch_once(&onceToken, ^{ handlers = new std::map<std::string, SEL>(); (*handlers)["chrome.send"] = @selector(handleChromeSendMessage:context:); - (*handlers)["document.favicons"] = - @selector(handleDocumentFaviconsMessage:context:); (*handlers)["window.error"] = @selector(handleWindowErrorMessage:context:); - (*handlers)["restoresession.error"] = - @selector(handleRestoreSessionErrorMessage:context:); }); DCHECK(handlers); auto iter = handlers->find(command); @@ -1964,27 +1889,6 @@ return NO; } -// Handles 'document.favicons' message. -- (BOOL)handleDocumentFaviconsMessage:(base::DictionaryValue*)message - context:(NSDictionary*)context { - if (![context[kIsMainFrame] boolValue]) - return NO; - - std::vector<web::FaviconURL> URLs; - GURL originGURL; - id origin = context[kOriginURLKey]; - if (origin) { - NSURL* originNSURL = base::mac::ObjCCastStrict<NSURL>(origin); - originGURL = net::GURLWithNSURL(originNSURL); - } - if (!web::ExtractFaviconURL(message, originGURL, &URLs)) - return NO; - - if (!URLs.empty()) - self.webStateImpl->OnFaviconUrlUpdated(URLs); - return YES; -} - // Handles 'window.error' message. - (BOOL)handleWindowErrorMessage:(base::DictionaryValue*)message context:(NSDictionary*)context { @@ -1998,28 +1902,6 @@ return YES; } -// Handles 'restoresession.error' message. -- (BOOL)handleRestoreSessionErrorMessage:(base::DictionaryValue*)message - context:(NSDictionary*)context { - if (![context[kIsMainFrame] boolValue]) - return NO; - std::string errorMessage; - if (!message->GetString("message", &errorMessage)) { - DLOG(WARNING) << "JS message parameter not found: message"; - return NO; - } - - // Restore session error is likely a result of coding error. Log diagnostics - // information that is sent back by the page to aid debugging. - NOTREACHED() - << "Session restore failed unexpectedly with error: " << errorMessage - << ". Web view URL: " - << (self.webView - ? net::GURLWithNSURL(self.webView.URL).possibly_invalid_spec() - : " N/A"); - return YES; -} - #pragma mark - WebUI // Sets up WebUI for URL.
diff --git a/ios/web/web_state/ui/crw_web_request_controller.h b/ios/web/web_state/ui/crw_web_request_controller.h index c009c1f..ef132a4 100644 --- a/ios/web/web_state/ui/crw_web_request_controller.h +++ b/ios/web/web_state/ui/crw_web_request_controller.h
@@ -72,6 +72,19 @@ (web::WKBackForwardListItemHolder*) holder; +// Loads |data| of type |MIMEType| and replaces last committed URL with the +// given |URL|. +- (void)loadData:(NSData*)data + webView:(WKWebView*)webView + MIMEType:(NSString*)MIMEType + forURL:(const GURL&)URL; + +// Loads |HTML| into the page and use |URL| to resolve relative URLs within the +// document. +- (void)loadHTML:(NSString*)HTML + webView:(WKWebView*)webView + forURL:(const GURL&)URL; + @end #endif // IOS_WEB_WEB_STATE_UI_CRW_WEB_REQUEST_CONTROLLER_H_
diff --git a/ios/web/web_state/ui/crw_web_request_controller.mm b/ios/web/web_state/ui/crw_web_request_controller.mm index 8586e01..d88ba4c 100644 --- a/ios/web/web_state/ui/crw_web_request_controller.mm +++ b/ios/web/web_state/ui/crw_web_request_controller.mm
@@ -7,6 +7,7 @@ #import <WebKit/WebKit.h> #include "base/feature_list.h" +#include "base/i18n/i18n_constants.h" #import "base/ios/block_types.h" #include "base/logging.h" #include "base/metrics/histogram_macros.h" @@ -32,6 +33,7 @@ using web::wk_navigation_util::ExtractUrlFromPlaceholderUrl; using web::wk_navigation_util::IsPlaceholderUrl; using web::wk_navigation_util::kReferrerHeaderName; +using web::wk_navigation_util::URLNeedsUserAgentType; namespace { // Values for the histogram that counts slow/fast back/forward navigations. @@ -256,6 +258,99 @@ })); } +- (void)loadData:(NSData*)data + webView:(WKWebView*)webView + MIMEType:(NSString*)MIMEType + forURL:(const GURL&)URL { + [_delegate webRequestControllerStopLoading:self]; + web::NavigationItemImpl* item = + self.navigationManagerImpl->GetLastCommittedItemImpl(); + auto navigationContext = web::NavigationContextImpl::CreateNavigationContext( + self.webState, URL, + /*has_user_gesture=*/true, item->GetTransitionType(), + /*is_renderer_initiated=*/false); + self.navigationHandler.navigationState = web::WKNavigationState::REQUESTED; + navigationContext->SetNavigationItemUniqueID(item->GetUniqueID()); + + item->SetNavigationInitiationType( + web::NavigationInitiationType::BROWSER_INITIATED); + // The error_retry_state_machine may still be in the + // |kDisplayingWebErrorForFailedNavigation| from the navigation that is being + // replaced. As the navigation is now successful, the error can be cleared. + item->error_retry_state_machine().SetNoNavigationError(); + // The load data call will replace the current navigation and the webView URL + // of the navigation will be replaced by |URL|. Set the URL of the + // navigationItem to keep them synced. + // Note: it is possible that the URL in item already match |url|. But item can + // also contain a placeholder URL intended to be replaced. + item->SetURL(URL); + navigationContext->SetMimeType(MIMEType); + if (item->GetUserAgentType() == web::UserAgentType::NONE && + URLNeedsUserAgentType(URL)) { + item->SetUserAgentType(web::UserAgentType::MOBILE); + } + + WKNavigation* navigation = + [webView loadData:data + MIMEType:MIMEType + characterEncodingName:base::SysUTF8ToNSString(base::kCodepageUTF8) + baseURL:net::NSURLWithGURL(URL)]; + + [self.navigationHandler.navigationStates + setContext:std::move(navigationContext) + forNavigation:navigation]; + [self.navigationHandler.navigationStates + setState:web::WKNavigationState::REQUESTED + forNavigation:navigation]; +} + +- (void)loadHTML:(NSString*)HTML + webView:(WKWebView*)webView + forURL:(const GURL&)URL { + DCHECK(HTML.length); + // Remove the transient content view. + self.webState->ClearTransientContent(); + + self.navigationHandler.navigationState = web::WKNavigationState::REQUESTED; + + WKNavigation* navigation = [webView loadHTMLString:HTML + baseURL:net::NSURLWithGURL(URL)]; + [self.navigationHandler.navigationStates + setState:web::WKNavigationState::REQUESTED + forNavigation:navigation]; + std::unique_ptr<web::NavigationContextImpl> context; + const ui::PageTransition loadHTMLTransition = + ui::PageTransition::PAGE_TRANSITION_TYPED; + if (self.webState->HasWebUI()) { + // WebUI uses |loadHTML:forURL:| to feed the content to web view. This + // should not be treated as a navigation, but WKNavigationDelegate callbacks + // still expect a valid context. + context = web::NavigationContextImpl::CreateNavigationContext( + self.webState, URL, /*has_user_gesture=*/true, loadHTMLTransition, + /*is_renderer_initiated=*/false); + context->SetNavigationItemUniqueID(self.currentNavItem->GetUniqueID()); + if (web::features::StorePendingItemInContext()) { + // Transfer pending item ownership to NavigationContext. + // NavigationManager owns pending item after navigation is requested and + // until navigation context is created. + context->SetItem(self.navigationManagerImpl->ReleasePendingItem()); + } + } else { + context = [_delegate webRequestController:self + registerLoadRequestForURL:URL + referrer:web::Referrer() + transition:loadHTMLTransition + sameDocumentNavigation:NO + hasUserGesture:YES + rendererInitiated:NO + placeholderNavigation:NO]; + } + context->SetLoadingHtmlString(true); + context->SetMimeType(@"text/html"); + [self.navigationHandler.navigationStates setContext:std::move(context) + forNavigation:navigation]; +} + // Reports Navigation.IOSWKWebViewSlowFastBackForward UMA. No-op if pending // navigation is not back forward navigation. - (void)reportBackForwardNavigationTypeForFastNavigation:(BOOL)isFast {
diff --git a/media/audio/cras/audio_manager_cras.cc b/media/audio/cras/audio_manager_cras.cc index 58e91b02..376989bf 100644 --- a/media/audio/cras/audio_manager_cras.cc +++ b/media/audio/cras/audio_manager_cras.cc
@@ -91,8 +91,7 @@ device_names->emplace_back(kInternalOutputVirtualDevice, base::NumberToString(device_list[0].id)); } else { - DCHECK(device_list[0].type == chromeos::AUDIO_TYPE_INTERNAL_MIC || - device_list[1].type == chromeos::AUDIO_TYPE_INTERNAL_MIC); + DCHECK(device_list[0].IsInternalMic() || device_list[1].IsInternalMic()); device_names->emplace_back(kInternalInputVirtualDevice, base::NumberToString(device_list[0].id)); }
diff --git a/media/blink/resource_multibuffer_data_provider.cc b/media/blink/resource_multibuffer_data_provider.cc index 551351c..e39a17f6 100644 --- a/media/blink/resource_multibuffer_data_provider.cc +++ b/media/blink/resource_multibuffer_data_provider.cc
@@ -251,23 +251,8 @@ destination_url_data->set_valid_until(base::Time::Now() + GetCacheValidUntil(response)); - uint32_t reasons = GetReasonsForUncacheability(response); - destination_url_data->set_cacheable(reasons == 0); - UMA_HISTOGRAM_BOOLEAN("Media.CacheUseful", reasons == 0); - int shift = 0; - int max_enum = base::bits::Log2Ceiling(kMaxReason); - while (reasons) { - DCHECK_LT(shift, max_enum); // Sanity check. - if (reasons & 0x1) { - // Note: this uses an exact linear UMA to fake an enum UMA, as the actual - // enum is a bitmask. - UMA_HISTOGRAM_EXACT_LINEAR("Media.UncacheableReason", shift, - max_enum); // PRESUBMIT_IGNORE_UMA_MAX - } - - reasons >>= 1; - ++shift; - } + destination_url_data->set_cacheable(GetReasonsForUncacheability(response) == + 0); // Expected content length can be |kPositionNotSpecified|, in that case // |content_length_| is not specified and this is a streaming response.
diff --git a/media/gpu/vaapi/vaapi_video_decoder.cc b/media/gpu/vaapi/vaapi_video_decoder.cc index 3e830d11..e372ad1 100644 --- a/media/gpu/vaapi/vaapi_video_decoder.cc +++ b/media/gpu/vaapi/vaapi_video_decoder.cc
@@ -130,7 +130,7 @@ return; } - if (!decoder_thread_.Start()) { + if (!decoder_thread_.IsRunning() && !decoder_thread_.Start()) { std::move(init_cb).Run(false); return; } @@ -149,9 +149,32 @@ InitCB init_cb, OutputCB output_cb) { DCHECK_CALLED_ON_VALID_SEQUENCE(decoder_sequence_checker_); - DCHECK_EQ(state_, State::kUninitialized); + DCHECK(state_ == State::kUninitialized || state_ == State::kWaitingForInput); DVLOGF(3); + // Reinitializing the decoder is allowed if there are no pending decodes. + if (current_decode_task_ || !decode_task_queue_.empty()) { + VLOGF(1) << "Don't call Initialize() while there are pending decode tasks"; + client_task_runner_->PostTask(FROM_HERE, + base::BindOnce(std::move(init_cb), false)); + return; + } + + // We expect the decoder to have released all output buffers (by the client + // triggering a flush or reset), even if the media::VideoDecoder API doesn't + // explicitly specify this. + DCHECK(output_frames_.empty()); + + if (state_ != State::kUninitialized) { + DVLOGF(3) << "Reinitializing decoder"; + if (decoder_) { + decoder_->Reset(); + decoder_ = nullptr; + } + vaapi_wrapper_ = nullptr; + SetState(State::kUninitialized); + } + // Initialize VAAPI wrapper. VideoCodecProfile profile = config.profile(); vaapi_wrapper_ = VaapiWrapper::CreateForVideoCodec( @@ -361,8 +384,13 @@ // Get a video frame from the video frame pool. scoped_refptr<VideoFrame> frame = frame_pool_->GetFrame(); - if (!frame) + if (!frame) { + // Ask the video frame pool to notify us when new frames are available, so + // we can retry the current decode task. + frame_pool_->NotifyWhenFrameAvailable(base::BindOnce( + &VaapiVideoDecoder::NotifyFrameAvailableTask, weak_this_)); return nullptr; + } frame->set_timestamp(current_decode_task_->buffer_->timestamp()); @@ -401,13 +429,6 @@ DCHECK_EQ(output_frames_.count(surface_id), 0u); output_frames_[surface_id] = frame; - // When the video frame is returned to the pool we need to be notified, so we - // can start decoding again if we are waiting for output buffers. - // TODO(dstaessens@): Don't make use of BindToCurrentLoop. - base::OnceClosure delete_frame_cb = BindToCurrentLoop( - base::BindOnce(&VaapiVideoDecoder::NotifyFrameAvailableTask, weak_this_)); - frame->AddDestructionObserver(std::move(delete_frame_cb)); - // When the last reference to the VASurface is dropped ReleaseFrameTask() will // be called. This means the decoder no longer needs the frame for output or // reference, so we can safely remove it from |output_frames_| and destroy the @@ -595,9 +616,8 @@ // Check whether the state change is valid. switch (state) { - case State::kDecoding: - DCHECK(state_ == State::kWaitingForInput || - state_ == State::kWaitingForOutput); + case State::kUninitialized: + DCHECK_EQ(state_, State::kWaitingForInput); break; case State::kWaitingForInput: DCHECK(decode_task_queue_.empty()); @@ -609,6 +629,10 @@ DCHECK(current_decode_task_); DCHECK_EQ(state_, State::kDecoding); break; + case State::kDecoding: + DCHECK(state_ == State::kWaitingForInput || + state_ == State::kWaitingForOutput); + break; case State::kResetting: DCHECK(state_ == State::kWaitingForInput || state_ == State::kWaitingForOutput || state_ == State::kDecoding);
diff --git a/media/renderers/video_resource_updater.cc b/media/renderers/video_resource_updater.cc index a5ace70..3f9ebba 100644 --- a/media/renderers/video_resource_updater.cc +++ b/media/renderers/video_resource_updater.cc
@@ -539,20 +539,11 @@ coded_size.height()); gfx::Size uv_tex_size(u_width, u_height); + DCHECK_EQ(frame_resources_.size(), + VideoFrame::NumPlanes(frame->format())); if (frame->HasTextures()) { - if (frame->format() == PIXEL_FORMAT_NV12) { - DCHECK_EQ(2u, frame_resources_.size()); - } else { - DCHECK_EQ(PIXEL_FORMAT_I420, frame->format()); - DCHECK_EQ(3u, - frame_resources_.size()); // Alpha is not supported yet. - } - } else { - DCHECK_GE(frame_resources_.size(), 3u); - DCHECK(frame_resources_.size() <= 3 || - ya_tex_size == VideoFrame::PlaneSize(frame->format(), - VideoFrame::kAPlane, - coded_size)); + DCHECK(frame->format() == PIXEL_FORMAT_NV12 || + frame->format() == PIXEL_FORMAT_I420); } // Compute the UV sub-sampling factor based on the ratio between
diff --git a/mojo/public/cpp/bindings/lib/message.cc b/mojo/public/cpp/bindings/lib/message.cc index 29b4d3c..87965c8 100644 --- a/mojo/public/cpp/bindings/lib/message.cc +++ b/mojo/public/cpp/bindings/lib/message.cc
@@ -243,6 +243,35 @@ serialized_ = true; } +Message::Message(base::span<const uint8_t> payload, + base::span<ScopedHandle> handles) { + MojoResult rv = mojo::CreateMessage(&handle_); + DCHECK_EQ(MOJO_RESULT_OK, rv); + DCHECK(handle_.is_valid()); + + void* buffer; + uint32_t buffer_size; + DCHECK(base::IsValueInRangeForNumericType<uint32_t>(payload.size())); + DCHECK(base::IsValueInRangeForNumericType<uint32_t>(handles.size())); + MojoAppendMessageDataOptions options; + options.struct_size = sizeof(options); + options.flags = MOJO_APPEND_MESSAGE_DATA_FLAG_COMMIT_SIZE; + rv = MojoAppendMessageData( + handle_->value(), static_cast<uint32_t>(payload.size()), + reinterpret_cast<MojoHandle*>(handles.data()), + static_cast<uint32_t>(handles.size()), &options, &buffer, &buffer_size); + DCHECK_EQ(MOJO_RESULT_OK, rv); + // Handle ownership has been taken by MojoAppendMessageData. + for (auto& handle : handles) + ignore_result(handle.release()); + + payload_buffer_ = internal::Buffer(buffer, payload.size(), payload.size()); + std::copy(payload.begin(), payload.end(), + static_cast<uint8_t*>(payload_buffer_.data())); + transferable_ = true; + serialized_ = true; +} + // static Message Message::CreateFromMessageHandle(ScopedMessageHandle* message_handle) { DCHECK(message_handle);
diff --git a/mojo/public/cpp/bindings/message.h b/mojo/public/cpp/bindings/message.h index 4ff8a6b..3be96de 100644 --- a/mojo/public/cpp/bindings/message.h +++ b/mojo/public/cpp/bindings/message.h
@@ -16,6 +16,7 @@ #include "base/callback.h" #include "base/compiler_specific.h" #include "base/component_export.h" +#include "base/containers/span.h" #include "base/logging.h" #include "base/memory/ptr_util.h" #include "mojo/public/cpp/bindings/lib/buffer.h" @@ -68,6 +69,14 @@ size_t payload_interface_id_count, std::vector<ScopedHandle>* handles); + // Constructs a new serialized Message object from a fully populated message + // payload (including a well-formed message header) and an optional set of + // handle attachments. This Message may not be extended with additional + // payload or handles once constructed, but its payload remains mutable as + // long as the Message is not moved and neither |Reset()| nor + // |TakeMojoMessage()| is called. + Message(base::span<const uint8_t> payload, base::span<ScopedHandle> handles); + // Constructs a new serialized Message object from an existing // ScopedMessageHandle; e.g., one read from a message pipe. //
diff --git a/mojo/public/cpp/bindings/tests/BUILD.gn b/mojo/public/cpp/bindings/tests/BUILD.gn index 789872b..91d54b39 100644 --- a/mojo/public/cpp/bindings/tests/BUILD.gn +++ b/mojo/public/cpp/bindings/tests/BUILD.gn
@@ -24,6 +24,7 @@ "map_unittest.cc", "message_queue.cc", "message_queue.h", + "message_unittest.cc", "multiplex_router_unittest.cc", "native_struct_unittest.cc", "new_endpoint_types_unittest.cc",
diff --git a/mojo/public/cpp/bindings/tests/message_unittest.cc b/mojo/public/cpp/bindings/tests/message_unittest.cc new file mode 100644 index 0000000..6c68fdf --- /dev/null +++ b/mojo/public/cpp/bindings/tests/message_unittest.cc
@@ -0,0 +1,81 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <stdint.h> + +#include <algorithm> +#include <vector> + +#include "mojo/public/cpp/bindings/message.h" +#include "mojo/public/cpp/system/message_pipe.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace mojo { +namespace test { +namespace { + +constexpr int32_t kTestMessageName = 42; +constexpr int32_t kTestMessageFlags = 7; +constexpr uint32_t kTestPayloadSize = 32; + +void CreateTestMessagePayload(std::vector<uint8_t>* bytes, + std::vector<ScopedHandle>* handles) { + Message message(kTestMessageName, kTestMessageFlags, 0, kTestPayloadSize, + nullptr); + message.header()->trace_id = 0; + bytes->resize(message.data_num_bytes()); + std::copy(message.data(), message.data() + message.data_num_bytes(), + bytes->begin()); + + MessagePipe pipe; + handles->resize(2); + handles->at(0) = ScopedHandle(std::move(pipe.handle0)); + handles->at(1) = ScopedHandle(std::move(pipe.handle1)); +} + +TEST(BindingsMessageTest, ConstructFromPayload) { + // Verifies that Message objects constructed directly from a raw payload look + // the same on the wire as raw messages constructed with lower level APIs. + MessagePipe pipe; + + // First feed the raw message data directly into the pipe. + std::vector<uint8_t> in_bytes1; + std::vector<ScopedHandle> in_handles1; + CreateTestMessagePayload(&in_bytes1, &in_handles1); + WriteMessageRaw(pipe.handle0.get(), in_bytes1.data(), in_bytes1.size(), + reinterpret_cast<const MojoHandle*>(in_handles1.data()), + in_handles1.size(), MOJO_WRITE_MESSAGE_FLAG_NONE); + for (auto& handle : in_handles1) + ignore_result(handle.release()); + + // Now construct a Message object from the same payload and feed that into the + // pipe. + std::vector<uint8_t> in_bytes2; + std::vector<ScopedHandle> in_handles2; + CreateTestMessagePayload(&in_bytes2, &in_handles2); + Message message(in_bytes2, in_handles2); + WriteMessageNew(pipe.handle0.get(), message.TakeMojoMessage(), + MOJO_WRITE_MESSAGE_FLAG_NONE); + + // Now read both messages and ensure that they're identical. + // NOTE: The handles themselves cannot be identical, but the same number of + // handles should be attached. + std::vector<uint8_t> out_bytes1; + std::vector<ScopedHandle> out_handles1; + ASSERT_EQ(MOJO_RESULT_OK, + ReadMessageRaw(pipe.handle1.get(), &out_bytes1, &out_handles1, + MOJO_READ_MESSAGE_FLAG_NONE)); + std::vector<uint8_t> out_bytes2; + std::vector<ScopedHandle> out_handles2; + ASSERT_EQ(MOJO_RESULT_OK, + ReadMessageRaw(pipe.handle1.get(), &out_bytes2, &out_handles2, + MOJO_READ_MESSAGE_FLAG_NONE)); + + EXPECT_EQ(out_bytes1, out_bytes2); + EXPECT_EQ(out_handles1.size(), out_handles2.size()); +} + +} // namespace +} // namespace test +} // namespace mojo
diff --git a/net/url_request/url_request_http_job.cc b/net/url_request/url_request_http_job.cc index f5a5564..43fd4d3d 100644 --- a/net/url_request/url_request_http_job.cc +++ b/net/url_request/url_request_http_job.cc
@@ -1416,10 +1416,6 @@ request_creation_time_ = base::Time(); UMA_HISTOGRAM_MEDIUM_TIMES("Net.HttpTimeToFirstByte", to_start); - if (request_info_.upload_data_stream && - request_info_.upload_data_stream->size() > 1024 * 1024) { - UMA_HISTOGRAM_MEDIUM_TIMES("Net.HttpTimeToFirstByte.LargeUpload", to_start); - } } void URLRequestHttpJob::ResetTimer() {
diff --git a/services/identity/public/cpp/access_token_fetcher_unittest.cc b/services/identity/public/cpp/access_token_fetcher_unittest.cc index 4fe4632..c1da225 100644 --- a/services/identity/public/cpp/access_token_fetcher_unittest.cc +++ b/services/identity/public/cpp/access_token_fetcher_unittest.cc
@@ -45,7 +45,7 @@ } // namespace class AccessTokenFetcherTest : public testing::Test, - public OAuth2TokenService::DiagnosticsObserver { + public AccessTokenDiagnosticsObserver { public: using TestTokenCallback = StrictMock<MockCallback<AccessTokenFetcher::TokenCallback>>; @@ -61,11 +61,11 @@ account_tracker_ = std::make_unique<AccountTrackerService>(); account_tracker_->Initialize(&pref_service_, base::FilePath()); - token_service_.AddDiagnosticsObserver(this); + token_service_.AddAccessTokenDiagnosticsObserver(this); } ~AccessTokenFetcherTest() override { - token_service_.RemoveDiagnosticsObserver(this); + token_service_.RemoveAccessTokenDiagnosticsObserver(this); } std::string AddAccount(const std::string& gaia_id, const std::string& email) { @@ -107,7 +107,7 @@ AccessTokenInfo access_token_info() { return access_token_info_; } private: - // OAuth2TokenService::DiagnosticsObserver: + // OAuth2AccessTokenManagerDiagnosticsObserver: void OnAccessTokenRequested( const CoreAccountId& account_id, const std::string& consumer_id,
diff --git a/services/identity/public/cpp/identity_manager.cc b/services/identity/public/cpp/identity_manager.cc index d19f7e8..0588de90 100644 --- a/services/identity/public/cpp/identity_manager.cc +++ b/services/identity/public/cpp/identity_manager.cc
@@ -67,6 +67,7 @@ primary_account_manager_->SetObserver(this); token_service_->AddDiagnosticsObserver(this); token_service_->AddObserver(this); + token_service_->AddAccessTokenDiagnosticsObserver(this); // IdentityManager owns the ATS and GCMS instances and will outlive them, so // base::Unretained is safe. @@ -100,6 +101,7 @@ primary_account_manager_->ClearObserver(); token_service_->RemoveObserver(this); token_service_->RemoveDiagnosticsObserver(this); + token_service_->RemoveAccessTokenDiagnosticsObserver(this); } void IdentityManager::AddObserver(Observer* observer) {
diff --git a/services/identity/public/cpp/identity_manager.h b/services/identity/public/cpp/identity_manager.h index cbf867a7..8514908 100644 --- a/services/identity/public/cpp/identity_manager.h +++ b/services/identity/public/cpp/identity_manager.h
@@ -53,6 +53,7 @@ // ./README.md for detailed documentation. class IdentityManager : public PrimaryAccountManager::Observer, public OAuth2TokenService::DiagnosticsObserver, + public AccessTokenDiagnosticsObserver, public OAuth2TokenServiceObserver { public: class Observer { @@ -596,7 +597,7 @@ const GoogleServiceAuthError& error); void OnGaiaCookieDeletedByUserAction(); - // OAuth2TokenService::DiagnosticsObserver: + // AccessTokenDiagnosticsObserver void OnAccessTokenRequested(const CoreAccountId& account_id, const std::string& consumer_id, const ScopeSet& scopes) override; @@ -607,6 +608,7 @@ base::Time expiration_time) override; void OnAccessTokenRemoved(const CoreAccountId& account_id, const ScopeSet& scopes) override; + // OAuth2TokenService::DiagnosticsObserver: void OnRefreshTokenAvailableFromSource(const CoreAccountId& account_id, bool is_refresh_token_valid, const std::string& source) override;
diff --git a/services/identity/public/cpp/identity_manager_unittest.cc b/services/identity/public/cpp/identity_manager_unittest.cc index 939637db..517ff9b 100644 --- a/services/identity/public/cpp/identity_manager_unittest.cc +++ b/services/identity/public/cpp/identity_manager_unittest.cc
@@ -103,7 +103,7 @@ // It should trigger OnAccessTokenRemovedFromCache from // IdentityManager::DiagnosticsObserver. - for (auto& observer : GetDiagnicsObservers()) + for (auto& observer : GetAccessTokenDiagnosticsObservers()) observer.OnAccessTokenRemoved(account_id, scopes); std::move(on_access_token_invalidated_callback_).Run();
diff --git a/services/network/cors/cors_url_loader.cc b/services/network/cors/cors_url_loader.cc index 5b172ca5..4bff8ed 100644 --- a/services/network/cors/cors_url_loader.cc +++ b/services/network/cors/cors_url_loader.cc
@@ -154,6 +154,16 @@ return; } + // Does not allow modifying headers that are stored in |cors_exempt_headers|. + for (const auto& header : modified_headers.GetHeaderVector()) { + if (request_.cors_exempt_headers.HasHeader(header.key)) { + LOG(WARNING) << "A client is trying to modify header value for '" + << header.key << "', but it is not permitted."; + HandleComplete(URLLoaderCompletionStatus(net::ERR_INVALID_ARGUMENT)); + return; + } + } + for (const auto& name : removed_headers) { request_.headers.RemoveHeader(name); request_.cors_exempt_headers.RemoveHeader(name);
diff --git a/services/network/cors/cors_url_loader_unittest.cc b/services/network/cors/cors_url_loader_unittest.cc index c62c701..9ee1956 100644 --- a/services/network/cors/cors_url_loader_unittest.cc +++ b/services/network/cors/cors_url_loader_unittest.cc
@@ -1227,6 +1227,36 @@ GetRequest().cors_exempt_headers.HasHeader(kTestCorsExemptHeader)); } +TEST_F(CorsURLLoaderTest, CorsExemptHeaderModificationOnRedirects) { + ResourceRequest request; + request.url = GURL("https://example.com/foo.png"); + request.cors_exempt_headers.SetHeader(kTestCorsExemptHeader, "test-value"); + CreateLoaderAndStart(request); + EXPECT_EQ(1, num_created_loaders()); + + NotifyLoaderClientOnReceiveRedirect( + CreateRedirectInfo(301, "GET", GURL("https://example.com/bar.png"))); + RunUntilRedirectReceived(); + + ASSERT_TRUE(IsNetworkLoaderStarted()); + EXPECT_TRUE(client().has_received_redirect()); + EXPECT_FALSE(client().has_received_response()); + EXPECT_FALSE(client().has_received_completion()); + EXPECT_TRUE( + GetRequest().cors_exempt_headers.HasHeader(kTestCorsExemptHeader)); + + net::HttpRequestHeaders modified_headers; + modified_headers.SetHeader(kTestCorsExemptHeader, "test-modified"); + FollowRedirect({}, modified_headers); + RunUntilComplete(); + + ASSERT_EQ(1, num_created_loaders()); + EXPECT_FALSE(client().has_received_response()); + EXPECT_TRUE(client().has_received_completion()); + ASSERT_TRUE( + GetRequest().cors_exempt_headers.HasHeader(kTestCorsExemptHeader)); +} + // Tests if OriginAccessList is actually used to decide the cors flag. // Details for the OriginAccessList behaviors are verified in // OriginAccessListTest, but this test intends to verify if CorsURlLoader calls
diff --git a/services/network/public/cpp/resource_request_body.h b/services/network/public/cpp/resource_request_body.h index eae9bc8..292aeb6 100644 --- a/services/network/public/cpp/resource_request_body.h +++ b/services/network/public/cpp/resource_request_body.h
@@ -19,6 +19,12 @@ #include "services/network/public/mojom/url_loader.mojom-shared.h" #include "url/gurl.h" +namespace blink { +namespace mojom { +class FetchAPIRequestBodyDataView; +} // namespace mojom +} // namespace blink + namespace network { // ResourceRequestBody represents body (i.e. upload data) of a HTTP request. @@ -98,6 +104,8 @@ private: friend class base::RefCountedThreadSafe<ResourceRequestBody>; + friend struct mojo::StructTraits<blink::mojom::FetchAPIRequestBodyDataView, + scoped_refptr<network::ResourceRequestBody>>; friend struct mojo::StructTraits<network::mojom::URLRequestBodyDataView, scoped_refptr<network::ResourceRequestBody>>; ~ResourceRequestBody();
diff --git a/services/tracing/perfetto/consumer_host.cc b/services/tracing/perfetto/consumer_host.cc index 79c2b6f..a3c16c77 100644 --- a/services/tracing/perfetto/consumer_host.cc +++ b/services/tracing/perfetto/consumer_host.cc
@@ -330,7 +330,7 @@ void ConsumerHost::TracingSession::RequestBufferUsage( RequestBufferUsageCallback callback) { if (!request_buffer_usage_callback_.is_null()) { - std::move(callback).Run(false, 0); + std::move(callback).Run(false, 0, false); return; } @@ -433,7 +433,7 @@ } if (!success || stats.buffer_stats_size() != 1) { - std::move(request_buffer_usage_callback_).Run(false, 0.0f); + std::move(request_buffer_usage_callback_).Run(false, 0.0f, false); return; } @@ -445,7 +445,10 @@ double percent_full = bytes_in_buffer / static_cast<double>(buf_stats.buffer_size()); percent_full = std::min(std::max(0.0, percent_full), 1.0); - std::move(request_buffer_usage_callback_).Run(true, percent_full); + bool data_loss = buf_stats.chunks_overwritten() > 0 || + buf_stats.chunks_discarded() > 0 || + buf_stats.abi_violations() > 0; + std::move(request_buffer_usage_callback_).Run(true, percent_full, data_loss); } void ConsumerHost::TracingSession::Flush(
diff --git a/services/tracing/public/mojom/perfetto_service.mojom b/services/tracing/public/mojom/perfetto_service.mojom index aad114c..b9241b0 100644 --- a/services/tracing/public/mojom/perfetto_service.mojom +++ b/services/tracing/public/mojom/perfetto_service.mojom
@@ -226,8 +226,10 @@ ReadBuffers(handle<data_pipe_producer> stream) => (); // Request current trace buffer usage of the active session. Will be returned - // as percentage value between 0.0f and 1.0f. - RequestBufferUsage() => (bool success, float percent_full); + // as percentage value between 0.0f and 1.0f. |data_loss| indicates whether + // any trace data is known to have been lost, e.g. because the ring buffer + // wrapped and data were overridden. + RequestBufferUsage() => (bool success, float percent_full, bool data_loss); // Disables tracing and converts the collected trace data converted into the // legacy JSON format before returning it via the data pipe. If
diff --git a/storage/browser/quota/quota_database_unittest.cc b/storage/browser/quota/quota_database_unittest.cc index 288049b..a1911ff 100644 --- a/storage/browser/quota/quota_database_unittest.cc +++ b/storage/browser/quota/quota_database_unittest.cc
@@ -13,8 +13,8 @@ #include "base/callback.h" #include "base/files/file_util.h" #include "base/files/scoped_temp_dir.h" -#include "base/message_loop/message_loop.h" #include "base/stl_util.h" +#include "base/test/scoped_task_environment.h" #include "sql/database.h" #include "sql/meta_table.h" #include "sql/statement.h" @@ -575,7 +575,7 @@ db->CommitTransaction(); } - base::MessageLoop message_loop_; + base::test::ScopedTaskEnvironment scoped_task_environment_; }; TEST_F(QuotaDatabaseTest, LazyOpen) {
diff --git a/third_party/blink/common/BUILD.gn b/third_party/blink/common/BUILD.gn index 0a0fbd0..aa5ca9e 100644 --- a/third_party/blink/common/BUILD.gn +++ b/third_party/blink/common/BUILD.gn
@@ -33,6 +33,7 @@ "feature_policy/feature_policy.cc", "feature_policy/policy_value.cc", "features.cc", + "fetch/fetch_api_request_body_mojom_traits.cc", "frame/frame_policy.cc", "frame/from_ad_state.cc", "frame/user_activation_state.cc",
diff --git a/third_party/blink/common/fetch/OWNERS b/third_party/blink/common/fetch/OWNERS new file mode 100644 index 0000000..b2e47ad --- /dev/null +++ b/third_party/blink/common/fetch/OWNERS
@@ -0,0 +1,7 @@ +file://third_party/blink/renderer/core/fetch/OWNERS + +per-file *_mojom_traits*.*=set noparent +per-file *_mojom_traits*.*=file://ipc/SECURITY_OWNERS + +# TEAM: blink-network-dev@chromium.org +# COMPONENT: Blink>Network>FetchAPI
diff --git a/third_party/blink/common/fetch/fetch_api_request_body_mojom_traits.cc b/third_party/blink/common/fetch/fetch_api_request_body_mojom_traits.cc new file mode 100644 index 0000000..b4b4a6a --- /dev/null +++ b/third_party/blink/common/fetch/fetch_api_request_body_mojom_traits.cc
@@ -0,0 +1,24 @@ +// 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 "third_party/blink/public/common/fetch/fetch_api_request_body_mojom_traits.h" + +#include "services/network/public/cpp/url_request_mojom_traits.h" + +namespace mojo { + +bool StructTraits<blink::mojom::FetchAPIRequestBodyDataView, + scoped_refptr<network::ResourceRequestBody>>:: + Read(blink::mojom::FetchAPIRequestBodyDataView data, + scoped_refptr<network::ResourceRequestBody>* out) { + auto body = base::MakeRefCounted<network::ResourceRequestBody>(); + if (!data.ReadElements(&(body->elements_))) + return false; + body->set_identifier(data.identifier()); + body->set_contains_sensitive_info(data.contains_sensitive_info()); + *out = std::move(body); + return true; +} + +} // namespace mojo
diff --git a/third_party/blink/public/common/DEPS b/third_party/blink/public/common/DEPS index 6f3146b3..727f80b9 100644 --- a/third_party/blink/public/common/DEPS +++ b/third_party/blink/public/common/DEPS
@@ -11,6 +11,7 @@ "+net", "+media", "+mojo", + "+services/network/public/cpp/resource_request_body.h", "+services/network/public/cpp/shared_url_loader_factory.h", "+services/network/public/mojom/url_loader_factory.mojom.h", "+skia/public/interfaces",
diff --git a/third_party/blink/public/common/fetch/fetch_api_request_body.typemap b/third_party/blink/public/common/fetch/fetch_api_request_body.typemap new file mode 100644 index 0000000..b57c723 --- /dev/null +++ b/third_party/blink/public/common/fetch/fetch_api_request_body.typemap
@@ -0,0 +1,15 @@ +# Copyright 2019 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +mojom = "//third_party/blink/public/mojom/fetch/fetch_api_request.mojom" +public_headers = [ + "//base/memory/scoped_refptr.h", + "//services/network/public/cpp/resource_request_body.h", +] +traits_headers = [ "//third_party/blink/public/common/fetch/fetch_api_request_body_mojom_traits.h" ] +public_deps = [ + "//base", + "//services/network/public/cpp:cpp_base", +] +type_mappings = [ "blink.mojom.FetchAPIRequestBody=scoped_refptr<network::ResourceRequestBody>[nullable_is_same_type,copyable_pass_by_value]" ]
diff --git a/third_party/blink/public/common/fetch/fetch_api_request_body_mojom_traits.h b/third_party/blink/public/common/fetch/fetch_api_request_body_mojom_traits.h new file mode 100644 index 0000000..e8b3d20 --- /dev/null +++ b/third_party/blink/public/common/fetch/fetch_api_request_body_mojom_traits.h
@@ -0,0 +1,48 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef THIRD_PARTY_BLINK_PUBLIC_COMMON_FETCH_FETCH_API_REQUEST_BODY_MOJOM_TRAITS_H_ +#define THIRD_PARTY_BLINK_PUBLIC_COMMON_FETCH_FETCH_API_REQUEST_BODY_MOJOM_TRAITS_H_ + +#include <utility> + +#include "base/memory/scoped_refptr.h" +#include "services/network/public/cpp/resource_request_body.h" +#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom.h" + +namespace mojo { + +template <> +struct StructTraits<blink::mojom::FetchAPIRequestBodyDataView, + scoped_refptr<network::ResourceRequestBody>> { + static bool IsNull(const scoped_refptr<network::ResourceRequestBody>& r) { + return !r; + } + + static void SetToNull(scoped_refptr<network::ResourceRequestBody>* out) { + out->reset(); + } + + static const std::vector<network::DataElement>& elements( + const scoped_refptr<network::ResourceRequestBody>& r) { + return *r->elements(); + } + + static uint64_t identifier( + const scoped_refptr<network::ResourceRequestBody>& r) { + return r->identifier_; + } + + static bool contains_sensitive_info( + const scoped_refptr<network::ResourceRequestBody>& r) { + return r->contains_sensitive_info_; + } + + static bool Read(blink::mojom::FetchAPIRequestBodyDataView data, + scoped_refptr<network::ResourceRequestBody>* out); +}; + +} // namespace mojo + +#endif // THIRD_PARTY_BLINK_PUBLIC_COMMON_FETCH_FETCH_API_REQUEST_BODY_MOJOM_TRAITS_H_
diff --git a/third_party/blink/public/mojom/background_sync/background_sync.mojom b/third_party/blink/public/mojom/background_sync/background_sync.mojom index 3ba75ec15..55bf6f1 100644 --- a/third_party/blink/public/mojom/background_sync/background_sync.mojom +++ b/third_party/blink/public/mojom/background_sync/background_sync.mojom
@@ -50,10 +50,37 @@ BackgroundSyncType sync_type; }; -interface BackgroundSyncService { - Register(SyncRegistrationOptions options, int64 service_worker_registration_id) - => (BackgroundSyncError err, SyncRegistrationOptions options); +// Used by SyncManager for one-shot Background Sync. +interface OneShotBackgroundSyncService { + // Used to register one-shot Background Sync tasks. + Register(SyncRegistrationOptions options, + int64 service_worker_registration_id) + => (BackgroundSyncError err, SyncRegistrationOptions? options); + + // Used to indicate that the register() promise has been resolved by + // JavaScript code. DidResolveRegistration(BackgroundSyncRegistrationInfo registration_info); - GetOneShotSyncRegistrations(int64 service_worker_registration_id) - => (BackgroundSyncError err, array<SyncRegistrationOptions> registrations); + + // Returns a list of all one-shot Background Sync registrations. + GetRegistrations(int64 service_worker_registration_id) + => (BackgroundSyncError err, + array<SyncRegistrationOptions> registrations); +}; + +// Used by PeriodicSyncManager for periodic Background Sync. +interface PeriodicBackgroundSyncService { + // Used to register periodic Background Sync tasks. + Register(SyncRegistrationOptions options, + int64 service_worker_registration_id) + => (BackgroundSyncError err, SyncRegistrationOptions? options); + + // Used to unregister periodic Background Sync tasks. Silently succeeds + // if called for non-existent periodic Background Sync registrations. + Unregister(int64 service_worker_registration_id, string tag) + => (BackgroundSyncError err); + + // Returns a list of all periodic Background Sync registrations. + GetRegistrations(int64 service_worker_registration_id) + => (BackgroundSyncError err, + array<SyncRegistrationOptions> registrations); };
diff --git a/third_party/blink/public/mojom/fetch/fetch_api_request.mojom b/third_party/blink/public/mojom/fetch/fetch_api_request.mojom index 44f7c7d..7f766b5 100644 --- a/third_party/blink/public/mojom/fetch/fetch_api_request.mojom +++ b/third_party/blink/public/mojom/fetch/fetch_api_request.mojom
@@ -108,6 +108,28 @@ map<string, string> headers; }; +// Struct representing a Body for a Request: +// https://fetch.spec.whatwg.org/#body +// This has the same members definition with network.mojom.URLRequestBody, which +// aims to pass around body for network.mojom.URLRequest. Both of them are +// typemapped to scoped_refptr<network::ResourceRequestBody> for the default +// variant, the only difference is for the Blink variant that +// network.mojom.URLRequestBody still is typemapped to +// scoped_refptr<network::ResourceRequestBody> but this is typemapped to +// scoped_refptr<blink::EncodedFormData>. +struct FetchAPIRequestBody { + // Store upload bodies + array<network.mojom.DataElement> elements; + + // Identifies a particular upload instance, which is used by the cache to + // formulate a cache key. + uint64 identifier; + + // Indicates whether the post data contains sensitive information like + // passwords. + bool contains_sensitive_info; +}; + // Struct representing a Request: // https://fetch.spec.whatwg.org/#request-class // Compared to network.mojom.URLRequest which is kind of internal data in the @@ -133,7 +155,7 @@ // service workers. // TODO(crbug.com/911930): Remove |blob| and use |body| instead everywhere. SerializedBlob? blob; - network.mojom.URLRequestBody? body; + FetchAPIRequestBody? body; Referrer? referrer; network.mojom.CredentialsMode credentials_mode =
diff --git a/third_party/blink/public/public_typemaps.gni b/third_party/blink/public/public_typemaps.gni index 0b8379e..396c5dc 100644 --- a/third_party/blink/public/public_typemaps.gni +++ b/third_party/blink/public/public_typemaps.gni
@@ -4,6 +4,7 @@ # These are typemaps which are exposed by Blink to its embedder. typemaps = [ + "//third_party/blink/public/common/fetch/fetch_api_request_body.typemap", "//third_party/blink/public/common/fetch/fetch_api_request_headers.typemap", "//third_party/blink/public/common/indexeddb/indexed_db_default.typemap", "//third_party/blink/public/common/loader/url_loader_factory_bundle.typemap",
diff --git a/third_party/blink/renderer/bindings/core/v8/referrer_script_info.cc b/third_party/blink/renderer/bindings/core/v8/referrer_script_info.cc index f4d42df..4875efe 100644 --- a/third_party/blink/renderer/bindings/core/v8/referrer_script_info.cc +++ b/third_party/blink/renderer/bindings/core/v8/referrer_script_info.cc
@@ -32,28 +32,32 @@ v8::Isolate* isolate = context->GetIsolate(); v8::Local<v8::Primitive> base_url_value = host_defined_options->Get(isolate, kBaseURL); + SECURITY_CHECK(base_url_value->IsString()); String base_url_string = - ToCoreStringWithNullCheck(v8::Local<v8::String>::Cast(base_url_value)); + ToCoreString(v8::Local<v8::String>::Cast(base_url_value)); KURL base_url = base_url_string.IsEmpty() ? KURL() : KURL(base_url_string); DCHECK(base_url.IsNull() || base_url.IsValid()); v8::Local<v8::Primitive> credentials_mode_value = host_defined_options->Get(isolate, kCredentialsMode); + SECURITY_CHECK(credentials_mode_value->IsUint32()); auto credentials_mode = static_cast<network::mojom::CredentialsMode>( credentials_mode_value->IntegerValue(context).ToChecked()); v8::Local<v8::Primitive> nonce_value = host_defined_options->Get(isolate, kNonce); - String nonce = - ToCoreStringWithNullCheck(v8::Local<v8::String>::Cast(nonce_value)); + SECURITY_CHECK(nonce_value->IsString()); + String nonce = ToCoreString(v8::Local<v8::String>::Cast(nonce_value)); v8::Local<v8::Primitive> parser_state_value = host_defined_options->Get(isolate, kParserState); + SECURITY_CHECK(parser_state_value->IsUint32()); ParserDisposition parser_state = static_cast<ParserDisposition>( parser_state_value->IntegerValue(context).ToChecked()); v8::Local<v8::Primitive> referrer_policy_value = host_defined_options->Get(isolate, kReferrerPolicy); + SECURITY_CHECK(referrer_policy_value->IsUint32()); network::mojom::ReferrerPolicy referrer_policy = static_cast<network::mojom::ReferrerPolicy>( referrer_policy_value->IntegerValue(context).ToChecked());
diff --git a/third_party/blink/renderer/core/animation/interpolation_effect_test.cc b/third_party/blink/renderer/core/animation/interpolation_effect_test.cc index 2ed3176..ea6fb6f 100644 --- a/third_party/blink/renderer/core/animation/interpolation_effect_test.cc +++ b/third_party/blink/renderer/core/animation/interpolation_effect_test.cc
@@ -67,6 +67,10 @@ interpolation_effect->GetActiveInterpolations(3, kInterpolationTestDuration, active_interpolations); EXPECT_EQ(0ul, active_interpolations.size()); + + interpolation_effect->GetActiveInterpolations(0, kInterpolationTestDuration, + active_interpolations); + EXPECT_EQ(1ul, active_interpolations.size()); } TEST(AnimationInterpolationEffectTest, MultipleInterpolations) {
diff --git a/third_party/blink/renderer/core/clipboard/data_transfer.cc b/third_party/blink/renderer/core/clipboard/data_transfer.cc index 0769fa7..b7160ec 100644 --- a/third_party/blink/renderer/core/clipboard/data_transfer.cc +++ b/third_party/blink/renderer/core/clipboard/data_transfer.cc
@@ -101,10 +101,9 @@ // object contains transparency and there are other elements in the same // stacking context which stacked below. PaintLayer* layer = dragged_layout_object->EnclosingLayer(); - if (!layer->GetLayoutObject().StyleRef().IsStackingContext()) { - layer = - PaintLayerStackingNode::AncestorStackingContextNode(layer)->Layer(); - } + if (!layer->GetLayoutObject().StyleRef().IsStackingContext()) + layer = layer->AncestorStackingContext(); + IntRect absolute_bounding_box = dragged_layout_object->AbsoluteBoundingBoxRectIncludingDescendants(); // TODO(chrishtr): consider using the root frame's visible rect instead
diff --git a/third_party/blink/renderer/core/css/remote_font_face_source.cc b/third_party/blink/renderer/core/css/remote_font_face_source.cc index 9ddc913..3241fe0 100644 --- a/third_party/blink/renderer/core/css/remote_font_face_source.cc +++ b/third_party/blink/renderer/core/css/remote_font_face_source.cc
@@ -359,13 +359,6 @@ DCHECK_NE(load_start_time_, 0); int duration = static_cast<int>(CurrentTimeMS() - load_start_time_); RecordLoadTimeHistogram(font, duration); - - enum { kCorsFail, kCorsSuccess, kCorsEnumMax }; - int cors_value = - font->GetResponse().IsCorsSameOrigin() ? kCorsSuccess : kCorsFail; - DEFINE_THREAD_SAFE_STATIC_LOCAL(EnumerationHistogram, cors_histogram, - ("WebFont.CORSSuccess", kCorsEnumMax)); - cors_histogram.Count(cors_value); } }
diff --git a/third_party/blink/renderer/core/css/resolver/style_adjuster.cc b/third_party/blink/renderer/core/css/resolver/style_adjuster.cc index 1a0b2673..08efdcc 100644 --- a/third_party/blink/renderer/core/css/resolver/style_adjuster.cc +++ b/third_party/blink/renderer/core/css/resolver/style_adjuster.cc
@@ -672,5 +672,17 @@ style.SetTextOverflow(text_control->ValueForTextOverflow()); } } + + if (RuntimeEnabledFeatures::LayoutNGBlockFragmentationEnabled()) { + // When establishing a block fragmentation context for LayoutNG, we require + // that everything fragmentable inside can be laid out by NG natively, since + // NG and legacy layout cannot cooperate within the same fragmentation + // context. Set a flag, so that we can quickly determine whether we need to + // check that an element is compatible with the NG block fragmentation + // machinery. + if (style.SpecifiesColumns() || + (element && element->GetDocument().Printing())) + style.SetInsideNGFragmentationContext(true); + } } } // namespace blink
diff --git a/third_party/blink/renderer/core/dom/element.cc b/third_party/blink/renderer/core/dom/element.cc index 0359576f..15474ea 100644 --- a/third_party/blink/renderer/core/dom/element.cc +++ b/third_party/blink/renderer/core/dom/element.cc
@@ -339,6 +339,18 @@ if (style.HasTextCombine() && !style.IsHorizontalWritingMode()) return true; + if (style.InsideNGFragmentationContext()) { + // If we're inside an NG block fragmentation context, all fragmentable boxes + // must be laid out by NG natively. We only allow legacy layout objects if + // they are monolithic (e.g. replaced content, inline-table, and so + // on). Inline display types end up on a line, and are therefore monolithic, + // so we can allow those. + if (!style.IsDisplayInlineType()) { + if (style.IsDisplayTableType() || style.IsDisplayFlexibleOrGridBox()) + return true; + } + } + return false; } @@ -3733,6 +3745,15 @@ // forced legacy layout in the ancestry, e.g. if this element no longer // establishes a new formatting context. ForceLegacyLayoutInFormattingContext(new_style); + + // If we're inside an NG fragmentation context, we also need the entire + // fragmentation context to fall back to legacy layout. Note that once this + // has happened, the fragmentation context will be locked to legacy layout, + // even if all the reasons for requiring it in the first place disappear + // (e.g. if the only reason was a table, and that table is removed, we'll + // still be using legacy layout). + if (new_style.InsideNGFragmentationContext()) + ForceLegacyLayoutInFragmentationContext(new_style); } else if (old_force) { // TODO(mstensho): If we have ancestors that got legacy layout just because // of this child, we should clean it up, and switch the subtree back to NG, @@ -3760,6 +3781,38 @@ } } +void Element::ForceLegacyLayoutInFragmentationContext( + const ComputedStyle& new_style) { + // This element cannot be laid out natively by LayoutNG. We now need to switch + // all enclosing block fragmentation contexts over to using legacy + // layout. Find the element that establishes the fragmentation context, and + // switch it over to legacy layout. Note that we walk the parent chain here, + // and not the containing block chain. This means that we may get false + // positives; e.g. if there's an absolutely positioned table, whose containing + // block of the table is on the outside of the fragmentation context, we're + // still going to fall back to legacy. + Element* parent; + for (Element* walker = this; walker; walker = parent) { + parent = ToElementOrNull(LayoutTreeBuilderTraversal::Parent(*walker)); + if (!walker->GetComputedStyle()->SpecifiesColumns()) + continue; + + // Found an element that establishes a fragmentation context. Force it to do + // legacy layout. Keep looking for outer fragmentation contexts, since we + // need to force them over to legacy as well. + walker->SetShouldForceLegacyLayoutForChild(true); + walker->SetNeedsReattachLayoutTree(); + if (parent && !parent->GetComputedStyle()->InsideNGFragmentationContext()) + return; + } + DCHECK(GetDocument().Printing()); + // Force legacy layout on the entire document, since we're printing, and + // there's some fragmentable box that needs legacy layout inside somewhere. + Element* root = GetDocument().documentElement(); + root->SetShouldForceLegacyLayoutForChild(true); + root->SetNeedsReattachLayoutTree(); +} + bool Element::IsFocusedElementInDocument() const { return this == GetDocument().FocusedElement(); }
diff --git a/third_party/blink/renderer/core/dom/element.h b/third_party/blink/renderer/core/dom/element.h index d14474df..fd76212 100644 --- a/third_party/blink/renderer/core/dom/element.h +++ b/third_party/blink/renderer/core/dom/element.h
@@ -1170,6 +1170,12 @@ // within a formatting context. void ForceLegacyLayoutInFormattingContext(const ComputedStyle& new_style); + // If this element requires legacy layout, and we're inside a fragmentation + // context, we need to force legacy layout for the entire fragmentation + // context. LayoutNG block fragmentation and legacy block fragmentation cannot + // cooperate within a fragmentation context. + void ForceLegacyLayoutInFragmentationContext(const ComputedStyle& new_style); + Member<ElementData> element_data_; };
diff --git a/third_party/blink/renderer/core/frame/location.cc b/third_party/blink/renderer/core/frame/location.cc index 2eb0735..06e790f 100644 --- a/third_party/blink/renderer/core/frame/location.cc +++ b/third_party/blink/renderer/core/frame/location.cc
@@ -201,10 +201,7 @@ if (hash[0] == '#') new_fragment_identifier = hash.Substring(1); url.SetFragmentIdentifier(new_fragment_identifier); - // Note that by parsing the URL and *then* comparing fragments, we are - // comparing fragments post-canonicalization, and so this handles the - // cases where fragment identifiers are ignored or invalid. - if (EqualIgnoringNullity(old_fragment_identifier, url.FragmentIdentifier())) + if (old_fragment_identifier == url.FragmentIdentifier()) return; SetLocation(url.GetString(), IncumbentDOMWindow(isolate), EnteredDOMWindow(isolate), &exception_state);
diff --git a/third_party/blink/renderer/core/inspector/browser_protocol.pdl b/third_party/blink/renderer/core/inspector/browser_protocol.pdl index 9fad4285..2675c6b 100644 --- a/third_party/blink/renderer/core/inspector/browser_protocol.pdl +++ b/third_party/blink/renderer/core/inspector/browser_protocol.pdl
@@ -6614,6 +6614,9 @@ # delivered via dataCollected events. event tracingComplete parameters + # Indicates whether some trace data is known to have been lost, e.g. because the trace ring + # buffer wrapped around. + boolean dataLossOccurred # A handle of the stream that holds resulting trace data. optional IO.StreamHandle stream # Trace data format of returned stream.
diff --git a/third_party/blink/renderer/core/inspector/inspector_dom_snapshot_agent.cc b/third_party/blink/renderer/core/inspector/inspector_dom_snapshot_agent.cc index eb6c249..a93cb08 100644 --- a/third_party/blink/renderer/core/inspector/inspector_dom_snapshot_agent.cc +++ b/third_party/blink/renderer/core/inspector/inspector_dom_snapshot_agent.cc
@@ -37,9 +37,8 @@ #include "third_party/blink/renderer/core/layout/layout_text.h" #include "third_party/blink/renderer/core/layout/layout_view.h" #include "third_party/blink/renderer/core/paint/paint_layer.h" +#include "third_party/blink/renderer/core/paint/paint_layer_paint_order_iterator.h" #include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h" -#include "third_party/blink/renderer/core/paint/paint_layer_stacking_node.h" -#include "third_party/blink/renderer/core/paint/paint_layer_stacking_node_iterator.h" #include "v8/include/v8-inspector.h" namespace blink { @@ -1059,12 +1058,9 @@ DCHECK(!embedded_document || !layer->FirstChild()); if (!embedded_document) { - if (PaintLayerStackingNode* node = layer->StackingNode()) { - PaintLayerStackingNodeIterator iterator(*node, kAllChildren); - while (PaintLayer* child_layer = iterator.Next()) { - VisitPaintLayer(child_layer); - } - } + PaintLayerPaintOrderIterator iterator(*layer, kAllChildren); + while (PaintLayer* child_layer = iterator.Next()) + VisitPaintLayer(child_layer); } }
diff --git a/third_party/blink/renderer/core/layout/layout_box.cc b/third_party/blink/renderer/core/layout/layout_box.cc index b1d20c0..edee4a8 100644 --- a/third_party/blink/renderer/core/layout/layout_box.cc +++ b/third_party/blink/renderer/core/layout/layout_box.cc
@@ -5716,7 +5716,8 @@ (Parent() && IsWritingModeRoot()) || (IsOutOfFlowPositioned() && StyleRef().GetPosition() == EPosition::kFixed) || - ShouldApplySizeContainment() || DisplayLockInducesSizeContainment()) + ShouldApplySizeContainment() || DisplayLockInducesSizeContainment() || + IsFrameSet()) return kForbidBreaks; EBreakInside break_value = BreakInside();
diff --git a/third_party/blink/renderer/core/layout/layout_image.cc b/third_party/blink/renderer/core/layout/layout_image.cc index 8e2bda7..988c24d4 100644 --- a/third_party/blink/renderer/core/layout/layout_image.cc +++ b/third_party/blink/renderer/core/layout/layout_image.cc
@@ -220,6 +220,8 @@ void LayoutImage::PaintReplaced(const PaintInfo& paint_info, const PhysicalOffset& paint_offset) const { + if (PaintBlockedByDisplayLock(DisplayLockContext::kChildren)) + return; ImagePainter(*this).PaintReplaced(paint_info, paint_offset); }
diff --git a/third_party/blink/renderer/core/layout/layout_tree_as_text.cc b/third_party/blink/renderer/core/layout/layout_tree_as_text.cc index ebc4716..ea3585eb 100644 --- a/third_party/blink/renderer/core/layout/layout_tree_as_text.cc +++ b/third_party/blink/renderer/core/layout/layout_tree_as_text.cc
@@ -60,6 +60,7 @@ #include "third_party/blink/renderer/core/page/print_context.h" #include "third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.h" #include "third_party/blink/renderer/core/paint/paint_layer.h" +#include "third_party/blink/renderer/core/paint/paint_layer_paint_order_iterator.h" #include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h" #include "third_party/blink/renderer/platform/geometry/layout_unit.h" #include "third_party/blink/renderer/platform/wtf/text/character_names.h" @@ -695,14 +696,12 @@ Write(ts, layer.GetLayoutObject(), indent + 1, behavior); } -static PaintLayerStackingNode::PaintLayers NormalFlowListFor( - PaintLayerStackingNode* node) { - PaintLayerStackingNode::PaintLayers vector; - if (node) { - PaintLayerStackingNodeIterator it(*node, kNormalFlowChildren); - while (PaintLayer* normal_flow_child = it.Next()) - vector.push_back(normal_flow_child); - } +static Vector<PaintLayer*> ChildLayers(const PaintLayer* layer, + PaintLayerIteration which_children) { + Vector<PaintLayer*> vector; + PaintLayerPaintOrderIterator it(*layer, which_children); + while (PaintLayer* child = it.Next()) + vector.push_back(child); return vector; } @@ -749,29 +748,23 @@ } #endif - bool paints_background_separately = false; - if (layer->StackingNode()) { - PaintLayerStackingNode::PaintLayers* neg_list = - layer->StackingNode()->NegZOrderList(); - paints_background_separately = neg_list && neg_list->size() > 0; - if (should_paint && paints_background_separately) { - Write(ts, *layer, layer_bounds, damage_rect.Rect(), - clip_rect_to_apply.Rect(), kLayerPaintPhaseBackground, indent, - behavior, marked_layer); - } + const auto& neg_list = ChildLayers(layer, kNegativeZOrderChildren); + bool paints_background_separately = !neg_list.IsEmpty(); + if (should_paint && paints_background_separately) { + Write(ts, *layer, layer_bounds, damage_rect.Rect(), + clip_rect_to_apply.Rect(), kLayerPaintPhaseBackground, indent, + behavior, marked_layer); + } - if (neg_list) { - int curr_indent = indent; - if (behavior & kLayoutAsTextShowLayerNesting) { - WriteIndent(ts, indent); - ts << " negative z-order list(" << neg_list->size() << ")\n"; - ++curr_indent; - } - for (unsigned i = 0; i != neg_list->size(); ++i) { - WriteLayers(ts, root_layer, neg_list->at(i), curr_indent, behavior, - marked_layer); - } + if (!neg_list.IsEmpty()) { + int curr_indent = indent; + if (behavior & kLayoutAsTextShowLayerNesting) { + WriteIndent(ts, indent); + ts << " negative z-order list(" << neg_list.size() << ")\n"; + ++curr_indent; } + for (auto* layer : neg_list) + WriteLayers(ts, root_layer, layer, curr_indent, behavior, marked_layer); } if (should_paint) { @@ -782,35 +775,28 @@ indent, behavior, marked_layer); } - if (layer->StackingNode()) { - PaintLayerStackingNode::PaintLayers normal_flow_list = - NormalFlowListFor(layer->StackingNode()); - if (!normal_flow_list.IsEmpty()) { - int curr_indent = indent; - if (behavior & kLayoutAsTextShowLayerNesting) { - WriteIndent(ts, indent); - ts << " normal flow list(" << normal_flow_list.size() << ")\n"; - ++curr_indent; - } - for (unsigned i = 0; i != normal_flow_list.size(); ++i) { - WriteLayers(ts, root_layer, normal_flow_list.at(i), curr_indent, - behavior, marked_layer); - } + const auto& normal_flow_list = ChildLayers(layer, kNormalFlowChildren); + if (!normal_flow_list.IsEmpty()) { + int curr_indent = indent; + if (behavior & kLayoutAsTextShowLayerNesting) { + WriteIndent(ts, indent); + ts << " normal flow list(" << normal_flow_list.size() << ")\n"; + ++curr_indent; } + for (auto* layer : normal_flow_list) + WriteLayers(ts, root_layer, layer, curr_indent, behavior, marked_layer); + } - if (PaintLayerStackingNode::PaintLayers* pos_list = - layer->StackingNode()->PosZOrderList()) { - int curr_indent = indent; - if (behavior & kLayoutAsTextShowLayerNesting) { - WriteIndent(ts, indent); - ts << " positive z-order list(" << pos_list->size() << ")\n"; - ++curr_indent; - } - for (unsigned i = 0; i != pos_list->size(); ++i) { - WriteLayers(ts, root_layer, pos_list->at(i), curr_indent, behavior, - marked_layer); - } + const auto& pos_list = ChildLayers(layer, kPositiveZOrderChildren); + if (!pos_list.IsEmpty()) { + int curr_indent = indent; + if (behavior & kLayoutAsTextShowLayerNesting) { + WriteIndent(ts, indent); + ts << " positive z-order list(" << pos_list.size() << ")\n"; + ++curr_indent; } + for (auto* layer : pos_list) + WriteLayers(ts, root_layer, layer, curr_indent, behavior, marked_layer); } }
diff --git a/third_party/blink/renderer/core/layout/ng/ng_block_node.cc b/third_party/blink/renderer/core/layout/ng/ng_block_node.cc index 66455df9..80313e52 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_block_node.cc +++ b/third_party/blink/renderer/core/layout/ng/ng_block_node.cc
@@ -949,6 +949,12 @@ DCHECK(!box_->IsLayoutBlock() || To<LayoutBlock>(box_)->CreatesNewFormattingContext()); + // We cannot enter legacy layout for something fragmentable if we're inside an + // NG block fragmentation context. LayoutNG and legacy block fragmentation + // cannot cooperate within the same fragmentation context. + DCHECK(!constraint_space.HasBlockFragmentation() || + box_->GetPaginationBreakability() == LayoutBox::kForbidBreaks); + scoped_refptr<const NGLayoutResult> layout_result = box_->GetCachedLayoutResult();
diff --git a/third_party/blink/renderer/core/layout/paint_containment_test.cc b/third_party/blink/renderer/core/layout/paint_containment_test.cc index 3b3ba26e..3e088f1 100644 --- a/third_party/blink/renderer/core/layout/paint_containment_test.cc +++ b/third_party/blink/renderer/core/layout/paint_containment_test.cc
@@ -28,8 +28,7 @@ // clipping and stacking performed by paint containment. DCHECK(obj.Layer()); PaintLayer* layer = obj.Layer(); - EXPECT_TRUE(layer->StackingNode() && - layer->GetLayoutObject().StyleRef().IsStackingContext()); + EXPECT_TRUE(layer->GetLayoutObject().StyleRef().IsStackingContext()); } TEST_F(PaintContainmentTest, BlockPaintContainment) {
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_root.cc b/third_party/blink/renderer/core/layout/svg/layout_svg_root.cc index 65ac466..a3152eb7 100644 --- a/third_party/blink/renderer/core/layout/svg/layout_svg_root.cc +++ b/third_party/blink/renderer/core/layout/svg/layout_svg_root.cc
@@ -264,6 +264,8 @@ void LayoutSVGRoot::PaintReplaced(const PaintInfo& paint_info, const PhysicalOffset& paint_offset) const { + if (PaintBlockedByDisplayLock(DisplayLockContext::kChildren)) + return; SVGRootPainter(*this).PaintReplaced(paint_info, paint_offset); }
diff --git a/third_party/blink/renderer/core/mojo/DEPS b/third_party/blink/renderer/core/mojo/DEPS index a3ad469..a3bebdc 100644 --- a/third_party/blink/renderer/core/mojo/DEPS +++ b/third_party/blink/renderer/core/mojo/DEPS
@@ -1,3 +1,5 @@ include_rules = [ - "+mojo/public/cpp/system", + "+base/numerics/safe_math.h", + + "+mojo/public", ]
diff --git a/third_party/blink/renderer/core/mojo/mojo_handle.cc b/third_party/blink/renderer/core/mojo/mojo_handle.cc index b74bf25..2951ad1 100644 --- a/third_party/blink/renderer/core/mojo/mojo_handle.cc +++ b/third_party/blink/renderer/core/mojo/mojo_handle.cc
@@ -4,6 +4,9 @@ #include "third_party/blink/renderer/core/mojo/mojo_handle.h" +#include "base/numerics/safe_math.h" +#include "mojo/public/c/system/message_pipe.h" +#include "mojo/public/cpp/bindings/message.h" #include "mojo/public/cpp/system/message_pipe.h" #include "third_party/blink/renderer/bindings/core/v8/array_buffer_or_array_buffer_view.h" #include "third_party/blink/renderer/core/execution_context/execution_context.h" @@ -50,11 +53,10 @@ MojoResult MojoHandle::writeMessage( ArrayBufferOrArrayBufferView& buffer, const HeapVector<Member<MojoHandle>>& handles) { - // mojo::WriteMessageRaw takes ownership of the handles, so release them here. - Vector<::MojoHandle, kHandleVectorInlineCapacity> raw_handles(handles.size()); - std::transform( - handles.begin(), handles.end(), raw_handles.begin(), - [](MojoHandle* handle) { return handle->handle_.release().value(); }); + Vector<mojo::ScopedHandle, kHandleVectorInlineCapacity> scoped_handles( + handles.size()); + std::transform(handles.begin(), handles.end(), scoped_handles.begin(), + [](MojoHandle* handle) { return std::move(handle->handle_); }); const void* bytes = nullptr; size_t num_bytes = 0; @@ -68,9 +70,13 @@ num_bytes = view->byteLength(); } - return mojo::WriteMessageRaw( - mojo::MessagePipeHandle(handle_.get().value()), bytes, num_bytes, - raw_handles.data(), raw_handles.size(), MOJO_WRITE_MESSAGE_FLAG_NONE); + auto message = mojo::Message( + base::make_span(static_cast<const uint8_t*>(bytes), num_bytes), + base::make_span(scoped_handles)); + DCHECK(!message.IsNull()); + return mojo::WriteMessageNew(mojo::MessagePipeHandle(handle_.get().value()), + message.TakeMojoMessage(), + MOJO_WRITE_MESSAGE_FLAG_NONE); } MojoReadMessageResult* MojoHandle::readMessage(
diff --git a/third_party/blink/renderer/core/paint/BUILD.gn b/third_party/blink/renderer/core/paint/BUILD.gn index ae24cb6..65a4f8c 100644 --- a/third_party/blink/renderer/core/paint/BUILD.gn +++ b/third_party/blink/renderer/core/paint/BUILD.gn
@@ -157,6 +157,8 @@ "paint_layer_clipper.cc", "paint_layer_clipper.h", "paint_layer_fragment.h", + "paint_layer_paint_order_iterator.cc", + "paint_layer_paint_order_iterator.h", "paint_layer_painter.cc", "paint_layer_painter.h", "paint_layer_painting_info.h", @@ -166,8 +168,6 @@ "paint_layer_scrollable_area.h", "paint_layer_stacking_node.cc", "paint_layer_stacking_node.h", - "paint_layer_stacking_node_iterator.cc", - "paint_layer_stacking_node_iterator.h", "paint_phase.cc", "paint_phase.h", "paint_property_tree_builder.cc",
diff --git a/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.cc b/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.cc index 00050711..d9796621 100644 --- a/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.cc +++ b/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.cc
@@ -65,9 +65,9 @@ #include "third_party/blink/renderer/core/paint/frame_paint_timing.h" #include "third_party/blink/renderer/core/paint/object_paint_invalidator.h" #include "third_party/blink/renderer/core/paint/paint_info.h" +#include "third_party/blink/renderer/core/paint/paint_layer_paint_order_iterator.h" #include "third_party/blink/renderer/core/paint/paint_layer_painter.h" #include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h" -#include "third_party/blink/renderer/core/paint/paint_layer_stacking_node_iterator.h" #include "third_party/blink/renderer/core/paint/scrollable_area_painter.h" #include "third_party/blink/renderer/core/probe/core_probes.h" #include "third_party/blink/renderer/platform/fonts/font_cache.h" @@ -402,8 +402,7 @@ bool isolate = owning_layer_.ShouldIsolateCompositedDescendants(); // non stacking context layers should never isolate - DCHECK((owning_layer_.StackingNode() && - owning_layer_.GetLayoutObject().StyleRef().IsStackingContext()) || + DCHECK(owning_layer_.GetLayoutObject().StyleRef().IsStackingContext() || !isolate); graphics_layer_->SetIsRootForIsolatedGroup(isolate); @@ -2774,16 +2773,8 @@ if (!parent->HasVisibleDescendant()) return false; - if (!parent->StackingNode()) - return false; - -#if DCHECK_IS_ON() - LayerListMutationDetector mutation_checker(parent->StackingNode()); -#endif - - PaintLayerStackingNodeIterator normal_flow_iterator(*parent->StackingNode(), - kAllChildren); - while (PaintLayer* child_layer = normal_flow_iterator.Next()) { + PaintLayerPaintOrderIterator iterator(*parent, kAllChildren); + while (PaintLayer* child_layer = iterator.Next()) { if (child_layer->HasCompositedLayerMapping()) continue; if (child_layer->HasVisibleContent() ||
diff --git a/third_party/blink/renderer/core/paint/compositing/compositing_layer_assigner.cc b/third_party/blink/renderer/core/paint/compositing/compositing_layer_assigner.cc index 0714fb3..f5379aa 100644 --- a/third_party/blink/renderer/core/paint/compositing/compositing_layer_assigner.cc +++ b/third_party/blink/renderer/core/paint/compositing/compositing_layer_assigner.cc
@@ -32,6 +32,7 @@ #include "third_party/blink/renderer/core/page/page.h" #include "third_party/blink/renderer/core/page/scrolling/scrolling_coordinator.h" #include "third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.h" +#include "third_party/blink/renderer/core/paint/paint_layer_paint_order_iterator.h" #include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h" namespace blink { @@ -339,10 +340,8 @@ } } - if (layer->StackingDescendantNeedsCompositingLayerAssignment() && - layer->GetLayoutObject().StyleRef().IsStackingContext()) { - PaintLayerStackingNodeIterator iterator(*layer->StackingNode(), - kNegativeZOrderChildren); + if (layer->StackingDescendantNeedsCompositingLayerAssignment()) { + PaintLayerPaintOrderIterator iterator(*layer, kNegativeZOrderChildren); while (PaintLayer* child_node = iterator.Next()) { AssignLayersToBackingsInternal(child_node, squashing_state, layers_needing_paint_invalidation); @@ -359,10 +358,9 @@ layers_needing_paint_invalidation); } - if (layer->StackingNode() && - layer->StackingDescendantNeedsCompositingLayerAssignment()) { - PaintLayerStackingNodeIterator iterator( - *layer->StackingNode(), kNormalFlowChildren | kPositiveZOrderChildren); + if (layer->StackingDescendantNeedsCompositingLayerAssignment()) { + PaintLayerPaintOrderIterator iterator(*layer, + kNormalFlowAndPositiveZOrderChildren); while (PaintLayer* curr_layer = iterator.Next()) { AssignLayersToBackingsInternal(curr_layer, squashing_state, layers_needing_paint_invalidation);
diff --git a/third_party/blink/renderer/core/paint/compositing/compositing_requirements_updater.cc b/third_party/blink/renderer/core/paint/compositing/compositing_requirements_updater.cc index aa4e40db..b3ae108 100644 --- a/third_party/blink/renderer/core/paint/compositing/compositing_requirements_updater.cc +++ b/third_party/blink/renderer/core/paint/compositing/compositing_requirements_updater.cc
@@ -31,9 +31,8 @@ #include "third_party/blink/renderer/core/layout/layout_view.h" #include "third_party/blink/renderer/core/paint/compositing/paint_layer_compositor.h" #include "third_party/blink/renderer/core/paint/paint_layer.h" +#include "third_party/blink/renderer/core/paint/paint_layer_paint_order_iterator.h" #include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h" -#include "third_party/blink/renderer/core/paint/paint_layer_stacking_node.h" -#include "third_party/blink/renderer/core/paint/paint_layer_stacking_node_iterator.h" #include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h" namespace blink { @@ -232,11 +231,7 @@ #if DCHECK_IS_ON() static void CheckSubtreeHasNoCompositing(PaintLayer* layer) { - if (!layer->StackingNode()) - return; - PaintLayerStackingNodeIterator iterator( - *layer->StackingNode(), - kNegativeZOrderChildren | kNormalFlowChildren | kPositiveZOrderChildren); + PaintLayerPaintOrderIterator iterator(*layer, kAllChildren); while (PaintLayer* cur_layer = iterator.Next()) { DCHECK(cur_layer->GetCompositingState() == kNotComposited); DCHECK(!cur_layer->DirectCompositingReasons() || @@ -394,9 +389,7 @@ } #if DCHECK_IS_ON() - base::Optional<LayerListMutationDetector> mutation_checker; - if (layer->StackingNode()) - mutation_checker.emplace(layer->StackingNode()); + PaintLayerListMutationDetector mutation_checker(*layer); #endif bool any_descendant_has3d_transform = false; @@ -426,10 +419,8 @@ !layer->HasCompositingDescendant() && !layer->DescendantMayNeedCompositingRequirementsUpdate(); - if (!skip_children && - layer->GetLayoutObject().StyleRef().IsStackingContext()) { - PaintLayerStackingNodeIterator iterator(*layer->StackingNode(), - kNegativeZOrderChildren); + if (!skip_children) { + PaintLayerPaintOrderIterator iterator(*layer, kNegativeZOrderChildren); while (PaintLayer* child_layer = iterator.Next()) { IntRect absolute_child_descendant_bounding_box; UpdateRecursive(layer, child_layer, overlap_map, child_recursion_data, @@ -478,9 +469,9 @@ child_recursion_data.testing_overlap_ = true; } - if (!skip_children && layer->StackingNode()) { - PaintLayerStackingNodeIterator iterator( - *layer->StackingNode(), kNormalFlowChildren | kPositiveZOrderChildren); + if (!skip_children) { + PaintLayerPaintOrderIterator iterator(*layer, + kNormalFlowAndPositiveZOrderChildren); while (PaintLayer* child_layer = iterator.Next()) { IntRect absolute_child_descendant_bounding_box; UpdateRecursive(layer, child_layer, overlap_map, child_recursion_data,
diff --git a/third_party/blink/renderer/core/paint/compositing/graphics_layer_tree_builder.cc b/third_party/blink/renderer/core/paint/compositing/graphics_layer_tree_builder.cc index 2c797e0..d27f2aa 100644 --- a/third_party/blink/renderer/core/paint/compositing/graphics_layer_tree_builder.cc +++ b/third_party/blink/renderer/core/paint/compositing/graphics_layer_tree_builder.cc
@@ -32,6 +32,7 @@ #include "third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.h" #include "third_party/blink/renderer/core/paint/compositing/paint_layer_compositor.h" #include "third_party/blink/renderer/core/paint/paint_layer.h" +#include "third_party/blink/renderer/core/paint/paint_layer_paint_order_iterator.h" namespace blink { @@ -85,14 +86,11 @@ : &pending_reparents; #if DCHECK_IS_ON() - base::Optional<LayerListMutationDetector> mutation_checker; - if (layer.StackingNode()) - mutation_checker.emplace(layer.StackingNode()); + PaintLayerListMutationDetector mutation_checker(layer); #endif - if (style.IsStackingContext()) { - PaintLayerStackingNodeIterator iterator(*layer.StackingNode(), - kNegativeZOrderChildren); + if (layer.IsStackingContextWithNegativeZOrderChildren()) { + PaintLayerPaintOrderIterator iterator(layer, kNegativeZOrderChildren); while (PaintLayer* child_layer = iterator.Next()) { RebuildRecursive(*child_layer, *layer_vector_for_children, *pending_reparents_for_children); @@ -107,9 +105,9 @@ } } - if (layer.StackingNode()) { - PaintLayerStackingNodeIterator iterator( - *layer.StackingNode(), kNormalFlowChildren | kPositiveZOrderChildren); + { + PaintLayerPaintOrderIterator iterator(layer, + kNormalFlowAndPositiveZOrderChildren); while (PaintLayer* child_layer = iterator.Next()) { RebuildRecursive(*child_layer, *layer_vector_for_children, *pending_reparents_for_children);
diff --git a/third_party/blink/renderer/core/paint/compositing/paint_layer_compositor.cc b/third_party/blink/renderer/core/paint/compositing/paint_layer_compositor.cc index c5ced0c8..c6d3d0b 100644 --- a/third_party/blink/renderer/core/paint/compositing/paint_layer_compositor.cc +++ b/third_party/blink/renderer/core/paint/compositing/paint_layer_compositor.cc
@@ -839,8 +839,7 @@ const PaintLayer* layer) const { if (!layer->HasCompositingDescendant()) return false; - return layer->StackingNode() && - layer->StackingNode()->HasNegativeZOrderList(); + return layer->IsStackingContextWithNegativeZOrderChildren(); } static void UpdateTrackingRasterInvalidationsRecursive(
diff --git a/third_party/blink/renderer/core/paint/paint_layer.cc b/third_party/blink/renderer/core/paint/paint_layer.cc index ef0a0be..e73a815 100644 --- a/third_party/blink/renderer/core/paint/paint_layer.cc +++ b/third_party/blink/renderer/core/paint/paint_layer.cc
@@ -77,6 +77,7 @@ #include "third_party/blink/renderer/core/paint/filter_effect_builder.h" #include "third_party/blink/renderer/core/paint/object_paint_invalidator.h" #include "third_party/blink/renderer/core/paint/paint_info.h" +#include "third_party/blink/renderer/core/paint/paint_layer_paint_order_iterator.h" #include "third_party/blink/renderer/core/paint/paint_layer_painter.h" #include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h" #include "third_party/blink/renderer/core/style/reference_clip_path_operation.h" @@ -164,6 +165,7 @@ has_fixed_position_descendant_(false), has_sticky_position_descendant_(false), has_non_contained_absolute_position_descendant_(false), + has_stacked_descendant_in_current_stacking_context_(false), self_painting_status_changed_(false), filter_on_effect_node_dirty_(false), backdrop_filter_on_effect_node_dirty_(false), @@ -176,6 +178,9 @@ descendant_needs_compositing_layer_assignment_(false), has_self_painting_layer_descendant_(false), is_non_stacked_with_in_flow_stacked_descendant_(false), +#if DCHECK_IS_ON() + layer_list_mutation_allowed_(true), +#endif layout_object_(layout_object), parent_(nullptr), previous_(nullptr), @@ -655,6 +660,7 @@ has_fixed_position_descendant_ = false; has_sticky_position_descendant_ = false; has_non_contained_absolute_position_descendant_ = false; + has_stacked_descendant_in_current_stacking_context_ = false; has_self_painting_layer_descendant_ = false; is_non_stacked_with_in_flow_stacked_descendant_ = false; @@ -662,7 +668,6 @@ GetLayoutObject().CanContainAbsolutePositionObjects(); const ComputedStyle& style = GetLayoutObject().StyleRef(); - bool needs_stacking_node = style.IsStackingContext(); bool is_stacked = style.IsStacked(); for (PaintLayer* child = FirstChild(); child; @@ -675,9 +680,9 @@ has_visible_descendant_ = true; has_non_isolated_descendant_with_blend_mode_ |= - (!child->GetLayoutObject().StyleRef().IsStackingContext() && + (!child_style.IsStackingContext() && child->HasNonIsolatedDescendantWithBlendMode()) || - child->GetLayoutObject().StyleRef().HasBlendMode(); + child_style.HasBlendMode(); has_descendant_with_clip_path_ |= child->HasDescendantWithClipPath() || child->GetLayoutObject().HasClipPath(); @@ -695,7 +700,14 @@ child_style.GetPosition() == EPosition::kAbsolute); } - needs_stacking_node = needs_stacking_node || !child_style.IsStacked(); + if (!has_stacked_descendant_in_current_stacking_context_) { + if (child_style.IsStacked()) { + has_stacked_descendant_in_current_stacking_context_ = true; + } else if (!child_style.IsStackingContext()) { + has_stacked_descendant_in_current_stacking_context_ = + child->has_stacked_descendant_in_current_stacking_context_; + } + } has_self_painting_layer_descendant_ = has_self_painting_layer_descendant_ || @@ -711,7 +723,7 @@ } } - UpdateStackingNode(needs_stacking_node); + UpdateStackingNode(); if (old_has_non_isolated_descendant_with_blend_mode != static_cast<bool>(has_non_isolated_descendant_with_blend_mode_)) @@ -775,13 +787,9 @@ void PaintLayer::Update3DTransformedDescendantStatus() { has3d_transformed_descendant_ = false; - if (!stacking_node_) - return; - // Transformed or preserve-3d descendants can only be in the z-order lists, // not in the normal flow list, so we only need to check those. - PaintLayerStackingNodeIterator iterator( - *stacking_node_.get(), kPositiveZOrderChildren | kNegativeZOrderChildren); + PaintLayerPaintOrderIterator iterator(*this, kStackedChildren); while (PaintLayer* child_layer = iterator.Next()) { bool child_has3d = false; // If the child lives in a 3d hierarchy, then the layer at the root of @@ -988,9 +996,15 @@ return Parent(); if (!GetLayoutObject().StyleRef().IsStacked()) return IsSelfPaintingLayer() ? Parent() : ContainingLayer(); - if (PaintLayerStackingNode* ancestor_stacking_node = - PaintLayerStackingNode::AncestorStackingContextNode(this)) - return ancestor_stacking_node->Layer(); + return AncestorStackingContext(); +} + +PaintLayer* PaintLayer::AncestorStackingContext() const { + for (PaintLayer* ancestor = Parent(); ancestor; + ancestor = ancestor->Parent()) { + if (ancestor->GetLayoutObject().StyleRef().IsStackingContext()) + return ancestor; + } return nullptr; } @@ -1313,12 +1327,16 @@ } void PaintLayer::AddChild(PaintLayer* child, PaintLayer* before_child) { +#if DCHECK_IS_ON() + DCHECK(layer_list_mutation_allowed_); +#endif + PaintLayer* prev_sibling = before_child ? before_child->PreviousSibling() : LastChild(); if (prev_sibling) { child->SetPreviousSibling(prev_sibling); prev_sibling->SetNextSibling(child); - DCHECK(prev_sibling != child); + DCHECK_NE(prev_sibling, child); } else { SetFirstChild(child); } @@ -1326,7 +1344,7 @@ if (before_child) { before_child->SetPreviousSibling(child); child->SetNextSibling(before_child); - DCHECK(before_child != child); + DCHECK_NE(before_child, child); } else { SetLastChild(child); } @@ -1351,7 +1369,7 @@ // ancestorStackingContextNode() can be null in the case where we're // building up generated content layers. This is ok, since the lists will // start off dirty in that case anyway. - PaintLayerStackingNode::DirtyStackingContextZOrderLists(child); + PaintLayerStackingNode::DirtyStackingContextZOrderLists(*child); MarkAncestorChainForFlagsUpdate(); } @@ -1368,7 +1386,11 @@ child->SetNeedsRepaint(); } -PaintLayer* PaintLayer::RemoveChild(PaintLayer* old_child) { +void PaintLayer::RemoveChild(PaintLayer* old_child) { +#if DCHECK_IS_ON() + DCHECK(layer_list_mutation_allowed_); +#endif + old_child->MarkCompositingContainerChainForNeedsRepaint(); if (old_child->PreviousSibling()) @@ -1390,7 +1412,7 @@ Compositor()->SetNeedsCompositingUpdate(kCompositingUpdateRebuildTree); } // Dirty the z-order list in which we are contained. - PaintLayerStackingNode::DirtyStackingContextZOrderLists(old_child); + PaintLayerStackingNode::DirtyStackingContextZOrderLists(*old_child); SetNeedsCompositingInputsUpdate(); } @@ -1410,8 +1432,6 @@ if (old_child->EnclosingPaginationLayer()) old_child->ClearPaginationRecursive(); - - return old_child; } void PaintLayer::ClearClipRects(ClipRectsCacheSlot cache_slot) { @@ -1425,7 +1445,7 @@ return; if (old_style && old_style->IsStacked()) { - PaintLayerStackingNode::DirtyStackingContextZOrderLists(this); + PaintLayerStackingNode::DirtyStackingContextZOrderLists(*this); MarkAncestorChainForFlagsUpdate(); } @@ -1619,10 +1639,18 @@ UpdateSelfPaintingLayer(); } -void PaintLayer::UpdateStackingNode(bool needs_stacking_node) { +void PaintLayer::UpdateStackingNode() { +#if DCHECK_IS_ON() + DCHECK(layer_list_mutation_allowed_); +#endif + + bool needs_stacking_node = + has_stacked_descendant_in_current_stacking_context_ && + GetLayoutObject().StyleRef().IsStackingContext(); + if (needs_stacking_node != !!stacking_node_) { if (needs_stacking_node) - stacking_node_ = std::make_unique<PaintLayerStackingNode>(this); + stacking_node_ = std::make_unique<PaintLayerStackingNode>(*this); else stacking_node_ = nullptr; } @@ -2390,7 +2418,7 @@ } PaintLayer* PaintLayer::HitTestChildren( - ChildrenIteration childrento_visit, + PaintLayerIteration children_to_visit, PaintLayer* root_layer, HitTestResult& result, const HitTestRecursionData& recursion_data, @@ -2402,9 +2430,6 @@ if (!HasSelfPaintingLayerDescendant()) return nullptr; - if (!stacking_node_) - return nullptr; - if (GetLayoutObject().PaintBlockedByDisplayLock( DisplayLockContext::kChildren)) return nullptr; @@ -2413,8 +2438,7 @@ PaintLayer* stop_layer = stop_node ? stop_node->PaintingLayer() : nullptr; PaintLayer* result_layer = nullptr; - PaintLayerStackingNodeReverseIterator iterator(*stacking_node_, - childrento_visit); + PaintLayerPaintOrderReverseIterator iterator(*this, children_to_visit); while (PaintLayer* child_layer = iterator.Next()) { if (child_layer->IsReplacedNormalFlowStacking()) continue; @@ -2637,18 +2661,7 @@ const PaintLayer& composited_layer, PhysicalRect& result, PaintLayer::CalculateBoundsOptions options) const { - if (!StackingNode()) - return; - - DCHECK(GetLayoutObject().StyleRef().IsStackingContext() || - !StackingNode()->HasPositiveZOrderList()); - -#if DCHECK_IS_ON() - LayerListMutationDetector mutation_checker( - const_cast<PaintLayer*>(this)->StackingNode()); -#endif - - PaintLayerStackingNodeIterator iterator(*StackingNode(), kAllChildren); + PaintLayerPaintOrderIterator iterator(*this, kAllChildren); while (PaintLayer* child_layer = iterator.Next()) { // Here we exclude both directly composited layers and squashing layers // because those Layers don't paint into the graphics layer @@ -2965,12 +2978,7 @@ bool PaintLayer::ChildBackgroundIsKnownToBeOpaqueInRect( const PhysicalRect& local_rect) const { - if (!stacking_node_) - return false; - - PaintLayerStackingNodeReverseIterator reverse_iterator( - *stacking_node_, - kPositiveZOrderChildren | kNormalFlowChildren | kNegativeZOrderChildren); + PaintLayerPaintOrderReverseIterator reverse_iterator(*this, kAllChildren); while (PaintLayer* child_layer = reverse_iterator.Next()) { // Stop at composited paint boundaries and non-self-painting layers. if (child_layer->IsPaintInvalidationContainer()) @@ -3191,7 +3199,7 @@ return; } - if (PaintLayerStackingNode::StyleDidChange(this, old_style)) + if (PaintLayerStackingNode::StyleDidChange(*this, old_style)) MarkAncestorChainForFlagsUpdate(); if (RequiresScrollableArea()) {
diff --git a/third_party/blink/renderer/core/paint/paint_layer.h b/third_party/blink/renderer/core/paint/paint_layer.h index 3f01ce60..36921b3 100644 --- a/third_party/blink/renderer/core/paint/paint_layer.h +++ b/third_party/blink/renderer/core/paint/paint_layer.h
@@ -56,7 +56,6 @@ #include "third_party/blink/renderer/core/paint/paint_layer_fragment.h" #include "third_party/blink/renderer/core/paint/paint_layer_resource_info.h" #include "third_party/blink/renderer/core/paint/paint_layer_stacking_node.h" -#include "third_party/blink/renderer/core/paint/paint_layer_stacking_node_iterator.h" #include "third_party/blink/renderer/core/paint/paint_result.h" #include "third_party/blink/renderer/platform/graphics/compositing_reasons.h" #include "third_party/blink/renderer/platform/graphics/paint/cull_rect.h" @@ -87,6 +86,23 @@ kCompositingQueriesAreOnlyAllowedInCertainDocumentLifecyclePhases }; +// Used in PaintLayerPaintOrderIterator. +enum PaintLayerIteration { + kNegativeZOrderChildren = 1, + // Normal flow children are not mandated by CSS 2.1 but are an artifact of + // our implementation: we allocate PaintLayers for elements that + // are not treated as stacking contexts and thus we need to walk them + // during painting and hit-testing. + kNormalFlowChildren = 1 << 1, + kPositiveZOrderChildren = 1 << 2, + + kStackedChildren = kNegativeZOrderChildren | kPositiveZOrderChildren, + kNormalFlowAndPositiveZOrderChildren = + kNormalFlowChildren | kPositiveZOrderChildren, + kAllChildren = + kNegativeZOrderChildren | kNormalFlowChildren | kPositiveZOrderChildren +}; + // FIXME: remove this once the compositing query DCHECKS are no longer hit. class CORE_EXPORT DisableCompositingQueryAsserts { STACK_ALLOCATED(); @@ -250,9 +266,10 @@ // good but we can't use it for now because it conflicts with // PaintInfo::paintContainer. PaintLayer* CompositingContainer() const; + PaintLayer* AncestorStackingContext() const; void AddChild(PaintLayer* new_child, PaintLayer* before_child = nullptr); - PaintLayer* RemoveChild(PaintLayer*); + void RemoveChild(PaintLayer*); void ClearClipRects(ClipRectsCacheSlot = kNumberOfClipRectsCacheSlots); @@ -329,9 +346,9 @@ : PhysicalOffset(); } - PaintLayerStackingNode* StackingNode() { return stacking_node_.get(); } - const PaintLayerStackingNode* StackingNode() const { - return stacking_node_.get(); + bool IsStackingContextWithNegativeZOrderChildren() const { + DCHECK(!stacking_node_ || GetLayoutObject().StyleRef().IsStackingContext()); + return stacking_node_ && !stacking_node_->NegZOrderList().IsEmpty(); } bool SubtreeIsInvisible() const { @@ -1086,6 +1103,7 @@ } PaintLayerStackingNode* StackingParent() { return stacking_parent_; } bool IsInStackingParentZOrderLists() const; + bool LayerListMutationAllowed() const { return layer_list_mutation_allowed_; } #endif void SetNeedsCompositingLayerAssignment(); @@ -1146,7 +1164,7 @@ double* z_offset = nullptr, const PhysicalOffset& translation_offset = PhysicalOffset()); PaintLayer* HitTestChildren( - ChildrenIteration, + PaintLayerIteration, PaintLayer* root_layer, HitTestResult&, const HitTestRecursionData& recursion_data, @@ -1187,7 +1205,7 @@ bool ShouldBeSelfPaintingLayer() const; - void UpdateStackingNode(bool needs_stacking_node); + void UpdateStackingNode(); FilterOperations FilterOperationsIncludingReflection() const; @@ -1259,6 +1277,10 @@ return *ancestor_dependent_compositing_inputs_; } + // This is private because PaintLayerStackingNode is only for PaintLayer and + // PaintLayerPaintOrderIterator. + PaintLayerStackingNode* StackingNode() const { return stacking_node_.get(); } + // Self-painting layer is an optimization where we avoid the heavy Layer // painting machinery for a Layer allocated only to handle the overflow clip // case. @@ -1316,6 +1338,7 @@ unsigned has_fixed_position_descendant_ : 1; unsigned has_sticky_position_descendant_ : 1; unsigned has_non_contained_absolute_position_descendant_ : 1; + unsigned has_stacked_descendant_in_current_stacking_context_ : 1; unsigned self_painting_status_changed_ : 1; @@ -1340,6 +1363,10 @@ unsigned has_self_painting_layer_descendant_ : 1; unsigned is_non_stacked_with_in_flow_stacked_descendant_ : 1; +#if DCHECK_IS_ON() + mutable unsigned layer_list_mutation_allowed_ : 1; +#endif + LayoutBoxModelObject& layout_object_; PaintLayer* parent_; @@ -1382,6 +1409,14 @@ PaintLayerStackingNode* stacking_parent_; #endif + // For layer_list_mutation_allowed_. + friend class PaintLayerListMutationDetector; + + // For stacking_node_ to avoid exposing it publicly. + friend class PaintLayerPaintOrderIterator; + friend class PaintLayerPaintOrderReverseIterator; + friend class PaintLayerStackingNode; + FRIEND_TEST_ALL_PREFIXES(PaintLayerTest, DescendantDependentFlagsStopsAtThrottledFrames); FRIEND_TEST_ALL_PREFIXES(PaintLayerTest, @@ -1390,6 +1425,27 @@ DISALLOW_COPY_AND_ASSIGN(PaintLayer); }; +#if DCHECK_IS_ON() +class PaintLayerListMutationDetector { + STACK_ALLOCATED(); + + public: + explicit PaintLayerListMutationDetector(const PaintLayer& layer) + : layer_(layer), + previous_mutation_allowed_state_(layer.layer_list_mutation_allowed_) { + layer.layer_list_mutation_allowed_ = false; + } + + ~PaintLayerListMutationDetector() { + layer_.layer_list_mutation_allowed_ = previous_mutation_allowed_state_; + } + + private: + const PaintLayer& layer_; + bool previous_mutation_allowed_state_; +}; +#endif + } // namespace blink #if DCHECK_IS_ON()
diff --git a/third_party/blink/renderer/core/paint/paint_layer_paint_order_iterator.cc b/third_party/blink/renderer/core/paint/paint_layer_paint_order_iterator.cc new file mode 100644 index 0000000..0456b7a --- /dev/null +++ b/third_party/blink/renderer/core/paint/paint_layer_paint_order_iterator.cc
@@ -0,0 +1,159 @@ +/* + * Copyright (C) 2013 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "third_party/blink/renderer/core/paint/paint_layer_paint_order_iterator.h" + +#include "third_party/blink/renderer/core/paint/paint_layer.h" +#include "third_party/blink/renderer/core/paint/paint_layer_stacking_node.h" + +namespace blink { + +PaintLayer* PaintLayerPaintOrderIterator::Next() { + if (remaining_children_ & kNegativeZOrderChildren) { + if (root_.StackingNode()) { + const auto& neg_z_order_list = root_.StackingNode()->NegZOrderList(); + if (index_ < neg_z_order_list.size()) + return neg_z_order_list[index_++]; + } + + index_ = 0; + remaining_children_ &= ~kNegativeZOrderChildren; + } + + if (remaining_children_ & kNormalFlowChildren) { + for (; current_normal_flow_child_; + current_normal_flow_child_ = + current_normal_flow_child_->NextSibling()) { + if (current_normal_flow_child_->GetLayoutObject().StyleRef().IsStacked()) + continue; + + PaintLayer* normal_flow_child = current_normal_flow_child_; + current_normal_flow_child_ = current_normal_flow_child_->NextSibling(); + return normal_flow_child; + } + + // We reset the iterator in case we reuse it. + current_normal_flow_child_ = root_.FirstChild(); + remaining_children_ &= ~kNormalFlowChildren; + } + + if (remaining_children_ & kPositiveZOrderChildren) { + if (root_.StackingNode()) { + const auto& pos_z_order_list = root_.StackingNode()->PosZOrderList(); + if (index_ < pos_z_order_list.size()) + return pos_z_order_list[index_++]; + } + + index_ = 0; + remaining_children_ &= ~kPositiveZOrderChildren; + } + + return nullptr; +} + +PaintLayer* PaintLayerPaintOrderReverseIterator::Next() { + if (remaining_children_ & kNegativeZOrderChildren) { + if (root_.StackingNode()) { + const auto& neg_z_order_list = root_.StackingNode()->NegZOrderList(); + if (index_ >= 0) + return neg_z_order_list[index_--]; + } + + remaining_children_ &= ~kNegativeZOrderChildren; + SetIndexToLastItem(); + } + + if (remaining_children_ & kNormalFlowChildren) { + for (; current_normal_flow_child_; + current_normal_flow_child_ = + current_normal_flow_child_->PreviousSibling()) { + if (current_normal_flow_child_->GetLayoutObject().StyleRef().IsStacked()) + continue; + + PaintLayer* normal_flow_child = current_normal_flow_child_; + current_normal_flow_child_ = + current_normal_flow_child_->PreviousSibling(); + return normal_flow_child; + } + + remaining_children_ &= ~kNormalFlowChildren; + SetIndexToLastItem(); + } + + if (remaining_children_ & kPositiveZOrderChildren) { + if (root_.StackingNode()) { + const auto& pos_z_order_list = root_.StackingNode()->PosZOrderList(); + if (index_ >= 0) + return pos_z_order_list[index_--]; + } + + remaining_children_ &= ~kPositiveZOrderChildren; + SetIndexToLastItem(); + } + + return nullptr; +} + +void PaintLayerPaintOrderReverseIterator::SetIndexToLastItem() { + if (remaining_children_ & kNegativeZOrderChildren) { + if (root_.StackingNode()) { + const auto& neg_z_order_list = root_.StackingNode()->NegZOrderList(); + if (!neg_z_order_list.IsEmpty()) { + index_ = neg_z_order_list.size() - 1; + return; + } + } + + remaining_children_ &= ~kNegativeZOrderChildren; + } + + if (remaining_children_ & kNormalFlowChildren) { + current_normal_flow_child_ = root_.LastChild(); + return; + } + + if (remaining_children_ & kPositiveZOrderChildren) { + if (root_.StackingNode()) { + const auto& pos_z_order_list = root_.StackingNode()->PosZOrderList(); + if (!pos_z_order_list.IsEmpty()) { + index_ = pos_z_order_list.size() - 1; + return; + } + } + + remaining_children_ &= ~kPositiveZOrderChildren; + } + + // No more list to visit. + DCHECK(!remaining_children_); + index_ = -1; +} + +} // namespace blink
diff --git a/third_party/blink/renderer/core/paint/paint_layer_paint_order_iterator.h b/third_party/blink/renderer/core/paint/paint_layer_paint_order_iterator.h new file mode 100644 index 0000000..32ee38c --- /dev/null +++ b/third_party/blink/renderer/core/paint/paint_layer_paint_order_iterator.h
@@ -0,0 +1,106 @@ +/* + * Copyright (C) 2013 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_PAINT_LAYER_PAINT_ORDER_ITERATOR_H_ +#define THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_PAINT_LAYER_PAINT_ORDER_ITERATOR_H_ + +#include "third_party/blink/renderer/core/paint/paint_layer.h" +#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h" + +namespace blink { + +// This iterator walks the PaintLayer descendants in the following paint order: +// NegativeZOrderChildren -> NormalFlowChildren -> PositiveZOrderChildren. +class CORE_EXPORT PaintLayerPaintOrderIterator { + STACK_ALLOCATED(); + + public: + PaintLayerPaintOrderIterator(const PaintLayer& root, + PaintLayerIteration which_children) + : root_(root), + remaining_children_(which_children), + index_(0), + current_normal_flow_child_(root.FirstChild()) +#if DCHECK_IS_ON() + , + mutation_detector_(root) +#endif + { + } + + PaintLayer* Next(); + + private: + const PaintLayer& root_; + unsigned remaining_children_; + unsigned index_; + PaintLayer* current_normal_flow_child_; +#if DCHECK_IS_ON() + PaintLayerListMutationDetector mutation_detector_; +#endif + DISALLOW_COPY_AND_ASSIGN(PaintLayerPaintOrderIterator); +}; + +// This iterator is similar to PaintLayerPaintOrderIterator but it walks the +// lists in reverse order (from the last item to the first one). +class CORE_EXPORT PaintLayerPaintOrderReverseIterator { + STACK_ALLOCATED(); + + public: + PaintLayerPaintOrderReverseIterator(const PaintLayer& root, + unsigned which_children) + : root_(root), + remaining_children_(which_children) +#if DCHECK_IS_ON() + , + mutation_detector_(root) +#endif + { + SetIndexToLastItem(); + } + + PaintLayer* Next(); + + private: + void SetIndexToLastItem(); + + const PaintLayer& root_; + unsigned remaining_children_; + int index_; + PaintLayer* current_normal_flow_child_; +#if DCHECK_IS_ON() + PaintLayerListMutationDetector mutation_detector_; +#endif + DISALLOW_COPY_AND_ASSIGN(PaintLayerPaintOrderReverseIterator); +}; + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_PAINT_LAYER_PAINT_ORDER_ITERATOR_H_
diff --git a/third_party/blink/renderer/core/paint/paint_layer_painter.cc b/third_party/blink/renderer/core/paint/paint_layer_painter.cc index 58f6b6ff..0f91221 100644 --- a/third_party/blink/renderer/core/paint/paint_layer_painter.cc +++ b/third_party/blink/renderer/core/paint/paint_layer_painter.cc
@@ -13,6 +13,7 @@ #include "third_party/blink/renderer/core/paint/object_paint_properties.h" #include "third_party/blink/renderer/core/paint/paint_info.h" #include "third_party/blink/renderer/core/paint/paint_layer.h" +#include "third_party/blink/renderer/core/paint/paint_layer_paint_order_iterator.h" #include "third_party/blink/renderer/core/paint/scrollable_area_painter.h" #include "third_party/blink/renderer/platform/geometry/float_point_3d.h" #include "third_party/blink/renderer/platform/graphics/graphics_layer.h" @@ -550,7 +551,7 @@ paint_layer_, DisplayItem::kLayerChunkNormalFlowAndPositiveZOrderChildren); } - if (PaintChildren(kNormalFlowChildren | kPositiveZOrderChildren, context, + if (PaintChildren(kNormalFlowAndPositiveZOrderChildren, context, painting_info, paint_flags) == kMayBeClippedByCullRect) result = kMayBeClippedByCullRect; } @@ -669,30 +670,21 @@ } PaintResult PaintLayerPainter::PaintChildren( - unsigned children_to_visit, + PaintLayerIteration children_to_visit, GraphicsContext& context, const PaintLayerPaintingInfo& painting_info, PaintLayerFlags paint_flags) { PaintResult result = kFullyPainted; if (!paint_layer_.HasSelfPaintingLayerDescendant()) return result; - if (!paint_layer_.StackingNode()) - return result; + if (paint_layer_.GetLayoutObject().PaintBlockedByDisplayLock( DisplayLockContext::kChildren)) { return result; } -#if DCHECK_IS_ON() - LayerListMutationDetector mutation_checker(paint_layer_.StackingNode()); -#endif - - PaintLayerStackingNodeIterator iterator(*paint_layer_.StackingNode(), - children_to_visit); - PaintLayer* child = iterator.Next(); - if (!child) - return result; - for (; child; child = iterator.Next()) { + PaintLayerPaintOrderIterator iterator(paint_layer_, children_to_visit); + while (PaintLayer* child = iterator.Next()) { // If this Layer should paint into its own backing or a grouped backing, // that will be done via CompositedLayerMapping::PaintContents() and // CompositedLayerMapping::DoPaintTask().
diff --git a/third_party/blink/renderer/core/paint/paint_layer_painter.h b/third_party/blink/renderer/core/paint/paint_layer_painter.h index 7c48860..c16f278 100644 --- a/third_party/blink/renderer/core/paint/paint_layer_painter.h +++ b/third_party/blink/renderer/core/paint/paint_layer_painter.h
@@ -6,6 +6,7 @@ #define THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_PAINT_LAYER_PAINTER_H_ #include "third_party/blink/renderer/core/core_export.h" +#include "third_party/blink/renderer/core/paint/paint_layer.h" #include "third_party/blink/renderer/core/paint/paint_layer_fragment.h" #include "third_party/blink/renderer/core/paint/paint_layer_painting_info.h" #include "third_party/blink/renderer/core/paint/paint_result.h" @@ -17,7 +18,6 @@ class ClipRect; class ComputedStyle; class DisplayItemClient; -class PaintLayer; class GraphicsContext; struct PhysicalOffset; @@ -60,7 +60,7 @@ private: friend class PaintLayerPainterTest; - PaintResult PaintChildren(unsigned children_to_visit, + PaintResult PaintChildren(PaintLayerIteration children_to_visit, GraphicsContext&, const PaintLayerPaintingInfo&, PaintLayerFlags);
diff --git a/third_party/blink/renderer/core/paint/paint_layer_stacking_node.cc b/third_party/blink/renderer/core/paint/paint_layer_stacking_node.cc index fd5c114..7598786 100644 --- a/third_party/blink/renderer/core/paint/paint_layer_stacking_node.cc +++ b/third_party/blink/renderer/core/paint/paint_layer_stacking_node.cc
@@ -59,101 +59,66 @@ // FIXME: This should not require PaintLayer. There is currently a cycle where // in order to determine if we isStacked() we have to ask the paint // layer about some of its state. -PaintLayerStackingNode::PaintLayerStackingNode(PaintLayer* layer) - : layer_(layer) -#if DCHECK_IS_ON() - , - layer_list_mutation_allowed_(true) -#endif -{ - // Non-stacking contexts should have empty z-order lists. As this is already - // the case, there is no need to dirty / recompute these lists. - z_order_lists_dirty_ = - layer->GetLayoutObject().StyleRef().IsStackingContext(); +PaintLayerStackingNode::PaintLayerStackingNode(PaintLayer& layer) + : layer_(layer), z_order_lists_dirty_(true) { + DCHECK(layer.GetLayoutObject().StyleRef().IsStackingContext()); } PaintLayerStackingNode::~PaintLayerStackingNode() { #if DCHECK_IS_ON() - if (!Layer()->GetLayoutObject().DocumentBeingDestroyed()) + if (!layer_.GetLayoutObject().DocumentBeingDestroyed()) UpdateStackingParentForZOrderLists(nullptr); #endif } -PaintLayerStackingNode::PaintLayers* PaintLayerStackingNode::PosZOrderList() - const { - DCHECK(!z_order_lists_dirty_); - DCHECK(Layer()->GetLayoutObject().StyleRef().IsStackingContext() || - !pos_z_order_list_); - return pos_z_order_list_.get(); -} - -PaintLayerStackingNode::PaintLayers* PaintLayerStackingNode::NegZOrderList() - const { - DCHECK(!z_order_lists_dirty_); - DCHECK(Layer()->GetLayoutObject().StyleRef().IsStackingContext() || - !neg_z_order_list_); - return neg_z_order_list_.get(); -} - -bool PaintLayerStackingNode::IsDirtyStackingContext() const { - return z_order_lists_dirty_ && - Layer()->GetLayoutObject().StyleRef().IsStackingContext(); -} - PaintLayerCompositor* PaintLayerStackingNode::Compositor() const { - DCHECK(Layer()->GetLayoutObject().View()); - if (!Layer()->GetLayoutObject().View()) + DCHECK(layer_.GetLayoutObject().View()); + if (!layer_.GetLayoutObject().View()) return nullptr; - return Layer()->GetLayoutObject().View()->Compositor(); + return layer_.GetLayoutObject().View()->Compositor(); } void PaintLayerStackingNode::DirtyZOrderLists() { #if DCHECK_IS_ON() - DCHECK(layer_list_mutation_allowed_); -#endif - DCHECK(Layer()->GetLayoutObject().StyleRef().IsStackingContext()); - -#if DCHECK_IS_ON() + DCHECK(layer_.LayerListMutationAllowed()); UpdateStackingParentForZOrderLists(nullptr); #endif - if (pos_z_order_list_) - pos_z_order_list_->clear(); - if (neg_z_order_list_) - neg_z_order_list_->clear(); + pos_z_order_list_.clear(); + neg_z_order_list_.clear(); z_order_lists_dirty_ = true; - if (!Layer()->GetLayoutObject().DocumentBeingDestroyed() && Compositor()) + if (!layer_.GetLayoutObject().DocumentBeingDestroyed() && Compositor()) Compositor()->SetNeedsCompositingUpdate(kCompositingUpdateRebuildTree); } void PaintLayerStackingNode::DirtyStackingContextZOrderLists( - PaintLayer* layer) { - if (PaintLayerStackingNode* stacking_node = - AncestorStackingContextNode(layer)) { - // This invalidation code intentionally refers to stale state. - DisableCompositingQueryAsserts disabler; + PaintLayer& layer) { + auto* stacking_context = layer.AncestorStackingContext(); + if (!stacking_context) + return; - // Changes of stacking may result in graphics layers changing size - // due to new contents painting into them. - PaintLayer* ancestor_layer = stacking_node->Layer(); - if (auto* mapping = ancestor_layer->GetCompositedLayerMapping()) { - mapping->SetNeedsGraphicsLayerUpdate(kGraphicsLayerUpdateSubtree); - } + // This invalidation code intentionally refers to stale state. + DisableCompositingQueryAsserts disabler; - stacking_node->DirtyZOrderLists(); - } + // Changes of stacking may result in graphics layers changing size + // due to new contents painting into them. + if (auto* mapping = stacking_context->GetCompositedLayerMapping()) + mapping->SetNeedsGraphicsLayerUpdate(kGraphicsLayerUpdateSubtree); + + if (stacking_context->StackingNode()) + stacking_context->StackingNode()->DirtyZOrderLists(); } void PaintLayerStackingNode::RebuildZOrderLists() { #if DCHECK_IS_ON() - DCHECK(layer_list_mutation_allowed_); + DCHECK(layer_.LayerListMutationAllowed()); #endif - DCHECK(IsDirtyStackingContext()); + DCHECK(z_order_lists_dirty_); - for (PaintLayer* child = Layer()->FirstChild(); child; + for (PaintLayer* child = layer_.FirstChild(); child; child = child->NextSibling()) - CollectLayers(child, pos_z_order_list_, neg_z_order_list_); + CollectLayers(*child); auto CompareZIndex = [](PaintLayer* first, PaintLayer* second) { return first->GetLayoutObject().StyleRef().ZIndex() < @@ -161,20 +126,17 @@ }; // Sort the two lists. - if (pos_z_order_list_) - std::stable_sort(pos_z_order_list_->begin(), pos_z_order_list_->end(), - CompareZIndex); - - if (neg_z_order_list_) - std::stable_sort(neg_z_order_list_->begin(), neg_z_order_list_->end(), - CompareZIndex); + std::stable_sort(pos_z_order_list_.begin(), pos_z_order_list_.end(), + CompareZIndex); + std::stable_sort(neg_z_order_list_.begin(), neg_z_order_list_.end(), + CompareZIndex); // Append layers for top layer elements after normal layer collection, to // ensure they are on top regardless of z-indexes. The layoutObjects of top // layer elements are children of the view, sorted in top layer stacking // order. - if (Layer()->IsRootLayer()) { - LayoutBlockFlow* root_block = Layer()->GetLayoutObject().View(); + if (layer_.IsRootLayer()) { + LayoutBlockFlow* root_block = layer_.GetLayoutObject().View(); // If the viewport is paginated, everything (including "top-layer" elements) // gets redirected to the flow thread. So that's where we have to look, in // that case. @@ -187,15 +149,9 @@ (child->GetNode() && child->GetNode()->IsElementNode()) ? ToElement(child->GetNode()) : nullptr; - if (child_element && child_element->IsInTopLayer()) { - PaintLayer* layer = ToLayoutBoxModelObject(child)->Layer(); - if (layer->StackingNode()) { - // Create the buffer if it doesn't exist yet. - if (!pos_z_order_list_) { - pos_z_order_list_ = std::make_unique<PaintLayers>(); - } - pos_z_order_list_->push_back(layer); - } + if (child_element && child_element->IsInTopLayer() && + child->StyleRef().IsStacked()) { + pos_z_order_list_.push_back(ToLayoutBoxModelObject(child)->Layer()); } } } @@ -207,48 +163,37 @@ z_order_lists_dirty_ = false; } -void PaintLayerStackingNode::CollectLayers( - PaintLayer* paint_layer, - std::unique_ptr<PaintLayers>& pos_buffer, - std::unique_ptr<PaintLayers>& neg_buffer) { - if (paint_layer->IsInTopLayer()) +void PaintLayerStackingNode::CollectLayers(PaintLayer& paint_layer) { + if (paint_layer.IsInTopLayer()) return; - const ComputedStyle& style = paint_layer->GetLayoutObject().StyleRef(); + const ComputedStyle& style = paint_layer.GetLayoutObject().StyleRef(); if (style.IsStacked()) { - std::unique_ptr<PaintLayers>& buffer = - (style.ZIndex() >= 0) ? pos_buffer : neg_buffer; - if (!buffer) - buffer = std::make_unique<PaintLayers>(); - buffer->push_back(paint_layer); + auto& list = style.ZIndex() >= 0 ? pos_z_order_list_ : neg_z_order_list_; + list.push_back(&paint_layer); } - if (!style.IsStackingContext()) { - for (PaintLayer* child = paint_layer->FirstChild(); child; - child = child->NextSibling()) { - CollectLayers(child, pos_buffer, neg_buffer); - } - } + if (style.IsStackingContext()) + return; + + for (PaintLayer* child = paint_layer.FirstChild(); child; + child = child->NextSibling()) + CollectLayers(*child); } #if DCHECK_IS_ON() void PaintLayerStackingNode::UpdateStackingParentForZOrderLists( PaintLayerStackingNode* stacking_parent) { - if (pos_z_order_list_) { - for (wtf_size_t i = 0; i < pos_z_order_list_->size(); ++i) - pos_z_order_list_->at(i)->SetStackingParent(stacking_parent); - } - - if (neg_z_order_list_) { - for (wtf_size_t i = 0; i < neg_z_order_list_->size(); ++i) - neg_z_order_list_->at(i)->SetStackingParent(stacking_parent); - } + for (auto* layer : pos_z_order_list_) + layer->SetStackingParent(stacking_parent); + for (auto* layer : neg_z_order_list_) + layer->SetStackingParent(stacking_parent); } #endif -bool PaintLayerStackingNode::StyleDidChange(PaintLayer* paint_layer, +bool PaintLayerStackingNode::StyleDidChange(PaintLayer& paint_layer, const ComputedStyle* old_style) { bool was_stacking_context = false; bool was_stacked = false; @@ -259,7 +204,7 @@ was_stacked = old_style->IsStacked(); } - const ComputedStyle& new_style = paint_layer->GetLayoutObject().StyleRef(); + const ComputedStyle& new_style = paint_layer.GetLayoutObject().StyleRef(); bool should_be_stacking_context = new_style.IsStackingContext(); bool should_be_stacked = new_style.IsStacked(); @@ -268,58 +213,25 @@ return false; // Need to force requirements update, due to change of stacking order. - paint_layer->SetNeedsCompositingRequirementsUpdate(); + paint_layer.SetNeedsCompositingRequirementsUpdate(); DirtyStackingContextZOrderLists(paint_layer); - if (paint_layer->StackingNode()) { - if (should_be_stacking_context) - paint_layer->StackingNode()->DirtyZOrderLists(); - else - paint_layer->StackingNode()->ClearZOrderLists(); - } + if (paint_layer.StackingNode()) + paint_layer.StackingNode()->DirtyZOrderLists(); if (was_stacked != should_be_stacked) { - if (!paint_layer->GetLayoutObject().DocumentBeingDestroyed() && - !paint_layer->IsRootLayer() && paint_layer->Compositor()) { - paint_layer->Compositor()->SetNeedsCompositingUpdate( + if (!paint_layer.GetLayoutObject().DocumentBeingDestroyed() && + !paint_layer.IsRootLayer() && paint_layer.Compositor()) { + paint_layer.Compositor()->SetNeedsCompositingUpdate( kCompositingUpdateRebuildTree); } } return true; } -PaintLayerStackingNode* PaintLayerStackingNode::AncestorStackingContextNode( - const PaintLayer* layer) { - for (PaintLayer* ancestor = layer->Parent(); ancestor; - ancestor = ancestor->Parent()) { - if (ancestor->GetLayoutObject().StyleRef().IsStackingContext()) - return ancestor->StackingNode(); - } - return nullptr; -} - -void PaintLayerStackingNode::ClearZOrderLists() { - DCHECK(!Layer()->GetLayoutObject().StyleRef().IsStackingContext()); - -#if DCHECK_IS_ON() - UpdateStackingParentForZOrderLists(nullptr); -#endif - - pos_z_order_list_.reset(); - neg_z_order_list_.reset(); -} - void PaintLayerStackingNode::UpdateZOrderLists() { - if (!z_order_lists_dirty_) - return; - - if (!Layer()->GetLayoutObject().StyleRef().IsStackingContext()) { - ClearZOrderLists(); - z_order_lists_dirty_ = false; - return; - } - - RebuildZOrderLists(); + if (z_order_lists_dirty_) + RebuildZOrderLists(); } } // namespace blink
diff --git a/third_party/blink/renderer/core/paint/paint_layer_stacking_node.h b/third_party/blink/renderer/core/paint/paint_layer_stacking_node.h index 3439dec..fb9288f4 100644 --- a/third_party/blink/renderer/core/paint/paint_layer_stacking_node.h +++ b/third_party/blink/renderer/core/paint/paint_layer_stacking_node.h
@@ -58,6 +58,9 @@ class PaintLayerCompositor; class ComputedStyle; +// This class is only for PaintLayer, PaintLayerPaintOrderIterator and +// PaintLayerPaintOrderReverseIterator. Other classes should not use this class. +// // PaintLayerStackingNode represents a stacked element which is either a // stacking context or a positioned element. // See @@ -74,131 +77,70 @@ // // Stacked elements form a subtree over the layout tree. Ideally we would want // objects of this class to be a node in this tree but there are potential -// issues with stale pointers so we rely on PaintLayer's tree -// structure. +// issues with stale pointers so we rely on PaintLayer's tree structure. // // This class's purpose is to represent a node in the stacked element tree // (aka paint tree). It currently caches the z-order lists for painting and // hit-testing. // -// To implement any z-order list iterations, use -// PaintLayerStackingNodeIterator and -// PaintLayerStackingNodeReverseIterator. +// To implement any paint order iterations, use PaintLayerPaintOrderIterator and +// PaintLayerZOrderReverseIterator. // -// Only a real stacking context can have non-empty z-order lists thus contain -// child nodes in the tree. The z-order lists of a positioned element with auto -// z-index are always empty (i.e. it's a leaf of the stacked element tree). -// A real stacking context can also be a leaf if it doesn't contain any stacked -// elements. +// We create PaintLayerStackingNode only for real stacking contexts with stacked +// children. PaintLayerPaintOrder[Reverse]Iterator can iterate normal flow +// children in paint order with or without a stacking node. class CORE_EXPORT PaintLayerStackingNode { USING_FAST_MALLOC(PaintLayerStackingNode); public: - explicit PaintLayerStackingNode(PaintLayer*); + explicit PaintLayerStackingNode(PaintLayer&); ~PaintLayerStackingNode(); - bool ZOrderListsDirty() const { return z_order_lists_dirty_; } - void DirtyZOrderLists(); void UpdateZOrderLists(); - void ClearZOrderLists(); - static void DirtyStackingContextZOrderLists(PaintLayer*); - - bool HasPositiveZOrderList() const { - return PosZOrderList() && PosZOrderList()->size(); - } - bool HasNegativeZOrderList() const { - return NegZOrderList() && NegZOrderList()->size(); - } + static void DirtyStackingContextZOrderLists(PaintLayer&); // Returns whether a relevant style changed. - static bool StyleDidChange(PaintLayer* paint_layer, + static bool StyleDidChange(PaintLayer& paint_layer, const ComputedStyle* old_style); - PaintLayer* Layer() const { return layer_; } - -#if DCHECK_IS_ON() - bool LayerListMutationAllowed() const { return layer_list_mutation_allowed_; } - void SetLayerListMutationAllowed(bool flag) { - layer_list_mutation_allowed_ = flag; - } -#endif - - static PaintLayerStackingNode* AncestorStackingContextNode(const PaintLayer*); using PaintLayers = Vector<PaintLayer*>; + const PaintLayers& PosZOrderList() const { + DCHECK(!z_order_lists_dirty_); + return pos_z_order_list_; + } + const PaintLayers& NegZOrderList() const { + DCHECK(!z_order_lists_dirty_); + return neg_z_order_list_; + } + private: - friend class PaintLayerStackingNodeIterator; - friend class PaintLayerStackingNodeReverseIterator; - friend class LayoutTreeAsText; - -#if DCHECK_IS_ON() - friend class PaintLayer; -#endif - - PaintLayers* PosZOrderList() const; - - PaintLayers* NegZOrderList() const; - + void DirtyZOrderLists(); void RebuildZOrderLists(); - static void CollectLayers(PaintLayer*, - std::unique_ptr<PaintLayers>& pos_z_order_list, - std::unique_ptr<PaintLayers>& neg_z_order_list); + void CollectLayers(PaintLayer&); #if DCHECK_IS_ON() void UpdateStackingParentForZOrderLists( PaintLayerStackingNode* stacking_parent); #endif - bool IsDirtyStackingContext() const; - PaintLayerCompositor* Compositor() const; - PaintLayer* layer_; + PaintLayer& layer_; - // m_posZOrderList holds a sorted list of all the descendant nodes within - // that have z-indices of 0 (or is treated as 0 for positioned objects) or - // greater. - std::unique_ptr<PaintLayers> pos_z_order_list_; - // m_negZOrderList holds descendants within our stacking context with - // negative z-indices. - std::unique_ptr<PaintLayers> neg_z_order_list_; + // Holds a sorted list of all the descendant nodes within that have z-indices + // of 0 (or is treated as 0 for positioned objects) or greater. + PaintLayers pos_z_order_list_; + // Holds descendants within our stacking context with negative z-indices. + PaintLayers neg_z_order_list_; - // This boolean caches whether the z-order lists above are dirty. - // It is only ever set for stacking contexts, as no other element can - // have z-order lists. + // Indicates whether the z-order lists above are dirty. bool z_order_lists_dirty_ : 1; -#if DCHECK_IS_ON() - bool layer_list_mutation_allowed_ : 1; -#endif - DISALLOW_COPY_AND_ASSIGN(PaintLayerStackingNode); }; -#if DCHECK_IS_ON() -class LayerListMutationDetector { - STACK_ALLOCATED(); - - public: - explicit LayerListMutationDetector(PaintLayerStackingNode* stacking_node) - : stacking_node_(stacking_node), - previous_mutation_allowed_state_( - stacking_node->LayerListMutationAllowed()) { - stacking_node_->SetLayerListMutationAllowed(false); - } - - ~LayerListMutationDetector() { - stacking_node_->SetLayerListMutationAllowed( - previous_mutation_allowed_state_); - } - - private: - PaintLayerStackingNode* stacking_node_; - bool previous_mutation_allowed_state_; -}; -#endif - } // namespace blink #endif // THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_PAINT_LAYER_STACKING_NODE_H_
diff --git a/third_party/blink/renderer/core/paint/paint_layer_stacking_node_iterator.cc b/third_party/blink/renderer/core/paint/paint_layer_stacking_node_iterator.cc deleted file mode 100644 index 076e289..0000000 --- a/third_party/blink/renderer/core/paint/paint_layer_stacking_node_iterator.cc +++ /dev/null
@@ -1,164 +0,0 @@ -/* - * Copyright (C) 2013 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "third_party/blink/renderer/core/paint/paint_layer_stacking_node_iterator.h" - -// FIXME: We should build our primitive on top of -// PaintLayerStackingNode and remove this include. -#include "third_party/blink/renderer/core/paint/paint_layer.h" -#include "third_party/blink/renderer/core/paint/paint_layer_stacking_node.h" - -namespace blink { - -PaintLayerStackingNodeIterator::PaintLayerStackingNodeIterator( - const PaintLayerStackingNode& root, - unsigned which_children) - : root_(root), remaining_children_(which_children), index_(0) { - current_normal_flow_child_ = root.Layer()->FirstChild(); -} - -PaintLayer* PaintLayerStackingNodeIterator::Next() { - if (remaining_children_ & kNegativeZOrderChildren) { - PaintLayerStackingNode::PaintLayers* neg_z_order_list = - root_.NegZOrderList(); - if (neg_z_order_list && index_ < neg_z_order_list->size()) - return neg_z_order_list->at(index_++); - - index_ = 0; - remaining_children_ &= ~kNegativeZOrderChildren; - } - - if (remaining_children_ & kNormalFlowChildren) { - for (; current_normal_flow_child_; - current_normal_flow_child_ = - current_normal_flow_child_->NextSibling()) { - if (!current_normal_flow_child_->GetLayoutObject() - .StyleRef() - .IsStacked()) { - PaintLayer* normal_flow_child = current_normal_flow_child_; - current_normal_flow_child_ = current_normal_flow_child_->NextSibling(); - return normal_flow_child; - } - } - - // We reset the iterator in case we reuse it. - current_normal_flow_child_ = root_.Layer()->FirstChild(); - remaining_children_ &= ~kNormalFlowChildren; - } - - if (remaining_children_ & kPositiveZOrderChildren) { - PaintLayerStackingNode::PaintLayers* pos_z_order_list = - root_.PosZOrderList(); - if (pos_z_order_list && index_ < pos_z_order_list->size()) - return pos_z_order_list->at(index_++); - - index_ = 0; - remaining_children_ &= ~kPositiveZOrderChildren; - } - - return nullptr; -} - -PaintLayer* PaintLayerStackingNodeReverseIterator::Next() { - if (remaining_children_ & kNegativeZOrderChildren) { - PaintLayerStackingNode::PaintLayers* neg_z_order_list = - root_.NegZOrderList(); - if (neg_z_order_list && index_ >= 0) - return neg_z_order_list->at(index_--); - - remaining_children_ &= ~kNegativeZOrderChildren; - SetIndexToLastItem(); - } - - if (remaining_children_ & kNormalFlowChildren) { - for (; current_normal_flow_child_; - current_normal_flow_child_ = - current_normal_flow_child_->PreviousSibling()) { - if (!current_normal_flow_child_->GetLayoutObject() - .StyleRef() - .IsStacked()) { - PaintLayer* normal_flow_child = current_normal_flow_child_; - current_normal_flow_child_ = - current_normal_flow_child_->PreviousSibling(); - return normal_flow_child; - } - } - - remaining_children_ &= ~kNormalFlowChildren; - SetIndexToLastItem(); - } - - if (remaining_children_ & kPositiveZOrderChildren) { - PaintLayerStackingNode::PaintLayers* pos_z_order_list = - root_.PosZOrderList(); - if (pos_z_order_list && index_ >= 0) - return pos_z_order_list->at(index_--); - - remaining_children_ &= ~kPositiveZOrderChildren; - SetIndexToLastItem(); - } - - return nullptr; -} - -void PaintLayerStackingNodeReverseIterator::SetIndexToLastItem() { - if (remaining_children_ & kNegativeZOrderChildren) { - PaintLayerStackingNode::PaintLayers* neg_z_order_list = - root_.NegZOrderList(); - if (neg_z_order_list) { - index_ = neg_z_order_list->size() - 1; - return; - } - - remaining_children_ &= ~kNegativeZOrderChildren; - } - - if (remaining_children_ & kNormalFlowChildren) { - current_normal_flow_child_ = root_.Layer()->LastChild(); - return; - } - - if (remaining_children_ & kPositiveZOrderChildren) { - PaintLayerStackingNode::PaintLayers* pos_z_order_list = - root_.PosZOrderList(); - if (pos_z_order_list) { - index_ = pos_z_order_list->size() - 1; - return; - } - - remaining_children_ &= ~kPositiveZOrderChildren; - } - - // No more list to visit. - DCHECK(!remaining_children_); - index_ = -1; -} - -} // namespace blink
diff --git a/third_party/blink/renderer/core/paint/paint_layer_stacking_node_iterator.h b/third_party/blink/renderer/core/paint/paint_layer_stacking_node_iterator.h deleted file mode 100644 index a002e2cf..0000000 --- a/third_party/blink/renderer/core/paint/paint_layer_stacking_node_iterator.h +++ /dev/null
@@ -1,99 +0,0 @@ -/* - * Copyright (C) 2013 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_PAINT_LAYER_STACKING_NODE_ITERATOR_H_ -#define THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_PAINT_LAYER_STACKING_NODE_ITERATOR_H_ - -#include "base/macros.h" -#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h" - -namespace blink { - -enum ChildrenIteration { - kNegativeZOrderChildren = 1, - // Normal flow children are not mandated by CSS 2.1 but are an artifact of - // our implementation: we allocate PaintLayers for elements that - // are not treated as stacking contexts and thus we need to walk them - // during painting and hit-testing. - kNormalFlowChildren = 1 << 1, - kPositiveZOrderChildren = 1 << 2, - kAllChildren = - kNegativeZOrderChildren | kNormalFlowChildren | kPositiveZOrderChildren -}; - -class PaintLayerStackingNode; -class PaintLayer; - -// This iterator walks the PaintLayerStackingNode lists in the following order: -// NegativeZOrderChildren -> NormalFlowChildren -> PositiveZOrderChildren. -class PaintLayerStackingNodeIterator { - STACK_ALLOCATED(); - - public: - PaintLayerStackingNodeIterator(const PaintLayerStackingNode& root, - unsigned which_children); - - PaintLayer* Next(); - - private: - const PaintLayerStackingNode& root_; - unsigned remaining_children_; - unsigned index_; - PaintLayer* current_normal_flow_child_; - DISALLOW_COPY_AND_ASSIGN(PaintLayerStackingNodeIterator); -}; - -// This iterator is similar to PaintLayerStackingNodeIterator but it walks the -// lists in reverse order (from the last item to the first one). -class PaintLayerStackingNodeReverseIterator { - STACK_ALLOCATED(); - - public: - PaintLayerStackingNodeReverseIterator(const PaintLayerStackingNode& root, - unsigned which_children) - : root_(root), remaining_children_(which_children) { - SetIndexToLastItem(); - } - - PaintLayer* Next(); - - private: - void SetIndexToLastItem(); - - const PaintLayerStackingNode& root_; - unsigned remaining_children_; - int index_; - PaintLayer* current_normal_flow_child_; - DISALLOW_COPY_AND_ASSIGN(PaintLayerStackingNodeReverseIterator); -}; - -} // namespace blink - -#endif // THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_PAINT_LAYER_STACKING_NODE_ITERATOR_H_
diff --git a/third_party/blink/renderer/core/paint/paint_layer_test.cc b/third_party/blink/renderer/core/paint/paint_layer_test.cc index 386a489..2bc5d6b 100644 --- a/third_party/blink/renderer/core/paint/paint_layer_test.cc +++ b/third_party/blink/renderer/core/paint/paint_layer_test.cc
@@ -8,6 +8,7 @@ #include "third_party/blink/renderer/core/html/html_iframe_element.h" #include "third_party/blink/renderer/core/layout/layout_box_model_object.h" #include "third_party/blink/renderer/core/layout/layout_view.h" +#include "third_party/blink/renderer/core/paint/paint_layer_paint_order_iterator.h" #include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h" #include "third_party/blink/renderer/core/testing/core_unit_test_helper.h" #include "third_party/blink/renderer/platform/testing/paint_test_configurations.h" @@ -588,15 +589,19 @@ PaintLayer* target = GetPaintLayerByElementId("target"); - EXPECT_TRUE(target->StackingNode()->HasNegativeZOrderList()); - EXPECT_FALSE(target->StackingNode()->HasPositiveZOrderList()); + EXPECT_TRUE( + PaintLayerPaintOrderIterator(*target, kNegativeZOrderChildren).Next()); + EXPECT_FALSE( + PaintLayerPaintOrderIterator(*target, kPositiveZOrderChildren).Next()); GetDocument().getElementById("child")->setAttribute(html_names::kStyleAttr, "z-index: 1"); UpdateAllLifecyclePhasesForTest(); - EXPECT_FALSE(target->StackingNode()->HasNegativeZOrderList()); - EXPECT_TRUE(target->StackingNode()->HasPositiveZOrderList()); + EXPECT_FALSE( + PaintLayerPaintOrderIterator(*target, kNegativeZOrderChildren).Next()); + EXPECT_TRUE( + PaintLayerPaintOrderIterator(*target, kPositiveZOrderChildren).Next()); } TEST_P(PaintLayerTest, HasDescendantWithClipPath) {
diff --git a/third_party/blink/renderer/core/script/layered_api_resources.h b/third_party/blink/renderer/core/script/layered_api_resources.h index 3f2c821..ccd501c 100644 --- a/third_party/blink/renderer/core/script/layered_api_resources.h +++ b/third_party/blink/renderer/core/script/layered_api_resources.h
@@ -29,8 +29,12 @@ const LayeredAPIResource kLayeredAPIResources[] = { {"blank/index.mjs", IDR_LAYERED_API_BLANK_INDEX_MJS, Module::kBlank}, + {"elements/switch/face_utils.mjs", + IDR_LAYERED_API_ELEMENTS_SWITCH_FACE_UTILS_MJS, Module::kElementsSwitch}, {"elements/switch/index.mjs", IDR_LAYERED_API_ELEMENTS_SWITCH_INDEX_MJS, Module::kElementsSwitch}, + {"elements/switch/reflection.mjs", + IDR_LAYERED_API_ELEMENTS_SWITCH_REFLECTION_MJS, Module::kElementsSwitch}, {"kv-storage/async_iterator.mjs", IDR_LAYERED_API_KV_STORAGE_ASYNC_ITERATOR_MJS, Module::kKvStorage},
diff --git a/third_party/blink/renderer/core/script/resources/layered_api/elements/switch/face_utils.mjs b/third_party/blink/renderer/core/script/resources/layered_api/elements/switch/face_utils.mjs new file mode 100644 index 0000000..f8e4685d --- /dev/null +++ b/third_party/blink/renderer/core/script/resources/layered_api/elements/switch/face_utils.mjs
@@ -0,0 +1,75 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** + * @file Utilities for form-associated custom elements + */ + +import * as reflection from './reflection.mjs'; + +function installGetter(proto, propName, getter) { + Object.defineProperty( + getter, 'name', + {configurable: true, enumerable: false, value: 'get ' + propName}); + Object.defineProperty( + proto, propName, {configurable: true, enumerable: true, get: getter}); +} + +/** + * Add the following properties to |proto|. + * - disabled + * - name + * - type + * - form + * - willValidate + * - validity + * - validationMessage + * - labels + * - checkValidity() + * - reportValidity() + * - setCustomValidity(error) + * + * @param {!Object} proto An Element prototype which will have properties + * @param {!Symbol} internals A Symbol of the ElementInternals property of the + * element + */ +export function installPropertiesAndFunctions(proto, internals) { + reflection.installBool(proto, 'disabled'); + reflection.installString(proto, 'name'); + installGetter(proto, 'type', function() { + if (!(this instanceof proto.constructor)) { + throw TypeError( + 'The context object is not an instance of ' + proto.contructor.name); + } + return this.localName; + }); + + installGetter(proto, 'form', function() { + return this[internals].form; + }); + installGetter(proto, 'willValidate', function() { + return this[internals].willValidate; + }); + installGetter(proto, 'validity', function() { + return this[internals].validity; + }); + installGetter(proto, 'validationMessage', function() { + return this[internals].validationMessage; + }); + installGetter(proto, 'labels', function() { + return this[internals].labels; + }); + proto.checkValidity = function() { + return this[internals].checkValidity(); + }; + proto.reportValidity = function() { + return this[internals].reportValidity(); + }; + proto.setCustomValidity = function(error) { + if (error === undefined) { + throw new TypeError('Too few arguments'); + } + this[internals].setValidity({customError: true}, error); + }; +}
diff --git a/third_party/blink/renderer/core/script/resources/layered_api/elements/switch/index.mjs b/third_party/blink/renderer/core/script/resources/layered_api/elements/switch/index.mjs index 062f30e..1fe4608 100644 --- a/third_party/blink/renderer/core/script/resources/layered_api/elements/switch/index.mjs +++ b/third_party/blink/renderer/core/script/resources/layered_api/elements/switch/index.mjs
@@ -2,5 +2,39 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// TODO(tkent): Add real code. +import * as face from './face_utils.mjs'; +import * as reflection from './reflection.mjs'; +// https://github.com/tkent-google/std-switch/issues/2 +const STATE_ATTR = 'on'; + +// Private property symbols +// TODO(tkent): Use a private field. +const _internals = Symbol(); + +export class StdSwitchElement extends HTMLElement { + static get formAssociated() { + return true; + } + + constructor() { + super(); + this[_internals] = this.attachInternals(); + } +} + +reflection.installBool(StdSwitchElement.prototype, STATE_ATTR); +reflection.installBool( + StdSwitchElement.prototype, 'default' + STATE_ATTR, + 'default' + STATE_ATTR.charAt(0).toUpperCase() + STATE_ATTR.substring(1)); +face.installPropertiesAndFunctions(StdSwitchElement.prototype, _internals); + +// This is necessary for anyObject.toString.call(switchInstance). +Object.defineProperty(StdSwitchElement.prototype, Symbol.toStringTag, { + configurable: true, + enumerable: false, + value: 'StdSwitchElement', + writable: false +}); + +customElements.define('std-switch', StdSwitchElement);
diff --git a/third_party/blink/renderer/core/script/resources/layered_api/elements/switch/reflection.mjs b/third_party/blink/renderer/core/script/resources/layered_api/elements/switch/reflection.mjs new file mode 100644 index 0000000..989a4aa --- /dev/null +++ b/third_party/blink/renderer/core/script/resources/layered_api/elements/switch/reflection.mjs
@@ -0,0 +1,63 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** + * @file Manage attribute-property reflections. + * https://html.spec.whatwg.org/C/common-dom-interfaces.html#reflecting-content-attributes-in-idl-attributes + */ + +/** + * Add a bool reflection property to the specified prototype for the specified + * attribute. + * + * @param {!Object} proto An element prototype + * @param {string} attrName An attribute name + * @param {string} propName An optional property name. attrName will be used if + * this argument is omitted. + */ +export function installBool(proto, attrName, propName = attrName) { + let getter = function() { + return this.hasAttribute(attrName); + }; + let setter = function(value) { + this.toggleAttribute(attrName, Boolean(value)); + }; + Object.defineProperty( + getter, 'name', + {configurable: true, enumerable: false, value: 'get ' + propName}); + Object.defineProperty( + setter, 'name', + {configurable: true, enumerable: false, value: 'set ' + propName}); + Object.defineProperty( + proto, propName, + {configurable: true, enumerable: true, get: getter, set: setter}); +} + +/** + * Add a DOMString reflection property to the specified prototype for the + * specified attribute. + * + * @param {!Element} element An element prototype + * @param {string} attrName An attribute name + * @param {string} propName An optional property name. attrName will be used if + * this argument is omitted. + */ +export function installString(proto, attrName, propName = attrName) { + let getter = function() { + let value = this.getAttribute(attrName); + return value === null ? '' : value; + }; + let setter = function(value) { + this.setAttribute(attrName, value); + }; + Object.defineProperty( + getter, 'name', + {configurable: true, enumerable: false, value: 'get ' + propName}); + Object.defineProperty( + setter, 'name', + {configurable: true, enumerable: false, value: 'set ' + propName}); + Object.defineProperty( + proto, propName, + {configurable: true, enumerable: true, get: getter, set: setter}); +}
diff --git a/third_party/blink/renderer/core/script/resources/layered_api/resources.grdp b/third_party/blink/renderer/core/script/resources/layered_api/resources.grdp index 7b97d28..1c8bb89 100644 --- a/third_party/blink/renderer/core/script/resources/layered_api/resources.grdp +++ b/third_party/blink/renderer/core/script/resources/layered_api/resources.grdp
@@ -7,7 +7,9 @@ third_party/blink/public/blink_resources.grd. --> <include name="IDR_LAYERED_API_BLANK_INDEX_MJS" file="../renderer/core/script/resources/layered_api/blank/index.mjs" type="BINDATA" skip_minify="true" compress="gzip"/> + <include name="IDR_LAYERED_API_ELEMENTS_SWITCH_FACE_UTILS_MJS" file="../renderer/core/script/resources/layered_api/elements/switch/face_utils.mjs" type="BINDATA" skip_minify="true" compress="gzip"/> <include name="IDR_LAYERED_API_ELEMENTS_SWITCH_INDEX_MJS" file="../renderer/core/script/resources/layered_api/elements/switch/index.mjs" type="BINDATA" skip_minify="true" compress="gzip"/> + <include name="IDR_LAYERED_API_ELEMENTS_SWITCH_REFLECTION_MJS" file="../renderer/core/script/resources/layered_api/elements/switch/reflection.mjs" type="BINDATA" skip_minify="true" compress="gzip"/> <include name="IDR_LAYERED_API_KV_STORAGE_ASYNC_ITERATOR_MJS" file="../renderer/core/script/resources/layered_api/kv-storage/async_iterator.mjs" type="BINDATA" skip_minify="true" compress="gzip"/> <include name="IDR_LAYERED_API_KV_STORAGE_IDB_UTILS_MJS" file="../renderer/core/script/resources/layered_api/kv-storage/idb_utils.mjs" type="BINDATA" skip_minify="true" compress="gzip"/> <include name="IDR_LAYERED_API_KV_STORAGE_INDEX_MJS" file="../renderer/core/script/resources/layered_api/kv-storage/index.mjs" type="BINDATA" skip_minify="true" compress="gzip"/>
diff --git a/third_party/blink/renderer/core/script/resources/layered_api/toast/index.mjs b/third_party/blink/renderer/core/script/resources/layered_api/toast/index.mjs index d79d4e4..36d24e5e 100644 --- a/third_party/blink/renderer/core/script/resources/layered_api/toast/index.mjs +++ b/third_party/blink/renderer/core/script/resources/layered_api/toast/index.mjs
@@ -50,14 +50,14 @@ #shadow = this.attachShadow({mode: 'closed'}); #timeoutID; - constructor(message = '') { + constructor(message) { super(); this.#shadow.adoptedStyleSheets = [generateStylesheet()]; this.#shadow.innerHTML = `<slot></slot>`; - if (!this.textContent) { - this.textContent = `${message}`; + if (message !== undefined) { + this.textContent = message; } }
diff --git a/third_party/blink/renderer/core/style/computed_style_extra_fields.json5 b/third_party/blink/renderer/core/style/computed_style_extra_fields.json5 index e9af136..c0e5ab30 100644 --- a/third_party/blink/renderer/core/style/computed_style_extra_fields.json5 +++ b/third_party/blink/renderer/core/style/computed_style_extra_fields.json5
@@ -113,6 +113,14 @@ keywords: ["not-inside-link", "inside-unvisited-link", "inside-visited-link"], inherited: true, }, + // Whether we're inside an NG block fragmentation context. + { + name: "InsideNGFragmentationContext", + field_template: "primitive", + default_value: "false", + type_name: "bool", + inherited: true, + }, // Style has content property with attr() values. { name: "HasAttrContent",
diff --git a/third_party/blink/renderer/modules/background_sync/sync_manager.cc b/third_party/blink/renderer/modules/background_sync/sync_manager.cc index 8e13b62d..311b6d4 100644 --- a/third_party/blink/renderer/modules/background_sync/sync_manager.cc +++ b/third_party/blink/renderer/modules/background_sync/sync_manager.cc
@@ -53,7 +53,7 @@ auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state); ScriptPromise promise = resolver->Promise(); - GetBackgroundSyncServicePtr()->GetOneShotSyncRegistrations( + GetBackgroundSyncServicePtr()->GetRegistrations( registration_->RegistrationId(), WTF::Bind(&SyncManager::GetRegistrationsCallback, WrapPersistent(resolver))); @@ -61,7 +61,7 @@ return promise; } -const mojom::blink::BackgroundSyncServicePtr& +const mojom::blink::OneShotBackgroundSyncServicePtr& SyncManager::GetBackgroundSyncServicePtr() { if (!background_sync_service_.get()) { Platform::Current()->GetInterfaceProvider()->GetInterface( @@ -133,7 +133,7 @@ case mojom::blink::BackgroundSyncError::NOT_ALLOWED: case mojom::blink::BackgroundSyncError::PERMISSION_DENIED: // These errors should never be returned from - // BackgroundSyncManager::GetOneShotSyncRegistrations + // BackgroundSyncManager::GetRegistrations NOTREACHED(); break; case mojom::blink::BackgroundSyncError::STORAGE:
diff --git a/third_party/blink/renderer/modules/background_sync/sync_manager.h b/third_party/blink/renderer/modules/background_sync/sync_manager.h index 5eedef11..a7d5356 100644 --- a/third_party/blink/renderer/modules/background_sync/sync_manager.h +++ b/third_party/blink/renderer/modules/background_sync/sync_manager.h
@@ -39,10 +39,11 @@ enum { kUnregisteredSyncID = -1 }; private: - // Returns an initialized BackgroundSyncServicePtr. A connection with the - // the browser's BackgroundSyncService is created the first time this method - // is called. - const mojom::blink::BackgroundSyncServicePtr& GetBackgroundSyncServicePtr(); + // Returns an initialized OneShotBackgroundSyncServicePtr. A connection with + // the browser's OneShotBackgroundSyncService is created the first time this + // method is called. + const mojom::blink::OneShotBackgroundSyncServicePtr& + GetBackgroundSyncServicePtr(); // Callbacks void RegisterCallback(ScriptPromiseResolver*, @@ -55,7 +56,7 @@ Member<ServiceWorkerRegistration> registration_; scoped_refptr<base::SequencedTaskRunner> task_runner_; - mojom::blink::BackgroundSyncServicePtr background_sync_service_; + mojom::blink::OneShotBackgroundSyncServicePtr background_sync_service_; }; } // namespace blink
diff --git a/third_party/blink/renderer/modules/native_file_system/file_system_directory_handle.idl b/third_party/blink/renderer/modules/native_file_system/file_system_directory_handle.idl index ca9e5b0..02dbcf2 100644 --- a/third_party/blink/renderer/modules/native_file_system/file_system_directory_handle.idl +++ b/third_party/blink/renderer/modules/native_file_system/file_system_directory_handle.idl
@@ -4,6 +4,7 @@ // https://wicg.github.io/native-file-system/#filesystemdirectoryhandle [ + Exposed=(Window,Worker), RuntimeEnabled=NativeFileSystem, ImplementedAs=NativeFileSystemDirectoryHandle ] interface FileSystemDirectoryHandle : FileSystemHandle {
diff --git a/third_party/blink/renderer/modules/native_file_system/file_system_file_handle.idl b/third_party/blink/renderer/modules/native_file_system/file_system_file_handle.idl index e432309..bd4170e7 100644 --- a/third_party/blink/renderer/modules/native_file_system/file_system_file_handle.idl +++ b/third_party/blink/renderer/modules/native_file_system/file_system_file_handle.idl
@@ -4,6 +4,7 @@ // https://wicg.github.io/native-file-system/#filesystemfilehandle [ + Exposed=(Window,Worker), RuntimeEnabled=NativeFileSystem, ImplementedAs=NativeFileSystemFileHandle ] interface FileSystemFileHandle : FileSystemHandle {
diff --git a/third_party/blink/renderer/modules/native_file_system/file_system_handle.idl b/third_party/blink/renderer/modules/native_file_system/file_system_handle.idl index 3572ab7..c96dfd6 100644 --- a/third_party/blink/renderer/modules/native_file_system/file_system_handle.idl +++ b/third_party/blink/renderer/modules/native_file_system/file_system_handle.idl
@@ -4,6 +4,7 @@ // https://wicg.github.io/native-file-system/#filesystemhandle [ + Exposed=(Window,Worker), RuntimeEnabled=NativeFileSystem, ImplementedAs=NativeFileSystemHandle ] interface FileSystemHandle {
diff --git a/third_party/blink/renderer/modules/native_file_system/file_system_writer.idl b/third_party/blink/renderer/modules/native_file_system/file_system_writer.idl index 72a5dcb..52ebb44e 100644 --- a/third_party/blink/renderer/modules/native_file_system/file_system_writer.idl +++ b/third_party/blink/renderer/modules/native_file_system/file_system_writer.idl
@@ -4,6 +4,7 @@ // https://wicg.github.io/native-file-system/#filesystemwriter [ + Exposed=(Window,Worker), ImplementedAs=NativeFileSystemWriter, RuntimeEnabled=NativeFileSystem ] interface FileSystemWriter {
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_dtmf_sender.idl b/third_party/blink/renderer/modules/peerconnection/rtc_dtmf_sender.idl index 30ca23d..b6f8e86 100644 --- a/third_party/blink/renderer/modules/peerconnection/rtc_dtmf_sender.idl +++ b/third_party/blink/renderer/modules/peerconnection/rtc_dtmf_sender.idl
@@ -25,6 +25,7 @@ // http://w3c.github.io/webrtc-pc/#rtcdtmfsender +[Exposed=Window] interface RTCDTMFSender : EventTarget { [RaisesException] void insertDTMF(DOMString tones, optional long duration, optional long interToneGap); attribute EventHandler ontonechange;
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_dtmf_tone_change_event.idl b/third_party/blink/renderer/modules/peerconnection/rtc_dtmf_tone_change_event.idl index 0aa9bd9..69a67ae 100644 --- a/third_party/blink/renderer/modules/peerconnection/rtc_dtmf_tone_change_event.idl +++ b/third_party/blink/renderer/modules/peerconnection/rtc_dtmf_tone_change_event.idl
@@ -26,6 +26,7 @@ // https://w3c.github.io/webrtc-pc/#rtcdtmftonechangeevent [ + Exposed=Window, Constructor(DOMString type, RTCDTMFToneChangeEventInit eventInitDict) ] interface RTCDTMFToneChangeEvent : Event { readonly attribute DOMString tone;
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_error.idl b/third_party/blink/renderer/modules/peerconnection/rtc_error.idl index f4de9ac..27bb63f4 100644 --- a/third_party/blink/renderer/modules/peerconnection/rtc_error.idl +++ b/third_party/blink/renderer/modules/peerconnection/rtc_error.idl
@@ -23,6 +23,7 @@ // https://w3c.github.io/webrtc-pc/#dfn-rtcerror [ + Exposed=Window, Constructor(RTCErrorInit init, optional DOMString message = "") ] interface RTCError : DOMException { readonly attribute RTCErrorDetailType errorDetail;
diff --git a/third_party/blink/renderer/modules/webgl/webgl2_compute_rendering_context_base.idl b/third_party/blink/renderer/modules/webgl/webgl2_compute_rendering_context_base.idl index 30e42ab..694c997 100644 --- a/third_party/blink/renderer/modules/webgl/webgl2_compute_rendering_context_base.idl +++ b/third_party/blink/renderer/modules/webgl/webgl2_compute_rendering_context_base.idl
@@ -49,8 +49,6 @@ const GLenum ATOMIC_COUNTER_BARRIER_BIT = 0x00001000; const GLenum SHADER_STORAGE_BARRIER_BIT = 0x00002000; const GLenum ALL_BARRIER_BITS = 0xFFFFFFFF; - const GLenum FALSE = 0; - const GLenum TRUE = 1; const GLenum READ_ONLY = 0x88B8; const GLenum WRITE_ONLY = 0x88B9; const GLenum READ_WRITE = 0x88BA;
diff --git a/third_party/blink/renderer/platform/animation/animation_utilities.h b/third_party/blink/renderer/platform/animation/animation_utilities.h index 183f3ee..07cdcb9 100644 --- a/third_party/blink/renderer/platform/animation/animation_utilities.h +++ b/third_party/blink/renderer/platform/animation/animation_utilities.h
@@ -34,8 +34,11 @@ // Calculates the accuracy for evaluating a timing function for an animation // with the specified duration. inline double AccuracyForDuration(double duration) { - double accuracy = 1.0 / (200.0 * duration); double default_epsilon = gfx::CubicBezier::GetDefaultEpsilon(); + if (duration == 0) { + return default_epsilon; + } + double accuracy = 1.0 / (200.0 * duration); // Avoid min()/max() from std here in the header, because that would require // inclusion of <algorithm>, which is slow to compile. return accuracy > default_epsilon ? accuracy : default_epsilon;
diff --git a/third_party/blink/renderer/platform/heap/BUILD.gn b/third_party/blink/renderer/platform/heap/BUILD.gn index de7b2ef0..a9b68c0 100644 --- a/third_party/blink/renderer/platform/heap/BUILD.gn +++ b/third_party/blink/renderer/platform/heap/BUILD.gn
@@ -112,6 +112,7 @@ "heap_thread_test.cc", "heap_traits_test.cc", "incremental_marking_test.cc", + "marking_verifier_test.cc", "name_trait_test.cc", "object_start_bitmap_test.cc", "persistent_test.cc",
diff --git a/third_party/blink/renderer/platform/heap/heap_page.cc b/third_party/blink/renderer/platform/heap/heap_page.cc index 398a426..56d46af 100644 --- a/third_party/blink/renderer/platform/heap/heap_page.cc +++ b/third_party/blink/renderer/platform/heap/heap_page.cc
@@ -110,6 +110,11 @@ return gc_info->finalize; } +const char* HeapObjectHeader::Name() const { + const GCInfo* gc_info = GCInfoTable::Get().GCInfoFromIndex(GcInfoIndex()); + return gc_info->name(Payload()).value; +} + BaseArena::BaseArena(ThreadState* state, int index) : thread_state_(state), index_(index) {} @@ -573,7 +578,10 @@ // for incremental marking the application is running between steps and // might set up a new area. SetAllocationPoint(nullptr, 0); - for (BasePage* page : swept_pages_) { + DCHECK(swept_unfinalized_pages_.IsEmpty()); + DCHECK(swept_unfinalized_empty_pages_.IsEmpty()); + // There may be objects on swept_pages_ as pre-finalizers may allocate. + for (BasePage* page : unswept_pages_) { static_cast<NormalPage*>(page)->VerifyMarking(); } #endif // DCHECK_IS_ON()
diff --git a/third_party/blink/renderer/platform/heap/heap_page.h b/third_party/blink/renderer/platform/heap/heap_page.h index 8fb72ee..cb8f094 100644 --- a/third_party/blink/renderer/platform/heap/heap_page.h +++ b/third_party/blink/renderer/platform/heap/heap_page.h
@@ -235,15 +235,18 @@ // The payload starts directly after the HeapObjectHeader, and the payload // size does not include the sizeof(HeapObjectHeader). - Address Payload(); + Address Payload() const; size_t PayloadSize(); - Address PayloadEnd(); + Address PayloadEnd() const; void Finalize(Address, size_t); // Returns true if object has finalizer. bool HasNonTrivialFinalizer() const; + // Returns a human-readable name of this object. + const char* Name() const; + // Returns true if magic number is valid. bool IsValid() const; // Returns true if magic number is valid or zapped. @@ -1061,12 +1064,14 @@ #endif } -inline Address HeapObjectHeader::Payload() { - return reinterpret_cast<Address>(this) + sizeof(HeapObjectHeader); +inline Address HeapObjectHeader::Payload() const { + return reinterpret_cast<Address>(const_cast<HeapObjectHeader*>(this)) + + sizeof(HeapObjectHeader); } -inline Address HeapObjectHeader::PayloadEnd() { - return reinterpret_cast<Address>(this) + size(); +inline Address HeapObjectHeader::PayloadEnd() const { + return reinterpret_cast<Address>(const_cast<HeapObjectHeader*>(this)) + + size(); } NO_SANITIZE_ADDRESS inline size_t HeapObjectHeader::PayloadSize() {
diff --git a/third_party/blink/renderer/platform/heap/heap_test_utilities.h b/third_party/blink/renderer/platform/heap/heap_test_utilities.h index 805cfb63..e4d705e 100644 --- a/third_party/blink/renderer/platform/heap/heap_test_utilities.h +++ b/third_party/blink/renderer/platform/heap/heap_test_utilities.h
@@ -10,6 +10,7 @@ #include "base/callback.h" #include "third_party/blink/renderer/platform/heap/blink_gc.h" #include "third_party/blink/renderer/platform/heap/garbage_collected.h" +#include "third_party/blink/renderer/platform/heap/handle.h" #include "third_party/blink/renderer/platform/heap/heap.h" #include "third_party/blink/renderer/platform/heap/trace_traits.h" #include "third_party/blink/renderer/platform/heap/visitor.h" @@ -106,6 +107,22 @@ void Trace(Visitor* visitor) override { Mixin::Trace(visitor); } }; +// Simple linked object to be used in tests. +class LinkedObject : public GarbageCollected<LinkedObject> { + public: + LinkedObject() = default; + explicit LinkedObject(LinkedObject* next) : next_(next) {} + + void set_next(LinkedObject* next) { next_ = next; } + LinkedObject* next() const { return next_; } + Member<LinkedObject>& next_ref() { return next_; } + + void Trace(Visitor* visitor) { visitor->Trace(next_); } + + private: + Member<LinkedObject> next_; +}; + } // namespace blink #endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_HEAP_TEST_UTILITIES_H_
diff --git a/third_party/blink/renderer/platform/heap/incremental_marking_test.cc b/third_party/blink/renderer/platform/heap/incremental_marking_test.cc index b0cda7d..4dbe630 100644 --- a/third_party/blink/renderer/platform/heap/incremental_marking_test.cc +++ b/third_party/blink/renderer/platform/heap/incremental_marking_test.cc
@@ -221,23 +221,16 @@ std::vector<std::pair<HeapObjectHeader*, bool /* was marked */>> headers_; }; -class Object : public GarbageCollected<Object> { +class Object : public LinkedObject { public: - Object() : next_(nullptr) {} - explicit Object(Object* next) : next_(next) {} - - void set_next(Object* next) { next_ = next; } + Object() = default; + explicit Object(Object* next) : LinkedObject(next) {} bool IsMarked() const { return HeapObjectHeader::FromPayload(this)->IsMarked(); } - virtual void Trace(blink::Visitor* visitor) { visitor->Trace(next_); } - - Member<Object>& next_ref() { return next_; } - - private: - Member<Object> next_; + void Trace(Visitor* visitor) { LinkedObject::Trace(visitor); } }; // =============================================================================
diff --git a/third_party/blink/renderer/platform/heap/marking_verifier.h b/third_party/blink/renderer/platform/heap/marking_verifier.h index 567227b6..5775e19 100644 --- a/third_party/blink/renderer/platform/heap/marking_verifier.h +++ b/third_party/blink/renderer/platform/heap/marking_verifier.h
@@ -28,6 +28,7 @@ !info->has_v_table || blink::VTableInitialized(header->Payload()); if (can_verify) { CHECK(header->IsValid()); + parent_ = header; info->trace(this, header->Payload()); } } @@ -76,8 +77,23 @@ // state meaning that there are unmarked objects reachable from marked // ones. CHECK(child_header); - CHECK(child_header->IsMarked()); + if (!child_header->IsMarked()) { + // Pre-finalizers may allocate. In that case the newly allocated objects + // reside on a page that is not scheduled for sweeping. + if (PageFromObject(child_header->Payload())->HasBeenSwept()) + return; + + LOG(FATAL) + << "MarkingVerifier: Encountered unmarked object. " << std::endl + << std::endl + << "Hint (use v8_enable_raw_heap_snapshots for better naming): " + << std::endl + << parent_->Name() << std::endl + << "\\-> " << child_header->Name() << std::endl; + } } + + HeapObjectHeader* parent_ = nullptr; }; } // namespace blink
diff --git a/third_party/blink/renderer/platform/heap/marking_verifier_test.cc b/third_party/blink/renderer/platform/heap/marking_verifier_test.cc new file mode 100644 index 0000000..497c3f9 --- /dev/null +++ b/third_party/blink/renderer/platform/heap/marking_verifier_test.cc
@@ -0,0 +1,91 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "third_party/blink/renderer/platform/heap/marking_verifier.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/blink/renderer/platform/heap/handle.h" +#include "third_party/blink/renderer/platform/heap/heap.h" +#include "third_party/blink/renderer/platform/heap/heap_test_utilities.h" +#include "third_party/blink/renderer/platform/heap/persistent.h" + +namespace blink { + +namespace { + +class ResurrectingPreFinalizer + : public GarbageCollected<ResurrectingPreFinalizer> { + USING_PRE_FINALIZER(ResurrectingPreFinalizer, Dispose); + + public: + enum TestType { kMember, kWeakMember }; + + class GlobalStorage : public GarbageCollected<GlobalStorage> { + public: + void Trace(Visitor* visitor) { + visitor->Trace(strong); + visitor->Trace(weak); + } + + Member<LinkedObject> strong; + WeakMember<LinkedObject> weak; + }; + + ResurrectingPreFinalizer(TestType test_type, + GlobalStorage* storage, + LinkedObject* object_that_dies) + : test_type_(test_type), + storage_(storage), + object_that_dies_(object_that_dies) {} + + void Trace(Visitor* visitor) { + visitor->Trace(storage_); + visitor->Trace(object_that_dies_); + } + + private: + void Dispose() { + switch (test_type_) { + case TestType::kMember: + storage_->strong = object_that_dies_; + break; + case TestType::kWeakMember: + storage_->weak = object_that_dies_; + break; + } + } + + TestType test_type_; + Member<GlobalStorage> storage_; + Member<LinkedObject> object_that_dies_; +}; + +} // namespace + +TEST(MarkingVerifierDeathTest, DiesOnResurrectedMember) { + if (!ThreadState::Current()->VerifyMarkingEnabled()) + return; + + Persistent<ResurrectingPreFinalizer::GlobalStorage> storage( + MakeGarbageCollected<ResurrectingPreFinalizer::GlobalStorage>()); + MakeGarbageCollected<ResurrectingPreFinalizer>( + ResurrectingPreFinalizer::kMember, storage.Get(), + MakeGarbageCollected<LinkedObject>()); + ASSERT_DEATH_IF_SUPPORTED(PreciselyCollectGarbage(), + "MarkingVerifier: Encountered unmarked object."); +} + +TEST(MarkingVerifierDeathTest, DiesOnResurrectedWeakMember) { + if (!ThreadState::Current()->VerifyMarkingEnabled()) + return; + + Persistent<ResurrectingPreFinalizer::GlobalStorage> storage( + MakeGarbageCollected<ResurrectingPreFinalizer::GlobalStorage>()); + MakeGarbageCollected<ResurrectingPreFinalizer>( + ResurrectingPreFinalizer::kWeakMember, storage.Get(), + MakeGarbageCollected<LinkedObject>()); + ASSERT_DEATH_IF_SUPPORTED(PreciselyCollectGarbage(), + "MarkingVerifier: Encountered unmarked object."); +} + +} // namespace blink
diff --git a/third_party/blink/renderer/platform/heap/thread_state.cc b/third_party/blink/renderer/platform/heap/thread_state.cc index bca3dad..eb0747518 100644 --- a/third_party/blink/renderer/platform/heap/thread_state.cc +++ b/third_party/blink/renderer/platform/heap/thread_state.cc
@@ -802,6 +802,9 @@ Heap().Compaction()->FilterNonLiveSlots(); } + // Last point where all mark bits are present. + VerifyMarking(marking_type); + EagerSweep(); { @@ -1614,7 +1617,7 @@ deadline); } -bool ThreadState::ShouldVerifyMarking() const { +bool ThreadState::VerifyMarkingEnabled() const { bool should_verify_marking = RuntimeEnabledFeatures::HeapIncrementalMarkingStressEnabled(); #if BUILDFLAG(BLINK_HEAP_VERIFICATION) @@ -1641,9 +1644,6 @@ const size_t marked_bytes = current_gc_data_.visitor->marked_bytes(); current_gc_data_.visitor.reset(); - if (ShouldVerifyMarking()) - VerifyMarking(marking_type); - Heap().stats_collector()->NotifyMarkingCompleted(marked_bytes); WTF::Partitions::ReportMemoryUsageHistogram(); @@ -1661,12 +1661,10 @@ } void ThreadState::VerifyMarking(BlinkGC::MarkingType marking_type) { - // Marking for snapshot does not clear unreachable weak fields prohibiting - // verification of markbits as we leave behind non-marked non-cleared weak - // fields. - if (marking_type == BlinkGC::kTakeSnapshot) - return; - Heap().VerifyMarking(); + DCHECK_NE(BlinkGC::kTakeSnapshot, marking_type); + + if (VerifyMarkingEnabled()) + Heap().VerifyMarking(); } void ThreadState::CollectAllGarbageForTesting(BlinkGC::StackState stack_state) {
diff --git a/third_party/blink/renderer/platform/heap/thread_state.h b/third_party/blink/renderer/platform/heap/thread_state.h index 68137405..4e7490f 100644 --- a/third_party/blink/renderer/platform/heap/thread_state.h +++ b/third_party/blink/renderer/platform/heap/thread_state.h
@@ -426,6 +426,8 @@ // Implementation for RAILModeObserver void OnRAILModeChanged(RAILMode new_mode) override; + bool VerifyMarkingEnabled() const; + private: // Stores whether some ThreadState is currently in incremental marking. static AtomicEntryFlag incremental_marking_flag_; @@ -475,8 +477,6 @@ bool MarkPhaseAdvanceMarking(base::TimeTicks deadline); void VerifyMarking(BlinkGC::MarkingType); - bool ShouldVerifyMarking() const; - // ShouldForceConservativeGC // implements the heuristics that are used to determine when to collect // garbage.
diff --git a/third_party/blink/renderer/platform/mojo/blink_typemaps.gni b/third_party/blink/renderer/platform/mojo/blink_typemaps.gni index cd20c6f..21cb9e5 100644 --- a/third_party/blink/renderer/platform/mojo/blink_typemaps.gni +++ b/third_party/blink/renderer/platform/mojo/blink_typemaps.gni
@@ -15,6 +15,7 @@ "//third_party/blink/renderer/platform/mojo/security_origin.typemap", "//third_party/blink/renderer/platform/mojo/string.typemap", "//third_party/blink/renderer/platform/mojo/time.typemap", + "//third_party/blink/renderer/platform/network/encoded_form_data_element.typemap", "//third_party/blink/renderer/platform/network/encoded_form_data.typemap", "//third_party/blink/renderer/platform/network/http_request_headers.typemap", "//third_party/blink/public/common/manifest/display_mode.typemap",
diff --git a/third_party/blink/renderer/platform/network/BUILD.gn b/third_party/blink/renderer/platform/network/BUILD.gn index 2ef1999..2bc375f 100644 --- a/third_party/blink/renderer/platform/network/BUILD.gn +++ b/third_party/blink/renderer/platform/network/BUILD.gn
@@ -31,6 +31,8 @@ "content_security_policy_response_headers.h", "encoded_form_data.cc", "encoded_form_data.h", + "encoded_form_data_element_mojom_traits.cc", + "encoded_form_data_element_mojom_traits.h", "encoded_form_data_mojom_traits.cc", "encoded_form_data_mojom_traits.h", "form_data_encoder.cc",
diff --git a/third_party/blink/renderer/platform/network/encoded_form_data.h b/third_party/blink/renderer/platform/network/encoded_form_data.h index 65f317bf..f47b14e 100644 --- a/third_party/blink/renderer/platform/network/encoded_form_data.h +++ b/third_party/blink/renderer/platform/network/encoded_form_data.h
@@ -38,14 +38,12 @@ #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" #include "third_party/blink/renderer/platform/wtf/vector.h" -namespace network { -namespace mojom { -class URLRequestBodyDataView; -} // namespace mojom -} // namespace network - namespace blink { +namespace mojom { +class FetchAPIRequestBodyDataView; +} // namespace mojom + class BlobDataHandle; class WrappedDataPipeGetter; @@ -153,7 +151,7 @@ bool IsSafeToSendToAnotherThread() const; private: - friend struct mojo::StructTraits<network::mojom::URLRequestBodyDataView, + friend struct mojo::StructTraits<blink::mojom::FetchAPIRequestBodyDataView, scoped_refptr<blink::EncodedFormData>>; EncodedFormData(); EncodedFormData(const EncodedFormData&);
diff --git a/third_party/blink/renderer/platform/network/encoded_form_data.typemap b/third_party/blink/renderer/platform/network/encoded_form_data.typemap index 55b4887..9c35be2 100644 --- a/third_party/blink/renderer/platform/network/encoded_form_data.typemap +++ b/third_party/blink/renderer/platform/network/encoded_form_data.typemap
@@ -2,12 +2,9 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -mojom = "//services/network/public/mojom/url_loader.mojom" +mojom = "//third_party/blink/public/mojom/fetch/fetch_api_request.mojom" public_headers = [ "//third_party/blink/renderer/platform/network/encoded_form_data.h" ] traits_headers = [ "//third_party/blink/renderer/platform/network/encoded_form_data_mojom_traits.h" ] -type_mappings = [ - "network.mojom.DataElement=::blink::FormDataElement[move_only]", - "network.mojom.URLRequestBody=scoped_refptr<::blink::EncodedFormData>[nullable_is_same_type,copyable_pass_by_value]", -] +type_mappings = [ "blink.mojom.FetchAPIRequestBody=scoped_refptr<::blink::EncodedFormData>[nullable_is_same_type,copyable_pass_by_value]" ]
diff --git a/third_party/blink/renderer/platform/network/encoded_form_data_element.typemap b/third_party/blink/renderer/platform/network/encoded_form_data_element.typemap new file mode 100644 index 0000000..7ee387a --- /dev/null +++ b/third_party/blink/renderer/platform/network/encoded_form_data_element.typemap
@@ -0,0 +1,11 @@ +# Copyright 2019 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +mojom = "//services/network/public/mojom/url_loader.mojom" +public_headers = + [ "//third_party/blink/renderer/platform/network/encoded_form_data.h" ] +traits_headers = [ "//third_party/blink/renderer/platform/network/encoded_form_data_element_mojom_traits.h" ] + +type_mappings = + [ "network.mojom.DataElement=::blink::FormDataElement[move_only]" ]
diff --git a/third_party/blink/renderer/platform/network/encoded_form_data_element_mojom_traits.cc b/third_party/blink/renderer/platform/network/encoded_form_data_element_mojom_traits.cc new file mode 100644 index 0000000..0c906c9 --- /dev/null +++ b/third_party/blink/renderer/platform/network/encoded_form_data_element_mojom_traits.cc
@@ -0,0 +1,174 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <utility> + +#include "third_party/blink/renderer/platform/network/encoded_form_data_element_mojom_traits.h" + +#include "base/feature_list.h" +#include "mojo/public/cpp/base/file_mojom_traits.h" +#include "mojo/public/cpp/base/file_path_mojom_traits.h" +#include "mojo/public/cpp/base/time_mojom_traits.h" +#include "mojo/public/cpp/bindings/array_traits_wtf_vector.h" +#include "mojo/public/cpp/bindings/string_traits_wtf.h" +#include "services/network/public/cpp/features.h" +#include "services/network/public/mojom/data_pipe_getter.mojom-blink.h" +#include "third_party/blink/public/mojom/blob/blob.mojom-blink.h" +#include "third_party/blink/public/mojom/blob/blob_registry.mojom-blink.h" +#include "third_party/blink/public/platform/interface_provider.h" +#include "third_party/blink/public/platform/platform.h" +#include "third_party/blink/renderer/platform/network/wrapped_data_pipe_getter.h" + +namespace mojo { + +// static +network::mojom::DataElementType +StructTraits<network::mojom::DataElementDataView, blink::FormDataElement>::type( + const blink::FormDataElement& data) { + switch (data.type_) { + case blink::FormDataElement::kData: + return network::mojom::DataElementType::kBytes; + case blink::FormDataElement::kEncodedFile: + return network::mojom::DataElementType::kFile; + case blink::FormDataElement::kEncodedBlob: { + if (data.optional_blob_data_handle_) + return network::mojom::DataElementType::kDataPipe; + return network::mojom::DataElementType::kBlob; + } + case blink::FormDataElement::kDataPipe: + return network::mojom::DataElementType::kDataPipe; + } + NOTREACHED(); + return network::mojom::DataElementType::kUnknown; +} + +// static +base::span<const uint8_t> +StructTraits<network::mojom::DataElementDataView, blink::FormDataElement>::buf( + const blink::FormDataElement& data) { + return base::make_span(reinterpret_cast<const uint8_t*>(data.data_.data()), + data.data_.size()); +} + +// static +base::File +StructTraits<network::mojom::DataElementDataView, blink::FormDataElement>::file( + const blink::FormDataElement& data) { + return base::File(); +} + +// static +base::FilePath +StructTraits<network::mojom::DataElementDataView, blink::FormDataElement>::path( + const blink::FormDataElement& data) { + return base::FilePath::FromUTF8Unsafe(data.filename_.Utf8()); +} + +// static +network::mojom::blink::DataPipeGetterPtrInfo +StructTraits<network::mojom::DataElementDataView, blink::FormDataElement>:: + data_pipe_getter(const blink::FormDataElement& data) { + if (data.type_ == blink::FormDataElement::kDataPipe) { + if (!data.data_pipe_getter_) + return nullptr; + network::mojom::blink::DataPipeGetterPtr data_pipe_getter; + (*data.data_pipe_getter_->GetPtr()) + ->Clone(mojo::MakeRequest(&data_pipe_getter)); + return data_pipe_getter.PassInterface(); + } + if (data.type_ == blink::FormDataElement::kEncodedBlob) { + if (data.optional_blob_data_handle_) { + blink::mojom::blink::BlobPtr blob_ptr(blink::mojom::blink::BlobPtrInfo( + data.optional_blob_data_handle_->CloneBlobPtr() + .PassInterface() + .PassHandle(), + blink::mojom::blink::Blob::Version_)); + network::mojom::blink::DataPipeGetterPtr data_pipe_getter_ptr; + blob_ptr->AsDataPipeGetter(MakeRequest(&data_pipe_getter_ptr)); + return data_pipe_getter_ptr.PassInterface(); + } + } + return nullptr; +} + +// static +base::Time +StructTraits<network::mojom::DataElementDataView, blink::FormDataElement>:: + expected_modification_time(const blink::FormDataElement& data) { + if (data.type_ == blink::FormDataElement::kEncodedFile) + return base::Time::FromDoubleT(data.expected_file_modification_time_); + return base::Time(); +} + +// static +bool StructTraits<network::mojom::DataElementDataView, blink::FormDataElement>:: + Read(network::mojom::DataElementDataView data, + blink::FormDataElement* out) { + network::mojom::DataElementType data_type; + if (!data.ReadType(&data_type)) { + return false; + } + out->file_start_ = data.offset(); + out->file_length_ = data.length(); + + switch (data_type) { + case network::mojom::DataElementType::kBytes: { + out->type_ = blink::FormDataElement::kData; + // TODO(richard.li): Delete this workaround when type of + // blink::FormDataElement::data_ is changed to WTF::Vector<uint8_t> + WTF::Vector<uint8_t> buf; + if (!data.ReadBuf(&buf)) { + return false; + } + out->data_.AppendRange(buf.begin(), buf.end()); + break; + } + case network::mojom::DataElementType::kFile: { + out->type_ = blink::FormDataElement::kEncodedFile; + base::FilePath file_path; + base::Time expected_time; + if (!data.ReadPath(&file_path) || + !data.ReadExpectedModificationTime(&expected_time)) { + return false; + } + out->expected_file_modification_time_ = expected_time.ToDoubleT(); + out->filename_ = + WTF::String(file_path.value().data(), file_path.value().size()); + break; + } + case network::mojom::DataElementType::kBlob: { + // Blobs are actually passed around as kDataPipe elements when network + // service is enabled, which keeps the blobs alive. + DCHECK(!base::FeatureList::IsEnabled(network::features::kNetworkService)); + out->type_ = blink::FormDataElement::kEncodedBlob; + if (!data.ReadBlobUuid(&out->blob_uuid_)) { + return false; + } + out->optional_blob_data_handle_ = blink::BlobDataHandle::Create( + out->blob_uuid_, "" /* type is not necessary */, data.length()); + break; + } + case network::mojom::DataElementType::kDataPipe: { + out->type_ = blink::FormDataElement::kDataPipe; + auto data_pipe_ptr_info = data.TakeDataPipeGetter< + network::mojom::blink::DataPipeGetterPtrInfo>(); + DCHECK(data_pipe_ptr_info.is_valid()); + + network::mojom::blink::DataPipeGetterPtr data_pipe_getter; + data_pipe_getter.Bind(std::move(data_pipe_ptr_info)); + out->data_pipe_getter_ = + base::MakeRefCounted<blink::WrappedDataPipeGetter>( + std::move(data_pipe_getter)); + break; + } + case network::mojom::DataElementType::kUnknown: + case network::mojom::DataElementType::kChunkedDataPipe: + case network::mojom::DataElementType::kRawFile: + NOTREACHED(); + return false; + } + return true; +} + +} // namespace mojo
diff --git a/third_party/blink/renderer/platform/network/encoded_form_data_element_mojom_traits.h b/third_party/blink/renderer/platform/network/encoded_form_data_element_mojom_traits.h new file mode 100644 index 0000000..8ed20e2 --- /dev/null +++ b/third_party/blink/renderer/platform/network/encoded_form_data_element_mojom_traits.h
@@ -0,0 +1,58 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_NETWORK_ENCODED_FORM_DATA_ELEMENT_MOJOM_TRAITS_H_ +#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_NETWORK_ENCODED_FORM_DATA_ELEMENT_MOJOM_TRAITS_H_ + +#include "services/network/public/mojom/url_loader.mojom-blink.h" +#include "third_party/blink/renderer/platform/network/encoded_form_data.h" + +namespace mojo { + +template <> +struct PLATFORM_EXPORT + StructTraits<network::mojom::DataElementDataView, blink::FormDataElement> { + static network::mojom::DataElementType type( + const blink::FormDataElement& data); + + static base::span<const uint8_t> buf(const blink::FormDataElement& data); + + static base::File file(const blink::FormDataElement& data); + + static base::FilePath path(const blink::FormDataElement& data); + + static const WTF::String& blob_uuid(const blink::FormDataElement& data) { + return data.blob_uuid_; + } + + static network::mojom::blink::DataPipeGetterPtrInfo data_pipe_getter( + const blink::FormDataElement& data); + + static network::mojom::blink::ChunkedDataPipeGetterPtrInfo + chunked_data_pipe_getter(const blink::FormDataElement& data) { + return nullptr; + } + + static uint64_t offset(const blink::FormDataElement& data) { + return data.file_start_; + } + + static uint64_t length(const blink::FormDataElement& data) { + if (data.type_ == blink::FormDataElement::kEncodedBlob && + data.optional_blob_data_handle_) { + return data.optional_blob_data_handle_->size(); + } + return data.file_length_; + } + + static base::Time expected_modification_time( + const blink::FormDataElement& data); + + static bool Read(network::mojom::DataElementDataView data, + blink::FormDataElement* out); +}; + +} // namespace mojo + +#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_NETWORK_ENCODED_FORM_DATA_ELEMENT_MOJOM_TRAITS_H_
diff --git a/third_party/blink/renderer/platform/network/encoded_form_data_mojom_traits.cc b/third_party/blink/renderer/platform/network/encoded_form_data_mojom_traits.cc index ab4901e..4389fce 100644 --- a/third_party/blink/renderer/platform/network/encoded_form_data_mojom_traits.cc +++ b/third_party/blink/renderer/platform/network/encoded_form_data_mojom_traits.cc
@@ -2,180 +2,18 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include <utility> - #include "third_party/blink/renderer/platform/network/encoded_form_data_mojom_traits.h" -#include "base/feature_list.h" -#include "mojo/public/cpp/base/file_mojom_traits.h" -#include "mojo/public/cpp/base/file_path_mojom_traits.h" -#include "mojo/public/cpp/base/time_mojom_traits.h" #include "mojo/public/cpp/bindings/array_traits_wtf_vector.h" -#include "mojo/public/cpp/bindings/string_traits_wtf.h" -#include "services/network/public/cpp/features.h" -#include "services/network/public/mojom/data_pipe_getter.mojom-blink.h" -#include "third_party/blink/public/mojom/blob/blob.mojom-blink.h" -#include "third_party/blink/public/mojom/blob/blob_registry.mojom-blink.h" -#include "third_party/blink/public/platform/interface_provider.h" -#include "third_party/blink/public/platform/platform.h" +#include "third_party/blink/renderer/platform/network/encoded_form_data_element_mojom_traits.h" #include "third_party/blink/renderer/platform/network/form_data_encoder.h" -#include "third_party/blink/renderer/platform/network/wrapped_data_pipe_getter.h" namespace mojo { // static -network::mojom::DataElementType -StructTraits<network::mojom::DataElementDataView, blink::FormDataElement>::type( - const blink::FormDataElement& data) { - switch (data.type_) { - case blink::FormDataElement::kData: - return network::mojom::DataElementType::kBytes; - case blink::FormDataElement::kEncodedFile: - return network::mojom::DataElementType::kFile; - case blink::FormDataElement::kEncodedBlob: { - if (data.optional_blob_data_handle_) - return network::mojom::DataElementType::kDataPipe; - return network::mojom::DataElementType::kBlob; - } - case blink::FormDataElement::kDataPipe: - return network::mojom::DataElementType::kDataPipe; - } - NOTREACHED(); - return network::mojom::DataElementType::kUnknown; -} - -// static -base::span<const uint8_t> -StructTraits<network::mojom::DataElementDataView, blink::FormDataElement>::buf( - const blink::FormDataElement& data) { - return base::make_span(reinterpret_cast<const uint8_t*>(data.data_.data()), - data.data_.size()); -} - -// static -base::File -StructTraits<network::mojom::DataElementDataView, blink::FormDataElement>::file( - const blink::FormDataElement& data) { - return base::File(); -} - -// static -base::FilePath -StructTraits<network::mojom::DataElementDataView, blink::FormDataElement>::path( - const blink::FormDataElement& data) { - return base::FilePath::FromUTF8Unsafe(data.filename_.Utf8()); -} - -// static -network::mojom::blink::DataPipeGetterPtrInfo -StructTraits<network::mojom::DataElementDataView, blink::FormDataElement>:: - data_pipe_getter(const blink::FormDataElement& data) { - if (data.type_ == blink::FormDataElement::kDataPipe) { - if (!data.data_pipe_getter_) - return nullptr; - network::mojom::blink::DataPipeGetterPtr data_pipe_getter; - (*data.data_pipe_getter_->GetPtr()) - ->Clone(mojo::MakeRequest(&data_pipe_getter)); - return data_pipe_getter.PassInterface(); - } - if (data.type_ == blink::FormDataElement::kEncodedBlob) { - if (data.optional_blob_data_handle_) { - blink::mojom::blink::BlobPtr blob_ptr(blink::mojom::blink::BlobPtrInfo( - data.optional_blob_data_handle_->CloneBlobPtr() - .PassInterface() - .PassHandle(), - blink::mojom::blink::Blob::Version_)); - network::mojom::blink::DataPipeGetterPtr data_pipe_getter_ptr; - blob_ptr->AsDataPipeGetter(MakeRequest(&data_pipe_getter_ptr)); - return data_pipe_getter_ptr.PassInterface(); - } - } - return nullptr; -} - -// static -base::Time -StructTraits<network::mojom::DataElementDataView, blink::FormDataElement>:: - expected_modification_time(const blink::FormDataElement& data) { - if (data.type_ == blink::FormDataElement::kEncodedFile) - return base::Time::FromDoubleT(data.expected_file_modification_time_); - return base::Time(); -} - -// static -bool StructTraits<network::mojom::DataElementDataView, blink::FormDataElement>:: - Read(network::mojom::DataElementDataView data, - blink::FormDataElement* out) { - network::mojom::DataElementType data_type; - if (!data.ReadType(&data_type)) { - return false; - } - out->file_start_ = data.offset(); - out->file_length_ = data.length(); - - switch (data_type) { - case network::mojom::DataElementType::kBytes: { - out->type_ = blink::FormDataElement::kData; - // TODO(richard.li): Delete this workaround when type of - // blink::FormDataElement::data_ is changed to WTF::Vector<uint8_t> - WTF::Vector<uint8_t> buf; - if (!data.ReadBuf(&buf)) { - return false; - } - out->data_.AppendRange(buf.begin(), buf.end()); - break; - } - case network::mojom::DataElementType::kFile: { - out->type_ = blink::FormDataElement::kEncodedFile; - base::FilePath file_path; - base::Time expected_time; - if (!data.ReadPath(&file_path) || - !data.ReadExpectedModificationTime(&expected_time)) { - return false; - } - out->expected_file_modification_time_ = expected_time.ToDoubleT(); - out->filename_ = - WTF::String(file_path.value().data(), file_path.value().size()); - break; - } - case network::mojom::DataElementType::kBlob: { - // Blobs are actually passed around as kDataPipe elements when network - // service is enabled, which keeps the blobs alive. - DCHECK(!base::FeatureList::IsEnabled(network::features::kNetworkService)); - out->type_ = blink::FormDataElement::kEncodedBlob; - if (!data.ReadBlobUuid(&out->blob_uuid_)) { - return false; - } - out->optional_blob_data_handle_ = blink::BlobDataHandle::Create( - out->blob_uuid_, "" /* type is not necessary */, data.length()); - break; - } - case network::mojom::DataElementType::kDataPipe: { - out->type_ = blink::FormDataElement::kDataPipe; - auto data_pipe_ptr_info = data.TakeDataPipeGetter< - network::mojom::blink::DataPipeGetterPtrInfo>(); - DCHECK(data_pipe_ptr_info.is_valid()); - - network::mojom::blink::DataPipeGetterPtr data_pipe_getter; - data_pipe_getter.Bind(std::move(data_pipe_ptr_info)); - out->data_pipe_getter_ = - base::MakeRefCounted<blink::WrappedDataPipeGetter>( - std::move(data_pipe_getter)); - break; - } - case network::mojom::DataElementType::kUnknown: - case network::mojom::DataElementType::kChunkedDataPipe: - case network::mojom::DataElementType::kRawFile: - NOTREACHED(); - return false; - } - return true; -} - -// static -bool StructTraits<network::mojom::URLRequestBodyDataView, +bool StructTraits<blink::mojom::FetchAPIRequestBodyDataView, scoped_refptr<blink::EncodedFormData>>:: - Read(network::mojom::URLRequestBodyDataView in, + Read(blink::mojom::FetchAPIRequestBodyDataView in, scoped_refptr<blink::EncodedFormData>* out) { *out = blink::EncodedFormData::Create(); if (!in.ReadElements(&((*out)->elements_))) {
diff --git a/third_party/blink/renderer/platform/network/encoded_form_data_mojom_traits.h b/third_party/blink/renderer/platform/network/encoded_form_data_mojom_traits.h index c2aed21..0a403da6 100644 --- a/third_party/blink/renderer/platform/network/encoded_form_data_mojom_traits.h +++ b/third_party/blink/renderer/platform/network/encoded_form_data_mojom_traits.h
@@ -5,58 +5,13 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_NETWORK_ENCODED_FORM_DATA_MOJOM_TRAITS_H_ #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_NETWORK_ENCODED_FORM_DATA_MOJOM_TRAITS_H_ -#include <string> - -#include "services/network/public/mojom/url_loader.mojom-blink.h" +#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink.h" #include "third_party/blink/renderer/platform/network/encoded_form_data.h" namespace mojo { template <> -struct PLATFORM_EXPORT - StructTraits<network::mojom::DataElementDataView, blink::FormDataElement> { - static network::mojom::DataElementType type( - const blink::FormDataElement& data); - - static base::span<const uint8_t> buf(const blink::FormDataElement& data); - - static base::File file(const blink::FormDataElement& data); - - static base::FilePath path(const blink::FormDataElement& data); - - static const WTF::String& blob_uuid(const blink::FormDataElement& data) { - return data.blob_uuid_; - } - - static network::mojom::blink::DataPipeGetterPtrInfo data_pipe_getter( - const blink::FormDataElement& data); - - static network::mojom::blink::ChunkedDataPipeGetterPtrInfo - chunked_data_pipe_getter(const blink::FormDataElement& data) { - return nullptr; - } - - static uint64_t offset(const blink::FormDataElement& data) { - return data.file_start_; - } - - static uint64_t length(const blink::FormDataElement& data) { - if (data.type_ == blink::FormDataElement::kEncodedBlob && - data.optional_blob_data_handle_) { - return data.optional_blob_data_handle_->size(); - } - return data.file_length_; - } - - static base::Time expected_modification_time( - const blink::FormDataElement& data); - - static bool Read(network::mojom::DataElementDataView data, - blink::FormDataElement* out); -}; - -template <> -struct PLATFORM_EXPORT StructTraits<network::mojom::URLRequestBodyDataView, +struct PLATFORM_EXPORT StructTraits<blink::mojom::FetchAPIRequestBodyDataView, scoped_refptr<blink::EncodedFormData>> { static bool IsNull(const scoped_refptr<blink::EncodedFormData>& data) { return !data; @@ -76,7 +31,7 @@ return data->contains_password_data_; } - static bool Read(network::mojom::URLRequestBodyDataView in, + static bool Read(blink::mojom::FetchAPIRequestBodyDataView in, scoped_refptr<blink::EncodedFormData>* out); };
diff --git a/third_party/blink/renderer/platform/network/encoded_form_data_test.cc b/third_party/blink/renderer/platform/network/encoded_form_data_test.cc index c71f053..31cbbcd 100644 --- a/third_party/blink/renderer/platform/network/encoded_form_data_test.cc +++ b/third_party/blink/renderer/platform/network/encoded_form_data_test.cc
@@ -15,6 +15,7 @@ #include "services/network/public/mojom/url_loader.mojom-blink.h" #include "third_party/blink/public/mojom/blob/blob.mojom-blink.h" #include "third_party/blink/renderer/platform/network/encoded_form_data.h" +#include "third_party/blink/renderer/platform/network/encoded_form_data_element_mojom_traits.h" #include "third_party/blink/renderer/platform/network/encoded_form_data_mojom_traits.h" #include "third_party/blink/renderer/platform/network/wrapped_data_pipe_getter.h" @@ -174,7 +175,7 @@ original1->SetContainsPasswordData(true); scoped_refptr<EncodedFormData> copied1 = EncodedFormData::Create(); EXPECT_TRUE(mojo::test::SerializeAndDeserialize< - network::mojom::blink::URLRequestBody>(&original1, &copied1)); + blink::mojom::blink::FetchAPIRequestBody>(&original1, &copied1)); EXPECT_EQ(original1->Identifier(), copied1->Identifier()); EXPECT_EQ(original1->ContainsPasswordData(), copied1->ContainsPasswordData()); }
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations index cdceabcf..95ca9054 100644 --- a/third_party/blink/web_tests/TestExpectations +++ b/third_party/blink/web_tests/TestExpectations
@@ -1375,7 +1375,6 @@ crbug.com/797591 virtual/layout_ng_experimental/fast/multicol/newmulticol/regular-block-becomes-multicol.html [ Failure ] ### Missing refs, these are also skipped for existing layout. -crbug.com/829028 virtual/layout_ng_experimental/external/wpt/css/css-multicol/balance-table-with-fractional-height-row.html [ Failure ] crbug.com/967329 virtual/layout_ng_experimental/external/wpt/css/css-multicol/columnfill-auto-max-height-002.html [ Failure ] crbug.com/967329 virtual/layout_ng_experimental/external/wpt/css/css-multicol/columnfill-auto-max-height-001.html [ Failure ] crbug.com/829028 virtual/layout_ng_experimental/external/wpt/css/css-multicol/filter-with-abspos.html [ Failure ] @@ -1517,10 +1516,6 @@ crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-multicol/multicol-span-all-margin-nested-firstchild-001.xht [ Failure ] crbug.com/792446 virtual/layout_ng_experimental/external/wpt/css/css-multicol/multicol-span-float-001.xht [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-multicol/multicol-span-none-001.xht [ Failure ] -crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-multicol/multicol-table-cell-001.xht [ Failure ] -crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-multicol/multicol-table-cell-height-001.xht [ Failure ] -crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-multicol/multicol-table-cell-height-002.xht [ Failure ] -crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-multicol/multicol-table-cell-vertical-align-001.xht [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-multicol/multicol-under-vertical-rl-scroll.html [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-multicol/multicol-width-001.xht [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-multicol/multicol-width-002.xht [ Failure ] @@ -1546,8 +1541,6 @@ crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/balance-line-overflow.html [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/balance-line-underflow-1.html [ Crash ] crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/balance-line-underflow-2.html [ Failure ] -crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/balance-repeating-table-headers.html [ Failure ] -crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/balance-table-with-border-spacing.html [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/basic-rtl.html [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/break-before-first-line-in-first-child.html [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/break-in-scrollable.html [ Failure ] @@ -1558,10 +1551,10 @@ crbug.com/714962 virtual/layout_ng_experimental/fast/multicol/change-height.html [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/client-rect-after-spanner.html [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/client-rect-nested.html [ Failure ] -crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/client-rects-crossing-boundaries.html [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/client-rects-crossing-boundaries-nested.html [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/client-rects.html [ Crash Failure ] crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/client-rects-rtl.html [ Crash Failure ] +crbug.com/829028 virtual/layout_ng_experimental/fast/multicol/clone-block-children-inline-mismatch-crash.html [ Crash ] crbug.com/874506 virtual/layout_ng_experimental/fast/multicol/column-break-with-balancing.html [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/column-count-with-rules.html [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/column-rules.html [ Failure ] @@ -1628,7 +1621,6 @@ crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/first-line-in-float-below-next-column-top.html [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/first-line-in-float-with-margin.html [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/fixedpos-child-becomes-static.html [ Failure ] -crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/flexbox.html [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/flipped-blocks-border-after.html [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/flipped-blocks-hit-test.html [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/float-after-break-after.html [ Failure ] @@ -1652,7 +1644,6 @@ crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/forced-break-after-last-block-before-spanner.html [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/forced-break-in-nested-columns.html [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/forced-break-too-short-column.html [ Failure ] -crbug.com/874506 virtual/layout_ng_experimental/fast/multicol/foreignObject.html [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/hit-test-above-or-below.html [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/hit-test-end-of-column.html [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/hit-test-end-of-column-with-line-height.html [ Crash Failure ] @@ -1661,8 +1652,6 @@ crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/inline-block-baseline.html [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/inline-getclientrects.html [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/inner-multicol-in-second-column.html [ Failure ] -crbug.com/714962 virtual/layout_ng_experimental/fast/multicol/input-type-number.html [ Failure ] -crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/input-with-overflow-second-column.html [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/insane-column-gap.html [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/layers-in-multicol.html [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/line-in-next-row-in-fourth-inner-multicol.html [ Failure ] @@ -1671,7 +1660,6 @@ crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/many-lines-overflow-in-single-row-inner.html [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/mixed-opacity-test.html [ Crash ] crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/mixed-positioning-stacking-order.html [ Failure ] -crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/multicol-with-child-renderLayer-for-input.html [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/nested-3-multicols-fixed-height.html [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/nested-auto-height-extra-block-inbetween.html [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/nested-auto-height.html [ Failure ] @@ -1708,7 +1696,6 @@ crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/newmulticol/hide-box-vertical-rl.html [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/newmulticol/list-item.html [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/newmulticol/orphans-and-widows-balance.html [ Failure ] -crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/newmulticol/table-cell.html [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/outlines-at-column-boundaries.html [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/out-of-flow/abspos-auto-position.html [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/out-of-flow/abspos-auto-position-on-line-at-boundary.html [ Failure ] @@ -1776,6 +1763,7 @@ crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/span/overflow-on-multicol.html [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/span/overflow-on-viewport.html [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/span/percent-margins.html [ Failure ] +crbug.com/829028 virtual/layout_ng_experimental/fast/multicol/span/positioned-objects-not-removed-crash.html [ Crash ] crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/span/preferred-widths-with-column-content.html [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/span/pseudo-after.html [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/span/pseudo-after-then-content.html [ Failure ] @@ -1793,11 +1781,9 @@ crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/span/spanner-first.html [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/span/spanner-img.html [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/span/spanner-last.html [ Failure ] -crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/span/spanner-table.html [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/span/spanner-with-margin.html [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/span/spanner-with-margins-between-margins.html [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/span/spanner-with-relpos-child.html [ Failure ] -crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/span/summary-split.html [ Failure ] crbug.com/824918 virtual/layout_ng_experimental/fast/multicol/span/trailing-margin-around-spanner.html [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/span/trailing-margin-before-spanner.html [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/span/two-rows-then-spanner-then-two-rows.html [ Failure ] @@ -1808,8 +1794,6 @@ crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/static-child-becomes-fixedpos.html [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/svg-change-column-crash.html [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/table-cell-content-change.html [ Failure ] -crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/table-cell-content-change-with-decorations.html [ Failure ] -crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/table-margin-collapse.html [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/tall-content-in-inner-with-fixed-height.html [ Failure ] crbug.com/829028 virtual/layout_ng_experimental/fast/multicol/tall-float1.html [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/tall-float2.html [ Failure ] @@ -1872,12 +1856,7 @@ crbug.com/591099 virtual/layout_ng_experimental/fragmentation/become-unfragmented-with-lines.html [ Crash Pass ] crbug.com/591099 virtual/layout_ng_experimental/fragmentation/become-unfragmented-with-unbreakable-blocks.html [ Crash Pass ] crbug.com/591099 virtual/layout_ng_experimental/fragmentation/block-after-float-first-child.html [ Failure ] -crbug.com/591099 virtual/layout_ng_experimental/fragmentation/border-spacing-break-before-unbreakable-row.html [ Failure ] -crbug.com/591099 virtual/layout_ng_experimental/fragmentation/break-in-first-table-row-only.html [ Failure ] -crbug.com/591099 virtual/layout_ng_experimental/fragmentation/break-in-second-table-section.html [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/fragmentation/break-inside-avoid-with-forced-break.html [ Failure ] -crbug.com/591099 virtual/layout_ng_experimental/fragmentation/break-in-tbody-after-caption.html [ Failure ] -crbug.com/591099 virtual/layout_ng_experimental/fragmentation/cells-dont-fit-on-page-paginated.html [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/fragmentation/change-fragmentainer-height-block-float-2.html [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/fragmentation/change-fragmentainer-height-block-float.html [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/fragmentation/change-fragmentainer-height-inline-float.html [ Failure ] @@ -1888,82 +1867,16 @@ crbug.com/591099 virtual/layout_ng_experimental/fragmentation/float-pushed-to-next-fragmentainer-by-floats.html [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/fragmentation/forced-break-clearance-unsplittable-content.html [ Failure ] crbug.com/829028 virtual/layout_ng_experimental/fragmentation/forced-break-inside-float.html [ Failure ] -crbug.com/591099 virtual/layout_ng_experimental/fragmentation/fragmented-rowspan-alignment.html [ Failure ] -crbug.com/591099 virtual/layout_ng_experimental/fragmentation/fragmented-rowspan.html [ Failure ] -crbug.com/591099 virtual/layout_ng_experimental/fragmentation/fragmented-table-cell.html [ Failure ] -crbug.com/591099 virtual/layout_ng_experimental/fragmentation/fragmented-table-with-fixed-height.html [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/fragmentation/image-block-as-first-child.html [ Failure ] -crbug.com/591099 virtual/layout_ng_experimental/fragmentation/multi-line-cells.html [ Failure ] -crbug.com/591099 virtual/layout_ng_experimental/fragmentation/multi-line-cells-paginated.html [ Failure ] -crbug.com/591099 virtual/layout_ng_experimental/fragmentation/nested-repeating-thead-2.html [ Failure ] -crbug.com/591099 virtual/layout_ng_experimental/fragmentation/nested-repeating-thead-3.html [ Failure ] -crbug.com/591099 virtual/layout_ng_experimental/fragmentation/nested-repeating-thead-4.html [ Failure ] -crbug.com/591099 virtual/layout_ng_experimental/fragmentation/nested-repeating-thead-tfoot-4.html [ Failure ] -crbug.com/591099 virtual/layout_ng_experimental/fragmentation/nested-repeating-thead-tfoot.html [ Failure ] -crbug.com/829028 virtual/layout_ng_experimental/fragmentation/no-repeating-table-header-after-sections.html [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/fragmentation/overflow-crossing-boundary.html [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/fragmentation/relayout-abspos.html [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/fragmentation/remove-unbreakable-block-in-line-float.html [ Failure ] -crbug.com/591099 virtual/layout_ng_experimental/fragmentation/repeating-thead-exceeds-page-size.html [ Failure ] -crbug.com/591099 virtual/layout_ng_experimental/fragmentation/repeating-thead-multiple-tables.html [ Failure ] -crbug.com/591099 virtual/layout_ng_experimental/fragmentation/repeating-thead-multiple-tables-page-border.html [ Failure ] -crbug.com/591099 virtual/layout_ng_experimental/fragmentation/repeating-thead-no-room-for-content-row-on-first-page.html [ Failure ] -crbug.com/591099 virtual/layout_ng_experimental/fragmentation/repeating-thead-tfoot-different-fragment-height.html [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/fragmentation/repeating-thead-under-repeating-thead.html [ Failure ] -crbug.com/591099 virtual/layout_ng_experimental/fragmentation/single-cell-repeating-thead-break-inside-avoid-content.html [ Failure ] -crbug.com/591099 virtual/layout_ng_experimental/fragmentation/single-cell-repeating-thead-break-inside-content-first-line.html [ Failure ] -crbug.com/591099 virtual/layout_ng_experimental/fragmentation/single-cell-repeating-thead-break-inside-content.html [ Failure ] -crbug.com/591099 virtual/layout_ng_experimental/fragmentation/single-cells-multiple-tables-no-repeating-thead.html [ Failure ] -crbug.com/591099 virtual/layout_ng_experimental/fragmentation/single-large-cell-with-header.html [ Failure ] -crbug.com/591099 virtual/layout_ng_experimental/fragmentation/single-line-cells.html [ Failure ] -crbug.com/591099 virtual/layout_ng_experimental/fragmentation/single-line-cells-in-multiple-table-sections.html [ Failure ] -crbug.com/591099 virtual/layout_ng_experimental/fragmentation/single-line-cells-multiple-tables-caption-repeating-thead-tfoot-with-border-spacing-at-top-of-row-2.html [ Crash ] -crbug.com/591099 virtual/layout_ng_experimental/fragmentation/single-line-cells-multiple-tables-caption-repeating-thead-tfoot-with-border-spacing-at-top-of-row-3.html [ Crash ] -crbug.com/591099 virtual/layout_ng_experimental/fragmentation/single-line-cells-multiple-tables-caption-repeating-thead-tfoot-with-border-spacing-at-top-of-row-4.html [ Failure ] -crbug.com/591099 virtual/layout_ng_experimental/fragmentation/single-line-cells-multiple-tables-caption-repeating-thead-tfoot-with-border-spacing-at-top-of-row.html [ Failure ] -crbug.com/591099 virtual/layout_ng_experimental/fragmentation/single-line-cells-nested-repeating-thead-2.html [ Failure ] -crbug.com/591099 virtual/layout_ng_experimental/fragmentation/single-line-cells-nested-repeating-thead-3.html [ Failure ] -crbug.com/591099 virtual/layout_ng_experimental/fragmentation/single-line-cells-nested-repeating-thead-4.html [ Failure ] -crbug.com/591099 virtual/layout_ng_experimental/fragmentation/single-line-cells-nested-repeating-thead.html [ Failure ] -crbug.com/591099 virtual/layout_ng_experimental/fragmentation/single-line-cells-nested-repeating-thead-nested-repeating-tfoot.html [ Failure ] -crbug.com/591099 virtual/layout_ng_experimental/fragmentation/single-line-cells-nested-repeating-thead-tfoot-2.html [ Failure ] -crbug.com/591099 virtual/layout_ng_experimental/fragmentation/single-line-cells-nested-repeating-thead-tfoot-3.html [ Failure ] -crbug.com/591099 virtual/layout_ng_experimental/fragmentation/single-line-cells-nested-repeating-thead-tfoot-4.html [ Failure ] -crbug.com/591099 virtual/layout_ng_experimental/fragmentation/single-line-cells-nested-repeating-thead-tfoot.html [ Failure ] -crbug.com/591099 virtual/layout_ng_experimental/fragmentation/single-line-cells-paginated.html [ Failure ] -crbug.com/591099 virtual/layout_ng_experimental/fragmentation/single-line-cells-paginated-with-text.html [ Failure ] -crbug.com/591099 virtual/layout_ng_experimental/fragmentation/single-line-cells-repeating-tfoot-rows-allowing-break.html [ Failure ] -crbug.com/591099 virtual/layout_ng_experimental/fragmentation/single-line-cells-repeating-thead-cell-straddles-page.html [ Failure ] -crbug.com/591099 virtual/layout_ng_experimental/fragmentation/single-line-cells-repeating-thead-cell-straddles-page-unsplittable-div.html [ Failure ] -crbug.com/591099 virtual/layout_ng_experimental/fragmentation/single-line-cells-repeating-thead.html [ Failure ] -crbug.com/591099 virtual/layout_ng_experimental/fragmentation/single-line-cells-repeating-thead-starts-middle-of-page-break-after-avoid-2.html [ Crash ] -crbug.com/591099 virtual/layout_ng_experimental/fragmentation/single-line-cells-repeating-thead-starts-middle-of-page-break-after-avoid-3.html [ Failure ] -crbug.com/591099 virtual/layout_ng_experimental/fragmentation/single-line-cells-repeating-thead-starts-middle-of-page-break-after-avoid.html [ Failure ] -crbug.com/591099 virtual/layout_ng_experimental/fragmentation/single-line-cells-repeating-thead-starts-middle-of-page.html [ Failure ] -crbug.com/591099 virtual/layout_ng_experimental/fragmentation/single-line-cells-repeating-thead-tfoot.html [ Failure ] -crbug.com/591099 virtual/layout_ng_experimental/fragmentation/single-line-cells-repeating-thead-tfoot-starts-middle-of-page-break-after-avoid-2.html [ Failure ] -crbug.com/591099 virtual/layout_ng_experimental/fragmentation/single-line-cells-repeating-thead-tfoot-starts-middle-of-page-break-after-avoid-3.html [ Failure ] -crbug.com/591099 virtual/layout_ng_experimental/fragmentation/single-line-cells-repeating-thead-tfoot-starts-middle-of-page-break-after-avoid.html [ Failure ] -crbug.com/591099 virtual/layout_ng_experimental/fragmentation/single-line-cells-repeating-thead-tfoot-starts-middle-of-page.html [ Failure ] -crbug.com/591099 virtual/layout_ng_experimental/fragmentation/single-line-cells-repeating-thead-tfoot-with-border-spacing-at-top-of-row.html [ Crash ] -crbug.com/591099 virtual/layout_ng_experimental/fragmentation/single-line-cells-repeating-thead-tfoot-with-caption.html [ Failure ] -crbug.com/591099 virtual/layout_ng_experimental/fragmentation/single-line-cells-repeating-thead-tfoot-with-two-captions.html [ Failure ] -crbug.com/591099 virtual/layout_ng_experimental/fragmentation/single-line-cells-repeating-thead-with-border-spacing-at-top-of-row.html [ Crash ] -crbug.com/591099 virtual/layout_ng_experimental/fragmentation/single-line-cells-repeating-thead-with-caption.html [ Failure ] -crbug.com/591099 virtual/layout_ng_experimental/fragmentation/single-line-cells-repeating-thead-with-two-captions.html [ Failure ] -crbug.com/591099 virtual/layout_ng_experimental/fragmentation/table-in-subpixel-fragmentainer.html [ Failure ] -crbug.com/591099 virtual/layout_ng_experimental/fragmentation/table-overlapping-rowspan.html [ Failure ] -crbug.com/591099 virtual/layout_ng_experimental/fragmentation/table-row-dimensions-break-freely.html [ Failure ] -crbug.com/591099 virtual/layout_ng_experimental/fragmentation/table-row-dimensions.html [ Failure ] -crbug.com/591099 virtual/layout_ng_experimental/fragmentation/table-row-dimensions-with-thead.html [ Failure ] -crbug.com/591099 virtual/layout_ng_experimental/fragmentation/table-row-page-break-collapsed-border.html [ Failure ] -crbug.com/591099 virtual/layout_ng_experimental/fragmentation/thead-under-repeating-thead.html [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/fragmentation/unbreakable-tall-float-before-block.html [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/fragmentation/unbreakable-tall-float-before-line.html [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/printing/absolute-positioned.html [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/printing/absolute-position-headers-and-footers.html [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/printing/allowed-page-breaks.html [ Failure ] -crbug.com/591099 virtual/layout_ng_experimental/printing/composited-thead-tfoot-repeat.html [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/printing/css2.1/page-break-after-000.html [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/printing/css2.1/page-break-after-002.html [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/printing/css2.1/page-break-after-003.html [ Failure ] @@ -1995,12 +1908,6 @@ crbug.com/591099 virtual/layout_ng_experimental/printing/respect-layout-overflow-from-pagination.html [ Failure ] crbug.com/824918 virtual/layout_ng_experimental/printing/setPrinting.html [ Failure ] crbug.com/829028 virtual/layout_ng_experimental/printing/single-line-must-not-be-split-into-two-pages.html [ Failure ] -crbug.com/591099 virtual/layout_ng_experimental/printing/tfoot-repeats-at-bottom-of-each-page-multiple-tables.html [ Failure ] -crbug.com/591099 virtual/layout_ng_experimental/printing/thead-repeat-in-nested-table.html [ Failure ] -crbug.com/591099 virtual/layout_ng_experimental/printing/thead-repeats-at-top-of-each-page.html [ Failure ] -crbug.com/591099 virtual/layout_ng_experimental/printing/thead-repeats-at-top-of-each-page-multiple-tables.html [ Failure ] -crbug.com/591099 virtual/layout_ng_experimental/printing/thead-repeats-with-translucent-text-and-borders.html [ Failure ] -crbug.com/591099 virtual/layout_ng_experimental/printing/thead-under-multicol.html [ Failure ] crbug.com/829804 virtual/layout_ng_experimental/printing/webgl-oversized-printing.html [ Skip ] crbug.com/824918 virtual/layout_ng_experimental/printing/width-overflow.html [ Failure ] Bug(none) virtual/layout_ng_experimental/fragmentation/scrolling-contents-scroll.html [ Crash Failure ] @@ -3310,6 +3217,8 @@ crbug.com/968164 external/wpt/css/css-ui/webkit-appearance-menulist-button-001.html [ Failure ] # ====== New tests from wpt-importer added here ====== +crbug.com/626703 [ Mac10.12 ] external/wpt/webaudio/the-audio-api/the-mediaelementaudiosourcenode-interface/mediaElementAudioSourceToScriptProcessorTest.html [ Timeout ] +crbug.com/626703 [ Mac10.12 ] external/wpt/html/semantics/embedded-content/media-elements/track/track-element/track-mode.html [ Timeout ] crbug.com/626703 [ Mac10.12 ] external/wpt/html/semantics/embedded-content/media-elements/ready-states/autoplay-hidden.optional.html [ Timeout ] crbug.com/626703 [ Mac10.12 ] external/wpt/html/semantics/embedded-content/media-elements/track/track-element/track-cue-negative-timestamp-events.html [ Timeout ] crbug.com/626703 external/wpt/webvtt/rendering/cues-with-video/processing-model/bidi/start_alignment.html [ Failure ] @@ -6152,7 +6061,6 @@ # Sheriff 2019-05-20 crbug.com/963739 [ Fuchsia ] synthetic_gestures/smooth-scroll-tiny-delta.html [ Pass Timeout ] -crbug.com/964158 [ Linux ] external/wpt/payment-handler/change-payment-method.https.html [ Pass Crash ] crbug.com/964239 external/wpt/css/css-scroll-snap/scroll-margin.html [ Pass Failure ] crbug.com/965389 [ Mac ] media/track/track-cue-rendering-position-auto.html [ Pass Failure ] @@ -6237,16 +6145,14 @@ crbug.com/973769 [ Linux ] http/tests/media/video-seek-to-middle.html [ Pass Failure ] crbug.com/973769 [ Linux ] media/controls/controls-cast-do-not-fade-out.html [ Pass Timeout ] crbug.com/973769 [ Linux ] media/video-pause-immediately.html [ Pass Failure ] -crbug.com/973769 [ Linux ] media/video-played-ranges-1.html [ Pass Failure ] -crbug.com/973769 [ Linux ] media/video-played-reset.html [ Pass Failure ] crbug.com/973769 [ Linux ] media/W3C/audio/events/event_timeupdate_manual.html [ Pass Failure ] # Flaky on Linux crbug.com/974660 [ Linux ] http/tests/devtools/elements/highlight/highlight-node-vertical-rl.js [ Pass Failure ] -# Failing on windows with lazy-feedback-allocation feature in V8. See the bug -# for more details. -crbug.com/976587 [ Win Mac ] netinfo/gc-unused-listeners.html [ Pass Failure ] +# Failing with lazy-feedback-allocation feature in V8. See the bug for more +# details. +crbug.com/976587 netinfo/gc-unused-listeners.html [ Pass Failure ] # TODO (michaelludwig): Remove after Skia roll and rebaseline crbug.com/976743 virtual/gpu-rasterization/images/color-profile-background-image-cover.html [ Pass Failure ]
diff --git a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_6.json b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_6.json index be5080b..0f85382b 100644 --- a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_6.json +++ b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_6.json
@@ -6211,6 +6211,18 @@ {} ] ], + "payment-handler/change-payment-method-manual.https.html": [ + [ + "payment-handler/change-payment-method-manual.https.html", + {} + ] + ], + "payment-handler/payment-request-event-manual.https.html": [ + [ + "payment-handler/payment-request-event-manual.https.html", + {} + ] + ], "payment-method-basic-card/empty-data-manual.https.html": [ [ "payment-method-basic-card/empty-data-manual.https.html", @@ -42667,6 +42679,18 @@ {} ] ], + "css/css-flexbox/flex-minimum-height-flex-items-015.html": [ + [ + "css/css-flexbox/flex-minimum-height-flex-items-015.html", + [ + [ + "/css/reference/ref-filled-green-100px-square.xht", + "==" + ] + ], + {} + ] + ], "css/css-flexbox/flex-minimum-width-flex-items-001.xht": [ [ "css/css-flexbox/flex-minimum-width-flex-items-001.xht", @@ -97775,6 +97799,18 @@ {} ] ], + "css/filter-effects/backdrop-filter-plus-mask.html": [ + [ + "css/filter-effects/backdrop-filter-plus-mask.html", + [ + [ + "/css/filter-effects/backdrop-filter-plus-mask-ref.html", + "==" + ] + ], + {} + ] + ], "css/filter-effects/backdrop-filter-reference-filter.html": [ [ "css/filter-effects/backdrop-filter-reference-filter.html", @@ -138644,9 +138680,6 @@ "css/css-shapes/spec-examples/reference/shape-outside-008-ref.html": [ [] ], - "css/css-shapes/spec-examples/shape-outside-018-expected.txt": [ - [] - ], "css/css-shapes/spec-examples/support/circle-no-shadow.png": [ [] ], @@ -142442,6 +142475,15 @@ "css/css-ui/appearance-cssom-001-expected.txt": [ [] ], + "css/css-ui/appearance-parsing-expected.txt": [ + [] + ], + "css/css-ui/appearance-property-expected.txt": [ + [] + ], + "css/css-ui/appearance-serialization-expected.txt": [ + [] + ], "css/css-ui/inheritance-expected.txt": [ [] ], @@ -143285,6 +143327,15 @@ "css/css-ui/tools/appearance-build-webkit-reftests.py": [ [] ], + "css/css-ui/webkit-appearance-parsing-expected.txt": [ + [] + ], + "css/css-ui/webkit-appearance-property-expected.txt": [ + [] + ], + "css/css-ui/webkit-appearance-serialization-expected.txt": [ + [] + ], "css/css-values/META.yml": [ [] ], @@ -145685,6 +145736,9 @@ "css/filter-effects/backdrop-filter-plus-filter-ref.html": [ [] ], + "css/filter-effects/backdrop-filter-plus-mask-ref.html": [ + [] + ], "css/filter-effects/backdrop-filter-update-ref.html": [ [] ], @@ -161342,6 +161396,9 @@ "payment-handler/payment-request-event-constructor.https.serviceworker.js": [ [] ], + "payment-handler/payment-request-event-manual.https-expected.txt": [ + [] + ], "payment-handler/payment-request-event.https-expected.txt": [ [] ], @@ -166529,33 +166586,18 @@ "subresource-integrity/alternate.css": [ [] ], - "subresource-integrity/crossorigin-anon-script.js": [ - [] - ], - "subresource-integrity/crossorigin-anon-script.js.headers": [ - [] - ], "subresource-integrity/crossorigin-anon-style.css": [ [] ], "subresource-integrity/crossorigin-anon-style.css.headers": [ [] ], - "subresource-integrity/crossorigin-creds-script.js": [ - [] - ], - "subresource-integrity/crossorigin-creds-script.js.sub.headers": [ - [] - ], "subresource-integrity/crossorigin-creds-style.css": [ [] ], "subresource-integrity/crossorigin-creds-style.css.sub.headers": [ [] ], - "subresource-integrity/crossorigin-ineligible-script.js": [ - [] - ], "subresource-integrity/crossorigin-ineligible-style.css": [ [] ], @@ -166631,10 +166673,10 @@ "subresource-integrity/ed25519-style.css.headers": [ [] ], - "subresource-integrity/matching-digest.js": [ + "subresource-integrity/script.js": [ [] ], - "subresource-integrity/non-matching-digest.js": [ + "subresource-integrity/sri-test-helpers.sub.js": [ [] ], "subresource-integrity/style.css": [ @@ -195892,6 +195934,12 @@ {} ] ], + "css/CSS2/floats/floats-saturated-position-crash.html": [ + [ + "css/CSS2/floats/floats-saturated-position-crash.html", + {} + ] + ], "css/CSS2/floats/list-item-taller-than-opportunity-001.html": [ [ "css/CSS2/floats/list-item-taller-than-opportunity-001.html", @@ -202030,6 +202078,12 @@ {} ] ], + "css/css-position/position-absolute-crash-chrome-009.html": [ + [ + "css/css-position/position-absolute-crash-chrome-009.html", + {} + ] + ], "css/css-position/position-absolute-dynamic-containing-block.html": [ [ "css/css-position/position-absolute-dynamic-containing-block.html", @@ -208740,6 +208794,24 @@ {} ] ], + "css/css-ui/appearance-parsing.html": [ + [ + "css/css-ui/appearance-parsing.html", + {} + ] + ], + "css/css-ui/appearance-property.html": [ + [ + "css/css-ui/appearance-property.html", + {} + ] + ], + "css/css-ui/appearance-serialization.html": [ + [ + "css/css-ui/appearance-serialization.html", + {} + ] + ], "css/css-ui/box-sizing-027.html": [ [ "css/css-ui/box-sizing-027.html", @@ -209004,6 +209076,24 @@ {} ] ], + "css/css-ui/webkit-appearance-parsing.html": [ + [ + "css/css-ui/webkit-appearance-parsing.html", + {} + ] + ], + "css/css-ui/webkit-appearance-property.html": [ + [ + "css/css-ui/webkit-appearance-property.html", + {} + ] + ], + "css/css-ui/webkit-appearance-serialization.html": [ + [ + "css/css-ui/webkit-appearance-serialization.html", + {} + ] + ], "css/css-values/absolute-length-units-001.html": [ [ "css/css-values/absolute-length-units-001.html", @@ -259861,14 +259951,6 @@ {} ] ], - "payment-handler/change-payment-method.https.html": [ - [ - "payment-handler/change-payment-method.https.html", - { - "testdriver": true - } - ] - ], "payment-handler/idlharness.https.any.js": [ [ "payment-handler/idlharness.https.any.html", @@ -259987,12 +260069,6 @@ {} ] ], - "payment-handler/payment-request-event.https.html": [ - [ - "payment-handler/payment-request-event.https.html", - {} - ] - ], "payment-handler/same-object-attributes.https.html": [ [ "payment-handler/same-object-attributes.https.html", @@ -281392,9 +281468,9 @@ {} ] ], - "subresource-integrity/subresource-integrity.sub.html": [ + "subresource-integrity/subresource-integrity.html": [ [ - "subresource-integrity/subresource-integrity.sub.html", + "subresource-integrity/subresource-integrity.html", {} ] ], @@ -325480,6 +325556,10 @@ "0ebd9a621db450a70e23af3d236b79a32aa4b56a", "reftest" ], + "css/CSS2/floats/floats-saturated-position-crash.html": [ + "08a400df569c2f42670de1963724d0e028bac150", + "testharness" + ], "css/CSS2/floats/floats-wrap-bfc-001-left-overflow-ref.xht": [ "9d4c968d1d687c42932cfa205775f300de4fe343", "support" @@ -345456,6 +345536,10 @@ "b130ff5561f721d69058902f9c5081b3f6471ace", "reftest" ], + "css/css-flexbox/flex-minimum-height-flex-items-015.html": [ + "81fd54915f52177649ff0e0d4d1a5fb657ddccfa", + "reftest" + ], "css/css-flexbox/flex-minimum-width-flex-items-001.xht": [ "cd18483ba414160c46e30bc282dec0c2fcd2f418", "reftest" @@ -364332,6 +364416,10 @@ "3d1c90930cf3f0b794ea34fcdbcb347cb6d3863c", "testharness" ], + "css/css-position/position-absolute-crash-chrome-009.html": [ + "23df49cfaae5cdba6225c981d652b491f9df6784", + "testharness" + ], "css/css-position/position-absolute-dynamic-containing-block.html": [ "3968f685849663574ca213fcb90dc5fb3eaffaa3", "testharness" @@ -367388,10 +367476,6 @@ "b16362153e512f9cccdeb5059f9bf9fa71c98c43", "testharness" ], - "css/css-shapes/spec-examples/shape-outside-018-expected.txt": [ - "50c5fb4c6d830e013ffd2484141a0735d144c1f7", - "support" - ], "css/css-shapes/spec-examples/shape-outside-018.html": [ "058e5793e5c2e6110f51299b1041da94cb3cdc79", "testharness" @@ -384000,10 +384084,26 @@ "da6f1ffa6cacd3ac0e77b343ffaa33ab44f4c2c2", "reftest" ], + "css/css-ui/appearance-parsing-expected.txt": [ + "c748b8aeb1f562e25ea64ef11239f4b670fc0759", + "support" + ], + "css/css-ui/appearance-parsing.html": [ + "8d6973231c0cb33fa0bd1ff83f54f98487d844e8", + "testharness" + ], "css/css-ui/appearance-progress-bar-001.html": [ "1573f69911566fc4410f6d49959f83dad140ce3e", "reftest" ], + "css/css-ui/appearance-property-expected.txt": [ + "90dcd4612b5f0193432bd81d19e7e89c790a9305", + "support" + ], + "css/css-ui/appearance-property.html": [ + "53b98ba6055f81b7dd8510cd5be5f85b1ff4a01f", + "testharness" + ], "css/css-ui/appearance-push-button-001.html": [ "3aecbb079809bb0f1e8c2a0786dee51bc6eb61d4", "reftest" @@ -384016,6 +384116,14 @@ "78741411551c667c3f3f317eeb475db883d9d7d4", "reftest" ], + "css/css-ui/appearance-serialization-expected.txt": [ + "edcbb8b50929b54000a972029bf7c292cf4b5f9d", + "support" + ], + "css/css-ui/appearance-serialization.html": [ + "ed968afee609b4beab0a67d7bc9fc11c686ecb33", + "testharness" + ], "css/css-ui/appearance-slider-horizontal-001.html": [ "4d5b1a94fc9485b3aad8744d09dfe7d8c4ea12eb", "reftest" @@ -386608,10 +386716,26 @@ "05fb5ce25f24df1bf8fd2c72323a9deea9d0e112", "reftest" ], + "css/css-ui/webkit-appearance-parsing-expected.txt": [ + "c748b8aeb1f562e25ea64ef11239f4b670fc0759", + "support" + ], + "css/css-ui/webkit-appearance-parsing.html": [ + "0f08eab222493a123fd5a44afce3689385a42390", + "testharness" + ], "css/css-ui/webkit-appearance-progress-bar-001.html": [ "b989502902d2b8716f7fcc0d8f18e124ec8cb94e", "reftest" ], + "css/css-ui/webkit-appearance-property-expected.txt": [ + "d0e76b0a11629e39dc97e7e3ac72e1f14132b827", + "support" + ], + "css/css-ui/webkit-appearance-property.html": [ + "fb3f7df2d4885c801711f91f7d1e1f7ba09a3951", + "testharness" + ], "css/css-ui/webkit-appearance-push-button-001.html": [ "6f44498d4660f58e6df2b32efd218c729edc0fc8", "reftest" @@ -386624,6 +386748,14 @@ "8abd91e3c8faa9f5e02a8af6d2f4e66e1a0c6c29", "reftest" ], + "css/css-ui/webkit-appearance-serialization-expected.txt": [ + "3ff4fe3e611739b95b9d38a2acffbd3559d044f2", + "support" + ], + "css/css-ui/webkit-appearance-serialization.html": [ + "b325fd5d6c647063c880046804afbac23c617d7f", + "testharness" + ], "css/css-ui/webkit-appearance-slider-horizontal-001.html": [ "a9375b5088ca995c545fb441cccef281242836dd", "reftest" @@ -395592,6 +395724,14 @@ "3a2d8feaeefc82c20afd3de2c2cf9ce9bf6aed11", "reftest" ], + "css/filter-effects/backdrop-filter-plus-mask-ref.html": [ + "15786e7ac873c6cbb4b5e6919f8f0d02bd522a79", + "support" + ], + "css/filter-effects/backdrop-filter-plus-mask.html": [ + "e1390af38d47b1eb6eec2df85299e279030aafd8", + "reftest" + ], "css/filter-effects/backdrop-filter-reference-filter.html": [ "6c61a9620aa82d23375fd31900d87bcfd873a5e1", "reftest" @@ -415565,7 +415705,7 @@ "testharness" ], "html/browsers/history/the-location-interface/location_hash.html": [ - "74d2d01543086e841cdfd39c95a2f956a9dd1f32", + "99f64ddea248a2fc77eb3faaa51f12ee97843eed", "testharness" ], "html/browsers/history/the-location-interface/location_host.html": [ @@ -448028,14 +448168,14 @@ "7c09f5d407e890c0ed02df1217d85f2f36d722bc", "testharness" ], + "payment-handler/change-payment-method-manual.https.html": [ + "56690d2b26ed671f773a16853463126e57735f77", + "manual" + ], "payment-handler/change-payment-method.https-expected.txt": [ "099831a8ee28b7c1c1137beae8c7a4c916bc1d38", "support" ], - "payment-handler/change-payment-method.https.html": [ - "56690d2b26ed671f773a16853463126e57735f77", - "testharness" - ], "payment-handler/idlharness.https.any.js": [ "878114ec7ed878d3e754341cbffa138092fee129", "testharness" @@ -448084,13 +448224,17 @@ "fdb71aa845179cf63344d9370b1a138ef8924746", "testharness" ], - "payment-handler/payment-request-event.https-expected.txt": [ + "payment-handler/payment-request-event-manual.https-expected.txt": [ "b76179f0c74a04d903ba1911be97252db6552851", "support" ], - "payment-handler/payment-request-event.https.html": [ + "payment-handler/payment-request-event-manual.https.html": [ "3c8deb3b92fe00d7b4bdf1c57f1e33ab553acee3", - "testharness" + "manual" + ], + "payment-handler/payment-request-event.https-expected.txt": [ + "b76179f0c74a04d903ba1911be97252db6552851", + "support" ], "payment-handler/register-and-activate-service-worker.js": [ "fb54c5c06488f319b0b4152837cc6a1b530cab7a", @@ -448541,7 +448685,7 @@ "manual" ], "payment-request/rejects_if_not_active.https-expected.txt": [ - "0d8fb1a5d178a8848d827d781c90d92fe18ddeaa", + "1fa19f3e96160290eca310571cce99cfbc513395", "support" ], "payment-request/rejects_if_not_active.https.html": [ @@ -449121,11 +449265,11 @@ "testharness" ], "pointerevents/pointerlock/pointerevent_pointerlock_after_pointercapture.html": [ - "3c768ef0574346a38a05b6153f7133c3adbb2be0", + "c66584a939420ca5470226b1e66d18d41cfe5d1e", "testharness" ], "pointerevents/pointerlock/pointerevent_pointerlock_supercedes_capture.html": [ - "98fec4e74f15984a31714d3b908c87b426aecc5c", + "f3f61cf0d03fed40b44c5f2c10043bcf6a7e611f", "testharness" ], "pointerevents/pointerlock/pointerevent_pointermove_in_pointerlock.html": [ @@ -463585,7 +463729,7 @@ "support" ], "service-workers/service-worker/resources/worker-interception-iframe.https.html": [ - "1ae1674a2b42be26b9f5d4b336fd9527f075cc75", + "87b0ed3f2498552d995cc5086fcc15b90d47097f", "support" ], "service-workers/service-worker/resources/worker-interception-redirect-serviceworker.js": [ @@ -463829,11 +463973,11 @@ "testharness" ], "service-workers/service-worker/worker-interception.https-expected.txt": [ - "e63c0271e6c98156254de5715b72e7a95b9bb5ab", + "3fb502afc0169f40220963532b91a9df672caedf", "support" ], "service-workers/service-worker/worker-interception.https.html": [ - "f30d6e9ac5460e2b255ecdbbba381ad0540f1cec", + "6b66fb0f02296410f4d96076c68deb798024e7b9", "testharness" ], "service-workers/service-worker/xhr-response-url.https.html": [ @@ -465121,7 +465265,7 @@ "testharness" ], "sms/interceptor.https.html": [ - "4a6772f4416ab0550e451c710da1b48bbd9303d6", + "b7e8fd53bff98c6c64554149e0cd71c5f1f45686", "testharness" ], "sms/resources/iframe.html": [ @@ -465133,7 +465277,7 @@ "testharness" ], "sms/sms_provider.js": [ - "a4759419a88670ec6e3f1cbd4ac3dcb3500ad57a", + "eaa31ebea3113db8ecac51d6d0dec08d2d234444", "support" ], "sms/sms_receiver.idl": [ @@ -465261,7 +465405,7 @@ "testharness" ], "std-toast/options.html": [ - "bd091a128e6474a1d6b6ca4a061ff6f5bafe8595", + "65d3a3ae37394bc137ce1baf570226b0b7cde098", "testharness" ], "std-toast/resources/helpers.js": [ @@ -465876,14 +466020,6 @@ "0ea6d22ec772aed88ec1926e7e1a23a4ba81375c", "support" ], - "subresource-integrity/crossorigin-anon-script.js": [ - "8493585f1b189c680fd4f6853a2cc9072ff962f7", - "support" - ], - "subresource-integrity/crossorigin-anon-script.js.headers": [ - "cb762eff806849df46dc758ef7b98b63f27f54c9", - "support" - ], "subresource-integrity/crossorigin-anon-style.css": [ "3cde4df12c45211dd3637cf79524bad1f6d09c55", "support" @@ -465892,14 +466028,6 @@ "cb762eff806849df46dc758ef7b98b63f27f54c9", "support" ], - "subresource-integrity/crossorigin-creds-script.js": [ - "6f39e25b40b9b552b6632123eab95e761e896558", - "support" - ], - "subresource-integrity/crossorigin-creds-script.js.sub.headers": [ - "d6af1f0deabbf20cdad47e8c084db6fbf42a42b7", - "support" - ], "subresource-integrity/crossorigin-creds-style.css": [ "3cde4df12c45211dd3637cf79524bad1f6d09c55", "support" @@ -465908,10 +466036,6 @@ "d6af1f0deabbf20cdad47e8c084db6fbf42a42b7", "support" ], - "subresource-integrity/crossorigin-ineligible-script.js": [ - "dd2f968ef6a3ed8c51b1c338dcaa2a8669747b32", - "support" - ], "subresource-integrity/crossorigin-ineligible-style.css": [ "3cde4df12c45211dd3637cf79524bad1f6d09c55", "support" @@ -466016,12 +466140,12 @@ "d2997e562fadfd208d202ce3d60d11cd937ea779", "testharness" ], - "subresource-integrity/matching-digest.js": [ - "ec41325e4e9cde1231f44aaa5343c5e2689228e4", + "subresource-integrity/script.js": [ + "bfca1efbf3fb10fc98dd39600966fc97817586ee", "support" ], - "subresource-integrity/non-matching-digest.js": [ - "1b4943ee016b366bf7c07401da5a87dcbbb537a9", + "subresource-integrity/sri-test-helpers.sub.js": [ + "22c9e9c5dd9af81d988f9c1570645925a558d070", "support" ], "subresource-integrity/style.css": [ @@ -466040,8 +466164,8 @@ "1f091ebd5694f9d6e2e09a6b36c19bffcfb0ac72", "testharness" ], - "subresource-integrity/subresource-integrity.sub.html": [ - "658ea6fd92eb4c7ced3f21f1051615de606e5ceb", + "subresource-integrity/subresource-integrity.html": [ + "f317b0e423ec26a12196b69de84bf10cae088d5a", "testharness" ], "subresource-integrity/tools/ed25519.py": [
diff --git a/third_party/blink/web_tests/external/wpt/css/css-ui/appearance-parsing-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-ui/appearance-parsing-expected.txt new file mode 100644 index 0000000..c748b8a --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-ui/appearance-parsing-expected.txt
@@ -0,0 +1,6 @@ +This is a testharness.js-based test. +FAIL parsing via attribute change steps of CSS declaration block's owner node assert_equals: expected "none" but got "" +FAIL parsing via modification of cssText assert_equals: expected "none" but got "" +FAIL parsing via creation of CSS declaration block assert_equals: expected "none" but got "" +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/css/css-ui/appearance-parsing.html b/third_party/blink/web_tests/external/wpt/css/css-ui/appearance-parsing.html new file mode 100644 index 0000000..8d697323 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-ui/appearance-parsing.html
@@ -0,0 +1,43 @@ +<!DOCTYPE html> +<html> +<head> + <meta charset="utf-8"> + <title>Parsing of `appearance`</title> + <link rel="help" href="https://drafts.csswg.org/css-ui-4/#appearance-switching"> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> +</head> +<body> +<script> +test(function() { + var input = document.createElement('input'); + input.setAttribute('style', 'appearance: none;'); + + assert_equals(input.style.getPropertyValue('appearance'), 'none'); +}, 'parsing via attribute change steps of CSS declaration block\'s owner node'); + +test(function() { + var input = document.createElement('input'); + input.style.cssText = 'appearance: none;'; + + assert_equals(input.style.getPropertyValue('appearance'), 'none'); +}, 'parsing via modification of cssText'); + +test(function(t) { + var style = document.createElement('style'); + style.appendChild( + document.createTextNode('#foo { appearance: none; }') + ); + document.body.appendChild(style); + t.add_cleanup(function() { + document.body.removeChild(style); + }); + + assert_equals(style.sheet.cssRules.length, 1); + assert_equals( + style.sheet.cssRules[0].style.getPropertyValue('appearance'), + 'none' + ); +}, 'parsing via creation of CSS declaration block'); +</script> +</body>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-ui/appearance-property-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-ui/appearance-property-expected.txt new file mode 100644 index 0000000..90dcd46 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-ui/appearance-property-expected.txt
@@ -0,0 +1,8 @@ +This is a testharness.js-based test. +FAIL setProperty assert_equals: expected (string) "none" but got (undefined) undefined +FAIL removeProperty assert_equals: expected (string) "" but got (undefined) undefined +PASS property assignment +FAIL getPropertyValue assert_equals: expected "none" but got "" +FAIL property access assert_equals: expected (string) "none" but got (undefined) undefined +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/css/css-ui/appearance-property.html b/third_party/blink/web_tests/external/wpt/css/css-ui/appearance-property.html new file mode 100644 index 0000000..53b98ba6 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-ui/appearance-property.html
@@ -0,0 +1,56 @@ +<!DOCTYPE html> +<html> +<head> + <meta charset="utf-8"> + <title>Property references to `appearance`</title> + <link rel="help" href="https://drafts.csswg.org/css-ui-4/#appearance-switching"> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> +</head> +<body> +<script> +function create(initialValue) { + var style = document.createElement('input').style; + + style.setProperty('appearance', initialValue); + + return style; +} + +test(function() { + var style = create(''); + + style.setProperty('appearance', 'none'); + + assert_equals(style.appearance, 'none'); +}, 'setProperty'); + +test(function() { + var style = create('none'); + + style.removeProperty('appearance'); + + assert_equals(style.appearance, ''); +}, 'removeProperty'); + +test(function() { + var style = create(''); + + style['appearance'] = 'none'; + + assert_equals(style.appearance, 'none'); +}, 'property assignment'); + +test(function() { + var style = create('none'); + + assert_equals(style.getPropertyValue('appearance'), 'none'); +}, 'getPropertyValue'); + +test(function() { + var style = create('none'); + + assert_equals(style['appearance'], 'none'); +}, 'property access'); +</script> +</body>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-ui/appearance-serialization-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-ui/appearance-serialization-expected.txt new file mode 100644 index 0000000..edcbb8b --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-ui/appearance-serialization-expected.txt
@@ -0,0 +1,6 @@ +This is a testharness.js-based test. +FAIL serialization via CSSStyleDeclaration assert_equals: expected "appearance: none;" but got "" +FAIL serialization via CSSStyleRule assert_equals: expected "#foo { appearance: none; }" but got "#foo { }" +FAIL serialization via CSSMediaRule assert_equals: expected "@media print {\n #foo { appearance: none; }\n}" but got "@media print {\n #foo { }\n}" +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/css/css-ui/appearance-serialization.html b/third_party/blink/web_tests/external/wpt/css/css-ui/appearance-serialization.html new file mode 100644 index 0000000..ed968af --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-ui/appearance-serialization.html
@@ -0,0 +1,48 @@ +<!DOCTYPE html> +<html> +<head> + <meta charset="utf-8"> + <title>Serialization of `appearance`</title> + <link rel="help" href="https://drafts.csswg.org/css-ui-4/#appearance-switching"> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> +</head> +<body> +<script> +test(function() { + var input = document.createElement('input'); + input.style.setProperty('appearance', 'none'); + + assert_equals(input.style.cssText, 'appearance: none;'); +}, 'serialization via CSSStyleDeclaration'); + +test(function(t) { + var style = document.createElement('style'); + document.body.appendChild(style); + t.add_cleanup(function() { + document.body.removeChild(style); + }); + style.sheet.insertRule('#foo {}', 0); + style.sheet.cssRules[0].style.setProperty('appearance', 'none'); + + assert_equals( + style.sheet.cssRules[0].cssText, '#foo { appearance: none; }' + ); +}, 'serialization via CSSStyleRule'); + +test(function(t) { + var style = document.createElement('style'); + document.body.appendChild(style); + t.add_cleanup(function() { + document.body.removeChild(style); + }); + style.sheet.insertRule('@media print { #foo {} }', 0); + style.sheet.cssRules[0].cssRules[0].style.setProperty('appearance', 'none'); + + assert_equals( + style.sheet.cssRules[0].cssText, + '@media print {\n #foo { appearance: none; }\n}' + ); +}, 'serialization via CSSMediaRule'); +</script> +</body>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-ui/webkit-appearance-parsing-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-ui/webkit-appearance-parsing-expected.txt new file mode 100644 index 0000000..c748b8a --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-ui/webkit-appearance-parsing-expected.txt
@@ -0,0 +1,6 @@ +This is a testharness.js-based test. +FAIL parsing via attribute change steps of CSS declaration block's owner node assert_equals: expected "none" but got "" +FAIL parsing via modification of cssText assert_equals: expected "none" but got "" +FAIL parsing via creation of CSS declaration block assert_equals: expected "none" but got "" +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/css/css-ui/webkit-appearance-parsing.html b/third_party/blink/web_tests/external/wpt/css/css-ui/webkit-appearance-parsing.html new file mode 100644 index 0000000..0f08eab --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-ui/webkit-appearance-parsing.html
@@ -0,0 +1,43 @@ +<!DOCTYPE html> +<html> +<head> + <meta charset="utf-8"> + <title>Parsing of `-webkit-appearance`</title> + <link rel="help" href="https://drafts.csswg.org/css-ui-4/#appearance-switching"> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> +</head> +<body> +<script> +test(function() { + var input = document.createElement('input'); + input.setAttribute('style', '-webkit-appearance: none;'); + + assert_equals(input.style.getPropertyValue('appearance'), 'none'); +}, 'parsing via attribute change steps of CSS declaration block\'s owner node'); + +test(function() { + var input = document.createElement('input'); + input.style.cssText = '-webkit-appearance: none;'; + + assert_equals(input.style.getPropertyValue('appearance'), 'none'); +}, 'parsing via modification of cssText'); + +test(function(t) { + var style = document.createElement('style'); + style.appendChild( + document.createTextNode('#foo { -webkit-appearance: none; }') + ); + document.body.appendChild(style); + t.add_cleanup(function() { + document.body.removeChild(style); + }); + + assert_equals(style.sheet.cssRules.length, 1); + assert_equals( + style.sheet.cssRules[0].style.getPropertyValue('appearance'), + 'none' + ); +}, 'parsing via creation of CSS declaration block'); +</script> +</body>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-ui/webkit-appearance-property-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-ui/webkit-appearance-property-expected.txt new file mode 100644 index 0000000..d0e76b0 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-ui/webkit-appearance-property-expected.txt
@@ -0,0 +1,18 @@ +This is a testharness.js-based test. +FAIL setProperty - CSS property name assert_equals: expected (string) "none" but got (undefined) undefined +FAIL setProperty - camel-cased property name (ignored) assert_equals: expected (string) "" but got (undefined) undefined +FAIL setProperty - webkit-cased property name (ignored) assert_equals: expected (string) "" but got (undefined) undefined +FAIL removeProperty - CSS property name assert_equals: expected (string) "" but got (undefined) undefined +FAIL removeProperty - camel-cased property name (ignored) assert_equals: expected (string) "none" but got (undefined) undefined +FAIL removeProperty - webkit-cased property name (ignored) assert_equals: expected (string) "none" but got (undefined) undefined +FAIL property assignment - CSS property name assert_equals: expected (string) "none" but got (undefined) undefined +FAIL property assignment - camel-cased property name assert_equals: expected (string) "none" but got (undefined) undefined +FAIL property assignment - webkit-cased property name assert_equals: expected (string) "none" but got (undefined) undefined +FAIL getPropertyValue - CSS property name assert_equals: expected "none" but got "" +PASS getPropertyValue - camel-cased property name (ignored) +PASS getPropertyValue - webkit-cased property name (ignored) +FAIL property access - CSS property name assert_equals: expected "none" but got "" +FAIL property access - camel-cased property name assert_equals: expected "none" but got "" +FAIL property access - webkit-cased property name assert_equals: expected "none" but got "" +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/css/css-ui/webkit-appearance-property.html b/third_party/blink/web_tests/external/wpt/css/css-ui/webkit-appearance-property.html new file mode 100644 index 0000000..fb3f7df2 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-ui/webkit-appearance-property.html
@@ -0,0 +1,128 @@ +<!DOCTYPE html> +<html> +<head> + <meta charset="utf-8"> + <title>Property references to `-webkit-appearance`</title> + <link rel="help" href="https://drafts.csswg.org/css-ui-4/#appearance-switching"> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> +</head> +<body> +<script> +function create(initialValue) { + var style = document.createElement('input').style; + + style.setProperty('appearance', initialValue); + + return style; +} + +test(function() { + var style = create(''); + + style.setProperty('-webkit-appearance', 'none'); + + assert_equals(style.appearance, 'none'); +}, 'setProperty - CSS property name'); + +test(function() { + var style = create(''); + + style.setProperty('WebkitAppearance', 'none'); + + assert_equals(style.appearance, ''); +}, 'setProperty - camel-cased property name (ignored)'); + +test(function() { + var style = create(''); + + style.setProperty('webkitAppearance', 'none'); + + assert_equals(style.appearance, ''); +}, 'setProperty - webkit-cased property name (ignored)'); + +test(function() { + var style = create('none'); + + style.removeProperty('-webkit-appearance'); + + assert_equals(style.appearance, ''); +}, 'removeProperty - CSS property name'); + +test(function() { + var style = create('none'); + + style.removeProperty('WebkitAppearance'); + + assert_equals(style.appearance, 'none'); +}, 'removeProperty - camel-cased property name (ignored)'); + +test(function() { + var style = create('none'); + + style.removeProperty('webkitAppearance'); + + assert_equals(style.appearance, 'none'); +}, 'removeProperty - webkit-cased property name (ignored)'); + +test(function() { + var style = create(''); + + style['-webkit-appearance'] = 'none'; + + assert_equals(style.appearance, 'none'); +}, 'property assignment - CSS property name'); + +test(function() { + var style = create(''); + + style['WebkitAppearance'] = 'none'; + + assert_equals(style.appearance, 'none'); +}, 'property assignment - camel-cased property name'); + +test(function() { + var style = create(''); + + style['webkitAppearance'] = 'none'; + + assert_equals(style.appearance, 'none'); +}, 'property assignment - webkit-cased property name'); + +test(function() { + var style = create('none'); + + assert_equals(style.getPropertyValue('-webkit-appearance'), 'none'); +}, 'getPropertyValue - CSS property name'); + +test(function() { + var style = create('none'); + + assert_equals(style.getPropertyValue('WebkitAppearance'), ''); +}, 'getPropertyValue - camel-cased property name (ignored)'); + +test(function() { + var style = create('none'); + + assert_equals(style.getPropertyValue('webkitAppearance'), ''); +}, 'getPropertyValue - webkit-cased property name (ignored)'); + +test(function() { + var style = create('none'); + + assert_equals(style['-webkit-appearance'], 'none'); +}, 'property access - CSS property name'); + +test(function() { + var style = create('none'); + + assert_equals(style['WebkitAppearance'], 'none'); +}, 'property access - camel-cased property name'); + +test(function() { + var style = create('none'); + + assert_equals(style['webkitAppearance'], 'none'); +}, 'property access - webkit-cased property name'); +</script> +</body>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-ui/webkit-appearance-serialization-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-ui/webkit-appearance-serialization-expected.txt new file mode 100644 index 0000000..3ff4fe3e --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-ui/webkit-appearance-serialization-expected.txt
@@ -0,0 +1,6 @@ +This is a testharness.js-based test. +FAIL serialization via CSSStyleDeclaration assert_equals: expected "appearance: none;" but got "-webkit-appearance: none;" +FAIL serialization via CSSStyleRule assert_equals: expected "#foo { appearance: none; }" but got "#foo { -webkit-appearance: none; }" +FAIL serialization via CSSMediaRule assert_equals: expected "@media print {\n #foo { appearance: none; }\n}" but got "@media print {\n #foo { -webkit-appearance: none; }\n}" +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/css/css-ui/webkit-appearance-serialization.html b/third_party/blink/web_tests/external/wpt/css/css-ui/webkit-appearance-serialization.html new file mode 100644 index 0000000..b325fd5 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-ui/webkit-appearance-serialization.html
@@ -0,0 +1,48 @@ +<!DOCTYPE html> +<html> +<head> + <meta charset="utf-8"> + <title>Serialization of `-webkit-appearance`</title> + <link rel="help" href="https://drafts.csswg.org/css-ui-4/#appearance-switching"> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> +</head> +<body> +<script> +test(function() { + var input = document.createElement('input'); + input.style.setProperty('-webkit-appearance', 'none'); + + assert_equals(input.style.cssText, 'appearance: none;'); +}, 'serialization via CSSStyleDeclaration'); + +test(function(t) { + var style = document.createElement('style'); + document.body.appendChild(style); + t.add_cleanup(function() { + document.body.removeChild(style); + }); + style.sheet.insertRule('#foo {}', 0); + style.sheet.cssRules[0].style.setProperty('-webkit-appearance', 'none'); + + assert_equals( + style.sheet.cssRules[0].cssText, '#foo { appearance: none; }' + ); +}, 'serialization via CSSStyleRule'); + +test(function(t) { + var style = document.createElement('style'); + document.body.appendChild(style); + t.add_cleanup(function() { + document.body.removeChild(style); + }); + style.sheet.insertRule('@media print { #foo {} }', 0); + style.sheet.cssRules[0].cssRules[0].style.setProperty('-webkit-appearance', 'none'); + + assert_equals( + style.sheet.cssRules[0].cssText, + '@media print {\n #foo { appearance: none; }\n}' + ); +}, 'serialization via CSSMediaRule'); +</script> +</body>
diff --git a/third_party/blink/web_tests/external/wpt/html/browsers/history/the-location-interface/location_hash.html b/third_party/blink/web_tests/external/wpt/html/browsers/history/the-location-interface/location_hash.html index 74d2d01..99f64dd 100644 --- a/third_party/blink/web_tests/external/wpt/html/browsers/history/the-location-interface/location_hash.html +++ b/third_party/blink/web_tests/external/wpt/html/browsers/history/the-location-interface/location_hash.html
@@ -23,6 +23,8 @@ var frameWin = document.getElementById("srcdoc-iframe").contentWindow; assert_equals(frameWin.location.href, "about:srcdoc"); assert_equals(frameWin.scrollY, 0, "Should not have scrolled yet"); + frameWin.location.hash = ""; + assert_equals(frameWin.location.href, "about:srcdoc#", "Setting an empty hash should result in an empty fragment, not no fragment."); frameWin.location.hash = "test"; assert_equals(frameWin.location.href, "about:srcdoc#test"); assert_true(frameWin.scrollY > frameWin.innerHeight,
diff --git a/third_party/blink/web_tests/external/wpt/payment-handler/change-payment-method.https.html b/third_party/blink/web_tests/external/wpt/payment-handler/change-payment-method-manual.https.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/payment-handler/change-payment-method.https.html rename to third_party/blink/web_tests/external/wpt/payment-handler/change-payment-method-manual.https.html
diff --git a/third_party/blink/web_tests/external/wpt/payment-handler/payment-request-event-manual.https-expected.txt b/third_party/blink/web_tests/external/wpt/payment-handler/payment-request-event-manual.https-expected.txt new file mode 100644 index 0000000..b76179f --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/payment-handler/payment-request-event-manual.https-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +FAIL Tests for PaymentRequestEvent Not allowed to install this payment handler +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/payment-handler/payment-request-event.https.html b/third_party/blink/web_tests/external/wpt/payment-handler/payment-request-event-manual.https.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/payment-handler/payment-request-event.https.html rename to third_party/blink/web_tests/external/wpt/payment-handler/payment-request-event-manual.https.html
diff --git a/third_party/blink/web_tests/external/wpt/service-workers/service-worker/resources/worker-interception-iframe.https.html b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/resources/worker-interception-iframe.https.html index 1ae1674..87b0ed3 100644 --- a/third_party/blink/web_tests/external/wpt/service-workers/service-worker/resources/worker-interception-iframe.https.html +++ b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/resources/worker-interception-iframe.https.html
@@ -2,65 +2,58 @@ <script src="test-helpers.sub.js?pipe=sub"></script> <script> -let worker_type; +class TestRunner { + constructor(script_url, worker_type) { + this.script_url = script_url; + this.worker_type = worker_type; + } -async function boilerplate_test(url, msg) { - let data; - if (worker_type === 'worker') { - const worker = new Worker(url); - data = await new Promise((resolve, reject) => { + // Tests subresource requests on a worker. + async run(subresource_type) { + let data; + if (this.worker_type === 'worker') { + data = await this.runOnDedicatedWorker(subresource_type); + } else if (this.worker_type === 'sharedworker') { + data = await this.runOnSharedWorker(subresource_type); + } else { + data = 'Unexpected worker type! ' + worker_type; + } + assert_equals(data, 'This load was successfully intercepted.'); + } + + async runOnDedicatedWorker(subresource_type) { + const worker = new Worker(this.script_url); + const data = await new Promise((resolve, reject) => { worker.onmessage = e => resolve(e.data); worker.onerror = e => reject(e); - worker.postMessage(msg); + worker.postMessage(subresource_type); }); - } else if (worker_type === 'sharedworker') { - const worker = new SharedWorker(url); - data = await new Promise((resolve, reject) => { + worker.terminate(); + return data; + } + + async runOnSharedWorker(subresource_type) { + const worker = new SharedWorker(this.script_url); + return await new Promise((resolve, reject) => { worker.port.onmessage = e => resolve(e.data); worker.onerror = e => reject(e); - worker.port.postMessage(msg); + worker.port.postMessage(subresource_type); }); - } else { - data = 'Unexpected worker type! ' + worker_type; } - assert_equals(data, 'This load was successfully intercepted.'); } -function xhr_test() { - return boilerplate_test('load_worker.js', 'xhr'); -} - -function fetch_test() { - return boilerplate_test('load_worker.js', 'fetch'); -} - -function importScripts_test() { - return boilerplate_test('load_worker.js', 'importScripts'); -} - -function nested_worker_xhr_test() { - return boilerplate_test('nested_load_worker.js', 'xhr'); -} - -function nested_worker_fetch_test() { - return boilerplate_test('nested_load_worker.js', 'fetch'); -} - -function nested_worker_importScripts_test() { - return boilerplate_test('nested_load_worker.js', 'importScripts'); -} - -window.addEventListener('message', evt => { - worker_type = evt.data; +window.addEventListener('message', async evt => { + const test_runner = new TestRunner(evt.data.script, evt.data.type); const port = evt.ports[0]; - xhr_test() - .then(fetch_test) - .then(importScripts_test) - .then(nested_worker_xhr_test) - .then(nested_worker_fetch_test) - .then(nested_worker_importScripts_test) - .then(() => port.postMessage({results: 'finish'})) - .catch(e => port.postMessage({results: 'failure:' + e})); + + try { + await test_runner.run('xhr'); + await test_runner.run('fetch'); + await test_runner.run('importScripts'); + port.postMessage({results: 'finish'}); + } catch(e) { + port.postMessage({results: 'failure:' + e}); + } }); </script>
diff --git a/third_party/blink/web_tests/external/wpt/service-workers/service-worker/worker-interception.https-expected.txt b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/worker-interception.https-expected.txt index e63c027..3fb502a 100644 --- a/third_party/blink/web_tests/external/wpt/service-workers/service-worker/worker-interception.https-expected.txt +++ b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/worker-interception.https-expected.txt
@@ -7,7 +7,9 @@ PASS Verify a cors worker script served by a service worker fails shared worker start. PASS Verify a no-cors cross-origin worker script served by a service worker fails dedicated worker start. PASS Verify a no-cors cross-origin worker script served by a service worker fails shared worker start. -PASS Verify subresource requests on a dedicated worker controlled by a service worker. -FAIL Verify subresource requests on a shared worker controlled by a service worker. assert_equals: expected "finish" but got "failure:Error: assert_equals: expected \"This load was successfully intercepted.\" but got \"Unexpected error! Worker is not defined\"" +FAIL Verify subresource requests on a dedicated worker controlled by a service worker. assert_equals: expected "finish" but got "failure:Error: assert_equals: expected \"This load was successfully intercepted.\" but got \"{\\\"error\\": {\\"message\\": \\"\\", \\"code\\": 404}}\"" +PASS Verify subresource requests on a shared worker controlled by a service worker. +FAIL Verify subresource requests on a nested dedicated worker created from a dedicated worker and controlled by a service worker. assert_equals: expected "finish" but got "failure:Error: assert_equals: expected \"This load was successfully intercepted.\" but got \"{\\\"error\\": {\\"message\\": \\"\\", \\"code\\": 404}}\"" +FAIL Verify subresource requests on a nested dedicated worker created from a shared worker and controlled by a service worker. assert_equals: expected "finish" but got "failure:Error: assert_equals: expected \"This load was successfully intercepted.\" but got \"Unexpected error! Worker is not defined\"" Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/external/wpt/service-workers/service-worker/worker-interception.https.html b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/worker-interception.https.html index f30d6e9..6b66fb0f0 100644 --- a/third_party/blink/web_tests/external/wpt/service-workers/service-worker/worker-interception.https.html +++ b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/worker-interception.https.html
@@ -15,7 +15,7 @@ } promise_test(async t => { - const worker_url = 'resources/dummy-synthesized-worker.js'; + const worker_url = 'resources/dummy-synthesized-worker.js?dedicated'; const service_worker = 'resources/dummy-worker-interceptor.js'; const scope = worker_url; @@ -30,7 +30,7 @@ `document is intercepted by worker's own service worker.`); promise_test(async t => { - const worker_url = 'resources/dummy-synthesized-worker.js'; + const worker_url = 'resources/dummy-synthesized-worker.js?shared'; const service_worker = 'resources/dummy-worker-interceptor.js'; const scope = worker_url; @@ -45,7 +45,7 @@ `document is intercepted by worker's own service worker.`); promise_test(async t => { - const worker_url = 'resources/dummy-same-origin-worker.js'; + const worker_url = 'resources/dummy-same-origin-worker.js?dedicated'; const service_worker = 'resources/dummy-worker-interceptor.js'; const scope = worker_url; @@ -60,7 +60,7 @@ 'in starting a dedicated worker.'); promise_test(async t => { - const worker_url = 'resources/dummy-same-origin-worker.js'; + const worker_url = 'resources/dummy-same-origin-worker.js?shared'; const service_worker = 'resources/dummy-worker-interceptor.js'; const scope = worker_url; @@ -75,7 +75,7 @@ 'in starting a shared worker.'); promise_test(async t => { - const worker_url = 'resources/dummy-cors-worker.js'; + const worker_url = 'resources/dummy-cors-worker.js?dedicated'; const service_worker = 'resources/dummy-worker-interceptor.js'; const scope = worker_url; @@ -87,7 +87,7 @@ 'worker start.'); promise_test(async t => { - const worker_url = 'resources/dummy-cors-worker.js'; + const worker_url = 'resources/dummy-cors-worker.js?shared'; const service_worker = 'resources/dummy-worker-interceptor.js'; const scope = worker_url; @@ -99,7 +99,7 @@ 'worker start.'); promise_test(async t => { - const worker_url = 'resources/dummy-no-cors-worker.js'; + const worker_url = 'resources/dummy-no-cors-worker.js?dedicated'; const service_worker = 'resources/dummy-worker-interceptor.js'; const scope = worker_url; @@ -111,7 +111,7 @@ 'fails dedicated worker start.'); promise_test(async t => { - const worker_url = 'resources/dummy-no-cors-worker.js'; + const worker_url = 'resources/dummy-no-cors-worker.js?shared'; const service_worker = 'resources/dummy-worker-interceptor.js'; const scope = worker_url; @@ -125,7 +125,7 @@ promise_test(async t => { const subdoc_url = 'resources/worker-interception-iframe.https.html'; const service_worker = 'resources/worker-load-interceptor.js'; - const scope = 'resources/'; + const scope = 'resources/load_worker.js?dedicated'; await setup_service_worker(t, service_worker, scope); const frame = await with_iframe(subdoc_url); @@ -133,7 +133,9 @@ const data = await new Promise((resolve, reject) => { const channel = new MessageChannel(); channel.port1.onmessage = e => resolve(e.data); - frame.contentWindow.postMessage('worker', '*', [channel.port2]); + frame.contentWindow.postMessage( + { script: 'load_worker.js?dedicated', type: 'worker' }, + '*', [channel.port2]); }); assert_equals(data.results, 'finish'); }, 'Verify subresource requests on a dedicated worker controlled by a ' + @@ -142,7 +144,7 @@ promise_test(async t => { const subdoc_url = 'resources/worker-interception-iframe.https.html'; const service_worker = 'resources/worker-load-interceptor.js'; - const scope = 'resources/'; + const scope = 'resources/load_worker.js?shared'; await setup_service_worker(t, service_worker, scope); const frame = await with_iframe(subdoc_url); @@ -150,11 +152,51 @@ const data = await new Promise((resolve, reject) => { const channel = new MessageChannel(); channel.port1.onmessage = e => resolve(e.data); - frame.contentWindow.postMessage('sharedworker', '*', [channel.port2]); + frame.contentWindow.postMessage( + { script: 'load_worker.js?shared', type: 'sharedworker' }, + '*', [channel.port2]); }); assert_equals(data.results, 'finish'); }, 'Verify subresource requests on a shared worker controlled by a service ' + 'worker.'); +promise_test(async t => { + const subdoc_url = 'resources/worker-interception-iframe.https.html'; + const service_worker = 'resources/worker-load-interceptor.js'; + const scope = 'resources/nested_load_worker.js?dedicated'; + + await setup_service_worker(t, service_worker, scope); + const frame = await with_iframe(subdoc_url); + t.add_cleanup(() => frame.remove()); + const data = await new Promise((resolve, reject) => { + const channel = new MessageChannel(); + channel.port1.onmessage = e => resolve(e.data); + frame.contentWindow.postMessage( + { script: 'nested_load_worker.js?dedicated', type: 'worker' }, + '*', [channel.port2]); + }); + assert_equals(data.results, 'finish'); +}, 'Verify subresource requests on a nested dedicated worker created from a ' + + 'dedicated worker and controlled by a service worker.'); + +promise_test(async t => { + const subdoc_url = 'resources/worker-interception-iframe.https.html'; + const service_worker = 'resources/worker-load-interceptor.js'; + const scope = 'resources/nested_load_worker.js?shared'; + + await setup_service_worker(t, service_worker, scope); + const frame = await with_iframe(subdoc_url); + t.add_cleanup(() => frame.remove()); + const data = await new Promise((resolve, reject) => { + const channel = new MessageChannel(); + channel.port1.onmessage = e => resolve(e.data); + frame.contentWindow.postMessage( + { script: 'nested_load_worker.js?shared', type: 'sharedworker' }, + '*', [channel.port2]); + }); + assert_equals(data.results, 'finish'); +}, 'Verify subresource requests on a nested dedicated worker created from a ' + + 'shared worker and controlled by a service worker.'); + </script> </body>
diff --git a/third_party/blink/web_tests/external/wpt/std-toast/options.html b/third_party/blink/web_tests/external/wpt/std-toast/options.html index bd091a12..65d3a3a 100644 --- a/third_party/blink/web_tests/external/wpt/std-toast/options.html +++ b/third_party/blink/web_tests/external/wpt/std-toast/options.html
@@ -15,11 +15,11 @@ // message test(() => { - const toast = new StdToastElement(false); + const toast = new StdToastElement('test'); document.body.appendChild(toast); - assert_equals(toast.textContent, 'false'); -}), 'passing false as message converts to the string `false`'; + assert_equals(toast.textContent, 'test'); +}, 'passing test string as message sets the message properly'); test(() => { const toast = new StdToastElement('<p>rich text</p>'); @@ -30,6 +30,34 @@ }, 'passing markup to the constructor does not pass through the markup behaviors'); test(() => { + const toast = new StdToastElement(false); + document.body.appendChild(toast); + + assert_equals(toast.textContent, 'false'); +}), 'passing false as message converts to the string `false`'; + +test(() => { + const toast = new StdToastElement(); + document.body.appendChild(toast); + + assert_equals(toast.textContent, ''); +}, 'passing nothing as message sets the message to the empty string'); + +test(() => { + const toast = new StdToastElement(undefined); + document.body.appendChild(toast); + + assert_equals(toast.textContent, ''); +}, 'passing `undefined` as message sets the message to the empty string'); + +test(() => { + const toast = new StdToastElement(''); + document.body.appendChild(toast); + + assert_equals(toast.textContent, ''); +}, 'passing empty string as message sets the message to the empty string'); + +test(() => { const toastString = '<std-toast id="test">test</std-toast>'; document.body.innerHTML = toastString; const toast = document.body.querySelector('#test');
diff --git a/third_party/blink/web_tests/external/wpt/subresource-integrity/crossorigin-anon-script.js b/third_party/blink/web_tests/external/wpt/subresource-integrity/crossorigin-anon-script.js deleted file mode 100644 index 8493585f1..0000000 --- a/third_party/blink/web_tests/external/wpt/subresource-integrity/crossorigin-anon-script.js +++ /dev/null
@@ -1 +0,0 @@ -crossorigin_anon_script=true; \ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/subresource-integrity/crossorigin-anon-script.js.headers b/third_party/blink/web_tests/external/wpt/subresource-integrity/crossorigin-anon-script.js.headers deleted file mode 100644 index cb762eff..0000000 --- a/third_party/blink/web_tests/external/wpt/subresource-integrity/crossorigin-anon-script.js.headers +++ /dev/null
@@ -1 +0,0 @@ -Access-Control-Allow-Origin: *
diff --git a/third_party/blink/web_tests/external/wpt/subresource-integrity/crossorigin-creds-script.js b/third_party/blink/web_tests/external/wpt/subresource-integrity/crossorigin-creds-script.js deleted file mode 100644 index 6f39e25..0000000 --- a/third_party/blink/web_tests/external/wpt/subresource-integrity/crossorigin-creds-script.js +++ /dev/null
@@ -1 +0,0 @@ -crossorigin_creds_script=true; \ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/subresource-integrity/crossorigin-creds-script.js.sub.headers b/third_party/blink/web_tests/external/wpt/subresource-integrity/crossorigin-creds-script.js.sub.headers deleted file mode 100644 index d6af1f0..0000000 --- a/third_party/blink/web_tests/external/wpt/subresource-integrity/crossorigin-creds-script.js.sub.headers +++ /dev/null
@@ -1,2 +0,0 @@ -Access-Control-Allow-Origin: {{location[scheme]}}://{{domains[]}}{{GET[acao_port]}} -Access-Control-Allow-Credentials: true
diff --git a/third_party/blink/web_tests/external/wpt/subresource-integrity/crossorigin-ineligible-script.js b/third_party/blink/web_tests/external/wpt/subresource-integrity/crossorigin-ineligible-script.js deleted file mode 100644 index dd2f968..0000000 --- a/third_party/blink/web_tests/external/wpt/subresource-integrity/crossorigin-ineligible-script.js +++ /dev/null
@@ -1 +0,0 @@ -crossorigin_ineligible_script=true; \ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/subresource-integrity/matching-digest.js b/third_party/blink/web_tests/external/wpt/subresource-integrity/matching-digest.js deleted file mode 100644 index ec41325e..0000000 --- a/third_party/blink/web_tests/external/wpt/subresource-integrity/matching-digest.js +++ /dev/null
@@ -1 +0,0 @@ -matching_digest=true; \ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/subresource-integrity/non-matching-digest.js b/third_party/blink/web_tests/external/wpt/subresource-integrity/non-matching-digest.js deleted file mode 100644 index 1b4943e..0000000 --- a/third_party/blink/web_tests/external/wpt/subresource-integrity/non-matching-digest.js +++ /dev/null
@@ -1 +0,0 @@ -non_matching_digest=true; \ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/subresource-integrity/script.js b/third_party/blink/web_tests/external/wpt/subresource-integrity/script.js new file mode 100644 index 0000000..bfca1efb --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/subresource-integrity/script.js
@@ -0,0 +1 @@ +// nothing important.
diff --git a/third_party/blink/web_tests/external/wpt/subresource-integrity/sri-test-helpers.sub.js b/third_party/blink/web_tests/external/wpt/subresource-integrity/sri-test-helpers.sub.js new file mode 100644 index 0000000..22c9e9c --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/subresource-integrity/sri-test-helpers.sub.js
@@ -0,0 +1,38 @@ +// This horrible hack is needed for the 'use-credentials' tests because, on +// response, if port 80 or 443 is the current port, it will not appear to +// the browser as part of the origin string. Since the origin *string* is +// used for CORS access control, instead of the origin itself, if there +// isn't an exact string match, the check will fail. For example, +// "http://example.com" would not match "http://example.com:80", because +// they are not exact string matches, even though the origins are the same. +// +// Thus, we only want the Access-Control-Allow-Origin header to have +// the port if it's not port 80 or 443, since the user agent will elide the +// ports in those cases. +const main_domain = "{{domains[]}}"; +const www_domain = "{{domains[www]}}"; +const default_port = (location.protocol === "https:") ? "{{ports[https][0]}}" : + "{{ports[http][0]}}"; + +const port_string = (default_port !== "80" && default_port !== "443") ? + `:${default_port}` : ""; +const www_host_and_port = www_domain + port_string; + +// General resource prefixes. +const same_origin_prefix = '/subresource-integrity/'; +const xorigin_prefix = `${location.protocol}//${www_host_and_port}/subresource-integrity/`; + +// Note that all of these style URLs have query parameters started, so any +// additional parameters should be appended starting with '&'. +const xorigin_anon_style = location.protocol + + '//' + www_host_and_port + + '/subresource-integrity/crossorigin-anon-style.css?'; + +const xorigin_creds_style = location.protocol + + '//' + www_host_and_port + + '/subresource-integrity/crossorigin-creds-style.css?acao_port=' + + port_string; + +const xorigin_ineligible_style = location.protocol + + '//' + www_host_and_port + + '/subresource-integrity/crossorigin-ineligible-style.css?';
diff --git a/third_party/blink/web_tests/external/wpt/subresource-integrity/subresource-integrity.sub.html b/third_party/blink/web_tests/external/wpt/subresource-integrity/subresource-integrity.html similarity index 74% rename from third_party/blink/web_tests/external/wpt/subresource-integrity/subresource-integrity.sub.html rename to third_party/blink/web_tests/external/wpt/subresource-integrity/subresource-integrity.html index 658ea6fd..f317b0e4 100644 --- a/third_party/blink/web_tests/external/wpt/subresource-integrity/subresource-integrity.sub.html +++ b/third_party/blink/web_tests/external/wpt/subresource-integrity/subresource-integrity.html
@@ -4,64 +4,13 @@ <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> <script src="/resources/sriharness.js"></script> +<script src="/common/utils.js"></script> +<script src="sri-test-helpers.sub.js"></script> <div id="log"></div> <div id="container"></div> <script> - // This horrible hack is needed for the 'use-credentials' tests because, on - // response, if port 80 or 443 is the current port, it will not appear to - // the browser as part of the origin string. Since the origin *string* is - // used for CORS access control, instead of the origin itself, if there - // isn't an exact string match, the check will fail. For example, - // "http://example.com" would not match "http://example.com:80", because - // they are not exact string matches, even though the origins are the same. - // - // Thus, we only want the Access-Control-Allow-Origin header to have - // the port if it's not port 80 or 443, since the user agent will elide the - // ports in those cases. - var main_domain = "{{domains[]}}"; - var www_domain = "{{domains[www]}}"; - var default_port = "{{ports[http][0]}}"; - if (location.protocol === "https:") { - default_port = "{{ports[https][0]}}"; - } - - var port_string = ""; - if (default_port !== "80" && default_port !== "443") - port_string = ":" + default_port; - - www_host_and_port = www_domain + port_string; - - // <script> tests - var xorigin_anon_script = location.protocol - + '//' + www_host_and_port - + '/subresource-integrity/crossorigin-anon-script.js'; - - var xorigin_creds_script = location.protocol - + '//' + www_host_and_port - + '/subresource-integrity/crossorigin-creds-script.js?acao_port=' - + port_string; - - var xorigin_ineligible_script = location.protocol - + '//' + www_host_and_port - + '/subresource-integrity/crossorigin-ineligible-script.js'; - - // Note that all of these style URLs have query parameters started, so any - // additional parameters should be appended starting with '&'. - var xorigin_anon_style = location.protocol - + '//' + www_host_and_port - + '/subresource-integrity/crossorigin-anon-style.css?'; - - var xorigin_creds_style = location.protocol - + '//' + www_host_and_port - + '/subresource-integrity/crossorigin-creds-style.css?acao_port=' - + port_string; - - var xorigin_ineligible_style = location.protocol - + '//' + www_host_and_port - + '/subresource-integrity/crossorigin-ineligible-style.css?'; - var style_tests = []; style_tests.execute = function() { if (this.length > 0) { @@ -78,78 +27,78 @@ new SRIScriptTest( true, "Same-origin with correct sha256 hash.", - "matching-digest.js", - "sha256-U9WYDtBWkcHx13+9UKk/3Q5eoqDc4YGxYb07EPWzb9E=" + `${same_origin_prefix}script.js?${token()}`, + "sha256-Bu681KMnQ15RYHFvsYdWumweeFAw0hJDTFt9seErghA=" ).execute(); new SRIScriptTest( true, "Same-origin with correct sha384 hash.", - "matching-digest.js", - "sha384-BDRTPSywZFyxfLEAzaLcL4FfERBgJgXfEkuT0r04LG93Yqn1PWNYPZMomaqEfE3H" + `${same_origin_prefix}script.js?${token()}`, + "sha384-cINXh+nCzEHPWzXS7eoT+vYMBpyqczOybRLNU3XAButFWCRhHT5hLByIbPRqIm2f" ).execute(); new SRIScriptTest( true, "Same-origin with correct sha512 hash.", - "matching-digest.js", - "sha512-geByvIIRspbnUnwooKGNNCb39nvg+EW0O9hDScTXeo/9pVZztLSUYU3LNV6H0lZapo8bCJUpyPPLAzE9fDzpxg==" + `${same_origin_prefix}script.js?${token()}`, + "sha512-KZdenhzBd7X7Q/vmaOSyvFz1CGdoVt26xzCZjlkU9lfBEK+V/ougGys7iYDi0+tOHIQSQa87bIqx95R7GU7I9Q==" ).execute(); new SRIScriptTest( true, "Same-origin with empty integrity.", - "matching-digest.js", + `${same_origin_prefix}script.js?${token()}`, "" ).execute(); new SRIScriptTest( false, "Same-origin with incorrect hash.", - "non-matching-digest.js", + `${same_origin_prefix}script.js?${token()}`, "sha256-deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdead" ).execute(); new SRIScriptTest( true, "Same-origin with multiple sha256 hashes, including correct.", - "matching-digest.js", - "sha256-U9WYDtBWkcHx13+9UKk/3Q5eoqDc4YGxYb07EPWzb9E= sha256-deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdead" + `${same_origin_prefix}script.js?${token()}`, + "sha256-Bu681KMnQ15RYHFvsYdWumweeFAw0hJDTFt9seErghA= sha256-deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdead" ).execute(); new SRIScriptTest( true, "Same-origin with multiple sha256 hashes, including unknown algorithm.", - "matching-digest.js", - "sha256-U9WYDtBWkcHx13+9UKk/3Q5eoqDc4YGxYb07EPWzb9E= foo666-deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdead" + `${same_origin_prefix}script.js?${token()}`, + "sha256-Bu681KMnQ15RYHFvsYdWumweeFAw0hJDTFt9seErghA= foo666-deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdead" ).execute(); new SRIScriptTest( true, "Same-origin with sha256 mismatch, sha512 match", - "matching-digest.js", - "sha512-geByvIIRspbnUnwooKGNNCb39nvg+EW0O9hDScTXeo/9pVZztLSUYU3LNV6H0lZapo8bCJUpyPPLAzE9fDzpxg== sha256-deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdead" + `${same_origin_prefix}script.js?${token()}`, + "sha512-KZdenhzBd7X7Q/vmaOSyvFz1CGdoVt26xzCZjlkU9lfBEK+V/ougGys7iYDi0+tOHIQSQa87bIqx95R7GU7I9Q== sha256-deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdead" ).execute(); new SRIScriptTest( false, "Same-origin with sha256 match, sha512 mismatch", - "matching-digest.js", - "sha512-deadbeefspbnUnwooKGNNCb39nvg+EW0O9hDScTXeo/9pVZztLSUYU3LNV6H0lZapo8bCJUpyPPLAzE9fDzpxg== sha256-U9WYDtBWkcHx13+9UKk/3Q5eoqDc4YGxYb07EPWzb9E=" + `${same_origin_prefix}script.js?${token()}`, + "sha512-deadbeefspbnUnwooKGNNCb39nvg+EW0O9hDScTXeo/9pVZztLSUYU3LNV6H0lZapo8bCJUpyPPLAzE9fDzpxg== sha256-Bu681KMnQ15RYHFvsYdWumweeFAw0hJDTFt9seErghA=" ).execute(); new SRIScriptTest( true, "<crossorigin='anonymous'> with correct hash, ACAO: *", - xorigin_anon_script, - "sha256-51AjITq701Y0yKSx3/UoIKtIY2UQ9+H8WGyyMuOWOC0=", + `${xorigin_prefix}script.js?${token()}&pipe=header(Access-Control-Allow-Origin,*)`, + "sha256-Bu681KMnQ15RYHFvsYdWumweeFAw0hJDTFt9seErghA=", "anonymous" ).execute(); new SRIScriptTest( false, "<crossorigin='anonymous'> with incorrect hash, ACAO: *", - xorigin_anon_script, + `${xorigin_prefix}script.js?${token()}&pipe=header(Access-Control-Allow-Origin,*)`, "sha256-deadbeefcSLlbFZCj1OACLxTxVck2TOrBTEdUbwz1yU=", "anonymous" ).execute(); @@ -157,15 +106,15 @@ new SRIScriptTest( true, "<crossorigin='use-credentials'> with correct hash, CORS-eligible", - xorigin_creds_script, - "sha256-IaGApVboXPQxVSm2wVFmhMq1Yu37gWklajgMdxKLIvc=", + `${xorigin_prefix}script.js?${token()}&pipe=header(Access-Control-Allow-Credentials,true)|header(Access-Control-Allow-Origin,${location.origin})`, + "sha256-Bu681KMnQ15RYHFvsYdWumweeFAw0hJDTFt9seErghA=", "use-credentials" ).execute(); new SRIScriptTest( false, "<crossorigin='use-credentials'> with incorrect hash CORS-eligible", - xorigin_creds_script, + `${xorigin_prefix}script.js?${token()}&pipe=header(Access-Control-Allow-Credentials,true)|header(Access-Control-Allow-Origin,${location.origin})`, "sha256-deadbeef2S+pTRZgiw3DWrhC6JLDlt2zRyGpwH7unU8=", "use-credentials" ).execute(); @@ -173,43 +122,43 @@ new SRIScriptTest( false, "<crossorigin='anonymous'> with CORS-ineligible resource", - xorigin_ineligible_script, - "sha256-F5fXKTX7SiWjtgybxiBZIo2qhh2WiQnNx372E60XrOo=", + `${xorigin_prefix}script.js?${token()}`, /* no ACAO header makes this CORS-ineligible */ + "sha256-Bu681KMnQ15RYHFvsYdWumweeFAw0hJDTFt9seErghA=", "anonymous" ).execute(); new SRIScriptTest( false, "Cross-origin, not CORS request, with correct hash", - xorigin_anon_script, - "sha256-51AjITq701Y0yKSx3/UoIKtIY2UQ9+H8WGyyMuOWOC0=" + `${xorigin_prefix}script.js?${token()}&pipe=header(Access-Control-Allow-Origin,*)`, + "sha256-Bu681KMnQ15RYHFvsYdWumweeFAw0hJDTFt9seErghA=" ).execute(); new SRIScriptTest( false, "Cross-origin, not CORS request, with hash mismatch", - xorigin_anon_script, + `${xorigin_prefix}script.js?${token()}&pipe=header(Access-Control-Allow-Origin,*)`, "sha256-deadbeef01Y0yKSx3/UoIKtIY2UQ9+H8WGyyMuOWOC0=" ).execute(); new SRIScriptTest( true, "Cross-origin, empty integrity", - xorigin_anon_script, + `${xorigin_prefix}script.js?${token()}&pipe=header(Access-Control-Allow-Origin,*)`, "" ).execute(); new SRIScriptTest( true, "Same-origin with correct hash, options.", - "matching-digest.js", - "sha256-U9WYDtBWkcHx13+9UKk/3Q5eoqDc4YGxYb07EPWzb9E=?foo=bar?spam=eggs" + `${same_origin_prefix}script.js?${token()}`, + "sha256-Bu681KMnQ15RYHFvsYdWumweeFAw0hJDTFt9seErghA=?foo=bar?spam=eggs" ).execute(); new SRIScriptTest( true, "Same-origin with unknown algorithm only.", - "matching-digest.js", + `${same_origin_prefix}script.js?${token()}`, "foo666-U9WYDtBWkcHx13+9UKk/3Q5eoqDc4YGxYb07EPWzb9E=" ).execute();
diff --git a/third_party/blink/web_tests/external/wpt/tools/wpt/run.py b/third_party/blink/web_tests/external/wpt/tools/wpt/run.py index 0d7fa22..fec2afc 100644 --- a/third_party/blink/web_tests/external/wpt/tools/wpt/run.py +++ b/third_party/blink/web_tests/external/wpt/tools/wpt/run.py
@@ -357,6 +357,8 @@ if kwargs["browser_channel"] == "dev": logger.info("Automatically turning on experimental features for Edge Dev") kwargs["binary_args"].append("--enable-experimental-web-platform-features") + # HACK(Hexcles): work around https://github.com/web-platform-tests/wpt/issues/17403 + kwargs["webdriver_args"].append("--disable-build-check") class Edge(BrowserSetup):
diff --git a/third_party/blink/web_tests/fast/loader/hashchange-event-expected.txt b/third_party/blink/web_tests/fast/loader/hashchange-event-expected.txt index 8e69dc91..d6dd0c2 100644 --- a/third_party/blink/web_tests/fast/loader/hashchange-event-expected.txt +++ b/third_party/blink/web_tests/fast/loader/hashchange-event-expected.txt
@@ -22,6 +22,12 @@ ALERT: Test number 1. hashchange event received by body-onhashchange-attribute. A total of 8 events have been received. +ALERT: Test number 1. +hashchange event received by window-event-listener. +A total of 9 events have been received. +ALERT: Test number 1. +hashchange event received by body-onhashchange-attribute. +A total of 10 events have been received. ALERT: Test number 2. hashchange event received by window-event-listener. A total of 1 events have been received.
diff --git a/third_party/blink/web_tests/fast/loader/hashchange-event.html b/third_party/blink/web_tests/fast/loader/hashchange-event.html index 44bbcba..e5535606 100644 --- a/third_party/blink/web_tests/fast/loader/hashchange-event.html +++ b/third_party/blink/web_tests/fast/loader/hashchange-event.html
@@ -7,7 +7,7 @@ location.href = "http://webkit.org/"; } -var targetNumberOfEventsForFirstTest = 8; +var targetNumberOfEventsForFirstTest = 10; var targetNumberOfEventsForSecondTest = 10; var testNumber = 1;
diff --git a/third_party/blink/web_tests/http/tests/loading/location-hash-reload-cycle-expected.txt b/third_party/blink/web_tests/http/tests/loading/location-hash-reload-cycle-expected.txt index 0fd9419b..b549b5aa 100644 --- a/third_party/blink/web_tests/http/tests/loading/location-hash-reload-cycle-expected.txt +++ b/third_party/blink/web_tests/http/tests/loading/location-hash-reload-cycle-expected.txt
@@ -3,6 +3,7 @@ main frame - didCommitLoadForFrame main frame - didReceiveTitle: main frame - didFinishDocumentLoadForFrame +main frame - didCommitLoadForFrame main frame - didHandleOnloadEventsForFrame main frame - didFinishLoadForFrame This test checks that no loader actions occur when setting window.location.hash to the empty string or "#". If this test fails when run in a browser, it will reload continuously. If this test fails when run in DumpRenderTree, the FrameLoader callback output will contain willPerformClientRedirectToURL callbacks.
diff --git a/third_party/blink/web_tests/http/tests/loading/location-hash-reload-cycle.html b/third_party/blink/web_tests/http/tests/loading/location-hash-reload-cycle.html index 7dc51bc..768c814 100644 --- a/third_party/blink/web_tests/http/tests/loading/location-hash-reload-cycle.html +++ b/third_party/blink/web_tests/http/tests/loading/location-hash-reload-cycle.html
@@ -5,7 +5,7 @@ { if (window.testRunner) testRunner.dumpAsText(); - + window.location.hash = ""; window.location.hash = "#"; }
diff --git a/third_party/blink/web_tests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt b/third_party/blink/web_tests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt index 25dc01c..1ae3824 100644 --- a/third_party/blink/web_tests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt +++ b/third_party/blink/web_tests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
@@ -1504,7 +1504,6 @@ attribute ELEMENT_ARRAY_BUFFER attribute ELEMENT_ARRAY_BUFFER_BINDING attribute EQUAL - attribute FALSE attribute FASTEST attribute FLOAT attribute FLOAT_32_UNSIGNED_INT_24_8_REV @@ -1935,7 +1934,6 @@ attribute TRIANGLES attribute TRIANGLE_FAN attribute TRIANGLE_STRIP - attribute TRUE attribute TYPE attribute UNIFORM attribute UNIFORM_ARRAY_STRIDE
diff --git a/third_party/blink/web_tests/media/video-played.js b/third_party/blink/web_tests/media/video-played.js index 47793af6..0f81639 100644 --- a/third_party/blink/web_tests/media/video-played.js +++ b/third_party/blink/web_tests/media/video-played.js
@@ -77,5 +77,5 @@ function startPlayingInNewRange(t, expectedStartTimes) { willCreateNewRange(expectedStartTimes); - playForDuration(0.1, t); + playForDuration(0.3, t); }
diff --git a/third_party/blink/web_tests/platform/linux/external/wpt/payment-handler/change-payment-method-manual.https-expected.txt b/third_party/blink/web_tests/platform/linux/external/wpt/payment-handler/change-payment-method-manual.https-expected.txt new file mode 100644 index 0000000..099831a --- /dev/null +++ b/third_party/blink/web_tests/platform/linux/external/wpt/payment-handler/change-payment-method-manual.https-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +FAIL Tests for PaymentRequestEvent.changePaymentMethod() Not allowed to install this payment handler +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/linux/virtual/layout_ng_experimental/printing/thead-tfoot-containing-svg-repeat-expected.png b/third_party/blink/web_tests/platform/linux/virtual/layout_ng_experimental/printing/thead-tfoot-containing-svg-repeat-expected.png deleted file mode 100644 index 646bce6..0000000 --- a/third_party/blink/web_tests/platform/linux/virtual/layout_ng_experimental/printing/thead-tfoot-containing-svg-repeat-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/layout_ng_experimental/printing/thead-tfoot-containing-svg-repeat-extra-pages-expected.png b/third_party/blink/web_tests/platform/linux/virtual/layout_ng_experimental/printing/thead-tfoot-containing-svg-repeat-extra-pages-expected.png deleted file mode 100644 index f68cef2..0000000 --- a/third_party/blink/web_tests/platform/linux/virtual/layout_ng_experimental/printing/thead-tfoot-containing-svg-repeat-extra-pages-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.10/external/wpt/payment-handler/change-payment-method-manual.https-expected.txt b/third_party/blink/web_tests/platform/mac-mac10.10/external/wpt/payment-handler/change-payment-method-manual.https-expected.txt new file mode 100644 index 0000000..099831a --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac10.10/external/wpt/payment-handler/change-payment-method-manual.https-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +FAIL Tests for PaymentRequestEvent.changePaymentMethod() Not allowed to install this payment handler +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/mac-mac10.11/external/wpt/payment-handler/change-payment-method-manual.https-expected.txt b/third_party/blink/web_tests/platform/mac-mac10.11/external/wpt/payment-handler/change-payment-method-manual.https-expected.txt new file mode 100644 index 0000000..099831a --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac10.11/external/wpt/payment-handler/change-payment-method-manual.https-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +FAIL Tests for PaymentRequestEvent.changePaymentMethod() Not allowed to install this payment handler +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/external/wpt/payment-handler/change-payment-method-manual.https-expected.txt b/third_party/blink/web_tests/platform/mac-mac10.12/external/wpt/payment-handler/change-payment-method-manual.https-expected.txt new file mode 100644 index 0000000..099831a --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac10.12/external/wpt/payment-handler/change-payment-method-manual.https-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +FAIL Tests for PaymentRequestEvent.changePaymentMethod() Not allowed to install this payment handler +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/mac-retina/external/wpt/payment-handler/change-payment-method-manual.https-expected.txt b/third_party/blink/web_tests/platform/mac-retina/external/wpt/payment-handler/change-payment-method-manual.https-expected.txt new file mode 100644 index 0000000..099831a --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-retina/external/wpt/payment-handler/change-payment-method-manual.https-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +FAIL Tests for PaymentRequestEvent.changePaymentMethod() Not allowed to install this payment handler +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/mac/external/wpt/payment-handler/change-payment-method-manual.https-expected.txt b/third_party/blink/web_tests/platform/mac/external/wpt/payment-handler/change-payment-method-manual.https-expected.txt new file mode 100644 index 0000000..099831a --- /dev/null +++ b/third_party/blink/web_tests/platform/mac/external/wpt/payment-handler/change-payment-method-manual.https-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +FAIL Tests for PaymentRequestEvent.changePaymentMethod() Not allowed to install this payment handler +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/mac/virtual/layout_ng_experimental/printing/composited-thead-tfoot-repeat-expected.png b/third_party/blink/web_tests/platform/mac/virtual/layout_ng_experimental/printing/composited-thead-tfoot-repeat-expected.png new file mode 100644 index 0000000..797ef0d --- /dev/null +++ b/third_party/blink/web_tests/platform/mac/virtual/layout_ng_experimental/printing/composited-thead-tfoot-repeat-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/layout_ng_experimental/printing/thead-tfoot-containing-svg-repeat-expected.png b/third_party/blink/web_tests/platform/mac/virtual/layout_ng_experimental/printing/thead-tfoot-containing-svg-repeat-expected.png deleted file mode 100644 index 6259647..0000000 --- a/third_party/blink/web_tests/platform/mac/virtual/layout_ng_experimental/printing/thead-tfoot-containing-svg-repeat-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/layout_ng_experimental/printing/thead-tfoot-containing-svg-repeat-extra-pages-expected.png b/third_party/blink/web_tests/platform/mac/virtual/layout_ng_experimental/printing/thead-tfoot-containing-svg-repeat-extra-pages-expected.png deleted file mode 100644 index 3b930031..0000000 --- a/third_party/blink/web_tests/platform/mac/virtual/layout_ng_experimental/printing/thead-tfoot-containing-svg-repeat-extra-pages-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/external/wpt/payment-handler/change-payment-method-manual.https-expected.txt b/third_party/blink/web_tests/platform/win/external/wpt/payment-handler/change-payment-method-manual.https-expected.txt new file mode 100644 index 0000000..099831a --- /dev/null +++ b/third_party/blink/web_tests/platform/win/external/wpt/payment-handler/change-payment-method-manual.https-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +FAIL Tests for PaymentRequestEvent.changePaymentMethod() Not allowed to install this payment handler +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/win/virtual/layout_ng_experimental/printing/thead-tfoot-containing-svg-repeat-expected.png b/third_party/blink/web_tests/platform/win/virtual/layout_ng_experimental/printing/thead-tfoot-containing-svg-repeat-expected.png deleted file mode 100644 index f80a414..0000000 --- a/third_party/blink/web_tests/platform/win/virtual/layout_ng_experimental/printing/thead-tfoot-containing-svg-repeat-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/layout_ng_experimental/printing/thead-tfoot-containing-svg-repeat-extra-pages-expected.png b/third_party/blink/web_tests/platform/win/virtual/layout_ng_experimental/printing/thead-tfoot-containing-svg-repeat-extra-pages-expected.png deleted file mode 100644 index 315db16..0000000 --- a/third_party/blink/web_tests/platform/win/virtual/layout_ng_experimental/printing/thead-tfoot-containing-svg-repeat-extra-pages-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/external/wpt/payment-handler/change-payment-method-manual.https-expected.txt b/third_party/blink/web_tests/platform/win7/external/wpt/payment-handler/change-payment-method-manual.https-expected.txt new file mode 100644 index 0000000..099831a --- /dev/null +++ b/third_party/blink/web_tests/platform/win7/external/wpt/payment-handler/change-payment-method-manual.https-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +FAIL Tests for PaymentRequestEvent.changePaymentMethod() Not allowed to install this payment handler +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt b/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt index 254d144..cb0882f 100644 --- a/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt +++ b/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt
@@ -1549,7 +1549,6 @@ [Worker] attribute ELEMENT_ARRAY_BUFFER [Worker] attribute ELEMENT_ARRAY_BUFFER_BINDING [Worker] attribute EQUAL -[Worker] attribute FALSE [Worker] attribute FASTEST [Worker] attribute FLOAT [Worker] attribute FLOAT_32_UNSIGNED_INT_24_8_REV @@ -1980,7 +1979,6 @@ [Worker] attribute TRIANGLES [Worker] attribute TRIANGLE_FAN [Worker] attribute TRIANGLE_STRIP -[Worker] attribute TRUE [Worker] attribute TYPE [Worker] attribute UNIFORM [Worker] attribute UNIFORM_ARRAY_STRIDE
diff --git a/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt b/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt index df0b724e..c1237a1 100644 --- a/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt +++ b/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt
@@ -8310,7 +8310,6 @@ attribute ELEMENT_ARRAY_BUFFER attribute ELEMENT_ARRAY_BUFFER_BINDING attribute EQUAL - attribute FALSE attribute FASTEST attribute FLOAT attribute FLOAT_32_UNSIGNED_INT_24_8_REV @@ -8741,7 +8740,6 @@ attribute TRIANGLES attribute TRIANGLE_FAN attribute TRIANGLE_STRIP - attribute TRUE attribute TYPE attribute UNIFORM attribute UNIFORM_ARRAY_STRIDE
diff --git a/third_party/blink/web_tests/webexposed/global-interface-listing-shared-worker-expected.txt b/third_party/blink/web_tests/webexposed/global-interface-listing-shared-worker-expected.txt index e2386af..8575d5f 100644 --- a/third_party/blink/web_tests/webexposed/global-interface-listing-shared-worker-expected.txt +++ b/third_party/blink/web_tests/webexposed/global-interface-listing-shared-worker-expected.txt
@@ -1413,7 +1413,6 @@ [Worker] attribute ELEMENT_ARRAY_BUFFER [Worker] attribute ELEMENT_ARRAY_BUFFER_BINDING [Worker] attribute EQUAL -[Worker] attribute FALSE [Worker] attribute FASTEST [Worker] attribute FLOAT [Worker] attribute FLOAT_32_UNSIGNED_INT_24_8_REV @@ -1844,7 +1843,6 @@ [Worker] attribute TRIANGLES [Worker] attribute TRIANGLE_FAN [Worker] attribute TRIANGLE_STRIP -[Worker] attribute TRUE [Worker] attribute TYPE [Worker] attribute UNIFORM [Worker] attribute UNIFORM_ARRAY_STRIDE
diff --git a/third_party/blink/web_tests/wpt_internal/display-lock/paint/locked-image-doesnt-paint-contents-ref.html b/third_party/blink/web_tests/wpt_internal/display-lock/paint/locked-image-doesnt-paint-contents-ref.html new file mode 100644 index 0000000..55a5f7c --- /dev/null +++ b/third_party/blink/web_tests/wpt_internal/display-lock/paint/locked-image-doesnt-paint-contents-ref.html
@@ -0,0 +1,24 @@ +<!doctype HTML> +<html> +<meta charset="utf8"> +<title>Display Locking: image locking (reference)</title> +<link rel="author" title="Vladimir Levin" href="mailto:vmpstr@chromium.org"> +<link rel="help" href="https://github.com/WICG/display-locking"> + +<style> +div { + background: blue; +} +.myimg { + display: inline-block; + width: 400px; + height: 200px; + background: lightblue; + border: 1px solid black; +} +</style> + +<div>lorem ipsum</div> +<div class="myimg"></div> +<div class="myimg"></div> +<div>consectetur adipiscing elit</div>
diff --git a/third_party/blink/web_tests/wpt_internal/display-lock/paint/locked-image-doesnt-paint-contents.html b/third_party/blink/web_tests/wpt_internal/display-lock/paint/locked-image-doesnt-paint-contents.html new file mode 100644 index 0000000..6e911a2 --- /dev/null +++ b/third_party/blink/web_tests/wpt_internal/display-lock/paint/locked-image-doesnt-paint-contents.html
@@ -0,0 +1,43 @@ +<!doctype HTML> +<html class="reftest-wait"> +<meta charset="utf8"> +<title>Display Locking: image locking</title> +<link rel="author" title="Vladimir Levin" href="mailto:vmpstr@chromium.org"> +<link rel="help" href="https://github.com/WICG/display-locking"> +<link rel="match" href="locked-image-doesnt-paint-contents-ref.html"> +<script src="/common/reftest-wait.js"></script> + +<style> +div { + background: blue; +} +img { + contain: style layout; + width: 400px; + height: 200px; + background: lightblue; + border: 1px solid black; +} +</style> + +<div>lorem ipsum</div> +<img id="img1" src="resources/dice.png"></img> +<img id="img2" src="resources/circles.svg"></img> +<div>consectetur adipiscing elit</div> + +<script> +async function runTest() { + const promises = []; + promises.push(document.getElementById("img1").displayLock.acquire({ timeout: Infinity })); + promises.push(document.getElementById("img2").displayLock.acquire({ timeout: Infinity })); + await Promise.all(promises); + takeScreenshot(); +} + +window.onload = () => { + requestAnimationFrame(() => { + requestAnimationFrame(runTest); + }); +}; +</script> +</html>
diff --git a/third_party/blink/web_tests/wpt_internal/display-lock/paint/locked-svg-doesnt-paint-contents-ref.html b/third_party/blink/web_tests/wpt_internal/display-lock/paint/locked-svg-doesnt-paint-contents-ref.html new file mode 100644 index 0000000..5b5aa52 --- /dev/null +++ b/third_party/blink/web_tests/wpt_internal/display-lock/paint/locked-svg-doesnt-paint-contents-ref.html
@@ -0,0 +1,23 @@ +<!doctype HTML> +<html> +<meta charset="utf8"> +<title>Display Locking: image locking (reference)</title> +<link rel="author" title="Vladimir Levin" href="mailto:vmpstr@chromium.org"> +<link rel="help" href="https://github.com/WICG/display-locking"> + +<style> +div { + background: blue; +} +.mysvg { + display: inline-block; + width: 400px; + height: 300px; + background: lightblue; + border: 1px solid black; +} +</style> + +<div>lorem ipsum</div> +<div class="mysvg"></div> +<div>consectetur adipiscing elit</div>
diff --git a/third_party/blink/web_tests/wpt_internal/display-lock/paint/locked-svg-doesnt-paint-contents.html b/third_party/blink/web_tests/wpt_internal/display-lock/paint/locked-svg-doesnt-paint-contents.html new file mode 100644 index 0000000..6bf5801 --- /dev/null +++ b/third_party/blink/web_tests/wpt_internal/display-lock/paint/locked-svg-doesnt-paint-contents.html
@@ -0,0 +1,49 @@ +<!doctype HTML> +<html class="reftest-wait"> +<meta charset="utf8"> +<title>Display Locking: svg locking</title> +<link rel="author" title="Vladimir Levin" href="mailto:vmpstr@chromium.org"> +<link rel="help" href="https://github.com/WICG/display-locking"> +<link rel="match" href="locked-svg-doesnt-paint-contents-ref.html"> +<script src="/common/reftest-wait.js"></script> + +<style> +div { + background: blue; +} +svg { + contain: style layout; + border: 1px solid black; + background: lightblue; +} +</style> + +<div>lorem ipsum</div> +<svg xmlns="http://www.w3.org/2000/svg" width="400" height="300" viewBox="0 0 400 300" id="svg"> + <g stroke-width="10" transform="translate(-30)"> + <circle cx="80" cy="50" r="35" fill="#084" stroke="none"/> + <circle cx="80" cy="50" r="20" fill="#080" stroke="#FF0"/> + <circle cx="80" cy="120" r="35" fill="#004" stroke="none"/> + <circle cx="80" cy="120" r="20" fill="#080" stroke="#FF0"/> + <circle cx="80" cy="190" r="35" fill="#088" stroke="none"/> + <circle cx="80" cy="190" r="20" fill="#080" stroke="#FF0"/> + <circle cx="80" cy="260" r="35" fill="#008" stroke="none"/> + <circle cx="80" cy="260" r="20" fill="#080" stroke="#FF0"/> + </g> +</svg> +<div>consectetur adipiscing elit</div> + +<script> +async function runTest() { + const container = document.getElementById("svg"); + await container.displayLock.acquire({ timeout: Infinity }); + takeScreenshot(); +} + +window.onload = () => { + requestAnimationFrame(() => { + requestAnimationFrame(runTest); + }); +}; +</script> +</html>
diff --git a/third_party/blink/web_tests/wpt_internal/display-lock/paint/resources/circles.svg b/third_party/blink/web_tests/wpt_internal/display-lock/paint/resources/circles.svg new file mode 100644 index 0000000..1a9ad75 --- /dev/null +++ b/third_party/blink/web_tests/wpt_internal/display-lock/paint/resources/circles.svg
@@ -0,0 +1,37 @@ +<?xml version="1.0" encoding="iso-8859-1" ?> +<svg viewBox="0 0 500 300" xmlns="http://www.w3.org/2000/svg"> +<rect x="0" y="0" width="500" height="300" fill="#fff" /> + +<g stroke-width="10" transform="translate(-30)"> + <circle cx="80" cy="50" r="35" fill="#084" stroke="none"/> + <circle cx="80" cy="50" r="20" fill="#080" stroke="#FF0"/> + <circle cx="80" cy="120" r="35" fill="#004" stroke="none"/> + <circle cx="80" cy="120" r="20" fill="#080" stroke="#FF0"/> + <circle cx="80" cy="190" r="35" fill="#088" stroke="none"/> + <circle cx="80" cy="190" r="20" fill="#080" stroke="#FF0"/> + <circle cx="80" cy="260" r="35" fill="#008" stroke="none"/> + <circle cx="80" cy="260" r="20" fill="#080" stroke="#FF0"/> +</g> + +<g stroke-width="10" transform="translate(170)"> + <circle cx="80" cy="50" r="35" fill="#085" stroke="none"/> + <circle cx="80" cy="50" r="20" fill="#080" stroke="#FF0"/> + <circle cx="80" cy="120" r="35" fill="#005" stroke="none"/> + <circle cx="80" cy="120" r="20" fill="#080" stroke="#FF0"/> + <circle cx="80" cy="190" r="35" fill="#689" stroke="none"/> + <circle cx="80" cy="190" r="20" fill="#080" stroke="#FF0"/> + <circle cx="80" cy="260" r="35" fill="#609" stroke="none"/> + <circle cx="80" cy="260" r="20" fill="#080" stroke="#FF0"/> +</g> + +<g stroke-width="10" transform="translate(370)"> + <circle cx="80" cy="50" r="35" fill="#084" stroke="none"/> + <circle cx="80" cy="50" r="20" fill="#080" stroke="#FF0"/> + <circle cx="80" cy="120" r="35" fill="#084" stroke="none"/> + <circle cx="80" cy="120" r="20" fill="#080" stroke="#FF0"/> + <circle cx="80" cy="190" r="35" fill="#088" stroke="none"/> + <circle cx="80" cy="190" r="20" fill="#080" stroke="#FF0"/> + <circle cx="80" cy="260" r="35" fill="#088" stroke="none"/> + <circle cx="80" cy="260" r="20" fill="#080" stroke="#FF0"/> +</g> +</svg>
diff --git a/third_party/blink/web_tests/wpt_internal/display-lock/paint/resources/dice.png b/third_party/blink/web_tests/wpt_internal/display-lock/paint/resources/dice.png new file mode 100644 index 0000000..f18b8141 --- /dev/null +++ b/third_party/blink/web_tests/wpt_internal/display-lock/paint/resources/dice.png Binary files differ
diff --git a/third_party/blink/web_tests/wpt_internal/display-lock/sizing/layout-replaced-ref.html b/third_party/blink/web_tests/wpt_internal/display-lock/sizing/layout-replaced-ref.html index 1ac35c6..581031b 100644 --- a/third_party/blink/web_tests/wpt_internal/display-lock/sizing/layout-replaced-ref.html +++ b/third_party/blink/web_tests/wpt_internal/display-lock/sizing/layout-replaced-ref.html
@@ -14,6 +14,7 @@ contain: style layout; width: 12px; height: 34px; + visibility: hidden; } </style>
diff --git a/third_party/blink/web_tests/wpt_internal/std-switch/README.md b/third_party/blink/web_tests/wpt_internal/std-switch/README.md new file mode 100644 index 0000000..e8a6d127 --- /dev/null +++ b/third_party/blink/web_tests/wpt_internal/std-switch/README.md
@@ -0,0 +1,5 @@ +# Tests for std-switch + +https://github.com/tkent-google/std-switch/blob/master/README.md + +Tests in tentative/ should be upstreamed to WPT in the future.
diff --git a/third_party/blink/web_tests/wpt_internal/std-switch/tentative/form-associated-basic.js b/third_party/blink/web_tests/wpt_internal/std-switch/tentative/form-associated-basic.js new file mode 100644 index 0000000..988a71f --- /dev/null +++ b/third_party/blink/web_tests/wpt_internal/std-switch/tentative/form-associated-basic.js
@@ -0,0 +1,97 @@ +const HTML_DOM = '/html/dom/'; + +function loadScript(src) { + return new Promise((resolve, reject) => { + let script = document.createElement('script'); + script.src = src; + script.addEventListener('load', e => resolve(), {once: true}); + script.addEventListener('error', e => reject(), {once: true}); + document.body.appendChild(script); + }); +} + +function formAssociatedTests(tag, reflectionDict) { + test(() => { + let control = document.createElement(tag); + assert_equals(control.type, tag); + }, `${tag} supports type property`); + + test(() => { + let control = document.createElement(tag); + assert_equals(control.form, null); + + let form1 = document.createElement('form'); + form1.appendChild(control); + assert_equals(control.form, form1); + + let form2 = document.createElement('form'); + form2.id = 'connected-form'; + document.body.appendChild(form2); + control.setAttribute('form', 'connected-form'); + control.remove(); + assert_equals(control.form, null); + document.body.appendChild(control); + assert_equals(control.form, document.getElementById('connected-form')); + }, `${tag} supports form property`); + + test(() => { + let control = document.createElement(tag); + assert_true(control.willValidate); + control.setAttribute('disabled', ''); + assert_false(control.willValidate); + control.removeAttribute('disabled'); + let datalist = document.createElement('datalist'); + datalist.appendChild(control); + assert_false(control.willValidate); + }, `${tag} supports willValidate property`); + + test(() => { + let control = document.createElement(tag); + assert_true(control.validity.valid); + assert_false(control.validity.customError); + assert_equals(control.validationMessage, ''); + assert_true(control.checkValidity(), '1: ' + control); + assert_true(control.reportValidity()); + + control.setCustomValidity('Invalid!'); + assert_false(control.validity.valid); + assert_true(control.validity.customError); + assert_equals(control.validationMessage, 'Invalid!'); + assert_false(control.checkValidity(), '2: ' + control); + assert_false(control.reportValidity()); + }, `${tag} supports form validation`); + + test(() => { + let control = document.createElement(tag); + assert_equals(control.labels.length, 0); + + let label = document.createElement('label'); + document.body.appendChild(label); + label.appendChild(control); + assert_array_equals(control.labels, [label], 'descendant association'); + assert_equals(label.control, control); + + document.body.appendChild(control); + document.body.appendChild(label); + assert_equals(control.labels.length, 0); + control.id = 'control'; + label.htmlFor = 'control'; + assert_array_equals(control.labels, [label], 'for= association'); + assert_equals(label.control, control); + }, `${tag} supports labels property`); + + promise_test(async () => { + await loadScript(HTML_DOM + 'original-harness.js'); + await loadScript(HTML_DOM + 'new-harness.js'); + let targetElements = {}; + targetElements[tag] = { + disabled: 'boolean', + name: 'string', + }; + for (let [key, value] of Object.entries(reflectionDict)) { + targetElements[tag][key] = value; + } + mergeElements(targetElements); + await loadScript(HTML_DOM + 'reflection.js'); + }, 'Setup reflection tests'); +}
diff --git a/third_party/blink/web_tests/wpt_internal/std-switch/tentative/import.html b/third_party/blink/web_tests/wpt_internal/std-switch/tentative/import.html new file mode 100644 index 0000000..33feb40e --- /dev/null +++ b/third_party/blink/web_tests/wpt_internal/std-switch/tentative/import.html
@@ -0,0 +1,22 @@ +<!DOCTYPE html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<body> +<script> +test(() => { + assert_not_own_property(window, 'StdSwitchElement'); + assert_true(document.createElement('std-switch') instanceof HTMLElement); +}, 'StdSwitchElement should not be available before import'); + +let t = async_test('StdSwitchElement should be available after import'); +</script> +<script type="module"> +import { StdSwitchElement } from 'std:elements/switch'; + +t.step(() => { + assert_not_own_property(window, 'StdSwitchElement'); + assert_true(document.createElement('std-switch') instanceof StdSwitchElement); + t.done(); +}); +</script> +</body>
diff --git a/third_party/blink/web_tests/wpt_internal/std-switch/tentative/interface.html b/third_party/blink/web_tests/wpt_internal/std-switch/tentative/interface.html new file mode 100644 index 0000000..d0aabcd5 --- /dev/null +++ b/third_party/blink/web_tests/wpt_internal/std-switch/tentative/interface.html
@@ -0,0 +1,51 @@ +<!DOCTYPE html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/resources/webidl2/lib/webidl2.js"></script> +<script src="/resources/idlharness.js"></script> +<script type="module"> +import { StdSwitchElement } from 'std:elements/switch'; + +const DEPS = ['html', 'SVG', 'cssom', 'touch-events', 'uievents', 'dom', 'xhr']; + +// WebIDL and idlharness.js are not capable of interfaces in a module. +const SWITCH_IDL = ` +[Exposed=Window, + Constructor()] +interface StdSwitchElement : HTMLElement { + [CEReactions] attribute boolean defaultOn; + [CEReactions] attribute boolean on; + + [CEReactions] attribute boolean disabled; + readonly attribute HTMLFormElement? form; + [CEReactions] attribute DOMString name; + readonly attribute DOMString type; + + readonly attribute boolean willValidate; + readonly attribute ValidityState validity; + readonly attribute DOMString validationMessage; + boolean checkValidity(); + boolean reportValidity(); + void setCustomValidity(DOMString error); + + readonly attribute NodeList labels; +};`; + +Object.defineProperty(window, 'StdSwitchElement', { + configurable: true, + enumerable: false, + value: StdSwitchElement, + writable: true, +}); + +promise_test(async () => { + let idlArray = new IdlArray(); + let dependentIdls = await Promise.all(DEPS.map(spec => { return fetch_spec(spec); })); + idlArray.add_idls(SWITCH_IDL); + for (let dep of dependentIdls) { + idlArray.add_dependency_idls(dep); + } + idlArray.add_objects({StdSwitchElement: ['document.createElement("std-switch")']}); + idlArray.test(); +}); +</script>
diff --git a/third_party/blink/web_tests/wpt_internal/std-switch/tentative/properties-functions.html b/third_party/blink/web_tests/wpt_internal/std-switch/tentative/properties-functions.html new file mode 100644 index 0000000..4f07751803 --- /dev/null +++ b/third_party/blink/web_tests/wpt_internal/std-switch/tentative/properties-functions.html
@@ -0,0 +1,14 @@ +<!DOCTYPE html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<body> +<script src="form-associated-basic.js"></script> +<script type=module> +import 'std:elements/switch'; + +formAssociatedTests('std-switch', { + defaultOn: {type: 'boolean', domAttrName: 'defaulton'}, + on: 'boolean' +}); +</script> +</body>
diff --git a/tools/clang/scripts/update.py b/tools/clang/scripts/update.py index 12831cfa..fd0dd559 100755 --- a/tools/clang/scripts/update.py +++ b/tools/clang/scripts/update.py
@@ -37,8 +37,8 @@ # Do NOT CHANGE this if you don't know what you're doing -- see # https://chromium.googlesource.com/chromium/src/+/master/docs/updating_clang.md # Reverting problematic clang rolls is safe, though. -CLANG_REVISION = '49b965079b18f8aa485dd1156dd088d40b7ee465' -CLANG_SVN_REVISION = '363450' +CLANG_REVISION = 'd874c057bc2361da5157553e1e2178f43c3ade1a' +CLANG_SVN_REVISION = '363790' CLANG_SUB_REVISION = 1 PACKAGE_VERSION = '%s-%s-%s' % (CLANG_SVN_REVISION, CLANG_REVISION[:8],
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index eebe8680..d5a3ceb 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -3382,6 +3382,7 @@ <int value="17" label="Get scripts failed"/> <int value="18" label="Get scripts unparsable"/> <int value="19" label="No initial scripts"/> + <int value="20" label="Installing the feature module failed"/> </enum> <enum name="AutofillAssistantOnBoarding"> @@ -33922,7 +33923,6 @@ <int value="-1308600417" label="NewNetErrorPageUI:disabled"/> <int value="-1304957199" label="OfflinePagesShowAlternateDinoPage:enabled"/> <int value="-1304758527" label="SyncSendTabToSelf:disabled"/> - <int value="-1303995589" label="shelf-new-ui"/> <int value="-1302904242" label="enable-navigation-tracing"/> <int value="-1302859198" label="enable-stylus-virtual-keyboard:disabled"/> <int value="-1294050129" label="ContentFullscreen:disabled"/> @@ -35168,6 +35168,7 @@ <int value="567368307" label="enable-experimental-canvas-features"/> <int value="575380532" label="ExperimentalAccessibilityLabels:disabled"/> <int value="575394365" label="AndroidPaymentApps:disabled"/> + <int value="575829120" label="shelf-hotseat"/> <int value="576701073" label="WebPaymentsJustInTimePaymentApp:disabled"/> <int value="576878329" label="enable-background-blur"/> <int value="581118445" label="enable-eol-notification"/> @@ -57433,6 +57434,9 @@ </enum> <enum name="UncacheableReason"> + <obsolete> + Deprecated 06/2019 in issue 975278. + </obsolete> <int value="0" label="kNoData"/> <int value="1" label="kPre11PartialResponse"/> <int value="2" label="kNoStrongValidatorOnPartialResponse"/> @@ -60847,6 +60851,11 @@ <int value="1" label="onReceivedClientCertRequest"/> <int value="2" label="onReceivedHttpAuthRequest"/> <int value="3" label="onDownloadStart"/> + <int value="4" label="onPageStarted"/> + <int value="5" label="onPageFinished"/> + <int value="6" label="onLoadResource"/> + <int value="7" label="onPageCommitVisible"/> + <int value="8" label="shouldOverrideUrlLoading"/> </enum> <enum name="WebViewClientErrorCode">
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index 65ffe90..e36ece1d 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -11286,7 +11286,7 @@ </histogram> <histogram name="BackgroundMode.BackgroundApplicationsCount" - expires_after="M77"> + expires_after="2020-02-01"> <owner>atwilson@chromium.org</owner> <owner>mvanouwerkerk@chromium.org</owner> <summary> @@ -11296,7 +11296,7 @@ </histogram> <histogram name="BackgroundMode.BackgroundModeEnabledPrefChanged" - enum="BooleanEnabled" expires_after="M77"> + enum="BooleanEnabled" expires_after="2020-02-01"> <owner>mvanouwerkerk@chromium.org</owner> <summary> Logged if BackgroundModeManager is running and listening for pref changes, @@ -11305,7 +11305,7 @@ </histogram> <histogram name="BackgroundMode.MenuItemClick" enum="BackgroundModeMenuItem" - expires_after="M77"> + expires_after="2020-02-01"> <owner>mvanouwerkerk@chromium.org</owner> <summary> Logged when an item in the system tray icon menu is clicked. @@ -11313,8 +11313,9 @@ </histogram> <histogram name="BackgroundMode.OnStartup.AutoLaunchState" - enum="AutoLaunchState" expires_after="2018-08-30"> + enum="AutoLaunchState" expires_after="2020-02-01"> <owner>gab@chromium.org</owner> + <owner>mvanouwerkerk@chromium.org</owner> <summary> Logged during BackgroundModeManager's initialization. Indicates the AutoLaunchState the current browser process was launched in. @@ -11322,16 +11323,19 @@ </histogram> <histogram name="BackgroundMode.OnStartup.IsBackgroundModePrefEnabled" - enum="BooleanEnabled" expires_after="2018-08-30"> + enum="BooleanEnabled" expires_after="2020-02-01"> <owner>gab@chromium.org</owner> + <owner>mvanouwerkerk@chromium.org</owner> <summary> Logged during BackgroundModeManager's initialization. Indicates the state of the kBackgroundModeEnabled pref on startup. </summary> </histogram> -<histogram name="BackgroundMode.TimeBeforeOptimizedRestart" units="ms"> +<histogram name="BackgroundMode.TimeBeforeOptimizedRestart" units="ms" + expires_after="2020-02-01"> <owner>peter@chromium.org</owner> + <owner>mvanouwerkerk@chromium.org</owner> <summary> The duration of a session before the browser got restarted in the background by the BackgroundOptimizer to purge the memory. @@ -39840,6 +39844,9 @@ </histogram> <histogram base="true" name="Extensions.LongInjectionTaskTime" units="ms"> + <obsolete> + Removed June 2019. + </obsolete> <owner>ksakamoto@chromium.org</owner> <summary> The amount of time taken to inject content scripts. If multiple scripts are @@ -40965,6 +40972,9 @@ <histogram base="true" name="Extensions.TimeYieldedBetweenContentScriptRuns" units="ms"> + <obsolete> + Removed June 2019. + </obsolete> <owner>ksakamoto@chromium.org</owner> <summary> Time elapsed between two asynchronously-injected content script runs. @@ -54765,6 +54775,9 @@ </histogram> <histogram name="Media.CacheUseful" enum="BooleanSuccess" expires_after="M77"> + <obsolete> + Deprecated 06/2019 in issue 975278. + </obsolete> <owner>dalecurtis@chromium.org</owner> <summary> Whether a media response might be used to satisfy a future request. @@ -57271,6 +57284,9 @@ <histogram name="Media.UncacheableReason" enum="UncacheableReason" expires_after="M77"> + <obsolete> + Deprecated 06/2019 in issue 975278. + </obsolete> <owner>dalecurtis@chromium.org</owner> <summary> Reasons a media response won't be used to satisfy a future request. @@ -69863,6 +69879,9 @@ <histogram name="Net.HttpTimeToFirstByte.LargeUpload" units="ms" expires_after="M77"> + <obsolete> + Deprecated 06/2019. + </obsolete> <owner>mmenke@chromium.org</owner> <summary> Time from when an HTTP request is issued to when the first byte is @@ -116528,7 +116547,7 @@ </histogram> <histogram name="ServiceWorker.ActivateEvent.Time" units="ms" - expires_after="M77"> + expires_after="2020-06-18"> <owner>shimazu@chromium.org</owner> <summary> Execution time of ServiceWorkerGlobalScope.onactivate. Includes the time for @@ -116549,7 +116568,7 @@ </histogram> <histogram name="ServiceWorker.ActivateEventStatus" - enum="ServiceWorkerStatusCode" expires_after="M77"> + enum="ServiceWorkerStatusCode" expires_after="2020-06-18"> <owner>falken@chromium.org</owner> <summary> The result of dispatching the activate event to the worker. This is recorded @@ -132130,6 +132149,9 @@ <histogram name="TabManager.Discarding.LogMemoryTime" units="ms" expires_after="M77"> + <obsolete> + Removed 06/2019, check Arc.LowMemoryKiller.FirstKillLatency instead. + </obsolete> <owner>cywang@chromium.org</owner> <owner>georgesak@chromium.org</owner> <summary> @@ -143676,6 +143698,9 @@ </histogram> <histogram name="WebFont.CORSSuccess" enum="BooleanSuccess" expires_after="M77"> + <obsolete> + Deprecated June 2019. + </obsolete> <owner>bashi@chromium.org</owner> <owner>kenjibaheux@chromium.org</owner> <summary>The success or failure of web fonts CORS-enabled fetching.</summary>
diff --git a/ui/accessibility/platform/ax_platform_node_auralinux.cc b/ui/accessibility/platform/ax_platform_node_auralinux.cc index faff790..86b8519 100644 --- a/ui/accessibility/platform/ax_platform_node_auralinux.cc +++ b/ui/accessibility/platform/ax_platform_node_auralinux.cc
@@ -199,17 +199,6 @@ return false; } -AtkObject* FindFirstAncestorThatEmitsAtkTextEvents(AtkObject* atk_object) { - if (!atk_object) - return nullptr; - - if (EmitsAtkTextEvents(atk_object)) - return atk_object; - - return FindFirstAncestorThatEmitsAtkTextEvents( - atk_object_get_parent(atk_object)); -} - bool IsFrameAncestorOfAtkObject(AtkObject* frame, AtkObject* atk_object) { AtkObject* current_frame = FindAtkObjectParentFrame(atk_object); while (current_frame) { @@ -341,6 +330,10 @@ return nullptr; } +bool SelectionOffsetsIndicateSelection(const std::pair<int, int>& offsets) { + return offsets.first >= 0 && offsets.second >= 0 && + offsets.first != offsets.second; +} namespace atk_component { @@ -3016,16 +3009,34 @@ } void AXPlatformNodeAuraLinux::OnTextSelectionChanged() { - AtkObject* object = FindFirstAncestorThatEmitsAtkTextEvents(atk_object_); - if (!object) + DCHECK(atk_object_); + if (!EmitsAtkTextEvents(atk_object_)) { + if (auto* parent = AtkObjectToAXPlatformNodeAuraLinux(GetParent())) + parent->OnTextSelectionChanged(); return; - - DCHECK(ATK_IS_TEXT(object)); - if (HasCaret()) { - g_signal_emit_by_name(object, "text-caret-moved", - atk_text_get_caret_offset(ATK_TEXT(object))); } - g_signal_emit_by_name(object, "text-selection-changed"); + + DCHECK(ATK_IS_TEXT(atk_object_)); + + std::pair<int, int> new_selection; + GetSelectionOffsets(&new_selection.first, &new_selection.second); + std::pair<int, int> old_selection = text_selection_; + text_selection_ = new_selection; + + // ATK does not consider a collapsed selection a selection, so + // when the collapsed selection changes (caret movement), we should + // avoid sending text-selection-changed events. + bool has_selection = SelectionOffsetsIndicateSelection(new_selection); + bool had_selection = SelectionOffsetsIndicateSelection(old_selection); + if (has_selection != had_selection || + (has_selection && new_selection != old_selection)) { + g_signal_emit_by_name(atk_object_, "text-selection-changed"); + } + + if (HasCaret() && new_selection.second != old_selection.second) { + g_signal_emit_by_name(atk_object_, "text-caret-moved", + UTF16ToUnicodeOffsetInText(new_selection.second)); + } } bool AXPlatformNodeAuraLinux::SupportsSelectionWithAtkSelection() { @@ -3636,10 +3647,9 @@ } bool AXPlatformNodeAuraLinux::HasSelection() { - int selection_start, selection_end; - GetSelectionOffsets(&selection_start, &selection_end); - return selection_start >= 0 && selection_end >= 0 && - selection_start != selection_end; + std::pair<int, int> selection; + GetSelectionOffsets(&selection.first, &selection.second); + return SelectionOffsetsIndicateSelection(selection); } void AXPlatformNodeAuraLinux::GetSelectionExtents(int* start_offset,
diff --git a/ui/accessibility/platform/ax_platform_node_auralinux.h b/ui/accessibility/platform/ax_platform_node_auralinux.h index 243de66..1f36fcb9 100644 --- a/ui/accessibility/platform/ax_platform_node_auralinux.h +++ b/ui/accessibility/platform/ax_platform_node_auralinux.h
@@ -8,6 +8,7 @@ #include <atk/atk.h> #include <string> +#include <utility> #include "base/macros.h" #include "base/optional.h" @@ -230,6 +231,11 @@ // minimized the last time it's visibility changed. bool was_minimized_ = false; + // The previously observed text selection for this node. We store + // this in order to avoid sending duplicate text-selection-changed + // and text-caret-moved events. + std::pair<int, int> text_selection_ = std::make_pair(-1, -1); + DISALLOW_COPY_AND_ASSIGN(AXPlatformNodeAuraLinux); };
diff --git a/ui/base/BUILD.gn b/ui/base/BUILD.gn index 59beb86..087e27c 100644 --- a/ui/base/BUILD.gn +++ b/ui/base/BUILD.gn
@@ -57,7 +57,6 @@ flags = [ "ENABLE_HIDPI=$enable_hidpi", "ENABLE_MESSAGE_CENTER=$enable_message_center", - "ENABLE_MUS=$enable_mus", "USE_ATK=$use_atk", "USE_XKBCOMMON=$use_xkbcommon", "HAS_NATIVE_ACCESSIBILITY=$has_native_accessibility",
diff --git a/ui/base/ui_base_features.cc b/ui/base/ui_base_features.cc index 396d1cc..0853c00 100644 --- a/ui/base/ui_base_features.cc +++ b/ui/base/ui_base_features.cc
@@ -120,11 +120,6 @@ }; #endif // defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX) -const base::Feature kMash = {"Mash", base::FEATURE_DISABLED_BY_DEFAULT}; - -const base::Feature kSingleProcessMash = {"SingleProcessMash", - base::FEATURE_DISABLED_BY_DEFAULT}; - const base::Feature kFormControlsRefresh = {"FormControlsRefresh", base::FEATURE_DISABLED_BY_DEFAULT}; @@ -132,19 +127,6 @@ return base::FeatureList::IsEnabled(features::kFormControlsRefresh); } -bool IsUsingWindowService() { - return IsSingleProcessMash() || IsMultiProcessMash(); -} - -bool IsMultiProcessMash() { - return base::FeatureList::IsEnabled(features::kMash); -} - -bool IsSingleProcessMash() { - return base::FeatureList::IsEnabled(features::kSingleProcessMash) && - !base::FeatureList::IsEnabled(features::kMash); -} - bool IsAutomaticUiAdjustmentsForTouchEnabled() { #if defined(OS_WIN) || defined(OS_CHROMEOS) return base::FeatureList::IsEnabled( @@ -169,8 +151,7 @@ base::FEATURE_DISABLED_BY_DEFAULT}; bool IsOzoneDrmMojo() { - return base::FeatureList::IsEnabled(kEnableOzoneDrmMojo) || - IsMultiProcessMash(); + return base::FeatureList::IsEnabled(kEnableOzoneDrmMojo); } #if defined(OS_CHROMEOS)
diff --git a/ui/base/ui_base_features.h b/ui/base/ui_base_features.h index 332d7c4..4f07ffb1 100644 --- a/ui/base/ui_base_features.h +++ b/ui/base/ui_base_features.h
@@ -64,35 +64,11 @@ extern const base::Feature kDirectManipulationStylus; #endif // defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX) -// Used to have ash (Chrome OS system UI) run in its own process. -// TODO(jamescook): Make flag only available in Chrome OS. -COMPONENT_EXPORT(UI_BASE_FEATURES) extern const base::Feature kMash; - -// NOTE: Do not access directly outside of tests. Use IsSingleProcessMash() -// to avoid problems when Mash and SingleProcessMash are both enabled. -COMPONENT_EXPORT(UI_BASE_FEATURES) -extern const base::Feature kSingleProcessMash; - // Used to enable the new controls UI. COMPONENT_EXPORT(UI_BASE_FEATURES) extern const base::Feature kFormControlsRefresh; COMPONENT_EXPORT(UI_BASE_FEATURES) bool IsFormControlsRefreshEnabled(); -// Returns true if Chrome's aura usage is backed by the WindowService. -COMPONENT_EXPORT(UI_BASE_FEATURES) bool IsUsingWindowService(); - -// Returns true if ash in running in a separate process (and is hosting the UI -// service and Viz graphics). See //ash/README.md. -COMPONENT_EXPORT(UI_BASE_FEATURES) bool IsMultiProcessMash(); - -// Returns true if code outside of ash is using the WindowService. In this mode -// there are two aura::Envs. Ash uses one with Env::Mode::LOCAL. Non-ash code -// uses an aura::Env with a mode of MUS. The non-ash code using mus targets the -// WindowService that ash is running. This exercises the WindowService mojo APIs -// similar to kMash, but leaves ash and browser running in the same process. -// See //ash/README.md. -COMPONENT_EXPORT(UI_BASE_FEATURES) bool IsSingleProcessMash(); - // Whether the UI may accommodate touch input in response to hardware changes. COMPONENT_EXPORT(UI_BASE_FEATURES) bool IsAutomaticUiAdjustmentsForTouchEnabled();
diff --git a/ui/base/ui_features.gni b/ui/base/ui_features.gni index 6ecd398d..88b0226 100644 --- a/ui/base/ui_features.gni +++ b/ui/base/ui_features.gni
@@ -13,9 +13,6 @@ # Whether the message center should be included for displaying notifications. enable_message_center = is_win || is_mac || is_linux || is_chromeos - - # Set to true to if mus (aka the window service) is enabled. - enable_mus = is_chromeos } enable_hidpi = is_mac || is_win || is_linux
diff --git a/ui/chromeos/ime/candidate_window_view.cc b/ui/chromeos/ime/candidate_window_view.cc index 97d801f36..c945c12 100644 --- a/ui/chromeos/ime/candidate_window_view.cc +++ b/ui/chromeos/ime/candidate_window_view.cc
@@ -10,7 +10,6 @@ #include "base/macros.h" #include "base/strings/utf_string_conversions.h" -#include "ui/base/ui_base_features.h" #include "ui/chromeos/ime/candidate_view.h" #include "ui/chromeos/ime/candidate_window_constants.h" #include "ui/display/display.h" @@ -153,7 +152,7 @@ was_candidate_window_open_(false), window_shell_id_(window_shell_id) { SetCanActivate(false); - DCHECK(parent || features::IsUsingWindowService()); + DCHECK(parent); set_parent_window(parent); set_margins(gfx::Insets());
diff --git a/ui/compositor/layer.cc b/ui/compositor/layer.cc index 316f96f..3b95dd1a 100644 --- a/ui/compositor/layer.cc +++ b/ui/compositor/layer.cc
@@ -400,6 +400,10 @@ return cc_layer_->masks_to_bounds(); } +void Layer::SetClipRect(const gfx::Rect& clip_rect) { + cc_layer_->SetClipRect(clip_rect); +} + void Layer::SetOpacity(float opacity) { GetAnimator()->SetOpacity(opacity); }
diff --git a/ui/compositor/layer.h b/ui/compositor/layer.h index 0850558..9ffad84 100644 --- a/ui/compositor/layer.h +++ b/ui/compositor/layer.h
@@ -184,6 +184,12 @@ void SetMasksToBounds(bool masks_to_bounds); bool GetMasksToBounds() const; + // Sets/gets the clip rect for the layer. |clip_rect| is in layer space and + // relative to |this| layer. Prefer SetMasksToBounds() to set the clip to the + // bounds of |this| layer. This clips the subtree rooted at |this| layer. + void SetClipRect(const gfx::Rect& clip_rect); + const gfx::Rect& clip_rect() const { return cc_layer_->clip_rect(); } + // The opacity of the layer. The opacity is applied to each pixel of the // texture (resulting alpha = opacity * alpha). float opacity() const;
diff --git a/ui/events/blink/input_handler_proxy_unittest.cc b/ui/events/blink/input_handler_proxy_unittest.cc index 9dc0d242..eb6047d 100644 --- a/ui/events/blink/input_handler_proxy_unittest.cc +++ b/ui/events/blink/input_handler_proxy_unittest.cc
@@ -10,9 +10,9 @@ #include "base/bind_helpers.h" #include "base/containers/circular_deque.h" #include "base/macros.h" -#include "base/message_loop/message_loop.h" #include "base/test/metrics/histogram_tester.h" #include "base/test/scoped_feature_list.h" +#include "base/test/scoped_task_environment.h" #include "base/test/simple_test_tick_clock.h" #include "base/test/trace_event_analyzer.h" #include "cc/input/main_thread_scrolling_reason.h" @@ -497,7 +497,7 @@ std::vector<InputHandlerProxy::EventDisposition> event_disposition_recorder_; std::vector<ui::LatencyInfo> latency_info_recorder_; - base::MessageLoop loop_; + base::test::ScopedTaskEnvironment scoped_task_environment_; base::WeakPtrFactory<InputHandlerProxyEventQueueTest> weak_ptr_factory_; };
diff --git a/ui/file_manager/file_manager/background/js/runtime_loaded_test_util.js b/ui/file_manager/file_manager/background/js/runtime_loaded_test_util.js index e773622..a0e6fc23 100644 --- a/ui/file_manager/file_manager/background/js/runtime_loaded_test_util.js +++ b/ui/file_manager/file_manager/background/js/runtime_loaded_test_util.js
@@ -440,18 +440,28 @@ if (opt_button !== undefined) { props.button = opt_button; } + if (!targetQuery) { + return false; + } + if (typeof targetQuery === 'string') { + targetQuery = [targetQuery]; + } + const elems = test.util.sync.deepQuerySelectorAll_( + contentWindow.document, /** @type !Array<string> */ (targetQuery)); + if (elems.length === 0) { + return false; + } + // Only sends the event to the first matched element. + const target = elems[0]; + const mouseOverEvent = new MouseEvent('mouseover', props); - const resultMouseOver = - test.util.sync.sendEvent(contentWindow, targetQuery, mouseOverEvent); + const resultMouseOver = target.dispatchEvent(mouseOverEvent); const mouseDownEvent = new MouseEvent('mousedown', props); - const resultMouseDown = - test.util.sync.sendEvent(contentWindow, targetQuery, mouseDownEvent); + const resultMouseDown = target.dispatchEvent(mouseDownEvent); const mouseUpEvent = new MouseEvent('mouseup', props); - const resultMouseUp = - test.util.sync.sendEvent(contentWindow, targetQuery, mouseUpEvent); + const resultMouseUp = target.dispatchEvent(mouseUpEvent); const clickEvent = new MouseEvent('click', props); - const resultClick = - test.util.sync.sendEvent(contentWindow, targetQuery, clickEvent); + const resultClick = target.dispatchEvent(clickEvent); return resultMouseOver && resultMouseDown && resultMouseUp && resultClick; };
diff --git a/ui/file_manager/file_manager/foreground/css/file_manager.css b/ui/file_manager/file_manager/foreground/css/file_manager.css index fa80b5d..59bb9e3 100644 --- a/ui/file_manager/file_manager/foreground/css/file_manager.css +++ b/ui/file_manager/file_manager/foreground/css/file_manager.css
@@ -1462,8 +1462,8 @@ @keyframes acceptsBlink { 0% { - color: rgb(90, 90, 90); background-color: transparent; + color: rgb(90, 90, 90); } } @@ -2149,6 +2149,19 @@ flex: 1 0 auto; } +/* Feedback panels */ + +.feedback-panels { + bottom: 24px; + position: absolute; + right: 24px; + z-index: 502; /* Above splitter, but below quickview. */ +} + +#completed-panel { + padding-bottom: 8px; +} + /* Progress center */ @keyframes progress-center-toggle {
diff --git a/ui/file_manager/file_manager/foreground/elements/BUILD.gn b/ui/file_manager/file_manager/foreground/elements/BUILD.gn index 81c6d0a..6af4b055 100644 --- a/ui/file_manager/file_manager/foreground/elements/BUILD.gn +++ b/ui/file_manager/file_manager/foreground/elements/BUILD.gn
@@ -94,3 +94,18 @@ ":files_toast_unittest", ] } + +js_library("xf_activity_complete") { +} + +js_library("xf_button") { +} + +js_library("xf_circular_progress") { +} + +js_library("xf_display_panel") { +} + +js_library("xf_panel_item") { +}
diff --git a/ui/file_manager/file_manager/foreground/elements/elements_bundle.html b/ui/file_manager/file_manager/foreground/elements/elements_bundle.html index e45b8e3..f34d700 100644 --- a/ui/file_manager/file_manager/foreground/elements/elements_bundle.html +++ b/ui/file_manager/file_manager/foreground/elements/elements_bundle.html
@@ -13,3 +13,4 @@ <link rel="import" href="files_toggle_ripple.html"> <link rel="import" href="files_tooltip.html"> <link rel="import" href="icons.html"> +<link rel="import" href="files_xf_elements.css">
diff --git a/ui/file_manager/file_manager/foreground/elements/xf_button.js b/ui/file_manager/file_manager/foreground/elements/xf_button.js index f56f218b..d4818d7 100644 --- a/ui/file_manager/file_manager/foreground/elements/xf_button.js +++ b/ui/file_manager/file_manager/foreground/elements/xf_button.js
@@ -11,9 +11,8 @@ } /** - * Creates an instance of Panelitem, attaching the template clone. + * Creates a PanelButton. * @private - * @return {PanelButton} Custom element instance. */ static createElement_() { const template = document.createElement('template');
diff --git a/ui/file_manager/file_manager/foreground/elements/xf_display_panel.js b/ui/file_manager/file_manager/foreground/elements/xf_display_panel.js index 26dc5cb..219d52ac 100644 --- a/ui/file_manager/file_manager/foreground/elements/xf_display_panel.js +++ b/ui/file_manager/file_manager/foreground/elements/xf_display_panel.js
@@ -9,13 +9,13 @@ constructor() { DisplayPanel.createElement_.call(super()); - /** @private {!HTMLElement} */ + /** @private {?Element} */ this.summary_ = this.shadowRoot.querySelector('#summary'); - /** @private {!HTMLElement} */ + /** @private {?Element} */ this.separator_ = this.shadowRoot.querySelector('#separator'); - /** @private {!HTMLElement} */ + /** @private {?Element} */ this.panels_ = this.shadowRoot.querySelector('#panels'); /** @@ -54,6 +54,7 @@ /** * Get the custom element template string. * @private + * @return {string} */ static html_() { return `<style> @@ -109,7 +110,7 @@ /** * Update the summary panel item progress indicator. - * @private + * @public */ updateProgress() { let total = 0; @@ -131,7 +132,7 @@ /** * Update the summary panel. - * @private + * @public */ updateSummaryPanel() { let summaryHost = this.shadowRoot.querySelector('#summary'); @@ -208,7 +209,7 @@ /** * Find a panel with given 'id'. - * @private + * @public */ findPanelItemById(id) { const panel = this.shadowRoot.querySelector('xf-panel-item[id=' + id + ']');
diff --git a/ui/file_manager/file_manager/foreground/elements/xf_panel_item.js b/ui/file_manager/file_manager/foreground/elements/xf_panel_item.js index f8a63027..57c6c9e7 100644 --- a/ui/file_manager/file_manager/foreground/elements/xf_panel_item.js +++ b/ui/file_manager/file_manager/foreground/elements/xf_panel_item.js
@@ -28,6 +28,9 @@ /** @private {number} */ this.panelType_ = this.panelTypeDefault; + + /** @public {?DisplayPanel} */ + this.parent = null; } /** @@ -91,24 +94,28 @@ // Setup the panel configuration for the panel type. // TOOD(crbug.com/947388) Simplify this switch breaking out common cases. + /** @type {?Element} */ + let primaryButton = null; + /** @type {?Element} */ + let secondaryButton = null; switch (type) { case this.panelTypeProgress: this.setAttribute('indicator', 'progress'); - let primaryButton = document.createElement('xf-button'); + primaryButton = document.createElement('xf-button'); primaryButton.id = 'primary-action'; - primaryButton.setAttribute('category', 'pause'); + primaryButton.dataset.category = 'pause'; buttonSpacer.insertAdjacentElement('beforebegin', primaryButton); - let secondaryButton = document.createElement('xf-button'); + secondaryButton = document.createElement('xf-button'); secondaryButton.id = 'secondary-action'; - secondaryButton.setAttribute('category', 'cancel'); + secondaryButton.dataset.category = 'cancel'; buttonSpacer.insertAdjacentElement('afterend', secondaryButton); break; case this.panelTypeSummary: this.setAttribute('indicator', 'largeprogress'); primaryButton = document.createElement('xf-button'); primaryButton.id = 'primary-action'; - primaryButton.setAttribute('category', 'expand'); + primaryButton.dataset.category = 'expand'; buttonSpacer.insertAdjacentElement('afterend', primaryButton); break; case this.panelTypeDone: @@ -116,12 +123,12 @@ this.setAttribute('status', 'success'); primaryButton = document.createElement('xf-button'); primaryButton.id = 'primary-action'; - primaryButton.setAttribute('category', 'dismiss'); + primaryButton.dataset.category = 'dismiss'; buttonSpacer.insertAdjacentElement('beforebegin', primaryButton); secondaryButton = document.createElement('xf-button'); secondaryButton.id = 'secondary-action'; - secondaryButton.setAttribute('category', 'undo'); + secondaryButton.dataset.category = 'undo'; buttonSpacer.insertAdjacentElement('afterend', secondaryButton); break; case this.panelTypeError: @@ -129,7 +136,7 @@ this.setAttribute('status', 'failure'); secondaryButton = document.createElement('xf-button'); secondaryButton.id = 'secondary-action'; - secondaryButton.setAttribute('category', 'retry'); + secondaryButton.dataset.category = 'retry'; buttonSpacer.insertAdjacentElement('afterend', secondaryButton); break; case this.panelTypeInfo: @@ -163,9 +170,9 @@ * @private */ attributeChangedCallback(name, oldValue, newValue) { - /** @type {HTMLElement} */ + /** @type {Element} */ let indicator = null; - /** @type {HTMLSpanElement} */ + /** @type {Element} */ let textNode; if (oldValue === newValue) { return; @@ -174,7 +181,7 @@ switch (name) { case 'count': if (this.indicator_) { - this.indicator_.setAttribute('label', newValue); + this.indicator_.setAttribute('label', newValue || ''); } break; case 'indicator':
diff --git a/ui/file_manager/file_manager/foreground/js/main_scripts.js b/ui/file_manager/file_manager/foreground/js/main_scripts.js index f33d0df..3206805 100644 --- a/ui/file_manager/file_manager/foreground/js/main_scripts.js +++ b/ui/file_manager/file_manager/foreground/js/main_scripts.js
@@ -181,6 +181,11 @@ // <include src="main_window_component.js"> // <include src="../../../base/js/filtered_volume_manager.js"> // <include src="webui_command_extender.js"> +// <include src="../elements/xf_activity_complete.js"> +// <include src="../elements/xf_button.js"> +// <include src="../elements/xf_circular_progress.js"> +// <include src="../elements/xf_display_panel.js"> +// <include src="../elements/xf_panel_item.js"> // // For accurate load performance tracking place main.js should be // // the last include to include.
diff --git a/ui/file_manager/file_manager/foreground/js/ui/BUILD.gn b/ui/file_manager/file_manager/foreground/js/ui/BUILD.gn index 03b0eff..f4e2079 100644 --- a/ui/file_manager/file_manager/foreground/js/ui/BUILD.gn +++ b/ui/file_manager/file_manager/foreground/js/ui/BUILD.gn
@@ -262,6 +262,11 @@ "//ui/file_manager/file_manager/foreground/elements:files_toast", "//ui/file_manager/file_manager/foreground/elements:files_toggle_ripple", "//ui/file_manager/file_manager/foreground/elements:files_tooltip", + "//ui/file_manager/file_manager/foreground/elements:xf_activity_complete", + "//ui/file_manager/file_manager/foreground/elements:xf_button", + "//ui/file_manager/file_manager/foreground/elements:xf_circular_progress", + "//ui/file_manager/file_manager/foreground/elements:xf_display_panel", + "//ui/file_manager/file_manager/foreground/elements:xf_panel_item", "//ui/file_manager/file_manager/foreground/js:launch_param", "//ui/file_manager/file_manager/foreground/js:providers_model", "//ui/webui/resources/js:util",
diff --git a/ui/file_manager/file_manager/foreground/js/ui/file_manager_ui.js b/ui/file_manager/file_manager/foreground/js/ui/file_manager_ui.js index fa2e69d..739d1f4 100644 --- a/ui/file_manager/file_manager/foreground/js/ui/file_manager_ui.js +++ b/ui/file_manager/file_manager/foreground/js/ui/file_manager_ui.js
@@ -241,6 +241,22 @@ queryRequiredElement('#progress-center', this.element)); /** + * Activity complete feedback panel. + * @type {!HTMLElement} + * @const + */ + this.activityCompletePanel = + queryRequiredElement('#completed-panel', this.element); + + /** + * Activity feedback panel. + * @type {!HTMLElement} + * @const + */ + this.activityProgressPanel = + queryRequiredElement('#progress-panel', this.element); + + /** * List container. * @type {ListContainer} */
diff --git a/ui/file_manager/file_manager/foreground/js/ui/progress_center_panel.js b/ui/file_manager/file_manager/foreground/js/ui/progress_center_panel.js index 1c230ba5..4db9a6b 100644 --- a/ui/file_manager/file_manager/foreground/js/ui/progress_center_panel.js +++ b/ui/file_manager/file_manager/foreground/js/ui/progress_center_panel.js
@@ -211,6 +211,12 @@ HTMLDivElement); /** + * Reference to the feedback panel host. + * TODO(crbug.com/947388) Add closure annotation here. + */ + this.feedbackHost_ = document.querySelector('#progress-panel'); + + /** * Close view that is a summarized progress item. * @type {ProgressCenterItemElement} * @private @@ -312,6 +318,8 @@ /** * Updates an item to the progress center panel. * @param {!ProgressCenterItem} item Item including new contents. + * @suppress {checkTypes} + * TODO(crbug.com/947388) Remove the suppress, and fix closure compile. */ updateItem(item) { const targetGroup = this.getGroupForItem_(item); @@ -321,30 +329,51 @@ // Update an open view item. const newItem = targetGroup.getItem(item.id); - let itemElement = this.getItemElement_(item.id); - if (newItem) { - if (!itemElement) { - itemElement = - new ProgressCenterItemElement(this.element_.ownerDocument); - // Find quiet node and insert the item before the quiet node. - this.openView_.insertBefore( - itemElement, this.openView_.querySelector('.quiet')); + if (util.isFeedbackPanelEnabled()) { + let panelItem = this.feedbackHost_.findPanelItemById(item.id); + if (newItem) { + if (!panelItem) { + panelItem = this.feedbackHost_.addPanelItem(item.id); + panelItem.panelType = panelItem.panelTypeProgress; + panelItem.setAttribute('primary-text', item.message); + } + panelItem.progress = item.progressRateInPercent; + // Remove the feedback panel when complete, and create + // an activity complete panel. + if (item.state == 'completed') { + this.feedbackHost_.removePanelItem(panelItem); + } + } else if (panelItem) { + this.feedbackHost_.removePanelItem(panelItem); } - itemElement.update(newItem, targetGroup.isAnimated(item.id)); } else { - if (itemElement) { - itemElement.parentNode.removeChild(itemElement); + let itemElement = this.getItemElement_(item.id); + if (newItem) { + if (!itemElement) { + itemElement = + new ProgressCenterItemElement(this.element_.ownerDocument); + // Find quiet node and insert the item before the quiet node. + this.openView_.insertBefore( + itemElement, this.openView_.querySelector('.quiet')); + } + itemElement.update(newItem, targetGroup.isAnimated(item.id)); + } else { + if (itemElement) { + itemElement.parentNode.removeChild(itemElement); + } } - } - // Update the close view. - this.updateCloseView_(); + // Update the close view. + this.updateCloseView_(); + } } /** * Handles the item animation end. * @param {Event} event Item animation end event. * @private + * @suppress {checkTypes} + * TODO(crbug.com/947388) Remove the suppress, and fix closure compile. */ onItemAnimationEnd_(event) { const targetGroup = event.target.classList.contains('quiet') ? @@ -355,10 +384,17 @@ } else { const itemId = event.target.getAttribute('data-progress-id'); targetGroup.completeItemAnimation(itemId); - const newItem = targetGroup.getItem(itemId); - const itemElement = this.getItemElement_(itemId); - if (!newItem && itemElement) { - itemElement.parentNode.removeChild(itemElement); + if (util.isFeedbackPanelEnabled()) { + const panelItem = this.feedbackHost_.findPanelItemById(itemId); + if (panelItem) { + this.feedbackHost_.removePanelItem(panelItem); + } + } else { + const newItem = targetGroup.getItem(itemId); + const itemElement = this.getItemElement_(itemId); + if (!newItem && itemElement) { + itemElement.parentNode.removeChild(itemElement); + } } } this.updateCloseView_();
diff --git a/ui/file_manager/file_manager/main.html b/ui/file_manager/file_manager/main.html index a96ee05..e99192250 100644 --- a/ui/file_manager/file_manager/main.html +++ b/ui/file_manager/file_manager/main.html
@@ -24,6 +24,7 @@ <link rel="stylesheet" href="foreground/css/file_status.css"> <link rel="stylesheet" href="foreground/css/file_types.css"> <link rel="stylesheet" href="foreground/css/common.css"> + <link rel="stylesheet" href="foreground/elements/files_xf_elements.css"> <link rel="stylesheet" href="cws_widget/cws_widget_container.css"> <script src="foreground/js/elements_importer.js"></script> @@ -77,6 +78,7 @@ background-color: black; }; --files-toggle-ripple-activated: { + background-color: black; opacity: 0.08; }; } @@ -551,6 +553,12 @@ </div> </div> </div> + <div class="feedback-panels"> + <xf-display-panel id="completed-panel"> + </xf-display-panel> + <xf-display-panel id="progress-panel"> + </xf-display-panel> + </div> <div class="dialog-footer progressable" tabindex="-1" visibleif="saveas-file open-file open-multi-file folder upload-folder"> <div class="left">
diff --git a/ui/file_manager/file_manager/test/js/strings.js b/ui/file_manager/file_manager/test/js/strings.js index 2660169..b50b3172 100644 --- a/ui/file_manager/file_manager/test/js/strings.js +++ b/ui/file_manager/file_manager/test/js/strings.js
@@ -11,6 +11,7 @@ loadTimeData.overrideValues({ 'CROSTINI_ENABLED': true, 'DRIVE_FS_ENABLED': true, + 'FEEDBACK_PANEL_ENABLED': false, 'GOOGLE_DRIVE_REDEEM_URL': 'http://www.google.com/intl/en/chrome/devices' + '/goodies.html?utm_source=filesapp&utm_medium=banner&utm_campaign=gsg', 'GOOGLE_DRIVE_OVERVIEW_URL':
diff --git a/ui/file_manager/file_manager/test/scripts/create_test_main.py b/ui/file_manager/file_manager/test/scripts/create_test_main.py index e89604f..5f66f6bb 100755 --- a/ui/file_manager/file_manager/test/scripts/create_test_main.py +++ b/ui/file_manager/file_manager/test/scripts/create_test_main.py
@@ -236,6 +236,7 @@ ('foreground/elements/files_toast.html', ()), ('foreground/elements/files_toggle_ripple.html', ()), ('foreground/elements/files_tooltip.html', ()), + ('foreground/elements/files_xf_elements.css', ()), ('foreground/elements/icons.html', ()), ): buf = i18n(read('ui/file_manager/file_manager/' + filename))
diff --git a/ui/file_manager/file_manager_resources.grd b/ui/file_manager/file_manager_resources.grd index 09f2ab7..9f93a3d7 100644 --- a/ui/file_manager/file_manager_resources.grd +++ b/ui/file_manager/file_manager_resources.grd
@@ -133,6 +133,7 @@ <include name="IDR_FILE_MANAGER_IMG_UI_2X_DRIVE_WELCOME_LOGO" file="file_manager/foreground/images/files/ui/2x/drive_logo.png" type="BINDATA" /> <include name="IDR_FILE_MANAGER_IMG_UI_DRIVE_WELCOME_PEOPLE" file="file_manager/foreground/images/files/ui/drive_banner_people.png" type="BINDATA" /> <include name="IDR_FILE_MANAGER_IMG_UI_2X_DRIVE_WELCOME_PEOPLE" file="file_manager/foreground/images/files/ui/2x/drive_banner_people.png" type="BINDATA" /> + <include name="IDR_FILE_MANAGER_ELEMENTS_FILES_XF_ELEMENTS_CSS" file="file_manager/foreground/elements/files_xf_elements.css" type="BINDATA" /> <!-- The VideoPlayer app pages and scripts. --> <include name="IDR_VIDEO_PLAYER_MANIFEST" file="video_player/manifest.json" type="BINDATA" />
diff --git a/ui/file_manager/gallery/gallery.html b/ui/file_manager/gallery/gallery.html index bb38438..6d8f2a6a 100644 --- a/ui/file_manager/gallery/gallery.html +++ b/ui/file_manager/gallery/gallery.html
@@ -36,9 +36,7 @@ cr-checkbox { --cr-checkbox-checked-box-color: white; --cr-checkbox-label-color: white; - --cr-checkbox-label-container: { - -webkit-padding-start: 6px; - }; + --cr-checkbox-label-padding-start: 6px; --cr-checkbox-mark-color: black; --cr-checkbox-ripple-checked-color: white; --cr-checkbox-ripple-size: 38px;
diff --git a/ui/file_manager/integration_tests/file_manager/copy_between_windows.js b/ui/file_manager/integration_tests/file_manager/copy_between_windows.js index c211e9a..d7cba90 100644 --- a/ui/file_manager/integration_tests/file_manager/copy_between_windows.js +++ b/ui/file_manager/integration_tests/file_manager/copy_between_windows.js
@@ -43,16 +43,12 @@ await remoteCall.waitForFiles(window1, [file.getExpectedRow()]); - await remoteCall.callRemoteTestUtil('fakeMouseClick', window1, []); - chrome.test.assertTrue( !!await remoteCall.callRemoteTestUtil('selectFile', window1, [name]), 'Failed: selectFile ' + name); await remoteCall.callRemoteTestUtil('execCommand', window1, ['copy']); - await remoteCall.callRemoteTestUtil('fakeMouseClick', window2, []); - await remoteCall.callRemoteTestUtil('execCommand', window2, ['paste']); const expectedFiles = [file.getExpectedRow()];
diff --git a/ui/ozone/platform/drm/host/drm_gpu_platform_support_host.cc b/ui/ozone/platform/drm/host/drm_gpu_platform_support_host.cc index 408a5cd..3e1f67ab 100644 --- a/ui/ozone/platform/drm/host/drm_gpu_platform_support_host.cc +++ b/ui/ozone/platform/drm/host/drm_gpu_platform_support_host.cc
@@ -11,7 +11,6 @@ #include "base/command_line.h" #include "base/threading/thread_task_runner_handle.h" #include "base/trace_event/trace_event.h" -#include "ui/base/ui_base_features.h" #include "ui/base/ui_base_switches.h" #include "ui/ozone/common/gpu/ozone_gpu_message_params.h" #include "ui/ozone/common/gpu/ozone_gpu_messages.h" @@ -93,11 +92,8 @@ : nullptr), cursor_(cursor), weak_ptr_factory_(this) { - if (ui_runner_) { + if (ui_runner_) weak_ptr_ = weak_ptr_factory_.GetWeakPtr(); - } else { - DCHECK(!features::IsMultiProcessMash()); - } } DrmGpuPlatformSupportHost::~DrmGpuPlatformSupportHost() {}
diff --git a/ui/views/controls/menu/menu_controller_unittest.cc b/ui/views/controls/menu/menu_controller_unittest.cc index be9e3026..3175143 100644 --- a/ui/views/controls/menu/menu_controller_unittest.cc +++ b/ui/views/controls/menu/menu_controller_unittest.cc
@@ -1898,14 +1898,7 @@ } // Tests that menus without parent widgets do not crash in MenuPreTargetHandler. -// This is generally true, except on Chrome OS running with the window service. -// In that case, a DCHECK fires to ensure menus can consume parents' key events. TEST_F(MenuControllerTest, RunWithoutWidgetDoesntCrash) { -#if defined(OS_CHROMEOS) - if (::features::IsUsingWindowService()) - return; -#endif // OS_CHROMEOS - ExitMenuRun(); MenuController* controller = menu_controller(); controller->Run(nullptr, nullptr, menu_item(), gfx::Rect(),
diff --git a/ui/views/controls/menu/menu_pre_target_handler_aura.cc b/ui/views/controls/menu/menu_pre_target_handler_aura.cc index 2bfd294..94976c2 100644 --- a/ui/views/controls/menu/menu_pre_target_handler_aura.cc +++ b/ui/views/controls/menu/menu_pre_target_handler_aura.cc
@@ -6,7 +6,6 @@ #include "ui/aura/env.h" #include "ui/aura/window.h" -#include "ui/base/ui_base_features.h" #include "ui/views/controls/menu/menu_controller.h" #include "ui/views/widget/widget.h" #include "ui/wm/public/activation_client.h" @@ -29,11 +28,7 @@ root_->AddObserver(this); } else { // This should only happen in cases like when context menus are shown for - // Windows OS system tray items and there is no parent window. This should - // not be hit on Chrome OS, where Window Service clients need to install a - // pre-target handler on the aura::Env associated with their app window. - DCHECK(!::features::IsUsingWindowService()) - << "MenuPreTargetHandlerAura may not work correctly without an owner."; + // Windows OS system tray items and there is no parent window. } aura::Env::GetInstance()->AddPreTargetHandler( this, ui::EventTarget::Priority::kSystem);
diff --git a/ui/webui/resources/cr_elements/cr_checkbox/cr_checkbox.html b/ui/webui/resources/cr_elements/cr_checkbox/cr_checkbox.html index bd6c454..ba013a9 100644 --- a/ui/webui/resources/cr_elements/cr_checkbox/cr_checkbox.html +++ b/ui/webui/resources/cr_elements/cr_checkbox/cr_checkbox.html
@@ -10,7 +10,7 @@ --cr-checkbox-border-size --cr-checkbox-checked-box-color --cr-checkbox-label-color - --cr-checkbox-label-container (CSS mixin) + --cr-checkbox-label-padding-start --cr-checkbox-mark-color --cr-checkbox-ripple-checked-color --cr-checkbox-ripple-size @@ -137,10 +137,8 @@ #label-container { color: var(--cr-checkbox-label-color, var(--cr-primary-text-color)); - padding-inline-start: 20px; + padding-inline-start: var(--cr-checkbox-label-padding-start, 20px); white-space: normal; - - @apply --cr-checkbox-label-container; } :host(.no-label) #label-container { @@ -160,7 +158,9 @@ aria-describedby="ariaDescription"> <span id="checkmark"></span> </div> - <div id="label-container" aria-hidden="true"><slot></slot></div> + <div id="label-container" aria-hidden="true" part="label-container"> + <slot></slot> + </div> <div id="ariaDescription">[[ariaDescription]]</div> </template> <script src="cr_checkbox.js"></script>
diff --git a/ui/webui/resources/cr_elements/cr_radio_button/cr_radio_button_style_css.html b/ui/webui/resources/cr_elements/cr_radio_button/cr_radio_button_style_css.html index f5c9390a..5d797a2 100644 --- a/ui/webui/resources/cr_elements/cr_radio_button/cr_radio_button_style_css.html +++ b/ui/webui/resources/cr_elements/cr_radio_button/cr_radio_button_style_css.html
@@ -50,18 +50,12 @@ #labelWrapper { flex: 1; margin-inline-start: var(--cr-radio-button-label-spacing, 20px); - - @apply --cr-radio-button-label; } #label { color: inherit; } - #slotted-content { - @apply --cr-radio-button-slot; - } - .disc-border, .disc, .disc-wrapper, @@ -71,10 +65,9 @@ .disc-wrapper { height: var(--cr-radio-button-size); + margin-block-start: var(--cr-radio-button-disc-margin-block-start, 0); position: relative; width: var(--cr-radio-button-size); - - @apply --cr-radio-button-disc; } .disc-border,