diff --git a/.gn b/.gn index ea7a2f4..a0cba4a 100644 --- a/.gn +++ b/.gn
@@ -279,6 +279,7 @@ "//extensions/renderer:unit_tests", "//extensions/shell/*", "//extensions/strings/*", + "//fuchsia/*", "//gin/*", "//google_apis/*", "//google_update/*", @@ -606,7 +607,6 @@ "//url/*", #"//v8/*", # Errors: https://bugs.chromium.org/p/v8/issues/detail?id=7330 - "//webrunner/*", ] # These are the list of GN files that run exec_script. This whitelist exists
diff --git a/BUILD.gn b/BUILD.gn index bb2769f0..b9eb08c 100644 --- a/BUILD.gn +++ b/BUILD.gn
@@ -764,14 +764,9 @@ if (is_fuchsia) { deps += [ + "//fuchsia:webrunner_unittests", + "//fuchsia/net_http:http_service_tests", "//headless", - "//headless:headless_shell", - "//headless:headless_tests", - "//webrunner", - "//webrunner:archive_sources", - "//webrunner:webrunner_unittests", - "//webrunner/net_http:http_pkg", - "//webrunner/net_http:http_service_tests", ] }
diff --git a/DEPS b/DEPS index e86cf84..3fc27ec2 100644 --- a/DEPS +++ b/DEPS
@@ -116,7 +116,7 @@ # 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': 'd4fdf78475a195ad1b83a5f51ad8d923f0150a33', + 'skia_revision': '14235d1ec0955fb615abba8007d067f622599d8d', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. @@ -128,7 +128,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': 'b3bdd2acc4f034eb3676df5dc7fd516da1288a6c', + 'angle_revision': '5fe7c5b926428d0d4dc8fa606afc7a4ab93cc49c', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling build tools # and whatever else without interference from each other. @@ -140,7 +140,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': 'd19dc58f1102216d472edfe2843c85bf2f4a1a7c', + 'pdfium_revision': 'f801451f55205c1839366b0dbd16c0689fb4275f', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling openmax_dl # and whatever else without interference from each other. @@ -224,7 +224,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. - 'spv_tools_revision': '7577415cc78c225b9ccce8a0771e39d7bbf815cd', + 'spv_tools_revision': '213e15e100e30c05626f456c3b8115fa3b2375c2', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. @@ -674,7 +674,7 @@ # Build tools for Chrome OS. Note: This depends on third_party/pyelftools. 'src/third_party/chromite': { - 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '5787b2a44d4740871eca43a6036c0d9e70d13938', + 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '5cfe5f2c7b78d0145fb4e8d5e17fe0876a67df88', 'condition': 'checkout_linux', }, @@ -840,7 +840,7 @@ Var('chromium_git') + '/chromium/deps/hunspell_dictionaries.git' + '@' + 'a9bac57ce6c9d390a52ebaad3259f5fdb871210e', 'src/third_party/icu': - Var('chromium_git') + '/chromium/deps/icu.git' + '@' + 'd65301491c513d49163ad29c853eb85c02c8d5b4', + Var('chromium_git') + '/chromium/deps/icu.git' + '@' + '07e7295d964399ee7bee16a3ac7ca5a053b2cf0a', 'src/third_party/icu4j': { 'packages': [ @@ -1235,7 +1235,7 @@ Var('chromium_git') + '/v8/v8.git' + '@' + Var('v8_revision'), 'src-internal': { - 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@902711febd7b3ad6a55ee9a0e4dcd16f3aa2bc22', + 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@64a7a9267e5fc11b6b959ea2c3062ccb588a3ad3', 'condition': 'checkout_src_internal', },
diff --git a/PRESUBMIT.py b/PRESUBMIT.py index 89967c3c..38a306d 100644 --- a/PRESUBMIT.py +++ b/PRESUBMIT.py
@@ -1643,19 +1643,19 @@ r"^courgette[\\/]courgette_minimal_tool\.cc$", r"^courgette[\\/]courgette_tool\.cc$", r"^extensions[\\/]renderer[\\/]logging_native_handler\.cc$", + r"^fuchsia[\\/]browser[\\/]frame_impl.cc$", + r"^headless[\\/]app[\\/]headless_shell\.cc$", r"^ipc[\\/]ipc_logging\.cc$", r"^native_client_sdk[\\/]", r"^remoting[\\/]base[\\/]logging\.h$", r"^remoting[\\/]host[\\/].*", r"^sandbox[\\/]linux[\\/].*", + r"^storage[\\/]browser[\\/]fileapi[\\/]" + + r"dump_file_system.cc$", r"^tools[\\/]", r"^ui[\\/]base[\\/]resource[\\/]data_pack.cc$", r"^ui[\\/]aura[\\/]bench[\\/]bench_main\.cc$", - r"^ui[\\/]ozone[\\/]platform[\\/]cast[\\/]", - r"^webrunner[\\/]browser[\\/]frame_impl.cc$", - r"^storage[\\/]browser[\\/]fileapi[\\/]" + - r"dump_file_system.cc$", - r"^headless[\\/]app[\\/]headless_shell\.cc$")) + r"^ui[\\/]ozone[\\/]platform[\\/]cast[\\/]")) source_file_filter = lambda x: input_api.FilterSourceFile( x, white_list=file_inclusion_pattern, black_list=black_list)
diff --git a/android_webview/browser/aw_proxying_url_loader_factory.cc b/android_webview/browser/aw_proxying_url_loader_factory.cc index 10476b7..0d7c43b 100644 --- a/android_webview/browser/aw_proxying_url_loader_factory.cc +++ b/android_webview/browser/aw_proxying_url_loader_factory.cc
@@ -158,7 +158,14 @@ std::unique_ptr<AwContentsIoThreadClient> io_thread_client = GetIoThreadClient(); DCHECK(io_thread_client); - request_.load_flags = GetCacheModeForClient(io_thread_client.get()); + + if (ShouldBlockURL(request_.url, io_thread_client.get())) { + OnRequestError(network::URLLoaderCompletionStatus(net::ERR_ACCESS_DENIED)); + return; + } + + request_.load_flags = + UpdateLoadFlags(request_.load_flags, io_thread_client.get()); // TODO: verify the case when WebContents::RenderFrameDeleted is called // before network request is intercepted (i.e. if that's possible and
diff --git a/android_webview/browser/net_helpers.cc b/android_webview/browser/net_helpers.cc index 7aac1055..473806f 100644 --- a/android_webview/browser/net_helpers.cc +++ b/android_webview/browser/net_helpers.cc
@@ -5,12 +5,27 @@ #include "android_webview/browser/net_helpers.h" #include "android_webview/browser/aw_contents_io_thread_client.h" +#include "android_webview/common/url_constants.h" #include "base/logging.h" #include "base/macros.h" #include "net/base/load_flags.h" +#include "url/gurl.h" namespace android_webview { +namespace { +int UpdateCacheControlFlags(int load_flags, int cache_control_flags) { + const int all_cache_control_flags = + net::LOAD_BYPASS_CACHE | net::LOAD_VALIDATE_CACHE | + net::LOAD_SKIP_CACHE_VALIDATION | net::LOAD_ONLY_FROM_CACHE; + DCHECK_EQ((cache_control_flags & all_cache_control_flags), + cache_control_flags); + load_flags &= ~all_cache_control_flags; + load_flags |= cache_control_flags; + return load_flags; +} + +// Gets the net-layer load_flags which reflect |client|'s cache mode. int GetCacheModeForClient(AwContentsIoThreadClient* client) { AwContentsIoThreadClient::CacheMode cache_mode = client->GetCacheMode(); switch (cache_mode) { @@ -32,6 +47,36 @@ } } +} // namespace + +int UpdateLoadFlags(int load_flags, AwContentsIoThreadClient* client) { + if (client->ShouldBlockNetworkLoads()) { + return UpdateCacheControlFlags( + load_flags, + net::LOAD_ONLY_FROM_CACHE | net::LOAD_SKIP_CACHE_VALIDATION); + } + + int cache_mode = GetCacheModeForClient(client); + if (!cache_mode) + return load_flags; + + return UpdateCacheControlFlags(load_flags, cache_mode); +} + +bool ShouldBlockURL(const GURL& url, AwContentsIoThreadClient* client) { + // Part of implementation of WebSettings.allowContentAccess. + if (url.SchemeIs(url::kContentScheme) && client->ShouldBlockContentUrls()) + return true; + + // Part of implementation of WebSettings.allowFileAccess. + if (url.SchemeIsFile() && client->ShouldBlockFileUrls()) { + // Application's assets and resources are always available. + return !IsAndroidSpecialFileUrl(url); + } + + return client->ShouldBlockNetworkLoads() && url.SchemeIs(url::kFtpScheme); +} + int GetHttpCacheSize() { // This currently returns a constant value, but we may consider deciding cache // size dynamically, since Android provides better support on newer versions
diff --git a/android_webview/browser/net_helpers.h b/android_webview/browser/net_helpers.h index 501d13c..e03bd56 100644 --- a/android_webview/browser/net_helpers.h +++ b/android_webview/browser/net_helpers.h
@@ -7,12 +7,18 @@ #include <memory> +class GURL; + namespace android_webview { class AwContentsIoThreadClient; -// Gets the net-layer load_flags which reflect |client|'s cache mode. -int GetCacheModeForClient(AwContentsIoThreadClient* client); +// Returns the updated request's |load_flags| based on the settings. +int UpdateLoadFlags(int load_flags, AwContentsIoThreadClient* client); + +// Returns true if the given URL should be aborted with +// net::ERR_ACCESS_DENIED. +bool ShouldBlockURL(const GURL& url, AwContentsIoThreadClient* client); // Determines the desired size for WebView's on-disk HttpCache, measured in // Bytes.
diff --git a/android_webview/browser/renderer_host/aw_resource_dispatcher_host_delegate.cc b/android_webview/browser/renderer_host/aw_resource_dispatcher_host_delegate.cc index ddc67c3..03d3c64 100644 --- a/android_webview/browser/renderer_host/aw_resource_dispatcher_host_delegate.cc +++ b/android_webview/browser/renderer_host/aw_resource_dispatcher_host_delegate.cc
@@ -47,18 +47,6 @@ DestructorAtExit g_webview_resource_dispatcher_host_delegate = LAZY_INSTANCE_INITIALIZER; -void SetCacheControlFlag( - net::URLRequest* request, int flag) { - const int all_cache_control_flags = - net::LOAD_BYPASS_CACHE | net::LOAD_VALIDATE_CACHE | - net::LOAD_SKIP_CACHE_VALIDATION | net::LOAD_ONLY_FROM_CACHE; - DCHECK_EQ((flag & all_cache_control_flags), flag); - int load_flags = request->load_flags(); - load_flags &= ~all_cache_control_flags; - load_flags |= flag; - request->SetLoadFlags(load_flags); -} - // Called when ResourceDispathcerHost detects a download request. // The download is already cancelled when this is called, since // relevant for DownloadListener is already extracted. @@ -230,31 +218,11 @@ if (!io_client) return false; - // Part of implementation of WebSettings.allowContentAccess. - if (request_->url().SchemeIs(url::kContentScheme) && - io_client->ShouldBlockContentUrls()) { + if (ShouldBlockURL(request_->url(), io_client.get())) return true; - } - // Part of implementation of WebSettings.allowFileAccess. - if (request_->url().SchemeIsFile() && - io_client->ShouldBlockFileUrls()) { - // Application's assets and resources are always available. - return !IsAndroidSpecialFileUrl(request_->url()); - } - - if (io_client->ShouldBlockNetworkLoads()) { - if (request_->url().SchemeIs(url::kFtpScheme)) { - return true; - } - SetCacheControlFlag( - request_, net::LOAD_ONLY_FROM_CACHE | net::LOAD_SKIP_CACHE_VALIDATION); - } else { - int cache_mode = GetCacheModeForClient(io_client.get()); - if (cache_mode) { - SetCacheControlFlag(request_, cache_mode); - } - } + request_->SetLoadFlags( + UpdateLoadFlags(request_->load_flags(), io_client.get())); return false; }
diff --git a/android_webview/glue/java/src/com/android/webview/chromium/WebViewChromiumFactoryProvider.java b/android_webview/glue/java/src/com/android/webview/chromium/WebViewChromiumFactoryProvider.java index b9d67eac..99e4c95 100644 --- a/android_webview/glue/java/src/com/android/webview/chromium/WebViewChromiumFactoryProvider.java +++ b/android_webview/glue/java/src/com/android/webview/chromium/WebViewChromiumFactoryProvider.java
@@ -127,7 +127,7 @@ private SharedPreferences mWebViewPrefs; private WebViewDelegate mWebViewDelegate; - private boolean mShouldDisableThreadChecking; + protected boolean mShouldDisableThreadChecking; // Initialization guarded by mAwInit.getLock() private Statics mStaticsAdapter;
diff --git a/ash/BUILD.gn b/ash/BUILD.gn index 3d6d3d9a..e589de94 100644 --- a/ash/BUILD.gn +++ b/ash/BUILD.gn
@@ -806,8 +806,6 @@ "system/network/sms_observer.h", "system/network/tray_network_state_observer.cc", "system/network/tray_network_state_observer.h", - "system/network/tray_vpn.cc", - "system/network/tray_vpn.h", "system/network/unified_network_detailed_view_controller.cc", "system/network/unified_network_detailed_view_controller.h", "system/network/unified_vpn_detailed_view_controller.cc", @@ -818,6 +816,8 @@ "system/network/vpn_list.h", "system/network/vpn_list_view.cc", "system/network/vpn_list_view.h", + "system/network/vpn_util.cc", + "system/network/vpn_util.h", "system/network/wifi_toggle_notification_controller.cc", "system/network/wifi_toggle_notification_controller.h", "system/night_light/night_light_controller.cc", @@ -1526,15 +1526,18 @@ deps = [ ":ash_shell_lib", + ":manifest", ":test_support", "//ash/components/quick_launch:lib", + "//ash/components/quick_launch:manifest", "//ash/components/quick_launch/public/mojom", "//ash/components/shortcut_viewer:lib", + "//ash/components/shortcut_viewer:manifest", "//ash/components/shortcut_viewer/public/mojom", "//ash/components/tap_visualizer:lib", + "//ash/components/tap_visualizer:manifest", "//ash/components/tap_visualizer/public/mojom", "//ash/public/cpp", - "//ash/shell:resources", "//base:i18n", "//chrome:packed_resources", "//chromeos", @@ -1549,8 +1552,10 @@ "//content/shell:content_shell_lib", "//device/bluetooth", "//net", + "//services/device/public/mojom", "//services/ws:lib", "//services/ws/ime/test_ime_driver:lib", + "//services/ws/ime/test_ime_driver:manifest", "//services/ws/ime/test_ime_driver/public/mojom", "//skia", "//ui/aura",
diff --git a/ash/resources/BUILD.gn b/ash/resources/BUILD.gn index 314655e..31dfd84 100644 --- a/ash/resources/BUILD.gn +++ b/ash/resources/BUILD.gn
@@ -76,11 +76,9 @@ ash_test_resources("with_content_100_percent") { percent = "100" sources = [ - "$root_gen_dir/ash/shell/ash_shell_resources.pak", "$root_gen_dir/content/content_resources.pak", ] deps = [ - "//ash/shell:resources", "//content:resources", ] }
diff --git a/ash/shelf/shelf_app_button.cc b/ash/shelf/shelf_app_button.cc index 406bc245..25dded4 100644 --- a/ash/shelf/shelf_app_button.cc +++ b/ash/shelf/shelf_app_button.cc
@@ -294,7 +294,8 @@ // static const char ShelfAppButton::kViewClassName[] = "ash/ShelfAppButton"; -ShelfAppButton::ShelfAppButton(ShelfView* shelf_view) +ShelfAppButton::ShelfAppButton(ShelfView* shelf_view, + const base::string16& title) : ShelfButton(shelf_view), icon_view_(new views::ImageView()), indicator_(new AppStatusIndicatorView()), @@ -303,6 +304,7 @@ destroyed_flag_(nullptr), is_notification_indicator_enabled_( features::IsNotificationIndicatorEnabled()) { + SetTitle(title); const gfx::ShadowValue kShadows[] = { gfx::ShadowValue(gfx::Vector2d(0, 2), 0, SkColorSetARGB(0x1A, 0, 0, 0)), gfx::ShadowValue(gfx::Vector2d(0, 3), 1, SkColorSetARGB(0x1A, 0, 0, 0)), @@ -343,6 +345,10 @@ image, icon_shadows_)); } +void ShelfAppButton::SetTitle(const base::string16 title) { + SetAccessibleName(title); +} + void ShelfAppButton::SetImage(const gfx::ImageSkia& image) { if (image.isNull()) { // TODO: need an empty image.
diff --git a/ash/shelf/shelf_app_button.h b/ash/shelf/shelf_app_button.h index 69e1ad8bb..34835b5e 100644 --- a/ash/shelf/shelf_app_button.h +++ b/ash/shelf/shelf_app_button.h
@@ -45,9 +45,12 @@ STATE_ACTIVE = 1 << 6, }; - ShelfAppButton(ShelfView* shelf_view); + ShelfAppButton(ShelfView* shelf_view, const base::string16& title); ~ShelfAppButton() override; + // Sets the textual title for this entry, to be shown in a tooltip. + void SetTitle(const base::string16 title); + // Sets the image to display for this entry. void SetImage(const gfx::ImageSkia& image);
diff --git a/ash/shelf/shelf_button.cc b/ash/shelf/shelf_button.cc index 5d58a38..991c5d5 100644 --- a/ash/shelf/shelf_button.cc +++ b/ash/shelf/shelf_button.cc
@@ -54,8 +54,16 @@ void ShelfButton::GetAccessibleNodeData(ui::AXNodeData* node_data) { node_data->role = ax::mojom::Role::kButton; - const base::string16 title = shelf_view_->GetTitleForView(this); - node_data->SetName(title.empty() ? GetAccessibleName() : title); + node_data->SetName(GetAccessibleName()); +} + +bool ShelfButton::GetTooltipText(const gfx::Point& p, + base::string16* tooltip) const { + // Copy the proper tooltip text, but return false because we do not want to + // show a tooltip with the standard view mechanism and instead use the + // custom display logic defined in |ShelfTooltipManager|. + *tooltip = GetAccessibleName(); + return false; } ////////////////////////////////////////////////////////////////////////////////
diff --git a/ash/shelf/shelf_button.h b/ash/shelf/shelf_button.h index 89aa3f5..fd1963b 100644 --- a/ash/shelf/shelf_button.h +++ b/ash/shelf/shelf_button.h
@@ -18,15 +18,17 @@ explicit ShelfButton(ShelfView* shelf_view); ~ShelfButton() override; - protected: - ShelfView* shelf_view() { return shelf_view_; } - // views::View bool OnMousePressed(const ui::MouseEvent& event) override; void OnMouseReleased(const ui::MouseEvent& event) override; void OnMouseCaptureLost() override; bool OnMouseDragged(const ui::MouseEvent& event) override; void GetAccessibleNodeData(ui::AXNodeData* node_data) override; + bool GetTooltipText(const gfx::Point& p, + base::string16* tooltip) const override; + + protected: + ShelfView* shelf_view() { return shelf_view_; } // views::Button void NotifyClick(const ui::Event& event) override;
diff --git a/ash/shelf/shelf_tooltip_manager.cc b/ash/shelf/shelf_tooltip_manager.cc index 2184d73..72b81d6e 100644 --- a/ash/shelf/shelf_tooltip_manager.cc +++ b/ash/shelf/shelf_tooltip_manager.cc
@@ -96,8 +96,9 @@ view, arrow, open_windows, this, shelf_view_->shelf_widget()->GetShelfBackgroundColor()); } else { - bubble_ = - new ShelfTooltipBubble(view, arrow, shelf_view_->GetTitleForView(view)); + base::string16 title; + view->GetTooltipText(gfx::Point(), &title); + bubble_ = new ShelfTooltipBubble(view, arrow, title); } aura::Window* window = bubble_->GetWidget()->GetNativeWindow();
diff --git a/ash/shelf/shelf_view.cc b/ash/shelf/shelf_view.cc index a743aaa..0ac929173 100644 --- a/ash/shelf/shelf_view.cc +++ b/ash/shelf/shelf_view.cc
@@ -39,6 +39,7 @@ #include "ash/wm/root_window_finder.h" #include "ash/wm/tablet_mode/tablet_mode_controller.h" #include "base/auto_reset.h" +#include "base/containers/adapters.h" #include "base/metrics/histogram_macros.h" #include "base/strings/utf_string_conversions.h" #include "base/timer/timer.h" @@ -57,7 +58,7 @@ #include "ui/views/animation/bounds_animator.h" #include "ui/views/animation/ink_drop.h" #include "ui/views/border.h" -#include "ui/views/controls/button/image_button.h" +#include "ui/views/controls/button/button.h" #include "ui/views/controls/menu/menu_model_adapter.h" #include "ui/views/controls/menu/menu_runner.h" #include "ui/views/controls/separator.h" @@ -465,6 +466,10 @@ return nullptr; } +OverflowButton* ShelfView::GetOverflowButton() const { + return overflow_button_; +} + void ShelfView::UpdateVisibleShelfItemBoundsUnion() { visible_shelf_item_bounds_union_.SetRect(0, 0, 0, 0); for (int i = first_visible_index_; i <= last_visible_index_; ++i) { @@ -479,6 +484,11 @@ if (ShouldShowTooltipForView(child)) visible_shelf_item_bounds_union_.Union(child->GetMirroredBounds()); } + // Also include the overflow button if it is visible. + if (overflow_button_->visible()) { + visible_shelf_item_bounds_union_.Union( + overflow_button_->GetMirroredBounds()); + } } bool ShelfView::ShouldHideTooltip(const gfx::Point& cursor_location) const { @@ -493,11 +503,12 @@ } bool ShelfView::ShouldShowTooltipForView(const views::View* view) const { - // TODO(msw): Push this app list state into ShelfItem::shows_tooltip. // If this is the app list button, only show the tooltip if the app list is // not already showing. if (view == GetAppListButton()) return !GetAppListButton()->is_showing_app_list(); + if (view == overflow_button_) + return true; // Don't show a tooltip for a view that's currently being dragged. if (view == drag_view_) return false; @@ -505,11 +516,6 @@ return ShelfItemForView(view) && !IsShowingMenuForView(view); } -base::string16 ShelfView::GetTitleForView(const views::View* view) const { - const ShelfItem* item = ShelfItemForView(view); - return item ? item->title : base::string16(); -} - gfx::Rect ShelfView::GetVisibleItemsBoundsInScreen() { gfx::Size preferred_size = GetPreferredSize(); gfx::Point origin(GetMirroredXWithWidthInView(0, preferred_size.width()), 0); @@ -517,6 +523,88 @@ return gfx::Rect(origin, preferred_size); } +gfx::Size ShelfView::CalculatePreferredSize() const { + gfx::Rect overflow_bounds; + CalculateIdealBounds(&overflow_bounds); + + int last_button_index = last_visible_index_; + if (!is_overflow_mode() && overflow_button_ && overflow_button_->visible()) + ++last_button_index; + + // When an item is dragged off from the overflow bubble, it is moved to last + // position and and changed to invisible. Overflow bubble size should be + // shrunk to fit only for visible items. + // If |dragged_to_another_shelf_| is set, there will be no + // invisible items in the shelf. + if (is_overflow_mode() && dragged_off_shelf_ && !dragged_to_another_shelf_ && + RemovableByRipOff(view_model_->GetIndexOfView(drag_view_)) == REMOVABLE) + last_button_index--; + + const gfx::Rect last_button_bounds = + last_button_index >= first_visible_index_ + ? view_model_->ideal_bounds(last_button_index) + : gfx::Rect(gfx::Size(ShelfConstants::shelf_size(), + ShelfConstants::shelf_size())); + + if (shelf_->IsHorizontalAlignment()) + return gfx::Size(last_button_bounds.right(), ShelfConstants::shelf_size()); + + return gfx::Size(ShelfConstants::shelf_size(), last_button_bounds.bottom()); +} + +void ShelfView::OnBoundsChanged(const gfx::Rect& previous_bounds) { + // This bounds change is produced by the shelf movement (rotation, alignment + // change, etc.) and all content has to follow. Using an animation at that + // time would produce a time lag since the animation of the BoundsAnimator has + // itself a delay before it arrives at the required location. As such we tell + // the animator to go there immediately. We still want to use an animation + // when the bounds change is caused by entering or exiting tablet mode. + if (shelf_->is_tablet_mode_animation_running()) { + AnimateToIdealBounds(); + if (IsShowingOverflowBubble()) { + overflow_bubble_->bubble_view()->shelf_view()->OnBoundsChanged( + previous_bounds); + } + return; + } + + BoundsAnimatorDisabler disabler(bounds_animator_.get()); + + LayoutToIdealBounds(); + shelf_->NotifyShelfIconPositionsChanged(); + + if (IsShowingOverflowBubble()) + overflow_bubble_->Hide(); +} + +views::FocusTraversable* ShelfView::GetPaneFocusTraversable() { + return this; +} + +void ShelfView::GetAccessibleNodeData(ui::AXNodeData* node_data) { + node_data->role = ax::mojom::Role::kToolbar; + node_data->SetName(l10n_util::GetStringUTF8(IDS_ASH_SHELF_ACCESSIBLE_NAME)); +} + +View* ShelfView::GetTooltipHandlerForPoint(const gfx::Point& point) { + // Similar implementation as views::View, but without going into each + // child's subviews. + View::Views children = GetChildrenInZOrder(); + for (auto* child : base::Reversed(children)) { + if (!child->visible()) + continue; + + gfx::Point point_in_child_coords(point); + ConvertPointToTarget(this, child, &point_in_child_coords); + if (child->HitTestPoint(point_in_child_coords) && + ShouldShowTooltipForView(child)) { + return child; + } + } + // If none of our children qualifies, just return the shelf view itself. + return this; +} + void ShelfView::ButtonPressed(views::Button* sender, const ui::Event& event, views::InkDrop* ink_drop) { @@ -723,11 +811,17 @@ std::vector<aura::Window*> window_list = Shell::Get()->mru_window_tracker()->BuildWindowForCycleList(); std::vector<aura::Window*> open_windows; - const std::string shelf_item_app_id = ShelfItemForView(view)->id.app_id; + const ShelfItem* item = ShelfItemForView(view); + + // The concept of a list of open windows doesn't make sense for something + // that isn't an app shortcut: return an empty list. + if (!item) + return open_windows; + for (auto* window : window_list) { const std::string window_app_id = ShelfID::Deserialize(window->GetProperty(kShelfIDKey)).app_id; - if (window_app_id == shelf_item_app_id) { + if (window_app_id == item->id.app_id) { // TODO: In the very first version we only show one window. Add the proper // UI to show all windows for a given open app. open_windows.push_back(window); @@ -1200,7 +1294,7 @@ case TYPE_BROWSER_SHORTCUT: case TYPE_APP: case TYPE_DIALOG: { - ShelfAppButton* button = new ShelfAppButton(this); + ShelfAppButton* button = new ShelfAppButton(this, item.title); button->SetImage(item.image); button->ReflectItemStatus(item); view = button; @@ -1802,69 +1896,6 @@ return modified_view ? view_model_->GetIndexOfView(modified_view) : -1; } -gfx::Size ShelfView::CalculatePreferredSize() const { - gfx::Rect overflow_bounds; - CalculateIdealBounds(&overflow_bounds); - - int last_button_index = last_visible_index_; - if (!is_overflow_mode() && overflow_button_ && overflow_button_->visible()) - ++last_button_index; - - // When an item is dragged off from the overflow bubble, it is moved to last - // position and and changed to invisible. Overflow bubble size should be - // shrunk to fit only for visible items. - // If |dragged_to_another_shelf_| is set, there will be no - // invisible items in the shelf. - if (is_overflow_mode() && dragged_off_shelf_ && !dragged_to_another_shelf_ && - RemovableByRipOff(view_model_->GetIndexOfView(drag_view_)) == REMOVABLE) - last_button_index--; - - const gfx::Rect last_button_bounds = - last_button_index >= first_visible_index_ - ? view_model_->ideal_bounds(last_button_index) - : gfx::Rect(gfx::Size(ShelfConstants::shelf_size(), - ShelfConstants::shelf_size())); - - if (shelf_->IsHorizontalAlignment()) - return gfx::Size(last_button_bounds.right(), ShelfConstants::shelf_size()); - - return gfx::Size(ShelfConstants::shelf_size(), last_button_bounds.bottom()); -} - -void ShelfView::OnBoundsChanged(const gfx::Rect& previous_bounds) { - // This bounds change is produced by the shelf movement (rotation, alignment - // change, etc.) and all content has to follow. Using an animation at that - // time would produce a time lag since the animation of the BoundsAnimator has - // itself a delay before it arrives at the required location. As such we tell - // the animator to go there immediately. We still want to use an animation - // when the bounds change is caused by entering or exiting tablet mode. - if (shelf_->is_tablet_mode_animation_running()) { - AnimateToIdealBounds(); - if (IsShowingOverflowBubble()) { - overflow_bubble_->bubble_view()->shelf_view()->OnBoundsChanged( - previous_bounds); - } - return; - } - - BoundsAnimatorDisabler disabler(bounds_animator_.get()); - - LayoutToIdealBounds(); - shelf_->NotifyShelfIconPositionsChanged(); - - if (IsShowingOverflowBubble()) - overflow_bubble_->Hide(); -} - -views::FocusTraversable* ShelfView::GetPaneFocusTraversable() { - return this; -} - -void ShelfView::GetAccessibleNodeData(ui::AXNodeData* node_data) { - node_data->role = ax::mojom::Role::kToolbar; - node_data->SetName(l10n_util::GetStringUTF8(IDS_ASH_SHELF_ACCESSIBLE_NAME)); -} - void ShelfView::OnGestureEvent(ui::GestureEvent* event) { // Convert the event location from current view to screen, since swiping up on // the shelf can open the fullscreen app list. Updating the bounds of the app @@ -2012,6 +2043,7 @@ CHECK_EQ(ShelfAppButton::kViewClassName, view->GetClassName()); ShelfAppButton* button = static_cast<ShelfAppButton*>(view); button->ReflectItemStatus(item); + button->SetTitle(item.title); button->SetImage(item.image); button->SchedulePaint(); break;
diff --git a/ash/shelf/shelf_view.h b/ash/shelf/shelf_view.h index 0ace96f..cbdc9bff 100644 --- a/ash/shelf/shelf_view.h +++ b/ash/shelf/shelf_view.h
@@ -151,6 +151,7 @@ AppListButton* GetAppListButton() const; BackButton* GetBackButton() const; + OverflowButton* GetOverflowButton() const; // Updates the union of all the shelf item bounds shown by this shelf view. // This is used to determine the common area where the mouse can hover @@ -166,13 +167,17 @@ // Returns true if a tooltip should be shown for the shelf item |view|. bool ShouldShowTooltipForView(const views::View* view) const; - // Returns the title of the shelf item |view|. - base::string16 GetTitleForView(const views::View* view) const; - // Returns rectangle bounding all visible launcher items. Used screen // coordinate system. gfx::Rect GetVisibleItemsBoundsInScreen(); + // Overridden from views::View: + gfx::Size CalculatePreferredSize() const override; + void OnBoundsChanged(const gfx::Rect& previous_bounds) override; + FocusTraversable* GetPaneFocusTraversable() override; + void GetAccessibleNodeData(ui::AXNodeData* node_data) override; + View* GetTooltipHandlerForPoint(const gfx::Point& point) override; + // InkDropButtonListener: void ButtonPressed(views::Button* sender, const ui::Event& event, @@ -394,12 +399,6 @@ const gfx::Point& location, bool context_menu) const; - // Overridden from views::View: - gfx::Size CalculatePreferredSize() const override; - void OnBoundsChanged(const gfx::Rect& previous_bounds) override; - FocusTraversable* GetPaneFocusTraversable() override; - void GetAccessibleNodeData(ui::AXNodeData* node_data) override; - // Overridden from ui::EventHandler: void OnGestureEvent(ui::GestureEvent* event) override; bool OnMouseWheel(const ui::MouseWheelEvent& event) override;
diff --git a/ash/shelf/shelf_view_unittest.cc b/ash/shelf/shelf_view_unittest.cc index d8e718f..e68aaa2 100644 --- a/ash/shelf/shelf_view_unittest.cc +++ b/ash/shelf/shelf_view_unittest.cc
@@ -35,6 +35,7 @@ #include "ash/shelf/shelf_widget.h" #include "ash/shell.h" #include "ash/shell_test_api.h" +#include "ash/strings/grit/ash_strings.h" #include "ash/system/status_area_widget.h" #include "ash/test/ash_test_base.h" #include "ash/test/ash_test_helper.h" @@ -60,6 +61,7 @@ #include "ui/aura/test/aura_test_base.h" #include "ui/aura/window.h" #include "ui/aura/window_event_dispatcher.h" +#include "ui/base/l10n/l10n_util.h" #include "ui/base/ui_base_features.h" #include "ui/compositor/layer.h" #include "ui/display/display.h" @@ -1333,6 +1335,27 @@ EXPECT_EQ(nullptr, tooltip_manager->GetCurrentAnchorView()); } +TEST_F(ShelfViewTest, ButtonTitlesTest) { + AddButtonsUntilOverflow(); + EXPECT_EQ(base::UTF8ToUTF16("Launcher"), + shelf_view_->GetAppListButton()->GetAccessibleName()); + EXPECT_EQ(l10n_util::GetStringUTF16(IDS_ASH_SHELF_BACK_BUTTON_TITLE), + shelf_view_->GetBackButton()->GetAccessibleName()); + EXPECT_EQ(l10n_util::GetStringUTF16(IDS_ASH_SHELF_OVERFLOW_NAME), + shelf_view_->GetOverflowButton()->GetAccessibleName()); + + for (int i = 0; i < test_api_->GetButtonCount(); i++) { + ShelfAppButton* button = test_api_->GetButton(i); + if (button) { + base::string16 tooltip; + button->GetTooltipText(gfx::Point(), &tooltip); + EXPECT_EQ(tooltip, button->GetAccessibleName()) + << "Each button's tooltip text should read the same as its " + << "accessible name"; + } + } +} + // Verify a fix for crash caused by a tooltip update for a deleted shelf // button, see crbug.com/288838. TEST_F(ShelfViewTest, RemovingItemClosesTooltip) {
diff --git a/ash/shell/BUILD.gn b/ash/shell/BUILD.gn deleted file mode 100644 index a8c43b64..0000000 --- a/ash/shell/BUILD.gn +++ /dev/null
@@ -1,40 +0,0 @@ -# Copyright 2018 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import("//services/service_manager/public/service_manifest.gni") -import("//tools/grit/grit_rule.gni") - -assert(is_chromeos) - -grit("resources") { - source = "ash_shell_resources.grd" - outputs = [ - "grit/ash_shell_resources.h", - "ash_shell_resources.pak", - ] - grit_flags = [ - "-E", - "root_gen_dir=" + rebase_path(root_gen_dir, root_build_dir), - ] - - deps = [ - ":ash_content_browser_manifest_overlay", - ":ash_content_packaged_services_manifest_overlay", - ] -} - -service_manifest("ash_content_browser_manifest_overlay") { - source = "//ash/shell/ash_content_browser_manifest_overlay.json" -} - -service_manifest("ash_content_packaged_services_manifest_overlay") { - source = "//ash/shell/ash_content_packaged_services_manifest_overlay.json" - packaged_services = [ - "//ash:manifest", - "//ash/components/quick_launch:manifest", - "//ash/components/shortcut_viewer:manifest", - "//ash/components/tap_visualizer:manifest", - "//services/ws/ime/test_ime_driver:manifest", - ] -}
diff --git a/ash/shell/OWNERS b/ash/shell/OWNERS index 9774cf01..c8dc16e 100644 --- a/ash/shell/OWNERS +++ b/ash/shell/OWNERS
@@ -1,7 +1 @@ per-file *app_list*=xiyuan@chromium.org - -per-file ash_content_packaged_services_manifest_overlay.json=set noparent -per-file ash_content_packaged_services_manifest_overlay.json=file://ipc/SECURITY_OWNERS - -per-file ash_content_browser_manifest_overlay.json=set noparent -per-file ash_content_browser_manifest_overlay.json=file://ipc/SECURITY_OWNERS
diff --git a/ash/shell/ash_content_browser_manifest_overlay.json b/ash/shell/ash_content_browser_manifest_overlay.json deleted file mode 100644 index 9f0f4d0..0000000 --- a/ash/shell/ash_content_browser_manifest_overlay.json +++ /dev/null
@@ -1,13 +0,0 @@ -{ - "name": "content_browser", - "display_name": "Ash Content Browser", - "interface_provider_specs": { - "service_manager:connector": { - "requires": { - "device": [ "device:fingerprint" ], - "shortcut_viewer_app": [ "shortcut_viewer" ], - "tap_visualizer_app": [ "tap_visualizer" ] - } - } - } -}
diff --git a/ash/shell/ash_content_packaged_services_manifest_overlay.json b/ash/shell/ash_content_packaged_services_manifest_overlay.json deleted file mode 100644 index eaffdf51..0000000 --- a/ash/shell/ash_content_packaged_services_manifest_overlay.json +++ /dev/null
@@ -1,5 +0,0 @@ -{ - "name": "content_packaged_services", - "display_name": "Ash Packaged Services", - "interface_provider_specs": {} -}
diff --git a/ash/shell/ash_shell_resources.grd b/ash/shell/ash_shell_resources.grd deleted file mode 100644 index d56ed86..0000000 --- a/ash/shell/ash_shell_resources.grd +++ /dev/null
@@ -1,20 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<grit latest_public_release="0" current_release="1" output_all_resource_defines="false"> - <outputs> - <output filename="grit/ash_shell_resources.h" type="rc_header"> - <emit emit_type='prepend'></emit> - </output> - <output filename="ash_shell_resources.pak" type="data_package" /> - </outputs> - <release seq="1"> - <includes> - <include name="IDR_ASH_SHELL_CONTENT_BROWSER_MANIFEST_OVERLAY" file="${root_gen_dir}\ash\shell\ash_content_browser_manifest_overlay.json" type="BINDATA" use_base_dir="false"/> - <include name="IDR_ASH_SHELL_CONTENT_PACKAGED_SERVICES_MANIFEST_OVERLAY" file="${root_gen_dir}\ash\shell\ash_content_packaged_services_manifest_overlay.json" type="BINDATA" use_base_dir="false"/> - <include name="IDR_ASH_SHELL_FONT_SERVICE_MANIFEST" file="../../components/services/font/manifest.json" type="BINDATA" use_base_dir="false" /> - <include name="IDR_ASH_SHELL_QUICK_LAUNCH_MANIFEST" file="../../ash/components/quick_launch/manifest.json" type="BINDATA" use_base_dir="false" /> - <include name="IDR_ASH_SHELL_SHORTCUT_VIEWER_MANIFEST" file="../../ash/components/shortcut_viewer/manifest.json" type="BINDATA" use_base_dir="false" /> - <include name="IDR_ASH_SHELL_TAP_VISUALIZER_MANIFEST" file="../../ash/components/tap_visualizer/manifest.json" type="BINDATA" use_base_dir="false" /> - <include name="IDR_ASH_SHELL_TEST_IME_DRIVER_MANIFEST" file="../../services/ws/ime/test_ime_driver/manifest.json" type="BINDATA" use_base_dir="false" /> - </includes> - </release> -</grit>
diff --git a/ash/shell/content/client/DEPS b/ash/shell/content/client/DEPS index 3ff3bd3..b4e4b71 100644 --- a/ash/shell/content/client/DEPS +++ b/ash/shell/content/client/DEPS
@@ -6,5 +6,6 @@ "+content/public", "+content/shell", "+storage/browser/quota", + "+services/device/public", "+services/ws/ime/test_ime_driver", ]
diff --git a/ash/shell/content/client/shell_content_browser_client.cc b/ash/shell/content/client/shell_content_browser_client.cc index d37d07b..ce8fe44 100644 --- a/ash/shell/content/client/shell_content_browser_client.cc +++ b/ash/shell/content/client/shell_content_browser_client.cc
@@ -7,18 +7,21 @@ #include <utility> #include "ash/ash_service.h" +#include "ash/components/quick_launch/manifest.h" #include "ash/components/quick_launch/public/mojom/constants.mojom.h" +#include "ash/components/shortcut_viewer/manifest.h" #include "ash/components/shortcut_viewer/public/mojom/shortcut_viewer.mojom.h" +#include "ash/components/tap_visualizer/manifest.h" #include "ash/components/tap_visualizer/public/mojom/tap_visualizer.mojom.h" +#include "ash/manifest.h" #include "ash/public/cpp/window_properties.h" #include "ash/public/interfaces/constants.mojom.h" #include "ash/shell.h" #include "ash/shell/content/client/shell_browser_main_parts.h" -#include "ash/shell/grit/ash_shell_resources.h" #include "base/base_switches.h" #include "base/bind.h" #include "base/command_line.h" -#include "base/json/json_reader.h" +#include "base/no_destructor.h" #include "base/stl_util.h" #include "base/strings/utf_string_conversions.h" #include "content/public/browser/browser_context.h" @@ -26,16 +29,47 @@ #include "content/public/common/service_manager_connection.h" #include "content/public/common/service_names.mojom.h" #include "content/public/utility/content_utility_client.h" +#include "services/device/public/mojom/constants.mojom.h" +#include "services/service_manager/public/cpp/manifest.h" +#include "services/service_manager/public/cpp/manifest_builder.h" +#include "services/ws/ime/test_ime_driver/manifest.h" #include "services/ws/ime/test_ime_driver/public/mojom/constants.mojom.h" #include "services/ws/public/mojom/constants.mojom.h" #include "services/ws/window_service.h" #include "storage/browser/quota/quota_settings.h" #include "third_party/skia/include/core/SkBitmap.h" -#include "ui/base/resource/resource_bundle.h" namespace ash { namespace shell { +namespace { + +const service_manager::Manifest& GetAshShellBrowserOverlayManifest() { + static base::NoDestructor<service_manager::Manifest> manifest{ + service_manager::ManifestBuilder() + .RequireCapability(device::mojom::kServiceName, "device:fingerprint") + .RequireCapability(shortcut_viewer::mojom::kServiceName, + "shortcut_viewer") + .RequireCapability(tap_visualizer::mojom::kServiceName, + "tap_visualizer") + .Build()}; + return *manifest; +} + +const service_manager::Manifest& GetAshShellPackagedServicesOverlayManifest() { + static base::NoDestructor<service_manager::Manifest> manifest{ + service_manager::ManifestBuilder() + .PackageService(ash::GetManifest()) + .PackageService(quick_launch_app::GetManifest()) + .PackageService(shortcut_viewer_app::GetManifest()) + .PackageService(tap_visualizer_app::GetManifest()) + .PackageService(test_ime_driver::GetManifest()) + .Build()}; + return *manifest; +} + +} // namespace + ShellContentBrowserClient::ShellContentBrowserClient() : shell_browser_main_parts_(nullptr) {} @@ -57,38 +91,15 @@ base::Optional<service_manager::Manifest> ShellContentBrowserClient::GetServiceManifestOverlay(base::StringPiece name) { - if (name == content::mojom::kBrowserServiceName) { - // This is necessary for outgoing interface requests (such as the keyboard - // shortcut viewer). - ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); - base::StringPiece manifest_contents = rb.GetRawDataResourceForScale( - IDR_ASH_SHELL_CONTENT_BROWSER_MANIFEST_OVERLAY, - ui::ScaleFactor::SCALE_FACTOR_NONE); - return service_manager::Manifest::FromValueDeprecated( - base::JSONReader::Read(manifest_contents)); - } - if (name == content::mojom::kPackagedServicesServiceName) { - ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); - base::StringPiece manifest_contents = rb.GetRawDataResourceForScale( - IDR_ASH_SHELL_CONTENT_PACKAGED_SERVICES_MANIFEST_OVERLAY, - ui::ScaleFactor::SCALE_FACTOR_NONE); - return service_manager::Manifest::FromValueDeprecated( - base::JSONReader::Read(manifest_contents)); - } - return base::nullopt; -} + // This is necessary for outgoing interface requests (such as the keyboard + // shortcut viewer). + if (name == content::mojom::kBrowserServiceName) + return GetAshShellBrowserOverlayManifest(); -std::vector<content::ContentBrowserClient::ServiceManifestInfo> -ShellContentBrowserClient::GetExtraServiceManifests() { - return { - {quick_launch::mojom::kServiceName, IDR_ASH_SHELL_QUICK_LAUNCH_MANIFEST}, - {shortcut_viewer::mojom::kServiceName, - IDR_ASH_SHELL_SHORTCUT_VIEWER_MANIFEST}, - {tap_visualizer::mojom::kServiceName, - IDR_ASH_SHELL_TAP_VISUALIZER_MANIFEST}, - {test_ime_driver::mojom::kServiceName, - IDR_ASH_SHELL_TEST_IME_DRIVER_MANIFEST}, - }; + if (name == content::mojom::kPackagedServicesServiceName) + return GetAshShellPackagedServicesOverlayManifest(); + + return base::nullopt; } void ShellContentBrowserClient::RegisterOutOfProcessServices(
diff --git a/ash/shell/content/client/shell_content_browser_client.h b/ash/shell/content/client/shell_content_browser_client.h index 8162e1f..54c934a 100644 --- a/ash/shell/content/client/shell_content_browser_client.h +++ b/ash/shell/content/client/shell_content_browser_client.h
@@ -34,7 +34,6 @@ storage::OptionalQuotaSettingsCallback callback) override; base::Optional<service_manager::Manifest> GetServiceManifestOverlay( base::StringPiece name) override; - std::vector<ServiceManifestInfo> GetExtraServiceManifests() override; void RegisterOutOfProcessServices(OutOfProcessServiceMap* services) override; void HandleServiceRequest( const std::string& service_name,
diff --git a/ash/system/date/date_view.cc b/ash/system/date/date_view.cc index 5f488c4..589bd322 100644 --- a/ash/system/date/date_view.cc +++ b/ash/system/date/date_view.cc
@@ -56,147 +56,19 @@ } // namespace -BaseDateTimeView::~BaseDateTimeView() { - model_->RemoveObserver(this); - timer_.Stop(); -} - -void BaseDateTimeView::UpdateText() { - base::Time now = base::Time::Now(); - UpdateTextInternal(now); - SchedulePaint(); - SetTimer(now); -} - -void BaseDateTimeView::UpdateTimeFormat() { - UpdateText(); -} - -void BaseDateTimeView::GetAccessibleNodeData(ui::AXNodeData* node_data) { - ActionableView::GetAccessibleNodeData(node_data); - node_data->role = ax::mojom::Role::kTime; -} - -void BaseDateTimeView::OnDateFormatChanged() { - UpdateTimeFormat(); -} - -void BaseDateTimeView::OnSystemClockTimeUpdated() { - UpdateTimeFormat(); -} - -void BaseDateTimeView::OnSystemClockCanSetTimeChanged(bool can_set_time) {} - -void BaseDateTimeView::Refresh() {} - -base::HourClockType BaseDateTimeView::GetHourTypeForTesting() const { - return model_->hour_clock_type(); -} - -BaseDateTimeView::BaseDateTimeView(ClockModel* model) +TimeView::TimeView(ClockLayout clock_layout, ClockModel* model) : ActionableView(TrayPopupInkDropStyle::INSET_BOUNDS), model_(model) { SetTimer(base::Time::Now()); SetFocusBehavior(FocusBehavior::NEVER); model_->AddObserver(this); -} - -void BaseDateTimeView::SetTimer(const base::Time& now) { - // Try to set the timer to go off at the next change of the minute. We don't - // want to have the timer go off more than necessary since that will cause - // the CPU to wake up and consume power. - base::Time::Exploded exploded; - now.LocalExplode(&exploded); - - // Often this will be called at minute boundaries, and we'll actually want - // 60 seconds from now. - int seconds_left = 60 - exploded.second; - if (seconds_left == 0) - seconds_left = 60; - - // Make sure that the timer fires on the next minute. Without this, if it is - // called just a teeny bit early, then it will skip the next minute. - seconds_left += kTimerSlopSeconds; - - timer_.Stop(); - timer_.Start(FROM_HERE, base::TimeDelta::FromSeconds(seconds_left), this, - &BaseDateTimeView::UpdateText); -} - -void BaseDateTimeView::UpdateTextInternal(const base::Time& now) { - SetAccessibleName(base::TimeFormatTimeOfDayWithHourClockType( - now, model_->hour_clock_type(), base::kKeepAmPm) + - base::ASCIIToUTF16(", ") + - base::TimeFormatFriendlyDate(now)); - - NotifyAccessibilityEvent(ax::mojom::Event::kTextChanged, true); -} - -void BaseDateTimeView::ChildPreferredSizeChanged(views::View* child) { - PreferredSizeChanged(); -} - -/////////////////////////////////////////////////////////////////////////////// - -TimeView::TimeView(ClockLayout clock_layout, ClockModel* model) - : BaseDateTimeView(model) { SetupLabels(); UpdateTextInternal(base::Time::Now()); UpdateClockLayout(clock_layout); } -TimeView::~TimeView() = default; - -void TimeView::UpdateTextInternal(const base::Time& now) { - // Just in case |now| is null, do NOT update time; otherwise, it will - // crash icu code by calling into base::TimeFormatTimeOfDayWithHourClockType, - // see details in crbug.com/147570. - if (now.is_null()) { - LOG(ERROR) << "Received null value from base::Time |now| in argument"; - return; - } - - BaseDateTimeView::UpdateTextInternal(now); - base::string16 current_time = base::TimeFormatTimeOfDayWithHourClockType( - now, model_->hour_clock_type(), base::kDropAmPm); - horizontal_label_->SetText(current_time); - horizontal_label_->SetTooltipText(base::TimeFormatFriendlyDate(now)); - horizontal_label_->NotifyAccessibilityEvent(ax::mojom::Event::kTextChanged, - true); - - // Calculate vertical clock layout labels. - size_t colon_pos = current_time.find(base::ASCIIToUTF16(":")); - base::string16 hour = current_time.substr(0, colon_pos); - base::string16 minute = current_time.substr(colon_pos + 1); - - // Sometimes pad single-digit hours with a zero for aesthetic reasons. - if (hour.length() == 1 && model_->hour_clock_type() == base::k24HourClock && - !base::i18n::IsRTL()) - hour = base::ASCIIToUTF16("0") + hour; - - vertical_label_hours_->SetText(hour); - vertical_label_minutes_->SetText(minute); - vertical_label_hours_->NotifyAccessibilityEvent( - ax::mojom::Event::kTextChanged, true); - vertical_label_minutes_->NotifyAccessibilityEvent( - ax::mojom::Event::kTextChanged, true); - Layout(); -} - -bool TimeView::PerformAction(const ui::Event& event) { - return false; -} - -bool TimeView::OnMousePressed(const ui::MouseEvent& event) { - // Let the event fall through. - return false; -} - -void TimeView::OnGestureEvent(ui::GestureEvent* event) { - // Skip gesture handling happening in Button so that the container views - // receive and handle them properly. - // TODO(mohsen): Refactor TimeView/DateView classes so that they are not - // ActionableView anymore. Create an ActionableView as a container for when - // needed. +TimeView::~TimeView() { + model_->RemoveObserver(this); + timer_.Stop(); } void TimeView::UpdateClockLayout(ClockLayout clock_layout) { @@ -236,10 +108,103 @@ set_color(vertical_label_minutes_); } +void TimeView::OnDateFormatChanged() { + UpdateTimeFormat(); +} + +void TimeView::OnSystemClockTimeUpdated() { + UpdateTimeFormat(); +} + +void TimeView::OnSystemClockCanSetTimeChanged(bool can_set_time) {} + void TimeView::Refresh() { UpdateText(); } +base::HourClockType TimeView::GetHourTypeForTesting() const { + return model_->hour_clock_type(); +} + +bool TimeView::PerformAction(const ui::Event& event) { + return false; +} + +void TimeView::GetAccessibleNodeData(ui::AXNodeData* node_data) { + ActionableView::GetAccessibleNodeData(node_data); + node_data->role = ax::mojom::Role::kTime; +} + +void TimeView::ChildPreferredSizeChanged(views::View* child) { + PreferredSizeChanged(); +} + +bool TimeView::OnMousePressed(const ui::MouseEvent& event) { + // Let the event fall through. + return false; +} + +void TimeView::OnGestureEvent(ui::GestureEvent* event) { + // Skip gesture handling happening in Button so that the container views + // receive and handle them properly. + // TODO(mohsen): Refactor TimeView/DateView classes so that they are not + // ActionableView anymore. Create an ActionableView as a container for when + // needed. +} + +void TimeView::UpdateText() { + base::Time now = base::Time::Now(); + UpdateTextInternal(now); + SchedulePaint(); + SetTimer(now); +} + +void TimeView::UpdateTimeFormat() { + UpdateText(); +} + +void TimeView::UpdateTextInternal(const base::Time& now) { + // Just in case |now| is null, do NOT update time; otherwise, it will + // crash icu code by calling into base::TimeFormatTimeOfDayWithHourClockType, + // see details in crbug.com/147570. + if (now.is_null()) { + LOG(ERROR) << "Received null value from base::Time |now| in argument"; + return; + } + + SetAccessibleName(base::TimeFormatTimeOfDayWithHourClockType( + now, model_->hour_clock_type(), base::kKeepAmPm) + + base::ASCIIToUTF16(", ") + + base::TimeFormatFriendlyDate(now)); + + NotifyAccessibilityEvent(ax::mojom::Event::kTextChanged, true); + + base::string16 current_time = base::TimeFormatTimeOfDayWithHourClockType( + now, model_->hour_clock_type(), base::kDropAmPm); + horizontal_label_->SetText(current_time); + horizontal_label_->SetTooltipText(base::TimeFormatFriendlyDate(now)); + horizontal_label_->NotifyAccessibilityEvent(ax::mojom::Event::kTextChanged, + true); + + // Calculate vertical clock layout labels. + size_t colon_pos = current_time.find(base::ASCIIToUTF16(":")); + base::string16 hour = current_time.substr(0, colon_pos); + base::string16 minute = current_time.substr(colon_pos + 1); + + // Sometimes pad single-digit hours with a zero for aesthetic reasons. + if (hour.length() == 1 && model_->hour_clock_type() == base::k24HourClock && + !base::i18n::IsRTL()) + hour = base::ASCIIToUTF16("0") + hour; + + vertical_label_hours_->SetText(hour); + vertical_label_minutes_->SetText(minute); + vertical_label_hours_->NotifyAccessibilityEvent( + ax::mojom::Event::kTextChanged, true); + vertical_label_minutes_->NotifyAccessibilityEvent( + ax::mojom::Event::kTextChanged, true); + Layout(); +} + void TimeView::SetupLabels() { horizontal_label_.reset(new views::Label()); SetupLabel(horizontal_label_.get()); @@ -261,5 +226,27 @@ label->SetElideBehavior(gfx::NO_ELIDE); } +void TimeView::SetTimer(const base::Time& now) { + // Try to set the timer to go off at the next change of the minute. We don't + // want to have the timer go off more than necessary since that will cause + // the CPU to wake up and consume power. + base::Time::Exploded exploded; + now.LocalExplode(&exploded); + + // Often this will be called at minute boundaries, and we'll actually want + // 60 seconds from now. + int seconds_left = 60 - exploded.second; + if (seconds_left == 0) + seconds_left = 60; + + // Make sure that the timer fires on the next minute. Without this, if it is + // called just a teeny bit early, then it will skip the next minute. + seconds_left += kTimerSlopSeconds; + + timer_.Stop(); + timer_.Start(FROM_HERE, base::TimeDelta::FromSeconds(seconds_left), this, + &TimeView::UpdateText); +} + } // namespace tray } // namespace ash
diff --git a/ash/system/date/date_view.h b/ash/system/date/date_view.h index a5ba987..bfbf61b9 100644 --- a/ash/system/date/date_view.h +++ b/ash/system/date/date_view.h
@@ -30,55 +30,9 @@ namespace tray { -// Abstract base class containing common updating and layout code for the -// DateView popup and the TimeView tray icon. Exported for tests. -class ASH_EXPORT BaseDateTimeView : public ActionableView, - public ClockObserver { - public: - ~BaseDateTimeView() override; - - // Updates the displayed text for the current time and calls SetTimer(). - void UpdateText(); - - // Updates the format of the displayed time. - void UpdateTimeFormat(); - - // views::View: - void GetAccessibleNodeData(ui::AXNodeData* node_data) override; - - // ClockObserver: - void OnDateFormatChanged() override; - void OnSystemClockTimeUpdated() override; - void OnSystemClockCanSetTimeChanged(bool can_set_time) override; - void Refresh() override; - - base::HourClockType GetHourTypeForTesting() const; - - protected: - explicit BaseDateTimeView(ClockModel* model); - - // Updates labels to display the current time. - virtual void UpdateTextInternal(const base::Time& now); - - ClockModel* const model_; - - private: - // Starts |timer_| to schedule the next update. - void SetTimer(const base::Time& now); - - // views::View: - void ChildPreferredSizeChanged(views::View* child) override; - - // Invokes UpdateText() when the displayed time should change. - base::OneShotTimer timer_; - - DISALLOW_COPY_AND_ASSIGN(BaseDateTimeView); -}; - // Tray view used to display the current time. // Exported for tests. -// TODO(tetsui): Combine with BaseDateTimeView. https://crbug.com/901712 -class ASH_EXPORT TimeView : public BaseDateTimeView { +class ASH_EXPORT TimeView : public ActionableView, public ClockObserver { public: enum class ClockLayout { HORIZONTAL_CLOCK, @@ -95,24 +49,40 @@ void SetTextColorBasedOnSession(session_manager::SessionState session_state); // ClockObserver: + void OnDateFormatChanged() override; + void OnSystemClockTimeUpdated() override; + void OnSystemClockCanSetTimeChanged(bool can_set_time) override; void Refresh() override; + base::HourClockType GetHourTypeForTesting() const; + private: friend class TimeViewTest; - // BaseDateTimeView: - void UpdateTextInternal(const base::Time& now) override; - // ActionableView: bool PerformAction(const ui::Event& event) override; // views::View: + void GetAccessibleNodeData(ui::AXNodeData* node_data) override; + void ChildPreferredSizeChanged(views::View* child) override; bool OnMousePressed(const ui::MouseEvent& event) override; void OnGestureEvent(ui::GestureEvent* event) override; + // Updates the displayed text for the current time and calls SetTimer(). + void UpdateText(); + + // Updates the format of the displayed time. + void UpdateTimeFormat(); + + // Updates labels to display the current time. + void UpdateTextInternal(const base::Time& now); + void SetupLabels(); void SetupLabel(views::Label* label); + // Starts |timer_| to schedule the next update. + void SetTimer(const base::Time& now); + // Label text used for the normal horizontal shelf. std::unique_ptr<views::Label> horizontal_label_; @@ -120,6 +90,11 @@ std::unique_ptr<views::Label> vertical_label_hours_; std::unique_ptr<views::Label> vertical_label_minutes_; + // Invokes UpdateText() when the displayed time should change. + base::OneShotTimer timer_; + + ClockModel* const model_; + DISALLOW_COPY_AND_ASSIGN(TimeView); };
diff --git a/ash/system/network/tray_vpn.h b/ash/system/network/tray_vpn.h deleted file mode 100644 index 445570d5f..0000000 --- a/ash/system/network/tray_vpn.h +++ /dev/null
@@ -1,19 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef ASH_SYSTEM_NETWORK_TRAY_VPN_H_ -#define ASH_SYSTEM_NETWORK_TRAY_VPN_H_ - -namespace ash { -namespace tray { - -// TODO(tetsui): Move them to VpnList. https://crbug.com/901714 -extern bool IsVPNVisibleInSystemTray(); -extern bool IsVPNEnabled(); -extern bool IsVPNConnected(); - -} // namespace tray -} // namespace ash - -#endif // ASH_SYSTEM_NETWORK_TRAY_VPN_H_
diff --git a/ash/system/network/vpn_feature_pod_controller.cc b/ash/system/network/vpn_feature_pod_controller.cc index 20c9983c..fd44d4f 100644 --- a/ash/system/network/vpn_feature_pod_controller.cc +++ b/ash/system/network/vpn_feature_pod_controller.cc
@@ -9,8 +9,8 @@ #include "ash/shell.h" #include "ash/strings/grit/ash_strings.h" #include "ash/system/network/network_icon.h" -#include "ash/system/network/tray_vpn.h" #include "ash/system/network/vpn_list.h" +#include "ash/system/network/vpn_util.h" #include "ash/system/tray/tray_constants.h" #include "ash/system/unified/feature_pod_button.h" #include "ash/system/unified/unified_system_tray_controller.h" @@ -63,14 +63,14 @@ if (!chromeos::NetworkHandler::IsInitialized()) return; - button_->SetVisible(tray::IsVPNVisibleInSystemTray()); + button_->SetVisible(vpn_util::IsVPNVisibleInSystemTray()); if (!button_->visible()) return; button_->SetSubLabel(l10n_util::GetStringUTF16( - tray::IsVPNConnected() ? IDS_ASH_STATUS_TRAY_VPN_CONNECTED_SHORT - : IDS_ASH_STATUS_TRAY_VPN_DISCONNECTED_SHORT)); - button_->SetToggled(tray::IsVPNEnabled() && tray::IsVPNConnected()); + vpn_util::IsVPNConnected() ? IDS_ASH_STATUS_TRAY_VPN_CONNECTED_SHORT + : IDS_ASH_STATUS_TRAY_VPN_DISCONNECTED_SHORT)); + button_->SetToggled(vpn_util::IsVPNEnabled() && vpn_util::IsVPNConnected()); } } // namespace ash
diff --git a/ash/system/network/tray_vpn.cc b/ash/system/network/vpn_util.cc similarity index 94% rename from ash/system/network/tray_vpn.cc rename to ash/system/network/vpn_util.cc index 15ab4b1..2d80e46 100644 --- a/ash/system/network/tray_vpn.cc +++ b/ash/system/network/vpn_util.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ash/system/network/tray_vpn.h" +#include "ash/system/network/vpn_util.h" #include "ash/session/session_controller.h" #include "ash/shell.h" @@ -16,7 +16,7 @@ using chromeos::NetworkTypePattern; namespace ash { -namespace tray { +namespace vpn_util { bool IsVPNVisibleInSystemTray() { LoginStatus login_status = Shell::Get()->session_controller()->login_status(); @@ -49,5 +49,5 @@ (vpn->IsConnectedState() || vpn->IsConnectingState()); } -} // namespace tray +} // namespace vpn_util } // namespace ash
diff --git a/ash/system/network/vpn_util.h b/ash/system/network/vpn_util.h new file mode 100644 index 0000000..d2fdc03 --- /dev/null +++ b/ash/system/network/vpn_util.h
@@ -0,0 +1,18 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef ASH_SYSTEM_NETWORK_VPN_UTIL_H_ +#define ASH_SYSTEM_NETWORK_VPN_UTIL_H_ + +namespace ash { +namespace vpn_util { + +extern bool IsVPNVisibleInSystemTray(); +extern bool IsVPNEnabled(); +extern bool IsVPNConnected(); + +} // namespace vpn_util +} // namespace ash + +#endif // ASH_SYSTEM_NETWORK_VPN_UTIL_H_
diff --git a/ash/wm/overview/window_selector.cc b/ash/wm/overview/window_selector.cc index 90832b2d..bac7095 100644 --- a/ash/wm/overview/window_selector.cc +++ b/ash/wm/overview/window_selector.cc
@@ -449,7 +449,8 @@ void WindowSelector::InitiateDrag(WindowSelectorItem* item, const gfx::Point& location_in_screen) { - window_drag_controller_.reset(new OverviewWindowDragController(this)); + window_drag_controller_ = + std::make_unique<OverviewWindowDragController>(this); window_drag_controller_->InitiateDrag(item, location_in_screen); for (std::unique_ptr<WindowGrid>& grid : grid_list_) @@ -813,7 +814,10 @@ void WindowSelector::ResetFocusRestoreWindow(bool focus) { if (!restore_focus_window_) return; - if (focus) { + + // Ensure the window is still in the window hierarchy and not in the middle + // of teardown. + if (focus && restore_focus_window_->GetRootWindow()) { base::AutoReset<bool> restoring_focus(&ignore_activations_, true); wm::ActivateWindow(restore_focus_window_); }
diff --git a/ash/wm/overview/window_selector_controller_unittest.cc b/ash/wm/overview/window_selector_controller_unittest.cc index 8a4398ee..0f3dab6 100644 --- a/ash/wm/overview/window_selector_controller_unittest.cc +++ b/ash/wm/overview/window_selector_controller_unittest.cc
@@ -4,6 +4,7 @@ #include "ash/wm/overview/window_selector_controller.h" +#include "ash/app_list/test/app_list_test_helper.h" #include "ash/shell.h" #include "ash/shell_observer.h" #include "ash/test/ash_test_base.h" @@ -333,6 +334,18 @@ EXPECT_EQ(OcclusionState::OCCLUDED, window2->occlusion_state()); } +// Tests that beginning window selection hides the app list. +TEST_F(WindowSelectorControllerTest, SelectingHidesAppList) { + std::unique_ptr<aura::Window> window(CreateTestWindow()); + + GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplay().id()); + GetAppListTestHelper()->CheckVisibility(true); + + Shell::Get()->window_selector_controller()->ToggleOverview(); + GetAppListTestHelper()->WaitUntilIdle(); + GetAppListTestHelper()->CheckVisibility(false); +} + class OverviewVirtualKeyboardTest : public WindowSelectorControllerTest { protected: void SetUp() override {
diff --git a/ash/wm/overview/window_selector_unittest.cc b/ash/wm/overview/window_selector_unittest.cc index 6b8d991..303e13e 100644 --- a/ash/wm/overview/window_selector_unittest.cc +++ b/ash/wm/overview/window_selector_unittest.cc
@@ -4,30 +4,22 @@ #include <algorithm> #include <memory> -#include <string> #include <vector> #include "ash/accessibility/accessibility_controller.h" #include "ash/accessibility/test_accessibility_controller_client.h" #include "ash/app_list/app_list_controller_impl.h" -#include "ash/app_list/home_launcher_gesture_handler.h" -#include "ash/app_list/test/app_list_test_helper.h" #include "ash/display/screen_orientation_controller.h" #include "ash/display/screen_orientation_controller_test_api.h" #include "ash/drag_drop/drag_drop_controller.h" -#include "ash/public/cpp/app_list/app_list_constants.h" -#include "ash/public/cpp/ash_features.h" -#include "ash/public/cpp/ash_switches.h" #include "ash/public/cpp/window_properties.h" #include "ash/screen_util.h" #include "ash/shelf/shelf.h" #include "ash/shelf/shelf_constants.h" #include "ash/shelf/shelf_view_test_api.h" #include "ash/shell.h" -#include "ash/system/unified/unified_system_tray.h" #include "ash/test/ash_test_base.h" #include "ash/wm/overview/caption_container_view.h" -#include "ash/wm/overview/cleanup_animation_observer.h" #include "ash/wm/overview/overview_constants.h" #include "ash/wm/overview/overview_utils.h" #include "ash/wm/overview/overview_window_drag_controller.h" @@ -35,27 +27,25 @@ #include "ash/wm/overview/window_selector.h" #include "ash/wm/overview/window_selector_controller.h" #include "ash/wm/overview/window_selector_item.h" -#include "ash/wm/splitview/split_view_constants.h" #include "ash/wm/splitview/split_view_controller.h" #include "ash/wm/splitview/split_view_divider.h" -#include "ash/wm/splitview/split_view_utils.h" #include "ash/wm/tablet_mode/tablet_mode_app_window_drag_controller.h" #include "ash/wm/tablet_mode/tablet_mode_controller.h" #include "ash/wm/window_state.h" #include "ash/wm/window_util.h" #include "ash/wm/wm_event.h" #include "ash/wm/workspace/workspace_window_resizer.h" -#include "base/memory/ptr_util.h" #include "base/run_loop.h" #include "base/stl_util.h" -#include "base/strings/string_number_conversions.h" #include "base/strings/utf_string_conversions.h" #include "base/test/metrics/user_action_tester.h" +#include "services/ws/public/mojom/window_tree_constants.mojom.h" #include "ui/aura/client/aura_constants.h" -#include "ui/aura/client/focus_client.h" #include "ui/aura/client/window_types.h" -#include "ui/aura/test/test_windows.h" +#include "ui/aura/test/test_window_delegate.h" #include "ui/aura/window.h" +#include "ui/aura/window_event_dispatcher.h" +#include "ui/aura/window_tree_host.h" #include "ui/base/hit_test.h" #include "ui/compositor/layer_animation_sequence.h" #include "ui/compositor/scoped_animation_duration_scale_mode.h" @@ -69,6 +59,7 @@ #include "ui/gfx/transform_util.h" #include "ui/views/controls/button/image_button.h" #include "ui/views/controls/label.h" +#include "ui/views/widget/widget.h" #include "ui/wm/core/coordinate_conversion.h" #include "ui/wm/core/shadow_controller.h" #include "ui/wm/core/window_util.h" @@ -79,20 +70,6 @@ constexpr const char kActiveWindowChangedFromOverview[] = "WindowSelector_ActiveWindowChanged"; -// A simple window delegate that returns the specified hit-test code when -// requested and applies a minimum size constraint if there is one. -class TestDragWindowDelegate : public aura::test::TestWindowDelegate { - public: - TestDragWindowDelegate() { set_window_component(HTCAPTION); } - ~TestDragWindowDelegate() override = default; - - private: - // Overridden from aura::Test::TestWindowDelegate: - void OnWindowDestroyed(aura::Window* window) override { delete this; } - - DISALLOW_COPY_AND_ASSIGN(TestDragWindowDelegate); -}; - // Helper function to get the index of |child|, given its parent window // |parent|. int IndexOf(aura::Window* child, aura::Window* parent) { @@ -156,41 +133,18 @@ WindowSelectorController::SetDoNotChangeWallpaperBlurForTests(); } - aura::Window* CreateWindow(const gfx::Rect& bounds) { - aura::Window* window = - CreateTestWindowInShellWithDelegate(&delegate_, -1, bounds); - window->SetProperty(aura::client::kTopViewInset, kHeaderHeightDp); - return window; - } - - aura::Window* CreateWindowWithId(const gfx::Rect& bounds, int id) { - aura::Window* window = - CreateTestWindowInShellWithDelegate(&delegate_, id, bounds); - window->SetProperty(aura::client::kTopViewInset, kHeaderHeightDp); - return window; - } - - // Creates a Widget containing a Window with the given |bounds|. This should - // be used when the test requires a Widget. For example any test that will - // cause a window to be closed via - // views::Widget::GetWidgetForNativeView(window)->Close(). - std::unique_ptr<views::Widget> CreateWindowWidget(const gfx::Rect& bounds) { - std::unique_ptr<views::Widget> widget(new views::Widget); - views::Widget::InitParams params; - params.bounds = bounds; - params.type = views::Widget::InitParams::TYPE_WINDOW; - params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; - params.context = CurrentContext(); - widget->Init(params); - widget->Show(); - aura::Window* window = widget->GetNativeWindow(); - window->SetProperty(aura::client::kTopViewInset, kHeaderHeightDp); - return widget; + // Enters tablet mode. Needed by tests that test dragging and or splitview, + // which are tablet mode only. + void EnterTabletMode() { + // Ensure calls to EnableTabletModeWindowManager complete. + base::RunLoop().RunUntilIdle(); + Shell::Get()->tablet_mode_controller()->EnableTabletModeWindowManager(true); + base::RunLoop().RunUntilIdle(); } bool WindowsOverlapping(aura::Window* window1, aura::Window* window2) { - gfx::Rect window1_bounds = GetTransformedTargetBounds(window1); - gfx::Rect window2_bounds = GetTransformedTargetBounds(window2); + const gfx::Rect window1_bounds = GetTransformedTargetBounds(window1); + const gfx::Rect window2_bounds = GetTransformedTargetBounds(window2); return window1_bounds.Intersects(window2_bounds); } @@ -209,8 +163,8 @@ aura::Window* GetOverviewWindowForMinimizedState(int index, aura::Window* window) { - WindowSelectorItem* selector = GetWindowItemForWindow(index, window); - return selector->GetOverviewWindowForMinimizedStateForTest(); + WindowSelectorItem* item = GetWindowItemForWindow(index, window); + return item->GetOverviewWindowForMinimizedStateForTest(); } gfx::Rect GetTransformedBounds(aura::Window* window) { @@ -255,8 +209,8 @@ void SendKey(ui::KeyboardCode key, int flags = ui::EF_NONE) { ui::test::EventGenerator event_generator(Shell::GetPrimaryRootWindow()); - event_generator.PressKey(key, flags); - event_generator.ReleaseKey(key, flags); + GetEventGenerator()->PressKey(key, flags); + GetEventGenerator()->ReleaseKey(key, flags); } bool IsSelecting() { return window_selector_controller()->IsSelecting(); } @@ -310,8 +264,8 @@ return ws->grid_list_[ws->selected_grid_index_]->is_selecting(); } - views::Widget* GetCloseButton(WindowSelectorItem* window) { - return window->caption_container_view_->GetCloseButton()->GetWidget(); + views::ImageButton* GetCloseButton(WindowSelectorItem* window) { + return window->caption_container_view_->GetCloseButton(); } views::Label* GetLabelView(WindowSelectorItem* window) { @@ -325,15 +279,14 @@ // Tests that a window is contained within a given WindowSelectorItem, and // that both the window and its matching close button are within the same // screen. - void IsWindowAndCloseButtonInScreen(aura::Window* window, - WindowSelectorItem* window_item) { - aura::Window* root_window = window_item->root_window(); + void CheckWindowAndCloseButtonInScreen(aura::Window* window, + WindowSelectorItem* window_item) { + const gfx::Rect screen_bounds = + window_item->root_window()->GetBoundsInScreen(); EXPECT_TRUE(window_item->Contains(window)); - EXPECT_TRUE(root_window->GetBoundsInScreen().Contains( - GetTransformedTargetBounds(window))); - EXPECT_TRUE( - root_window->GetBoundsInScreen().Contains(GetTransformedTargetBounds( - GetCloseButton(window_item)->GetNativeView()))); + EXPECT_TRUE(screen_bounds.Contains(GetTransformedTargetBounds(window))); + EXPECT_TRUE(screen_bounds.Contains( + GetCloseButton(window_item)->GetBoundsInScreen())); } void SetGridBounds(WindowGrid* grid, const gfx::Rect& bounds) { @@ -364,7 +317,6 @@ } private: - aura::test::TestWindowDelegate delegate_; std::unique_ptr<ShelfViewTestAPI> shelf_view_test_api_; DISALLOW_COPY_AND_ASSIGN(WindowSelectorTest); @@ -372,12 +324,11 @@ // Tests that an a11y alert is sent on entering overview mode. TEST_F(WindowSelectorTest, A11yAlertOnOverviewMode) { - const gfx::Rect bounds(400, 400); TestAccessibilityControllerClient client; AccessibilityController* controller = Shell::Get()->accessibility_controller(); controller->SetClient(client.CreateInterfacePtrAndBind()); - std::unique_ptr<aura::Window> window(CreateWindow(bounds)); + std::unique_ptr<aura::Window> window(CreateTestWindow()); EXPECT_NE(mojom::AccessibilityAlert::WINDOW_OVERVIEW_MODE_ENTERED, client.last_a11y_alert()); ToggleOverview(); @@ -391,10 +342,10 @@ TEST_F(WindowSelectorTest, SmallDisplay) { UpdateDisplay("3x1"); gfx::Rect bounds(0, 0, 1, 1); - std::unique_ptr<aura::Window> window1(CreateWindow(bounds)); - std::unique_ptr<aura::Window> window2(CreateWindow(bounds)); - std::unique_ptr<aura::Window> window3(CreateWindow(bounds)); - std::unique_ptr<aura::Window> window4(CreateWindow(bounds)); + std::unique_ptr<aura::Window> window1(CreateTestWindow(bounds)); + std::unique_ptr<aura::Window> window2(CreateTestWindow(bounds)); + std::unique_ptr<aura::Window> window3(CreateTestWindow(bounds)); + std::unique_ptr<aura::Window> window4(CreateTestWindow(bounds)); window1->SetProperty(aura::client::kTopViewInset, 0); window2->SetProperty(aura::client::kTopViewInset, 0); window3->SetProperty(aura::client::kTopViewInset, 0); @@ -404,16 +355,19 @@ // Tests entering overview mode with two windows and selecting one by clicking. TEST_F(WindowSelectorTest, Basic) { - const gfx::Rect bounds(400, 400); + // Overview disabled by default. + EXPECT_FALSE(IsSelecting()); + aura::Window* root_window = Shell::GetPrimaryRootWindow(); - std::unique_ptr<aura::Window> window1(CreateWindow(bounds)); - std::unique_ptr<aura::Window> window2(CreateWindow(bounds)); + std::unique_ptr<aura::Window> window1(CreateTestWindow()); + std::unique_ptr<aura::Window> window2(CreateTestWindow()); EXPECT_TRUE(WindowsOverlapping(window1.get(), window2.get())); - wm::ActivateWindow(window2.get()); + ::wm::ActivateWindow(window2.get()); EXPECT_FALSE(wm::IsActiveWindow(window1.get())); EXPECT_TRUE(wm::IsActiveWindow(window2.get())); EXPECT_EQ(window2.get(), wm::GetFocusedWindow()); + // Hide the cursor before entering overview to test that it will be shown. aura::client::GetCursorClient(root_window)->HideCursor(); @@ -436,8 +390,7 @@ // Tests activating minimized window. TEST_F(WindowSelectorTest, ActivateMinimized) { - const gfx::Rect bounds(400, 400); - std::unique_ptr<aura::Window> window(CreateWindow(bounds)); + std::unique_ptr<aura::Window> window(CreateTestWindow()); wm::WindowState* window_state = wm::GetWindowState(window.get()); wm::WMEvent minimize_event(wm::WM_EVENT_MINIMIZE); @@ -459,9 +412,8 @@ const gfx::Point point = GetTransformedBoundsInRootWindow(window_for_minimized_window) .CenterPoint(); - ui::test::EventGenerator event_generator( - window_for_minimized_window->GetRootWindow(), point); - event_generator.ClickLeftButton(); + GetEventGenerator()->set_current_screen_location(point); + GetEventGenerator()->ClickLeftButton(); EXPECT_FALSE(IsSelecting()); @@ -473,10 +425,9 @@ // Tests that the ordering of windows is stable across different overview // sessions even when the windows have the same bounds. TEST_F(WindowSelectorTest, WindowsOrder) { - const gfx::Rect bounds(400, 400); - std::unique_ptr<aura::Window> window1(CreateWindowWithId(bounds, 1)); - std::unique_ptr<aura::Window> window2(CreateWindowWithId(bounds, 2)); - std::unique_ptr<aura::Window> window3(CreateWindowWithId(bounds, 3)); + std::unique_ptr<aura::Window> window1(CreateTestWindowInShellWithId(1)); + std::unique_ptr<aura::Window> window2(CreateTestWindowInShellWithId(2)); + std::unique_ptr<aura::Window> window3(CreateTestWindowInShellWithId(3)); // The order of windows in overview mode is MRU. wm::GetWindowState(window1.get())->Activate(); @@ -503,17 +454,14 @@ // Tests selecting a window by tapping on it. TEST_F(WindowSelectorTest, BasicGesture) { - const gfx::Rect bounds(400, 400); - std::unique_ptr<aura::Window> window1(CreateWindow(bounds)); - std::unique_ptr<aura::Window> window2(CreateWindow(bounds)); - wm::ActivateWindow(window1.get()); + std::unique_ptr<aura::Window> window1(CreateTestWindow()); + std::unique_ptr<aura::Window> window2(CreateTestWindow()); + ::wm::ActivateWindow(window1.get()); EXPECT_EQ(window1.get(), wm::GetFocusedWindow()); ToggleOverview(); EXPECT_EQ(window_selector()->GetOverviewFocusWindow(), wm::GetFocusedWindow()); - ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow(), - window2.get()); - generator.GestureTapAt( + GetEventGenerator()->GestureTapAt( GetTransformedTargetBounds(window2.get()).CenterPoint()); EXPECT_EQ(window2.get(), wm::GetFocusedWindow()); } @@ -523,22 +471,19 @@ // in overview mode which is different from the previously-active window. TEST_F(WindowSelectorTest, ActiveWindowChangedUserActionRecorded) { base::UserActionTester user_action_tester; - const gfx::Rect bounds(400, 400); - std::unique_ptr<aura::Window> window1(CreateWindow(bounds)); - std::unique_ptr<aura::Window> window2(CreateWindow(bounds)); + std::unique_ptr<aura::Window> window1(CreateTestWindow()); + std::unique_ptr<aura::Window> window2(CreateTestWindow()); + ::wm::ActivateWindow(window1.get()); + ToggleOverview(); // Tap on |window2| to activate it and exit overview. - wm::ActivateWindow(window1.get()); - ToggleOverview(); - ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow(), - window2.get()); - generator.GestureTapAt( + GetEventGenerator()->GestureTapAt( GetTransformedTargetBounds(window2.get()).CenterPoint()); EXPECT_EQ( 1, user_action_tester.GetActionCount(kActiveWindowChangedFromOverview)); // Click on |window2| to activate it and exit overview. - wm::ActivateWindow(window1.get()); + ::wm::ActivateWindow(window1.get()); ToggleOverview(); ClickWindow(window2.get()); EXPECT_EQ( @@ -546,7 +491,7 @@ // Select |window2| using the arrow keys. Activate it (and exit overview) by // pressing the return key. - wm::ActivateWindow(window1.get()); + ::wm::ActivateWindow(window1.get()); ToggleOverview(); ASSERT_TRUE(SelectWindow(window2.get())); SendKey(ui::VKEY_RETURN); @@ -560,18 +505,13 @@ // exiting overview without selecting a window does not record the action. TEST_F(WindowSelectorTest, ActiveWindowChangedUserActionNotRecorded) { base::UserActionTester user_action_tester; - const gfx::Rect bounds(400, 400); - std::unique_ptr<aura::Window> window1(CreateWindow(bounds)); - std::unique_ptr<aura::Window> window2(CreateWindow(bounds)); - - // Set |window1| to be initially active. - wm::ActivateWindow(window1.get()); + std::unique_ptr<aura::Window> window1(CreateTestWindow()); + std::unique_ptr<aura::Window> window2(CreateTestWindow()); + ::wm::ActivateWindow(window1.get()); ToggleOverview(); // Tap on |window1| to exit overview. - ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow(), - window1.get()); - generator.GestureTapAt( + GetEventGenerator()->GestureTapAt( GetTransformedTargetBounds(window1.get()).CenterPoint()); EXPECT_EQ( 0, user_action_tester.GetActionCount(kActiveWindowChangedFromOverview)); @@ -603,18 +543,17 @@ // recorded when overview mode exits as a result of closing its only window. TEST_F(WindowSelectorTest, ActiveWindowChangedUserActionWindowClose) { base::UserActionTester user_action_tester; - std::unique_ptr<views::Widget> widget = - CreateWindowWidget(gfx::Rect(400, 400)); + std::unique_ptr<views::Widget> widget(CreateTestWidget( + nullptr, kShellWindowId_DefaultContainer, gfx::Rect(400, 400))); ToggleOverview(); - aura::Window* window = widget->GetNativeWindow(); - gfx::Rect bounds = GetTransformedBoundsInRootWindow(window); - gfx::Point point(bounds.right() - 5, bounds.y() + 5); - ui::test::EventGenerator event_generator(window->GetRootWindow(), point); - + const gfx::Point point = GetCloseButton(GetWindowItemForWindow(0, window)) + ->GetBoundsInScreen() + .CenterPoint(); ASSERT_FALSE(widget->IsClosed()); - event_generator.ClickLeftButton(); + GetEventGenerator()->set_current_screen_location(point); + GetEventGenerator()->ClickLeftButton(); ASSERT_TRUE(widget->IsClosed()); EXPECT_EQ( 0, user_action_tester.GetActionCount(kActiveWindowChangedFromOverview)); @@ -624,73 +563,68 @@ // is tapped while a finger is already down over a window. TEST_F(WindowSelectorTest, NoCrashWithDesktopTap) { std::unique_ptr<aura::Window> window( - CreateWindow(gfx::Rect(200, 300, 250, 450))); + CreateTestWindow(gfx::Rect(200, 300, 250, 450))); ToggleOverview(); - gfx::Rect bounds = GetTransformedBoundsInRootWindow(window.get()); - ui::test::EventGenerator event_generator(window->GetRootWindow(), - bounds.CenterPoint()); + const gfx::Rect bounds = GetTransformedBoundsInRootWindow(window.get()); + GetEventGenerator()->set_current_screen_location(bounds.CenterPoint()); // Press down on the window. const int kTouchId = 19; - event_generator.PressTouchId(kTouchId); + GetEventGenerator()->PressTouchId(kTouchId); // Tap on the desktop, which should not cause a crash. Overview mode should // be disengaged. - event_generator.GestureTapAt(gfx::Point(0, 0)); + GetEventGenerator()->GestureTapAt(gfx::Point(0, 0)); EXPECT_FALSE(IsSelecting()); - event_generator.ReleaseTouchId(kTouchId); + GetEventGenerator()->ReleaseTouchId(kTouchId); } // Tests that we do not crash and a window is selected when appropriate when // we click on a window during touch. TEST_F(WindowSelectorTest, ClickOnWindowDuringTouch) { - const gfx::Rect bounds(400, 400); - std::unique_ptr<aura::Window> window1(CreateWindow(bounds)); - std::unique_ptr<aura::Window> window2(CreateWindow(bounds)); - wm::ActivateWindow(window2.get()); + std::unique_ptr<aura::Window> window1(CreateTestWindow()); + std::unique_ptr<aura::Window> window2(CreateTestWindow()); + ::wm::ActivateWindow(window2.get()); EXPECT_FALSE(wm::IsActiveWindow(window1.get())); EXPECT_TRUE(wm::IsActiveWindow(window2.get())); ToggleOverview(); gfx::Rect window1_bounds = GetTransformedBoundsInRootWindow(window1.get()); - ui::test::EventGenerator event_generator(window1->GetRootWindow(), - window1_bounds.CenterPoint()); + GetEventGenerator()->set_current_screen_location( + window1_bounds.CenterPoint()); // Clicking on |window2| while touching on |window1| should not cause a // crash, it should do nothing since overview only handles one click or touch // at a time. const int kTouchId = 19; - event_generator.PressTouchId(kTouchId); - event_generator.MoveMouseToCenterOf(window2.get()); - event_generator.ClickLeftButton(); + GetEventGenerator()->PressTouchId(kTouchId); + GetEventGenerator()->MoveMouseToCenterOf(window2.get()); + GetEventGenerator()->ClickLeftButton(); EXPECT_TRUE(IsSelecting()); EXPECT_FALSE(wm::IsActiveWindow(window2.get())); // Clicking on |window1| while touching on |window1| should not cause // a crash, overview mode should be disengaged, and |window1| should // be active. - event_generator.MoveMouseToCenterOf(window1.get()); - event_generator.ClickLeftButton(); + GetEventGenerator()->MoveMouseToCenterOf(window1.get()); + GetEventGenerator()->ClickLeftButton(); EXPECT_FALSE(IsSelecting()); EXPECT_TRUE(wm::IsActiveWindow(window1.get())); - event_generator.ReleaseTouchId(kTouchId); + GetEventGenerator()->ReleaseTouchId(kTouchId); } // Tests that a window does not receive located events when in overview mode. TEST_F(WindowSelectorTest, WindowDoesNotReceiveEvents) { - gfx::Rect window_bounds(20, 10, 200, 300); - aura::Window* root_window = Shell::GetPrimaryRootWindow(); - std::unique_ptr<aura::Window> window(CreateWindow(window_bounds)); - - gfx::Point point1(window_bounds.x() + 10, window_bounds.y() + 10); - + std::unique_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(400, 400))); + const gfx::Point point1 = window->bounds().CenterPoint(); ui::MouseEvent event1(ui::ET_MOUSE_PRESSED, point1, point1, ui::EventTimeForNow(), ui::EF_NONE, ui::EF_NONE); + aura::Window* root_window = Shell::GetPrimaryRootWindow(); ui::EventTarget* root_target = root_window; ui::EventTargeter* targeter = root_window->GetHost()->dispatcher()->GetDefaultEventTargeter(); @@ -702,8 +636,8 @@ ToggleOverview(); // The bounds have changed, take that into account. - gfx::Rect bounds = GetTransformedBoundsInRootWindow(window.get()); - gfx::Point point2(bounds.x() + 10, bounds.y() + 10); + const gfx::Point point2 = + GetTransformedBoundsInRootWindow(window.get()).CenterPoint(); ui::MouseEvent event2(ui::ET_MOUSE_PRESSED, point2, point2, ui::EventTimeForNow(), ui::EF_NONE, ui::EF_NONE); @@ -713,37 +647,34 @@ // Tests that clicking on the close button effectively closes the window. TEST_F(WindowSelectorTest, CloseButton) { - std::unique_ptr<views::Widget> widget = - CreateWindowWidget(gfx::Rect(0, 0, 400, 400)); - - std::unique_ptr<views::Widget> minimized_widget = - CreateWindowWidget(gfx::Rect(400, 0, 400, 400)); + std::unique_ptr<views::Widget> widget(CreateTestWidget()); + std::unique_ptr<views::Widget> minimized_widget(CreateTestWidget()); minimized_widget->Minimize(); ToggleOverview(); - aura::Window* window = widget->GetNativeWindow(); - gfx::Rect bounds = GetTransformedBoundsInRootWindow(window); - gfx::Point point(bounds.right() - 5, bounds.y() + 5); - ui::test::EventGenerator event_generator(window->GetRootWindow(), point); + const gfx::Point point = GetCloseButton(GetWindowItemForWindow(0, window)) + ->GetBoundsInScreen() + .CenterPoint(); + GetEventGenerator()->set_current_screen_location(point); EXPECT_FALSE(widget->IsClosed()); - event_generator.ClickLeftButton(); + GetEventGenerator()->ClickLeftButton(); EXPECT_TRUE(widget->IsClosed()); - - EXPECT_TRUE(IsSelecting()); + ASSERT_TRUE(IsSelecting()); aura::Window* window_for_minimized_window = GetOverviewWindowForMinimizedState(0, minimized_widget->GetNativeWindow()); ASSERT_TRUE(window_for_minimized_window); - const gfx::Rect rect = - GetTransformedBoundsInRootWindow(window_for_minimized_window); - - event_generator.MoveMouseTo(gfx::Point(rect.right() - 10, rect.y() - 10)); - + const gfx::Point point2 = + GetCloseButton(GetWindowItemForWindow(0, window_for_minimized_window)) + ->GetBoundsInScreen() + .CenterPoint(); + GetEventGenerator()->MoveMouseTo(point2); EXPECT_FALSE(minimized_widget->IsClosed()); - event_generator.ClickLeftButton(); + + GetEventGenerator()->ClickLeftButton(); EXPECT_TRUE(minimized_widget->IsClosed()); // All minimized windows are closed, so it should exit overview mode. @@ -753,22 +684,19 @@ // Tests minimizing/unminimizing in overview mode. TEST_F(WindowSelectorTest, MinimizeUnminimize) { - std::unique_ptr<views::Widget> widget = - CreateWindowWidget(gfx::Rect(400, 400)); + std::unique_ptr<views::Widget> widget(CreateTestWidget()); aura::Window* window = widget->GetNativeWindow(); ToggleOverview(); - EXPECT_FALSE(GetOverviewWindowForMinimizedState(0, window)); + widget->Minimize(); EXPECT_TRUE(widget->IsMinimized()); EXPECT_TRUE(IsSelecting()); - EXPECT_TRUE(GetOverviewWindowForMinimizedState(0, window)); widget->Restore(); EXPECT_FALSE(widget->IsMinimized()); - EXPECT_FALSE(GetOverviewWindowForMinimizedState(0, window)); EXPECT_TRUE(IsSelecting()); } @@ -777,30 +705,20 @@ // closes the window. TEST_F(WindowSelectorTest, CloseButtonOnMultipleDisplay) { UpdateDisplay("600x400,600x400"); - aura::Window::Windows root_windows = Shell::GetAllRootWindows(); - - std::unique_ptr<aura::Window> window1( - CreateWindow(gfx::Rect(650, 300, 250, 450))); // We need a widget for the close button to work because windows are closed // via the widget. We also use the widget to determine if the window has been - // closed or not. We explicity create the widget so that the window can be - // parented to a non-primary root window. - std::unique_ptr<views::Widget> widget(new views::Widget); - views::Widget::InitParams params; - params.bounds = gfx::Rect(650, 0, 400, 400); - params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; - params.parent = window1->parent(); - widget->Init(params); - widget->Show(); - aura::Window* window = widget->GetNativeWindow(); - window->SetProperty(aura::client::kTopViewInset, kHeaderHeightDp); - - ASSERT_EQ(root_windows[1], window1->GetRootWindow()); + // closed or not. Parent the window to a window in a non-primary root window. + std::unique_ptr<aura::Window> window( + CreateTestWindow(gfx::Rect(650, 300, 250, 450))); + std::unique_ptr<views::Widget> widget(CreateTestWidget()); + widget->SetBounds(gfx::Rect(650, 0, 400, 400)); + aura::Window* window2 = widget->GetNativeWindow(); + window2->SetProperty(aura::client::kTopViewInset, kHeaderHeightDp); + views::Widget::ReparentNativeView(window2, window->parent()); + ASSERT_EQ(Shell::GetAllRootWindows()[1], window2->GetRootWindow()); ToggleOverview(); - - aura::Window* window2 = widget->GetNativeWindow(); gfx::Rect bounds = GetTransformedBoundsInRootWindow(window2); gfx::Point point(bounds.right() - 5, bounds.y() + 5); ui::test::EventGenerator event_generator(window2->GetRootWindow(), point); @@ -812,10 +730,9 @@ // Tests entering overview mode with two windows and selecting one. TEST_F(WindowSelectorTest, FullscreenWindow) { - const gfx::Rect bounds(400, 400); - std::unique_ptr<aura::Window> window1(CreateWindow(bounds)); - std::unique_ptr<aura::Window> window2(CreateWindow(bounds)); - wm::ActivateWindow(window1.get()); + std::unique_ptr<aura::Window> window1(CreateTestWindow()); + std::unique_ptr<aura::Window> window2(CreateTestWindow()); + ::wm::ActivateWindow(window1.get()); const wm::WMEvent toggle_fullscreen_event(wm::WM_EVENT_TOGGLE_FULLSCREEN); wm::GetWindowState(window1.get())->OnWMEvent(&toggle_fullscreen_event); @@ -823,8 +740,7 @@ // Enter overview and select the fullscreen window. ToggleOverview(); - - // The window is still fullscreen as it was selected. + ClickWindow(window1.get()); EXPECT_TRUE(wm::GetWindowState(window1.get())->IsFullscreen()); // Entering overview and selecting another window, the previous window remains @@ -834,37 +750,18 @@ EXPECT_TRUE(wm::GetWindowState(window1.get())->IsFullscreen()); } -TEST_F(WindowSelectorTest, SkipOverviewWindow) { - const gfx::Rect bounds(400, 400); - std::unique_ptr<aura::Window> window1(CreateWindow(bounds)); - std::unique_ptr<aura::Window> window2(CreateWindow(bounds)); - - window2->SetProperty(ash::kHideInOverviewKey, true); - - // Enter overview. - ToggleOverview(); - EXPECT_TRUE(window1->IsVisible()); - EXPECT_FALSE(window2->IsVisible()); - - // Exit overview. - ToggleOverview(); - base::RunLoop().RunUntilIdle(); - - EXPECT_TRUE(window1->IsVisible()); - EXPECT_TRUE(window2->IsVisible()); -} - // Tests that entering overview when a fullscreen window is active in maximized // mode correctly applies the transformations to the window and correctly // updates the window bounds on exiting overview mode: http://crbug.com/401664. TEST_F(WindowSelectorTest, FullscreenWindowTabletMode) { UpdateDisplay("800x600"); const gfx::Rect bounds(400, 400); - std::unique_ptr<aura::Window> window1(CreateWindow(bounds)); - std::unique_ptr<aura::Window> window2(CreateWindow(bounds)); - Shell::Get()->tablet_mode_controller()->EnableTabletModeWindowManager(true); - wm::ActivateWindow(window2.get()); - wm::ActivateWindow(window1.get()); + std::unique_ptr<aura::Window> window1(CreateTestWindow(bounds)); + std::unique_ptr<aura::Window> window2(CreateTestWindow(bounds)); + ::wm::ActivateWindow(window2.get()); + ::wm::ActivateWindow(window1.get()); + + EnterTabletMode(); gfx::Rect normal_window_bounds(window1->bounds()); const wm::WMEvent toggle_fullscreen_event(wm::WM_EVENT_TOGGLE_FULLSCREEN); wm::GetWindowState(window1.get())->OnWMEvent(&toggle_fullscreen_event); @@ -913,28 +810,28 @@ screen->GetDisplayNearestWindow(window1.get()).work_area()); } -// Tests that beginning window selection hides the app list. -TEST_F(WindowSelectorTest, SelectingHidesAppList) { - const gfx::Rect bounds(400, 400); - std::unique_ptr<aura::Window> window1(CreateWindow(bounds)); - std::unique_ptr<aura::Window> window2(CreateWindow(bounds)); +TEST_F(WindowSelectorTest, SkipOverviewWindow) { + std::unique_ptr<aura::Window> window1(CreateTestWindow()); + std::unique_ptr<aura::Window> window2(CreateTestWindow()); + window2->SetProperty(ash::kHideInOverviewKey, true); - GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplay().id()); - GetAppListTestHelper()->CheckVisibility(true); + // Enter overview. + ToggleOverview(); + EXPECT_TRUE(window1->IsVisible()); + EXPECT_FALSE(window2->IsVisible()); + // Exit overview. ToggleOverview(); - GetAppListTestHelper()->WaitUntilIdle(); - GetAppListTestHelper()->CheckVisibility(false); - ToggleOverview(); + base::RunLoop().RunUntilIdle(); + EXPECT_TRUE(window1->IsVisible()); + EXPECT_TRUE(window2->IsVisible()); } // Tests that a minimized window's visibility and layer visibility // stay invisible (A minimized window is cloned during overview). TEST_F(WindowSelectorTest, MinimizedWindowState) { - const gfx::Rect bounds(400, 400); - std::unique_ptr<aura::Window> window1(CreateWindow(bounds)); - wm::WindowState* window_state = wm::GetWindowState(window1.get()); - window_state->Minimize(); + std::unique_ptr<aura::Window> window1(CreateTestWindow()); + wm::GetWindowState(window1.get())->Minimize(); EXPECT_FALSE(window1->IsVisible()); EXPECT_FALSE(window1->layer()->GetTargetVisibility()); @@ -949,38 +846,33 @@ // Tests that a bounds change during overview is corrected for. TEST_F(WindowSelectorTest, BoundsChangeDuringOverview) { - std::unique_ptr<aura::Window> window(CreateWindow(gfx::Rect(0, 0, 400, 400))); + std::unique_ptr<aura::Window> window( + CreateTestWindowInShellWithDelegate(nullptr, -1, gfx::Rect(400, 400))); // Use overview headers above the window in this test. window->SetProperty(aura::client::kTopViewInset, 0); ToggleOverview(); gfx::Rect overview_bounds = GetTransformedTargetBounds(window.get()); window->SetBounds(gfx::Rect(200, 0, 200, 200)); gfx::Rect new_overview_bounds = GetTransformedTargetBounds(window.get()); - EXPECT_EQ(overview_bounds.x(), new_overview_bounds.x()); - EXPECT_EQ(overview_bounds.y(), new_overview_bounds.y()); - EXPECT_EQ(overview_bounds.width(), new_overview_bounds.width()); - EXPECT_EQ(overview_bounds.height(), new_overview_bounds.height()); + EXPECT_EQ(overview_bounds, new_overview_bounds); ToggleOverview(); } // Tests that a newly created window aborts overview. TEST_F(WindowSelectorTest, NewWindowCancelsOverview) { - const gfx::Rect bounds(400, 400); - std::unique_ptr<aura::Window> window1(CreateWindow(bounds)); - std::unique_ptr<aura::Window> window2(CreateWindow(bounds)); + std::unique_ptr<aura::Window> window1(CreateTestWindow()); ToggleOverview(); EXPECT_TRUE(IsSelecting()); // A window being created should exit overview mode. - std::unique_ptr<aura::Window> window3(CreateWindow(bounds)); + std::unique_ptr<aura::Window> window2(CreateTestWindow()); EXPECT_FALSE(IsSelecting()); } // Tests that a window activation exits overview mode. TEST_F(WindowSelectorTest, ActivationCancelsOverview) { - const gfx::Rect bounds(400, 400); - std::unique_ptr<aura::Window> window1(CreateWindow(bounds)); - std::unique_ptr<aura::Window> window2(CreateWindow(bounds)); + std::unique_ptr<aura::Window> window1(CreateTestWindow()); + std::unique_ptr<aura::Window> window2(CreateTestWindow()); window2->Focus(); ToggleOverview(); EXPECT_TRUE(IsSelecting()); @@ -997,9 +889,8 @@ // Tests that exiting overview mode without selecting a window restores focus // to the previously focused window. TEST_F(WindowSelectorTest, CancelRestoresFocus) { - const gfx::Rect bounds(400, 400); - std::unique_ptr<aura::Window> window(CreateWindow(bounds)); - wm::ActivateWindow(window.get()); + std::unique_ptr<aura::Window> window(CreateTestWindow()); + ::wm::ActivateWindow(window.get()); EXPECT_EQ(window.get(), wm::GetFocusedWindow()); // In overview mode, the overview focus window should be focused. @@ -1014,9 +905,8 @@ // Tests that overview mode is exited if the last remaining window is destroyed. TEST_F(WindowSelectorTest, LastWindowDestroyed) { - const gfx::Rect bounds(400, 400); - std::unique_ptr<aura::Window> window1(CreateWindow(bounds)); - std::unique_ptr<aura::Window> window2(CreateWindow(bounds)); + std::unique_ptr<aura::Window> window1(CreateTestWindow()); + std::unique_ptr<aura::Window> window2(CreateTestWindow()); ToggleOverview(); window1.reset(); @@ -1024,11 +914,33 @@ EXPECT_FALSE(IsSelecting()); } +// Regression test for crash when closing the last overview mode window under +// SingleProcessMash. https://crbug.com/922293. +TEST_F(WindowSelectorTest, DontRestoreFocusToUnparentedWindow) { + const gfx::Rect bounds(400, 400); + std::unique_ptr<aura::Window> parent = CreateTestWindow(bounds); + std::unique_ptr<aura::Window> child = CreateChildWindow(parent.get(), bounds); + + // Enter overview with a focused child window. This simulates an app window + // web contents RenderWidgetHostViewAura. + child->Focus(); + ToggleOverview(); + + // Simulate the asynchronous window teardown for used by client widgets. + // Hierarchy changes are processed first, so the child is removed from its + // parent, then the windows are destroyed. + parent->RemoveChild(child.get()); + parent.reset(); + child.reset(); + + // Overview mode exits without crashing. + EXPECT_FALSE(IsSelecting()); +} + // Tests that entering overview mode restores a window to its original // target location. TEST_F(WindowSelectorTest, QuickReentryRestoresInitialTransform) { - const gfx::Rect bounds(400, 400); - std::unique_ptr<aura::Window> window(CreateWindow(bounds)); + std::unique_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(400, 400))); gfx::Rect initial_bounds = GetTransformedBounds(window.get()); ToggleOverview(); // Quickly exit and reenter overview mode. The window should still be @@ -1050,39 +962,38 @@ // child even though not activatable themselves. TEST_F(WindowSelectorTest, ModalChild) { const gfx::Rect bounds(400, 400); - std::unique_ptr<aura::Window> window1(CreateWindow(bounds)); - std::unique_ptr<aura::Window> child1(CreateWindow(bounds)); - child1->SetProperty(aura::client::kModalKey, ui::MODAL_TYPE_WINDOW); - ::wm::AddTransientChild(window1.get(), child1.get()); - EXPECT_EQ(window1->parent(), child1->parent()); + std::unique_ptr<aura::Window> window(CreateTestWindow(bounds)); + std::unique_ptr<aura::Window> child(CreateTestWindow(bounds)); + child->SetProperty(aura::client::kModalKey, ui::MODAL_TYPE_WINDOW); + ::wm::AddTransientChild(window.get(), child.get()); + EXPECT_EQ(window->parent(), child->parent()); ToggleOverview(); - EXPECT_TRUE(window1->IsVisible()); - EXPECT_TRUE(child1->IsVisible()); - EXPECT_EQ(GetTransformedTargetBounds(child1.get()), - GetTransformedTargetBounds(window1.get())); + EXPECT_TRUE(window->IsVisible()); + EXPECT_TRUE(child->IsVisible()); + EXPECT_EQ(GetTransformedTargetBounds(child.get()), + GetTransformedTargetBounds(window.get())); ToggleOverview(); } // Tests that clicking a modal window's parent activates the modal window in // overview. TEST_F(WindowSelectorTest, ClickModalWindowParent) { - std::unique_ptr<aura::Window> window1( - CreateWindow(gfx::Rect(0, 0, 180, 180))); - std::unique_ptr<aura::Window> child1( - CreateWindow(gfx::Rect(200, 0, 180, 180))); - child1->SetProperty(aura::client::kModalKey, ui::MODAL_TYPE_WINDOW); - ::wm::AddTransientChild(window1.get(), child1.get()); - EXPECT_FALSE(WindowsOverlapping(window1.get(), child1.get())); - EXPECT_EQ(window1->parent(), child1->parent()); + std::unique_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(180, 180))); + std::unique_ptr<aura::Window> child( + CreateTestWindow(gfx::Rect(200, 0, 180, 180))); + child->SetProperty(aura::client::kModalKey, ui::MODAL_TYPE_WINDOW); + ::wm::AddTransientChild(window.get(), child.get()); + EXPECT_FALSE(WindowsOverlapping(window.get(), child.get())); + EXPECT_EQ(window->parent(), child->parent()); ToggleOverview(); // Given that their relative positions are preserved, the windows should still // not overlap. - EXPECT_FALSE(WindowsOverlapping(window1.get(), child1.get())); - ClickWindow(window1.get()); + EXPECT_FALSE(WindowsOverlapping(window.get(), child.get())); + ClickWindow(window.get()); EXPECT_FALSE(IsSelecting()); // Clicking on window1 should activate child1. - EXPECT_TRUE(wm::IsActiveWindow(child1.get())); + EXPECT_TRUE(wm::IsActiveWindow(child.get())); } // Tests that windows remain on the display they are currently on in overview @@ -1093,10 +1004,10 @@ gfx::Rect bounds1(0, 0, 400, 400); gfx::Rect bounds2(650, 0, 400, 400); - std::unique_ptr<aura::Window> window1(CreateWindow(bounds1)); - std::unique_ptr<aura::Window> window2(CreateWindow(bounds1)); - std::unique_ptr<aura::Window> window3(CreateWindow(bounds2)); - std::unique_ptr<aura::Window> window4(CreateWindow(bounds2)); + std::unique_ptr<aura::Window> window1(CreateTestWindow(bounds1)); + std::unique_ptr<aura::Window> window2(CreateTestWindow(bounds1)); + std::unique_ptr<aura::Window> window3(CreateTestWindow(bounds2)); + std::unique_ptr<aura::Window> window4(CreateTestWindow(bounds2)); EXPECT_EQ(root_windows[0], window1->GetRootWindow()); EXPECT_EQ(root_windows[0], window2->GetRootWindow()); EXPECT_EQ(root_windows[1], window3->GetRootWindow()); @@ -1110,26 +1021,25 @@ EXPECT_EQ(root_windows[1], window4->GetRootWindow()); // Window indices are based on top-down order. The reverse of our creation. - IsWindowAndCloseButtonInScreen(window1.get(), - GetWindowItemForWindow(0, window1.get())); - IsWindowAndCloseButtonInScreen(window2.get(), - GetWindowItemForWindow(0, window2.get())); - IsWindowAndCloseButtonInScreen(window3.get(), - GetWindowItemForWindow(1, window3.get())); - IsWindowAndCloseButtonInScreen(window4.get(), - GetWindowItemForWindow(1, window4.get())); + CheckWindowAndCloseButtonInScreen(window1.get(), + GetWindowItemForWindow(0, window1.get())); + CheckWindowAndCloseButtonInScreen(window2.get(), + GetWindowItemForWindow(0, window2.get())); + CheckWindowAndCloseButtonInScreen(window3.get(), + GetWindowItemForWindow(1, window3.get())); + CheckWindowAndCloseButtonInScreen(window4.get(), + GetWindowItemForWindow(1, window4.get())); } // Tests shutting down during overview. TEST_F(WindowSelectorTest, Shutdown) { - const gfx::Rect bounds(400, 400); // These windows will be deleted when the test exits and the Shell instance // is shut down. - std::unique_ptr<aura::Window> window1(CreateWindow(bounds)); - std::unique_ptr<aura::Window> window2(CreateWindow(bounds)); + std::unique_ptr<aura::Window> window1(CreateTestWindow()); + std::unique_ptr<aura::Window> window2(CreateTestWindow()); - wm::ActivateWindow(window2.get()); - wm::ActivateWindow(window1.get()); + ::wm::ActivateWindow(window2.get()); + ::wm::ActivateWindow(window1.get()); ToggleOverview(); } @@ -1137,17 +1047,16 @@ // Tests removing a display during overview. TEST_F(WindowSelectorTest, RemoveDisplay) { UpdateDisplay("400x400,400x400"); - gfx::Rect bounds1(0, 0, 100, 100); - gfx::Rect bounds2(450, 0, 100, 100); - std::unique_ptr<aura::Window> window1(CreateWindow(bounds1)); - std::unique_ptr<aura::Window> window2(CreateWindow(bounds2)); + std::unique_ptr<aura::Window> window1(CreateTestWindow(gfx::Rect(100, 100))); + std::unique_ptr<aura::Window> window2( + CreateTestWindow(gfx::Rect(450, 0, 100, 100))); aura::Window::Windows root_windows = Shell::GetAllRootWindows(); EXPECT_EQ(root_windows[0], window1->GetRootWindow()); EXPECT_EQ(root_windows[1], window2->GetRootWindow()); - wm::ActivateWindow(window2.get()); - wm::ActivateWindow(window1.get()); + ::wm::ActivateWindow(window2.get()); + ::wm::ActivateWindow(window1.get()); ToggleOverview(); EXPECT_TRUE(IsSelecting()); @@ -1158,17 +1067,16 @@ // Tests removing a display during overview with NON_ZERO_DURATION animation. TEST_F(WindowSelectorTest, RemoveDisplayWithAnimation) { UpdateDisplay("400x400,400x400"); - gfx::Rect bounds1(0, 0, 100, 100); - gfx::Rect bounds2(450, 0, 100, 100); - std::unique_ptr<aura::Window> window1(CreateWindow(bounds1)); - std::unique_ptr<aura::Window> window2(CreateWindow(bounds2)); + std::unique_ptr<aura::Window> window1(CreateTestWindow(gfx::Rect(100, 100))); + std::unique_ptr<aura::Window> window2( + CreateTestWindow(gfx::Rect(450, 0, 100, 100))); aura::Window::Windows root_windows = Shell::GetAllRootWindows(); EXPECT_EQ(root_windows[0], window1->GetRootWindow()); EXPECT_EQ(root_windows[1], window2->GetRootWindow()); - wm::ActivateWindow(window2.get()); - wm::ActivateWindow(window1.get()); + ::wm::ActivateWindow(window2.get()); + ::wm::ActivateWindow(window1.get()); ToggleOverview(); EXPECT_TRUE(IsSelecting()); @@ -1179,35 +1087,52 @@ EXPECT_FALSE(IsSelecting()); } +namespace { + +// A simple window delegate that returns the specified hit-test code when +// requested and applies a minimum size constraint if there is one. +class TestDragWindowDelegate : public aura::test::TestWindowDelegate { + public: + TestDragWindowDelegate() { set_window_component(HTCAPTION); } + ~TestDragWindowDelegate() override = default; + + private: + // aura::Test::TestWindowDelegate: + void OnWindowDestroyed(aura::Window* window) override { delete this; } + + DISALLOW_COPY_AND_ASSIGN(TestDragWindowDelegate); +}; + +} // namespace + // Tests that toggling overview on and off does not cancel drag. TEST_F(WindowSelectorTest, DragDropInProgress) { - gfx::Rect bounds(0, 0, 100, 100); std::unique_ptr<aura::Window> window(CreateTestWindowInShellWithDelegate( - new TestDragWindowDelegate(), -1, bounds)); + new TestDragWindowDelegate(), -1, gfx::Rect(100, 100))); - ui::test::EventGenerator event_generator(window->GetRootWindow(), - window.get()); - event_generator.PressLeftButton(); - event_generator.MoveMouseBy(10, 10); + GetEventGenerator()->set_current_screen_location( + window->GetBoundsInScreen().CenterPoint()); + GetEventGenerator()->PressLeftButton(); + GetEventGenerator()->MoveMouseBy(10, 10); EXPECT_EQ(gfx::Rect(10, 10, 100, 100), window->bounds()); ToggleOverview(); ASSERT_TRUE(IsSelecting()); - event_generator.MoveMouseBy(10, 10); + GetEventGenerator()->MoveMouseBy(10, 10); ToggleOverview(); ASSERT_FALSE(IsSelecting()); - event_generator.MoveMouseBy(10, 10); - event_generator.ReleaseLeftButton(); + GetEventGenerator()->MoveMouseBy(10, 10); + GetEventGenerator()->ReleaseLeftButton(); base::RunLoop().RunUntilIdle(); EXPECT_EQ(gfx::Rect(30, 30, 100, 100), window->bounds()); } // Test that a label is created under the window on entering overview mode. TEST_F(WindowSelectorTest, CreateLabelUnderWindow) { - std::unique_ptr<aura::Window> window(CreateWindow(gfx::Rect(0, 0, 300, 500))); + std::unique_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(300, 500))); const base::string16 window_title = base::UTF8ToUTF16("My window"); window->SetTitle(window_title); ToggleOverview(); @@ -1235,11 +1160,12 @@ TEST_F(WindowSelectorTest, DisplayOrientationChanged) { aura::Window* root_window = Shell::Get()->GetPrimaryRootWindow(); UpdateDisplay("600x200"); - EXPECT_EQ("0,0 600x200", root_window->bounds().ToString()); - gfx::Rect window_bounds(0, 0, 150, 150); + EXPECT_EQ(gfx::Rect(600, 200), root_window->bounds()); std::vector<std::unique_ptr<aura::Window>> windows; - for (int i = 0; i < 3; i++) - windows.push_back(base::WrapUnique(CreateWindow(window_bounds))); + for (int i = 0; i < 3; i++) { + windows.push_back( + std::unique_ptr<aura::Window>(CreateTestWindow(gfx::Rect(150, 150)))); + } ToggleOverview(); for (const auto& window : windows) { @@ -1250,7 +1176,7 @@ // Rotate the display, windows should be repositioned to be within the screen // bounds. UpdateDisplay("600x200/r"); - EXPECT_EQ("0,0 200x600", root_window->bounds().ToString()); + EXPECT_EQ(gfx::Rect(200, 600), root_window->bounds()); for (const auto& window : windows) { EXPECT_TRUE(root_window->bounds().Contains( GetTransformedTargetBounds(window.get()))); @@ -1259,9 +1185,8 @@ // Tests traversing some windows in overview mode with the tab key. TEST_F(WindowSelectorTest, BasicTabKeyNavigation) { - gfx::Rect bounds(0, 0, 100, 100); - std::unique_ptr<aura::Window> window2(CreateWindow(bounds)); - std::unique_ptr<aura::Window> window1(CreateWindow(bounds)); + std::unique_ptr<aura::Window> window2(CreateTestWindow()); + std::unique_ptr<aura::Window> window1(CreateTestWindow()); ToggleOverview(); const std::vector<std::unique_ptr<WindowSelectorItem>>& overview_windows = @@ -1276,15 +1201,11 @@ // Tests that pressing Ctrl+W while a window is selected in overview closes it. TEST_F(WindowSelectorTest, CloseWindowWithKey) { - gfx::Rect bounds(0, 0, 100, 100); - std::unique_ptr<aura::Window> window2(CreateWindow(bounds)); - std::unique_ptr<views::Widget> widget = - CreateWindowWidget(gfx::Rect(0, 0, 400, 400)); - aura::Window* window1 = widget->GetNativeWindow(); + std::unique_ptr<views::Widget> widget(CreateTestWidget()); ToggleOverview(); SendKey(ui::VKEY_RIGHT); - EXPECT_EQ(window1, GetSelectedWindow()); + EXPECT_EQ(widget->GetNativeWindow(), GetSelectedWindow()); SendKey(ui::VKEY_W, ui::EF_CONTROL_DOWN); EXPECT_TRUE(widget->IsClosed()); } @@ -1297,7 +1218,7 @@ std::vector<std::unique_ptr<aura::Window>> windows; for (size_t i = test_windows; i > 0; i--) { windows.push_back( - base::WrapUnique(CreateWindowWithId(gfx::Rect(0, 0, 100, 100), i))); + std::unique_ptr<aura::Window>(CreateTestWindowInShellWithId(i))); } ui::KeyboardCode arrow_keys[] = {ui::VKEY_RIGHT, ui::VKEY_DOWN, ui::VKEY_LEFT, @@ -1327,7 +1248,7 @@ } } -// Verifies hitting the escape and back keys exit overview mode. +// Tests hitting the escape and back keys exit overview mode. TEST_F(WindowSelectorTest, ExitOverviewWithKey) { std::unique_ptr<aura::Window> window1(CreateTestWindow()); std::unique_ptr<aura::Window> window2(CreateTestWindow()); @@ -1362,12 +1283,12 @@ // Tests basic selection across multiple monitors. TEST_F(WindowSelectorTest, BasicMultiMonitorArrowKeyNavigation) { UpdateDisplay("400x400,400x400"); - gfx::Rect bounds1(0, 0, 100, 100); - gfx::Rect bounds2(450, 0, 100, 100); - std::unique_ptr<aura::Window> window4(CreateWindow(bounds2)); - std::unique_ptr<aura::Window> window3(CreateWindow(bounds2)); - std::unique_ptr<aura::Window> window2(CreateWindow(bounds1)); - std::unique_ptr<aura::Window> window1(CreateWindow(bounds1)); + const gfx::Rect bounds1(100, 100); + const gfx::Rect bounds2(450, 0, 100, 100); + std::unique_ptr<aura::Window> window4(CreateTestWindow(bounds2)); + std::unique_ptr<aura::Window> window3(CreateTestWindow(bounds2)); + std::unique_ptr<aura::Window> window2(CreateTestWindow(bounds1)); + std::unique_ptr<aura::Window> window1(CreateTestWindow(bounds1)); ToggleOverview(); @@ -1393,10 +1314,9 @@ display::test::CreateDisplayLayout(display_manager(), display::DisplayPlacement::LEFT, 0)); aura::Window::Windows root_windows = Shell::GetAllRootWindows(); - gfx::Rect bounds1(-350, 0, 100, 100); - gfx::Rect bounds2(0, 0, 100, 100); - std::unique_ptr<aura::Window> window2(CreateWindow(bounds2)); - std::unique_ptr<aura::Window> window1(CreateWindow(bounds1)); + std::unique_ptr<aura::Window> window2(CreateTestWindow(gfx::Rect(100, 100))); + std::unique_ptr<aura::Window> window1( + CreateTestWindow(gfx::Rect(-350, 0, 100, 100))); EXPECT_EQ(root_windows[1], window1->GetRootWindow()); EXPECT_EQ(root_windows[0], window2->GetRootWindow()); @@ -1407,6 +1327,7 @@ SendKey(ui::VKEY_RIGHT); EXPECT_EQ(GetSelectedWindow(), window1.get()); + // Exit and reenter overview. ToggleOverview(); ToggleOverview(); @@ -1420,12 +1341,11 @@ TEST_F(WindowSelectorTest, ThreeMonitor) { UpdateDisplay("400x400,400x400,400x400"); aura::Window::Windows root_windows = Shell::GetAllRootWindows(); - const gfx::Rect bounds1(0, 0, 100, 100); - const gfx::Rect bounds2(400, 0, 100, 100); - const gfx::Rect bounds3(800, 0, 100, 100); - std::unique_ptr<aura::Window> window3(CreateWindow(bounds3)); - std::unique_ptr<aura::Window> window2(CreateWindow(bounds2)); - std::unique_ptr<aura::Window> window1(CreateWindow(bounds1)); + std::unique_ptr<aura::Window> window3( + CreateTestWindow(gfx::Rect(800, 0, 100, 100))); + std::unique_ptr<aura::Window> window2( + CreateTestWindow(gfx::Rect(400, 0, 100, 100))); + std::unique_ptr<aura::Window> window1(CreateTestWindow(gfx::Rect(100, 100))); EXPECT_EQ(root_windows[0], window1->GetRootWindow()); EXPECT_EQ(root_windows[1], window2->GetRootWindow()); EXPECT_EQ(root_windows[2], window3->GetRootWindow()); @@ -1443,7 +1363,7 @@ EXPECT_EQ(GetSelectedWindow(), window2.get()); ToggleOverview(); - window3.reset(CreateWindow(bounds3)); + window3 = CreateTestWindow(gfx::Rect(800, 0, 100, 100)); ToggleOverview(); SendKey(ui::VKEY_RIGHT); SendKey(ui::VKEY_RIGHT); @@ -1458,9 +1378,8 @@ // Tests selecting a window in overview mode with the return key. TEST_F(WindowSelectorTest, SelectWindowWithReturnKey) { - gfx::Rect bounds(0, 0, 100, 100); - std::unique_ptr<aura::Window> window2(CreateWindow(bounds)); - std::unique_ptr<aura::Window> window1(CreateWindow(bounds)); + std::unique_ptr<aura::Window> window2(CreateTestWindow()); + std::unique_ptr<aura::Window> window1(CreateTestWindow()); ToggleOverview(); // Pressing the return key without a selection widget should not do anything. @@ -1481,68 +1400,54 @@ EXPECT_TRUE(wm::IsActiveWindow(window2.get())); } -// Tests clicking on the desktop itself to cancel overview mode. TEST_F(WindowSelectorTest, CancelOverviewOnMouseClick) { - // Overview disabled by default. - EXPECT_FALSE(IsSelecting()); - // Point and bounds selected so that they don't intersect. This causes // events located at the point to be passed to WallpaperController, // and not the window. - gfx::Point point_in_background_page(0, 0); - gfx::Rect bounds(10, 10, 100, 100); - std::unique_ptr<aura::Window> window1(CreateWindow(bounds)); - ui::test::EventGenerator* generator = GetEventGenerator(); + const gfx::Point point_in_background_page(0, 0); + std::unique_ptr<aura::Window> window( + CreateTestWindow(gfx::Rect(10, 10, 100, 100))); // Move mouse to point in the background page. Sending an event here will pass // it to the WallpaperController in both regular and overview mode. - generator->MoveMouseTo(point_in_background_page); + GetEventGenerator()->MoveMouseTo(point_in_background_page); // Clicking on the background page while not in overview should not toggle // overview. - generator->ClickLeftButton(); + GetEventGenerator()->ClickLeftButton(); EXPECT_FALSE(IsSelecting()); - // Switch to overview mode. + // Switch to overview mode. Clicking should now exit overview mode. ToggleOverview(); ASSERT_TRUE(IsSelecting()); - - // Click should now exit overview mode. - generator->ClickLeftButton(); + GetEventGenerator()->ClickLeftButton(); EXPECT_FALSE(IsSelecting()); } // Tests tapping on the desktop itself to cancel overview mode. TEST_F(WindowSelectorTest, CancelOverviewOnTap) { - // Overview disabled by default. - EXPECT_FALSE(IsSelecting()); - // Point and bounds selected so that they don't intersect. This causes // events located at the point to be passed to WallpaperController, // and not the window. gfx::Point point_in_background_page(0, 0); - gfx::Rect bounds(10, 10, 100, 100); - std::unique_ptr<aura::Window> window1(CreateWindow(bounds)); - ui::test::EventGenerator* generator = GetEventGenerator(); + std::unique_ptr<aura::Window> window( + CreateTestWindow(gfx::Rect(10, 10, 100, 100))); // Tapping on the background page while not in overview should not toggle // overview. - generator->GestureTapAt(point_in_background_page); + GetEventGenerator()->GestureTapAt(point_in_background_page); EXPECT_FALSE(IsSelecting()); - // Switch to overview mode. + // Switch to overview mode. Tapping should now exit overview mode. ToggleOverview(); ASSERT_TRUE(IsSelecting()); - - // Tap should now exit overview mode. - generator->GestureTapAt(point_in_background_page); + GetEventGenerator()->GestureTapAt(point_in_background_page); EXPECT_FALSE(IsSelecting()); } // Start dragging a window and activate overview mode. This test should not // crash or DCHECK inside aura::Window::StackChildRelativeTo(). TEST_F(WindowSelectorTest, OverviewWhileDragging) { - const gfx::Rect bounds(10, 10, 100, 100); - std::unique_ptr<aura::Window> window(CreateWindow(bounds)); + std::unique_ptr<aura::Window> window(CreateTestWindow()); std::unique_ptr<WindowResizer> resizer(CreateWindowResizer( window.get(), gfx::Point(), HTCAPTION, ::wm::WINDOW_MOVE_SOURCE_MOUSE)); ASSERT_TRUE(resizer.get()); @@ -1639,9 +1544,8 @@ // Create two windows with widgets (widgets are needed to close the windows // later in the test), one each on the first two monitors. aura::Window::Windows root_windows = Shell::GetAllRootWindows(); - const gfx::Rect bounds(100, 100); - std::unique_ptr<views::Widget> widget1(CreateWindowWidget(bounds)); - std::unique_ptr<views::Widget> widget2(CreateWindowWidget(bounds)); + std::unique_ptr<views::Widget> widget1(CreateTestWidget()); + std::unique_ptr<views::Widget> widget2(CreateTestWidget()); aura::Window* window1 = widget1->GetNativeWindow(); aura::Window* window2 = widget2->GetNativeWindow(); ASSERT_TRUE(wm::MoveWindowToDisplay(window2, GetSecondaryDisplay().id())); @@ -1687,13 +1591,12 @@ // Tests window list animation states are correctly updated. TEST_F(WindowSelectorTest, SetWindowListAnimationStates) { - const gfx::Rect bounds(400, 400); - std::unique_ptr<aura::Window> window1(CreateWindow(bounds)); - std::unique_ptr<aura::Window> window2(CreateWindow(bounds)); - std::unique_ptr<aura::Window> window3(CreateWindow(bounds)); - wm::ActivateWindow(window3.get()); - wm::ActivateWindow(window2.get()); - wm::ActivateWindow(window1.get()); + std::unique_ptr<aura::Window> window1(CreateTestWindow()); + std::unique_ptr<aura::Window> window2(CreateTestWindow()); + std::unique_ptr<aura::Window> window3(CreateTestWindow()); + ::wm::ActivateWindow(window3.get()); + ::wm::ActivateWindow(window2.get()); + ::wm::ActivateWindow(window1.get()); EXPECT_FALSE(wm::GetWindowState(window1.get())->IsFullscreen()); EXPECT_FALSE(wm::GetWindowState(window2.get())->IsFullscreen()); @@ -1720,13 +1623,12 @@ // Tests window list animation states are correctly updated with selected // window. TEST_F(WindowSelectorTest, SetWindowListAnimationStatesWithSelectedWindow) { - const gfx::Rect bounds(400, 400); - std::unique_ptr<aura::Window> window1(CreateWindow(bounds)); - std::unique_ptr<aura::Window> window2(CreateWindow(bounds)); - std::unique_ptr<aura::Window> window3(CreateWindow(bounds)); - wm::ActivateWindow(window3.get()); - wm::ActivateWindow(window2.get()); - wm::ActivateWindow(window1.get()); + std::unique_ptr<aura::Window> window1(CreateTestWindow()); + std::unique_ptr<aura::Window> window2(CreateTestWindow()); + std::unique_ptr<aura::Window> window3(CreateTestWindow()); + ::wm::ActivateWindow(window3.get()); + ::wm::ActivateWindow(window2.get()); + ::wm::ActivateWindow(window1.get()); EXPECT_FALSE(wm::GetWindowState(window1.get())->IsFullscreen()); EXPECT_FALSE(wm::GetWindowState(window2.get())->IsFullscreen()); @@ -1759,13 +1661,12 @@ // Tests OverviewWindowAnimationObserver can handle deleted window. TEST_F(WindowSelectorTest, OverviewWindowAnimationObserverCanHandleDeletedWindow) { - const gfx::Rect bounds(400, 400); - std::unique_ptr<aura::Window> window1(CreateWindow(bounds)); - std::unique_ptr<aura::Window> window2(CreateWindow(bounds)); - std::unique_ptr<aura::Window> window3(CreateWindow(bounds)); - wm::ActivateWindow(window3.get()); - wm::ActivateWindow(window2.get()); - wm::ActivateWindow(window1.get()); + std::unique_ptr<aura::Window> window1(CreateTestWindow()); + std::unique_ptr<aura::Window> window2(CreateTestWindow()); + std::unique_ptr<aura::Window> window3(CreateTestWindow()); + ::wm::ActivateWindow(window3.get()); + ::wm::ActivateWindow(window2.get()); + ::wm::ActivateWindow(window1.get()); EXPECT_FALSE(wm::GetWindowState(window1.get())->IsFullscreen()); EXPECT_FALSE(wm::GetWindowState(window2.get())->IsFullscreen()); @@ -1803,13 +1704,12 @@ // Tests can handle OverviewWindowAnimationObserver was deleted. TEST_F(WindowSelectorTest, HandleOverviewWindowAnimationObserverWasDeleted) { - const gfx::Rect bounds(400, 400); - std::unique_ptr<aura::Window> window1(CreateWindow(bounds)); - std::unique_ptr<aura::Window> window2(CreateWindow(bounds)); - std::unique_ptr<aura::Window> window3(CreateWindow(bounds)); - wm::ActivateWindow(window3.get()); - wm::ActivateWindow(window2.get()); - wm::ActivateWindow(window1.get()); + std::unique_ptr<aura::Window> window1(CreateTestWindow()); + std::unique_ptr<aura::Window> window2(CreateTestWindow()); + std::unique_ptr<aura::Window> window3(CreateTestWindow()); + ::wm::ActivateWindow(window3.get()); + ::wm::ActivateWindow(window2.get()); + ::wm::ActivateWindow(window1.get()); EXPECT_FALSE(wm::GetWindowState(window1.get())->IsFullscreen()); EXPECT_FALSE(wm::GetWindowState(window2.get())->IsFullscreen()); @@ -1825,12 +1725,11 @@ // Enter overview. ToggleOverview(); - // Click on |window2| to activate it and exit overview. - // Should only set |should_animate_when_exiting_| and - // |should_be_observed_when_exiting_| on window 2. - // Because the animation duration is zero in test, the - // OverviewWindowAnimationObserver will delete itself immediatelly before - // |window3|'s is added to it. + // Click on |window2| to activate it and exit overview. Should only set + // |should_animate_when_exiting_| and |should_be_observed_when_exiting_| on + // window 2. Because the animation duration is zero in test, the + // OverviewWindowAnimationObserver will delete itself immediately before + // |window3| is added to it. ClickWindow(window2.get()); EXPECT_FALSE(window1->layer()->GetAnimator()->is_animating()); EXPECT_FALSE(window2->layer()->GetAnimator()->is_animating()); @@ -1840,13 +1739,12 @@ // Tests can handle |gained_active| window is not in the |window_grid| when // OnWindowActivated. TEST_F(WindowSelectorTest, HandleActiveWindowNotInWindowGrid) { - const gfx::Rect bounds(400, 400); - std::unique_ptr<aura::Window> window1(CreateWindow(bounds)); - std::unique_ptr<aura::Window> window2(CreateWindow(bounds)); - std::unique_ptr<aura::Window> window3(CreateWindow(bounds)); - wm::ActivateWindow(window3.get()); - wm::ActivateWindow(window2.get()); - wm::ActivateWindow(window1.get()); + std::unique_ptr<aura::Window> window1(CreateTestWindow()); + std::unique_ptr<aura::Window> window2(CreateTestWindow()); + std::unique_ptr<aura::Window> window3(CreateTestWindow()); + ::wm::ActivateWindow(window3.get()); + ::wm::ActivateWindow(window2.get()); + ::wm::ActivateWindow(window1.get()); EXPECT_FALSE(wm::GetWindowState(window1.get())->IsFullscreen()); EXPECT_FALSE(wm::GetWindowState(window2.get())->IsFullscreen()); @@ -1865,8 +1763,7 @@ ui::ScopedAnimationDurationScaleMode test_duration_mode( ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION); // Create and active a new window should exit overview without error. - auto widget = - CreateTestWidget(nullptr, kShellWindowId_StatusContainer, bounds); + auto widget = CreateTestWidget(); TweenTester tester1(window1.get()); TweenTester tester2(window2.get()); @@ -1885,26 +1782,26 @@ // Fails consistently; see https://crbug.com/812497. TEST_F(WindowSelectorTest, DISABLED_HandleAlwaysOnTopWindow) { const gfx::Rect bounds(400, 400); - std::unique_ptr<aura::Window> window1(CreateWindow(bounds)); - std::unique_ptr<aura::Window> window2(CreateWindow(bounds)); - std::unique_ptr<aura::Window> window3(CreateWindow(bounds)); - std::unique_ptr<aura::Window> window4(CreateWindow(bounds)); - std::unique_ptr<aura::Window> window5(CreateWindow(bounds)); - std::unique_ptr<aura::Window> window6(CreateWindow(bounds)); - std::unique_ptr<aura::Window> window7(CreateWindow(bounds)); - std::unique_ptr<aura::Window> window8(CreateWindow(bounds)); + std::unique_ptr<aura::Window> window1(CreateTestWindow(bounds)); + std::unique_ptr<aura::Window> window2(CreateTestWindow(bounds)); + std::unique_ptr<aura::Window> window3(CreateTestWindow(bounds)); + std::unique_ptr<aura::Window> window4(CreateTestWindow(bounds)); + std::unique_ptr<aura::Window> window5(CreateTestWindow(bounds)); + std::unique_ptr<aura::Window> window6(CreateTestWindow(bounds)); + std::unique_ptr<aura::Window> window7(CreateTestWindow(bounds)); + std::unique_ptr<aura::Window> window8(CreateTestWindow(bounds)); window3->SetProperty(aura::client::kAlwaysOnTopKey, true); window5->SetProperty(aura::client::kAlwaysOnTopKey, true); // Control z order and MRU order. - wm::ActivateWindow(window8.get()); - wm::ActivateWindow(window7.get()); // Will be fullscreen. - wm::ActivateWindow(window6.get()); // Will be maximized. - wm::ActivateWindow(window5.get()); // AlwaysOnTop window. - wm::ActivateWindow(window4.get()); - wm::ActivateWindow(window3.get()); // AlwaysOnTop window. - wm::ActivateWindow(window2.get()); // Will be fullscreen. - wm::ActivateWindow(window1.get()); + ::wm::ActivateWindow(window8.get()); + ::wm::ActivateWindow(window7.get()); // Will be fullscreen. + ::wm::ActivateWindow(window6.get()); // Will be maximized. + ::wm::ActivateWindow(window5.get()); // AlwaysOnTop window. + ::wm::ActivateWindow(window4.get()); + ::wm::ActivateWindow(window3.get()); // AlwaysOnTop window. + ::wm::ActivateWindow(window2.get()); // Will be fullscreen. + ::wm::ActivateWindow(window1.get()); EXPECT_FALSE(wm::GetWindowState(window2.get())->IsFullscreen()); EXPECT_FALSE(wm::GetWindowState(window6.get())->IsFullscreen()); @@ -1958,14 +1855,14 @@ // https://crbug.com/816224. wm::GetWindowState(window2.get())->OnWMEvent(&toggle_fullscreen_event); wm::GetWindowState(window7.get())->OnWMEvent(&toggle_fullscreen_event); - wm::ActivateWindow(window8.get()); - wm::ActivateWindow(window7.get()); // Will be fullscreen. - wm::ActivateWindow(window6.get()); // Maximized. - wm::ActivateWindow(window5.get()); // AlwaysOnTop window. - wm::ActivateWindow(window4.get()); - wm::ActivateWindow(window3.get()); // AlwaysOnTop window. - wm::ActivateWindow(window2.get()); // Will be fullscreen. - wm::ActivateWindow(window1.get()); + ::wm::ActivateWindow(window8.get()); + ::wm::ActivateWindow(window7.get()); // Will be fullscreen. + ::wm::ActivateWindow(window6.get()); // Maximized. + ::wm::ActivateWindow(window5.get()); // AlwaysOnTop window. + ::wm::ActivateWindow(window4.get()); + ::wm::ActivateWindow(window3.get()); // AlwaysOnTop window. + ::wm::ActivateWindow(window2.get()); // Will be fullscreen. + ::wm::ActivateWindow(window1.get()); wm::GetWindowState(window2.get())->OnWMEvent(&toggle_fullscreen_event); wm::GetWindowState(window7.get())->OnWMEvent(&toggle_fullscreen_event); // Enter overview. @@ -1994,14 +1891,14 @@ // https://crbug.com/816224. wm::GetWindowState(window2.get())->OnWMEvent(&toggle_fullscreen_event); wm::GetWindowState(window7.get())->OnWMEvent(&toggle_fullscreen_event); - wm::ActivateWindow(window8.get()); - wm::ActivateWindow(window7.get()); // Will be fullscreen. - wm::ActivateWindow(window6.get()); // Maximized. - wm::ActivateWindow(window5.get()); // AlwaysOnTop window. - wm::ActivateWindow(window4.get()); - wm::ActivateWindow(window3.get()); // AlwaysOnTop window. - wm::ActivateWindow(window2.get()); // Will be fullscreen. - wm::ActivateWindow(window1.get()); + ::wm::ActivateWindow(window8.get()); + ::wm::ActivateWindow(window7.get()); // Will be fullscreen. + ::wm::ActivateWindow(window6.get()); // Maximized. + ::wm::ActivateWindow(window5.get()); // AlwaysOnTop window. + ::wm::ActivateWindow(window4.get()); + ::wm::ActivateWindow(window3.get()); // AlwaysOnTop window. + ::wm::ActivateWindow(window2.get()); // Will be fullscreen. + ::wm::ActivateWindow(window1.get()); wm::GetWindowState(window2.get())->OnWMEvent(&toggle_fullscreen_event); wm::GetWindowState(window7.get())->OnWMEvent(&toggle_fullscreen_event); // Enter overview. @@ -2031,14 +1928,14 @@ // https://crbug.com/816224. wm::GetWindowState(window2.get())->OnWMEvent(&toggle_fullscreen_event); wm::GetWindowState(window7.get())->OnWMEvent(&toggle_fullscreen_event); - wm::ActivateWindow(window8.get()); - wm::ActivateWindow(window7.get()); // Will be fullscreen. - wm::ActivateWindow(window6.get()); // Maximized. - wm::ActivateWindow(window5.get()); // AlwaysOnTop window. - wm::ActivateWindow(window4.get()); - wm::ActivateWindow(window3.get()); // AlwaysOnTop window. - wm::ActivateWindow(window2.get()); // Will be fullscreen. - wm::ActivateWindow(window1.get()); + ::wm::ActivateWindow(window8.get()); + ::wm::ActivateWindow(window7.get()); // Will be fullscreen. + ::wm::ActivateWindow(window6.get()); // Maximized. + ::wm::ActivateWindow(window5.get()); // AlwaysOnTop window. + ::wm::ActivateWindow(window4.get()); + ::wm::ActivateWindow(window3.get()); // AlwaysOnTop window. + ::wm::ActivateWindow(window2.get()); // Will be fullscreen. + ::wm::ActivateWindow(window1.get()); wm::GetWindowState(window2.get())->OnWMEvent(&toggle_fullscreen_event); wm::GetWindowState(window7.get())->OnWMEvent(&toggle_fullscreen_event); // Enter overview. @@ -2065,16 +1962,12 @@ // released. TEST_F(WindowSelectorTest, WindowItemCanAnimateOnDragRelease) { UpdateDisplay("400x400"); - const gfx::Rect bounds(10, 10, 200, 200); - std::unique_ptr<aura::Window> window1(CreateWindow(bounds)); - std::unique_ptr<aura::Window> window2(CreateWindow(bounds)); - wm::ActivateWindow(window2.get()); - wm::ActivateWindow(window1.get()); + std::unique_ptr<aura::Window> window1(CreateTestWindow()); + std::unique_ptr<aura::Window> window2(CreateTestWindow()); + ::wm::ActivateWindow(window2.get()); + ::wm::ActivateWindow(window1.get()); - // The item dragging is only allowed in tablet mode. - base::RunLoop().RunUntilIdle(); - Shell::Get()->tablet_mode_controller()->EnableTabletModeWindowManager(true); - + EnterTabletMode(); ToggleOverview(); WindowSelectorItem* item2 = GetWindowItemForWindow(0, window2.get()); // Drag |item2| in a way so that |window2| does not get activated. @@ -2096,14 +1989,10 @@ // visibility when a item is being dragged. TEST_F(WindowSelectorTest, WindowItemTitleCloseVisibilityOnDrag) { UpdateDisplay("400x400"); - const gfx::Rect bounds(10, 10, 200, 200); - std::unique_ptr<aura::Window> window1(CreateWindow(bounds)); - std::unique_ptr<aura::Window> window2(CreateWindow(bounds)); + std::unique_ptr<aura::Window> window1(CreateTestWindow()); + std::unique_ptr<aura::Window> window2(CreateTestWindow()); - // Dragging is only allowed in tablet mode. - base::RunLoop().RunUntilIdle(); - Shell::Get()->tablet_mode_controller()->EnableTabletModeWindowManager(true); - + EnterTabletMode(); ToggleOverview(); WindowSelectorItem* item1 = GetWindowItemForWindow(0, window1.get()); WindowSelectorItem* item2 = GetWindowItemForWindow(0, window2.get()); @@ -2135,19 +2024,15 @@ // Tests that overview widgets are stacked in the correct order. TEST_F(WindowSelectorTest, OverviewWidgetStackingOrder) { // Create three windows, including one minimized. - const gfx::Rect bounds(10, 10, 200, 200); - std::unique_ptr<aura::Window> window(CreateWindow(bounds)); - std::unique_ptr<aura::Window> minimized(CreateWindow(bounds)); + std::unique_ptr<aura::Window> window(CreateTestWindow()); + std::unique_ptr<aura::Window> minimized(CreateTestWindow()); wm::GetWindowState(minimized.get())->Minimize(); - std::unique_ptr<aura::Window> window3(CreateWindow(bounds)); + std::unique_ptr<aura::Window> window3(CreateTestWindow()); aura::Window* parent = window->parent(); DCHECK_EQ(parent, minimized->parent()); - // Dragging is only allowed in tablet mode. - base::RunLoop().RunUntilIdle(); - Shell::Get()->tablet_mode_controller()->EnableTabletModeWindowManager(true); - + EnterTabletMode(); ToggleOverview(); WindowSelectorItem* item1 = GetWindowItemForWindow(0, window.get()); WindowSelectorItem* item2 = GetWindowItemForWindow(0, minimized.get()); @@ -2219,15 +2104,11 @@ // Tests that overview widgets are stacked in the correct order. TEST_F(WindowSelectorTest, OverviewWidgetStackingOrderWithDragging) { - const gfx::Rect bounds(10, 10, 200, 200); - std::unique_ptr<aura::Window> window1(CreateWindow(bounds)); - std::unique_ptr<aura::Window> window2(CreateWindow(bounds)); - std::unique_ptr<aura::Window> window3(CreateWindow(bounds)); + std::unique_ptr<aura::Window> window1(CreateTestWindow()); + std::unique_ptr<aura::Window> window2(CreateTestWindow()); + std::unique_ptr<aura::Window> window3(CreateTestWindow()); - // Dragging is only allowed in tablet mode. - base::RunLoop().RunUntilIdle(); - Shell::Get()->tablet_mode_controller()->EnableTabletModeWindowManager(true); - + EnterTabletMode(); ToggleOverview(); WindowSelectorItem* item1 = GetWindowItemForWindow(0, window1.get()); WindowSelectorItem* item2 = GetWindowItemForWindow(0, window2.get()); @@ -2274,10 +2155,9 @@ // when the 400x200 is rotated to 200x400, and should be considered a normal // overview window after display change. UpdateDisplay("400x200"); - std::unique_ptr<aura::Window> wide(CreateWindow(gfx::Rect(10, 10, 400, 160))); - std::unique_ptr<aura::Window> tall(CreateWindow(gfx::Rect(10, 10, 50, 200))); - std::unique_ptr<aura::Window> normal( - CreateWindow(gfx::Rect(10, 10, 200, 200))); + std::unique_ptr<aura::Window> wide(CreateTestWindow(gfx::Rect(400, 160))); + std::unique_ptr<aura::Window> tall(CreateTestWindow(gfx::Rect(50, 200))); + std::unique_ptr<aura::Window> normal(CreateTestWindow(gfx::Rect(200, 200))); ToggleOverview(); base::RunLoop().RunUntilIdle(); @@ -2309,18 +2189,13 @@ // Verify that the mask that is applied to add rounded corners in overview mode // is removed during animations and drags. TEST_F(WindowSelectorTest, RoundedEdgeMaskVisibility) { - UpdateDisplay("400x400"); - const gfx::Rect bounds(0, 0, 200, 200); - std::unique_ptr<aura::Window> window1(CreateWindow(bounds)); - std::unique_ptr<aura::Window> window2(CreateWindow(bounds)); + std::unique_ptr<aura::Window> window1(CreateTestWindow()); + std::unique_ptr<aura::Window> window2(CreateTestWindow()); - wm::ActivateWindow(window2.get()); - wm::ActivateWindow(window1.get()); + ::wm::ActivateWindow(window2.get()); + ::wm::ActivateWindow(window1.get()); - // Dragging is only allowed in tablet mode. - base::RunLoop().RunUntilIdle(); - Shell::Get()->tablet_mode_controller()->EnableTabletModeWindowManager(true); - + EnterTabletMode(); ToggleOverview(); base::RunLoop().RunUntilIdle(); WindowSelectorItem* item1 = GetWindowItemForWindow(0, window1.get()); @@ -2382,13 +2257,15 @@ }; // Add three windows which in overview mode will be considered wide, tall and - // normal. Set top view insets to 0, so it is easy to check the ratios of - // the shadows match the ratios of the untransformed windows. + // normal. Set top view insets to 0 so it is easy to check the ratios of the + // shadows match the ratios of the untransformed windows. UpdateDisplay("400x400"); - std::unique_ptr<aura::Window> wide(CreateWindow(gfx::Rect(10, 10, 400, 100))); - std::unique_ptr<aura::Window> tall(CreateWindow(gfx::Rect(10, 10, 100, 400))); + std::unique_ptr<aura::Window> wide( + CreateTestWindowInShellWithDelegate(nullptr, -1, gfx::Rect(400, 100))); + std::unique_ptr<aura::Window> tall( + CreateTestWindowInShellWithDelegate(nullptr, -1, gfx::Rect(100, 400))); std::unique_ptr<aura::Window> normal( - CreateWindow(gfx::Rect(10, 10, 200, 200))); + CreateTestWindowInShellWithDelegate(nullptr, -1, gfx::Rect(200, 200))); wide->SetProperty(aura::client::kTopViewInset, 0); tall->SetProperty(aura::client::kTopViewInset, 0); normal->SetProperty(aura::client::kTopViewInset, 0); @@ -2438,14 +2315,10 @@ // Verify that attempting to drag with a secondary finger works as expected. // Disabled due to flakiness: crbug.com/834708 TEST_F(WindowSelectorTest, DISABLED_DraggingWithTwoFingers) { - std::unique_ptr<aura::Window> window1 = CreateTestWindow(); - std::unique_ptr<aura::Window> window2 = CreateTestWindow(); + std::unique_ptr<aura::Window> window1(CreateTestWindow()); + std::unique_ptr<aura::Window> window2(CreateTestWindow()); - // Dragging is only allowed in tablet mode. - base::RunLoop().RunUntilIdle(); - Shell::Get()->tablet_mode_controller()->EnableTabletModeWindowManager(true); - base::RunLoop().RunUntilIdle(); - + EnterTabletMode(); ToggleOverview(); base::RunLoop().RunUntilIdle(); WindowSelectorItem* item1 = GetWindowItemForWindow(0, window1.get()); @@ -2506,8 +2379,7 @@ // Verify that shadows on windows disappear for the duration of overview mode. TEST_F(WindowSelectorTest, ShadowDisappearsInOverview) { - const gfx::Rect bounds(200, 200); - std::unique_ptr<aura::Window> window(CreateWindow(bounds)); + std::unique_ptr<aura::Window> window(CreateTestWindow()); // Verify that the shadow is initially visible. ::wm::ShadowController* shadow_controller = Shell::Get()->shadow_controller(); @@ -2524,8 +2396,8 @@ // Verify that PIP windows will be excluded from the overview, but not hidden. TEST_F(WindowSelectorTest, PipWindowShownButExcludedFromOverview) { - std::unique_ptr<aura::Window> pip_window(CreateWindow(gfx::Rect(200, 200))); - + std::unique_ptr<aura::Window> pip_window( + CreateTestWindow(gfx::Rect(200, 200))); wm::WindowState* window_state = wm::GetWindowState(pip_window.get()); const wm::WMEvent enter_pip(wm::WM_EVENT_PIP); window_state->OnWMEvent(&enter_pip); @@ -2540,10 +2412,9 @@ // Tests the PositionWindows function works as expected. TEST_F(WindowSelectorTest, PositionWindows) { - const gfx::Rect bounds(200, 200); - std::unique_ptr<aura::Window> window1(CreateWindow(bounds)); - std::unique_ptr<aura::Window> window2(CreateWindow(bounds)); - std::unique_ptr<aura::Window> window3(CreateWindow(bounds)); + std::unique_ptr<aura::Window> window1(CreateTestWindow()); + std::unique_ptr<aura::Window> window2(CreateTestWindow()); + std::unique_ptr<aura::Window> window3(CreateTestWindow()); ToggleOverview(); WindowSelectorItem* item1 = GetWindowItemForWindow(0, window1.get()); @@ -2582,14 +2453,10 @@ // Tests that overview mode is entered with kWindowDragged mode when an app is // dragged from the top of the screen. TEST_F(WindowSelectorTest, DraggingFromTopAnimation) { - // Ensure calls to EnableTabletModeWindowManager complete. - base::RunLoop().RunUntilIdle(); - Shell::Get()->tablet_mode_controller()->EnableTabletModeWindowManager(true); - base::RunLoop().RunUntilIdle(); - - const gfx::Rect bounds(200, 200); - std::unique_ptr<aura::Window> window(CreateWindow(bounds)); - std::unique_ptr<views::Widget> widget(CreateWindowWidget(bounds)); + EnterTabletMode(); + std::unique_ptr<views::Widget> widget(CreateTestWidget( + nullptr, kShellWindowId_DefaultContainer, gfx::Rect(200, 200))); + widget->GetNativeWindow()->SetProperty(aura::client::kTopViewInset, 20); // Drag from the the top of the app to enter overview. auto drag_controller = std::make_unique<TabletModeAppWindowDragController>(); @@ -2608,9 +2475,7 @@ // behaviors and alignments. TEST_F(WindowSelectorTest, GridBounds) { UpdateDisplay("600x600"); - - const gfx::Rect bounds(200, 200); - std::unique_ptr<aura::Window> window(CreateWindow(bounds)); + std::unique_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(200, 200))); Shelf* shelf = GetPrimaryShelf(); shelf->SetAlignment(SHELF_ALIGNMENT_BOTTOM); @@ -2656,10 +2521,7 @@ void SetUp() override { WindowSelectorTest::SetUp(); - // Ensure calls to EnableTabletModeWindowManager complete. - base::RunLoop().RunUntilIdle(); - Shell::Get()->tablet_mode_controller()->EnableTabletModeWindowManager(true); - base::RunLoop().RunUntilIdle(); + EnterTabletMode(); } SplitViewController* split_view_controller() { @@ -2718,7 +2580,6 @@ const gfx::Point& end_location, SelectorItemLocation location, bool long_press = true) { - // Start drag in the middle of the seletor item. gfx::Point start_location; switch (location) { case SelectorItemLocation::CENTER: @@ -2756,12 +2617,7 @@ // Creates a window which cannot be snapped by splitview. std::unique_ptr<aura::Window> CreateUnsnappableWindow( const gfx::Rect& bounds = gfx::Rect()) { - std::unique_ptr<aura::Window> window; - if (bounds.IsEmpty()) - window = CreateTestWindow(); - else - window = base::WrapUnique<aura::Window>(CreateWindow(bounds)); - + std::unique_ptr<aura::Window> window = CreateTestWindow(); window->SetProperty(aura::client::kResizeBehaviorKey, ws::mojom::kResizeBehaviorNone); return window; @@ -2879,14 +2735,13 @@ // will be closed. TEST_F(SplitViewWindowSelectorTest, DragToClose) { // This test requires a widget. - const gfx::Rect bounds(400, 400); - std::unique_ptr<views::Widget> widget1(CreateWindowWidget(bounds)); + std::unique_ptr<views::Widget> widget(CreateTestWidget()); ToggleOverview(); ASSERT_TRUE(window_selector_controller()->IsSelecting()); WindowSelectorItem* item = - GetWindowItemForWindow(0, widget1->GetNativeWindow()); + GetWindowItemForWindow(0, widget->GetNativeWindow()); const gfx::Point start = item->target_bounds().CenterPoint(); ASSERT_TRUE(item); @@ -2904,21 +2759,21 @@ window_selector()->CompleteDrag(item, start + gfx::Vector2d(0, 180)); base::RunLoop().RunUntilIdle(); EXPECT_FALSE(window_selector()); + EXPECT_TRUE(widget->IsClosed()); } // Verify that if the window item has been flung enough vertically, the window // will be closed. TEST_F(SplitViewWindowSelectorTest, FlingToClose) { // This test requires a widget. - const gfx::Rect bounds(400, 400); - std::unique_ptr<views::Widget> widget1(CreateWindowWidget(bounds)); + std::unique_ptr<views::Widget> widget(CreateTestWidget()); ToggleOverview(); ASSERT_TRUE(window_selector_controller()->IsSelecting()); EXPECT_EQ(1u, window_selector()->grid_list_for_testing()[0]->size()); WindowSelectorItem* item = - GetWindowItemForWindow(0, widget1->GetNativeWindow()); + GetWindowItemForWindow(0, widget->GetNativeWindow()); const gfx::Point start = item->target_bounds().CenterPoint(); ASSERT_TRUE(item); @@ -2928,7 +2783,7 @@ window_selector()->Fling(item, start, 2500, 0); ASSERT_TRUE(window_selector()); - // Verify that items flung vertically, but without enough velocity do not + // Verify that items flung vertically but without enough velocity do not // close the item. window_selector()->InitiateDrag(item, start); window_selector()->Drag(item, start + gfx::Vector2d(0, 50)); @@ -2942,6 +2797,7 @@ window_selector()->Fling(item, start, 0, 2500); base::RunLoop().RunUntilIdle(); EXPECT_FALSE(window_selector()); + EXPECT_TRUE(widget->IsClosed()); } // Tests that nudging occurs in the most basic case, which is we have one row @@ -3082,10 +2938,9 @@ // overview mode when split view is enabled. TEST_F(SplitViewWindowSelectorTest, WindowGridSizeWhileDraggingWithSplitView) { // Add three windows and enter overview mode. - const gfx::Rect bounds(400, 400); - std::unique_ptr<aura::Window> window1(CreateWindow(bounds)); - std::unique_ptr<aura::Window> window2(CreateWindow(bounds)); - std::unique_ptr<aura::Window> window3(CreateWindow(bounds)); + std::unique_ptr<aura::Window> window1(CreateTestWindow()); + std::unique_ptr<aura::Window> window2(CreateTestWindow()); + std::unique_ptr<aura::Window> window3(CreateTestWindow()); ToggleOverview(); ASSERT_TRUE(window_selector_controller()->IsSelecting()); @@ -3200,7 +3055,7 @@ // Create a new window should exit the overview mode. std::unique_ptr<aura::Window> window2(CreateWindow(bounds)); - wm::ActivateWindow(window2.get()); + ::wm::ActivateWindow(window2.get()); EXPECT_FALSE(window_selector_controller()->IsSelecting()); EXPECT_EQ(split_view_controller()->state(), SplitViewController::BOTH_SNAPPED); @@ -3212,8 +3067,8 @@ // If there are more than 2 windows in overview std::unique_ptr<aura::Window> window3(CreateWindow(bounds)); std::unique_ptr<aura::Window> window4(CreateWindow(bounds)); - wm::ActivateWindow(window3.get()); - wm::ActivateWindow(window4.get()); + ::wm::ActivateWindow(window3.get()); + ::wm::ActivateWindow(window4.get()); EXPECT_FALSE(window_selector_controller()->IsSelecting()); EXPECT_EQ(split_view_controller()->state(), SplitViewController::BOTH_SNAPPED); @@ -3537,9 +3392,9 @@ // Exiting the splitview will hide the unsnappable label. const gfx::Rect divider_bounds = GetSplitViewDividerBounds(/*is_dragging=*/false); - ui::test::EventGenerator* generator = GetEventGenerator(); - generator->set_current_screen_location(divider_bounds.CenterPoint()); - generator->DragMouseTo(0, 0); + GetEventGenerator()->set_current_screen_location( + divider_bounds.CenterPoint()); + GetEventGenerator()->DragMouseTo(0, 0); EXPECT_FALSE(split_view_controller()->IsSplitViewModeActive()); EXPECT_EQ(0.f, unsnappable_layer->opacity()); @@ -3721,9 +3576,9 @@ // Drag the divider to the left edge. const gfx::Rect divider_bounds = GetSplitViewDividerBounds(/*is_dragging=*/false); - ui::test::EventGenerator* generator = GetEventGenerator(); - generator->set_current_screen_location(divider_bounds.CenterPoint()); - generator->DragMouseTo(0, 0); + GetEventGenerator()->set_current_screen_location( + divider_bounds.CenterPoint()); + GetEventGenerator()->DragMouseTo(0, 0); // Verify that it is still in overview mode and that |window1| is returned to // the overview list. @@ -3820,7 +3675,7 @@ // Now snap both |window1| and |window2|. selector_item1 = GetWindowItemForWindow(grid_index, window1.get()); DragWindowTo(selector_item1, gfx::Point(0, 0)); - wm::ActivateWindow(window2.get()); + ::wm::ActivateWindow(window2.get()); EXPECT_FALSE(IsSelecting()); EXPECT_EQ(split_view_controller()->state(), SplitViewController::BOTH_SNAPPED); @@ -3908,7 +3763,7 @@ EXPECT_FALSE(window3->layer()->GetTargetTransform().IsIdentity()); EXPECT_EQ(SplitViewController::LEFT_SNAPPED, split_view_controller()->state()); - wm::ActivateWindow(window2.get()); + ::wm::ActivateWindow(window2.get()); EXPECT_EQ(SplitViewController::BOTH_SNAPPED, split_view_controller()->state()); EXPECT_FALSE(window_selector_controller()->IsSelecting()); @@ -3924,7 +3779,7 @@ EXPECT_EQ(SplitViewController::LEFT_SNAPPED, split_view_controller()->state()); std::unique_ptr<aura::Window> window4(CreateWindow(bounds)); - wm::ActivateWindow(window4.get()); + ::wm::ActivateWindow(window4.get()); EXPECT_EQ(SplitViewController::BOTH_SNAPPED, split_view_controller()->state()); EXPECT_FALSE(window_selector_controller()->IsSelecting()); @@ -3969,8 +3824,7 @@ // Verify the behavior when trying to exit overview with one snapped window // is as expected. TEST_F(SplitViewWindowSelectorTest, ExitOverviewWithOneSnapped) { - const gfx::Rect bounds(0, 0, 400, 400); - std::unique_ptr<aura::Window> window(CreateWindow(bounds)); + std::unique_ptr<aura::Window> window(CreateWindow(gfx::Rect(400, 400))); // Tests that we cannot exit overview when there is one snapped window and no // windows in overview normally.
diff --git a/base/android/junit/src/org/chromium/base/GcStateAssertTest.java b/base/android/junit/src/org/chromium/base/GcStateAssertTest.java index 6460441..1548070 100644 --- a/base/android/junit/src/org/chromium/base/GcStateAssertTest.java +++ b/base/android/junit/src/org/chromium/base/GcStateAssertTest.java
@@ -32,6 +32,9 @@ @Before public void setUp() { + if (!BuildConfig.DCHECK_IS_ON) { + return; + } mTestClass = new TestClass(); mTargetRef = mTestClass.mGcStateAssert.mWrapper; mFound = false; @@ -49,6 +52,9 @@ @After public void tearDown() { + if (!BuildConfig.DCHECK_IS_ON) { + return; + } GcStateAssert.sTestHook = null; }
diff --git a/base/cpu.cc b/base/cpu.cc index aac2e957..3a0f6fa0 100644 --- a/base/cpu.cc +++ b/base/cpu.cc
@@ -152,6 +152,7 @@ memcpy(cpu_string, &cpu_info[1], kVendorNameSize); cpu_string[kVendorNameSize] = '\0'; cpu_vendor_ = cpu_string; + bool hypervisor = false; // Interpret CPU feature information. if (num_ids > 0) { @@ -176,6 +177,13 @@ has_sse42_ = (cpu_info[2] & 0x00100000) != 0; has_popcnt_ = (cpu_info[2] & 0x00800000) != 0; + // "Hypervisor Present Bit: Bit 31 of ECX of CPUID leaf 0x1." + // See https://lwn.net/Articles/301888/ + // This is checking for any hypervisor. Hypervisors may choose not to + // announce themselves. Hypervisors trap CPUID and sometimes return + // different results to underlying hardware. + hypervisor = (cpu_info[2] & 0x80000000) != 0; + // AVX instructions will generate an illegal instruction exception unless // a) they are supported by the CPU, // b) XSAVE is supported by the CPU and @@ -222,6 +230,23 @@ __cpuid(cpu_info, kParameterContainingNonStopTimeStampCounter); has_non_stop_time_stamp_counter_ = (cpu_info[3] & (1 << 8)) != 0; } + + if (!has_non_stop_time_stamp_counter_ && hypervisor) { + int cpu_info_hv[4] = {}; + __cpuid(cpu_info_hv, 0x40000000); + if (cpu_info_hv[1] == 0x7263694D && // Micr + cpu_info_hv[2] == 0x666F736F && // osof + cpu_info_hv[3] == 0x76482074) { // t Hv + // If CPUID says we have a variant TSC and a hypervisor has identified + // itself and the hypervisor says it is Microsoft Hyper-V, then treat + // TSC as invariant. + // + // Microsoft Hyper-V hypervisor reports variant TSC as there are some + // scenarios (eg. VM live migration) where the TSC is variant, but for + // our purposes we can treat it as invariant. + has_non_stop_time_stamp_counter_ = true; + } + } #elif defined(ARCH_CPU_ARM_FAMILY) && (defined(OS_ANDROID) || defined(OS_LINUX)) cpu_brand_ = *CpuInfoBrand(); #endif
diff --git a/build/android/gyp/javac.py b/build/android/gyp/javac.py index 1377681..8ad9bb7 100755 --- a/build/android/gyp/javac.py +++ b/build/android/gyp/javac.py
@@ -317,7 +317,7 @@ # Compiles with Error Prone take twice as long to run as pure javac. Thus GN # rules run both in parallel, with Error Prone only used for checks. - save_outputs = not options.use_errorprone_path + save_outputs = not options.enable_errorprone with build_utils.TempDir() as temp_dir: srcjars = options.java_srcjars @@ -546,8 +546,11 @@ help='Whether code being compiled should be built with stricter ' 'warnings for chromium code.') parser.add_option( - '--use-errorprone-path', - help='Use the Errorprone compiler at this path.') + '--errorprone-path', help='Use the Errorprone compiler at this path.') + parser.add_option( + '--enable-errorprone', + action='store_true', + help='Enable errorprone checks') parser.add_option('--jar-path', help='Jar output path.') parser.add_option( '--javac-arg', @@ -603,27 +606,38 @@ argv = build_utils.ExpandFileArgs(argv) options, java_files = _ParseOptions(argv) - if options.use_errorprone_path: - javac_path = options.use_errorprone_path + # Until we add a version of javac via DEPS, use errorprone with all checks + # disabled rather than javac. This ensures builds are reproducible. + # https://crbug.com/693079 + # As of Jan 2019, on a z920, compiling chrome_java times: + # * With javac: 17 seconds + # * With errorprone (checks disabled): 20 seconds + # * With errorprone (checks enabled): 30 seconds + if options.errorprone_path: + javac_path = options.errorprone_path else: javac_path = distutils.spawn.find_executable('javac') - javac_cmd = [javac_path] - javac_cmd.extend(( - '-g', - # Chromium only allows UTF8 source files. Being explicit avoids - # javac pulling a default encoding from the user's environment. - '-encoding', 'UTF-8', - # Prevent compiler from compiling .java files not listed as inputs. - # See: http://blog.ltgt.net/most-build-tools-misuse-javac/ - '-sourcepath', ':', - )) + javac_cmd = [ + javac_path, + '-g', + # Chromium only allows UTF8 source files. Being explicit avoids + # javac pulling a default encoding from the user's environment. + '-encoding', + 'UTF-8', + # Prevent compiler from compiling .java files not listed as inputs. + # See: http://blog.ltgt.net/most-build-tools-misuse-javac/ + '-sourcepath', + ':', + ] - if options.use_errorprone_path: + if options.enable_errorprone: for warning in ERRORPRONE_WARNINGS_TO_TURN_OFF: javac_cmd.append('-Xep:{}:OFF'.format(warning)) for warning in ERRORPRONE_WARNINGS_TO_ERROR: javac_cmd.append('-Xep:{}:ERROR'.format(warning)) + elif options.errorprone_path: + javac_cmd.append('-XepDisableAllChecks') if options.java_version: javac_cmd.extend([ @@ -665,7 +679,7 @@ options.processorpath) # GN already knows of java_files, so listing them just make things worse when # they change. - depfile_deps = ([javac_path] + classpath_inputs + options.java_srcjars) + depfile_deps = [javac_path] + classpath_inputs + options.java_srcjars input_paths = depfile_deps + java_files output_paths = [
diff --git a/build/config/android/internal_rules.gni b/build/config/android/internal_rules.gni index fdaaca3..4658cefc 100644 --- a/build/config/android/internal_rules.gni +++ b/build/config/android/internal_rules.gni
@@ -2798,16 +2798,23 @@ if (_chromium_code) { args += [ "--chromium-code=1" ] } - if (invoker.enable_errorprone) { + + # Use system javac only for debug builds. It's faster, but non-hermetic. + if (!is_java_debug || invoker.enable_errorprone) { deps += [ "//third_party/errorprone:errorprone($default_toolchain)" ] + args += [ + "--errorprone-path", + "bin/errorprone", + ] + } + if (invoker.enable_errorprone) { deps += [ "//tools/android/errorprone_plugin:errorprone_plugin_java($default_toolchain)" ] _rebased_errorprone_processorpath = [ "lib.java/tools/android/errorprone_plugin/errorprone_plugin_java.jar", ] args += [ - "--use-errorprone-path", - "bin/errorprone", "--processorpath=$_rebased_errorprone_processorpath", + "--enable-errorprone", ] } foreach(e, _provider_configurations) {
diff --git a/build/config/android/rules.gni b/build/config/android/rules.gni index 9c8e867..9b5b3b1 100644 --- a/build/config/android/rules.gni +++ b/build/config/android/rules.gni
@@ -3861,6 +3861,9 @@ if (defined(invoker.extra_modules)) { _module_count = 0 + + # Mark as used in case extra_modules is an empty list. + assert(_module_count == 0) foreach(_module, invoker.extra_modules) { _module_count += 1 assert(defined(_module.name),
diff --git a/build/config/fuchsia/build_manifest.py b/build/config/fuchsia/build_manifest.py index 72dd8ac..0fac7f88 100644 --- a/build/config/fuchsia/build_manifest.py +++ b/build/config/fuchsia/build_manifest.py
@@ -2,20 +2,9 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -"""Creates a archive manifest used for Fuchsia package generation. +"""Creates a archive manifest used for Fuchsia package generation.""" -Arguments: - root_dir: The absolute path to the Chromium source tree root. - - out_dir: The absolute path to the Chromium build directory. - - app_name: The filename of the package's executable target. - - runtime_deps: The path to the GN runtime deps file. - - output_path: The path of the manifest file which will be written. -""" - +import argparse import json import os import re @@ -148,10 +137,9 @@ return file_tag == '\x7fELF' -def BuildManifest(root_dir, out_dir, app_name, app_filename, - sandbox_policy_path, runtime_deps_file, depfile_path, - dynlib_paths, output_path): - with open(output_path, 'w') as manifest, open(depfile_path, 'w') as depfile: +def BuildManifest(args): + with open(args.output_path, 'w') as manifest, \ + open(args.depfile_path, 'w') as depfile: # Process the runtime deps file for file paths, recursively walking # directories as needed. File paths are stored in absolute form, # so that MakePackagePath() may relativize to either the source root or @@ -159,7 +147,7 @@ # runtime_deps may contain duplicate paths, so use a set for # de-duplication. expanded_files = set() - for next_path in open(runtime_deps_file, 'r'): + for next_path in open(args.runtime_deps_file, 'r'): next_path = next_path.strip() if os.path.isdir(next_path): for root, _, files in os.walk(next_path): @@ -173,7 +161,7 @@ # Get set of dist libraries available for dynamic linking. dist_libs = set() - for next_dir in dynlib_paths.split(','): + for next_dir in args.dynlib_path: dist_libs = dist_libs.union(EnumerateDirectoryFiles(next_dir)) # Compute the set of dynamic libraries used by the application or its @@ -184,55 +172,90 @@ # (binaries and libraries) are included as well. expanded_files = expanded_files.union( ComputeTransitiveLibDeps( - app_filename, + args.app_filename, {os.path.basename(f): f for f in expanded_files.union(dist_libs)})) # Format and write out the manifest contents. - gen_dir = os.path.join(out_dir, "gen") + gen_dir = os.path.join(args.out_dir, "gen") app_found = False + excluded_files_set = set(args.exclude_file) for current_file in expanded_files: if _IsBinary(current_file): current_file = _GetStrippedPath(current_file) - in_package_path = MakePackagePath(os.path.join(out_dir, current_file), - [gen_dir, root_dir, out_dir]) - if in_package_path == app_filename: + absolute_file_path = os.path.join(args.out_dir, current_file) + in_package_path = MakePackagePath(absolute_file_path, + [gen_dir, args.root_dir, args.out_dir]) + if in_package_path == args.app_filename: app_found = True + if in_package_path in excluded_files_set: + excluded_files_set.remove(in_package_path) + continue + # The source path is relativized so that it can be used on multiple # environments with differing parent directory structures, # e.g. builder bots and swarming clients. manifest.write('%s=%s\n' % (in_package_path, - os.path.relpath(current_file, out_dir))) + os.path.relpath(current_file, args.out_dir))) + + if len(excluded_files_set) > 0: + raise Exception('Some files were excluded with --exclude-file, but ' + 'not found in the deps list: %s' % + ', '.join(excluded_files_set)); if not app_found: raise Exception('Could not locate executable inside runtime_deps.') # Write meta/package manifest file. - with open(os.path.join(os.path.dirname(output_path), 'package'), 'w') \ + with open(os.path.join(os.path.dirname(args.output_path), 'package'), 'w') \ as package_json: - json.dump({'version': '0', 'name': app_name}, package_json) + json.dump({'version': '0', 'name': args.app_name}, package_json) manifest.write('meta/package=%s\n' % - os.path.relpath(package_json.name, out_dir)) + os.path.relpath(package_json.name, args.out_dir)) # Write component manifest file. - with open(os.path.join(os.path.dirname(output_path), - app_name + '.cmx'), 'w') as component_manifest_file: + cmx_file_path = os.path.join(os.path.dirname(args.output_path), + args.app_name + '.cmx') + with open(cmx_file_path, 'w') as component_manifest_file: component_manifest = { - 'program': { 'binary': app_filename }, - 'sandbox': json.load(open(sandbox_policy_path, 'r')), + 'program': { 'binary': args.app_filename }, + 'sandbox': json.load(open(args.sandbox_policy_path, 'r')), } json.dump(component_manifest, component_manifest_file) + manifest.write('meta/%s=%s\n' % (os.path.basename(component_manifest_file.name), - os.path.relpath(component_manifest_file.name, out_dir))) + os.path.relpath(cmx_file_path, args.out_dir))) depfile.write( - "%s: %s" % (os.path.relpath(output_path, out_dir), - " ".join([os.path.relpath(f, out_dir) + "%s: %s" % (os.path.relpath(args.output_path, args.out_dir), + " ".join([os.path.relpath(f, args.out_dir) for f in expanded_files]))) return 0 +def main(): + parser = argparse.ArgumentParser() + parser.add_argument('--root-dir', required=True, help='Build root directory') + parser.add_argument('--out-dir', required=True, help='Build output directory') + parser.add_argument('--app-name', required=True, help='Package name') + parser.add_argument('--app-filename', required=True, + help='Path to the main application binary relative to the output dir.') + parser.add_argument('--sandbox-policy-path', required=True, + help='Path to the sandbox policy file relative to the output dir.') + parser.add_argument('--runtime-deps-file', required=True, + help='File with the list of runtime dependencies.') + parser.add_argument('--depfile-path', required=True, + help='Path to write GN deps file.') + parser.add_argument('--exclude-file', action='append', default=[], + help='Package-relative file path to exclude from the package.') + parser.add_argument('--dynlib-path', action='append', default=[], + help='Paths for the dynamic libraries relative to the output dir.') + parser.add_argument('--output-path', required=True, help='Output file path.') + + args = parser.parse_args() + + return BuildManifest(args) if __name__ == '__main__': - sys.exit(BuildManifest(*sys.argv[1:])) + sys.exit(main())
diff --git a/build/config/fuchsia/package.gni b/build/config/fuchsia/package.gni index 83a5dae0..2e71029 100644 --- a/build/config/fuchsia/package.gni +++ b/build/config/fuchsia/package.gni
@@ -84,17 +84,37 @@ depfile = _depfile args = [ + "--root-dir", rebase_path("//"), + "--out-dir", rebase_path(root_out_dir), + "--app-name", pkg.package_name, + "--app-filename", get_label_info(pkg.binary, "name"), + "--sandbox-policy-path", rebase_path(pkg.sandbox_policy), + "--runtime-deps-file", rebase_path(_runtime_deps_file), + "--depfile-path", rebase_path(_depfile), - rebase_path(dist_libroot) + "," + rebase_path("${sysroot}/dist"), + "--dynlib-path", + rebase_path(dist_libroot), + "--dynlib-path", + rebase_path("${sysroot}/dist"), + "--output-path", rebase_path(_archive_manifest), ] + if (defined(pkg.excluded_files)) { + foreach(filename, pkg.excluded_files) { + args += [ + "--exclude-file", + filename, + ] + } + } + write_runtime_deps = _runtime_deps_file }
diff --git a/build/fuchsia/linux.sdk.sha1 b/build/fuchsia/linux.sdk.sha1 index 109f90b..0e56d05 100644 --- a/build/fuchsia/linux.sdk.sha1 +++ b/build/fuchsia/linux.sdk.sha1
@@ -1 +1 @@ -8239079b3b80414f4ad7566335007b4e8a82192a \ No newline at end of file +06501f59b8b19215e4235b97f3f0b006ed059d68 \ No newline at end of file
diff --git a/build/fuchsia/mac.sdk.sha1 b/build/fuchsia/mac.sdk.sha1 index 983be8f..f091d05 100644 --- a/build/fuchsia/mac.sdk.sha1 +++ b/build/fuchsia/mac.sdk.sha1
@@ -1 +1 @@ -73b95194dc363d5c7391e4e6220b24e1424dd71c \ No newline at end of file +59ee2ad79697b65682a86c4fd07fa7ba95b69c3e \ No newline at end of file
diff --git a/cc/scheduler/scheduler_state_machine.cc b/cc/scheduler/scheduler_state_machine.cc index eec833c..57bd80e 100644 --- a/cc/scheduler/scheduler_state_machine.cc +++ b/cc/scheduler/scheduler_state_machine.cc
@@ -714,8 +714,12 @@ if (begin_frame_source_paused_) return false; - // Don't create a pending tree till a frame sink is initialized. - if (!HasInitializedLayerTreeFrameSink()) + // Don't create a pending tree till a frame sink is fully initialized. Check + // for the ACTIVE state explicitly instead of calling + // HasInitializedLayerTreeFrameSink() because that only checks if frame sink + // has been recreated, but doesn't check if we're waiting for first commit or + // activation. + if (layer_tree_frame_sink_state_ != LayerTreeFrameSinkState::ACTIVE) return false; return true;
diff --git a/cc/scheduler/scheduler_state_machine_unittest.cc b/cc/scheduler/scheduler_state_machine_unittest.cc index 931c38bd..ca5ad89 100644 --- a/cc/scheduler/scheduler_state_machine_unittest.cc +++ b/cc/scheduler/scheduler_state_machine_unittest.cc
@@ -2310,24 +2310,63 @@ SchedulerStateMachine::Action::PERFORM_IMPL_SIDE_INVALIDATION); } -TEST(SchedulerStateMachineTest, - NoImplSideInvalidationWithoutLayerTreeFrameSink) { +TEST(SchedulerStateMachineTest, NoImplSideInvalidationUntilFrameSinkActive) { SchedulerSettings settings; StateMachine state(settings); - SET_UP_STATE(state); + SET_UP_STATE(state) - // Impl-side invalidations should not be triggered till the frame sink is - // initialized. + // Prefer impl side invalidation over begin main frame. + state.set_should_defer_invalidation_for_fast_main_frame(false); + state.DidLoseLayerTreeFrameSink(); + + // Create new frame sink but don't commit or activate yet. EXPECT_ACTION_UPDATE_STATE( SchedulerStateMachine::Action::BEGIN_LAYER_TREE_FRAME_SINK_CREATION); - EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE); - // No impl-side invalidations should be performed during frame sink creation. + state.DidCreateAndInitializeLayerTreeFrameSink(); + state.SetNeedsBeginMainFrame(); + bool needs_first_draw_on_activation = true; state.SetNeedsImplSideInvalidation(needs_first_draw_on_activation); + state.IssueNextBeginImplFrame(); + EXPECT_ACTION_UPDATE_STATE( + SchedulerStateMachine::Action::SEND_BEGIN_MAIN_FRAME); + // No impl side invalidation because we're still waiting for first commit. EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE); + + state.NotifyBeginMainFrameStarted(); + state.NotifyReadyToCommit(); + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::COMMIT); + + state.OnBeginImplFrameDeadline(); + state.OnBeginImplFrameIdle(); + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE); + + state.SetNeedsImplSideInvalidation(needs_first_draw_on_activation); + + state.IssueNextBeginImplFrame(); + // No impl side invalidation because we're still waiting for first activation. + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE); + + state.NotifyReadyToActivate(); + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::ACTIVATE_SYNC_TREE); + + state.OnBeginImplFrameDeadline(); + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::DRAW_IF_POSSIBLE); + state.OnBeginImplFrameIdle(); + + state.SetNeedsBeginMainFrame(); + state.SetNeedsImplSideInvalidation(needs_first_draw_on_activation); + + state.IssueNextBeginImplFrame(); + EXPECT_ACTION_UPDATE_STATE( + SchedulerStateMachine::Action::SEND_BEGIN_MAIN_FRAME); + // Impl side invalidation only after receiving first commit and activation for + // new frame sink. + EXPECT_ACTION_UPDATE_STATE( + SchedulerStateMachine::Action::PERFORM_IMPL_SIDE_INVALIDATION); } TEST(SchedulerStateMachineTest, ImplSideInvalidationWhenPendingTreeExists) {
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn index 3dfe2add..6d6fb03 100644 --- a/chrome/android/BUILD.gn +++ b/chrome/android/BUILD.gn
@@ -1836,6 +1836,16 @@ base_module_target = ":chrome_modern_public_base_bundle_module" version_code = chrome_modern_version_code version_name = chrome_version_name + uncompress_shared_libraries = chromium_linker_supported + } + + vr_module_tmpl("vr_monochrome_public_bundle_module") { + manifest_package = manifest_package + module_name = "VrMonochromePublic" + base_module_target = ":monochrome_public_base_bundle_module" + version_code = monochrome_version_code + version_name = chrome_version_name + uncompress_shared_libraries = true } } @@ -1878,12 +1888,21 @@ proguard_android_sdk_dep = webview_framework_dep } enable_language_splits = enable_chrome_language_splits + extra_modules = [] if (modularize_ar) { - extra_modules = [ + extra_modules += [ { name = "ar" module_target = ":ar_public_bundle_module" }, ] } + if (modularize_vr) { + extra_modules += [ + { + name = "vr" + module_target = ":vr_monochrome_public_bundle_module" + }, + ] + } }
diff --git a/chrome/android/chrome_public_apk_tmpl.gni b/chrome/android/chrome_public_apk_tmpl.gni index 4a7ceea9..a2eaf1b2 100644 --- a/chrome/android/chrome_public_apk_tmpl.gni +++ b/chrome/android/chrome_public_apk_tmpl.gni
@@ -370,12 +370,6 @@ png_to_webp = true } - # TODO(crbug.com/862719): Remove Java VR code from the monochrome base - # module once we can conditionally install the VR DFM. - if (enable_vr) { - deps += [ "//chrome/browser/android/vr:java" ] - } - if ((invoker.target_type == "android_apk" || !modularize_ar) && package_arcore) { deps += [ "//third_party/android_deps:com_google_ar_core_java" ]
diff --git a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedNewTabPage.java b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedNewTabPage.java index f90a139..4103136 100644 --- a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedNewTabPage.java +++ b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedNewTabPage.java
@@ -14,7 +14,6 @@ import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; -import android.widget.FrameLayout; import android.widget.ScrollView; import com.google.android.libraries.feed.api.scope.FeedProcessScope; @@ -32,6 +31,7 @@ import org.chromium.chrome.R; import org.chromium.chrome.browser.ChromeActivity; import org.chromium.chrome.browser.feed.action.FeedActionHandler; +import org.chromium.chrome.browser.gesturenav.HistoryNavigationLayout; import org.chromium.chrome.browser.native_page.ContextMenuManager; import org.chromium.chrome.browser.native_page.NativePageHost; import org.chromium.chrome.browser.ntp.NewTabPage; @@ -63,7 +63,7 @@ private final int mWideMargin; private UiConfig mUiConfig; - private FrameLayout mRootView; + private HistoryNavigationLayout mRootView; private ContextMenuManager mContextMenuManager; // Used when Feed is enabled. @@ -183,7 +183,7 @@ /** * Provides the additional capabilities needed for the {@link FeedNewTabPage} container view. */ - private class RootView extends FrameLayout { + private class RootView extends HistoryNavigationLayout { public RootView(Context context) { super(context); } @@ -202,6 +202,12 @@ return !(mTab != null && DeviceFormFactor.isWindowOnTablet(mTab.getWindowAndroid())) && (mFakeboxDelegate != null && mFakeboxDelegate.isUrlBarFocused()); } + + @Override + public boolean wasLastSideSwipeGestureConsumed() { + // TODO(jinsukkim): Get the correct info from mStream. + return true; + } } /**
diff --git a/chrome/android/java/res/layout/recent_tabs_page.xml b/chrome/android/java/res/layout/recent_tabs_page.xml index bdff54c..e7ac82a 100644 --- a/chrome/android/java/res/layout/recent_tabs_page.xml +++ b/chrome/android/java/res/layout/recent_tabs_page.xml
@@ -4,7 +4,7 @@ found in the LICENSE file. --> <!-- This single-child FrameLayout is needed for its top padding. --> -<FrameLayout +<org.chromium.chrome.browser.gesturenav.HistoryNavigationLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" @@ -32,4 +32,4 @@ android:scrollbarStyle="outsideOverlay" /> </org.chromium.chrome.browser.ntp.NativePageRootFrameLayout> -</FrameLayout> +</org.chromium.chrome.browser.gesturenav.HistoryNavigationLayout>
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ActivityTabProvider.java b/chrome/android/java/src/org/chromium/chrome/browser/ActivityTabProvider.java index 25d9a96..f555c649 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ActivityTabProvider.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ActivityTabProvider.java
@@ -213,7 +213,9 @@ */ private void triggerActivityTabChangeEvent(Tab tab) { // Allow the event to trigger before native is ready (before the layout manager is set). - if (mLayoutManager != null && !(mLayoutManager.getActiveLayout() instanceof StaticLayout) + if (mLayoutManager != null + && !(mLayoutManager.getActiveLayout() instanceof StaticLayout + || mLayoutManager.getActiveLayout() instanceof SimpleAnimationLayout) && tab != null) { return; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java index 9b6a667..3e557fa 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java
@@ -316,6 +316,9 @@ /** A means of providing the foreground tab of the activity to different features. */ private ActivityTabProvider mActivityTabProvider = new ActivityTabProvider(); + /** A means of providing the theme color to different features. */ + private final TabThemeColorProvider mTabThemeColorProvider = new TabThemeColorProvider(); + /** Whether or not the activity is in started state. */ private boolean mStarted; @@ -627,7 +630,7 @@ Callback<Boolean> urlFocusChangedCallback = hasFocus -> onOmniboxFocusChanged(hasFocus); mToolbarManager = new ToolbarManager(this, toolbarContainer, mAppMenuHandler, mAppMenuPropertiesDelegate, getCompositorViewHolder().getInvalidator(), - urlFocusChangedCallback); + urlFocusChangedCallback, mTabThemeColorProvider); mFindToolbarManager = new FindToolbarManager(this, mToolbarManager.getActionModeControllerCallback()); mAppMenuHandler.addObserver(new AppMenuObserver() { @@ -666,6 +669,7 @@ mTabModelSelector = createTabModelSelector(); mActivityTabProvider.setTabModelSelector(mTabModelSelector); + mTabThemeColorProvider.setActivityTabProvider(mActivityTabProvider); if (mTabModelSelector == null) { assert isFinishing(); @@ -727,12 +731,6 @@ @Override public void onDidChangeThemeColor(Tab tab, int color) { setStatusBarColor(tab, color); - - if (getToolbarManager() == null) return; - getToolbarManager().updatePrimaryColor(color, true); - - ControlContainer controlContainer = findViewById(R.id.control_container); - controlContainer.getToolbarResourceAdapter().invalidate(null); } @Override @@ -1367,6 +1365,7 @@ manager.removeTouchExplorationStateChangeListener(mTouchExplorationStateChangeListener); } + mTabThemeColorProvider.destroy(); mActivityTabProvider.destroy(); mComponent = null;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/SingleTabActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/SingleTabActivity.java index 83c2cbd9..a56a642 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/SingleTabActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/SingleTabActivity.java
@@ -18,7 +18,6 @@ import org.chromium.chrome.browser.tabmodel.TabModelSelector; import org.chromium.chrome.browser.tabmodel.TabSelectionType; import org.chromium.chrome.browser.tabmodel.document.TabDelegate; -import org.chromium.content_public.browser.ChildProcessImportance; import org.chromium.content_public.browser.LoadUrlParams; /** @@ -67,7 +66,6 @@ Tab tab = createTab(); getTabModelSelector().setTab(tab); tab.show(TabSelectionType.FROM_NEW); - tab.setImportance(ChildProcessImportance.MODERATE); } @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/SwipeRefreshHandler.java b/chrome/android/java/src/org/chromium/chrome/browser/SwipeRefreshHandler.java index cd4950073..dfd96e3 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/SwipeRefreshHandler.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/SwipeRefreshHandler.java
@@ -5,14 +5,17 @@ package org.chromium.chrome.browser; import android.content.Context; +import android.support.annotation.IntDef; import android.support.annotation.Nullable; import android.view.ViewGroup; import android.view.ViewGroup.LayoutParams; +import org.chromium.base.ThreadUtils; import org.chromium.base.TraceEvent; import org.chromium.base.metrics.RecordUserAction; import org.chromium.chrome.R; import org.chromium.chrome.browser.feature_engagement.TrackerFactory; +import org.chromium.chrome.browser.gesturenav.SideSlideLayout; import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.tab.TabWebContentsUserData; @@ -22,12 +25,28 @@ import org.chromium.third_party.android.swiperefresh.SwipeRefreshLayout; import org.chromium.ui.OverscrollRefreshHandler; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + /** * An overscroll handler implemented in terms a modified version of the Android * compat library's SwipeRefreshLayout effect. */ public class SwipeRefreshHandler extends TabWebContentsUserData implements OverscrollRefreshHandler { + /** + * The targets that can handle MotionEvents. + */ + @IntDef({SwipeType.NONE, SwipeType.PULL_TO_REFRESH, SwipeType.HISTORY_NAV}) + @Retention(RetentionPolicy.SOURCE) + private @interface SwipeType { + int NONE = 0; + int PULL_TO_REFRESH = 1; + int HISTORY_NAV = 2; + } + + private @SwipeType int mSwipeType; + private static final Class<SwipeRefreshHandler> USER_DATA_KEY = SwipeRefreshHandler.class; // Synthetic delay between the {@link #didStopRefreshing()} signal and the @@ -38,9 +57,11 @@ // guarding against cases where the page reload fails or takes too long. private static final int MAX_REFRESH_ANIMATION_DURATION_MS = 7500; + private final boolean mNavigationEnabled; + // The modified AppCompat version of the refresh effect, handling all core // logic, rendering and animation. - private final SwipeRefreshLayout mSwipeRefreshLayout; + private SwipeRefreshLayout mSwipeRefreshLayout; // The Tab where the swipe occurs. private Tab mTab; @@ -55,11 +76,22 @@ // Handles removing the layout from the view hierarchy. This is posted to ensure it does not // conflict with pending Android draws. - private Runnable mDetachLayoutRunnable; + private Runnable mDetachRefreshLayoutRunnable; // Accessibility utterance used to indicate refresh activation. private String mAccessibilityRefreshString; + // History navigation layout and the main logic turning the gesture into corresponding UI. + private SideSlideLayout mSideSlideLayout; + + // Async runnable for ending the refresh animation after the page first + // loads a frame. This is used to provide a reasonable minimum animation time. + private Runnable mStopNavigatingRunnable; + + // Handles removing the layout from the view hierarchy. This is posted to ensure it does not + // conflict with pending Android draws. + private Runnable mDetachSideSlideLayoutRunnable; + public static SwipeRefreshHandler from(Tab tab) { SwipeRefreshHandler handler = get(tab); if (handler == null) { @@ -82,19 +114,20 @@ private SwipeRefreshHandler(Tab tab) { super(tab); mTab = tab; + mNavigationEnabled = ChromeFeatureList.isEnabled(ChromeFeatureList.GESTURE_NAVIGATION); + } - final Context context = tab.getThemedApplicationContext(); + private void initSwipeRefreshLayout() { + final Context context = mTab.getThemedApplicationContext(); mSwipeRefreshLayout = new SwipeRefreshLayout(context); mSwipeRefreshLayout.setLayoutParams( new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); mSwipeRefreshLayout.setColorSchemeResources(R.color.light_active_color); - // SwipeRefreshLayout.LARGE layouts appear broken on JellyBean. - mSwipeRefreshLayout.setSize(SwipeRefreshLayout.DEFAULT); - mSwipeRefreshLayout.setEnabled(false); + if (mContainerView != null) mSwipeRefreshLayout.setEnabled(true); mSwipeRefreshLayout.setOnRefreshListener(() -> { cancelStopRefreshingRunnable(); - mSwipeRefreshLayout.postDelayed( + ThreadUtils.postOnUiThreadDelayed( getStopRefreshingRunnable(), MAX_REFRESH_ANIMATION_DURATION_MS); if (mAccessibilityRefreshString == null) { int resId = R.string.accessibility_swipe_refresh; @@ -105,12 +138,38 @@ RecordUserAction.record("MobilePullGestureReload"); }); mSwipeRefreshLayout.setOnResetListener(() -> { - if (mDetachLayoutRunnable != null) return; - mDetachLayoutRunnable = () -> { - mDetachLayoutRunnable = null; + if (mDetachRefreshLayoutRunnable != null) return; + mDetachRefreshLayoutRunnable = () -> { + mDetachRefreshLayoutRunnable = null; detachSwipeRefreshLayoutIfNecessary(); }; - mSwipeRefreshLayout.post(mDetachLayoutRunnable); + ThreadUtils.postOnUiThread(mDetachRefreshLayoutRunnable); + }); + } + + private void initSideSlideLayout() { + mSideSlideLayout = new SideSlideLayout(mTab.getThemedApplicationContext()); + mSideSlideLayout.setLayoutParams( + new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); + if (mContainerView != null) mSideSlideLayout.setEnabled(true); + + mSideSlideLayout.setOnNavigationListener((isForward) -> { + if (isForward) { + mTab.goForward(); + } else { + mTab.goBack(); + } + cancelStopNavigatingRunnable(); + mSideSlideLayout.post(getStopNavigatingRunnable()); + }); + + mSideSlideLayout.setOnResetListener(() -> { + if (mDetachSideSlideLayoutRunnable != null) return; + mDetachSideSlideLayoutRunnable = () -> { + mDetachSideSlideLayoutRunnable = null; + detachSideSlideLayoutIfNecessary(); + }; + mSideSlideLayout.post(mDetachSideSlideLayoutRunnable); }); } @@ -123,16 +182,22 @@ @Override public void cleanupWebContents(WebContents webContents) { - detachSwipeRefreshLayoutIfNecessary(); - cancelStopRefreshingRunnable(); + if (mSwipeRefreshLayout != null) detachSwipeRefreshLayoutIfNecessary(); + if (mSideSlideLayout != null) detachSideSlideLayoutIfNecessary(); mContainerView = null; setEnabled(false); } @Override public void destroyInternal() { - mSwipeRefreshLayout.setOnRefreshListener(null); - mSwipeRefreshLayout.setOnResetListener(null); + if (mSwipeRefreshLayout != null) { + mSwipeRefreshLayout.setOnRefreshListener(null); + mSwipeRefreshLayout.setOnResetListener(null); + } + if (mSideSlideLayout != null) { + mSideSlideLayout.setOnNavigationListener(null); + mSideSlideLayout.setOnResetListener(null); + } } /** @@ -141,59 +206,85 @@ * visiblity of the animation. */ public void didStopRefreshing() { - if (!mSwipeRefreshLayout.isRefreshing()) return; + if (mSwipeRefreshLayout == null || !mSwipeRefreshLayout.isRefreshing()) return; cancelStopRefreshingRunnable(); mSwipeRefreshLayout.postDelayed( getStopRefreshingRunnable(), STOP_REFRESH_ANIMATION_DELAY_MS); } @Override - public boolean start() { + public boolean start(float xDelta, float yDelta) { if (mTab.getActivity() != null && mTab.getActivity().getBottomSheet() != null) { Tracker tracker = TrackerFactory.getTrackerForProfile(Profile.getLastUsedProfile()); tracker.notifyEvent(EventConstants.PULL_TO_REFRESH); } - attachSwipeRefreshLayoutIfNecessary(); - return mSwipeRefreshLayout.start(); + if (yDelta > 0 && yDelta > Math.abs(xDelta)) { + if (mSwipeRefreshLayout == null) initSwipeRefreshLayout(); + mSwipeType = SwipeType.PULL_TO_REFRESH; + attachSwipeRefreshLayoutIfNecessary(); + return mSwipeRefreshLayout.start(); + } else if (Math.abs(xDelta) > Math.abs(yDelta) && mNavigationEnabled) { + if (mSideSlideLayout == null) initSideSlideLayout(); + mSwipeType = SwipeType.HISTORY_NAV; + boolean isForward = xDelta <= 0; + boolean shouldStart = isForward ? mTab.canGoForward() : mTab.canGoBack(); + if (shouldStart) { + mSideSlideLayout.setDirection(isForward); + attachSideSlideLayoutIfNecessary(); + mSideSlideLayout.start(); + } + return shouldStart; + } + mSwipeType = SwipeType.NONE; + return false; } @Override - public void pull(float delta) { + public void pull(float xDelta, float yDelta) { TraceEvent.begin("SwipeRefreshHandler.pull"); - mSwipeRefreshLayout.pull(delta); + if (mSwipeType == SwipeType.PULL_TO_REFRESH) { + mSwipeRefreshLayout.pull(yDelta); + } else if (mSwipeType == SwipeType.HISTORY_NAV) { + mSideSlideLayout.pull(xDelta); + } TraceEvent.end("SwipeRefreshHandler.pull"); } @Override public void release(boolean allowRefresh) { TraceEvent.begin("SwipeRefreshHandler.release"); - mSwipeRefreshLayout.release(allowRefresh); + if (mSwipeType == SwipeType.PULL_TO_REFRESH) { + mSwipeRefreshLayout.release(allowRefresh); + } else if (mSwipeType == SwipeType.HISTORY_NAV) { + mSideSlideLayout.release(allowRefresh); + } TraceEvent.end("SwipeRefreshHandler.release"); } @Override public void reset() { cancelStopRefreshingRunnable(); - mSwipeRefreshLayout.reset(); + if (mSwipeRefreshLayout != null) mSwipeRefreshLayout.reset(); + cancelStopNavigatingRunnable(); + if (mSideSlideLayout != null) mSideSlideLayout.reset(); } @Override public void setEnabled(boolean enabled) { - mSwipeRefreshLayout.setEnabled(enabled); if (!enabled) reset(); } private void cancelStopRefreshingRunnable() { if (mStopRefreshingRunnable != null) { - mSwipeRefreshLayout.removeCallbacks(mStopRefreshingRunnable); + ThreadUtils.getUiThreadHandler().removeCallbacks(mStopRefreshingRunnable); } } private void cancelDetachLayoutRunnable() { - if (mDetachLayoutRunnable != null) { - mSwipeRefreshLayout.removeCallbacks(mDetachLayoutRunnable); - mDetachLayoutRunnable = null; + if (mDetachRefreshLayoutRunnable != null) { + ThreadUtils.getUiThreadHandler().removeCallbacks(mDetachRefreshLayoutRunnable); + mDetachRefreshLayoutRunnable = null; } } @@ -219,4 +310,39 @@ mContainerView.removeView(mSwipeRefreshLayout); } } + + private void cancelStopNavigatingRunnable() { + if (mStopNavigatingRunnable != null) { + mSideSlideLayout.removeCallbacks(mStopNavigatingRunnable); + mStopNavigatingRunnable = null; + } + } + + private void cancelDetachSideSlideLayoutRunnable() { + if (mDetachSideSlideLayoutRunnable != null) { + mSideSlideLayout.removeCallbacks(mDetachSideSlideLayoutRunnable); + mDetachSideSlideLayoutRunnable = null; + } + } + + private Runnable getStopNavigatingRunnable() { + if (mStopNavigatingRunnable == null) { + mStopNavigatingRunnable = () -> mSideSlideLayout.stopNavigating(); + } + return mStopNavigatingRunnable; + } + + private void attachSideSlideLayoutIfNecessary() { + cancelDetachSideSlideLayoutRunnable(); + if (mSideSlideLayout.getParent() == null) { + mContainerView.addView(mSideSlideLayout); + } + } + + private void detachSideSlideLayoutIfNecessary() { + cancelDetachSideSlideLayoutRunnable(); + if (mSideSlideLayout.getParent() != null) { + mContainerView.removeView(mSideSlideLayout); + } + } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/TabThemeColorProvider.java b/chrome/android/java/src/org/chromium/chrome/browser/TabThemeColorProvider.java new file mode 100644 index 0000000..219a7bdf --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/TabThemeColorProvider.java
@@ -0,0 +1,44 @@ +// 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; + +import org.chromium.chrome.browser.ActivityTabProvider.ActivityTabTabObserver; +import org.chromium.chrome.browser.tab.Tab; +import org.chromium.chrome.browser.tab.TabThemeColorHelper; + +/** A ThemeColorProvider for the current tab's theming. */ +public class TabThemeColorProvider extends ThemeColorProvider { + /** The {@link sActivityTabTabObserver} used to know when the active tab color changed. */ + private ActivityTabTabObserver mActivityTabTabObserver; + + public TabThemeColorProvider() {} + + /** + * @param provider A means of getting the activity's tab. + */ + public void setActivityTabProvider(ActivityTabProvider provider) { + mActivityTabTabObserver = new ActivityTabTabObserver(provider) { + @Override + public void onObservingDifferentTab(Tab tab) { + if (tab == null) return; + updatePrimaryColor(TabThemeColorHelper.getColor(tab), false); + } + + @Override + public void onDidChangeThemeColor(Tab tab, int color) { + updatePrimaryColor(color, true); + } + }; + } + + @Override + public void destroy() { + super.destroy(); + if (mActivityTabTabObserver != null) { + mActivityTabTabObserver.destroy(); + mActivityTabTabObserver = null; + } + } +}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ThemeColorProvider.java b/chrome/android/java/src/org/chromium/chrome/browser/ThemeColorProvider.java new file mode 100644 index 0000000..26732b9a --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/ThemeColorProvider.java
@@ -0,0 +1,104 @@ +// 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; + +import android.content.Context; +import android.content.res.ColorStateList; +import android.support.v7.content.res.AppCompatResources; + +import org.chromium.base.ContextUtils; +import org.chromium.base.ObserverList; +import org.chromium.chrome.R; +import org.chromium.chrome.browser.util.ColorUtils; + +/** + * An abstract class that provides the current theme color. + */ +public abstract class ThemeColorProvider { + /** + * An interface to be notified about changes to the theme color. + */ + public interface ThemeColorObserver { + /** + * @param color The new color the observer should use. + * @param shouldAnimate Whether the change of color should be animated. + */ + void onThemeColorChanged(int color, boolean shouldAnimate); + } + + /** + * An interface to be notified about changes to the tint. + */ + public interface TintObserver { + /** + * @param tint The new tint the observer should use. + * @param useLight Whether the observer should use light mode. + */ + void onTintChanged(ColorStateList tint, boolean useLight); + } + + /** Light mode tint (used when color is dark). */ + private final ColorStateList mLightModeTint; + + /** Dark mode tint (used when color is light). */ + private final ColorStateList mDarkModeTint; + + /** Current primary color. */ + private int mPrimaryColor; + + /** Whether should use light tint (corresponds to dark color). */ + private boolean mUseLight; + + /** List of {@link ThemeColorObserver}s. These are used to broadcast events to listeners. */ + private final ObserverList<ThemeColorObserver> mThemeColorObservers; + + /** List of {@link TintObserver}s. These are used to broadcast events to listeners. */ + private final ObserverList<TintObserver> mTintObservers; + + public ThemeColorProvider() { + mThemeColorObservers = new ObserverList<ThemeColorObserver>(); + mTintObservers = new ObserverList<TintObserver>(); + final Context context = ContextUtils.getApplicationContext(); + mLightModeTint = AppCompatResources.getColorStateList(context, R.color.light_mode_tint); + mDarkModeTint = AppCompatResources.getColorStateList(context, R.color.dark_mode_tint); + } + + public void addThemeColorObserver(ThemeColorObserver observer) { + mThemeColorObservers.addObserver(observer); + } + + public void removeThemeColorObserver(ThemeColorObserver observer) { + mThemeColorObservers.removeObserver(observer); + } + + public void addTintObserver(TintObserver observer) { + mTintObservers.addObserver(observer); + } + + public void removeTintObserver(TintObserver observer) { + mTintObservers.removeObserver(observer); + } + + public void destroy() { + mThemeColorObservers.clear(); + mTintObservers.clear(); + } + + protected void updatePrimaryColor(int color, boolean shouldAnimate) { + if (mPrimaryColor == color) return; + mPrimaryColor = color; + for (ThemeColorObserver observer : mThemeColorObservers) { + observer.onThemeColorChanged(color, shouldAnimate); + } + + final boolean useLight = ColorUtils.shouldUseLightForegroundOnBackground(color); + if (useLight == mUseLight) return; + mUseLight = useLight; + final ColorStateList tint = useLight ? mLightModeTint : mDarkModeTint; + for (TintObserver observer : mTintObservers) { + observer.onTintChanged(tint, useLight); + } + } +}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java index f48e886c..8c2bdb2 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java
@@ -276,7 +276,7 @@ getToolbarManager().setUrlBarHidden(true); } int toolbarColor = mIntentDataProvider.getToolbarColor(); - getToolbarManager().updatePrimaryColor(toolbarColor, false); + getToolbarManager().onThemeColorChanged(toolbarColor, false); if (!mIntentDataProvider.isOpenedByChrome()) { getToolbarManager().setShouldUpdateToolbarPrimaryColor(false); } @@ -519,11 +519,11 @@ if (tab.isPreview()) { final int defaultColor = ColorUtils.getDefaultThemeColor(getResources(), false); - manager.updatePrimaryColor(defaultColor, false); + manager.onThemeColorChanged(defaultColor, false); setStatusBarColor(defaultColor, false); mTriggeredPreviewChange = true; } else if (mOriginalColor != manager.getPrimaryColor() && mTriggeredPreviewChange) { - manager.updatePrimaryColor(mOriginalColor, false); + manager.onThemeColorChanged(mOriginalColor, false); setStatusBarColor(mOriginalColor, false); mTriggeredPreviewChange = false;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/ArrowDrawable.java b/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/ArrowDrawable.java new file mode 100644 index 0000000..22339ccf --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/ArrowDrawable.java
@@ -0,0 +1,161 @@ +// 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.gesturenav; + +import android.content.res.Resources; +import android.graphics.Canvas; +import android.graphics.ColorFilter; +import android.graphics.Paint; +import android.graphics.Paint.Style; +import android.graphics.Path; +import android.graphics.PixelFormat; +import android.graphics.Rect; +import android.graphics.RectF; +import android.graphics.drawable.Drawable; +import android.support.annotation.ColorInt; + +import org.chromium.chrome.R; + +/** + * Arrow drawable indicating forward/backward direction for Material theme. + */ +class ArrowDrawable extends Drawable { + private static final int CIRCLE_DIAMETER_DP = 40; + private static final float CENTER_RADIUS_DP = 8.75f; + private static final float STROKE_WIDTH_DP = 2.5f; + private static final int ARROW_WIDTH_DP = 10; + + private final Resources mResources; + + private final RectF mTempBounds = new RectF(); + private final Paint mPaint = new Paint(); + private final Paint mArrowFill = new Paint(); + private final Path mArrow = new Path(); + + private final float mArrowWidth; + private final float mStrokeWidth; + private final float mStrokeInset; + + private float mArrowScale; + private float mCenterRadius; + private float mWidth; + private float mHeight; + private int mAlpha; + private @ColorInt int mBackgroundColor; + private @ColorInt int mForegroundColor; + private boolean mIsForward; + + public ArrowDrawable(Resources resources) { + mResources = resources; + mForegroundColor = mResources.getColor(R.color.light_active_color); + + float screenDensity = mResources.getDisplayMetrics().density; + mWidth = CIRCLE_DIAMETER_DP * screenDensity; + mHeight = CIRCLE_DIAMETER_DP * screenDensity; + mArrowWidth = ARROW_WIDTH_DP * screenDensity; + mStrokeWidth = STROKE_WIDTH_DP * screenDensity; + mCenterRadius = CENTER_RADIUS_DP * screenDensity; + mStrokeInset = Math.min(mWidth, mHeight) / 2.0f - mCenterRadius; + + mPaint.setStrokeCap(Paint.Cap.SQUARE); + mPaint.setAntiAlias(true); + mPaint.setStyle(Style.STROKE); + mPaint.setStrokeWidth(mStrokeWidth); + + mArrow.setFillType(android.graphics.Path.FillType.EVEN_ODD); + mArrowFill.setStyle(Paint.Style.FILL); + mArrowFill.setAntiAlias(true); + } + + /** + * Sets the direction the arrow points to. + * @param forward {@code true} if the arrow points forward. + */ + public void setDirection(boolean forward) { + mIsForward = forward; + } + + /** + * Set the scale of the arrow. + * @param scale Scale value of the range 0..1 + */ + public void setArrowScale(float scale) { + if (scale == mArrowScale) return; + mArrowScale = scale; + invalidateSelf(); + } + + /** + * Update the background color to match the parent view. + * @param color Background color. + */ + public void setBackgroundColor(@ColorInt int color) { + mBackgroundColor = color; + } + + @Override + public int getIntrinsicHeight() { + return (int) mHeight; + } + + @Override + public int getIntrinsicWidth() { + return (int) mWidth; + } + + @Override + public int getOpacity() { + return PixelFormat.TRANSLUCENT; + } + + @Override + public void setColorFilter(ColorFilter filter) { + mPaint.setColorFilter(filter); + invalidateSelf(); + } + + @Override + public void setAlpha(int alpha) { + if (mAlpha == alpha) return; + mAlpha = alpha; + invalidateSelf(); + } + + @Override + public int getAlpha() { + return mAlpha; + } + + @Override + public void draw(Canvas c) { + final Rect bounds = getBounds(); + final int saveCount = c.save(); + final RectF lineBounds = mTempBounds; + + lineBounds.set(bounds); + lineBounds.inset(mStrokeInset, mStrokeInset); + mPaint.setColor(mForegroundColor); + + c.drawLine(lineBounds.left, (lineBounds.top + lineBounds.bottom) / 2, lineBounds.right, + (lineBounds.top + lineBounds.bottom) / 2, mPaint); + + float delta = mArrowWidth * mArrowScale / 2f; + mArrow.reset(); + mArrow.moveTo(delta, -delta); + mArrow.lineTo(delta, delta); + mArrow.lineTo(delta * 2, 0); + + // Adjust the position of the triangle so that it is positioned at the end of the line. + float inset = (int) mStrokeInset / 2f * mArrowScale; + float x = (float) (mCenterRadius + bounds.exactCenterX()); + float y = (float) bounds.exactCenterY(); + mArrow.offset(x - inset, y); + mArrow.close(); + mArrowFill.setColor(mForegroundColor); + if (!mIsForward) c.rotate(180, bounds.exactCenterX(), bounds.exactCenterY()); + c.drawPath(mArrow, mArrowFill); + c.restoreToCount(saveCount); + } +}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/HistoryNavigationLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/HistoryNavigationLayout.java new file mode 100644 index 0000000..a28b64f0 --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/HistoryNavigationLayout.java
@@ -0,0 +1,201 @@ +// 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.gesturenav; + +import android.content.Context; +import android.support.annotation.IntDef; +import android.util.AttributeSet; +import android.view.GestureDetector; +import android.view.MotionEvent; +import android.widget.FrameLayout; + +import org.chromium.chrome.browser.ActivityTabProvider; +import org.chromium.chrome.browser.ChromeActivity; +import org.chromium.chrome.browser.ChromeFeatureList; +import org.chromium.chrome.browser.tab.Tab; + +/** + * FrameLayout that supports side-wise slide gesture for history navigation. Inheriting + * class may need to override {@link #isGestureConsumed()} if {@link #onTouchEvent} cannot + * be relied upon to know whether the side-wise swipe related event was handled. Namely + * {@link android.support.v7.widget.RecyclerView}) always claims to handle touch events. + */ +public class HistoryNavigationLayout extends FrameLayout { + @IntDef({GestureState.NONE, GestureState.STARTED, GestureState.DRAGGED}) + private @interface GestureState { + int NONE = 0; + int STARTED = 1; + int DRAGGED = 2; + } + + private GestureDetector mDetector; + + private SideSlideLayout mSideSlideLayout; + + // Async runnable for ending the refresh animation after the page first + // loads a frame. This is used to provide a reasonable minimum animation time. + private Runnable mStopNavigatingRunnable; + + // Handles removing the layout from the view hierarchy. This is posted to ensure + // it does not conflict with pending Android draws. + private Runnable mDetachLayoutRunnable; + + // Provides activity tab where the navigation should happen. + private ActivityTabProvider mTabProvider; + + public HistoryNavigationLayout(Context context) { + this(context, null); + } + + public HistoryNavigationLayout(Context context, AttributeSet attrs) { + super(context, attrs); + if (!ChromeFeatureList.isEnabled(ChromeFeatureList.GESTURE_NAVIGATION)) return; + if (context instanceof ChromeActivity) { + mTabProvider = ((ChromeActivity) context).getActivityTabProvider(); + mDetector = new GestureDetector(getContext(), new SideNavGestureListener()); + } else { + throw new IllegalStateException("This native page should be under ChromeActivity"); + } + } + + private void createLayout() { + mSideSlideLayout = new SideSlideLayout(getContext()); + mSideSlideLayout.setLayoutParams( + new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); + mSideSlideLayout.setEnabled(false); + mSideSlideLayout.setOnNavigationListener((isForward) -> { + if (mTabProvider == null) return; + Tab tab = mTabProvider.getActivityTab(); + if (isForward) { + tab.goForward(); + } else { + tab.goBack(); + } + cancelStopNavigatingRunnable(); + mSideSlideLayout.post(getStopNavigatingRunnable()); + }); + + mSideSlideLayout.setOnResetListener(() -> { + if (mDetachLayoutRunnable != null) return; + mDetachLayoutRunnable = () -> { + mDetachLayoutRunnable = null; + detachSideSlideLayoutIfNecessary(); + }; + mSideSlideLayout.post(mDetachLayoutRunnable); + }); + } + + @Override + public boolean dispatchTouchEvent(MotionEvent e) { + if (mDetector != null) { + mDetector.onTouchEvent(e); + if (e.getAction() == MotionEvent.ACTION_UP) { + if (mSideSlideLayout != null) mSideSlideLayout.release(true); + } + } + return super.dispatchTouchEvent(e); + } + + private class SideNavGestureListener extends GestureDetector.SimpleOnGestureListener { + private @GestureState int mState = GestureState.NONE; + + @Override + public boolean onDown(MotionEvent event) { + mState = GestureState.STARTED; + return true; + } + + @Override + public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { + if (wasLastSideSwipeGestureConsumed()) { + reset(); + mState = GestureState.NONE; + return true; + } + if (mState == GestureState.STARTED) { + if (Math.abs(distanceX) > Math.abs(distanceY)) { + boolean forward = distanceX > 0; + if (canNavigate(forward)) { + start(forward); + mState = GestureState.DRAGGED; + } + } + if (mState != GestureState.DRAGGED) mState = GestureState.NONE; + } + if (mState == GestureState.DRAGGED) mSideSlideLayout.pull(-distanceX); + return true; + } + } + + private boolean canNavigate(boolean forward) { + if (mTabProvider == null) return false; + Tab tab = mTabProvider.getActivityTab(); + return forward ? tab.canGoForward() : tab.canGoBack(); + } + + /** + * Checks if the gesture event was consumed by one of children views, in which case + * history navigation should not proceed. Whatever the child view does with the gesture + * events should take precedence and not be disturbed by the navigation. + * + * @return {@code true} if gesture event is consumed by one of the children. + */ + public boolean wasLastSideSwipeGestureConsumed() { + return false; + } + + private void start(boolean isForward) { + if (mSideSlideLayout == null) createLayout(); + mSideSlideLayout.setEnabled(true); + mSideSlideLayout.setDirection(isForward); + attachSideSlideLayoutIfNecessary(); + mSideSlideLayout.start(); + } + + /** + * Reset navigation UI in action. + */ + public void reset() { + cancelStopNavigatingRunnable(); + if (mSideSlideLayout != null) mSideSlideLayout.reset(); + } + + private void cancelStopNavigatingRunnable() { + if (mStopNavigatingRunnable != null) { + mSideSlideLayout.removeCallbacks(mStopNavigatingRunnable); + mStopNavigatingRunnable = null; + } + } + + private void cancelDetachLayoutRunnable() { + if (mDetachLayoutRunnable != null) { + mSideSlideLayout.removeCallbacks(mDetachLayoutRunnable); + mDetachLayoutRunnable = null; + } + } + + private Runnable getStopNavigatingRunnable() { + if (mStopNavigatingRunnable == null) { + mStopNavigatingRunnable = () -> mSideSlideLayout.stopNavigating(); + } + return mStopNavigatingRunnable; + } + + private void attachSideSlideLayoutIfNecessary() { + // The animation view is attached/detached on-demand to minimize overlap + // with composited SurfaceView content. + cancelDetachLayoutRunnable(); + if (mSideSlideLayout.getParent() == null) { + addView(mSideSlideLayout); + } + } + + private void detachSideSlideLayoutIfNecessary() { + cancelDetachLayoutRunnable(); + if (mSideSlideLayout.getParent() != null) { + removeView(mSideSlideLayout); + } + } +}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/SideSlideLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/SideSlideLayout.java new file mode 100644 index 0000000..6d70fc8 --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/SideSlideLayout.java
@@ -0,0 +1,377 @@ +// 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.gesturenav; + +import android.content.Context; +import android.support.annotation.IntDef; +import android.view.View; +import android.view.ViewGroup; +import android.view.animation.Animation; +import android.view.animation.Animation.AnimationListener; +import android.view.animation.DecelerateInterpolator; +import android.view.animation.Transformation; + +import org.chromium.base.metrics.RecordHistogram; +import org.chromium.chrome.R; +import org.chromium.third_party.android.swiperefresh.CircleImageView; + +/** + * The SideSlideLayout can be used whenever the user navigates the contents + * of a view using horizontal gesture. Shows an arrow widget moving horizontally + * in reaction to the gesture which, if goes over a threshold, triggers navigation. + * The caller that instantiates this view should add an {@link #OnNavigateListener} + * to be notified whenever the gesture is completed. + * Based on {@link org.chromium.third_party.android.swiperefresh.SwipeRefreshLayout} + * and modified accordingly to support horizontal gesture. + */ +public class SideSlideLayout extends ViewGroup { + // Used to record the UMA histogram Overscroll.* This definition should be + // in sync with that in content/browser/web_contents/aura/types.h + // TODO(jinsukkim): Generate java enum from the native header. + @IntDef({UmaNavigationType.NAVIGATION_TYPE_NONE, UmaNavigationType.FORWARD_TOUCHPAD, + UmaNavigationType.BACK_TOUCHPAD, UmaNavigationType.FORWARD_TOUCHSCREEN, + UmaNavigationType.BACK_TOUCHSCREEN, UmaNavigationType.RELOAD_TOUCHPAD, + UmaNavigationType.RELOAD_TOUCHSCREEN, UmaNavigationType.NAVIGATION_TYPE_COUNT}) + private @interface UmaNavigationType { + int NAVIGATION_TYPE_NONE = 0; + int FORWARD_TOUCHPAD = 1; + int BACK_TOUCHPAD = 2; + int FORWARD_TOUCHSCREEN = 3; + int BACK_TOUCHSCREEN = 4; + int RELOAD_TOUCHPAD = 5; + int RELOAD_TOUCHSCREEN = 6; + int NAVIGATION_TYPE_COUNT = 7; + } + + /** + * Classes that wish to be notified when the swipe gesture correctly + * triggers navigation should implement this interface. + */ + public interface OnNavigateListener { void onNavigate(boolean isForward); } + + /** + * Classes that wish to be notified when a reset is triggered should + * implement this interface. + */ + public interface OnResetListener { void onReset(); } + + private static final int MAX_ALPHA = 255; + private static final int STARTING_ALPHA = (int) (.3f * MAX_ALPHA); + + private static final int CIRCLE_DIAMETER_DP = 40; + private static final int MAX_CIRCLE_RADIUS_DP = 30; + + // Offset in dips from the border of the view. Gesture triggers the navigation + // if slid by this amount or more. + private static final int TARGET_THRESHOLD_DP = 128; + + private static final float DECELERATE_INTERPOLATION_FACTOR = 2f; + + private static final int SCALE_DOWN_DURATION_MS = 500; + private static final int ANIMATE_TO_START_DURATION_MS = 500; + + // Minimum number of pull updates necessary to trigger a side nav. + private static final int MIN_PULLS_TO_ACTIVATE = 3; + + private final DecelerateInterpolator mDecelerateInterpolator; + private final float mTotalDragDistance; + private final int mMediumAnimationDuration; + private final int mCircleWidth; + private final int mCircleHeight; + + private OnNavigateListener mListener; + private OnResetListener mResetListener; + + // Flag indicating that the navigation will be activated. + private boolean mNavigating; + + private int mCurrentTargetOffset; + private float mTotalMotionY; + + // Whether or not the starting offset has been determined. + private boolean mOriginalOffsetCalculated; + + // True while side gesture is in progress. + private boolean mIsBeingDragged; + + private CircleImageView mCircleView; + private ArrowDrawable mArrow; + + // Start position for animation moving the UI back to original offset. + private int mFrom; + private int mOriginalOffset; + + private Animation mScaleDownAnimation; + private AnimationListener mCancelAnimationListener; + + private boolean mIsForward; + + private final AnimationListener mNavigateListener = new AnimationListener() { + @Override + public void onAnimationStart(Animation animation) {} + + @Override + public void onAnimationRepeat(Animation animation) {} + + @Override + public void onAnimationEnd(Animation animation) { + if (mNavigating) { + // Make sure the arrow widget is fully visible + mArrow.setAlpha(MAX_ALPHA); + if (mListener != null) mListener.onNavigate(mIsForward); + recordHistogram("Overscroll.Navigated3", mIsForward); + } else { + reset(); + } + mCurrentTargetOffset = mCircleView.getLeft(); + } + }; + + private final Animation mAnimateToStartPosition = new Animation() { + @Override + public void applyTransformation(float interpolatedTime, Transformation t) { + int targetTop = mFrom + (int) ((mOriginalOffset - mFrom) * interpolatedTime); + int offset = targetTop - mCircleView.getLeft(); + mTotalMotionY += offset; + + float progress = Math.min(1.f, Math.abs(mTotalMotionY) / mTotalDragDistance); + mCircleView.setProgress(progress); + setTargetOffsetLeftAndRight(offset); + } + }; + + public SideSlideLayout(Context context) { + super(context); + + mMediumAnimationDuration = + getResources().getInteger(android.R.integer.config_mediumAnimTime); + + setWillNotDraw(false); + mDecelerateInterpolator = new DecelerateInterpolator(DECELERATE_INTERPOLATION_FACTOR); + + final float density = getResources().getDisplayMetrics().density; + mCircleWidth = (int) (CIRCLE_DIAMETER_DP * density); + mCircleHeight = (int) (CIRCLE_DIAMETER_DP * density); + + int background = getContext().getResources().getColor(R.color.modern_grey_50); + mCircleView = new CircleImageView(getContext(), background, CIRCLE_DIAMETER_DP / 2, + MAX_CIRCLE_RADIUS_DP, R.color.modern_blue_300); + + mArrow = new ArrowDrawable(getContext().getResources()); + mArrow.setBackgroundColor(background); + mCircleView.setImageDrawable(mArrow); + mCircleView.setVisibility(View.GONE); + addView(mCircleView); + + // The absolute offset has to take into account that the circle starts at an offset + mTotalDragDistance = TARGET_THRESHOLD_DP * density; + } + + /** + * Set the listener to be notified when the navigation is triggered. + */ + public void setOnNavigationListener(OnNavigateListener listener) { + mListener = listener; + } + + /** + * Set the reset listener to be notified when a reset is triggered. + */ + public void setOnResetListener(OnResetListener listener) { + mResetListener = listener; + } + + /** + * Stop navigation. + */ + public void stopNavigating() { + setNavigating(false); + } + + private void setNavigating(boolean navigating) { + if (mNavigating != navigating) { + mNavigating = navigating; + if (mNavigating) startScaleDownAnimation(mNavigateListener); + } + } + + private void startScaleDownAnimation(AnimationListener listener) { + if (mScaleDownAnimation == null) { + mScaleDownAnimation = new Animation() { + @Override + public void applyTransformation(float interpolatedTime, Transformation t) { + float progress = 1 - interpolatedTime; // [0..1] + mCircleView.setScaleX(progress); + mCircleView.setScaleY(progress); + } + }; + mScaleDownAnimation.setDuration(SCALE_DOWN_DURATION_MS); + } + mCircleView.setAnimationListener(listener); + mCircleView.clearAnimation(); + mCircleView.startAnimation(mScaleDownAnimation); + } + + /** + * Set the direction used for sliding gesture. + * @param forward {@code true} if direction is forward. + */ + public void setDirection(boolean forward) { + mIsForward = forward; + } + + @Override + protected void onLayout(boolean changed, int left, int top, int right, int bottom) { + if (getChildCount() == 0) return; + + final int height = getMeasuredHeight(); + int circleWidth = mCircleView.getMeasuredWidth(); + int circleHeight = mCircleView.getMeasuredHeight(); + mCircleView.layout(mCurrentTargetOffset, height / 2 - circleHeight / 2, + mCurrentTargetOffset + circleWidth, height / 2 + circleHeight / 2); + } + + @Override + public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + mCircleView.measure(MeasureSpec.makeMeasureSpec(mCircleWidth, MeasureSpec.EXACTLY), + MeasureSpec.makeMeasureSpec(mCircleHeight, MeasureSpec.EXACTLY)); + if (!mOriginalOffsetCalculated) { + initializeOffset(); + mOriginalOffsetCalculated = true; + } + } + + private void initializeOffset() { + mCurrentTargetOffset = mOriginalOffset = + mIsForward ? getMeasuredWidth() : -mCircleView.getMeasuredWidth(); + } + + /** + * Start the pull effect. If the effect is disabled or a navigation animation + * is currently active, the request will be ignored. + * @return whether a new pull sequence has started. + */ + public boolean start() { + if (!isEnabled() || mNavigating || mListener == null) return false; + mCircleView.clearAnimation(); + mTotalMotionY = 0; + mIsBeingDragged = true; + mArrow.setAlpha(STARTING_ALPHA); + mArrow.setDirection(mIsForward); + initializeOffset(); + return true; + } + + /** + * Apply a pull impulse to the effect. If the effect is disabled or has yet + * to start, the pull will be ignored. + * @param delta the magnitude of the pull. + */ + public void pull(float delta) { + if (!isEnabled() || !mIsBeingDragged) return; + + float maxDelta = mTotalDragDistance / MIN_PULLS_TO_ACTIVATE; + delta = Math.max(-maxDelta, Math.min(maxDelta, delta)); + mTotalMotionY += delta; + + float overscroll = mTotalMotionY; + float extraOs = Math.abs(overscroll) - mTotalDragDistance; + float slingshotDist = mTotalDragDistance; + float tensionSlingshotPercent = + Math.max(0, Math.min(extraOs, slingshotDist * 2) / slingshotDist); + float tensionPercent = + (float) ((tensionSlingshotPercent / 4) - Math.pow((tensionSlingshotPercent / 4), 2)) + * 2f; + + if (mCircleView.getVisibility() != View.VISIBLE) mCircleView.setVisibility(View.VISIBLE); + mCircleView.setScaleX(1f); + mCircleView.setScaleY(1f); + + float originalDragPercent = Math.abs(overscroll) / mTotalDragDistance; + float dragPercent = Math.min(1f, Math.abs(originalDragPercent)); + float adjustedPercent = (float) Math.max(dragPercent - .4, 0) * 5 / 3; + mArrow.setArrowScale(Math.min(1f, adjustedPercent)); + + float alphaStrength = Math.max(0f, Math.min(1f, (dragPercent - .9f) / .1f)); + mArrow.setAlpha(STARTING_ALPHA + (int) (alphaStrength * (MAX_ALPHA - STARTING_ALPHA))); + mCircleView.setProgress(Math.min(1.f, Math.abs(overscroll) / mTotalDragDistance)); + + float extraMove = slingshotDist * tensionPercent * 2; + int targetDiff = (int) (slingshotDist * dragPercent + extraMove); + int targetX = mOriginalOffset + (mIsForward ? -targetDiff : targetDiff); + setTargetOffsetLeftAndRight(targetX - mCurrentTargetOffset); + } + + private void setTargetOffsetLeftAndRight(int offset) { + mCircleView.offsetLeftAndRight(offset); + mCurrentTargetOffset = mCircleView.getLeft(); + } + + /** + * Release the active pull. If no pull has started, the release will be ignored. + * If the pull was sufficiently large, the navigation sequence will be initiated. + * @param allowNav whether to allow a sufficiently large pull to trigger + * the navigation action and animation sequence. + */ + public void release(boolean allowNav) { + if (!mIsBeingDragged) return; + + // See ACTION_UP handling in {@link #onTouchEvent(...)}. + mIsBeingDragged = false; + final float overscroll = Math.abs(mTotalMotionY); + if (isEnabled() && allowNav && overscroll > mTotalDragDistance) { + setNavigating(true); + return; + } + // Cancel navigation + mNavigating = false; + if (mCancelAnimationListener == null) { + mCancelAnimationListener = new AnimationListener() { + @Override + public void onAnimationStart(Animation animation) {} + + @Override + public void onAnimationEnd(Animation animation) { + startScaleDownAnimation(mNavigateListener); + } + + @Override + public void onAnimationRepeat(Animation animation) {} + }; + } + mFrom = mCurrentTargetOffset; + mAnimateToStartPosition.reset(); + mAnimateToStartPosition.setDuration(ANIMATE_TO_START_DURATION_MS); + mAnimateToStartPosition.setInterpolator(mDecelerateInterpolator); + mCircleView.setAnimationListener(mCancelAnimationListener); + mCircleView.clearAnimation(); + mCircleView.startAnimation(mAnimateToStartPosition); + recordHistogram("Overscroll.Cancelled3", mIsForward); + } + + /** + * Reset the effect, clearing any active animations. + */ + public void reset() { + mIsBeingDragged = false; + setNavigating(false); + mCircleView.setVisibility(View.GONE); + mCircleView.getBackground().setAlpha(MAX_ALPHA); + mArrow.setAlpha(MAX_ALPHA); + + // Return the circle to its start position + setTargetOffsetLeftAndRight(mOriginalOffset - mCurrentTargetOffset); + mCurrentTargetOffset = mCircleView.getLeft(); + if (mResetListener != null) mResetListener.onReset(); + } + + private static void recordHistogram(String name, boolean forward) { + RecordHistogram.recordEnumeratedHistogram(name, + forward ? UmaNavigationType.FORWARD_TOUCHSCREEN + : UmaNavigationType.BACK_TOUCHSCREEN, + UmaNavigationType.NAVIGATION_TYPE_COUNT); + } +}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/IncognitoNewTabPageView.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/IncognitoNewTabPageView.java index 9fd1a791..8c15fe3 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/IncognitoNewTabPageView.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/IncognitoNewTabPageView.java
@@ -8,18 +8,17 @@ import android.graphics.Canvas; import android.util.AttributeSet; import android.view.View; -import android.widget.FrameLayout; import org.chromium.base.ApiCompatibilityUtils; import org.chromium.chrome.R; import org.chromium.chrome.browser.ChromeFeatureList; +import org.chromium.chrome.browser.gesturenav.HistoryNavigationLayout; import org.chromium.chrome.browser.util.ViewUtils; /** * The New Tab Page for use in the incognito profile. */ -public class IncognitoNewTabPageView extends FrameLayout { - +public class IncognitoNewTabPageView extends HistoryNavigationLayout { private IncognitoNewTabPageManager mManager; private boolean mFirstShow = true; private NewTabPageScrollView mScrollView;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageUma.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageUma.java index fc16548..8482c66 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageUma.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageUma.java
@@ -316,8 +316,8 @@ status = ContentSuggestionsDisplayStatus.COLLAPSED; } - RecordHistogram.recordEnumeratedHistogram("ContentSuggestions.Feed.DisplayStatus", status, - ContentSuggestionsDisplayStatus.NUM_ENTRIES); + RecordHistogram.recordEnumeratedHistogram("ContentSuggestions.Feed.DisplayStatusOnOpen", + status, ContentSuggestionsDisplayStatus.NUM_ENTRIES); } /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageView.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageView.java index 84e4f7a..cfd61ab1 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageView.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageView.java
@@ -12,12 +12,12 @@ import android.support.v7.widget.RecyclerView.ViewHolder; import android.util.AttributeSet; import android.view.LayoutInflater; -import android.widget.FrameLayout; import org.chromium.base.TraceEvent; import org.chromium.base.VisibleForTesting; import org.chromium.chrome.R; import org.chromium.chrome.browser.compositor.layouts.content.InvalidationAwareThumbnailProvider; +import org.chromium.chrome.browser.gesturenav.HistoryNavigationLayout; import org.chromium.chrome.browser.native_page.ContextMenuManager; import org.chromium.chrome.browser.ntp.NewTabPage.FakeboxDelegate; import org.chromium.chrome.browser.ntp.cards.NewTabPageAdapter; @@ -35,7 +35,7 @@ * The native new tab page, represented by some basic data such as title and url, and an Android * View that displays the page. */ -public class NewTabPageView extends FrameLayout { +public class NewTabPageView extends HistoryNavigationLayout { private static final String TAG = "NewTabPageView"; private NewTabPageRecyclerView mRecyclerView; @@ -228,6 +228,11 @@ return mNewTabPageLayout; } + @Override + public boolean wasLastSideSwipeGestureConsumed() { + return mRecyclerView.isCardBeingSwiped(); + } + /** * Sets the {@link FakeboxDelegate} associated with the new tab page. * @param fakeboxDelegate The {@link FakeboxDelegate} used to determine whether the URL bar
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteMediator.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteMediator.java index 76b1bc2..bacc34eb 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteMediator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteMediator.java
@@ -29,8 +29,9 @@ import org.chromium.chrome.browser.omnibox.suggestions.AutocompleteController.OnSuggestionsReceivedListener; import org.chromium.chrome.browser.omnibox.suggestions.AutocompleteCoordinator.AutocompleteDelegate; import org.chromium.chrome.browser.omnibox.suggestions.AutocompleteCoordinator.SuggestionProcessor; +import org.chromium.chrome.browser.omnibox.suggestions.basic.AnswerSuggestionProcessor; import org.chromium.chrome.browser.omnibox.suggestions.basic.BasicSuggestionProcessor; -import org.chromium.chrome.browser.omnibox.suggestions.basic.BasicSuggestionProcessor.SuggestionHost; +import org.chromium.chrome.browser.omnibox.suggestions.basic.SuggestionHost; import org.chromium.chrome.browser.omnibox.suggestions.basic.SuggestionView.SuggestionViewDelegate; import org.chromium.chrome.browser.omnibox.suggestions.editurl.EditUrlSuggestionProcessor; import org.chromium.chrome.browser.profiles.Profile; @@ -87,6 +88,7 @@ private final Handler mHandler; private final BasicSuggestionProcessor mBasicSuggestionProcessor; private EditUrlSuggestionProcessor mEditUrlProcessor; + private final AnswerSuggestionProcessor mAnswerSuggestionProcessor; private ToolbarDataProvider mDataProvider; private boolean mNativeInitialized; @@ -145,6 +147,7 @@ mBasicSuggestionProcessor = new BasicSuggestionProcessor(mContext, this, textProvider); mEditUrlProcessor = new EditUrlSuggestionProcessor( delegate, (suggestion) -> onSelection(suggestion, 0)); + mAnswerSuggestionProcessor = new AnswerSuggestionProcessor(mContext, this); } /** @@ -262,7 +265,7 @@ mHandler.post(deferredRunnable); } mDeferredNativeRunnables.clear(); - mBasicSuggestionProcessor.onNativeInitialized(); + mAnswerSuggestionProcessor.onNativeInitialized(); } /** @@ -293,8 +296,9 @@ // a consequence the omnibox is unfocused). hideSuggestions(); } - mBasicSuggestionProcessor.onUrlFocusChange(hasFocus); if (mEditUrlProcessor != null) mEditUrlProcessor.onUrlFocusChange(hasFocus); + mAnswerSuggestionProcessor.onUrlFocusChange(hasFocus); + mBasicSuggestionProcessor.onUrlFocusChange(hasFocus); } /** @@ -642,7 +646,10 @@ * @return The appropriate suggestion processor for the provided suggestion. */ private SuggestionProcessor getProcessorForSuggestion(OmniboxSuggestion suggestion) { - if (mEditUrlProcessor != null && mEditUrlProcessor.doesProcessSuggestion(suggestion)) { + if (mAnswerSuggestionProcessor.doesProcessSuggestion(suggestion)) { + return mAnswerSuggestionProcessor; + } else if (mEditUrlProcessor != null + && mEditUrlProcessor.doesProcessSuggestion(suggestion)) { return mEditUrlProcessor; } return mBasicSuggestionProcessor;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/basic/AnswerSuggestionProcessor.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/basic/AnswerSuggestionProcessor.java new file mode 100644 index 0000000..b965b6f --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/basic/AnswerSuggestionProcessor.java
@@ -0,0 +1,233 @@ +// 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.omnibox.suggestions.basic; + +import android.content.Context; +import android.graphics.Bitmap; +import android.util.Pair; +import android.util.TypedValue; +import android.view.View; + +import org.chromium.base.ThreadUtils; +import org.chromium.chrome.browser.ChromeFeatureList; +import org.chromium.chrome.browser.omnibox.suggestions.AnswersImageFetcher; +import org.chromium.chrome.browser.omnibox.suggestions.AutocompleteCoordinator.SuggestionProcessor; +import org.chromium.chrome.browser.omnibox.suggestions.OmniboxSuggestion; +import org.chromium.chrome.browser.omnibox.suggestions.OmniboxSuggestionUiType; +import org.chromium.chrome.browser.omnibox.suggestions.SuggestionCommonProperties; +import org.chromium.chrome.browser.omnibox.suggestions.basic.SuggestionViewProperties.SuggestionIcon; +import org.chromium.chrome.browser.omnibox.suggestions.basic.SuggestionViewProperties.SuggestionTextContainer; +import org.chromium.components.omnibox.AnswerType; +import org.chromium.components.omnibox.SuggestionAnswer; +import org.chromium.ui.modelutil.PropertyModel; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** A class that handles model and view creation for the most commonly used omnibox suggestion. */ +public class AnswerSuggestionProcessor implements SuggestionProcessor { + private final Map<String, List<PropertyModel>> mPendingAnswerRequestUrls; + private final Context mContext; + private final SuggestionHost mSuggestionHost; + private final AnswersImageFetcher mImageFetcher; + private boolean mEnableNewAnswerLayout; + + /** + * @param context An Android context. + * @param suggestionHost A handle to the object using the suggestions. + */ + public AnswerSuggestionProcessor(Context context, SuggestionHost suggestionHost) { + mContext = context; + mSuggestionHost = suggestionHost; + mPendingAnswerRequestUrls = new HashMap<>(); + mImageFetcher = new AnswersImageFetcher(); + } + + @Override + public boolean doesProcessSuggestion(OmniboxSuggestion suggestion) { + return suggestion.hasAnswer(); + } + + /** + * Signals that native initialization has completed. + */ + public void onNativeInitialized() { + // Experiment: controls presence of certain answer icon types. + mEnableNewAnswerLayout = + ChromeFeatureList.isEnabled(ChromeFeatureList.OMNIBOX_NEW_ANSWER_LAYOUT); + } + + @Override + public int getViewTypeId() { + return OmniboxSuggestionUiType.DEFAULT; + } + + @Override + public PropertyModel createModelForSuggestion(OmniboxSuggestion suggestion) { + return new PropertyModel(SuggestionViewProperties.ALL_KEYS); + } + + @Override + public void populateModel(OmniboxSuggestion suggestion, PropertyModel model, int position) { + maybeFetchAnswerIcon(suggestion, model); + + model.set(SuggestionViewProperties.SUGGESTION_ICON_TYPE, + SuggestionViewProperties.SuggestionIcon.UNDEFINED); + model.set(SuggestionViewProperties.DELEGATE, + mSuggestionHost.createSuggestionViewDelegate(suggestion, position)); + + setStateForSuggestion(model, suggestion.getAnswer()); + } + + @Override + public void onUrlFocusChange(boolean hasFocus) { + if (!hasFocus) mImageFetcher.clearCache(); + } + + private void maybeFetchAnswerIcon(OmniboxSuggestion suggestion, PropertyModel model) { + ThreadUtils.assertOnUiThread(); + + // Attempting to fetch answer data before we have a profile to request it for. + if (mSuggestionHost.getCurrentProfile() == null) return; + + if (!suggestion.hasAnswer()) return; + final String url = suggestion.getAnswer().getSecondLine().getImage(); + if (url == null) return; + + // Do not make duplicate answer image requests for the same URL (to avoid generating + // duplicate bitmaps for the same image). + if (mPendingAnswerRequestUrls.containsKey(url)) { + mPendingAnswerRequestUrls.get(url).add(model); + return; + } + + List<PropertyModel> models = new ArrayList<>(); + models.add(model); + mPendingAnswerRequestUrls.put(url, models); + mImageFetcher.requestAnswersImage(mSuggestionHost.getCurrentProfile(), url, + new AnswersImageFetcher.AnswersImageObserver() { + @Override + public void onAnswersImageChanged(Bitmap bitmap) { + ThreadUtils.assertOnUiThread(); + + List<PropertyModel> models = mPendingAnswerRequestUrls.remove(url); + boolean didUpdate = false; + for (int i = 0; i < models.size(); i++) { + PropertyModel model = models.get(i); + if (!mSuggestionHost.isActiveModel(model)) continue; + model.set(SuggestionViewProperties.ANSWER_IMAGE, bitmap); + didUpdate = true; + } + if (didUpdate) mSuggestionHost.notifyPropertyModelsChanged(); + } + }); + } + + /** + * Sets both lines of the Omnibox suggestion based on an Answers in Suggest result. + */ + private void setStateForSuggestion(PropertyModel model, SuggestionAnswer answer) { + float density = mContext.getResources().getDisplayMetrics().density; + SuggestionAnswer.ImageLine firstLine = answer.getFirstLine(); + SuggestionAnswer.ImageLine secondLine = answer.getSecondLine(); + int numAnswerLines = parseNumAnswerLines(secondLine.getTextFields()); + if (numAnswerLines == -1) numAnswerLines = 1; + model.set(SuggestionViewProperties.IS_ANSWER, true); + + if (mEnableNewAnswerLayout) { + model.set(SuggestionViewProperties.TEXT_LINE_2_SIZING, + Pair.create(TypedValue.COMPLEX_UNIT_SP, + (float) AnswerTextBuilder.getMaxTextHeightSp(firstLine))); + model.set(SuggestionViewProperties.TEXT_LINE_2_TEXT, + new SuggestionTextContainer( + AnswerTextBuilder.buildSpannable(firstLine, density))); + + model.set(SuggestionViewProperties.TEXT_LINE_1_SIZING, + Pair.create(TypedValue.COMPLEX_UNIT_SP, + (float) AnswerTextBuilder.getMaxTextHeightSp(secondLine))); + model.set(SuggestionViewProperties.TEXT_LINE_1_TEXT, + new SuggestionTextContainer( + AnswerTextBuilder.buildSpannable(secondLine, density))); + model.set(SuggestionViewProperties.TEXT_LINE_1_MAX_LINES, numAnswerLines); + model.set(SuggestionViewProperties.TEXT_LINE_2_MAX_LINES, 1); + model.set(SuggestionViewProperties.TEXT_LINE_2_TEXT_COLOR, + SuggestionViewViewBinder.getStandardFontColor( + mContext, model.get(SuggestionCommonProperties.USE_DARK_COLORS))); + model.set(SuggestionViewProperties.TEXT_LINE_1_TEXT_DIRECTION, + View.TEXT_DIRECTION_INHERIT); + } else { + model.set(SuggestionViewProperties.TEXT_LINE_1_SIZING, + Pair.create(TypedValue.COMPLEX_UNIT_SP, + (float) AnswerTextBuilder.getMaxTextHeightSp(firstLine))); + model.set(SuggestionViewProperties.TEXT_LINE_1_TEXT, + new SuggestionTextContainer( + AnswerTextBuilder.buildSpannable(firstLine, density))); + + model.set(SuggestionViewProperties.TEXT_LINE_2_SIZING, + Pair.create(TypedValue.COMPLEX_UNIT_SP, + (float) AnswerTextBuilder.getMaxTextHeightSp(secondLine))); + model.set(SuggestionViewProperties.TEXT_LINE_2_TEXT, + new SuggestionTextContainer( + AnswerTextBuilder.buildSpannable(secondLine, density))); + model.set(SuggestionViewProperties.TEXT_LINE_1_MAX_LINES, 1); + model.set(SuggestionViewProperties.TEXT_LINE_2_MAX_LINES, numAnswerLines); + model.set(SuggestionViewProperties.TEXT_LINE_2_TEXT_COLOR, + SuggestionViewViewBinder.getStandardFontColor( + mContext, model.get(SuggestionCommonProperties.USE_DARK_COLORS))); + model.set(SuggestionViewProperties.TEXT_LINE_2_TEXT_DIRECTION, + View.TEXT_DIRECTION_INHERIT); + } + + model.set(SuggestionViewProperties.HAS_ANSWER_IMAGE, secondLine.hasImage()); + + model.set(SuggestionViewProperties.REFINABLE, true); + + @SuggestionIcon + int icon = SuggestionIcon.MAGNIFIER; + if (mEnableNewAnswerLayout) { + switch (answer.getType()) { + case AnswerType.DICTIONARY: + icon = SuggestionIcon.DICTIONARY; + break; + case AnswerType.FINANCE: + icon = SuggestionIcon.FINANCE; + break; + case AnswerType.KNOWLEDGE_GRAPH: + icon = SuggestionIcon.KNOWLEDGE; + break; + case AnswerType.SUNRISE: + icon = SuggestionIcon.SUNRISE; + break; + case AnswerType.TRANSLATION: + icon = SuggestionIcon.TRANSLATION; + break; + case AnswerType.WEATHER: + icon = SuggestionIcon.WEATHER; + break; + case AnswerType.WHEN_IS: + icon = SuggestionIcon.EVENT; + break; + case AnswerType.CURRENCY: + icon = SuggestionIcon.CURRENCY; + break; + case AnswerType.SPORTS: + icon = SuggestionIcon.SPORTS; + } + } + + model.set(SuggestionViewProperties.SUGGESTION_ICON_TYPE, icon); + } + + private static int parseNumAnswerLines(List<SuggestionAnswer.TextField> textFields) { + for (int i = 0; i < textFields.size(); i++) { + if (textFields.get(i).hasNumLines()) { + return Math.min(3, textFields.get(i).getNumLines()); + } + } + return -1; + } +}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/basic/BasicSuggestionProcessor.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/basic/BasicSuggestionProcessor.java index 0a7b049..b0e7daf72 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/basic/BasicSuggestionProcessor.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/basic/BasicSuggestionProcessor.java
@@ -5,7 +5,6 @@ package org.chromium.chrome.browser.omnibox.suggestions.basic; import android.content.Context; -import android.graphics.Bitmap; import android.text.Spannable; import android.text.SpannableString; import android.text.TextUtils; @@ -14,64 +13,25 @@ import android.util.TypedValue; import android.view.View; -import org.chromium.base.ThreadUtils; -import org.chromium.chrome.browser.ChromeFeatureList; import org.chromium.chrome.browser.omnibox.MatchClassificationStyle; import org.chromium.chrome.browser.omnibox.OmniboxSuggestionType; import org.chromium.chrome.browser.omnibox.UrlBarEditingTextStateProvider; -import org.chromium.chrome.browser.omnibox.suggestions.AnswersImageFetcher; import org.chromium.chrome.browser.omnibox.suggestions.AutocompleteCoordinator.SuggestionProcessor; import org.chromium.chrome.browser.omnibox.suggestions.OmniboxSuggestion; import org.chromium.chrome.browser.omnibox.suggestions.OmniboxSuggestionUiType; import org.chromium.chrome.browser.omnibox.suggestions.SuggestionCommonProperties; -import org.chromium.chrome.browser.omnibox.suggestions.basic.SuggestionView.SuggestionViewDelegate; import org.chromium.chrome.browser.omnibox.suggestions.basic.SuggestionViewProperties.SuggestionIcon; import org.chromium.chrome.browser.omnibox.suggestions.basic.SuggestionViewProperties.SuggestionTextContainer; -import org.chromium.chrome.browser.profiles.Profile; -import org.chromium.components.omnibox.AnswerType; -import org.chromium.components.omnibox.SuggestionAnswer; import org.chromium.ui.modelutil.PropertyModel; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; -import java.util.Map; -/** A class that handles model and view creation for the most commonly used omnibox suggestion. */ +/** A class that handles model and view creation for the basic omnibox suggestions. */ public class BasicSuggestionProcessor implements SuggestionProcessor { - /** A mechanism for creating {@link SuggestionViewDelegate}s. */ - public interface SuggestionHost { - /** - * @param suggestion The suggestion to create the delegate for. - * @param position The position of the delegate in the list. - * @return A delegate for the specified suggestion. - */ - SuggestionViewDelegate createSuggestionViewDelegate( - OmniboxSuggestion suggestion, int position); - - /** - * @param model The model to check. - * @return Whether the model is active in the list being shown. - */ - boolean isActiveModel(PropertyModel model); - - /** - * Notify the host that the suggestion models have changed. - */ - void notifyPropertyModelsChanged(); - - /** - * @return The browser's active profile. - */ - Profile getCurrentProfile(); - } - - private final Map<String, List<PropertyModel>> mPendingAnswerRequestUrls; private final Context mContext; private final SuggestionHost mSuggestionHost; - private final AnswersImageFetcher mImageFetcher; private final UrlBarEditingTextStateProvider mUrlBarEditingTextProvider; - private boolean mEnableNewAnswerLayout; /** * @param context An Android context. @@ -82,8 +42,6 @@ UrlBarEditingTextStateProvider editingTextProvider) { mContext = context; mSuggestionHost = suggestionHost; - mPendingAnswerRequestUrls = new HashMap<>(); - mImageFetcher = new AnswersImageFetcher(); mUrlBarEditingTextProvider = editingTextProvider; } @@ -92,15 +50,6 @@ return true; } - /** - * Signals that native initialization has completed. - */ - public void onNativeInitialized() { - // Experiment: controls presence of certain answer icon types. - mEnableNewAnswerLayout = - ChromeFeatureList.isEnabled(ChromeFeatureList.OMNIBOX_NEW_ANSWER_LAYOUT); - } - @Override public int getViewTypeId() { return OmniboxSuggestionUiType.DEFAULT; @@ -113,162 +62,18 @@ @Override public void populateModel(OmniboxSuggestion suggestion, PropertyModel model, int position) { - maybeFetchAnswerIcon(suggestion, model); - model.set(SuggestionViewProperties.SUGGESTION_ICON_TYPE, SuggestionViewProperties.SuggestionIcon.UNDEFINED); model.set(SuggestionViewProperties.DELEGATE, mSuggestionHost.createSuggestionViewDelegate(suggestion, position)); - // Suggestions with attached answers are rendered with rich results regardless of which - // suggestion type they are. - if (suggestion.hasAnswer()) { - setStateForAnswerSuggestion(model, suggestion.getAnswer()); - } else { - setStateForTextSuggestion(model, suggestion); - } + setStateForSuggestion(model, suggestion); } @Override - public void onUrlFocusChange(boolean hasFocus) { - if (!hasFocus) mImageFetcher.clearCache(); - } + public void onUrlFocusChange(boolean hasFocus) {} - private void maybeFetchAnswerIcon(OmniboxSuggestion suggestion, PropertyModel model) { - ThreadUtils.assertOnUiThread(); - - // Attempting to fetch answer data before we have a profile to request it for. - if (mSuggestionHost.getCurrentProfile() == null) return; - - if (!suggestion.hasAnswer()) return; - final String url = suggestion.getAnswer().getSecondLine().getImage(); - if (url == null) return; - - // Do not make duplicate answer image requests for the same URL (to avoid generating - // duplicate bitmaps for the same image). - if (mPendingAnswerRequestUrls.containsKey(url)) { - mPendingAnswerRequestUrls.get(url).add(model); - return; - } - - List<PropertyModel> models = new ArrayList<>(); - models.add(model); - mPendingAnswerRequestUrls.put(url, models); - mImageFetcher.requestAnswersImage(mSuggestionHost.getCurrentProfile(), url, - new AnswersImageFetcher.AnswersImageObserver() { - @Override - public void onAnswersImageChanged(Bitmap bitmap) { - ThreadUtils.assertOnUiThread(); - - List<PropertyModel> models = mPendingAnswerRequestUrls.remove(url); - boolean didUpdate = false; - for (int i = 0; i < models.size(); i++) { - PropertyModel model = models.get(i); - if (!mSuggestionHost.isActiveModel(model)) continue; - model.set(SuggestionViewProperties.ANSWER_IMAGE, bitmap); - didUpdate = true; - } - if (didUpdate) mSuggestionHost.notifyPropertyModelsChanged(); - } - }); - } - - /** - * Sets both lines of the Omnibox suggestion based on an Answers in Suggest result. - */ - private void setStateForAnswerSuggestion(PropertyModel model, SuggestionAnswer answer) { - float density = mContext.getResources().getDisplayMetrics().density; - SuggestionAnswer.ImageLine firstLine = answer.getFirstLine(); - SuggestionAnswer.ImageLine secondLine = answer.getSecondLine(); - int numAnswerLines = parseNumAnswerLines(secondLine.getTextFields()); - if (numAnswerLines == -1) numAnswerLines = 1; - model.set(SuggestionViewProperties.IS_ANSWER, true); - - if (mEnableNewAnswerLayout) { - model.set(SuggestionViewProperties.TEXT_LINE_2_SIZING, - Pair.create(TypedValue.COMPLEX_UNIT_SP, - (float) AnswerTextBuilder.getMaxTextHeightSp(firstLine))); - model.set(SuggestionViewProperties.TEXT_LINE_2_TEXT, - new SuggestionTextContainer( - AnswerTextBuilder.buildSpannable(firstLine, density))); - - model.set(SuggestionViewProperties.TEXT_LINE_1_SIZING, - Pair.create(TypedValue.COMPLEX_UNIT_SP, - (float) AnswerTextBuilder.getMaxTextHeightSp(secondLine))); - model.set(SuggestionViewProperties.TEXT_LINE_1_TEXT, - new SuggestionTextContainer( - AnswerTextBuilder.buildSpannable(secondLine, density))); - model.set(SuggestionViewProperties.TEXT_LINE_1_MAX_LINES, numAnswerLines); - model.set(SuggestionViewProperties.TEXT_LINE_2_MAX_LINES, 1); - model.set(SuggestionViewProperties.TEXT_LINE_2_TEXT_COLOR, - SuggestionViewViewBinder.getStandardFontColor( - mContext, model.get(SuggestionCommonProperties.USE_DARK_COLORS))); - model.set(SuggestionViewProperties.TEXT_LINE_1_TEXT_DIRECTION, - View.TEXT_DIRECTION_INHERIT); - } else { - model.set(SuggestionViewProperties.TEXT_LINE_1_SIZING, - Pair.create(TypedValue.COMPLEX_UNIT_SP, - (float) AnswerTextBuilder.getMaxTextHeightSp(firstLine))); - model.set(SuggestionViewProperties.TEXT_LINE_1_TEXT, - new SuggestionTextContainer( - AnswerTextBuilder.buildSpannable(firstLine, density))); - - model.set(SuggestionViewProperties.TEXT_LINE_2_SIZING, - Pair.create(TypedValue.COMPLEX_UNIT_SP, - (float) AnswerTextBuilder.getMaxTextHeightSp(secondLine))); - model.set(SuggestionViewProperties.TEXT_LINE_2_TEXT, - new SuggestionTextContainer( - AnswerTextBuilder.buildSpannable(secondLine, density))); - model.set(SuggestionViewProperties.TEXT_LINE_1_MAX_LINES, 1); - model.set(SuggestionViewProperties.TEXT_LINE_2_MAX_LINES, numAnswerLines); - model.set(SuggestionViewProperties.TEXT_LINE_2_TEXT_COLOR, - SuggestionViewViewBinder.getStandardFontColor( - mContext, model.get(SuggestionCommonProperties.USE_DARK_COLORS))); - model.set(SuggestionViewProperties.TEXT_LINE_2_TEXT_DIRECTION, - View.TEXT_DIRECTION_INHERIT); - } - - model.set(SuggestionViewProperties.HAS_ANSWER_IMAGE, secondLine.hasImage()); - - model.set(SuggestionViewProperties.REFINABLE, true); - - @SuggestionIcon - int icon = SuggestionIcon.MAGNIFIER; - if (mEnableNewAnswerLayout) { - switch (answer.getType()) { - case AnswerType.DICTIONARY: - icon = SuggestionIcon.DICTIONARY; - break; - case AnswerType.FINANCE: - icon = SuggestionIcon.FINANCE; - break; - case AnswerType.KNOWLEDGE_GRAPH: - icon = SuggestionIcon.KNOWLEDGE; - break; - case AnswerType.SUNRISE: - icon = SuggestionIcon.SUNRISE; - break; - case AnswerType.TRANSLATION: - icon = SuggestionIcon.TRANSLATION; - break; - case AnswerType.WEATHER: - icon = SuggestionIcon.WEATHER; - break; - case AnswerType.WHEN_IS: - icon = SuggestionIcon.EVENT; - break; - case AnswerType.CURRENCY: - icon = SuggestionIcon.CURRENCY; - break; - case AnswerType.SPORTS: - icon = SuggestionIcon.SPORTS; - } - } - - model.set(SuggestionViewProperties.SUGGESTION_ICON_TYPE, icon); - } - - private void setStateForTextSuggestion(PropertyModel model, OmniboxSuggestion suggestion) { + private void setStateForSuggestion(PropertyModel model, OmniboxSuggestion suggestion) { int suggestionType = suggestion.getType(); @SuggestionIcon int suggestionIcon; @@ -406,15 +211,6 @@ return str; } - private static int parseNumAnswerLines(List<SuggestionAnswer.TextField> textFields) { - for (int i = 0; i < textFields.size(); i++) { - if (textFields.get(i).hasNumLines()) { - return Math.min(3, textFields.get(i).getNumLines()); - } - } - return -1; - } - private static boolean applyHighlightToMatchRegions( Spannable str, List<OmniboxSuggestion.MatchClassification> classifications) { boolean hasMatch = false;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/basic/SuggestionHost.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/basic/SuggestionHost.java new file mode 100644 index 0000000..886fce3 --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/basic/SuggestionHost.java
@@ -0,0 +1,36 @@ +// 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.omnibox.suggestions.basic; + +import org.chromium.chrome.browser.omnibox.suggestions.OmniboxSuggestion; +import org.chromium.chrome.browser.omnibox.suggestions.basic.SuggestionView.SuggestionViewDelegate; +import org.chromium.chrome.browser.profiles.Profile; +import org.chromium.ui.modelutil.PropertyModel; + +/** A mechanism for creating {@link SuggestionViewDelegate}s. */ +public interface SuggestionHost { + /** + * @param suggestion The suggestion to create the delegate for. + * @param position The position of the delegate in the list. + * @return A delegate for the specified suggestion. + */ + SuggestionViewDelegate createSuggestionViewDelegate(OmniboxSuggestion suggestion, int position); + + /** + * @param model The model to check. + * @return Whether the model is active in the list being shown. + */ + boolean isActiveModel(PropertyModel model); + + /** + * Notify the host that the suggestion models have changed. + */ + void notifyPropertyModelsChanged(); + + /** + * @return The browser's active profile. + */ + Profile getCurrentProfile(); +}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsRecyclerView.java b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsRecyclerView.java index 999b6cb2..f56c2d9a 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsRecyclerView.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsRecyclerView.java
@@ -82,6 +82,8 @@ /** The context menu manager for this view. */ private ContextMenuManager mContextMenuManager; + private boolean mIsCardBeingSwiped; + public SuggestionsRecyclerView(Context context) { this(context, null); } @@ -381,6 +383,8 @@ @Override public void onChildDraw(Canvas c, RecyclerView recyclerView, ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) { + mIsCardBeingSwiped = isCurrentlyActive && dX != 0.f; + // In some cases a removed child may call this method when unrelated items are // interacted with (https://crbug.com/664466, b/32900699), but in that case // getSiblingDismissalViewHolders() below will return an empty list. @@ -393,6 +397,14 @@ } } + /** + * Tells if one of card views is being swiped now. + * @return {@code true} if a card view is being swiped. + */ + public boolean isCardBeingSwiped() { + return mIsCardBeingSwiped; + } + private List<ViewHolder> getDismissalGroupViewHolders(ViewHolder viewHolder) { int position = viewHolder.getAdapterPosition(); if (position == NO_POSITION) return Collections.emptyList();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/Tab.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/Tab.java index f70c5d6..adbe5ef 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tab/Tab.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/Tab.java
@@ -6,7 +6,6 @@ import android.annotation.SuppressLint; import android.app.Activity; -import android.app.Application; import android.content.Context; import android.content.Intent; import android.content.res.Resources; @@ -1052,6 +1051,7 @@ maybeShowNativePage(nativePage.getUrl(), true); } NativePageAssassin.getInstance().tabShown(this); + TabImportanceManager.tabShown(this); // If the page is still loading, update the progress bar (otherwise it would not show // until the renderer notifies of new progress being made). @@ -1095,7 +1095,7 @@ } } - public final void setImportance(@ChildProcessImportance int importance) { + /* package */ final void setImportance(@ChildProcessImportance int importance) { if (mImportance == importance) return; mImportance = importance; WebContents webContents = getWebContents(); @@ -1681,6 +1681,8 @@ destroyNativePageInternal(currentNativePage); destroyWebContents(true); + TabImportanceManager.tabDestroyed(this); + // Destroys the native tab after destroying the ContentView but before destroying the // InfoBarContainer. The native tab should be destroyed before the infobar container as // destroying the native tab cleanups up any remaining infobars. The infobar container @@ -2132,7 +2134,7 @@ } private static Rect getEstimatedContentSize(Context context) { - return ExternalPrerenderHandler.estimateContentSize((Application) context, false); + return ExternalPrerenderHandler.estimateContentSize(context, false); } /** This is currently called when committing a pre-rendered page. */
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabImportanceManager.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabImportanceManager.java new file mode 100644 index 0000000..e38137d --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabImportanceManager.java
@@ -0,0 +1,45 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.tab; + +import org.chromium.base.ThreadUtils; +import org.chromium.content_public.browser.ChildProcessImportance; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +/** + * Manages the importance for all Tabs in the same process. Ensures that at least one tab is + * important, and unless multiple tabs are simultaneously visible, only one is important. + */ +public class TabImportanceManager { + // Typically no more than 2 visible tabs at once (multi-window). + private static final List<Tab> sImportantTabs = new ArrayList<>(2); + + public static void tabShown(Tab shownTab) { + ThreadUtils.assertOnUiThread(); + shownTab.setImportance(ChildProcessImportance.MODERATE); + // Shown tabs should always be important, but hidden tabs should only be normal if there's + // at least one important tab for two reasons: + // 1. We could be switching between tabs within the same process and don't want the process + // to be killed while switching. + // 2. We want the most recently used tab to stay alive. + Iterator<Tab> it = sImportantTabs.iterator(); + while (it.hasNext()) { + Tab importantTab = it.next(); + if (importantTab.isHidden()) { + importantTab.setImportance(ChildProcessImportance.NORMAL); + it.remove(); + } + } + if (!sImportantTabs.contains(shownTab)) sImportantTabs.add(shownTab); + } + + public static void tabDestroyed(Tab tab) { + ThreadUtils.assertOnUiThread(); + sImportantTabs.remove(tab); + } +}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelSelectorImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelSelectorImpl.java index 87acda5..9326962 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelSelectorImpl.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelSelectorImpl.java
@@ -14,7 +14,6 @@ import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.tab.Tab.TabHidingType; import org.chromium.chrome.browser.tabmodel.TabPersistentStore.TabPersistentStoreObserver; -import org.chromium.content_public.browser.ChildProcessImportance; import org.chromium.content_public.browser.LoadUrlParams; import java.util.concurrent.atomic.AtomicBoolean; @@ -341,7 +340,6 @@ public void requestToShowTab(Tab tab, @TabSelectionType int type) { boolean isFromExternalApp = tab != null && tab.getLaunchType() == TabLaunchType.FROM_EXTERNAL_APP; - Tab tabToDropImportance = null; if (mVisibleTab != tab && tab != null && !tab.isNativePage()) { TabModelImpl.startTabSwitchLatencyTiming(type); } @@ -357,14 +355,10 @@ mVisibleTab.hide(TabHidingType.CHANGED_TABS); mTabSaver.addTabToSaveQueue(mVisibleTab); } - tabToDropImportance = mVisibleTab; mVisibleTab = null; } if (tab == null) { - if (tabToDropImportance != null) { - tabToDropImportance.setImportance(ChildProcessImportance.NORMAL); - } notifyChanged(); return; } @@ -377,9 +371,6 @@ // |tabToDropImportance| must be null, so no need to drop importance. return; } - if (tabToDropImportance == null) { - tabToDropImportance = mVisibleTab; - } mVisibleTab = tab; // Don't execute the tab display part if Chrome has just been sent to background. This @@ -389,13 +380,6 @@ tab.show(type); mUma.onShowTab(tab.getId(), tab.isBeingRestored()); } - - // Always raise importance before lowering it on old Tab because in case these two Tabs - // are hosted by the same process, the process importance is not dropped momentarily. - mVisibleTab.setImportance(ChildProcessImportance.MODERATE); - if (tabToDropImportance != null) { - tabToDropImportance.setImportance(ChildProcessImportance.NORMAL); - } } private void cacheTabBitmap(Tab tabToCache) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/HomeButton.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/HomeButton.java index 5d3907ea..8e80a46 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/HomeButton.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/HomeButton.java
@@ -19,19 +19,19 @@ import org.chromium.chrome.R; import org.chromium.chrome.browser.ActivityTabProvider; import org.chromium.chrome.browser.ActivityTabProvider.ActivityTabTabObserver; +import org.chromium.chrome.browser.ThemeColorProvider; +import org.chromium.chrome.browser.ThemeColorProvider.TintObserver; import org.chromium.chrome.browser.ntp.NewTabPage; import org.chromium.chrome.browser.partnercustomizations.HomepageManager; import org.chromium.chrome.browser.tab.Tab; -import org.chromium.chrome.browser.toolbar.ThemeColorProvider.ThemeColorObserver; import org.chromium.chrome.browser.util.FeatureUtilities; import org.chromium.ui.widget.ChromeImageButton; /** * The home button. */ -public class HomeButton extends ChromeImageButton implements ThemeColorObserver, - OnCreateContextMenuListener, - MenuItem.OnMenuItemClickListener { +public class HomeButton extends ChromeImageButton + implements TintObserver, OnCreateContextMenuListener, MenuItem.OnMenuItemClickListener { private static final int ID_REMOVE = 0; /** A provider that notifies components when the theme color changes.*/ @@ -55,7 +55,7 @@ public void destroy() { if (mThemeColorProvider != null) { - mThemeColorProvider.removeObserver(this); + mThemeColorProvider.removeTintObserver(this); mThemeColorProvider = null; } if (mActivityTabTabObserver != null) { @@ -66,11 +66,11 @@ public void setThemeColorProvider(ThemeColorProvider themeColorProvider) { mThemeColorProvider = themeColorProvider; - mThemeColorProvider.addObserver(this); + mThemeColorProvider.addTintObserver(this); } @Override - public void onThemeColorChanged(ColorStateList tint, int primaryColor) { + public void onTintChanged(ColorStateList tint, boolean useLight) { ApiCompatibilityUtils.setImageTintList(this, tint); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/MenuButton.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/MenuButton.java index 0188e10..9e14b33 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/MenuButton.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/MenuButton.java
@@ -15,14 +15,14 @@ import org.chromium.base.ApiCompatibilityUtils; import org.chromium.chrome.R; +import org.chromium.chrome.browser.ThemeColorProvider; +import org.chromium.chrome.browser.ThemeColorProvider.TintObserver; import org.chromium.chrome.browser.omaha.UpdateMenuItemHelper; -import org.chromium.chrome.browser.toolbar.ThemeColorProvider.ThemeColorObserver; -import org.chromium.chrome.browser.util.ColorUtils; /** * The overflow menu button. */ -public class MenuButton extends FrameLayout implements ThemeColorObserver { +public class MenuButton extends FrameLayout implements TintObserver { /** The {@link ImageButton} for the menu button. */ private ImageButton mMenuImageButton; @@ -151,18 +151,18 @@ public void setThemeColorProvider(ThemeColorProvider themeColorProvider) { mThemeColorProvider = themeColorProvider; - mThemeColorProvider.addObserver(this); + mThemeColorProvider.addTintObserver(this); } @Override - public void onThemeColorChanged(ColorStateList tintList, int primaryColor) { + public void onTintChanged(ColorStateList tintList, boolean useLight) { ApiCompatibilityUtils.setImageTintList(mMenuImageButton, tintList); - setUseLightDrawables(ColorUtils.shouldUseLightForegroundOnBackground(primaryColor)); + setUseLightDrawables(useLight); } public void destroy() { if (mThemeColorProvider != null) { - mThemeColorProvider.removeObserver(this); + mThemeColorProvider.removeTintObserver(this); mThemeColorProvider = null; } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/TabSwitcherButtonCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/TabSwitcherButtonCoordinator.java index d2f0130..9becd72b 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/TabSwitcherButtonCoordinator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/TabSwitcherButtonCoordinator.java
@@ -9,11 +9,12 @@ import android.view.ViewGroup; import org.chromium.chrome.R; +import org.chromium.chrome.browser.ThemeColorProvider; +import org.chromium.chrome.browser.ThemeColorProvider.TintObserver; import org.chromium.chrome.browser.tabmodel.TabModelSelector; import org.chromium.chrome.browser.tabmodel.TabModelSelectorObserver; import org.chromium.chrome.browser.tabmodel.TabModelSelectorTabModelObserver; import org.chromium.chrome.browser.toolbar.TabCountProvider.TabCountObserver; -import org.chromium.chrome.browser.toolbar.ThemeColorProvider.ThemeColorObserver; import org.chromium.chrome.browser.util.AccessibilityUtil; import org.chromium.ui.modelutil.PropertyModel; import org.chromium.ui.modelutil.PropertyModelChangeProcessor; @@ -36,7 +37,7 @@ private TabModelSelectorTabModelObserver mTabModelSelectorTabModelObserver; private ThemeColorProvider mThemeColorProvider; - private ThemeColorObserver mThemeColorObserver; + private TintObserver mTintObserver; private TabCountProvider mTabCountProvider; private TabCountObserver mTabCountObserver; @@ -65,13 +66,13 @@ public void setThemeColorProvider(ThemeColorProvider themeColorProvider) { mThemeColorProvider = themeColorProvider; - mThemeColorObserver = new ThemeColorObserver() { + mTintObserver = new TintObserver() { @Override - public void onThemeColorChanged(ColorStateList tint, int primaryColor) { + public void onTintChanged(ColorStateList tint, boolean useLight) { mTabSwitcherButtonModel.set(TabSwitcherButtonProperties.TINT, tint); } }; - mThemeColorProvider.addObserver(mThemeColorObserver); + mThemeColorProvider.addTintObserver(mTintObserver); } public void setTabCountProvider(TabCountProvider tabCountProvider) { @@ -87,7 +88,7 @@ public void destroy() { if (mThemeColorProvider != null) { - mThemeColorProvider.removeObserver(mThemeColorObserver); + mThemeColorProvider.removeTintObserver(mTintObserver); mThemeColorProvider = null; } if (mTabCountProvider != null) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ThemeColorProvider.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ThemeColorProvider.java deleted file mode 100644 index eac9716..0000000 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ThemeColorProvider.java +++ /dev/null
@@ -1,29 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package org.chromium.chrome.browser.toolbar; - -import android.content.res.ColorStateList; - -/** - * An interface that provides the current theme color. - */ -public interface ThemeColorProvider { - /** - * An interface to be notified about changes to the theme color. - */ - public interface ThemeColorObserver { - void onThemeColorChanged(ColorStateList tint, int primaryColor); - } - - /** - * @param observer An observer to be notified of theme color changes. - */ - void addObserver(ThemeColorObserver observer); - - /** - * @param observer Remove the observer. - */ - void removeObserver(ThemeColorObserver observer); -}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java index a1c6d3bc..155447f5 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java
@@ -33,6 +33,8 @@ import org.chromium.chrome.browser.ChromeActivity; import org.chromium.chrome.browser.ChromeTabbedActivity; import org.chromium.chrome.browser.TabLoadStatus; +import org.chromium.chrome.browser.ThemeColorProvider; +import org.chromium.chrome.browser.ThemeColorProvider.ThemeColorObserver; import org.chromium.chrome.browser.UrlConstants; import org.chromium.chrome.browser.WindowDelegate; import org.chromium.chrome.browser.appmenu.AppMenuButtonHelper; @@ -92,7 +94,6 @@ import org.chromium.chrome.browser.toolbar.top.TopToolbarCoordinator; import org.chromium.chrome.browser.toolbar.top.ViewShiftingActionBarDelegate; import org.chromium.chrome.browser.translate.TranslateBridge; -import org.chromium.chrome.browser.util.ColorUtils; import org.chromium.chrome.browser.util.FeatureUtilities; import org.chromium.chrome.browser.widget.ScrimView; import org.chromium.chrome.browser.widget.ScrimView.ScrimObserver; @@ -122,7 +123,8 @@ * Contains logic for managing the toolbar visual component. This class manages the interactions * with the rest of the application to ensure the toolbar is always visually up to date. */ -public class ToolbarManager implements ScrimObserver, ToolbarTabController, UrlFocusChangeListener { +public class ToolbarManager + implements ScrimObserver, ToolbarTabController, UrlFocusChangeListener, ThemeColorObserver { /** * Handle UI updates of menu icons. Only applicable for phones. */ @@ -168,6 +170,7 @@ private final AsyncViewProvider<ToolbarLayout> mToolbarProvider; private final IncognitoStateProvider mIncognitoStateProvider; private final TabCountProvider mTabCountProvider; + private final ThemeColorProvider mThemeColorProvider; private TopToolbarCoordinator mToolbar; private final ToolbarControlContainer mControlContainer; @@ -235,7 +238,8 @@ */ public ToolbarManager(ChromeActivity activity, ToolbarControlContainer controlContainer, final AppMenuHandler menuHandler, AppMenuPropertiesDelegate appMenuPropertiesDelegate, - Invalidator invalidator, Callback<Boolean> urlFocusChangedCallback) { + Invalidator invalidator, Callback<Boolean> urlFocusChangedCallback, + ThemeColorProvider themeColorProvider) { mActivity = activity; mActionBarDelegate = new ViewShiftingActionBarDelegate(activity, controlContainer); @@ -301,6 +305,8 @@ mToolbarProvider.whenLoaded((toolbar) -> onToolbarInflationComplete(menuHandler, appMenuPropertiesDelegate, invalidator)); + mThemeColorProvider = themeColorProvider; + mThemeColorProvider.addThemeColorObserver(this); } @Override @@ -1173,6 +1179,8 @@ mLocationBar.removeUrlFocusChangeListener(mLocationBarFocusObserver); mLocationBarFocusObserver = null; } + + if (mThemeColorProvider != null) mThemeColorProvider.removeThemeColorObserver(this); } /** @@ -1412,7 +1420,8 @@ * @param color The primary color for the current tab. * @param shouldAnimate Whether the change of color should be animated. */ - public void updatePrimaryColor(int color, boolean shouldAnimate) { + @Override + public void onThemeColorChanged(int color, boolean shouldAnimate) { if (!mShouldUpdateToolbarPrimaryColor) return; boolean colorChanged = mCurrentThemeColor != color; @@ -1652,11 +1661,6 @@ } if (tab != null) tab.addObserver(mTabObserver); } - int defaultPrimaryColor = - ColorUtils.getDefaultThemeColor(mActivity.getResources(), isIncognito); - int primaryColor = - tab != null ? TabThemeColorHelper.getColor(tab) : defaultPrimaryColor; - updatePrimaryColor(primaryColor, false); mToolbar.onTabOrModelChanged();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomToolbarNewTabButton.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomToolbarNewTabButton.java index 56a1ad5..6cfab10 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomToolbarNewTabButton.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomToolbarNewTabButton.java
@@ -16,18 +16,19 @@ import org.chromium.base.ApiCompatibilityUtils; import org.chromium.chrome.R; import org.chromium.chrome.browser.ChromeFeatureList; +import org.chromium.chrome.browser.ThemeColorProvider; +import org.chromium.chrome.browser.ThemeColorProvider.ThemeColorObserver; +import org.chromium.chrome.browser.ThemeColorProvider.TintObserver; import org.chromium.chrome.browser.toolbar.IncognitoStateProvider; import org.chromium.chrome.browser.toolbar.IncognitoStateProvider.IncognitoStateObserver; -import org.chromium.chrome.browser.toolbar.ThemeColorProvider; -import org.chromium.chrome.browser.toolbar.ThemeColorProvider.ThemeColorObserver; import org.chromium.chrome.browser.util.ColorUtils; import org.chromium.ui.widget.ChromeImageButton; /** * The tab switcher new tab button. */ -class BottomToolbarNewTabButton - extends ChromeImageButton implements IncognitoStateObserver, ThemeColorObserver { +class BottomToolbarNewTabButton extends ChromeImageButton + implements IncognitoStateObserver, ThemeColorObserver, TintObserver { /** The gray pill background behind the plus icon. */ private final Drawable mBackground; @@ -62,7 +63,8 @@ mIncognitoStateProvider = null; } if (mThemeColorProvider != null) { - mThemeColorProvider.removeObserver(this); + mThemeColorProvider.removeThemeColorObserver(this); + mThemeColorProvider.removeTintObserver(this); mThemeColorProvider = null; } } @@ -88,14 +90,19 @@ void setThemeColorProvider(ThemeColorProvider themeColorProvider) { mThemeColorProvider = themeColorProvider; - mThemeColorProvider.addObserver(this); + mThemeColorProvider.addThemeColorObserver(this); + mThemeColorProvider.addTintObserver(this); } @Override - public void onThemeColorChanged(ColorStateList tint, int primaryColor) { - ApiCompatibilityUtils.setImageTintList(this, tint); + public void onThemeColorChanged(int primaryColor, boolean shouldAnimate) { mBackground.setColorFilter( ColorUtils.getTextBoxColorForToolbarBackground(mResources, false, primaryColor), PorterDuff.Mode.SRC_IN); } + + @Override + public void onTintChanged(ColorStateList tint, boolean useLight) { + ApiCompatibilityUtils.setImageTintList(this, tint); + } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomToolbarThemeColorProvider.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomToolbarThemeColorProvider.java index f0b39ca..69cdb44 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomToolbarThemeColorProvider.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomToolbarThemeColorProvider.java
@@ -5,34 +5,22 @@ package org.chromium.chrome.browser.toolbar.bottom; import android.content.Context; -import android.content.res.ColorStateList; -import android.support.v7.content.res.AppCompatResources; import org.chromium.base.ApiCompatibilityUtils; import org.chromium.base.ContextUtils; -import org.chromium.base.ObserverList; import org.chromium.chrome.R; import org.chromium.chrome.browser.ChromeFeatureList; +import org.chromium.chrome.browser.ThemeColorProvider; import org.chromium.chrome.browser.compositor.layouts.EmptyOverviewModeObserver; import org.chromium.chrome.browser.compositor.layouts.OverviewModeBehavior; import org.chromium.chrome.browser.compositor.layouts.OverviewModeBehavior.OverviewModeObserver; import org.chromium.chrome.browser.device.DeviceClassManager; import org.chromium.chrome.browser.toolbar.IncognitoStateProvider; import org.chromium.chrome.browser.toolbar.IncognitoStateProvider.IncognitoStateObserver; -import org.chromium.chrome.browser.toolbar.ThemeColorProvider; -import org.chromium.chrome.browser.toolbar.ThemeColorProvider.ThemeColorObserver; /** A ThemeColorProvider for the bottom toolbar. */ -public class BottomToolbarThemeColorProvider implements ThemeColorProvider, IncognitoStateObserver { - /** List of {@link ThemeColorObserver}s. These are used to broadcast events to listeners. */ - private final ObserverList<ThemeColorObserver> mThemeColorObservers; - - /** Tint to be used in dark mode. */ - private final ColorStateList mDarkModeTint; - - /** Tint to be used in light mode. */ - private final ColorStateList mLightModeTint; - +public class BottomToolbarThemeColorProvider + extends ThemeColorProvider implements IncognitoStateObserver { /** Primary color for light mode. */ private final int mLightPrimaryColor; @@ -46,7 +34,7 @@ private OverviewModeBehavior mOverviewModeBehavior; /** Observer to know when overview mode is entered/exited. */ - private OverviewModeObserver mOverviewModeObserver; + private final OverviewModeObserver mOverviewModeObserver; /** Whether theme is dark mode. */ private boolean mIsUsingDarkBackground; @@ -58,11 +46,7 @@ private boolean mIsOverviewVisible; public BottomToolbarThemeColorProvider() { - mThemeColorObservers = new ObserverList<ThemeColorObserver>(); - final Context context = ContextUtils.getApplicationContext(); - mDarkModeTint = AppCompatResources.getColorStateList(context, R.color.light_mode_tint); - mLightModeTint = AppCompatResources.getColorStateList(context, R.color.dark_mode_tint); mLightPrimaryColor = ApiCompatibilityUtils.getColor( context.getResources(), R.color.modern_primary_color); mDarkPrimaryColor = ApiCompatibilityUtils.getColor( @@ -83,16 +67,6 @@ }; } - @Override - public void addObserver(ThemeColorObserver observer) { - mThemeColorObservers.addObserver(observer); - } - - @Override - public void removeObserver(ThemeColorObserver observer) { - mThemeColorObservers.removeObserver(observer); - } - void setIncognitoStateProvider(IncognitoStateProvider provider) { mIncognitoStateProvider = provider; mIncognitoStateProvider.addIncognitoStateObserverAndTrigger(this); @@ -117,16 +91,12 @@ && (isAccessibilityEnabled || isHorizontalTabSwitcherEnabled || !mIsOverviewVisible); - if (shouldUseDarkBackground == mIsUsingDarkBackground) return; - mIsUsingDarkBackground = shouldUseDarkBackground; - final int primaryColor = mIsUsingDarkBackground ? mDarkPrimaryColor : mLightPrimaryColor; - final ColorStateList tint = mIsUsingDarkBackground ? mDarkModeTint : mLightModeTint; - for (ThemeColorObserver observer : mThemeColorObservers) { - observer.onThemeColorChanged(tint, primaryColor); - } + updatePrimaryColor(shouldUseDarkBackground ? mDarkPrimaryColor : mLightPrimaryColor, false); } - void destroy() { + @Override + public void destroy() { + super.destroy(); if (mIncognitoStateProvider != null) { mIncognitoStateProvider.removeObserver(this); mIncognitoStateProvider = null; @@ -135,6 +105,5 @@ mOverviewModeBehavior.removeOverviewModeObserver(mOverviewModeObserver); mOverviewModeBehavior = null; } - mThemeColorObservers.clear(); } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/BrowsingModeBottomToolbarCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/BrowsingModeBottomToolbarCoordinator.java index 9088647..264d087 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/BrowsingModeBottomToolbarCoordinator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/BrowsingModeBottomToolbarCoordinator.java
@@ -10,6 +10,7 @@ import org.chromium.chrome.R; import org.chromium.chrome.browser.ActivityTabProvider; import org.chromium.chrome.browser.ActivityTabProvider.HintlessActivityTabObserver; +import org.chromium.chrome.browser.ThemeColorProvider; import org.chromium.chrome.browser.appmenu.AppMenuButtonHelper; import org.chromium.chrome.browser.compositor.layouts.LayoutManager; import org.chromium.chrome.browser.compositor.layouts.OverviewModeBehavior; @@ -22,7 +23,6 @@ import org.chromium.chrome.browser.toolbar.MenuButton; import org.chromium.chrome.browser.toolbar.TabCountProvider; import org.chromium.chrome.browser.toolbar.TabSwitcherButtonCoordinator; -import org.chromium.chrome.browser.toolbar.ThemeColorProvider; import org.chromium.chrome.browser.toolbar.bottom.BrowsingModeBottomToolbarViewBinder.ViewHolder; import org.chromium.components.feature_engagement.Tracker; import org.chromium.ui.base.WindowAndroid;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/BrowsingModeBottomToolbarMediator.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/BrowsingModeBottomToolbarMediator.java index c531357..19606ef4 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/BrowsingModeBottomToolbarMediator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/BrowsingModeBottomToolbarMediator.java
@@ -4,13 +4,14 @@ package org.chromium.chrome.browser.toolbar.bottom; -import android.content.res.ColorStateList; import android.content.res.Resources; import android.view.View; import org.chromium.base.ApiCompatibilityUtils; import org.chromium.chrome.R; import org.chromium.chrome.browser.ChromeActivity; +import org.chromium.chrome.browser.ThemeColorProvider; +import org.chromium.chrome.browser.ThemeColorProvider.ThemeColorObserver; import org.chromium.chrome.browser.compositor.bottombar.OverlayPanelManager.OverlayPanelManagerObserver; import org.chromium.chrome.browser.compositor.layouts.Layout; import org.chromium.chrome.browser.compositor.layouts.LayoutManager; @@ -21,8 +22,6 @@ import org.chromium.chrome.browser.compositor.layouts.eventfilter.EdgeSwipeHandler; import org.chromium.chrome.browser.fullscreen.ChromeFullscreenManager; import org.chromium.chrome.browser.fullscreen.ChromeFullscreenManager.FullscreenListener; -import org.chromium.chrome.browser.toolbar.ThemeColorProvider; -import org.chromium.chrome.browser.toolbar.ThemeColorProvider.ThemeColorObserver; import org.chromium.chrome.browser.widget.FeatureHighlightProvider; import org.chromium.components.feature_engagement.FeatureConstants; import org.chromium.components.feature_engagement.Tracker; @@ -98,7 +97,7 @@ void setThemeColorProvider(ThemeColorProvider themeColorProvider) { mThemeColorProvider = themeColorProvider; - mThemeColorProvider.addObserver(this); + mThemeColorProvider.addThemeColorObserver(this); } void setResourceManager(ResourceManager resourceManager) { @@ -175,7 +174,7 @@ manager.removeSceneChangeObserver(this); } if (mThemeColorProvider != null) { - mThemeColorProvider.removeObserver(this); + mThemeColorProvider.removeThemeColorObserver(this); mThemeColorProvider = null; } } @@ -264,7 +263,7 @@ } @Override - public void onThemeColorChanged(ColorStateList tintList, int primaryColor) { + public void onThemeColorChanged(int primaryColor, boolean shouldAnimate) { mModel.set(BrowsingModeBottomToolbarModel.PRIMARY_COLOR, primaryColor); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/CloseAllTabsButton.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/CloseAllTabsButton.java index 89ad0ebc4..64e17f2 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/CloseAllTabsButton.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/CloseAllTabsButton.java
@@ -12,19 +12,19 @@ import org.chromium.base.ApiCompatibilityUtils; import org.chromium.chrome.R; import org.chromium.chrome.browser.ChromeFeatureList; +import org.chromium.chrome.browser.ThemeColorProvider; +import org.chromium.chrome.browser.ThemeColorProvider.TintObserver; import org.chromium.chrome.browser.toolbar.IncognitoStateProvider; import org.chromium.chrome.browser.toolbar.IncognitoStateProvider.IncognitoStateObserver; import org.chromium.chrome.browser.toolbar.TabCountProvider; import org.chromium.chrome.browser.toolbar.TabCountProvider.TabCountObserver; -import org.chromium.chrome.browser.toolbar.ThemeColorProvider; -import org.chromium.chrome.browser.toolbar.ThemeColorProvider.ThemeColorObserver; import org.chromium.ui.widget.ChromeImageButton; /** * The close all tabs button. */ class CloseAllTabsButton extends ChromeImageButton - implements ThemeColorObserver, IncognitoStateObserver, TabCountObserver { + implements TintObserver, IncognitoStateObserver, TabCountObserver { /** A provider that notifies when the theme color changes.*/ private ThemeColorProvider mThemeColorProvider; @@ -43,7 +43,7 @@ void destroy() { if (mThemeColorProvider != null) { - mThemeColorProvider.removeObserver(this); + mThemeColorProvider.removeTintObserver(this); mThemeColorProvider = null; } if (mIncognitoStateProvider != null) { @@ -58,11 +58,11 @@ void setThemeColorProvider(ThemeColorProvider themeColorProvider) { mThemeColorProvider = themeColorProvider; - mThemeColorProvider.addObserver(this); + mThemeColorProvider.addTintObserver(this); } @Override - public void onThemeColorChanged(ColorStateList tint, int primaryColor) { + public void onTintChanged(ColorStateList tint, boolean useLight) { ApiCompatibilityUtils.setImageTintList(this, tint); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/SearchAccelerator.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/SearchAccelerator.java index 7fdcc90..5160a50 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/SearchAccelerator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/SearchAccelerator.java
@@ -13,15 +13,16 @@ import org.chromium.base.ApiCompatibilityUtils; import org.chromium.chrome.R; -import org.chromium.chrome.browser.toolbar.ThemeColorProvider; -import org.chromium.chrome.browser.toolbar.ThemeColorProvider.ThemeColorObserver; +import org.chromium.chrome.browser.ThemeColorProvider; +import org.chromium.chrome.browser.ThemeColorProvider.ThemeColorObserver; +import org.chromium.chrome.browser.ThemeColorProvider.TintObserver; import org.chromium.chrome.browser.util.ColorUtils; import org.chromium.ui.widget.ChromeImageButton; /** * The search accelerator. */ -class SearchAccelerator extends ChromeImageButton implements ThemeColorObserver { +class SearchAccelerator extends ChromeImageButton implements ThemeColorObserver, TintObserver { /** A provider that notifies components when the theme color changes.*/ private ThemeColorProvider mThemeColorProvider; @@ -43,21 +44,27 @@ void setThemeColorProvider(ThemeColorProvider themeColorProvider) { mThemeColorProvider = themeColorProvider; - mThemeColorProvider.addObserver(this); + mThemeColorProvider.addThemeColorObserver(this); + mThemeColorProvider.addTintObserver(this); } void destroy() { if (mThemeColorProvider != null) { - mThemeColorProvider.removeObserver(this); + mThemeColorProvider.removeThemeColorObserver(this); + mThemeColorProvider.removeTintObserver(this); mThemeColorProvider = null; } } @Override - public void onThemeColorChanged(ColorStateList tint, int primaryColor) { - ApiCompatibilityUtils.setImageTintList(this, tint); + public void onThemeColorChanged(int color, boolean shouldAnimate) { mBackground.setColorFilter( - ColorUtils.getTextBoxColorForToolbarBackground(mResources, false, primaryColor), + ColorUtils.getTextBoxColorForToolbarBackground(mResources, false, color), PorterDuff.Mode.SRC_IN); } + + @Override + public void onTintChanged(ColorStateList tint, boolean useLight) { + ApiCompatibilityUtils.setImageTintList(this, tint); + } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/ShareButton.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/ShareButton.java index 9a590a92..d61f271 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/ShareButton.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/ShareButton.java
@@ -11,16 +11,16 @@ import org.chromium.base.ApiCompatibilityUtils; import org.chromium.chrome.browser.ActivityTabProvider; import org.chromium.chrome.browser.ActivityTabProvider.ActivityTabTabObserver; +import org.chromium.chrome.browser.ThemeColorProvider; +import org.chromium.chrome.browser.ThemeColorProvider.TintObserver; import org.chromium.chrome.browser.UrlConstants; import org.chromium.chrome.browser.tab.Tab; -import org.chromium.chrome.browser.toolbar.ThemeColorProvider; -import org.chromium.chrome.browser.toolbar.ThemeColorProvider.ThemeColorObserver; import org.chromium.ui.widget.ChromeImageButton; /** * The share button. */ -class ShareButton extends ChromeImageButton implements ThemeColorObserver { +class ShareButton extends ChromeImageButton implements TintObserver { /** A provider that notifies components when the theme color changes.*/ private ThemeColorProvider mThemeColorProvider; @@ -31,9 +31,9 @@ super(context, attrs); } - void setThemeColorProvider(ThemeColorProvider themeStateProvider) { - mThemeColorProvider = themeStateProvider; - mThemeColorProvider.addObserver(this); + void setThemeColorProvider(ThemeColorProvider themeColorProvider) { + mThemeColorProvider = themeColorProvider; + mThemeColorProvider.addTintObserver(this); } void setActivityTabProvider(ActivityTabProvider activityTabProvider) { @@ -54,7 +54,7 @@ void destroy() { if (mThemeColorProvider != null) { - mThemeColorProvider.removeObserver(this); + mThemeColorProvider.removeTintObserver(this); mThemeColorProvider = null; } if (mActivityTabTabObserver != null) { @@ -71,7 +71,7 @@ } @Override - public void onThemeColorChanged(ColorStateList tint, int primaryColor) { + public void onTintChanged(ColorStateList tint, boolean useLight) { ApiCompatibilityUtils.setImageTintList(this, tint); } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/TabSwitcherBottomToolbarCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/TabSwitcherBottomToolbarCoordinator.java index a1e4ce7..dfb041a1 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/TabSwitcherBottomToolbarCoordinator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/TabSwitcherBottomToolbarCoordinator.java
@@ -9,13 +9,13 @@ import android.view.ViewStub; import org.chromium.chrome.R; +import org.chromium.chrome.browser.ThemeColorProvider; import org.chromium.chrome.browser.appmenu.AppMenuButtonHelper; import org.chromium.chrome.browser.compositor.layouts.OverviewModeBehavior; import org.chromium.chrome.browser.tabmodel.TabModelSelector; import org.chromium.chrome.browser.toolbar.IncognitoStateProvider; import org.chromium.chrome.browser.toolbar.MenuButton; import org.chromium.chrome.browser.toolbar.TabCountProvider; -import org.chromium.chrome.browser.toolbar.ThemeColorProvider; import org.chromium.ui.modelutil.PropertyModelChangeProcessor; /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/TabSwitcherBottomToolbarMediator.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/TabSwitcherBottomToolbarMediator.java index 49e9359..aa8769f4 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/TabSwitcherBottomToolbarMediator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/TabSwitcherBottomToolbarMediator.java
@@ -4,12 +4,10 @@ package org.chromium.chrome.browser.toolbar.bottom; -import android.content.res.ColorStateList; - +import org.chromium.chrome.browser.ThemeColorProvider; +import org.chromium.chrome.browser.ThemeColorProvider.ThemeColorObserver; import org.chromium.chrome.browser.compositor.layouts.OverviewModeBehavior; import org.chromium.chrome.browser.compositor.layouts.OverviewModeBehavior.OverviewModeObserver; -import org.chromium.chrome.browser.toolbar.ThemeColorProvider; -import org.chromium.chrome.browser.toolbar.ThemeColorProvider.ThemeColorObserver; /** * This class is responsible for reacting to events from the outside world, interacting with other @@ -38,7 +36,7 @@ mModel = model; mThemeColorProvider = themeColorProvider; - mThemeColorProvider.addObserver(this); + mThemeColorProvider.addThemeColorObserver(this); mOverviewModeBehavior = overviewModeBehavior; mOverviewModeBehavior.addOverviewModeObserver(this); @@ -49,7 +47,7 @@ */ void destroy() { if (mOverviewModeBehavior != null) mOverviewModeBehavior.removeOverviewModeObserver(this); - if (mThemeColorProvider != null) mThemeColorProvider.removeObserver(this); + if (mThemeColorProvider != null) mThemeColorProvider.removeThemeColorObserver(this); } @Override @@ -69,7 +67,7 @@ public void onOverviewModeFinishedHiding() {} @Override - public void onThemeColorChanged(ColorStateList tint, int primaryColor) { + public void onThemeColorChanged(int primaryColor, boolean shouldAnimate) { mModel.set(TabSwitcherBottomToolbarModel.PRIMARY_COLOR, primaryColor); } }
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 0af635cd3..b1e70777 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
@@ -2186,6 +2186,7 @@ }); mBrandColorTransitionAnimation.start(); mBrandColorTransitionActive = true; + mLayoutUpdateHost.requestUpdate(); } private void updateNtpAnimationState() {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr/VrShell.java b/chrome/android/java/src/org/chromium/chrome/browser/vr/VrShell.java index 4062a55..6b78545 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/vr/VrShell.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/vr/VrShell.java
@@ -6,6 +6,7 @@ import android.annotation.SuppressLint; import android.annotation.TargetApi; +import android.content.pm.PackageManager; import android.graphics.Color; import android.graphics.PixelFormat; import android.graphics.Point; @@ -413,13 +414,11 @@ // relatively low-res Pixel, and higher-res Pixel XL and other devices. boolean lowDensity = dm.densityDpi <= DisplayMetrics.DENSITY_XXHIGH; - boolean hasOrCanRequestAudioPermission = - mActivity.getWindowAndroid().hasPermission(android.Manifest.permission.RECORD_AUDIO) - || mActivity.getWindowAndroid().canRequestPermission( - android.Manifest.permission.RECORD_AUDIO); + boolean hasOrCanRequestRecordAudioPermission = + hasRecordAudioPermission() || canRequestRecordAudioPermission(); boolean supportsRecognition = FeatureUtilities.isRecognitionIntentPresent(mActivity, false); mNativeVrShell = nativeInit(mDelegate, forWebVr, !mVrBrowsingEnabled, - hasOrCanRequestAudioPermission && supportsRecognition, + hasOrCanRequestRecordAudioPermission && supportsRecognition, getGvrApi().getNativeGvrContext(), mReprojectedRendering, displayWidthMeters, displayHeightMeters, dm.widthPixels, dm.heightPixels, pauseContent, lowDensity, isStandaloneVrDevice); @@ -534,8 +533,14 @@ // Returns true if Chrome has permission to use audio input. @CalledByNative - public boolean hasAudioPermission() { - return mDelegate.hasAudioPermission(); + public boolean hasRecordAudioPermission() { + return mDelegate.hasRecordAudioPermission(); + } + + // Returns true if Chrome has not been permanently denied audio input permission. + @CalledByNative + public boolean canRequestRecordAudioPermission() { + return mDelegate.canRequestRecordAudioPermission(); } // Exits VR, telling the user to remove their headset, and returning to Chromium. @@ -568,6 +573,8 @@ @Override public void run() { VrShellDelegate.enterVrIfNecessary(); + nativeRequestRecordAudioPermissionResult(mNativeVrShell, + grantResults[0] == PackageManager.PERMISSION_GRANTED); } }); } @@ -1273,7 +1280,7 @@ } private native long nativeInit(VrShellDelegate delegate, boolean forWebVR, - boolean browsingDisabled, boolean hasOrCanRequestAudioPermission, long gvrApi, + boolean browsingDisabled, boolean hasOrCanRequestRecordAudioPermission, long gvrApi, boolean reprojectedRendering, float displayWidthMeters, float displayHeightMeters, int displayWidthPixels, int displayHeightPixels, boolean pauseContent, boolean lowDensity, boolean isStandaloneVrDevice); @@ -1329,4 +1336,6 @@ long nativeVrShell, int elementName, int timeoutMs, boolean visibility); private native void nativeResumeContentRendering(long nativeVrShell); private native void nativeOnOverlayTextureEmptyChanged(long nativeVrShell, boolean empty); + private native void nativeRequestRecordAudioPermissionResult( + long nativeVrShell, boolean canRecordAudio); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr/VrShellDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/vr/VrShellDelegate.java index 67afd026..0b008695 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/vr/VrShellDelegate.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/vr/VrShellDelegate.java
@@ -1189,10 +1189,15 @@ return false; } - public boolean hasAudioPermission() { + public boolean hasRecordAudioPermission() { return mActivity.getWindowAndroid().hasPermission(android.Manifest.permission.RECORD_AUDIO); } + public boolean canRequestRecordAudioPermission() { + return mActivity.getWindowAndroid().canRequestPermission( + android.Manifest.permission.RECORD_AUDIO); + } + private boolean isWindowModeCorrectForVr() { int flags = mActivity.getWindow().getDecorView().getSystemUiVisibility(); int orientation = mActivity.getResources().getConfiguration().orientation;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java index b6b153f..d64ffcb 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java
@@ -771,7 +771,7 @@ taskDescriptionColor = mBrandColor; statusBarColor = ColorUtils.getDarkenedColorForStatusBar(mBrandColor); if (getToolbarManager() != null) { - getToolbarManager().updatePrimaryColor(mBrandColor, false); + getToolbarManager().onThemeColorChanged(mBrandColor, false); } }
diff --git a/chrome/android/java_sources.gni b/chrome/android/java_sources.gni index 4ca7824..c83429b 100644 --- a/chrome/android/java_sources.gni +++ b/chrome/android/java_sources.gni
@@ -70,6 +70,8 @@ "java/src/org/chromium/chrome/browser/SnackbarActivity.java", "java/src/org/chromium/chrome/browser/SwipeRefreshHandler.java", "java/src/org/chromium/chrome/browser/SynchronousInitializationActivity.java", + "java/src/org/chromium/chrome/browser/TabThemeColorProvider.java", + "java/src/org/chromium/chrome/browser/ThemeColorProvider.java", "java/src/org/chromium/chrome/browser/UrlConstants.java", "java/src/org/chromium/chrome/browser/UsbChooserDialog.java", "java/src/org/chromium/chrome/browser/WarmupManager.java", @@ -742,6 +744,9 @@ "java/src/org/chromium/chrome/browser/gcore/ConnectedTask.java", "java/src/org/chromium/chrome/browser/gcore/GoogleApiClientHelper.java", "java/src/org/chromium/chrome/browser/gcore/LifecycleHook.java", + "java/src/org/chromium/chrome/browser/gesturenav/ArrowDrawable.java", + "java/src/org/chromium/chrome/browser/gesturenav/HistoryNavigationLayout.java", + "java/src/org/chromium/chrome/browser/gesturenav/SideSlideLayout.java", "java/src/org/chromium/chrome/browser/gsa/ContextReporter.java", "java/src/org/chromium/chrome/browser/gsa/GSAAccountChangeListener.java", "java/src/org/chromium/chrome/browser/gsa/GSAContextDisplaySelection.java", @@ -1168,8 +1173,10 @@ "java/src/org/chromium/chrome/browser/omnibox/suggestions/SuggestionListProperties.java", "java/src/org/chromium/chrome/browser/omnibox/suggestions/SuggestionListViewBinder.java", "java/src/org/chromium/chrome/browser/omnibox/suggestions/VoiceSuggestionProvider.java", + "java/src/org/chromium/chrome/browser/omnibox/suggestions/basic/AnswerSuggestionProcessor.java", "java/src/org/chromium/chrome/browser/omnibox/suggestions/basic/AnswerTextBuilder.java", "java/src/org/chromium/chrome/browser/omnibox/suggestions/basic/BasicSuggestionProcessor.java", + "java/src/org/chromium/chrome/browser/omnibox/suggestions/basic/SuggestionHost.java", "java/src/org/chromium/chrome/browser/omnibox/suggestions/basic/SuggestionView.java", "java/src/org/chromium/chrome/browser/omnibox/suggestions/basic/SuggestionViewProperties.java", "java/src/org/chromium/chrome/browser/omnibox/suggestions/basic/SuggestionViewViewBinder.java", @@ -1538,6 +1545,7 @@ "java/src/org/chromium/chrome/browser/tab/TabFullscreenHandler.java", "java/src/org/chromium/chrome/browser/tab/TabGestureStateListener.java", "java/src/org/chromium/chrome/browser/tab/TabIdManager.java", + "java/src/org/chromium/chrome/browser/tab/TabImportanceManager.java", "java/src/org/chromium/chrome/browser/tab/TabObserver.java", "java/src/org/chromium/chrome/browser/tab/TabRedirectHandler.java", "java/src/org/chromium/chrome/browser/tab/TabState.java", @@ -1605,7 +1613,6 @@ "java/src/org/chromium/chrome/browser/toolbar/TabSwitcherButtonView.java", "java/src/org/chromium/chrome/browser/toolbar/TabSwitcherButtonViewBinder.java", "java/src/org/chromium/chrome/browser/toolbar/TabSwitcherDrawable.java", - "java/src/org/chromium/chrome/browser/toolbar/ThemeColorProvider.java", "java/src/org/chromium/chrome/browser/toolbar/ToolbarButtonInProductHelpController.java", "java/src/org/chromium/chrome/browser/toolbar/ToolbarDataProvider.java", "java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java",
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageAutoFetchTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageAutoFetchTest.java index 3e0dbf0..d94ce4b 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageAutoFetchTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageAutoFetchTest.java
@@ -152,6 +152,7 @@ } @Test + @DisabledTest(message = "crbug.com/923212") @MediumTest @Feature({"OfflineAutoFetch"}) public void testAutoFetchRequestRetainedOnOtherTabClosed() throws Exception {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/top/BrandColorTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/top/BrandColorTest.java index 9d893afb..1b67a0b7 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/top/BrandColorTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/top/BrandColorTest.java
@@ -152,7 +152,7 @@ ThreadUtils.runOnUiThreadBlocking(new Runnable() { @Override public void run() { - mActivityTestRule.getActivity().getToolbarManager().updatePrimaryColor( + mActivityTestRule.getActivity().getToolbarManager().onThemeColorChanged( mDefaultColor, false); // Since the color should change instantly, there is no need to use the criteria // helper.
diff --git a/chrome/android/modules/vr/vr_module_tmpl.gni b/chrome/android/modules/vr/vr_module_tmpl.gni index 9ff046a..7e0028e 100644 --- a/chrome/android/modules/vr/vr_module_tmpl.gni +++ b/chrome/android/modules/vr/vr_module_tmpl.gni
@@ -30,6 +30,7 @@ [ "base_module_target", "module_name", + "uncompress_shared_libraries", "version_code", "version_name", ]) @@ -39,6 +40,8 @@ "//chrome/browser/android/vr:java", ] proguard_enabled = !is_java_debug - uncompress_shared_libraries = chromium_linker_supported + if (!defined(invoker.uncompress_shared_libraries)) { + uncompress_shared_libraries = chromium_linker_supported + } } }
diff --git a/chrome/app/bookmarks_strings.grdp b/chrome/app/bookmarks_strings.grdp index 91e4d951..2d46be6 100644 --- a/chrome/app/bookmarks_strings.grdp +++ b/chrome/app/bookmarks_strings.grdp
@@ -305,7 +305,7 @@ <!-- Begin of Bookmarks Manager strings. --> <message name="IDS_BOOKMARK_MANAGER_TITLE" desc="Title of the bookmark manager window."> - Bookmark Manager + Bookmarks </message> <message name="IDS_BOOKMARK_MANAGER_SEARCH_BUTTON" desc="Title of the button in the bookmark manager that triggers a search"> Search bookmarks @@ -377,133 +377,127 @@ <message name="IDS_EXPORT_BOOKMARKS_DEFAULT_FILENAME" desc="Filename that pre-populates the filename field when user attempts to export their bookmarks from Bookmark Manager."> bookmarks_<ph name="DATESTAMP">$1<ex>02_11_11</ex></ph>.html </message> - <!-- End of Bookmarks Manager strings. --> - - <!-- Begin of material design Bookmarks Manager strings. --> - <message name="IDS_MD_BOOKMARK_MANAGER_ADD_BOOKMARK_TITLE" desc="Title of the dialog in the bookmark manager that creates a new bookmark."> + <message name="IDS_BOOKMARK_MANAGER_ADD_BOOKMARK_TITLE" desc="Title of the dialog in the bookmark manager that creates a new bookmark."> Add bookmark </message> - <message name="IDS_MD_BOOKMARK_MANAGER_ADD_FOLDER_TITLE" desc="Title of the dialog in the bookmark manager that creates a new bookmark folder."> + <message name="IDS_BOOKMARK_MANAGER_ADD_FOLDER_TITLE" desc="Title of the dialog in the bookmark manager that creates a new bookmark folder."> Add folder </message> - <message name="IDS_MD_BOOKMARK_MANAGER_CLEAR_SEARCH" desc="Title of the button in the bookmark manager that stops a search."> + <message name="IDS_BOOKMARK_MANAGER_CLEAR_SEARCH" desc="Title of the button in the bookmark manager that stops a search."> Clear search </message> - <message name="IDS_MD_BOOKMARK_MANAGER_EMPTY_LIST" desc="The message shown when the user has no bookmarks added. 'Star' refers to the icon in the omnibox for adding to bookmarks."> + <message name="IDS_BOOKMARK_MANAGER_EMPTY_LIST" desc="The message shown when the user has no bookmarks added. 'Star' refers to the icon in the omnibox for adding to bookmarks."> To bookmark pages, click the star in the address bar </message> - <message name="IDS_MD_BOOKMARK_MANAGER_EMPTY_UNMODIFIABLE_LIST" desc="The message shown when an unmodifiable bookmark folder is empty."> + <message name="IDS_BOOKMARK_MANAGER_EMPTY_UNMODIFIABLE_LIST" desc="The message shown when an unmodifiable bookmark folder is empty."> This folder is empty </message> - <message name="IDS_MD_BOOKMARK_MANAGER_FOLDER_LABEL" desc="Label for a folder of bookmarks which is used to label folders for screen reader users."> + <message name="IDS_BOOKMARK_MANAGER_FOLDER_LABEL" desc="Label for a folder of bookmarks which is used to label folders for screen reader users."> Folder </message> - <message name="IDS_MD_BOOKMARK_MANAGER_FOLDER_RENAME_TITLE" desc="Title of the bookmark editor window when editing folders."> + <message name="IDS_BOOKMARK_MANAGER_FOLDER_RENAME_TITLE" desc="Title of the bookmark editor window when editing folders."> Rename folder </message> - <message name="IDS_MD_BOOKMARK_MANAGER_FOLDER_LIST_CHANGED" desc="Message announced by screenreaders when the bookmark list changes."> + <message name="IDS_BOOKMARK_MANAGER_FOLDER_LIST_CHANGED" desc="Message announced by screenreaders when the bookmark list changes."> {COUNT, plural, =1 {1 item in bookmark list} other {# items in bookmark list}} </message> - <message name="IDS_MD_BOOKMARK_MANAGER_LIST_AX_LABEL" desc="Spoken feedback for focusing the bookmark list."> + <message name="IDS_BOOKMARK_MANAGER_LIST_AX_LABEL" desc="Spoken feedback for focusing the bookmark list."> Bookmark list </message> - <message name="IDS_MD_BOOKMARK_MANAGER_MENU_ADD_BOOKMARK" desc="Title of the bookmark toolbar dropdown menu item that adds a new bookmark."> + <message name="IDS_BOOKMARK_MANAGER_MENU_ADD_BOOKMARK" desc="Title of the bookmark toolbar dropdown menu item that adds a new bookmark."> Add new bookmark </message> - <message name="IDS_MD_BOOKMARK_MANAGER_MENU_ADD_FOLDER" desc="Title of the bookmark toolbar dropdown menu item that adds a new folder."> + <message name="IDS_BOOKMARK_MANAGER_MENU_ADD_FOLDER" desc="Title of the bookmark toolbar dropdown menu item that adds a new folder."> Add new folder </message> - <message name="IDS_MD_BOOKMARK_MANAGER_MENU_COPY_URL" desc="Title of the bookmark dropdown menu item that copies the url of the bookmark."> + <message name="IDS_BOOKMARK_MANAGER_MENU_COPY_URL" desc="Title of the bookmark dropdown menu item that copies the url of the bookmark."> Copy URL </message> - <message name="IDS_MD_BOOKMARK_MANAGER_MENU_EXPORT" desc="Title of the bookmark toolbar dropdown menu item that exports bookmarks."> + <message name="IDS_BOOKMARK_MANAGER_MENU_EXPORT" desc="Title of the bookmark toolbar dropdown menu item that exports bookmarks."> Export bookmarks </message> - <message name="IDS_MD_BOOKMARK_MANAGER_MENU_HELP_CENTER" desc="Title of the bookmark toolbar dropdown menu item that opens the help center."> + <message name="IDS_BOOKMARK_MANAGER_MENU_HELP_CENTER" desc="Title of the bookmark toolbar dropdown menu item that opens the help center."> Help center </message> - <message name="IDS_MD_BOOKMARK_MANAGER_MENU_IMPORT" desc="Title of the bookmark toolbar dropdown menu item that imports bookmarks."> + <message name="IDS_BOOKMARK_MANAGER_MENU_IMPORT" desc="Title of the bookmark toolbar dropdown menu item that imports bookmarks."> Import bookmarks </message> - <message name="IDS_MD_BOOKMARK_MANAGER_MENU_OPEN_ALL" desc="Menu title for opening all urls in a bookmark folder"> + <message name="IDS_BOOKMARK_MANAGER_MENU_OPEN_ALL" desc="Menu title for opening all urls in a bookmark folder"> Open all bookmarks </message> - <message name="IDS_MD_BOOKMARK_MANAGER_MENU_OPEN_ALL_NEW_WINDOW" desc="Menu title for opening all urls in a bookmark folder in a new window"> + <message name="IDS_BOOKMARK_MANAGER_MENU_OPEN_ALL_NEW_WINDOW" desc="Menu title for opening all urls in a bookmark folder in a new window"> Open all in new window </message> - <message name="IDS_MD_BOOKMARK_MANAGER_MENU_OPEN_ALL_INCOGNITO" desc="Menu description for opening all urls in a bookmark folder in an incognito window"> + <message name="IDS_BOOKMARK_MANAGER_MENU_OPEN_ALL_INCOGNITO" desc="Menu description for opening all urls in a bookmark folder in an incognito window"> Open all in incognito window </message> - <message name="IDS_MD_BOOKMARK_MANAGER_MENU_OPEN_IN_NEW_TAB" desc="Menu description for opening a bookmark in a new tab"> + <message name="IDS_BOOKMARK_MANAGER_MENU_OPEN_IN_NEW_TAB" desc="Menu description for opening a bookmark in a new tab"> Open in new tab </message> - <message name="IDS_MD_BOOKMARK_MANAGER_MENU_OPEN_IN_NEW_WINDOW" desc="Menu description for opening a bookmark in a new window"> + <message name="IDS_BOOKMARK_MANAGER_MENU_OPEN_IN_NEW_WINDOW" desc="Menu description for opening a bookmark in a new window"> Open in new window </message> - <message name="IDS_MD_BOOKMARK_MANAGER_MENU_OPEN_INCOGNITO" desc="Menu description for opening a bookmark in incognito window"> + <message name="IDS_BOOKMARK_MANAGER_MENU_OPEN_INCOGNITO" desc="Menu description for opening a bookmark in incognito window"> Open in incognito window </message> - <message name="IDS_MD_BOOKMARK_MANAGER_MENU_RENAME" desc="Title of the bookmark list dropdown menu item that renames folders."> + <message name="IDS_BOOKMARK_MANAGER_MENU_RENAME" desc="Title of the bookmark list dropdown menu item that renames folders."> Rename </message> - <message name="IDS_MD_BOOKMARK_MANAGER_MENU_SHOW_IN_FOLDER" desc="The label of the menu item in the bookmark manager context menu that changes the selection in the tree to match the folder of the selected item in the list."> + <message name="IDS_BOOKMARK_MANAGER_MENU_SHOW_IN_FOLDER" desc="The label of the menu item in the bookmark manager context menu that changes the selection in the tree to match the folder of the selected item in the list."> Show in folder </message> - <message name="IDS_MD_BOOKMARK_MANAGER_MENU_SORT" desc="Title of the bookmark toolbar dropdown menu item that sorts bookmarks by title."> + <message name="IDS_BOOKMARK_MANAGER_MENU_SORT" desc="Title of the bookmark toolbar dropdown menu item that sorts bookmarks by title."> Sort by name </message> - <message name="IDS_MD_BOOKMARK_MANAGER_MORE_ACTIONS" desc="Tooltip of the button in the bookmark manager which shows an action menu for a bookmark, with actions like 'Edit' or 'Delete'"> + <message name="IDS_BOOKMARK_MANAGER_MORE_ACTIONS" desc="Tooltip of the button in the bookmark manager which shows an action menu for a bookmark, with actions like 'Edit' or 'Delete'"> More actions </message> - <message name="IDS_MD_BOOKMARK_MANAGER_MORE_ACTIONS_AX_LABEL" desc="Spoken text for the button in the bookmark manager which shows an action menu for a bookmark, with actions like 'Edit' or 'Delete'"> + <message name="IDS_BOOKMARK_MANAGER_MORE_ACTIONS_AX_LABEL" desc="Spoken text for the button in the bookmark manager which shows an action menu for a bookmark, with actions like 'Edit' or 'Delete'"> More actions for <ph name="BOOKMARK_NAME">$1<ex>Bookmark X</ex></ph> </message> - <message name="IDS_MD_BOOKMARK_MANAGER_OPEN_DIALOG_TITLE" desc="Title of the dialog confirming whether a large number of bookmarks should be opened."> + <message name="IDS_BOOKMARK_MANAGER_OPEN_DIALOG_TITLE" desc="Title of the dialog confirming whether a large number of bookmarks should be opened."> Open selected items </message> - <message name="IDS_MD_BOOKMARK_MANAGER_OPEN_DIALOG_CONFIRM" desc="Label for the button to confirm opening a large number of bookmarks."> + <message name="IDS_BOOKMARK_MANAGER_OPEN_DIALOG_CONFIRM" desc="Label for the button to confirm opening a large number of bookmarks."> Open </message> - <message name="IDS_MD_BOOKMARK_MANAGER_ITEMS_SELECTED" desc="Label displayed in bookmark manager toolbar telling the user how many items they have selected."> + <message name="IDS_BOOKMARK_MANAGER_ITEMS_SELECTED" desc="Label displayed in bookmark manager toolbar telling the user how many items they have selected."> <ph name="NUMBER_OF_ITEMS_SELECTED">$1</ph> selected </message> - <message name="IDS_MD_BOOKMARK_MANAGER_SIDEBAR_AX_LABEL" desc="Message announced by screenreaders for the bookmark manager sidebar."> + <message name="IDS_BOOKMARK_MANAGER_SIDEBAR_AX_LABEL" desc="Message announced by screenreaders for the bookmark manager sidebar."> Bookmark folder tree </message> - <message name="IDS_MD_BOOKMARK_MANAGER_SIDEBAR_NODE_COLLAPSE_AX_LABEL" desc="Message announced by screenreaders for button to collapse a folder in the bookmark manager sidebar."> + <message name="IDS_BOOKMARK_MANAGER_SIDEBAR_NODE_COLLAPSE_AX_LABEL" desc="Message announced by screenreaders for button to collapse a folder in the bookmark manager sidebar."> Collapse <ph name="FOLDER_NAME">$1<ex>Recipes</ex></ph> </message> - <message name="IDS_MD_BOOKMARK_MANAGER_SIDEBAR_NODE_EXPAND_AX_LABEL" desc="Message announced by screenreaders for button to expand a folder in the bookmark manager sidebar."> + <message name="IDS_BOOKMARK_MANAGER_SIDEBAR_NODE_EXPAND_AX_LABEL" desc="Message announced by screenreaders for button to expand a folder in the bookmark manager sidebar."> Expand <ph name="FOLDER_NAME">$1<ex>Recipes</ex></ph> </message> - <message name="IDS_MD_BOOKMARK_MANAGER_TITLE" desc="Title of the bookmark manager window."> - Bookmarks - </message> - <message name="IDS_MD_BOOKMARK_MANAGER_TOAST_FOLDER_SORTED" desc="Label displayed in toast popup message when a folder's children are sorted."> + <message name="IDS_BOOKMARK_MANAGER_TOAST_FOLDER_SORTED" desc="Label displayed in toast popup message when a folder's children are sorted."> Folder sorted </message> - <message name="IDS_MD_BOOKMARK_MANAGER_TOAST_ITEM_DELETED" desc="Label displayed in toast popup message when a single item is deleted."> + <message name="IDS_BOOKMARK_MANAGER_TOAST_ITEM_DELETED" desc="Label displayed in toast popup message when a single item is deleted."> '<ph name="DELETED_ITEM_NAME">$1<ex>Bookmark X</ex></ph>' deleted </message> - <message name="IDS_MD_BOOKMARK_MANAGER_TOAST_ITEMS_DELETED" desc="Label displayed in toast popup message when two or more items are deleted."> + <message name="IDS_BOOKMARK_MANAGER_TOAST_ITEMS_DELETED" desc="Label displayed in toast popup message when two or more items are deleted."> {COUNT, plural, =1 {1 bookmark deleted} other {# bookmarks deleted}} </message> - <message name="IDS_MD_BOOKMARK_MANAGER_TOAST_URL_COPIED" desc="Label displayed in toast popup message when a URL is copied."> + <message name="IDS_BOOKMARK_MANAGER_TOAST_URL_COPIED" desc="Label displayed in toast popup message when a URL is copied."> URL copied </message> - <message name="IDS_MD_BOOKMARK_MANAGER_TOAST_ITEM_COPIED" desc="Label displayed in toast popup message when a single item is copied."> + <message name="IDS_BOOKMARK_MANAGER_TOAST_ITEM_COPIED" desc="Label displayed in toast popup message when a single item is copied."> '<ph name="COPIED_ITEM_NAME">$1<ex>Bookmark X</ex></ph>' copied </message> - <message name="IDS_MD_BOOKMARK_MANAGER_TOAST_ITEMS_COPIED" desc="Label displayed in a toast popup message when two or more bookmark items are copied"> + <message name="IDS_BOOKMARK_MANAGER_TOAST_ITEMS_COPIED" desc="Label displayed in a toast popup message when two or more bookmark items are copied"> {COUNT, plural, =1 {1 item copied} other {# items copied}} </message> - <!-- End of material design Bookmarks Manager strings. --> + <!-- End of Bookmarks Manager strings. --> <!-- Begin of Bookmarks Menu (in the Main Menu) strings. --> <message name="IDS_BOOKMARKS_MENU" desc="The title of the Bookmarks menu in the Main menu and in the Mac menu bar.">
diff --git a/chrome/app/chromeos_strings.grdp b/chrome/app/chromeos_strings.grdp index 81abca3..741b00e 100644 --- a/chrome/app/chromeos_strings.grdp +++ b/chrome/app/chromeos_strings.grdp
@@ -3762,4 +3762,16 @@ <message name="IDS_PLUGIN_VM_LAUNCHER_RETRY_BUTTON" desc="Label for the button in the PluginVm launcher dialog to retry PluginVm environment setting." translateable="false"> Retry </message> + + <!-- Strings for Account Manager welcome screen --> + <message name="IDS_ACCOUNT_MANAGER_WELCOME_TITLE" desc="Title for the Chrome OS Account Manager Welcome screen."> + Manage your Google Accounts in one place + </message> + <message name="IDS_ACCOUNT_MANAGER_WELCOME_TEXT" desc="Text body for the Chrome OS Account Manager Welcome screen."> + Apps and websites that have your permission can access the account information they need to work properly. + + If you don't want to add an account, sign in as a guest or open an incognito window for web browsing. + + You can go to Settings -> Google Accounts to view and manage all accounts. + </message> </grit-part>
diff --git a/chrome/app/chromeos_strings_grdp/IDS_ACCOUNT_MANAGER_WELCOME_TEXT.png.sha1 b/chrome/app/chromeos_strings_grdp/IDS_ACCOUNT_MANAGER_WELCOME_TEXT.png.sha1 new file mode 100644 index 0000000..226cbec --- /dev/null +++ b/chrome/app/chromeos_strings_grdp/IDS_ACCOUNT_MANAGER_WELCOME_TEXT.png.sha1
@@ -0,0 +1 @@ +43b13f274f906c3b0e2aca792cc286b883b73c05 \ No newline at end of file
diff --git a/chrome/app/chromeos_strings_grdp/IDS_ACCOUNT_MANAGER_WELCOME_TITLE.png.sha1 b/chrome/app/chromeos_strings_grdp/IDS_ACCOUNT_MANAGER_WELCOME_TITLE.png.sha1 new file mode 100644 index 0000000..226cbec --- /dev/null +++ b/chrome/app/chromeos_strings_grdp/IDS_ACCOUNT_MANAGER_WELCOME_TITLE.png.sha1
@@ -0,0 +1 @@ +43b13f274f906c3b0e2aca792cc286b883b73c05 \ No newline at end of file
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index b3b6844..d0b1931 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd
@@ -5761,6 +5761,9 @@ <message name="IDS_TAB_CXMENU_ADD_TAB_TO_EXISTING_GROUP" desc="The label of the tab context menu submenu for adding one or more tabs to an existing tab group."> Add to existing group </message> + <message name="IDS_TAB_CXMENU_REMOVE_TAB_FROM_GROUP" desc="The label of the tab context menu item for removing one or more tabs from the groups that contain them."> + Remove from group + </message> </if> <if expr="use_titlecase"> <message name="IDS_TAB_CXMENU_NEWTAB" desc="In Title Case: The label of the 'New Tab' Tab context menu item."> @@ -5808,6 +5811,9 @@ <message name="IDS_TAB_CXMENU_ADD_TAB_TO_EXISTING_GROUP" desc="In Title Case: The label of the tab context menu submenu for adding one or more tabs to an existing tab group."> Add to Existing Group </message> + <message name="IDS_TAB_CXMENU_REMOVE_TAB_FROM_GROUP" desc="In Title Case: The label of the tab context menu item for removing one or more tabs from the groups that contain them."> + Remove From Group + </message> <message name="IDS_TAB_CXMENU_SEND_TO_MY_DEVICES" desc="In Title Case: The label of the tab context menu item for share this tab to other devices."> Send To My Devices </message>
diff --git a/chrome/app/generated_resources_grd/IDS_TAB_CXMENU_REMOVE_TAB_FROM_GROUP.png.sha1 b/chrome/app/generated_resources_grd/IDS_TAB_CXMENU_REMOVE_TAB_FROM_GROUP.png.sha1 new file mode 100644 index 0000000..4f6f73d0 --- /dev/null +++ b/chrome/app/generated_resources_grd/IDS_TAB_CXMENU_REMOVE_TAB_FROM_GROUP.png.sha1
@@ -0,0 +1 @@ +a728e9c9bfcfdb90c4a75006ecde8f77c2b53c06 \ No newline at end of file
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index 8762d326..465284d1 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -2598,6 +2598,12 @@ flag_descriptions::kExperimentalAccessibilityLabelsName, flag_descriptions::kExperimentalAccessibilityLabelsDescription, kOsAll, SINGLE_VALUE_TYPE(::switches::kEnableExperimentalAccessibilityLabels)}, + {"enable-experimental-accessibility-language-detection", + flag_descriptions::kExperimentalAccessibilityLanguageDetectionName, + flag_descriptions::kExperimentalAccessibilityLanguageDetectionDescription, + kOsCrOS, + SINGLE_VALUE_TYPE( + ::switches::kEnableExperimentalAccessibilityLanguageDetection)}, #if defined(OS_CHROMEOS) {"opt-in-ime-menu", flag_descriptions::kEnableImeMenuName, flag_descriptions::kEnableImeMenuDescription, kOsCrOS,
diff --git a/chrome/browser/android/vr/vr_gl_thread.cc b/chrome/browser/android/vr/vr_gl_thread.cc index 90351cfc7..6342cc9e 100644 --- a/chrome/browser/android/vr/vr_gl_thread.cc +++ b/chrome/browser/android/vr/vr_gl_thread.cc
@@ -392,6 +392,16 @@ weak_browser_ui_, reason)); } +void VrGLThread::SetHasOrCanRequestRecordAudioPermission( + bool const has_or_can_request_record_audio) { + DCHECK(OnMainThread()); + task_runner()->PostTask( + FROM_HERE, + base::BindOnce( + &BrowserUiInterface::SetHasOrCanRequestRecordAudioPermission, + weak_browser_ui_, has_or_can_request_record_audio)); +} + void VrGLThread::SetSpeechRecognitionEnabled(bool enabled) { DCHECK(OnMainThread()); task_runner()->PostTask(
diff --git a/chrome/browser/android/vr/vr_gl_thread.h b/chrome/browser/android/vr/vr_gl_thread.h index 60098650..0ffa15a 100644 --- a/chrome/browser/android/vr/vr_gl_thread.h +++ b/chrome/browser/android/vr/vr_gl_thread.h
@@ -130,6 +130,8 @@ const CapturingStateModel& potential_capturing) override; void ShowExitVrPrompt(UiUnsupportedMode reason) override; void SetSpeechRecognitionEnabled(bool enabled) override; + void SetHasOrCanRequestRecordAudioPermission( + bool has_or_can_request_record_audio) override; void SetRecognitionResult(const base::string16& result) override; void OnSpeechRecognitionStateChanged(int new_state) override; void SetOmniboxSuggestions(
diff --git a/chrome/browser/android/vr/vr_shell.cc b/chrome/browser/android/vr/vr_shell.cc index 8dc3df1..e31b54df 100644 --- a/chrome/browser/android/vr/vr_shell.cc +++ b/chrome/browser/android/vr/vr_shell.cc
@@ -947,7 +947,7 @@ if (!active && !speech_recognizer_) return; - if (!HasAudioPermission()) { + if (!HasRecordAudioPermission()) { OnUnsupportedMode( UiUnsupportedMode::kVoiceSearchNeedsRecordAudioOsPermission); return; @@ -986,9 +986,24 @@ Java_VrShell_showPageInfo(base::android::AttachCurrentThread(), j_vr_shell_); } -bool VrShell::HasAudioPermission() { +bool VrShell::HasRecordAudioPermission() const { JNIEnv* env = base::android::AttachCurrentThread(); - return Java_VrShell_hasAudioPermission(env, j_vr_shell_); + return Java_VrShell_hasRecordAudioPermission(env, j_vr_shell_); +} + +bool VrShell::CanRequestRecordAudioPermission() const { + JNIEnv* env = base::android::AttachCurrentThread(); + return Java_VrShell_canRequestRecordAudioPermission(env, j_vr_shell_); +} + +void VrShell::RequestRecordAudioPermissionResult( + JNIEnv* env, + const base::android::JavaParamRef<jobject>& object, + jboolean can_record_audio) { + // If permission was denied, we need to check if it was *permanently* denied. + if (!can_record_audio && !CanRequestRecordAudioPermission()) { + ui_->SetHasOrCanRequestRecordAudioPermission(false); + } } void VrShell::PollCapturingState() { @@ -1352,7 +1367,7 @@ const JavaParamRef<jobject>& delegate, jboolean for_web_vr, jboolean browsing_disabled, - jboolean has_or_can_request_audio_permission, + jboolean has_or_can_request_record_audio_permission, jlong gvr_api, jboolean reprojected_rendering, jfloat display_width_meters, @@ -1365,8 +1380,8 @@ UiInitialState ui_initial_state; ui_initial_state.browsing_disabled = browsing_disabled; ui_initial_state.in_web_vr = for_web_vr; - ui_initial_state.has_or_can_request_audio_permission = - has_or_can_request_audio_permission; + ui_initial_state.has_or_can_request_record_audio_permission = + has_or_can_request_record_audio_permission; ui_initial_state.assets_supported = AssetsLoader::AssetsSupported(); ui_initial_state.is_standalone_vr_device = is_standalone_vr_device; ui_initial_state.use_new_incognito_strings =
diff --git a/chrome/browser/android/vr/vr_shell.h b/chrome/browser/android/vr/vr_shell.h index 25aa514..2a404d96 100644 --- a/chrome/browser/android/vr/vr_shell.h +++ b/chrome/browser/android/vr/vr_shell.h
@@ -205,7 +205,12 @@ void StartAutocomplete(const AutocompleteRequest& request); void StopAutocomplete(); void ShowPageInfo(); - bool HasAudioPermission(); + bool HasRecordAudioPermission() const; + bool CanRequestRecordAudioPermission() const; + void RequestRecordAudioPermissionResult( + JNIEnv* env, + const base::android::JavaParamRef<jobject>& object, + jboolean can_record_audio); void ClearFocusedElement(); void ProcessContentGesture(std::unique_ptr<InputEvent> event, int content_id);
diff --git a/chrome/browser/apps/app_service/arc_apps.cc b/chrome/browser/apps/app_service/arc_apps.cc index 095967e..832ea6b 100644 --- a/chrome/browser/apps/app_service/arc_apps.cc +++ b/chrome/browser/apps/app_service/arc_apps.cc
@@ -237,6 +237,50 @@ } } +void ArcApps::OnAppRegistered(const std::string& app_id, + const ArcAppListPrefs::AppInfo& app_info) { + OnAppStatesChanged(app_id, app_info); +} + +void ArcApps::OnAppStatesChanged(const std::string& app_id, + const ArcAppListPrefs::AppInfo& app_info) { + apps::mojom::AppPtr app = apps::mojom::App::New(); + app->app_type = apps::mojom::AppType::kArc; + app->app_id = app_id; + app->readiness = NewReadiness(app_info.ready); + Publish(std::move(app)); +} + +void ArcApps::OnAppRemoved(const std::string& app_id) { + apps::mojom::AppPtr app = apps::mojom::App::New(); + app->app_type = apps::mojom::AppType::kArc; + app->app_id = app_id; + app->readiness = NewReadiness(false); + Publish(std::move(app)); +} + +void ArcApps::OnAppIconUpdated(const std::string& app_id, + const ArcAppIconDescriptor& descriptor) { + apps::mojom::AppPtr app = apps::mojom::App::New(); + app->app_type = apps::mojom::AppType::kArc; + app->app_id = app_id; + app->icon_key = NewIconKey(app_id); + Publish(std::move(app)); +} + +void ArcApps::OnAppNameUpdated(const std::string& app_id, + const std::string& name) { + apps::mojom::AppPtr app = apps::mojom::App::New(); + app->app_type = apps::mojom::AppType::kArc; + app->app_id = app_id; + app->name = name; + Publish(std::move(app)); +} + +void ArcApps::OnAppLastLaunchTimeUpdated(const std::string& app_id) { + // TODO(crbug.com/826982): implement. +} + void ArcApps::ObservePrefs() { prefs_->AddObserver(this); prefs_->app_connection_holder()->AddObserver(this); @@ -248,13 +292,10 @@ app->app_type = apps::mojom::AppType::kArc; app->app_id = app_id; - app->readiness = apps::mojom::Readiness::kReady; + app->readiness = NewReadiness(app_info.ready); app->name = app_info.name; - app->icon_key = apps::mojom::IconKey::New(); - app->icon_key->icon_type = apps::mojom::IconType::kArc; - app->icon_key->s_key = app_id; - app->icon_key->u_key = next_u_key_++; + app->icon_key = NewIconKey(app_id); bool installed_internally = prefs_->IsDefault(app_id) || @@ -271,4 +312,29 @@ return app; } +apps::mojom::IconKeyPtr ArcApps::NewIconKey(const std::string& app_id) { + auto icon_key = apps::mojom::IconKey::New(); + icon_key->icon_type = apps::mojom::IconType::kArc; + icon_key->s_key = app_id; + icon_key->u_key = next_u_key_++; + return icon_key; +} + +// static +apps::mojom::Readiness ArcApps::NewReadiness(bool ready) { + // TODO(crbug.com/826982): examine ArcAppListPrefs::AppInfo::suspended, and + // possibly have a corresponding 'suspended' apps::mojom::Readiness enum + // value. + return ready ? apps::mojom::Readiness::kReady + : apps::mojom::Readiness::kUninstalledByUser; +} + +void ArcApps::Publish(apps::mojom::AppPtr app) { + subscribers_.ForAllPtrs([&app](apps::mojom::Subscriber* subscriber) { + std::vector<apps::mojom::AppPtr> apps; + apps.push_back(app.Clone()); + subscriber->OnApps(std::move(apps)); + }); +} + } // namespace apps
diff --git a/chrome/browser/apps/app_service/arc_apps.h b/chrome/browser/apps/app_service/arc_apps.h index a83c46859..14d4dc05 100644 --- a/chrome/browser/apps/app_service/arc_apps.h +++ b/chrome/browser/apps/app_service/arc_apps.h
@@ -60,12 +60,24 @@ void OnConnectionReady() override; // ArcAppListPrefs::Observer overrides. - // TODO(crbug.com/826982): implement. + void OnAppRegistered(const std::string& app_id, + const ArcAppListPrefs::AppInfo& app_info) override; + void OnAppStatesChanged(const std::string& app_id, + const ArcAppListPrefs::AppInfo& app_info) override; + void OnAppRemoved(const std::string& app_id) override; + void OnAppIconUpdated(const std::string& app_id, + const ArcAppIconDescriptor& descriptor) override; + void OnAppNameUpdated(const std::string& app_id, + const std::string& name) override; + void OnAppLastLaunchTimeUpdated(const std::string& app_id) override; void ObservePrefs(); apps::mojom::AppPtr Convert(const std::string& app_id, const ArcAppListPrefs::AppInfo& app_info); + apps::mojom::IconKeyPtr NewIconKey(const std::string& app_id); + static apps::mojom::Readiness NewReadiness(bool ready); + void Publish(apps::mojom::AppPtr app); mojo::Binding<apps::mojom::Publisher> binding_; mojo::InterfacePtrSet<apps::mojom::Subscriber> subscribers_;
diff --git a/chrome/browser/browser_resources.grd b/chrome/browser/browser_resources.grd index 7b7ff54..b08c482 100644 --- a/chrome/browser/browser_resources.grd +++ b/chrome/browser/browser_resources.grd
@@ -269,61 +269,61 @@ </if> <if expr="not is_android"> - <!-- MD Bookmarks. --> - <include name="IDR_MD_BOOKMARKS_IMAGES_FOLDER_OPEN_SVG" file="resources\bookmarks\images\folder_open.svg" type="BINDATA" /> - <include name="IDR_MD_BOOKMARKS_IMAGES_FOLDER_SVG" file="resources\bookmarks\images\folder.svg" type="BINDATA" /> + <!-- Bookmarks WebUI. --> + <include name="IDR_BOOKMARKS_IMAGES_FOLDER_OPEN_SVG" file="resources\bookmarks\images\folder_open.svg" type="BINDATA" /> + <include name="IDR_BOOKMARKS_IMAGES_FOLDER_SVG" file="resources\bookmarks\images\folder.svg" type="BINDATA" /> <if expr="optimize_webui"> <then> - <include name="IDR_MD_BOOKMARKS_VULCANIZED_HTML" file="${root_gen_dir}\chrome\browser\resources\bookmarks\vulcanized.html" use_base_dir="false" preprocess="true" type="BINDATA" compress="gzip" /> - <include name="IDR_MD_BOOKMARKS_VULCANIZED_P2_HTML" file="${root_gen_dir}\chrome\browser\resources\bookmarks\vulcanized.p2.html" use_base_dir="false" preprocess="true" type="BINDATA" compress="gzip" /> - <include name="IDR_MD_BOOKMARKS_CRISPER_JS" file="${root_gen_dir}\chrome\browser\resources\bookmarks\crisper.js" use_base_dir="false" preprocess="true" type="BINDATA" compress="gzip" /> + <include name="IDR_BOOKMARKS_VULCANIZED_HTML" file="${root_gen_dir}\chrome\browser\resources\bookmarks\vulcanized.html" use_base_dir="false" preprocess="true" type="BINDATA" compress="gzip" /> + <include name="IDR_BOOKMARKS_VULCANIZED_P2_HTML" file="${root_gen_dir}\chrome\browser\resources\bookmarks\vulcanized.p2.html" use_base_dir="false" preprocess="true" type="BINDATA" compress="gzip" /> + <include name="IDR_BOOKMARKS_CRISPER_JS" file="${root_gen_dir}\chrome\browser\resources\bookmarks\crisper.js" use_base_dir="false" preprocess="true" type="BINDATA" compress="gzip" /> </then> <else> - <include name="IDR_MD_BOOKMARKS_ACTIONS_HTML" file="resources\bookmarks\actions.html" type="BINDATA" /> - <include name="IDR_MD_BOOKMARKS_ACTIONS_JS" file="resources\bookmarks\actions.js" type="BINDATA" /> - <include name="IDR_MD_BOOKMARKS_API_LISTENER_HTML" file="resources\bookmarks\api_listener.html" type="BINDATA" /> - <include name="IDR_MD_BOOKMARKS_API_LISTENER_JS" file="resources\bookmarks\api_listener.js" type="BINDATA" /> - <include name="IDR_MD_BOOKMARKS_APP_HTML" file="resources\bookmarks\app.html" type="BINDATA" preprocess="true" /> - <include name="IDR_MD_BOOKMARKS_APP_JS" file="resources\bookmarks\app.js" type="BINDATA" /> - <include name="IDR_MD_BOOKMARKS_BOOKMARKS_HTML" file="resources\bookmarks\bookmarks.html" type="BINDATA" /> - <include name="IDR_MD_BOOKMARKS_COMMAND_MANAGER_HTML" file="resources\bookmarks\command_manager.html" type="BINDATA" /> - <include name="IDR_MD_BOOKMARKS_COMMAND_MANAGER_JS" file="resources\bookmarks\command_manager.js" type="BINDATA" /> - <include name="IDR_MD_BOOKMARKS_CONSTANTS_HTML" file="resources\bookmarks\constants.html" type="BINDATA" /> - <include name="IDR_MD_BOOKMARKS_CONSTANTS_JS" file="resources\bookmarks\constants.js" type="BINDATA" /> - <include name="IDR_MD_BOOKMARKS_DEBOUNCER_HTML" file="resources\bookmarks\debouncer.html" type="BINDATA" /> - <include name="IDR_MD_BOOKMARKS_DEBOUNCER_JS" file="resources\bookmarks\debouncer.js" type="BINDATA" /> - <include name="IDR_MD_BOOKMARKS_DIALOG_FOCUS_MANAGER_HTML" file="resources\bookmarks\dialog_focus_manager.html" type="BINDATA" /> - <include name="IDR_MD_BOOKMARKS_DIALOG_FOCUS_MANAGER_JS" file="resources\bookmarks\dialog_focus_manager.js" type="BINDATA" /> - <include name="IDR_MD_BOOKMARKS_DND_MANAGER_HTML" file="resources\bookmarks\dnd_manager.html" type="BINDATA" /> - <include name="IDR_MD_BOOKMARKS_DND_MANAGER_JS" file="resources\bookmarks\dnd_manager.js" type="BINDATA" /> - <include name="IDR_MD_BOOKMARKS_EDIT_DIALOG_HTML" file="resources\bookmarks\edit_dialog.html" type="BINDATA" /> - <include name="IDR_MD_BOOKMARKS_EDIT_DIALOG_JS" file="resources\bookmarks\edit_dialog.js" type="BINDATA" /> - <include name="IDR_MD_BOOKMARKS_FOLDER_NODE_HTML" file="resources\bookmarks\folder_node.html" type="BINDATA" /> - <include name="IDR_MD_BOOKMARKS_FOLDER_NODE_JS" file="resources\bookmarks\folder_node.js" type="BINDATA" /> - <include name="IDR_MD_BOOKMARKS_ITEM_HTML" file="resources\bookmarks\item.html" type="BINDATA" /> - <include name="IDR_MD_BOOKMARKS_ITEM_JS" file="resources\bookmarks\item.js" type="BINDATA" /> - <include name="IDR_MD_BOOKMARKS_LIST_HTML" file="resources\bookmarks\list.html" type="BINDATA" /> - <include name="IDR_MD_BOOKMARKS_LIST_JS" file="resources\bookmarks\list.js" type="BINDATA" /> - <include name="IDR_MD_BOOKMARKS_MOUSE_FOCUS_BEHAVIOR_HTML" file="resources\bookmarks\mouse_focus_behavior.html" type="BINDATA" /> - <include name="IDR_MD_BOOKMARKS_MOUSE_FOCUS_BEHAVIOR_JS" file="resources\bookmarks\mouse_focus_behavior.js" type="BINDATA" /> - <include name="IDR_MD_BOOKMARKS_REDUCERS_HTML" file="resources\bookmarks\reducers.html" type="BINDATA" /> - <include name="IDR_MD_BOOKMARKS_REDUCERS_JS" file="resources\bookmarks\reducers.js" type="BINDATA" /> - <include name="IDR_MD_BOOKMARKS_ROUTER_HTML" file="resources\bookmarks\router.html" type="BINDATA" /> - <include name="IDR_MD_BOOKMARKS_ROUTER_JS" file="resources\bookmarks\router.js" type="BINDATA" /> - <include name="IDR_MD_BOOKMARKS_SHARED_STYLE_HTML" file="resources\bookmarks\shared_style.html" type="BINDATA" /> - <include name="IDR_MD_BOOKMARKS_SHARED_VARS_HTML" file="resources\bookmarks\shared_vars.html" type="BINDATA" /> - <include name="IDR_MD_BOOKMARKS_STORE_CLIENT_HTML" file="resources\bookmarks\store_client.html" type="BINDATA" /> - <include name="IDR_MD_BOOKMARKS_STORE_CLIENT_JS" file="resources\bookmarks\store_client.js" type="BINDATA" /> - <include name="IDR_MD_BOOKMARKS_STORE_HTML" file="resources\bookmarks\store.html" type="BINDATA" /> - <include name="IDR_MD_BOOKMARKS_STORE_JS" file="resources\bookmarks\store.js" type="BINDATA" /> - <include name="IDR_MD_BOOKMARKS_STRINGS_HTML" file="resources\bookmarks\strings.html" type="BINDATA" /> + <include name="IDR_BOOKMARKS_ACTIONS_HTML" file="resources\bookmarks\actions.html" type="BINDATA" /> + <include name="IDR_BOOKMARKS_ACTIONS_JS" file="resources\bookmarks\actions.js" type="BINDATA" /> + <include name="IDR_BOOKMARKS_API_LISTENER_HTML" file="resources\bookmarks\api_listener.html" type="BINDATA" /> + <include name="IDR_BOOKMARKS_API_LISTENER_JS" file="resources\bookmarks\api_listener.js" type="BINDATA" /> + <include name="IDR_BOOKMARKS_APP_HTML" file="resources\bookmarks\app.html" type="BINDATA" preprocess="true" /> + <include name="IDR_BOOKMARKS_APP_JS" file="resources\bookmarks\app.js" type="BINDATA" /> + <include name="IDR_BOOKMARKS_BOOKMARKS_HTML" file="resources\bookmarks\bookmarks.html" type="BINDATA" /> + <include name="IDR_BOOKMARKS_COMMAND_MANAGER_HTML" file="resources\bookmarks\command_manager.html" type="BINDATA" /> + <include name="IDR_BOOKMARKS_COMMAND_MANAGER_JS" file="resources\bookmarks\command_manager.js" type="BINDATA" /> + <include name="IDR_BOOKMARKS_CONSTANTS_HTML" file="resources\bookmarks\constants.html" type="BINDATA" /> + <include name="IDR_BOOKMARKS_CONSTANTS_JS" file="resources\bookmarks\constants.js" type="BINDATA" /> + <include name="IDR_BOOKMARKS_DEBOUNCER_HTML" file="resources\bookmarks\debouncer.html" type="BINDATA" /> + <include name="IDR_BOOKMARKS_DEBOUNCER_JS" file="resources\bookmarks\debouncer.js" type="BINDATA" /> + <include name="IDR_BOOKMARKS_DIALOG_FOCUS_MANAGER_HTML" file="resources\bookmarks\dialog_focus_manager.html" type="BINDATA" /> + <include name="IDR_BOOKMARKS_DIALOG_FOCUS_MANAGER_JS" file="resources\bookmarks\dialog_focus_manager.js" type="BINDATA" /> + <include name="IDR_BOOKMARKS_DND_MANAGER_HTML" file="resources\bookmarks\dnd_manager.html" type="BINDATA" /> + <include name="IDR_BOOKMARKS_DND_MANAGER_JS" file="resources\bookmarks\dnd_manager.js" type="BINDATA" /> + <include name="IDR_BOOKMARKS_EDIT_DIALOG_HTML" file="resources\bookmarks\edit_dialog.html" type="BINDATA" /> + <include name="IDR_BOOKMARKS_EDIT_DIALOG_JS" file="resources\bookmarks\edit_dialog.js" type="BINDATA" /> + <include name="IDR_BOOKMARKS_FOLDER_NODE_HTML" file="resources\bookmarks\folder_node.html" type="BINDATA" /> + <include name="IDR_BOOKMARKS_FOLDER_NODE_JS" file="resources\bookmarks\folder_node.js" type="BINDATA" /> + <include name="IDR_BOOKMARKS_ITEM_HTML" file="resources\bookmarks\item.html" type="BINDATA" /> + <include name="IDR_BOOKMARKS_ITEM_JS" file="resources\bookmarks\item.js" type="BINDATA" /> + <include name="IDR_BOOKMARKS_LIST_HTML" file="resources\bookmarks\list.html" type="BINDATA" /> + <include name="IDR_BOOKMARKS_LIST_JS" file="resources\bookmarks\list.js" type="BINDATA" /> + <include name="IDR_BOOKMARKS_MOUSE_FOCUS_BEHAVIOR_HTML" file="resources\bookmarks\mouse_focus_behavior.html" type="BINDATA" /> + <include name="IDR_BOOKMARKS_MOUSE_FOCUS_BEHAVIOR_JS" file="resources\bookmarks\mouse_focus_behavior.js" type="BINDATA" /> + <include name="IDR_BOOKMARKS_REDUCERS_HTML" file="resources\bookmarks\reducers.html" type="BINDATA" /> + <include name="IDR_BOOKMARKS_REDUCERS_JS" file="resources\bookmarks\reducers.js" type="BINDATA" /> + <include name="IDR_BOOKMARKS_ROUTER_HTML" file="resources\bookmarks\router.html" type="BINDATA" /> + <include name="IDR_BOOKMARKS_ROUTER_JS" file="resources\bookmarks\router.js" type="BINDATA" /> + <include name="IDR_BOOKMARKS_SHARED_STYLE_HTML" file="resources\bookmarks\shared_style.html" type="BINDATA" /> + <include name="IDR_BOOKMARKS_SHARED_VARS_HTML" file="resources\bookmarks\shared_vars.html" type="BINDATA" /> + <include name="IDR_BOOKMARKS_STORE_CLIENT_HTML" file="resources\bookmarks\store_client.html" type="BINDATA" /> + <include name="IDR_BOOKMARKS_STORE_CLIENT_JS" file="resources\bookmarks\store_client.js" type="BINDATA" /> + <include name="IDR_BOOKMARKS_STORE_HTML" file="resources\bookmarks\store.html" type="BINDATA" /> + <include name="IDR_BOOKMARKS_STORE_JS" file="resources\bookmarks\store.js" type="BINDATA" /> + <include name="IDR_BOOKMARKS_STRINGS_HTML" file="resources\bookmarks\strings.html" type="BINDATA" /> - <include name="IDR_MD_BOOKMARKS_TOAST_MANAGER_HTML" file="resources\bookmarks\toast_manager.html" type="BINDATA" /> - <include name="IDR_MD_BOOKMARKS_TOAST_MANAGER_JS" file="resources\bookmarks\toast_manager.js" type="BINDATA" /> - <include name="IDR_MD_BOOKMARKS_TOOLBAR_HTML" file="resources\bookmarks\toolbar.html" type="BINDATA" /> - <include name="IDR_MD_BOOKMARKS_TOOLBAR_JS" file="resources\bookmarks\toolbar.js" type="BINDATA" /> - <include name="IDR_MD_BOOKMARKS_UTIL_HTML" file="resources\bookmarks\util.html" type="BINDATA" /> - <include name="IDR_MD_BOOKMARKS_UTIL_JS" file="resources\bookmarks\util.js" type="BINDATA" /> + <include name="IDR_BOOKMARKS_TOAST_MANAGER_HTML" file="resources\bookmarks\toast_manager.html" type="BINDATA" /> + <include name="IDR_BOOKMARKS_TOAST_MANAGER_JS" file="resources\bookmarks\toast_manager.js" type="BINDATA" /> + <include name="IDR_BOOKMARKS_TOOLBAR_HTML" file="resources\bookmarks\toolbar.html" type="BINDATA" /> + <include name="IDR_BOOKMARKS_TOOLBAR_JS" file="resources\bookmarks\toolbar.js" type="BINDATA" /> + <include name="IDR_BOOKMARKS_UTIL_HTML" file="resources\bookmarks\util.html" type="BINDATA" /> + <include name="IDR_BOOKMARKS_UTIL_JS" file="resources\bookmarks\util.js" type="BINDATA" /> </else> </if> @@ -498,6 +498,14 @@ <include name="IDR_BLUETOOTH_PAIRING_DIALOG_JS" file="resources\chromeos\bluetooth_pairing_dialog\bluetooth_pairing_dialog.js" type="chrome_html" /> </else> </if> + <!-- Chrome OS Account Manager welcome screen resources --> + <include name="IDR_ACCOUNT_MANAGER_WELCOME_CSS" file="resources\chromeos\account_manager_welcome.css" flattenhtml="true" type="chrome_html" /> + <include name="IDR_ACCOUNT_MANAGER_WELCOME_HTML" file="resources\chromeos\account_manager_welcome.html" allowexternalscript="true" flattenhtml="true" type="chrome_html" /> + <include name="IDR_ACCOUNT_MANAGER_WELCOME_JS" file="resources\chromeos\account_manager_welcome.js" flattenhtml="true" type="chrome_html" /> + <include name="IDR_ACCOUNT_MANAGER_WELCOME_1X_PNG" file="resources\chromeos\account_manager_welcome_1x.png" type="BINDATA" /> + <include name="IDR_ACCOUNT_MANAGER_WELCOME_2X_PNG" file="resources\chromeos\account_manager_welcome_2x.png" type="BINDATA" /> + <include name="IDR_ACCOUNT_MANAGER_WELCOME_GOOGLE_LOGO_SVG" file="resources\chromeos\googleg.svg" type="BINDATA" /> + <include name="IDR_CROSH_BUILTIN_MANIFEST" file="resources\chromeos\crosh_builtin\manifest.json" type="BINDATA" /> <include name="IDR_CRYPTOHOME_HTML" file="resources\chromeos\cryptohome.html" flattenhtml="true" type="BINDATA" /> <include name="IDR_CRYPTOHOME_JS" file="resources\chromeos\cryptohome.js" type="BINDATA" />
diff --git a/chrome/browser/browsing_data/cookies_tree_model.cc b/chrome/browser/browsing_data/cookies_tree_model.cc index e365b84d..9cd3d365 100644 --- a/chrome/browser/browsing_data/cookies_tree_model.cc +++ b/chrome/browser/browsing_data/cookies_tree_model.cc
@@ -387,8 +387,8 @@ } void RetrieveSize(const SizeRetrievalCallback& callback) override { - callback.Run(this->GetDetailedInfo().origin, - this->GetDetailedInfo().appcache_info->size); + const DetailedInfo info = GetDetailedInfo(); + callback.Run(info.origin, info.appcache_info->size); } private: @@ -432,8 +432,8 @@ } void RetrieveSize(const SizeRetrievalCallback& callback) override { - callback.Run(this->GetDetailedInfo().origin, - this->GetDetailedInfo().database_info->size); + const DetailedInfo info = GetDetailedInfo(); + callback.Run(info.origin, info.database_info->size); } private: @@ -475,8 +475,8 @@ } void RetrieveSize(const SizeRetrievalCallback& callback) override { - callback.Run(this->GetDetailedInfo().origin, - this->GetDetailedInfo().local_storage_info->size); + const DetailedInfo info = GetDetailedInfo(); + callback.Run(info.origin, info.local_storage_info->size); } private: @@ -559,8 +559,8 @@ } void RetrieveSize(const SizeRetrievalCallback& callback) override { - callback.Run(this->GetDetailedInfo().origin, - this->GetDetailedInfo().usage_info->total_size_bytes); + const DetailedInfo info = GetDetailedInfo(); + callback.Run(info.origin, info.usage_info->total_size_bytes); } private: @@ -603,11 +603,11 @@ void RetrieveSize(const SizeRetrievalCallback& callback) override { int64_t size = 0; - for (auto const& usage : - this->GetDetailedInfo().file_system_info->usage_map) { + const DetailedInfo info = GetDetailedInfo(); + for (auto const& usage : info.file_system_info->usage_map) { size += usage.second; } - callback.Run(this->GetDetailedInfo().origin, size); + callback.Run(info.origin, size); } private: @@ -686,8 +686,8 @@ } void RetrieveSize(const SizeRetrievalCallback& callback) override { - callback.Run(this->GetDetailedInfo().origin, - this->GetDetailedInfo().usage_info->total_size_bytes); + const DetailedInfo info = GetDetailedInfo(); + callback.Run(info.origin, info.usage_info->total_size_bytes); } private: @@ -768,8 +768,8 @@ } void RetrieveSize(const SizeRetrievalCallback& callback) override { - callback.Run(this->GetDetailedInfo().origin, - this->GetDetailedInfo().usage_info->total_size_bytes); + const DetailedInfo info = GetDetailedInfo(); + callback.Run(info.origin, info.usage_info->total_size_bytes); } private: @@ -806,13 +806,14 @@ container->media_license_info_list_.erase(media_license_info_); } } + DetailedInfo GetDetailedInfo() const override { return DetailedInfo().InitMediaLicense(&*media_license_info_); } void RetrieveSize(const SizeRetrievalCallback& callback) override { - callback.Run(this->GetDetailedInfo().origin, - this->GetDetailedInfo().media_license_info->size); + const DetailedInfo info = GetDetailedInfo(); + callback.Run(info.origin, info.media_license_info->size); } private: @@ -887,12 +888,32 @@ }; /////////////////////////////////////////////////////////////////////////////// +// CookieTreeCollectionNode + +class CookieTreeCollectionNode : public CookieTreeNode { + public: + explicit CookieTreeCollectionNode(const base::string16& title) + : CookieTreeNode(title) {} + + ~CookieTreeCollectionNode() override {} + + void RetrieveSize(const SizeRetrievalCallback& callback) final { + for (int i = 0; i < this->child_count(); ++i) { + this->GetChild(i)->RetrieveSize(callback); + } + } + + private: + DISALLOW_COPY_AND_ASSIGN(CookieTreeCollectionNode); +}; + +/////////////////////////////////////////////////////////////////////////////// // CookieTreeAppCachesNode -class CookieTreeAppCachesNode : public CookieTreeNode { +class CookieTreeAppCachesNode : public CookieTreeCollectionNode { public: CookieTreeAppCachesNode() - : CookieTreeNode( + : CookieTreeCollectionNode( l10n_util::GetStringUTF16(IDS_COOKIES_APPLICATION_CACHES)) {} ~CookieTreeAppCachesNode() override {} @@ -901,12 +922,6 @@ return DetailedInfo().Init(DetailedInfo::TYPE_APPCACHES); } - void RetrieveSize(const SizeRetrievalCallback& callback) override { - for (int i = 0; i < this->child_count(); ++i) { - this->GetChild(i)->RetrieveSize(callback); - } - } - void AddAppCacheNode(std::unique_ptr<CookieTreeAppCacheNode> child) { AddChildSortedByTitle(std::move(child)); } @@ -918,10 +933,11 @@ /////////////////////////////////////////////////////////////////////////////// // CookieTreeDatabasesNode -class CookieTreeDatabasesNode : public CookieTreeNode { +class CookieTreeDatabasesNode : public CookieTreeCollectionNode { public: CookieTreeDatabasesNode() - : CookieTreeNode(l10n_util::GetStringUTF16(IDS_COOKIES_WEB_DATABASES)) {} + : CookieTreeCollectionNode( + l10n_util::GetStringUTF16(IDS_COOKIES_WEB_DATABASES)) {} ~CookieTreeDatabasesNode() override {} @@ -929,12 +945,6 @@ return DetailedInfo().Init(DetailedInfo::TYPE_DATABASES); } - void RetrieveSize(const SizeRetrievalCallback& callback) override { - for (int i = 0; i < this->child_count(); ++i) { - this->GetChild(i)->RetrieveSize(callback); - } - } - void AddDatabaseNode(std::unique_ptr<CookieTreeDatabaseNode> child) { AddChildSortedByTitle(std::move(child)); } @@ -946,10 +956,11 @@ /////////////////////////////////////////////////////////////////////////////// // CookieTreeLocalStoragesNode -class CookieTreeLocalStoragesNode : public CookieTreeNode { +class CookieTreeLocalStoragesNode : public CookieTreeCollectionNode { public: CookieTreeLocalStoragesNode() - : CookieTreeNode(l10n_util::GetStringUTF16(IDS_COOKIES_LOCAL_STORAGE)) {} + : CookieTreeCollectionNode( + l10n_util::GetStringUTF16(IDS_COOKIES_LOCAL_STORAGE)) {} ~CookieTreeLocalStoragesNode() override {} @@ -957,12 +968,6 @@ return DetailedInfo().Init(DetailedInfo::TYPE_LOCAL_STORAGES); } - void RetrieveSize(const SizeRetrievalCallback& callback) override { - for (int i = 0; i < this->child_count(); ++i) { - this->GetChild(i)->RetrieveSize(callback); - } - } - void AddLocalStorageNode(std::unique_ptr<CookieTreeLocalStorageNode> child) { AddChildSortedByTitle(std::move(child)); } @@ -998,10 +1003,11 @@ /////////////////////////////////////////////////////////////////////////////// // CookieTreeIndexedDBsNode -class CookieTreeIndexedDBsNode : public CookieTreeNode { +class CookieTreeIndexedDBsNode : public CookieTreeCollectionNode { public: CookieTreeIndexedDBsNode() - : CookieTreeNode(l10n_util::GetStringUTF16(IDS_COOKIES_INDEXED_DBS)) {} + : CookieTreeCollectionNode( + l10n_util::GetStringUTF16(IDS_COOKIES_INDEXED_DBS)) {} ~CookieTreeIndexedDBsNode() override {} @@ -1009,12 +1015,6 @@ return DetailedInfo().Init(DetailedInfo::TYPE_INDEXED_DBS); } - void RetrieveSize(const SizeRetrievalCallback& callback) override { - for (int i = 0; i < this->child_count(); ++i) { - this->GetChild(i)->RetrieveSize(callback); - } - } - void AddIndexedDBNode(std::unique_ptr<CookieTreeIndexedDBNode> child) { AddChildSortedByTitle(std::move(child)); } @@ -1026,10 +1026,11 @@ /////////////////////////////////////////////////////////////////////////////// // CookieTreeFileSystemsNode -class CookieTreeFileSystemsNode : public CookieTreeNode { +class CookieTreeFileSystemsNode : public CookieTreeCollectionNode { public: CookieTreeFileSystemsNode() - : CookieTreeNode(l10n_util::GetStringUTF16(IDS_COOKIES_FILE_SYSTEMS)) {} + : CookieTreeCollectionNode( + l10n_util::GetStringUTF16(IDS_COOKIES_FILE_SYSTEMS)) {} ~CookieTreeFileSystemsNode() override {} @@ -1037,12 +1038,6 @@ return DetailedInfo().Init(DetailedInfo::TYPE_FILE_SYSTEMS); } - void RetrieveSize(const SizeRetrievalCallback& callback) override { - for (int i = 0; i < this->child_count(); ++i) { - this->GetChild(i)->RetrieveSize(callback); - } - } - void AddFileSystemNode(std::unique_ptr<CookieTreeFileSystemNode> child) { AddChildSortedByTitle(std::move(child)); } @@ -1054,11 +1049,11 @@ /////////////////////////////////////////////////////////////////////////////// // CookieTreeServiceWorkersNode -class CookieTreeServiceWorkersNode : public CookieTreeNode { +class CookieTreeServiceWorkersNode : public CookieTreeCollectionNode { public: CookieTreeServiceWorkersNode() - : CookieTreeNode(l10n_util::GetStringUTF16(IDS_COOKIES_SERVICE_WORKERS)) { - } + : CookieTreeCollectionNode( + l10n_util::GetStringUTF16(IDS_COOKIES_SERVICE_WORKERS)) {} ~CookieTreeServiceWorkersNode() override {} @@ -1066,12 +1061,6 @@ return DetailedInfo().Init(DetailedInfo::TYPE_SERVICE_WORKERS); } - void RetrieveSize(const SizeRetrievalCallback& callback) override { - for (int i = 0; i < this->child_count(); ++i) { - this->GetChild(i)->RetrieveSize(callback); - } - } - void AddServiceWorkerNode( std::unique_ptr<CookieTreeServiceWorkerNode> child) { AddChildSortedByTitle(std::move(child)); @@ -1106,10 +1095,11 @@ /////////////////////////////////////////////////////////////////////////////// // CookieTreeCacheStoragesNode -class CookieTreeCacheStoragesNode : public CookieTreeNode { +class CookieTreeCacheStoragesNode : public CookieTreeCollectionNode { public: CookieTreeCacheStoragesNode() - : CookieTreeNode(l10n_util::GetStringUTF16(IDS_COOKIES_CACHE_STORAGE)) {} + : CookieTreeCollectionNode( + l10n_util::GetStringUTF16(IDS_COOKIES_CACHE_STORAGE)) {} ~CookieTreeCacheStoragesNode() override {} @@ -1117,12 +1107,6 @@ return DetailedInfo().Init(DetailedInfo::TYPE_CACHE_STORAGES); } - void RetrieveSize(const SizeRetrievalCallback& callback) override { - for (int i = 0; i < this->child_count(); ++i) { - this->GetChild(i)->RetrieveSize(callback); - } - } - void AddCacheStorageNode(std::unique_ptr<CookieTreeCacheStorageNode> child) { AddChildSortedByTitle(std::move(child)); } @@ -1166,10 +1150,11 @@ /////////////////////////////////////////////////////////////////////////////// // CookieTreeMediaLicensesNode -class CookieTreeMediaLicensesNode : public CookieTreeNode { +class CookieTreeMediaLicensesNode : public CookieTreeCollectionNode { public: CookieTreeMediaLicensesNode() - : CookieTreeNode(l10n_util::GetStringUTF16(IDS_COOKIES_MEDIA_LICENSES)) {} + : CookieTreeCollectionNode( + l10n_util::GetStringUTF16(IDS_COOKIES_MEDIA_LICENSES)) {} ~CookieTreeMediaLicensesNode() override {} @@ -1177,12 +1162,6 @@ return DetailedInfo().Init(DetailedInfo::TYPE_MEDIA_LICENSES); } - void RetrieveSize(const SizeRetrievalCallback& callback) override { - for (int i = 0; i < this->child_count(); ++i) { - this->GetChild(i)->RetrieveSize(callback); - } - } - void AddMediaLicenseNode(std::unique_ptr<CookieTreeMediaLicenseNode> child) { AddChildSortedByTitle(std::move(child)); }
diff --git a/chrome/browser/chrome_browser_main_mac.mm b/chrome/browser/chrome_browser_main_mac.mm index ea96e17..cff6866 100644 --- a/chrome/browser/chrome_browser_main_mac.mm +++ b/chrome/browser/chrome_browser_main_mac.mm
@@ -6,6 +6,9 @@ #import <Cocoa/Cocoa.h> #include <libproc.h> +#include <stdlib.h> +#include <sys/mount.h> +#include <sys/param.h> #include "base/command_line.h" #include "base/files/file_path.h" @@ -16,6 +19,7 @@ #include "base/mac/scoped_nsobject.h" #include "base/mac/sdk_forward_declarations.h" #include "base/metrics/histogram_macros.h" +#include "base/optional.h" #include "base/path_service.h" #include "base/task/post_task.h" #include "base/task/task_traits.h" @@ -251,12 +255,151 @@ }]; } +bool IsDirectoryWriteable(NSString* dir_path) { + NSString* file_path = [dir_path stringByAppendingPathComponent:@"tempfile"]; + NSData* data = [NSData dataWithBytes:"\01\02\03\04\05" length:5]; + BOOL success = [data writeToFile:file_path atomically:NO]; + if (success) + [[NSFileManager defaultManager] removeItemAtPath:file_path error:nil]; + + return success; +} + +bool IsOnSameFilesystemAsChromium(NSString* dir_path) { + static const base::Optional<fsid_t> cr_fsid = []() -> base::Optional<fsid_t> { + struct statfs buf; + int result = statfs( + [[base::mac::OuterBundle() bundlePath] fileSystemRepresentation], &buf); + if (result != 0) + return base::nullopt; + return buf.f_fsid; + }(); + + if (!cr_fsid) + return false; + + struct statfs buf; + int result = statfs([dir_path fileSystemRepresentation], &buf); + if (result != 0) + return false; + + return cr_fsid->val[0] == buf.f_fsid.val[0] && + cr_fsid->val[1] == buf.f_fsid.val[1]; +} + +// Used for UMA; never alter existing values. +enum class StagingDirectoryStep { + kFailedToFindDirectory, + kItemReplacementDirectory, + kSiblingDirectory, + kNSTemporaryDirectory, + kTMPDIRDirectory, + kTmpDirectory, + kMaxValue = kTmpDirectory, +}; + +void LogStagingDirectoryLocation(StagingDirectoryStep step) { + UMA_HISTOGRAM_ENUMERATION("OSX.StagingDirectoryLocation", step); +} + +void RecordStagingDirectoryStats() { + NSURL* bundle_url = [base::mac::OuterBundle() bundleURL]; + NSFileManager* file_manager = [NSFileManager defaultManager]; + + // 1. NSItemReplacementDirectory + + NSError* error = nil; + NSURL* item_replacement_dir = + [file_manager URLForDirectory:NSItemReplacementDirectory + inDomain:NSUserDomainMask + appropriateForURL:bundle_url + create:YES + error:&error]; + if (item_replacement_dir && !error && + IsDirectoryWriteable([item_replacement_dir path])) { + LogStagingDirectoryLocation( + StagingDirectoryStep::kItemReplacementDirectory); + return; + } + + // 2. A directory alongside Chromium. + + NSURL* bundle_parent_url = + [[bundle_url URLByStandardizingPath] URLByDeletingLastPathComponent]; + NSURL* sibling_dir = + [bundle_parent_url URLByAppendingPathComponent:@".GoogleChromeStaging" + isDirectory:YES]; + NSString* sibling_dir_path = [sibling_dir path]; + + BOOL is_directory; + BOOL path_existed = [file_manager fileExistsAtPath:sibling_dir_path + isDirectory:&is_directory]; + + BOOL success = true; + error = nil; + if (!path_existed) { + success = [file_manager createDirectoryAtURL:sibling_dir + withIntermediateDirectories:YES + attributes:nil + error:&error]; + } else if (!is_directory) { + // There is a non-directory there; don't attempt to use this location + // further. + success = false; + } + + if (success) { + success &= !error && IsDirectoryWriteable(sibling_dir_path); + + // Only delete this directory if this was the code that created it. + if (!path_existed) + [file_manager removeItemAtURL:sibling_dir error:nil]; + } + + if (success) { + LogStagingDirectoryLocation(StagingDirectoryStep::kSiblingDirectory); + return; + } + + // 3. NSTemporaryDirectory() + + NSString* ns_temporary_dir = NSTemporaryDirectory(); + if (ns_temporary_dir && IsOnSameFilesystemAsChromium(ns_temporary_dir) && + IsDirectoryWriteable(ns_temporary_dir)) { + LogStagingDirectoryLocation(StagingDirectoryStep::kNSTemporaryDirectory); + return; + } + + // 4. $TMPDIR + + const char* tmpdir_cstr = getenv("TMPDIR"); + NSString* tmpdir = tmpdir_cstr ? @(tmpdir_cstr) : nil; + if (tmpdir && IsOnSameFilesystemAsChromium(tmpdir) && + IsDirectoryWriteable(tmpdir)) { + LogStagingDirectoryLocation(StagingDirectoryStep::kTMPDIRDirectory); + return; + } + + // 5. /tmp + + NSString* tmp = @"/tmp"; + if (IsOnSameFilesystemAsChromium(tmp) && IsDirectoryWriteable(tmp)) { + LogStagingDirectoryLocation(StagingDirectoryStep::kTmpDirectory); + return; + } + + // 6. Give up. + + LogStagingDirectoryLocation(StagingDirectoryStep::kFailedToFindDirectory); +} + // Records various bits of information about the local Chromium installation in // UMA. void RecordInstallationStats() { RecordFilesystemStats(); RecordInstanceStats(); InstallFastUserSwitchStatRecorder(); + RecordStagingDirectoryStats(); } } // namespace
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn index ebd07a34..b35dd7c5 100644 --- a/chrome/browser/chromeos/BUILD.gn +++ b/chrome/browser/chromeos/BUILD.gn
@@ -315,6 +315,9 @@ "account_mapper_util.h", "android_sms/android_sms_app_helper_delegate_impl.cc", "android_sms/android_sms_app_helper_delegate_impl.h", + "android_sms/android_sms_app_setup_controller.h", + "android_sms/android_sms_app_setup_controller_impl.cc", + "android_sms/android_sms_app_setup_controller_impl.h", "android_sms/android_sms_pairing_state_tracker_impl.cc", "android_sms/android_sms_pairing_state_tracker_impl.h", "android_sms/android_sms_service.cc", @@ -2041,6 +2044,8 @@ testonly = true sources = [ + "android_sms/fake_android_sms_app_setup_controller.cc", + "android_sms/fake_android_sms_app_setup_controller.h", "android_sms/fake_connection_establisher.cc", "android_sms/fake_connection_establisher.h", "app_mode/test_kiosk_extension_builder.cc", @@ -2125,6 +2130,7 @@ "accessibility/switch_access_panel_unittest.cc", "account_manager/account_migration_runner_unittest.cc", "android_sms/android_sms_app_helper_delegate_impl_unittest.cc", + "android_sms/android_sms_app_setup_controller_impl_unittest.cc", "android_sms/connection_establisher_impl_unittest.cc", "android_sms/connection_manager_unittest.cc", "android_sms/pairing_lost_notifier_unittest.cc",
diff --git a/chrome/browser/chromeos/android_sms/android_sms_app_setup_controller.h b/chrome/browser/chromeos/android_sms/android_sms_app_setup_controller.h new file mode 100644 index 0000000..94e2c13 --- /dev/null +++ b/chrome/browser/chromeos/android_sms/android_sms_app_setup_controller.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 CHROME_BROWSER_CHROMEOS_ANDROID_SMS_ANDROID_SMS_APP_SETUP_CONTROLLER_H_ +#define CHROME_BROWSER_CHROMEOS_ANDROID_SMS_ANDROID_SMS_APP_SETUP_CONTROLLER_H_ + +#include "base/callback_forward.h" +#include "base/macros.h" +#include "url/gurl.h" + +namespace extensions { +class Extension; +} // namespace extensions + +namespace chromeos { + +namespace android_sms { + +// Manages the setup and uninstallation process of the Android SMS PWA. +class AndroidSmsAppSetupController { + public: + AndroidSmsAppSetupController() = default; + virtual ~AndroidSmsAppSetupController() = default; + + using SuccessCallback = base::OnceCallback<void(bool)>; + + // Performs the setup process for the app at |url|, which includes: + // (1) Installing the PWA, + // (2) Granting permission for the PWA to show notifications, and + // (3) Setting a cookie which defaults the PWA to remember this computer. + virtual void SetUpApp(const GURL& url, SuccessCallback callback) = 0; + + // Returns the extension for the PWA at |url|; if no PWA exists, null is + // returned. + virtual const extensions::Extension* GetPwa(const GURL& url) = 0; + + // Deletes the cookie which causes the PWA to remember this computer by + // default. Note that this does not actually stop the PWA from remembering + // this computer; rather, it stops the PWA from *defaulting* to remember the + // computer in the case that the user has not gone through the PWA's setup. + virtual void DeleteRememberDeviceByDefaultCookie( + const GURL& url, + SuccessCallback callback) = 0; + + // Uninstalls the app at |url| and deletes relevant cookies from the setup + // process. + virtual void RemoveApp(const GURL& url, SuccessCallback callback) = 0; + + private: + DISALLOW_COPY_AND_ASSIGN(AndroidSmsAppSetupController); +}; + +} // namespace android_sms + +} // namespace chromeos + +#endif // CHROME_BROWSER_CHROMEOS_ANDROID_SMS_ANDROID_SMS_APP_SETUP_CONTROLLER_H_
diff --git a/chrome/browser/chromeos/android_sms/android_sms_app_setup_controller_impl.cc b/chrome/browser/chromeos/android_sms/android_sms_app_setup_controller_impl.cc new file mode 100644 index 0000000..05bc0be --- /dev/null +++ b/chrome/browser/chromeos/android_sms/android_sms_app_setup_controller_impl.cc
@@ -0,0 +1,247 @@ +// 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 "chrome/browser/chromeos/android_sms/android_sms_app_setup_controller_impl.h" + +#include "base/callback.h" +#include "base/containers/flat_map.h" +#include "base/metrics/histogram_macros.h" +#include "base/optional.h" +#include "chrome/browser/extensions/extension_util.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/web_applications/components/pending_app_manager.h" +#include "chrome/browser/web_applications/components/web_app_constants.h" +#include "chromeos/components/multidevice/logging/logging.h" +#include "components/content_settings/core/browser/host_content_settings_map.h" +#include "content/public/browser/browser_context.h" +#include "content/public/browser/storage_partition.h" +#include "services/network/public/mojom/cookie_manager.mojom.h" +#include "url/gurl.h" + +namespace chromeos { + +namespace android_sms { + +namespace { + +const char kDefaultToPersistCookieName[] = "default_to_persist"; +const char kDefaultToPersistCookieValue[] = "true"; + +} // namespace + +AndroidSmsAppSetupControllerImpl::PwaDelegate::PwaDelegate() = default; + +AndroidSmsAppSetupControllerImpl::PwaDelegate::~PwaDelegate() = default; + +const extensions::Extension* +AndroidSmsAppSetupControllerImpl::PwaDelegate::GetPwaForUrl(const GURL& url, + Profile* profile) { + return extensions::util::GetInstalledPwaForUrl(profile, url); +} + +network::mojom::CookieManager* +AndroidSmsAppSetupControllerImpl::PwaDelegate::GetCookieManager( + const GURL& url, + Profile* profile) { + return content::BrowserContext::GetStoragePartitionForSite(profile, url) + ->GetCookieManagerForBrowserProcess(); +} + +AndroidSmsAppSetupControllerImpl::AndroidSmsAppSetupControllerImpl( + Profile* profile, + web_app::PendingAppManager* pending_app_manager, + HostContentSettingsMap* host_content_settings_map) + : profile_(profile), + pending_app_manager_(pending_app_manager), + host_content_settings_map_(host_content_settings_map), + pwa_delegate_(std::make_unique<PwaDelegate>()), + weak_ptr_factory_(this) {} + +AndroidSmsAppSetupControllerImpl::~AndroidSmsAppSetupControllerImpl() = default; + +void AndroidSmsAppSetupControllerImpl::SetUpApp(const GURL& url, + SuccessCallback callback) { + PA_LOG(VERBOSE) << "AndroidSmsAppSetupControllerImpl::SetUpApp(): Setting " + << "DefaultToPersist cookie at " << url << " before PWA " + << "installation."; + pwa_delegate_->GetCookieManager(url, profile_) + ->SetCanonicalCookie( + *net::CanonicalCookie::CreateSanitizedCookie( + url, kDefaultToPersistCookieName, kDefaultToPersistCookieValue, + std::string() /* domain */, std::string() /* path */, + base::Time::Now() /* creation_time */, + base::Time() /* expiration_time */, + base::Time::Now() /* last_access_time */, true /* secure */, + false /* http_only */, net::CookieSameSite::STRICT_MODE, + net::COOKIE_PRIORITY_DEFAULT), + true /* secure_source */, false /* modify_http_only */, + base::BindOnce(&AndroidSmsAppSetupControllerImpl::OnSetCookieResult, + weak_ptr_factory_.GetWeakPtr(), url, + std::move(callback))); +} + +const extensions::Extension* AndroidSmsAppSetupControllerImpl::GetPwa( + const GURL& url) { + return pwa_delegate_->GetPwaForUrl(url, profile_); +} + +void AndroidSmsAppSetupControllerImpl::DeleteRememberDeviceByDefaultCookie( + const GURL& url, + SuccessCallback callback) { + PA_LOG(INFO) << "AndroidSmsAppSetupControllerImpl::" + << "DeleteRememberDeviceByDefaultCookie(): Deleting " + << "DefaultToPersist cookie at " << url << "."; + network::mojom::CookieDeletionFilterPtr filter( + network::mojom::CookieDeletionFilter::New()); + filter->url = url; + filter->cookie_name = kDefaultToPersistCookieName; + pwa_delegate_->GetCookieManager(url, profile_) + ->DeleteCookies( + std::move(filter), + base::BindOnce( + &AndroidSmsAppSetupControllerImpl::OnDeleteCookiesResult, + weak_ptr_factory_.GetWeakPtr(), url, std::move(callback))); +} + +void AndroidSmsAppSetupControllerImpl::RemoveApp(const GURL& url, + SuccessCallback callback) { + // If there is no app installed at |url|, there is nothing more to do. + if (!pwa_delegate_->GetPwaForUrl(url, profile_)) { + PA_LOG(VERBOSE) << "AndroidSmsAppSetupControllerImpl::RemoveApp(): No app " + << "is installed at " << url << "; skipping removal " + << "process."; + std::move(callback).Run(true /* success */); + return; + } + + PA_LOG(INFO) << "AndroidSmsAppSetupControllerImpl::RemoveApp(): " + << "Uninstalling app at " << url << "."; + // UninstallApps() takes a base::RepeatedCallback, but |callback| is a + // base::OnceCallback; thus, |callback| cannot be included in the closure + // because it has move-only semantics. Assign this uninstall attempt an ID + // associated with |callback| so that it can be retrieved in + // OnAppUninstallResult(). + auto id = base::UnguessableToken::Create(); + uninstall_id_to_callback_map_.emplace(id, std::move(callback)); + pending_app_manager_->UninstallApps( + std::vector<GURL>{url}, + base::BindRepeating( + &AndroidSmsAppSetupControllerImpl::OnAppUninstallResult, + weak_ptr_factory_.GetWeakPtr(), id)); +} + +void AndroidSmsAppSetupControllerImpl::OnSetCookieResult( + const GURL& url, + SuccessCallback callback, + bool succeeded) { + if (!succeeded) { + PA_LOG(WARNING) << "AndroidSmsAppSetupControllerImpl::" + << "OnSetCookieResult(): Failed to set " + << "DefaultToPersist cookie at " << url << ". Proceeding " + << "with installation request."; + } + + // If the app is already installed at |url|, there is nothing more to do. + if (pwa_delegate_->GetPwaForUrl(url, profile_)) { + PA_LOG(VERBOSE) << "AndroidSmsAppSetupControllerImpl::OnSetCookieResult(): " + << "App is already installed at " << url << "; skipping " + << "setup process."; + std::move(callback).Run(true /* success */); + return; + } + + web_app::PendingAppManager::AppInfo info(url, + web_app::LaunchContainer::kWindow, + web_app::InstallSource::kInternal); + info.override_previous_user_uninstall = true; + // The ServiceWorker does not load in time for the installability check, so + // bypass it as a workaround. + info.bypass_service_worker_check = true; + info.require_manifest = true; + + PA_LOG(VERBOSE) << "AndroidSmsAppSetupControllerImpl::OnSetCookieResult(): " + << "Installing PWA for " << url << "."; + pending_app_manager_->Install( + std::move(info), + base::BindOnce(&AndroidSmsAppSetupControllerImpl::OnAppInstallResult, + weak_ptr_factory_.GetWeakPtr(), std::move(callback))); +} + +void AndroidSmsAppSetupControllerImpl::OnAppInstallResult( + SuccessCallback callback, + const GURL& url, + web_app::InstallResultCode code) { + UMA_HISTOGRAM_ENUMERATION("AndroidSms.PWAInstallationResult", code); + + if (code != web_app::InstallResultCode::kSuccess) { + PA_LOG(WARNING) + << "AndroidSmsAppSetupControllerImpl::OnAppInstallResult(): " + << "PWA for " << url << " failed to install. " + << "InstallResultCode: " << static_cast<int>(code); + std::move(callback).Run(false /* success */); + return; + } + + PA_LOG(INFO) << "AndroidSmsAppSetupControllerImpl::OnAppInstallResult(): " + << "PWA for " << url << " was installed successfully."; + + // Grant notification permission for the PWA. + host_content_settings_map_->SetWebsiteSettingDefaultScope( + url, GURL() /* top_level_url */, + ContentSettingsType::CONTENT_SETTINGS_TYPE_NOTIFICATIONS, + content_settings::ResourceIdentifier(), + std::make_unique<base::Value>(ContentSetting::CONTENT_SETTING_ALLOW)); + + std::move(callback).Run(true /* success */); +} + +void AndroidSmsAppSetupControllerImpl::OnAppUninstallResult( + const base::UnguessableToken& id, + const GURL& url, + bool succeeded) { + UMA_HISTOGRAM_BOOLEAN("AndroidSms.PWAUninstallationResult", succeeded); + + // OnAppUninstallResult() should only be called once per ID, so the uninstall + // callback is always expected to exist in the map. + SuccessCallback callback = std::move(uninstall_id_to_callback_map_[id]); + CHECK(callback); + uninstall_id_to_callback_map_.erase(id); + + if (!succeeded) { + PA_LOG(ERROR) + << "AndroidSmsAppSetupControllerImpl::OnAppUninstallResult(): " + << "PWA for " << url << " failed to uninstall."; + std::move(callback).Run(false /* success */); + return; + } + + DeleteRememberDeviceByDefaultCookie(url, std::move(callback)); +} + +void AndroidSmsAppSetupControllerImpl::OnDeleteCookiesResult( + const GURL& url, + SuccessCallback callback, + uint32_t num_deleted) { + if (num_deleted != 1u) { + PA_LOG(WARNING) << "AndroidSmsAppSetupControllerImpl::" + << "OnDeleteCookiesResult(): Tried to delete a single " + << "cookie at " << url << ", but " << num_deleted << " " + << "cookies were deleted."; + } + + // Even if an unexpected number of cookies was deleted, consider this a + // success. If SetUpApp() failed to install a cookie earlier, the setup + // process is still considered a success, so failing to delete a cookie should + // also be considered a success. + std::move(callback).Run(true /* success */); +} + +void AndroidSmsAppSetupControllerImpl::SetPwaDelegateForTesting( + std::unique_ptr<PwaDelegate> test_pwa_delegate) { + pwa_delegate_ = std::move(test_pwa_delegate); +} + +} // namespace android_sms + +} // namespace chromeos
diff --git a/chrome/browser/chromeos/android_sms/android_sms_app_setup_controller_impl.h b/chrome/browser/chromeos/android_sms/android_sms_app_setup_controller_impl.h new file mode 100644 index 0000000..95036f4c --- /dev/null +++ b/chrome/browser/chromeos/android_sms/android_sms_app_setup_controller_impl.h
@@ -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. + +#ifndef CHROME_BROWSER_CHROMEOS_ANDROID_SMS_ANDROID_SMS_APP_SETUP_CONTROLLER_IMPL_H_ +#define CHROME_BROWSER_CHROMEOS_ANDROID_SMS_ANDROID_SMS_APP_SETUP_CONTROLLER_IMPL_H_ + +#include "base/containers/flat_map.h" +#include "base/memory/weak_ptr.h" +#include "base/unguessable_token.h" +#include "chrome/browser/chromeos/android_sms/android_sms_app_setup_controller.h" +#include "url/gurl.h" + +class HostContentSettingsMap; +class Profile; + +namespace network { +namespace mojom { +class CookieManager; +} // namespace mojom +} // namespace network + +namespace web_app { +enum class InstallResultCode; +class PendingAppManager; +} // namespace web_app + +namespace chromeos { + +namespace android_sms { + +// Concrete AndroidSmsAppSetupController implementation. +class AndroidSmsAppSetupControllerImpl : public AndroidSmsAppSetupController { + public: + AndroidSmsAppSetupControllerImpl( + Profile* profile, + web_app::PendingAppManager* pending_app_manager, + HostContentSettingsMap* host_content_settings_map); + ~AndroidSmsAppSetupControllerImpl() override; + + private: + friend class AndroidSmsAppSetupControllerImplTest; + + // Thin wrapper around static PWA functions which is stubbed out for tests. + class PwaDelegate { + public: + PwaDelegate(); + virtual ~PwaDelegate(); + + virtual const extensions::Extension* GetPwaForUrl(const GURL& url, + Profile* profile); + virtual network::mojom::CookieManager* GetCookieManager(const GURL& url, + Profile* profile); + }; + + // AndroidSmsAppSetupController: + void SetUpApp(const GURL& url, SuccessCallback callback) override; + const extensions::Extension* GetPwa(const GURL& url) override; + void DeleteRememberDeviceByDefaultCookie(const GURL& url, + SuccessCallback callback) override; + void RemoveApp(const GURL& url, SuccessCallback callback) override; + + void OnSetCookieResult(const GURL& url, + SuccessCallback callback, + bool succeeded); + void OnAppInstallResult(SuccessCallback callback, + const GURL& url, + web_app::InstallResultCode code); + void OnAppUninstallResult(const base::UnguessableToken& id, + const GURL& url, + bool succeeded); + void OnDeleteCookiesResult(const GURL& url, + SuccessCallback callback, + uint32_t num_deleted); + + void SetPwaDelegateForTesting(std::unique_ptr<PwaDelegate> test_pwa_delegate); + + Profile* profile_; + web_app::PendingAppManager* pending_app_manager_; + HostContentSettingsMap* host_content_settings_map_; + + std::unique_ptr<PwaDelegate> pwa_delegate_; + base::flat_map<base::UnguessableToken, SuccessCallback> + uninstall_id_to_callback_map_; + base::WeakPtrFactory<AndroidSmsAppSetupControllerImpl> weak_ptr_factory_; + + DISALLOW_COPY_AND_ASSIGN(AndroidSmsAppSetupControllerImpl); +}; + +} // namespace android_sms + +} // namespace chromeos + +#endif // CHROME_BROWSER_CHROMEOS_ANDROID_SMS_ANDROID_SMS_APP_SETUP_CONTROLLER_IMPL_H_
diff --git a/chrome/browser/chromeos/android_sms/android_sms_app_setup_controller_impl_unittest.cc b/chrome/browser/chromeos/android_sms/android_sms_app_setup_controller_impl_unittest.cc new file mode 100644 index 0000000..b2e3f79 --- /dev/null +++ b/chrome/browser/chromeos/android_sms/android_sms_app_setup_controller_impl_unittest.cc
@@ -0,0 +1,389 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/chromeos/android_sms/android_sms_app_setup_controller_impl.h" + +#include <memory> +#include <tuple> +#include <utility> +#include <vector> + +#include "base/bind.h" +#include "base/containers/flat_map.h" +#include "base/files/file_path.h" +#include "base/macros.h" +#include "base/memory/ptr_util.h" +#include "base/memory/ref_counted.h" +#include "base/path_service.h" +#include "base/run_loop.h" +#include "base/test/metrics/histogram_tester.h" +#include "chrome/browser/content_settings/host_content_settings_map_factory.h" +#include "chrome/browser/web_applications/components/test_pending_app_manager.h" +#include "chrome/browser/web_applications/components/web_app_constants.h" +#include "chrome/test/base/testing_profile.h" +#include "components/content_settings/core/browser/host_content_settings_map.h" +#include "content/public/test/test_browser_thread_bundle.h" +#include "extensions/common/extension.h" +#include "extensions/common/extension_builder.h" +#include "extensions/common/extension_paths.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace chromeos { + +namespace android_sms { + +namespace { + +const char kTestUrl1[] = "https://test-url-1.com/"; +const char kTestUrl2[] = "https://test-url-2.com/"; + +web_app::PendingAppManager::AppInfo GetAppInfoForUrl(const GURL& url) { + web_app::PendingAppManager::AppInfo info(url, + web_app::LaunchContainer::kWindow, + web_app::InstallSource::kInternal); + info.override_previous_user_uninstall = true; + info.bypass_service_worker_check = true; + info.require_manifest = true; + return info; +} + +class FakeCookieManager : public network::mojom::CookieManager { + public: + FakeCookieManager() = default; + ~FakeCookieManager() override { + EXPECT_TRUE(set_canonical_cookie_calls_.empty()); + EXPECT_TRUE(delete_cookies_calls_.empty()); + } + + void InvokePendingSetCanonicalCookieCallback( + const std::string& expected_cookie_name, + bool expected_secure_source, + bool expected_modify_http_only, + bool success) { + ASSERT_FALSE(set_canonical_cookie_calls_.empty()); + auto params = std::move(set_canonical_cookie_calls_.front()); + set_canonical_cookie_calls_.erase(set_canonical_cookie_calls_.begin()); + + EXPECT_EQ(expected_cookie_name, std::get<0>(params).Name()); + EXPECT_EQ(expected_secure_source, std::get<1>(params)); + EXPECT_EQ(expected_modify_http_only, std::get<2>(params)); + + std::move(std::get<3>(params)).Run(success); + } + + void InvokePendingDeleteCookiesCallback( + const GURL& expected_url, + const std::string& expected_cookie_name, + bool success) { + ASSERT_FALSE(delete_cookies_calls_.empty()); + auto params = std::move(delete_cookies_calls_.front()); + delete_cookies_calls_.erase(delete_cookies_calls_.begin()); + + EXPECT_EQ(expected_url, params.first->url); + EXPECT_EQ(expected_cookie_name, params.first->cookie_name); + + std::move(params.second).Run(success); + } + + // network::mojom::CookieManager + void SetCanonicalCookie(const net::CanonicalCookie& cookie, + bool secure_source, + bool modify_http_only, + SetCanonicalCookieCallback callback) override { + set_canonical_cookie_calls_.emplace_back( + cookie, secure_source, modify_http_only, std::move(callback)); + } + + void DeleteCookies(network::mojom::CookieDeletionFilterPtr filter, + DeleteCookiesCallback callback) override { + delete_cookies_calls_.emplace_back(std::move(filter), std::move(callback)); + } + + void GetAllCookies(GetAllCookiesCallback callback) override {} + void GetCookieList(const GURL& url, + const net::CookieOptions& cookie_options, + GetCookieListCallback callback) override {} + void DeleteCanonicalCookie(const net::CanonicalCookie& cookie, + DeleteCanonicalCookieCallback callback) override {} + void AddCookieChangeListener( + const GURL& url, + const std::string& name, + network::mojom::CookieChangeListenerPtr listener) override {} + void AddGlobalChangeListener( + network::mojom::CookieChangeListenerPtr notification_pointer) override {} + void CloneInterface( + network::mojom::CookieManagerRequest new_interface) override {} + void FlushCookieStore(FlushCookieStoreCallback callback) override {} + void SetContentSettings( + const std::vector<::ContentSettingPatternSource>& settings) override {} + void SetForceKeepSessionState() override {} + void BlockThirdPartyCookies(bool block) override {} + + private: + std::vector< + std::tuple<net::CanonicalCookie, bool, bool, SetCanonicalCookieCallback>> + set_canonical_cookie_calls_; + std::vector< + std::pair<network::mojom::CookieDeletionFilterPtr, DeleteCookiesCallback>> + delete_cookies_calls_; +}; + +} // namespace + +class AndroidSmsAppSetupControllerImplTest : public testing::Test { + protected: + class TestPwaDelegate : public AndroidSmsAppSetupControllerImpl::PwaDelegate { + public: + explicit TestPwaDelegate(FakeCookieManager* fake_cookie_manager) + : fake_cookie_manager_(fake_cookie_manager) {} + ~TestPwaDelegate() override = default; + + void SetHasPwa(const GURL& url, bool has_pwa) { + // If no PWA should exist, erase any existing entry and return. + if (!has_pwa) { + url_to_pwa_map_.erase(url); + return; + } + + // If a PWA already exists for this URL, there is nothing to do. + if (base::ContainsKey(url_to_pwa_map_, url)) + return; + + // Create a test Extension and add it to |url_to_pwa_map_|. + base::FilePath path; + base::PathService::Get(extensions::DIR_TEST_DATA, &path); + url_to_pwa_map_[url] = extensions::ExtensionBuilder(url.spec()) + .SetPath(path.AppendASCII(url.spec())) + .Build(); + } + + // AndroidSmsAppSetupControllerImpl::PwaDelegate: + const extensions::Extension* GetPwaForUrl(const GURL& url, + Profile* profile) override { + if (!base::ContainsKey(url_to_pwa_map_, url)) + return nullptr; + + return url_to_pwa_map_[url].get(); + } + + network::mojom::CookieManager* GetCookieManager(const GURL& url, + Profile* profile) override { + return fake_cookie_manager_; + } + + private: + FakeCookieManager* fake_cookie_manager_; + base::flat_map<GURL, scoped_refptr<const extensions::Extension>> + url_to_pwa_map_; + }; + + AndroidSmsAppSetupControllerImplTest() + : host_content_settings_map_( + HostContentSettingsMapFactory::GetForProfile(&profile_)) {} + + ~AndroidSmsAppSetupControllerImplTest() override = default; + + // testing::Test: + void SetUp() override { + host_content_settings_map_->ClearSettingsForOneType( + ContentSettingsType::CONTENT_SETTINGS_TYPE_NOTIFICATIONS); + fake_cookie_manager_ = std::make_unique<FakeCookieManager>(); + auto test_pwa_delegate = + std::make_unique<TestPwaDelegate>(fake_cookie_manager_.get()); + test_pwa_delegate_ = test_pwa_delegate.get(); + test_pending_app_manager_ = + std::make_unique<web_app::TestPendingAppManager>(); + setup_controller_ = base::WrapUnique(new AndroidSmsAppSetupControllerImpl( + &profile_, test_pending_app_manager_.get(), + host_content_settings_map_)); + + std::unique_ptr<AndroidSmsAppSetupControllerImpl::PwaDelegate> + base_delegate(test_pwa_delegate.release()); + + static_cast<AndroidSmsAppSetupControllerImpl*>(setup_controller_.get()) + ->SetPwaDelegateForTesting(std::move(base_delegate)); + } + + void CallSetUpApp(const GURL url, size_t num_expected_app_installs) { + const auto& install_requests = + test_pending_app_manager_->install_requests(); + size_t num_install_requests_before_call = install_requests.size(); + + base::RunLoop run_loop; + base::HistogramTester histogram_tester; + + setup_controller_->SetUpApp( + url, + base::BindOnce(&AndroidSmsAppSetupControllerImplTest::OnSetUpAppResult, + base::Unretained(this), run_loop.QuitClosure())); + + fake_cookie_manager_->InvokePendingSetCanonicalCookieCallback( + "default_to_persist" /* expected_cookie_name */, + true /* expected_secure_source */, + false /* expected_modify_http_only */, true /* success */); + + // If the PWA was not already installed at the URL, SetUpApp() should + // install it. + if (!test_pwa_delegate_->GetPwaForUrl(url, &profile_)) { + EXPECT_EQ(num_install_requests_before_call + 1u, install_requests.size()); + EXPECT_EQ(GetAppInfoForUrl(url), install_requests.back()); + + EXPECT_EQ(ContentSetting::CONTENT_SETTING_ALLOW, + GetNotificationSetting(url)); + } + + if (num_expected_app_installs) { + histogram_tester.ExpectBucketCount("AndroidSms.PWAInstallationResult", + web_app::InstallResultCode::kSuccess, + num_expected_app_installs); + } + + run_loop.Run(); + EXPECT_TRUE(*last_set_up_app_result_); + last_set_up_app_result_.reset(); + } + + void CallDeleteRememberDeviceByDefaultCookie(const GURL url) { + base::RunLoop run_loop; + + setup_controller_->DeleteRememberDeviceByDefaultCookie( + url, base::BindOnce(&AndroidSmsAppSetupControllerImplTest:: + OnDeleteRememberDeviceByDefaultCookieResult, + base::Unretained(this), run_loop.QuitClosure())); + + fake_cookie_manager_->InvokePendingDeleteCookiesCallback( + url, "default_to_persist" /* expected_cookie_name */, + true /* success */); + + run_loop.Run(); + EXPECT_TRUE(*last_delete_cookie_result_); + last_delete_cookie_result_.reset(); + } + + void CallRemoveApp(const GURL url, size_t num_expected_app_uninstalls) { + const auto& uninstall_requests = + test_pending_app_manager_->uninstall_requests(); + size_t num_uninstall_requests_before_call = uninstall_requests.size(); + + base::RunLoop run_loop; + base::HistogramTester histogram_tester; + + setup_controller_->RemoveApp( + url, + base::BindOnce(&AndroidSmsAppSetupControllerImplTest::OnRemoveAppResult, + base::Unretained(this), run_loop.QuitClosure())); + + // If the PWA was already installed at the URL, RemoveApp() should uninstall + // the it. + if (test_pwa_delegate_->GetPwaForUrl(url, &profile_)) { + EXPECT_EQ(num_uninstall_requests_before_call + 1u, + uninstall_requests.size()); + EXPECT_EQ(url, uninstall_requests.back()); + + fake_cookie_manager_->InvokePendingDeleteCookiesCallback( + url, "default_to_persist" /* expected_cookie_name */, + true /* success */); + } + + if (num_expected_app_uninstalls) { + histogram_tester.ExpectBucketCount("AndroidSms.PWAUninstallationResult", + true, num_expected_app_uninstalls); + } + + run_loop.Run(); + EXPECT_TRUE(*last_remove_app_result_); + last_remove_app_result_.reset(); + } + + TestPwaDelegate* test_pwa_delegate() { return test_pwa_delegate_; } + + private: + ContentSetting GetNotificationSetting(const GURL& url) { + std::unique_ptr<base::Value> notification_settings_value = + host_content_settings_map_->GetWebsiteSetting( + url, GURL() /* top_level_url */, + ContentSettingsType::CONTENT_SETTINGS_TYPE_NOTIFICATIONS, + content_settings::ResourceIdentifier(), nullptr); + return static_cast<ContentSetting>(notification_settings_value->GetInt()); + } + + void OnSetUpAppResult(base::OnceClosure quit_closure, bool success) { + EXPECT_FALSE(last_set_up_app_result_); + last_set_up_app_result_ = success; + std::move(quit_closure).Run(); + } + + void OnDeleteRememberDeviceByDefaultCookieResult( + base::OnceClosure quit_closure, + bool success) { + EXPECT_FALSE(last_delete_cookie_result_); + last_delete_cookie_result_ = success; + std::move(quit_closure).Run(); + } + + void OnRemoveAppResult(base::OnceClosure quit_closure, bool success) { + EXPECT_FALSE(last_remove_app_result_); + last_remove_app_result_ = success; + std::move(quit_closure).Run(); + } + + content::TestBrowserThreadBundle thread_bundle_; + + base::Optional<bool> last_set_up_app_result_; + base::Optional<bool> last_delete_cookie_result_; + base::Optional<bool> last_remove_app_result_; + + TestingProfile profile_; + HostContentSettingsMap* host_content_settings_map_; + std::unique_ptr<FakeCookieManager> fake_cookie_manager_; + std::unique_ptr<web_app::TestPendingAppManager> test_pending_app_manager_; + TestPwaDelegate* test_pwa_delegate_; + std::unique_ptr<AndroidSmsAppSetupController> setup_controller_; + + DISALLOW_COPY_AND_ASSIGN(AndroidSmsAppSetupControllerImplTest); +}; + +TEST_F(AndroidSmsAppSetupControllerImplTest, SetUpApp_NoPreviousApp) { + CallSetUpApp(GURL(kTestUrl1), 1u /* num_expected_app_installs */); +} + +TEST_F(AndroidSmsAppSetupControllerImplTest, SetUpApp_AppAlreadyInstalled) { + // Start with a PWA already installed at the URL. + test_pwa_delegate()->SetHasPwa(GURL(kTestUrl1), true); + CallSetUpApp(GURL(kTestUrl1), 0u /* num_expected_app_installs */); +} + +TEST_F(AndroidSmsAppSetupControllerImplTest, SetUpApp_OtherPwaInstalled) { + // Start with a PWA already installed at a different URL. + test_pwa_delegate()->SetHasPwa(GURL(kTestUrl2), true); + CallSetUpApp(GURL(kTestUrl1), 1u /* num_expected_app_installs */); +} + +TEST_F(AndroidSmsAppSetupControllerImplTest, SetUpAppThenDeleteCookie) { + CallSetUpApp(GURL(kTestUrl1), 1u /* num_expected_app_installs */); + CallDeleteRememberDeviceByDefaultCookie(GURL(kTestUrl1)); +} + +TEST_F(AndroidSmsAppSetupControllerImplTest, SetUpAppThenRemove) { + // Install and remove. + CallSetUpApp(GURL(kTestUrl1), 1u /* num_expected_app_installs */); + test_pwa_delegate()->SetHasPwa(GURL(kTestUrl1), true); + CallRemoveApp(GURL(kTestUrl1), 1u /* num_expected_app_uninstalls */); + test_pwa_delegate()->SetHasPwa(GURL(kTestUrl1), false); + + // Repeat once more. + CallSetUpApp(GURL(kTestUrl1), 1u /* num_expected_app_installs */); + test_pwa_delegate()->SetHasPwa(GURL(kTestUrl1), true); + CallRemoveApp(GURL(kTestUrl1), 1u /* num_expected_app_uninstalls */); + test_pwa_delegate()->SetHasPwa(GURL(kTestUrl1), false); +} + +TEST_F(AndroidSmsAppSetupControllerImplTest, RemoveApp_NoInstalledApp) { + // Do not have an installed app before attempting to remove it. + CallRemoveApp(GURL(kTestUrl1), 0u /* num_expected_app_uninstalls */); +} + +} // namespace android_sms + +} // namespace chromeos
diff --git a/chrome/browser/chromeos/android_sms/fake_android_sms_app_setup_controller.cc b/chrome/browser/chromeos/android_sms/fake_android_sms_app_setup_controller.cc new file mode 100644 index 0000000..0e56d0a --- /dev/null +++ b/chrome/browser/chromeos/android_sms/fake_android_sms_app_setup_controller.cc
@@ -0,0 +1,136 @@ +// 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 "chrome/browser/chromeos/android_sms/fake_android_sms_app_setup_controller.h" + +#include "base/callback.h" +#include "base/logging.h" +#include "base/path_service.h" +#include "extensions/common/extension.h" +#include "extensions/common/extension_builder.h" +#include "extensions/common/extension_paths.h" + +namespace chromeos { + +namespace android_sms { + +FakeAndroidSmsAppSetupController::AppMetadata::AppMetadata() = default; + +FakeAndroidSmsAppSetupController::AppMetadata::AppMetadata( + const AppMetadata& other) = default; + +FakeAndroidSmsAppSetupController::AppMetadata::~AppMetadata() = default; + +FakeAndroidSmsAppSetupController::FakeAndroidSmsAppSetupController() = default; + +FakeAndroidSmsAppSetupController::~FakeAndroidSmsAppSetupController() = default; + +const FakeAndroidSmsAppSetupController::AppMetadata* +FakeAndroidSmsAppSetupController::GetAppMetadataAtUrl(const GURL& url) const { + const auto it = url_to_metadata_map_.find(url); + if (it == url_to_metadata_map_.end()) + return nullptr; + return std::addressof(it->second); +} + +void FakeAndroidSmsAppSetupController::SetAppAtUrl( + const GURL& url, + const base::Optional<extensions::ExtensionId>& id_for_app) { + if (!id_for_app) { + url_to_metadata_map_.erase(url); + return; + } + + // Create a test Extension and add it to |url_to_metadata_map_|. + base::FilePath path; + base::PathService::Get(extensions::DIR_TEST_DATA, &path); + url_to_metadata_map_[url].pwa = + extensions::ExtensionBuilder( + url.spec(), extensions::ExtensionBuilder::Type::PLATFORM_APP) + .SetPath(path.AppendASCII(url.spec())) + .SetID(*id_for_app) + .Build(); +} + +void FakeAndroidSmsAppSetupController::CompletePendingSetUpAppRequest( + const GURL& expected_url, + const base::Optional<extensions::ExtensionId>& id_for_app) { + DCHECK(!pending_set_up_app_requests_.empty()); + + auto request = std::move(pending_set_up_app_requests_.front()); + pending_set_up_app_requests_.erase(pending_set_up_app_requests_.begin()); + DCHECK_EQ(expected_url, request->first); + + if (!id_for_app) { + std::move(request->second).Run(false /* success */); + return; + } + + SetAppAtUrl(expected_url, *id_for_app); + std::move(request->second).Run(true /* success */); +} + +void FakeAndroidSmsAppSetupController::CompletePendingDeleteCookieRequest( + const GURL& expected_url) { + DCHECK(!pending_delete_cookie_requests_.empty()); + + auto request = std::move(pending_delete_cookie_requests_.front()); + pending_delete_cookie_requests_.erase( + pending_delete_cookie_requests_.begin()); + DCHECK_EQ(expected_url, request->first); + + // The app must exist before the cookie is deleted. + auto it = url_to_metadata_map_.find(expected_url); + DCHECK(it != url_to_metadata_map_.end()); + + it->second.is_cookie_present = false; + + std::move(request->second).Run(true /* success */); +} + +void FakeAndroidSmsAppSetupController::CompleteRemoveAppRequest( + const GURL& expected_url, + bool should_succeed) { + DCHECK(!pending_remove_app_requests_.empty()); + + auto request = std::move(pending_remove_app_requests_.front()); + pending_remove_app_requests_.erase(pending_remove_app_requests_.begin()); + DCHECK_EQ(expected_url, request->first); + + if (should_succeed) + SetAppAtUrl(expected_url, base::nullopt /* id_for_app */); + + std::move(request->second).Run(should_succeed); +} + +void FakeAndroidSmsAppSetupController::SetUpApp(const GURL& url, + SuccessCallback callback) { + pending_set_up_app_requests_.push_back( + std::make_unique<RequestData>(url, std::move(callback))); +} + +const extensions::Extension* FakeAndroidSmsAppSetupController::GetPwa( + const GURL& url) { + auto it = url_to_metadata_map_.find(url); + if (it == url_to_metadata_map_.end()) + return nullptr; + return it->second.pwa.get(); +} + +void FakeAndroidSmsAppSetupController::DeleteRememberDeviceByDefaultCookie( + const GURL& url, + SuccessCallback callback) { + pending_delete_cookie_requests_.push_back( + std::make_unique<RequestData>(url, std::move(callback))); +} + +void FakeAndroidSmsAppSetupController::RemoveApp(const GURL& url, + SuccessCallback callback) { + pending_remove_app_requests_.push_back( + std::make_unique<RequestData>(url, std::move(callback))); +} + +} // namespace android_sms + +} // namespace chromeos
diff --git a/chrome/browser/chromeos/android_sms/fake_android_sms_app_setup_controller.h b/chrome/browser/chromeos/android_sms/fake_android_sms_app_setup_controller.h new file mode 100644 index 0000000..05306384 --- /dev/null +++ b/chrome/browser/chromeos/android_sms/fake_android_sms_app_setup_controller.h
@@ -0,0 +1,89 @@ +// 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 CHROME_BROWSER_CHROMEOS_ANDROID_SMS_FAKE_ANDROID_SMS_APP_SETUP_CONTROLLER_H_ +#define CHROME_BROWSER_CHROMEOS_ANDROID_SMS_FAKE_ANDROID_SMS_APP_SETUP_CONTROLLER_H_ + +#include <list> +#include <memory> +#include <utility> + +#include "base/containers/flat_map.h" +#include "base/memory/ref_counted.h" +#include "base/optional.h" +#include "chrome/browser/chromeos/android_sms/android_sms_app_setup_controller.h" +#include "extensions/common/extension_id.h" +#include "url/gurl.h" + +namespace extensions { +class Extension; +} // namespace extensions + +namespace chromeos { + +namespace android_sms { + +// Test AndroidSmsAppSetupController implementation. +class FakeAndroidSmsAppSetupController : public AndroidSmsAppSetupController { + public: + FakeAndroidSmsAppSetupController(); + ~FakeAndroidSmsAppSetupController() override; + + struct AppMetadata { + AppMetadata(); + AppMetadata(const AppMetadata& other); + ~AppMetadata(); + + scoped_refptr<const extensions::Extension> pwa; + bool is_cookie_present = true; + }; + + // Returns null if no app has been installed at |url|. + const AppMetadata* GetAppMetadataAtUrl(const GURL& url) const; + + // If |id_for_app| is provided, this function installs an app with the given + // ID at |ur|. Otherwise, this function removes any existing app at that URL. + void SetAppAtUrl(const GURL& url, + const base::Optional<extensions::ExtensionId>& id_for_app); + + // Completes a pending setup request (i.e., a previous call to SetUpApp()). + // If |id_for_app| is set, the request is successful and the installed app + // will have the provided ID; if |id_for_app| is null, the request fails. + void CompletePendingSetUpAppRequest( + const GURL& expected_url, + const base::Optional<extensions::ExtensionId>& id_for_app); + + // Completes a pending cookie deletion request (i.e., a previous call to + // DeleteRememberDeviceByDefaultCookie()). + void CompletePendingDeleteCookieRequest(const GURL& expected_url); + + // Completes a pending app removal request (i.e., a previous call to + // RemoveApp()). If |success| is true, the app will be removed; otherwise, the + // app will remain in place. + void CompleteRemoveAppRequest(const GURL& expected_url, bool success); + + private: + // AndroidSmsAppSetupController: + void SetUpApp(const GURL& url, SuccessCallback callback) override; + const extensions::Extension* GetPwa(const GURL& url) override; + void DeleteRememberDeviceByDefaultCookie(const GURL& url, + SuccessCallback callback) override; + void RemoveApp(const GURL& url, SuccessCallback callback) override; + + using RequestData = std::pair<GURL, SuccessCallback>; + + std::list<std::unique_ptr<RequestData>> pending_set_up_app_requests_; + std::list<std::unique_ptr<RequestData>> pending_delete_cookie_requests_; + std::list<std::unique_ptr<RequestData>> pending_remove_app_requests_; + + base::flat_map<GURL, AppMetadata> url_to_metadata_map_; + + DISALLOW_COPY_AND_ASSIGN(FakeAndroidSmsAppSetupController); +}; + +} // namespace android_sms + +} // namespace chromeos + +#endif // CHROME_BROWSER_CHROMEOS_ANDROID_SMS_FAKE_ANDROID_SMS_APP_SETUP_CONTROLLER_H_
diff --git a/chrome/browser/chromeos/dbus/proxy_resolution_service_provider.cc b/chrome/browser/chromeos/dbus/proxy_resolution_service_provider.cc index e1ebb04..eac39c6 100644 --- a/chrome/browser/chromeos/dbus/proxy_resolution_service_provider.cc +++ b/chrome/browser/chromeos/dbus/proxy_resolution_service_provider.cc
@@ -29,25 +29,25 @@ struct ProxyResolutionServiceProvider::Request { public: Request(const std::string& source_url, - std::unique_ptr<dbus::Response> response, - const dbus::ExportedObject::ResponseSender& response_sender, - scoped_refptr<net::URLRequestContextGetter> context_getter) + scoped_refptr<net::URLRequestContextGetter> context_getter, + scoped_refptr<base::SingleThreadTaskRunner> notify_thread, + NotifyCallback notify_callback) : source_url(source_url), - response(std::move(response)), - response_sender(response_sender), - context_getter(context_getter) { - DCHECK(this->response); - DCHECK(!response_sender.is_null()); - } + context_getter(context_getter), + notify_thread(std::move(notify_thread)), + notify_callback(std::move(notify_callback)) {} ~Request() = default; + // Invokes |notify_callback| on |notify_thread|. + void PostNotify(const std::string& error, const std::string& pac_string) { + notify_thread->PostTask( + FROM_HERE, + base::BindOnce(std::move(notify_callback), error, pac_string)); + } + // URL being resolved. const std::string source_url; - // D-Bus response and callback for returning data on resolution completion. - std::unique_ptr<dbus::Response> response; - const dbus::ExportedObject::ResponseSender response_sender; - // Used to get the network context associated with the profile used to run // this request. const scoped_refptr<net::URLRequestContextGetter> context_getter; @@ -58,8 +58,10 @@ // ProxyInfo resolved for |source_url|. net::ProxyInfo proxy_info; - // Error from proxy resolution. - std::string error; + // The callback to invoke on completion, as well as the thread it should be + // invoked on. + scoped_refptr<base::SingleThreadTaskRunner> notify_thread; + NotifyCallback notify_callback; private: DISALLOW_COPY_AND_ASSIGN(Request); @@ -80,10 +82,10 @@ VLOG(1) << "ProxyResolutionServiceProvider started"; exported_object_->ExportMethod( kNetworkProxyServiceInterface, kNetworkProxyServiceResolveProxyMethod, - base::Bind(&ProxyResolutionServiceProvider::ResolveProxy, - weak_ptr_factory_.GetWeakPtr()), - base::Bind(&ProxyResolutionServiceProvider::OnExported, - weak_ptr_factory_.GetWeakPtr())); + base::BindRepeating(&ProxyResolutionServiceProvider::DbusResolveProxy, + weak_ptr_factory_.GetWeakPtr()), + base::BindRepeating(&ProxyResolutionServiceProvider::OnExported, + weak_ptr_factory_.GetWeakPtr())); } bool ProxyResolutionServiceProvider::OnOriginThread() { @@ -100,7 +102,7 @@ LOG(ERROR) << "Failed to export " << interface_name << "." << method_name; } -void ProxyResolutionServiceProvider::ResolveProxy( +void ProxyResolutionServiceProvider::DbusResolveProxy( dbus::MethodCall* method_call, dbus::ExportedObject::ResponseSender response_sender) { DCHECK(OnOriginThread()); @@ -117,33 +119,41 @@ std::unique_ptr<dbus::Response> response = dbus::Response::FromMethodCall(method_call); + + NotifyCallback notify_dbus_callback = + base::BindOnce(&ProxyResolutionServiceProvider::NotifyProxyResolved, + weak_ptr_factory_.GetWeakPtr(), std::move(response), + std::move(response_sender)); + + ResolveProxyInternal(source_url, std::move(notify_dbus_callback)); +} + +void ProxyResolutionServiceProvider::ResolveProxyInternal( + const std::string& source_url, + NotifyCallback callback) { scoped_refptr<net::URLRequestContextGetter> context_getter = request_context_getter_for_test_ ? request_context_getter_for_test_ : ProfileManager::GetPrimaryUserProfile()->GetRequestContext(); std::unique_ptr<Request> request = std::make_unique<Request>( - source_url, std::move(response), response_sender, context_getter); - NotifyCallback notify_callback = - base::Bind(&ProxyResolutionServiceProvider::NotifyProxyResolved, - weak_ptr_factory_.GetWeakPtr()); + source_url, context_getter, origin_thread_, std::move(callback)); // This would ideally call PostTaskAndReply() instead of PostTask(), but // ResolveProxyOnNetworkThread()'s call to - // net::ProxyResolutionService::ResolveProxy() can result in an asynchronous - // lookup, in which case the result won't be available immediately. + // net::ProxyResolutionService::DbusResolveProxy() can result in an + // asynchronous lookup, in which case the result won't be available + // immediately. context_getter->GetNetworkTaskRunner()->PostTask( FROM_HERE, base::BindOnce( &ProxyResolutionServiceProvider::ResolveProxyOnNetworkThread, - std::move(request), origin_thread_, notify_callback)); + std::move(request))); } // static void ProxyResolutionServiceProvider::ResolveProxyOnNetworkThread( - std::unique_ptr<Request> request, - scoped_refptr<base::SingleThreadTaskRunner> notify_thread, - NotifyCallback notify_callback) { + std::unique_ptr<Request> request) { DCHECK(request->context_getter->GetNetworkTaskRunner() ->BelongsToCurrentThread()); @@ -151,16 +161,14 @@ request->context_getter->GetURLRequestContext() ->proxy_resolution_service(); if (!proxy_resolution_service) { - request->error = "No proxy service in chrome"; - OnResolutionComplete(std::move(request), notify_thread, notify_callback, - net::ERR_UNEXPECTED); + request->PostNotify("No proxy service in chrome", "DIRECT"); return; } Request* request_ptr = request.get(); - net::CompletionCallback callback = base::Bind( - &ProxyResolutionServiceProvider::OnResolutionComplete, - base::Passed(std::move(request)), notify_thread, notify_callback); + net::CompletionCallback callback = + base::BindRepeating(&ProxyResolutionServiceProvider::OnResolutionComplete, + base::Passed(std::move(request))); VLOG(1) << "Starting network proxy resolution for " << request_ptr->source_url; @@ -176,28 +184,29 @@ // static void ProxyResolutionServiceProvider::OnResolutionComplete( std::unique_ptr<Request> request, - scoped_refptr<base::SingleThreadTaskRunner> notify_thread, - NotifyCallback notify_callback, int result) { DCHECK(request->context_getter->GetNetworkTaskRunner() ->BelongsToCurrentThread()); - if (request->error.empty() && result != net::OK) - request->error = net::ErrorToString(result); + request->request.reset(); - notify_thread->PostTask(FROM_HERE, - base::BindOnce(notify_callback, std::move(request))); + request->PostNotify( + result == net::OK ? "" : net::ErrorToString(result), + result == net::OK ? request->proxy_info.ToPacString() : "DIRECT"); } void ProxyResolutionServiceProvider::NotifyProxyResolved( - std::unique_ptr<Request> request) { + std::unique_ptr<dbus::Response> response, + dbus::ExportedObject::ResponseSender response_sender, + const std::string& error, + const std::string& pac_string) { DCHECK(OnOriginThread()); // Reply to the original D-Bus method call. - dbus::MessageWriter writer(request->response.get()); - writer.AppendString(request->proxy_info.ToPacString()); - writer.AppendString(request->error); - request->response_sender.Run(std::move(request->response)); + dbus::MessageWriter writer(response.get()); + writer.AppendString(pac_string); + writer.AppendString(error); + response_sender.Run(std::move(response)); } } // namespace chromeos
diff --git a/chrome/browser/chromeos/dbus/proxy_resolution_service_provider.h b/chrome/browser/chromeos/dbus/proxy_resolution_service_provider.h index 8516cef..cfa9181 100644 --- a/chrome/browser/chromeos/dbus/proxy_resolution_service_provider.h +++ b/chrome/browser/chromeos/dbus/proxy_resolution_service_provider.h
@@ -13,7 +13,6 @@ #include "base/memory/weak_ptr.h" #include "chromeos/dbus/services/cros_dbus_service.h" #include "dbus/exported_object.h" -#include "net/base/completion_callback.h" namespace base { class SingleThreadTaskRunner; @@ -71,6 +70,15 @@ // Data used for a single proxy resolution. struct Request; + // Callback that is invoked with the result of proxy resolution. On success + // |error| is empty, and |pac_string| contains the result. Otherwise |error| + // is non-empty. + using NotifyCallback = + base::OnceCallback<void(const std::string& error, + const std::string& pac_string)>; + + friend class ProxyResolutionServiceProviderTestWrapper; + // Returns true if called on |origin_thread_|. bool OnOriginThread(); @@ -81,35 +89,27 @@ // Callback invoked when Chrome OS clients send network proxy resolution // requests to the service. Called on UI thread. - void ResolveProxy(dbus::MethodCall* method_call, - dbus::ExportedObject::ResponseSender response_sender); + void DbusResolveProxy(dbus::MethodCall* method_call, + dbus::ExportedObject::ResponseSender response_sender); - // Callback passed to network thread static methods to run - // NotifyProxyResolved() on |origin_thread_|. This callback can be bound to a - // WeakPtr from |weak_ptr_factory_| (since the pointer will be dereferenced on - // |origin_thread_|), but the network methods can't (since WeakPtr disallows - // use on threads besides the one where it was created) and are static as a - // result. - using NotifyCallback = base::Callback<void(std::unique_ptr<Request>)>; + void ResolveProxyInternal(const std::string& source_url, + NotifyCallback callback); // Helper method for ResolveProxy() that runs on network thread. - static void ResolveProxyOnNetworkThread( - std::unique_ptr<Request> request, - scoped_refptr<base::SingleThreadTaskRunner> notify_thread, - NotifyCallback notify_callback); + static void ResolveProxyOnNetworkThread(std::unique_ptr<Request> request); // Callback on network thread for when // net::ProxyResolutionService::ResolveProxy() completes, synchronously or // asynchronously. - static void OnResolutionComplete( - std::unique_ptr<Request> request, - scoped_refptr<base::SingleThreadTaskRunner> notify_thread, - NotifyCallback notify_callback, - int result); + static void OnResolutionComplete(std::unique_ptr<Request> request, + int result); // Called on UI thread from OnResolutionComplete() to pass the resolved proxy // information to the client over D-Bus. - void NotifyProxyResolved(std::unique_ptr<Request> request); + void NotifyProxyResolved(std::unique_ptr<dbus::Response> response, + dbus::ExportedObject::ResponseSender response_sender, + const std::string& error, + const std::string& pac_string); scoped_refptr<dbus::ExportedObject> exported_object_; scoped_refptr<base::SingleThreadTaskRunner> origin_thread_;
diff --git a/chrome/browser/chromeos/dbus/proxy_resolution_service_provider_browsertest.cc b/chrome/browser/chromeos/dbus/proxy_resolution_service_provider_browsertest.cc new file mode 100644 index 0000000..914de97c --- /dev/null +++ b/chrome/browser/chromeos/dbus/proxy_resolution_service_provider_browsertest.cc
@@ -0,0 +1,144 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/base64.h" +#include "base/bind.h" +#include "base/bind_helpers.h" +#include "chrome/browser/chromeos/dbus/proxy_resolution_service_provider.h" +#include "chrome/common/chrome_switches.h" +#include "chrome/test/base/in_process_browser_test.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/common/content_switches.h" +#include "net/url_request/url_request_context_getter.h" + +namespace chromeos { + +// Helper for calling ProxyResolutionServiceProvider's |ResolveProxyInternal()| +// method. Unlike the unit-tests which mock the network setup, this uses the +// default dependencies from the running browser. +class ProxyResolutionServiceProviderTestWrapper { + public: + ProxyResolutionServiceProviderTestWrapper() { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + } + + ~ProxyResolutionServiceProviderTestWrapper() { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + } + + // Calls ResolveProxyInternal() and returns its result synchronously as a + // single string (which may be prefixed by "ERROR: " if it is an error message + // as opposed to a proxy result). + std::string ResolveProxyAndWait(const std::string& url) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + + base::RunLoop run_loop; + + std::string result; + impl_.ResolveProxyInternal( + url, + base::BindOnce( + &ProxyResolutionServiceProviderTestWrapper::OnResolveProxyComplete, + &result, run_loop.QuitClosure())); + + run_loop.Run(); + + return result; + } + + private: + static void OnResolveProxyComplete(std::string* result, + base::RepeatingClosure quit_closure, + const std::string& error, + const std::string& pac_string) { + if (!error.empty()) { + *result = "ERROR: " + error; + } else { + *result = pac_string; + } + + std::move(quit_closure).Run(); + } + + ProxyResolutionServiceProvider impl_; + + DISALLOW_COPY_AND_ASSIGN(ProxyResolutionServiceProviderTestWrapper); +}; + +// Base test fixture that exposes a way to invoke ProxyResolutionServiceProvider +// synchronously from the UI thread. +class ProxyResolutionServiceProviderBaseBrowserTest + : public InProcessBrowserTest { + public: + void SetUpOnMainThread() override { + InProcessBrowserTest::SetUpOnMainThread(); + proxy_service_ = + std::make_unique<ProxyResolutionServiceProviderTestWrapper>(); + } + + void TearDownOnMainThread() override { + proxy_service_.reset(); + InProcessBrowserTest::TearDownOnMainThread(); + } + + std::string ResolveProxyAndWait(const std::string& source_url) { + return proxy_service_->ResolveProxyAndWait(source_url); + } + + private: + std::unique_ptr<ProxyResolutionServiceProviderTestWrapper> proxy_service_; +}; + +// Fixture that launches the browser with --proxy-server="https://proxy.test". +class ProxyResolutionServiceProviderManualProxyBrowserTest + : public ProxyResolutionServiceProviderBaseBrowserTest { + public: + void SetUpCommandLine(base::CommandLine* command_line) override { + command_line->AppendSwitchASCII(switches::kProxyServer, + "https://proxy.test"); + } +}; + +// Tests that the D-Bus proxy resolver returns the correct result when using +// --proxy-server flag. These resolutions will happen synchronously at the //net +// layer. +IN_PROC_BROWSER_TEST_F(ProxyResolutionServiceProviderManualProxyBrowserTest, + ResolveProxy) { + EXPECT_EQ("HTTPS proxy.test:443", + ResolveProxyAndWait("http://www.google.com")); +} + +// Simple PAC script that returns the same two proxies for all requests. +const char kPacData[] = + "function FindProxyForURL(url, host) {\n" + " return 'PROXY foo1; PROXY foo2';\n" + "}\n"; + +// Fixture that launches the browser with --proxy-pac-url="data:...". +class ProxyResolutionServiceProviderPacBrowserTest + : public ProxyResolutionServiceProviderBaseBrowserTest { + public: + void SetUpCommandLine(base::CommandLine* command_line) override { + command_line->AppendSwitchASCII(switches::kProxyPacUrl, GetPacUrl()); + } + + private: + // Encode the PAC script as a data: URL. + static std::string GetPacUrl() { + std::string b64_encoded; + base::Base64Encode(kPacData, &b64_encoded); + return "data:application/x-javascript-config;base64," + b64_encoded; + } +}; + +// Tests that the D-Bus proxy resolver returns the correct result when using +// --proxy-pac-url flag. These resolutions will happen asynchronously at the +// //net layer, as they need to query a PAC script. +IN_PROC_BROWSER_TEST_F(ProxyResolutionServiceProviderPacBrowserTest, + ResolveProxy) { + EXPECT_EQ("PROXY foo1:80;PROXY foo2:80", + ResolveProxyAndWait("http://www.google.com")); +} + +} // namespace chromeos
diff --git a/chrome/browser/chromeos/login/users/avatar/user_image_manager_browsertest.cc b/chrome/browser/chromeos/login/users/avatar/user_image_manager_browsertest.cc index 45e590c..9c09df4 100644 --- a/chrome/browser/chromeos/login/users/avatar/user_image_manager_browsertest.cc +++ b/chrome/browser/chromeos/login/users/avatar/user_image_manager_browsertest.cc
@@ -62,15 +62,12 @@ #include "components/prefs/pref_change_registrar.h" #include "components/prefs/pref_service.h" #include "components/prefs/scoped_user_pref_update.h" -#include "components/signin/core/browser/profile_oauth2_token_service.h" #include "components/user_manager/scoped_user_manager.h" #include "components/user_manager/user.h" #include "components/user_manager/user_image/user_image.h" #include "components/user_manager/user_manager.h" #include "crypto/rsa_private_key.h" -#include "google_apis/gaia/gaia_oauth_client.h" #include "google_apis/gaia/gaia_urls.h" -#include "google_apis/gaia/oauth2_token_service.h" #include "net/test/embedded_test_server/controllable_http_response.h" #include "net/test/embedded_test_server/embedded_test_server.h" #include "net/test/embedded_test_server/http_request.h"
diff --git a/chrome/browser/extensions/api/autofill_private/autofill_private_api.cc b/chrome/browser/extensions/api/autofill_private/autofill_private_api.cc index 3fea3a1..1379f8ec 100644 --- a/chrome/browser/extensions/api/autofill_private/autofill_private_api.cc +++ b/chrome/browser/extensions/api/autofill_private/autofill_private_api.cc
@@ -370,7 +370,6 @@ autofill_util::AddressEntryList address_list = autofill_util::GenerateAddressList(*personal_data); - base::RecordAction(base::UserMetricsAction("AutofillAddressesViewed")); return RespondNow(ArgumentList( api::autofill_private::GetAddressList::Results::Create(address_list))); } @@ -539,7 +538,6 @@ autofill_util::CreditCardEntryList credit_card_list = autofill_util::GenerateCreditCardList(*personal_data); - base::RecordAction(base::UserMetricsAction("AutofillCreditCardsViewed")); return RespondNow( ArgumentList(api::autofill_private::GetCreditCardList::Results::Create( credit_card_list)));
diff --git a/chrome/browser/extensions/api/cast_streaming/performance_test.cc b/chrome/browser/extensions/api/cast_streaming/performance_test.cc index 2d218e5..73d4dea 100644 --- a/chrome/browser/extensions/api/cast_streaming/performance_test.cc +++ b/chrome/browser/extensions/api/cast_streaming/performance_test.cc
@@ -7,27 +7,28 @@ #include <algorithm> #include <cmath> +#include <cstring> #include <iterator> #include <map> #include <vector> +#include "base/base64.h" #include "base/command_line.h" -#include "base/macros.h" -#include "base/strings/string_number_conversions.h" +#include "base/files/file_path.h" +#include "base/files/file_util.h" +#include "base/strings/strcat.h" #include "base/strings/stringprintf.h" #include "base/test/trace_event_analyzer.h" #include "base/time/default_tick_clock.h" +#include "base/values.h" #include "build/build_config.h" -#include "chrome/browser/extensions/extension_apitest.h" -#include "chrome/browser/extensions/extension_service.h" -#include "chrome/browser/extensions/tab_helper.h" +#include "chrome/browser/extensions/api/tab_capture/tab_capture_performance_test_base.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/common/chrome_paths.h" #include "chrome/common/chrome_switches.h" -#include "chrome/test/base/test_launcher_utils.h" -#include "chrome/test/base/test_switches.h" #include "chrome/test/base/tracing.h" #include "content/public/common/content_switches.h" -#include "extensions/common/switches.h" -#include "extensions/test/extension_test_message_listener.h" +#include "content/public/test/browser_test_utils.h" #include "media/base/audio_bus.h" #include "media/base/video_frame.h" #include "media/cast/test/skewed_tick_clock.h" @@ -44,19 +45,10 @@ #include "net/base/rand_callback.h" #include "net/log/net_log_source.h" #include "net/socket/udp_server_socket.h" -#include "testing/gtest/include/gtest/gtest.h" #include "testing/perf/perf_test.h" -#include "ui/compositor/compositor_switches.h" -#include "ui/gl/gl_switches.h" - -#if defined(OS_WIN) -#include "base/win/windows_version.h" -#endif namespace { -constexpr char kExtensionId[] = "ddchlicdkolnonkihahngkmmmjnjlkkf"; - // Number of events to trim from the begining and end. These events don't // contribute anything toward stable measurements: A brief moment of startup // "jank" is acceptable, and shutdown may result in missing events (e.g., if @@ -67,9 +59,6 @@ constexpr size_t kMinDataPoints = 100; // 1 sec of audio, or ~5 sec at 24fps. enum TestFlags { - kUseGpu = 1 << 0, // Only execute test if --enable-gpu was given - // on the command line. This is required for - // tests that run on GPU. kSmallWindow = 1 << 2, // Window size: 1 = 800x600, 0 = 2000x1000 k24fps = 1 << 3, // Use 24 fps video. k30fps = 1 << 4, // Use 30 fps video. @@ -350,25 +339,21 @@ DISALLOW_COPY_AND_ASSIGN(TestPatternReceiver); }; -class CastV2PerformanceTest : public extensions::ExtensionApiTest, +class CastV2PerformanceTest : public TabCapturePerformanceTestBase, public testing::WithParamInterface<int> { public: - CastV2PerformanceTest() { LOG(ERROR) << __func__ << ": Hello!"; } - - ~CastV2PerformanceTest() override { LOG(ERROR) << __func__ << ": Goodbye!"; } + CastV2PerformanceTest() = default; + ~CastV2PerformanceTest() override = default; bool HasFlag(TestFlags flag) const { return (GetParam() & flag) == flag; } - bool IsGpuAvailable() const { - return base::CommandLine::ForCurrentProcess()->HasSwitch("enable-gpu"); - } - - std::string GetSuffixForTestFlags() { + std::string GetSuffixForTestFlags() const { std::string suffix; - if (HasFlag(kUseGpu)) - suffix += "_gpu"; + // Note: Add "_gpu" tag for backwards-compatibility with existing + // Performance Dashboard timeseries data. + suffix += "_gpu"; if (HasFlag(kSmallWindow)) suffix += "_small"; if (HasFlag(k24fps)) @@ -392,7 +377,7 @@ return suffix; } - int getfps() { + int get_fps() const { if (HasFlag(k24fps)) return 24; if (HasFlag(k30fps)) @@ -404,45 +389,38 @@ } void SetUp() override { - LOG(ERROR) << __func__ << ": Starting..."; - EnablePixelOutput(); - if (!HasFlag(kUseGpu)) - UseSoftwareCompositing(); - LOG(ERROR) << __func__ << ": Doing normal SetUp()..."; - extensions::ExtensionApiTest::SetUp(); - LOG(ERROR) << __func__ << ": Completed."; - } + // Produce the full HTML test page with the barcode video embedded within + // (as a data URI). + const base::FilePath video_file = + GetApiTestDataDir() + .AppendASCII("cast_streaming") + .AppendASCII( + base::StringPrintf("test_video_%dfps.webm", get_fps())); + std::string file_contents; + const bool success = base::ReadFileToString(video_file, &file_contents); + CHECK(success) << "Failed to load video at: " << video_file.AsUTF8Unsafe(); + std::string video_in_base64; + base::Base64Encode(file_contents, &video_in_base64); + test_page_html_ = + base::StrCat({"<html><body>\n" + "<video width='100%' height='100%'>\n" + " <source src='data:video/webm;base64,", + video_in_base64, + "'>\n" + "</video>\n" + "</body></html>"}); - void SetUpOnMainThread() override { - LOG(ERROR) << __func__ << ": Doing normal SetUpOnMainThread()..."; - extensions::ExtensionApiTest::SetUpOnMainThread(); - LOG(ERROR) << __func__ << ": Completed."; + TabCapturePerformanceTestBase::SetUp(); } void SetUpCommandLine(base::CommandLine* command_line) override { - LOG(ERROR) << __func__ << ": Starting..."; - // Some of the tests may launch http requests through JSON or AJAX - // which causes a security error (cross domain request) when the page - // is loaded from the local file system ( file:// ). The following switch - // fixes that error. - command_line->AppendSwitch(switches::kAllowFileAccessFromFiles); - if (HasFlag(kSmallWindow)) { command_line->AppendSwitchASCII(switches::kWindowSize, "800,600"); } else { command_line->AppendSwitchASCII(switches::kWindowSize, "2000,1500"); } - if (!HasFlag(kUseGpu)) - command_line->AppendSwitch(switches::kDisableGpu); - - command_line->AppendSwitchASCII( - extensions::switches::kWhitelistedExtensionID, - kExtensionId); - - LOG(ERROR) << __func__ << ": Doing normal SetUpCommandLine()..."; - extensions::ExtensionApiTest::SetUpCommandLine(command_line); - LOG(ERROR) << __func__ << ": Completed."; + TabCapturePerformanceTestBase::SetUpCommandLine(command_line); } void GetTraceEvents(trace_analyzer::TraceAnalyzer* analyzer, @@ -623,128 +601,139 @@ return MeanAndError(deltas); } - void RunTest(const std::string& test_name) { - LOG(ERROR) << __func__ << ": Starting..."; + protected: + // The complete HTML test web page without any external dependencies, + // including the entire barcode video as an embedded data URI. Populated in + // SetUp(). + std::string test_page_html_; - if (HasFlag(kUseGpu) && !IsGpuAvailable()) { - LOG(WARNING) << - "Test skipped: requires gpu. Pass --enable-gpu on the command " - "line if use of GPU is desired."; - return; - } + // While the source video frame rate may vary (24, 30, or 60 FPS), the maximum + // capture frame rate is always fixed at 30 FPS. This allows testing of the + // entire system when it is forced to perform a 60→30 frame rate conversion. + static constexpr int kMaxCaptureFrameRate = 30; - ASSERT_EQ(1, - (HasFlag(k24fps) ? 1 : 0) + - (HasFlag(k30fps) ? 1 : 0) + - (HasFlag(k60fps) ? 1 : 0)); - - net::IPEndPoint receiver_end_point = media::cast::test::GetFreeLocalPort(); - LOG(ERROR) << __func__ << ": Got local UDP port for testing: " - << receiver_end_point.ToString(); - - // Start the in-process receiver that examines audio/video for the expected - // test patterns. - base::TimeDelta delta = base::TimeDelta::FromSeconds(0); - if (HasFlag(kFastClock)) { - delta = base::TimeDelta::FromSeconds(10); - } - if (HasFlag(kSlowClock)) { - delta = base::TimeDelta::FromSeconds(-10); - } - scoped_refptr<media::cast::StandaloneCastEnvironment> cast_environment( - new SkewedCastEnvironment(delta)); - TestPatternReceiver* const receiver = - new TestPatternReceiver(cast_environment, receiver_end_point); - LOG(ERROR) << __func__ << ": Starting receiver..."; - receiver->Start(); - - LOG(ERROR) << __func__ << ": Creating UDPProxy..."; - std::unique_ptr<media::cast::test::UDPProxy> udp_proxy; - if (HasFlag(kProxyWifi) || HasFlag(kProxySlow) || HasFlag(kProxyBad)) { - net::IPEndPoint proxy_end_point = media::cast::test::GetFreeLocalPort(); - if (HasFlag(kProxyWifi)) { - udp_proxy = media::cast::test::UDPProxy::Create( - proxy_end_point, receiver_end_point, - media::cast::test::WifiNetwork(), media::cast::test::WifiNetwork(), - nullptr); - } else if (HasFlag(kProxySlow)) { - udp_proxy = media::cast::test::UDPProxy::Create( - proxy_end_point, receiver_end_point, - media::cast::test::SlowNetwork(), media::cast::test::SlowNetwork(), - nullptr); - } else if (HasFlag(kProxyBad)) { - udp_proxy = media::cast::test::UDPProxy::Create( - proxy_end_point, receiver_end_point, - media::cast::test::BadNetwork(), media::cast::test::BadNetwork(), - nullptr); - } - receiver_end_point = proxy_end_point; - } - - LOG(ERROR) << __func__ << ": Starting tracing..."; - std::string json_events; - ASSERT_TRUE(tracing::BeginTracing("gpu.capture,cast_perf_test")); - const std::string page_url = base::StringPrintf( - "performance%d.html?port=%d&autoThrottling=%s&aesKey=%s&aesIvMask=%s", - getfps(), receiver_end_point.port(), - HasFlag(kAutoThrottling) ? "true" : "false", - base::HexEncode(kAesKey, sizeof(kAesKey)).c_str(), - base::HexEncode(kAesIvMask, sizeof(kAesIvMask)).c_str()); - LOG(ERROR) << __func__ << ": Running extension subtest..."; - ASSERT_TRUE(RunExtensionSubtest("cast_streaming", page_url)) << message_; - LOG(ERROR) << __func__ << ": Extension subtest finished. Ending tracing..."; - ASSERT_TRUE(tracing::EndTracing(&json_events)); - LOG(ERROR) << __func__ << ": Stopping receiver..."; - receiver->Stop(); - - // Stop all threads, removes the need for synchronization when analyzing - // the data. - LOG(ERROR) << __func__ << ": Shutting-down CastEnvironment..."; - cast_environment->Shutdown(); - LOG(ERROR) << __func__ << ": Analyzing..."; - std::unique_ptr<trace_analyzer::TraceAnalyzer> analyzer; - analyzer.reset(trace_analyzer::TraceAnalyzer::Create(json_events)); - analyzer->AssociateAsyncBeginEndEvents(); - - // This prints out the average time between capture events. - // Depending on the test, the capture frame rate is capped (e.g., at 30fps, - // this score cannot get any better than 33.33 ms). However, the measurement - // is important since it provides a valuable check that capture can keep up - // with the content's framerate. - MeanAndError capture_data = AnalyzeTraceDistance(analyzer.get(), "Capture"); - // Lower is better. - capture_data.Print(test_name, - GetSuffixForTestFlags(), - "time_between_captures", - "ms"); - - receiver->Analyze(test_name, GetSuffixForTestFlags()); - - AnalyzeLatency(test_name, analyzer.get()); - LOG(ERROR) << __func__ << ": Completed."; - } + // Naming of performance measurement written to stdout. + static const char kTestName[]; }; +// static +const char CastV2PerformanceTest::kTestName[] = "CastV2Performance"; + } // namespace IN_PROC_BROWSER_TEST_P(CastV2PerformanceTest, Performance) { - LOG(ERROR) << __func__ << ": Test procedure started."; - RunTest("CastV2Performance"); - LOG(ERROR) << __func__ << ": Completed."; + net::IPEndPoint receiver_end_point = media::cast::test::GetFreeLocalPort(); + VLOG(1) << "Got local UDP port for testing: " + << receiver_end_point.ToString(); + + // Start the in-process receiver that examines audio/video for the expected + // test patterns. + base::TimeDelta delta = base::TimeDelta::FromSeconds(0); + if (HasFlag(kFastClock)) { + delta = base::TimeDelta::FromSeconds(10); + } + if (HasFlag(kSlowClock)) { + delta = base::TimeDelta::FromSeconds(-10); + } + scoped_refptr<media::cast::StandaloneCastEnvironment> cast_environment( + new SkewedCastEnvironment(delta)); + TestPatternReceiver* const receiver = + new TestPatternReceiver(cast_environment, receiver_end_point); + receiver->Start(); + + // Create a proxy for the UDP packets that simulates certain network + // environments. + std::unique_ptr<media::cast::test::UDPProxy> udp_proxy; + if (HasFlag(kProxyWifi) || HasFlag(kProxySlow) || HasFlag(kProxyBad)) { + net::IPEndPoint proxy_end_point = media::cast::test::GetFreeLocalPort(); + if (HasFlag(kProxyWifi)) { + udp_proxy = media::cast::test::UDPProxy::Create( + proxy_end_point, receiver_end_point, media::cast::test::WifiNetwork(), + media::cast::test::WifiNetwork(), nullptr); + } else if (HasFlag(kProxySlow)) { + udp_proxy = media::cast::test::UDPProxy::Create( + proxy_end_point, receiver_end_point, media::cast::test::SlowNetwork(), + media::cast::test::SlowNetwork(), nullptr); + } else if (HasFlag(kProxyBad)) { + udp_proxy = media::cast::test::UDPProxy::Create( + proxy_end_point, receiver_end_point, media::cast::test::BadNetwork(), + media::cast::test::BadNetwork(), nullptr); + } + receiver_end_point = proxy_end_point; + } + + // Load the extension and test page, and tell the extension to start tab + // capture + Cast Streaming. + LoadExtension(GetApiTestDataDir() + .AppendASCII("cast_streaming") + .AppendASCII("perftest_extension")); + NavigateToTestPage(test_page_html_); + const base::Value response = SendMessageToExtension(base::StringPrintf( + "{start:true, enableAutoThrottling:%s, maxFrameRate:%d, recvPort:%d," + " aesKey:'%s', aesIvMask:'%s'}", + HasFlag(kAutoThrottling) ? "true" : "false", kMaxCaptureFrameRate, + receiver_end_point.port(), + base::HexEncode(kAesKey, sizeof(kAesKey)).c_str(), + base::HexEncode(kAesIvMask, sizeof(kAesIvMask)).c_str())); + const std::string* reason = response.FindStringKey("reason"); + ASSERT_TRUE(response.FindBoolKey("success").value_or(false)) + << (reason ? *reason : std::string("<MISSING REASON>")); + + // Now that capture has started, start playing the barcode video in the test + // page. + const std::string javascript_to_play_video( + "new Promise((resolve) => {\n" + " const video = document.getElementsByTagName('video')[0];\n" + " video.addEventListener('playing', () => { resolve(true); });\n" + " video.play();\n" + "})"); + LOG(INFO) << "Starting playback of barcode video..."; + ASSERT_EQ(true, content::EvalJs( + browser()->tab_strip_model()->GetActiveWebContents(), + javascript_to_play_video)); + + // Observe the running browser for a while, collecting a trace. + const std::string json_events = TraceAndObserve("gpu.capture,cast_perf_test"); + + // Shut down the receiver and all the CastEnvironment threads. + VLOG(1) << "Shutting-down receiver and CastEnvironment..."; + receiver->Stop(); + cast_environment->Shutdown(); + + VLOG(2) << "Dump of trace events (trace_events.json.gz.b64):\n" + << MakeBase64EncodedGZippedString(json_events); + + VLOG(1) << "Analyzing trace events..."; + std::unique_ptr<trace_analyzer::TraceAnalyzer> analyzer; + analyzer.reset(trace_analyzer::TraceAnalyzer::Create(json_events)); + analyzer->AssociateAsyncBeginEndEvents(); + + // This prints out the average time between capture events. + // Depending on the test, the capture frame rate is capped (e.g., at 30fps, + // this score cannot get any better than 33.33 ms). However, the measurement + // is important since it provides a valuable check that capture can keep up + // with the content's framerate. + MeanAndError capture_data = AnalyzeTraceDistance(analyzer.get(), "Capture"); + // Lower is better. + capture_data.Print(kTestName, GetSuffixForTestFlags(), + "time_between_captures", "ms"); + + receiver->Analyze(kTestName, GetSuffixForTestFlags()); + + AnalyzeLatency(kTestName, analyzer.get()); } // Note: First argument is optional and intentionally left blank. // (it's a prefix for the generated test cases) -INSTANTIATE_TEST_CASE_P( - , - CastV2PerformanceTest, - testing::Values(kUseGpu | k24fps, - kUseGpu | k30fps, - kUseGpu | k60fps, - kUseGpu | k30fps | kProxyWifi, - kUseGpu | k30fps | kProxyBad, - kUseGpu | k30fps | kSlowClock, - kUseGpu | k30fps | kFastClock, - kUseGpu | k30fps | kProxyWifi | kAutoThrottling, - kUseGpu | k30fps | kProxySlow | kAutoThrottling, - kUseGpu | k30fps | kProxyBad | kAutoThrottling)); +INSTANTIATE_TEST_CASE_P(, + CastV2PerformanceTest, + testing::Values(k24fps, + k30fps, + k60fps, + k30fps | kProxyWifi, + k30fps | kProxyBad, + k30fps | kSlowClock, + k30fps | kFastClock, + k30fps | kProxyWifi | kAutoThrottling, + k30fps | kProxySlow | kAutoThrottling, + k30fps | kProxyBad | kAutoThrottling));
diff --git a/chrome/browser/extensions/api/tab_capture/tab_capture_performance_test_base.cc b/chrome/browser/extensions/api/tab_capture/tab_capture_performance_test_base.cc new file mode 100644 index 0000000..3d6e530 --- /dev/null +++ b/chrome/browser/extensions/api/tab_capture/tab_capture_performance_test_base.cc
@@ -0,0 +1,217 @@ +// 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 "chrome/browser/extensions/api/tab_capture/tab_capture_performance_test_base.h" + +#include <stdint.h> + +#include <cmath> + +#include "base/base64.h" +#include "base/command_line.h" +#include "base/files/file_path.h" +#include "base/path_service.h" +#include "base/strings/stringprintf.h" +#include "chrome/browser/extensions/extension_service.h" +#include "chrome/browser/extensions/unpacked_installer.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/common/chrome_paths.h" +#include "chrome/test/base/tracing.h" +#include "chrome/test/base/ui_test_utils.h" +#include "content/public/test/browser_test_utils.h" +#include "extensions/browser/extension_registry.h" +#include "extensions/browser/extension_system.h" +#include "extensions/browser/test_extension_registry_observer.h" +#include "extensions/common/extension.h" +#include "extensions/common/switches.h" +#include "net/dns/mock_host_resolver.h" +#include "net/test/embedded_test_server/embedded_test_server.h" +#include "net/test/embedded_test_server/http_request.h" +#include "net/test/embedded_test_server/http_response.h" +#include "third_party/zlib/google/compression_utils.h" +#include "ui/gl/gl_switches.h" + +TabCapturePerformanceTestBase::TabCapturePerformanceTestBase() = default; + +TabCapturePerformanceTestBase::~TabCapturePerformanceTestBase() = default; + +void TabCapturePerformanceTestBase::SetUp() { + // Because screen capture is involved, require pixel output. + EnablePixelOutput(); + + InProcessBrowserTest::SetUp(); +} + +void TabCapturePerformanceTestBase::SetUpOnMainThread() { + InProcessBrowserTest::SetUpOnMainThread(); + + host_resolver()->AddRule("*", "127.0.0.1"); + embedded_test_server()->RegisterRequestHandler(base::BindRepeating( + &TabCapturePerformanceTestBase::HandleRequest, base::Unretained(this))); + const bool did_start = embedded_test_server()->Start(); + CHECK(did_start); +} + +void TabCapturePerformanceTestBase::SetUpCommandLine( + base::CommandLine* command_line) { + // Note: The naming "kUseGpuInTests" is very misleading. It actually means + // "don't use a software OpenGL implementation." Subclasses will either call + // UseSoftwareCompositing() to use Chrome's software compositor, or else they + // won't (which means use the default hardware-accelerated compositor). + command_line->AppendSwitch(switches::kUseGpuInTests); + + command_line->AppendSwitchASCII(extensions::switches::kWhitelistedExtensionID, + kExtensionId); + + InProcessBrowserTest::SetUpCommandLine(command_line); +} + +void TabCapturePerformanceTestBase::LoadExtension( + const base::FilePath& unpacked_dir) { + CHECK(!extension_); + + LOG(INFO) << "Loading extension..."; + auto* const extension_registry = + extensions::ExtensionRegistry::Get(browser()->profile()); + extensions::TestExtensionRegistryObserver registry_observer( + extension_registry); + auto* const extension_service = + extensions::ExtensionSystem::Get(browser()->profile()) + ->extension_service(); + extensions::UnpackedInstaller::Create(extension_service)->Load(unpacked_dir); + extension_ = registry_observer.WaitForExtensionReady(); + CHECK(extension_); + CHECK_EQ(kExtensionId, extension_->id()); +} + +void TabCapturePerformanceTestBase::NavigateToTestPage( + const std::string& test_page_html_content) { + LOG(INFO) << "Navigating to test page..."; + test_page_to_serve_ = test_page_html_content; + ui_test_utils::NavigateToURL( + browser(), + embedded_test_server()->GetURL(kTestWebPageHostname, kTestWebPagePath)); +} + +base::Value TabCapturePerformanceTestBase::SendMessageToExtension( + const std::string& json) { + CHECK(extension_); + + const std::string javascript = base::StringPrintf( + "new Promise((resolve, reject) => {\n" + " chrome.runtime.sendMessage(\n" + " '%s',\n" + " %s,\n" + " response => {\n" + " if (!response) {\n" + " reject(chrome.runtime.lastError.message);\n" + " } else {\n" + " resolve(response);\n" + " }\n" + " });\n" + "})", + extension_->id().c_str(), json.c_str()); + LOG(INFO) << "Sending message to extension: " << json; + auto* const web_contents = + browser()->tab_strip_model()->GetActiveWebContents(); + for (;;) { + const auto result = content::EvalJs(web_contents, javascript); + if (result.error.empty()) { + return result.value.Clone(); + } + LOG(INFO) << "Race condition: Waiting for extension to come up, before " + "'sendMessage' retry..."; + ContinueBrowserFor(kSendMessageRetryPeriod); + } + NOTREACHED(); + return base::Value(); +} + +std::string TabCapturePerformanceTestBase::TraceAndObserve( + const std::string& category_patterns) { + LOG(INFO) << "Starting tracing and running for " + << kObservationPeriod.InSecondsF() << " sec..."; + std::string json_events; + bool success = tracing::BeginTracing(category_patterns); + CHECK(success); + ContinueBrowserFor(kObservationPeriod); + success = tracing::EndTracing(&json_events); + CHECK(success); + LOG(INFO) << "Observation period has completed. Ending tracing..."; + return json_events; +} + +// static +base::FilePath TabCapturePerformanceTestBase::GetApiTestDataDir() { + base::FilePath dir; + const bool success = base::PathService::Get(chrome::DIR_TEST_DATA, &dir); + CHECK(success); + return dir.AppendASCII("extensions").AppendASCII("api_test"); +} + +// static +std::string TabCapturePerformanceTestBase::MakeBase64EncodedGZippedString( + const std::string& input) { + std::string gzipped_input; + compression::GzipCompress(input, &gzipped_input); + std::string result; + base::Base64Encode(gzipped_input, &result); + + // Break up the string with newlines to make it easier to handle in the + // console logs. + constexpr size_t kMaxLineWidth = 80; + std::string formatted_result; + formatted_result.reserve(result.size() + 1 + (result.size() / kMaxLineWidth)); + for (std::string::size_type src_pos = 0; src_pos < result.size(); + src_pos += kMaxLineWidth) { + formatted_result.append(result, src_pos, kMaxLineWidth); + formatted_result.append(1, '\n'); + } + return formatted_result; +} + +// static +void TabCapturePerformanceTestBase::ContinueBrowserFor( + base::TimeDelta duration) { + base::RunLoop run_loop; + base::SequencedTaskRunnerHandle::Get()->PostDelayedTask( + FROM_HERE, run_loop.QuitClosure(), duration); + run_loop.Run(); +} + +std::unique_ptr<net::test_server::HttpResponse> +TabCapturePerformanceTestBase::HandleRequest( + const net::test_server::HttpRequest& request) { + auto response = std::make_unique<net::test_server::BasicHttpResponse>(); + response->set_content_type("text/html"); + const GURL& url = request.GetURL(); + if (url.path() == kTestWebPagePath) { + response->set_content(test_page_to_serve_); + } else { + response->set_code(net::HTTP_NOT_FOUND); + } + VLOG(1) << __func__ << ": request url=" << url.spec() + << ", response=" << response->code(); + return response; +} + +// static +constexpr base::TimeDelta TabCapturePerformanceTestBase::kObservationPeriod; + +// static +constexpr base::TimeDelta + TabCapturePerformanceTestBase::kSendMessageRetryPeriod; + +// static +const char TabCapturePerformanceTestBase::kTestWebPageHostname[] = + "in-process-perf-test.chromium.org"; + +// static +const char TabCapturePerformanceTestBase::kTestWebPagePath[] = + "/test_page.html"; + +// static +const char TabCapturePerformanceTestBase::kExtensionId[] = + "ddchlicdkolnonkihahngkmmmjnjlkkf";
diff --git a/chrome/browser/extensions/api/tab_capture/tab_capture_performance_test_base.h b/chrome/browser/extensions/api/tab_capture/tab_capture_performance_test_base.h new file mode 100644 index 0000000..5f71057 --- /dev/null +++ b/chrome/browser/extensions/api/tab_capture/tab_capture_performance_test_base.h
@@ -0,0 +1,120 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_EXTENSIONS_API_TAB_CAPTURE_TAB_CAPTURE_PERFORMANCE_TEST_BASE_H_ +#define CHROME_BROWSER_EXTENSIONS_API_TAB_CAPTURE_TAB_CAPTURE_PERFORMANCE_TEST_BASE_H_ + +#include <memory> +#include <string> + +#include "base/macros.h" +#include "chrome/test/base/in_process_browser_test.h" + +namespace base { +class CommandLine; +class FilePath; +} // namespace base + +namespace extensions { +class Extension; +} + +namespace net { +namespace test_server { +struct HttpRequest; +class HttpResponse; +} // namespace test_server +} // namespace net + +// Base class shared by TabCapturePerformanceTest and +// CastV2StreamingPerformanceTest which includes common set-up and utilities. +// This provides the facility for loading an extension that starts capture, +// loading a test page containing content to be captured, and sending messages +// to engage the extension. +class TabCapturePerformanceTestBase : public InProcessBrowserTest { + public: + TabCapturePerformanceTestBase(); + ~TabCapturePerformanceTestBase() override; + + // SetUp overrides to enable pixel output, configure the embedded test server, + // whitelist the extension loaded by the tests. + void SetUp() override; + void SetUpOnMainThread() override; + void SetUpCommandLine(base::CommandLine* command_line) override; + + // Returns the currently-loaded extension. + const extensions::Extension* extension() const { return extension_; } + + // Loads an unpacked extension found at the given path. This may only be + // called once. This blocks until the extension is ready (but its background + // page might not have run yet!). + void LoadExtension(const base::FilePath& unpacked_dir); + + // Navigate the current (only) browser tab to the test page. This will cause a + // resource request on the embedded test server (see HandleRequest()). This + // blocks until the load is complete. + void NavigateToTestPage(const std::string& test_page_html_content); + + // Execute JavaScript in the test page, to send a message to the extension to + // do something (e.g., start tab capture of the test page), and returns the + // response value. + // + // There is a possible race condition addressed here: The Extensions component + // uses a specialized "serial delayed load queue" that makes it non-trivial to + // discover whether a background page has run yet. If the background page has + // not run yet, there would be nothing listening for the message. To mitigate + // this problem, a simple retry loop is used. + base::Value SendMessageToExtension(const std::string& json); + + // Runs the browser for a while, with tracing enabled to collect events + // matching the given |category_patterns|, then returns the JSON events string + // returned by tracing::EndTracing(). + std::string TraceAndObserve(const std::string& category_patterns); + + // Returns the path ".../test/data/extensions/api_test/". + static base::FilePath GetApiTestDataDir(); + + // GzipCompresses the given |input| string, then Base64-encodes and formats to + // 80-char lines. + static std::string MakeBase64EncodedGZippedString(const std::string& input); + + // Uses base::RunLoop to run the browser for the given |duration|. + static void ContinueBrowserFor(base::TimeDelta duration); + + protected: + // After the page has loaded, this is how long the browser is run with trace + // event recording taking place. + static constexpr base::TimeDelta kObservationPeriod = + base::TimeDelta::FromSeconds(15); + + // If sending a message to the extension fails, because the extension has not + // started its message listener yet, how long before the next retry? + static constexpr base::TimeDelta kSendMessageRetryPeriod = + base::TimeDelta::FromMilliseconds(250); + + // Note: The hostname must match the pattern found in the Extension's manifest + // file, or it will not be able to send/receive messaging from the test web + // page (due to extension permissions). + static const char kTestWebPageHostname[]; + static const char kTestWebPagePath[]; + + // The expected ID of the loaded extension. + static const char kExtensionId[]; + + private: + // Set to the test page that should be served by the next call to + // HandleRequest(). + std::string test_page_to_serve_; + + // Handles requests from the tab open in the browser. Called by the embedded + // test server (see SetUpOnMainThread()). + std::unique_ptr<net::test_server::HttpResponse> HandleRequest( + const net::test_server::HttpRequest& request); + + const extensions::Extension* extension_ = nullptr; + + DISALLOW_COPY_AND_ASSIGN(TabCapturePerformanceTestBase); +}; + +#endif // CHROME_BROWSER_EXTENSIONS_API_TAB_CAPTURE_TAB_CAPTURE_PERFORMANCE_TEST_BASE_H_
diff --git a/chrome/browser/extensions/api/tab_capture/tab_capture_performancetest.cc b/chrome/browser/extensions/api/tab_capture/tab_capture_performancetest.cc index 9aadd4d..63f04e32 100644 --- a/chrome/browser/extensions/api/tab_capture/tab_capture_performancetest.cc +++ b/chrome/browser/extensions/api/tab_capture/tab_capture_performancetest.cc
@@ -7,12 +7,12 @@ #include "base/command_line.h" #include "base/strings/stringprintf.h" #include "base/test/trace_event_analyzer.h" -#include "chrome/browser/extensions/extension_apitest.h" +#include "chrome/browser/extensions/api/tab_capture/tab_capture_performance_test_base.h" #include "chrome/browser/extensions/extension_service.h" -#include "chrome/browser/extensions/tab_helper.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/exclusive_access/fullscreen_controller.h" #include "chrome/common/chrome_switches.h" +#include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/test_launcher_utils.h" #include "chrome/test/base/test_switches.h" #include "chrome/test/base/tracing.h" @@ -30,8 +30,6 @@ namespace { -constexpr char kExtensionId[] = "ddchlicdkolnonkihahngkmmmjnjlkkf"; - // Number of events to trim from the begining and end. These events don't // contribute anything toward stable measurements: A brief moment of startup // "jank" is acceptable, and shutdown may result in missing events (since @@ -49,20 +47,17 @@ kSmallWindow = 1 << 4, // Window size: 1 = 800x600, 0 = 2000x1000 }; -class TabCapturePerformanceTest : public extensions::ExtensionApiTest, +class TabCapturePerformanceTest : public TabCapturePerformanceTestBase, public testing::WithParamInterface<int> { public: - TabCapturePerformanceTest() {} + TabCapturePerformanceTest() = default; + ~TabCapturePerformanceTest() override = default; bool HasFlag(TestFlags flag) const { return (GetParam() & flag) == flag; } - bool IsGpuAvailable() const { - return base::CommandLine::ForCurrentProcess()->HasSwitch("enable-gpu"); - } - - std::string GetSuffixForTestFlags() { + std::string GetSuffixForTestFlags() const { std::string suffix; if (HasFlag(kUseGpu)) suffix += "_comp_gpu"; @@ -74,60 +69,51 @@ } void SetUp() override { - EnablePixelOutput(); + const base::FilePath test_file = GetApiTestDataDir() + .AppendASCII("tab_capture") + .AppendASCII("balls.html"); + const bool success = base::ReadFileToString(test_file, &test_page_html_); + CHECK(success) << "Failed to load test page at: " + << test_file.AsUTF8Unsafe(); + if (!HasFlag(kUseGpu)) UseSoftwareCompositing(); - extensions::ExtensionApiTest::SetUp(); + + TabCapturePerformanceTestBase::SetUp(); } void SetUpCommandLine(base::CommandLine* command_line) override { - // Some of the tests may launch http requests through JSON or AJAX - // which causes a security error (cross domain request) when the page - // is loaded from the local file system ( file:// ). The following switch - // fixes that error. - command_line->AppendSwitch(switches::kAllowFileAccessFromFiles); - if (HasFlag(kSmallWindow)) { command_line->AppendSwitchASCII(switches::kWindowSize, "800,600"); } else { command_line->AppendSwitchASCII(switches::kWindowSize, "2000,1500"); } - if (!HasFlag(kUseGpu)) - command_line->AppendSwitch(switches::kDisableGpu); - - command_line->AppendSwitchASCII( - extensions::switches::kWhitelistedExtensionID, - kExtensionId); - - extensions::ExtensionApiTest::SetUpCommandLine(command_line); + TabCapturePerformanceTestBase::SetUpCommandLine(command_line); } - void FindEvents(trace_analyzer::TraceAnalyzer* analyzer, - const std::string& event_name, - trace_analyzer::TraceEventVector* events) { + static void GetTraceEvents(trace_analyzer::TraceAnalyzer* analyzer, + const std::string& event_name, + trace_analyzer::TraceEventVector* events) { trace_analyzer::Query query = trace_analyzer::Query::EventNameIs(event_name) && (trace_analyzer::Query::EventPhaseIs(TRACE_EVENT_PHASE_BEGIN) || - trace_analyzer::Query::EventPhaseIs(TRACE_EVENT_PHASE_COMPLETE) || trace_analyzer::Query::EventPhaseIs(TRACE_EVENT_PHASE_ASYNC_BEGIN) || trace_analyzer::Query::EventPhaseIs(TRACE_EVENT_PHASE_FLOW_BEGIN) || - trace_analyzer::Query::EventPhaseIs(TRACE_EVENT_PHASE_INSTANT)); + trace_analyzer::Query::EventPhaseIs(TRACE_EVENT_PHASE_INSTANT) || + trace_analyzer::Query::EventPhaseIs(TRACE_EVENT_PHASE_COMPLETE)); analyzer->FindEvents(query, events); + VLOG(0) << "Retrieved " << events->size() << " events for: " << event_name; + ASSERT_LT(2 * kTrimEvents + kMinDataPoints, events->size()) + << "Not enough events of type " << event_name << " found for analysis."; } // Analyze and print the mean and stddev of how often events having the name // |event_name| occur. bool PrintRateResults(trace_analyzer::TraceAnalyzer* analyzer, - const std::string& test_name, const std::string& event_name) { trace_analyzer::TraceEventVector events; - FindEvents(analyzer, event_name, &events); - if (events.size() < (2 * kTrimEvents + kMinDataPoints)) { - LOG(ERROR) << "Not enough events of type " << event_name << " found (" - << events.size() << ") for rate analysis."; - return false; - } + GetTraceEvents(analyzer, event_name, &events); // Ignore some events for startup/setup/caching/teardown. trace_analyzer::TraceEventVector rate_events(events.begin() + kTrimEvents, @@ -141,7 +127,7 @@ double std_dev_ms = stats.standard_deviation_us / 1000.0; std::string mean_and_error = base::StringPrintf("%f,%f", mean_ms, std_dev_ms); - perf_test::PrintResultMeanAndError(test_name, GetSuffixForTestFlags(), + perf_test::PrintResultMeanAndError(kTestName, GetSuffixForTestFlags(), event_name, mean_and_error, "ms", true); return true; } @@ -149,15 +135,9 @@ // Analyze and print the mean and stddev of the amount of time between the // begin and end timestamps of each event having the name |event_name|. bool PrintLatencyResults(trace_analyzer::TraceAnalyzer* analyzer, - const std::string& test_name, const std::string& event_name) { trace_analyzer::TraceEventVector events; - FindEvents(analyzer, event_name, &events); - if (events.size() < (2 * kTrimEvents + kMinDataPoints)) { - LOG(ERROR) << "Not enough events of type " << event_name << " found (" - << events.size() << ") for latency analysis."; - return false; - } + GetTraceEvents(analyzer, event_name, &events); // Ignore some events for startup/setup/caching/teardown. trace_analyzer::TraceEventVector events_to_analyze( @@ -181,7 +161,7 @@ const double std_dev_us = sqrt(std::max(0.0, count * sqr_sum - sum * sum)) / count; perf_test::PrintResultMeanAndError( - test_name, GetSuffixForTestFlags(), event_name + "Latency", + kTestName, GetSuffixForTestFlags(), event_name + "Latency", base::StringPrintf("%f,%f", mean_us / 1000.0, std_dev_us / 1000.0), "ms", true); return true; @@ -190,15 +170,9 @@ // Analyze and print the mean and stddev of how often events having the name // |event_name| are missing the success=true flag. bool PrintFailRateResults(trace_analyzer::TraceAnalyzer* analyzer, - const std::string& test_name, const std::string& event_name) { trace_analyzer::TraceEventVector events; - FindEvents(analyzer, event_name, &events); - if (events.size() < (2 * kTrimEvents + kMinDataPoints)) { - LOG(ERROR) << "Not enough events of type " << event_name << " found (" - << events.size() << ") for fail rate analysis."; - return false; - } + GetTraceEvents(analyzer, event_name, &events); // Ignore some events for startup/setup/caching/teardown. trace_analyzer::TraceEventVector events_to_analyze( @@ -230,61 +204,69 @@ fail_percent *= fail_count / events_to_analyze.size(); } perf_test::PrintResult( - test_name, GetSuffixForTestFlags(), event_name + "FailRate", + kTestName, GetSuffixForTestFlags(), event_name + "FailRate", base::StringPrintf("%f", fail_percent), "percent", true); return true; } - void RunTest(const std::string& test_name) { - if (HasFlag(kUseGpu) && !IsGpuAvailable()) { - LOG(WARNING) << - "Test skipped: requires gpu. Pass --enable-gpu on the command " - "line if use of GPU is desired."; - return; - } + protected: + // The HTML test web page that draws animating balls continuously. Populated + // in SetUp(). + std::string test_page_html_; - std::string json_events; - ASSERT_TRUE(tracing::BeginTracing("gpu,gpu.capture")); - std::string page = "performance.html"; - page += HasFlag(kTestThroughWebRTC) ? "?WebRTC=1" : "?WebRTC=0"; - page += "&fps=60"; - ASSERT_TRUE(RunExtensionSubtest("tab_capture", page)) << message_; - ASSERT_TRUE(tracing::EndTracing(&json_events)); - std::unique_ptr<trace_analyzer::TraceAnalyzer> analyzer; - analyzer.reset(trace_analyzer::TraceAnalyzer::Create(json_events)); - analyzer->AssociateAsyncBeginEndEvents(); - - // The printed result will be the average time between composites in the - // renderer of the page being captured. This may not reach the full frame - // rate if the renderer cannot draw as fast as is desired. - // - // Note that any changes to drawing or compositing in the renderer, - // including changes to Blink (e.g., Canvas drawing), layout, etc.; will - // have an impact on this result. - EXPECT_TRUE( - PrintRateResults(analyzer.get(), test_name, - "RenderWidget::DidCommitAndDrawCompositorFrame")); - - // This prints out the average time between capture events in the browser - // process. This should roughly match the renderer's draw+composite rate. - EXPECT_TRUE(PrintRateResults(analyzer.get(), test_name, "Capture")); - - // Analyze mean/stddev of the capture latency. This is a measure of how long - // each capture took, from initiation until read-back from the GPU into a - // media::VideoFrame was complete. Lower is better. - EXPECT_TRUE(PrintLatencyResults(analyzer.get(), test_name, "Capture")); - - // Analyze percentage of failed captures. This measures how often captures - // were initiated, but not completed successfully. Lower is better, and zero - // is ideal. - EXPECT_TRUE(PrintFailRateResults(analyzer.get(), test_name, "Capture")); - } + // Naming of performance measurement written to stdout. + static const char kTestName[]; }; +// static +const char TabCapturePerformanceTest::kTestName[] = "TabCapturePerformance"; + } // namespace IN_PROC_BROWSER_TEST_P(TabCapturePerformanceTest, Performance) { - RunTest("TabCapturePerformance"); + // Load the extension and test page, and tell the extension to start tab + // capture. + LoadExtension(GetApiTestDataDir() + .AppendASCII("tab_capture") + .AppendASCII("perftest_extension")); + NavigateToTestPage(test_page_html_); + const base::Value response = SendMessageToExtension( + base::StringPrintf("{start:true, passThroughWebRTC:%s}", + HasFlag(kTestThroughWebRTC) ? "true" : "false")); + const std::string* reason = response.FindStringKey("reason"); + ASSERT_TRUE(response.FindBoolKey("success").value_or(false)) + << (reason ? *reason : std::string("<MISSING REASON>")); + + // Observe the running browser for a while, collecting a trace. + const std::string json_events = TraceAndObserve("gpu,gpu.capture"); + + std::unique_ptr<trace_analyzer::TraceAnalyzer> analyzer; + analyzer.reset(trace_analyzer::TraceAnalyzer::Create(json_events)); + analyzer->AssociateAsyncBeginEndEvents(); + + // The printed result will be the average time between composites in the + // renderer of the page being captured. This may not reach the full frame + // rate if the renderer cannot draw as fast as is desired. + // + // Note that any changes to drawing or compositing in the renderer, + // including changes to Blink (e.g., Canvas drawing), layout, etc.; will + // have an impact on this result. + EXPECT_TRUE(PrintRateResults( + analyzer.get(), "RenderWidget::DidCommitAndDrawCompositorFrame")); + + // This prints out the average time between capture events in the browser + // process. This should roughly match the renderer's draw+composite rate. + EXPECT_TRUE(PrintRateResults(analyzer.get(), "Capture")); + + // Analyze mean/stddev of the capture latency. This is a measure of how long + // each capture took, from initiation until read-back from the GPU into a + // media::VideoFrame was complete. Lower is better. + EXPECT_TRUE(PrintLatencyResults(analyzer.get(), "Capture")); + + // Analyze percentage of failed captures. This measures how often captures + // were initiated, but not completed successfully. Lower is better, and zero + // is ideal. + EXPECT_TRUE(PrintFailRateResults(analyzer.get(), "Capture")); } // Note: First argument is optional and intentionally left blank.
diff --git a/chrome/browser/extensions/content_capabilities_browsertest.cc b/chrome/browser/extensions/content_capabilities_browsertest.cc index 284be119..89d1b0e 100644 --- a/chrome/browser/extensions/content_capabilities_browsertest.cc +++ b/chrome/browser/extensions/content_capabilities_browsertest.cc
@@ -202,7 +202,9 @@ // script without a user gesture. EXPECT_TRUE( CanWriteClipboard(extension.get(), GetTestURLFor("bar.example.com"))); - if (!base::FeatureList::IsEnabled(features::kUserActivationV2)) { + if (!base::FeatureList::IsEnabled(features::kUserActivationV2) || + base::FeatureList::IsEnabled( + features::kUserActivationSameOriginVisibility)) { EXPECT_TRUE(CanWriteClipboardInAboutBlankFrame( extension.get(), GetTestURLFor("bar.example.com"))); } else {
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json index b4a8819..76cc8a94 100644 --- a/chrome/browser/flag-metadata.json +++ b/chrome/browser/flag-metadata.json
@@ -1150,7 +1150,7 @@ }, { "name": "enable-drive-fs", - // "owners": [ "your-team" ], + "owners": [ "sammc", "dats" ], "expiry_milestone": 76 }, { @@ -1189,6 +1189,11 @@ "expiry_milestone": 76 }, { + "name": "enable-experimental-accessibility-language-detection", + "owners": [ "chrishall", "//ui/accessibility/OWNERS" ], + "expiry_milestone": 76 + }, + { "name": "enable-experimental-accessibility-switch-access", "owners": [ "anastasi@google.com", "dmazzoni", "dtseng" ], "expiry_milestone": 76 @@ -1465,7 +1470,7 @@ }, { "name": "enable-myfiles-volume", - // "owners": [ "your-team" ], + "owners": [ "lucmult", "noel" ], "expiry_milestone": 76 }, {
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc index 6070d92f..86cbbb8b 100644 --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc
@@ -723,6 +723,12 @@ const char kExperimentalAccessibilityLabelsDescription[] = "Enable additional features for image labels for accessibility."; +const char kExperimentalAccessibilityLanguageDetectionName[] = + "Experimental accessibility language detection"; +const char kExperimentalAccessibilityLanguageDetectionDescription[] = + "Enable language detection for in-page content which is then exposed to " + "accessiblity technologies such as screen readers."; + const char kExperimentalAccessibilitySwitchAccessName[] = "Experimental feature Switch Access"; const char kExperimentalAccessibilitySwitchAccessDescription[] =
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h index 8275926e..da377e6 100644 --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h
@@ -176,6 +176,9 @@ extern const char kExperimentalAccessibilityLabelsName[]; extern const char kExperimentalAccessibilityLabelsDescription[]; +extern const char kExperimentalAccessibilityLanguageDetectionName[]; +extern const char kExperimentalAccessibilityLanguageDetectionDescription[]; + extern const char kExperimentalAccessibilitySwitchAccessName[]; extern const char kExperimentalAccessibilitySwitchAccessDescription[];
diff --git a/chrome/browser/previews/lazyload_browsertest.cc b/chrome/browser/previews/lazyload_browsertest.cc deleted file mode 100644 index 1de73ea..0000000 --- a/chrome/browser/previews/lazyload_browsertest.cc +++ /dev/null
@@ -1,71 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/run_loop.h" -#include "base/test/metrics/histogram_tester.h" -#include "base/test/scoped_feature_list.h" -#include "build/build_config.h" -#include "chrome/test/base/in_process_browser_test.h" -#include "chrome/test/base/ui_test_utils.h" -#include "components/data_use_measurement/core/data_use_user_data.h" -#include "content/public/common/content_features.h" -#include "content/public/test/browser_test_base.h" -#include "content/public/test/browser_test_utils.h" -#include "net/test/embedded_test_server/embedded_test_server.h" -#include "testing/gtest/include/gtest/gtest.h" - -class LazyLoadBrowserTest : public InProcessBrowserTest { - protected: - void SetUp() override { - scoped_feature_list_.InitAndEnableFeature(features::kLazyImageLoading); - InProcessBrowserTest::SetUp(); - } - base::test::ScopedFeatureList scoped_feature_list_; -}; - -IN_PROC_BROWSER_TEST_F(LazyLoadBrowserTest, CSSBackgroundImageDeferred) { - ASSERT_TRUE(embedded_test_server()->Start()); - base::HistogramTester histogram_tester; - ui_test_utils::NavigateToURL( - browser(), - embedded_test_server()->GetURL("/lazyload/css-background-image.html")); - - base::RunLoop().RunUntilIdle(); - // Navigate away to finish the histogram recording. - ui_test_utils::NavigateToURL(browser(), GURL(url::kAboutBlankURL)); - - // Verify that nothing is recorded for the image bucket. - EXPECT_GE(0, histogram_tester.GetBucketCount( - "DataUse.ContentType.UserTrafficKB", - data_use_measurement::DataUseUserData::IMAGE)); -} - -#if defined(OS_CHROMEOS) || defined(OS_WIN) -// Disable the tests flaky in Windows, chromeOS -#define MAYBE_CSSBackgroundImageLoadedWhenScrolled \ - DISABLED_CSSBackgroundImageLoadedWhenScrolled -#else -#define MAYBE_CSSBackgroundImageLoadedWhenScrolled \ - CSSBackgroundImageLoadedWhenScrolled -#endif - -IN_PROC_BROWSER_TEST_F(LazyLoadBrowserTest, - MAYBE_CSSBackgroundImageLoadedWhenScrolled) { - ASSERT_TRUE(embedded_test_server()->Start()); - base::HistogramTester histogram_tester; - - // Simulate scrolling by loading the anchor section where images are located. - ui_test_utils::NavigateToURL( - browser(), embedded_test_server()->GetURL( - "/lazyload/css-background-image.html#images")); - - base::RunLoop().RunUntilIdle(); - // Navigate away to finish the histogram recording. - ui_test_utils::NavigateToURL(browser(), GURL(url::kAboutBlankURL)); - - // Verify that the image bucket has substantial kilobytes recorded. - EXPECT_LE(35 /* kb */, histogram_tester.GetBucketCount( - "DataUse.ContentType.UserTrafficKB", - data_use_measurement::DataUseUserData::IMAGE)); -}
diff --git a/chrome/browser/resources/bookmarks/README.md b/chrome/browser/resources/bookmarks/README.md index 44f0f1e4..c6c83b16 100644 --- a/chrome/browser/resources/bookmarks/README.md +++ b/chrome/browser/resources/bookmarks/README.md
@@ -1,4 +1,4 @@ -# Material Design Bookmark Manager +# Bookmark Manager The bookmark manager (BMM) is a WebUI surface with a large amount of functionality for managing bookmarks across a relatively simple UI. This
diff --git a/chrome/browser/resources/bookmarks/types.js b/chrome/browser/resources/bookmarks/types.js index 66d7f9d..0983d50 100644 --- a/chrome/browser/resources/bookmarks/types.js +++ b/chrome/browser/resources/bookmarks/types.js
@@ -3,7 +3,7 @@ // found in the LICENSE file. /** - * @fileoverview Closure typedefs for MD Bookmarks. + * @fileoverview Closure typedefs for Bookmarks. */ /**
diff --git a/chrome/browser/resources/cast/cast.html b/chrome/browser/resources/cast/cast.html index e7afdd9..4510540e 100644 --- a/chrome/browser/resources/cast/cast.html +++ b/chrome/browser/resources/cast/cast.html
@@ -1,5 +1,5 @@ <!DOCTYPE HTML> -<html i18n-values="dir:textdirection;lang:language"> +<html dir="$i18n{textdirection}" lang="$i18n{language}"> <head> <meta charset="utf-8"> <title>Google Cast</title>
diff --git a/chrome/browser/resources/chromeos/account_manager_welcome.css b/chrome/browser/resources/chromeos/account_manager_welcome.css new file mode 100644 index 0000000..75086d7 --- /dev/null +++ b/chrome/browser/resources/chromeos/account_manager_welcome.css
@@ -0,0 +1,46 @@ +/* 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. */ + +body { + padding-inline-end: 4em; + padding-inline-start: 4em; +} + +h1 { + font-family: 'Google Sans', Helvetica, Roboto, sans-serif; + font-weight: normal; +} + +p { + font-family: 'Google Sans', Helvetica, Roboto, sans-serif; + white-space: pre-line; +} + +#google-logo { + height: 30px; + width: 30px; +} + +#welcome-image { + display: block; + margin-inline-end: auto; + margin-inline-start: auto; +} + +#ok-button-container { + position: relative; +} + +#ok-button { + background-color: var(--google-blue-600); + bottom: 0; + color: white; + position: absolute; + right: 0; +} + +html[dir='rtl'] #ok-button { + left: 0; + right: auto; +}
diff --git a/chrome/browser/resources/chromeos/account_manager_welcome.html b/chrome/browser/resources/chromeos/account_manager_welcome.html new file mode 100644 index 0000000..ef31103b --- /dev/null +++ b/chrome/browser/resources/chromeos/account_manager_welcome.html
@@ -0,0 +1,33 @@ +<!doctype html> +<html i18n-values="dir:textdirection;lang:language"> +<head> + <meta charset="utf-8"> + <link rel="import" href="chrome://resources/html/polymer.html"> + <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html"> + <link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/color.html"> + <link rel="import" href="chrome://resources/cr_elements/shared_style_css.html"> + + <link rel="stylesheet" href="account_manager_welcome.css"> + <link rel="stylesheet" href="chrome://resources/css/text_defaults_md.css"> + + <script src="chrome://resources/js/cr.js"></script> + <script src="chrome://resources/js/load_time_data.js"></script> + <script src="chrome://resources/js/util.js"></script> + <script src="strings.js"></script> + <script src="account_manager_welcome.js"></script> +</head> +<body i18n-values=".style.fontFamily:fontfamily;.style.fontSize:fontsize"> + <img id="google-logo" src="googleg.svg"> + <h1 i18n-content="welcomeTitle"></h1> + <p i18n-content="welcomeMessage"></p> + <img id="welcome-image" + srcset="account_manager_welcome_1x.png 1x, + account_manager_welcome_2x.png 2x"> + + <div id="ok-button-container"> + <paper-button raised id="ok-button" i18n-content="okButton"></paper-button> + </div> + + <script src="chrome://resources/js/i18n_template.js"></script> +</body> +</html>
diff --git a/chrome/browser/resources/chromeos/account_manager_welcome.js b/chrome/browser/resources/chromeos/account_manager_welcome.js new file mode 100644 index 0000000..4168a1f --- /dev/null +++ b/chrome/browser/resources/chromeos/account_manager_welcome.js
@@ -0,0 +1,23 @@ +// 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. + +cr.define('account_manager_welcome', function() { + 'use strict'; + + function initialize() { + $('ok-button').addEventListener('click', closeDialog); + } + + function closeDialog() { + chrome.send('closeDialog'); + } + + return { + initialize: initialize, + closeDialog: closeDialog, + }; +}); + +document.addEventListener( + 'DOMContentLoaded', account_manager_welcome.initialize);
diff --git a/chrome/browser/resources/chromeos/account_manager_welcome_1x.png b/chrome/browser/resources/chromeos/account_manager_welcome_1x.png new file mode 100644 index 0000000..1dda30db --- /dev/null +++ b/chrome/browser/resources/chromeos/account_manager_welcome_1x.png Binary files differ
diff --git a/chrome/browser/resources/chromeos/account_manager_welcome_2x.png b/chrome/browser/resources/chromeos/account_manager_welcome_2x.png new file mode 100644 index 0000000..edbacc93 --- /dev/null +++ b/chrome/browser/resources/chromeos/account_manager_welcome_2x.png Binary files differ
diff --git a/chrome/browser/resources/chromeos/chromevox/cvox2/background/desktop_automation_handler.js b/chrome/browser/resources/chromeos/chromevox/cvox2/background/desktop_automation_handler.js index 125d457..dcf68f9 100644 --- a/chrome/browser/resources/chromeos/chromevox/cvox2/background/desktop_automation_handler.js +++ b/chrome/browser/resources/chromeos/chromevox/cvox2/background/desktop_automation_handler.js
@@ -72,7 +72,6 @@ this.addListener_(EventType.BLUR, this.onBlur); this.addListener_( EventType.CHECKED_STATE_CHANGED, this.onCheckedStateChanged); - this.addListener_(EventType.CHILDREN_CHANGED, this.onChildrenChanged); this.addListener_( EventType.DOCUMENT_SELECTION_CHANGED, this.onDocumentSelectionChanged); this.addListener_(EventType.EXPANDED_CHANGED, this.onEventIfInRange); @@ -188,14 +187,17 @@ if (prev.contentEquals(cursors.Range.fromNode(evt.target)) || evt.target.state.focused) { var prevTarget = this.lastAttributeTarget_; - this.lastAttributeTarget_ = evt.target; - var prevOutput = this.lastAttributeOutput_; - this.lastAttributeOutput_ = new Output().withRichSpeechAndBraille( - cursors.Range.fromNode(evt.target), prev, Output.EventType.NAVIGATE); - if (evt.target == prevTarget && prevOutput && - prevOutput.equals(this.lastAttributeOutput_)) + // Re-target to active descendant if it exists. + var prevOutput = this.lastAttributeOutput_; + this.lastAttributeTarget_ = evt.target.activeDescendant || evt.target; + this.lastAttributeOutput_ = new Output().withRichSpeechAndBraille( + cursors.Range.fromNode(this.lastAttributeTarget_), prev, + Output.EventType.NAVIGATE); + if (this.lastAttributeTarget_ == prevTarget && prevOutput && + prevOutput.equals(this.lastAttributeOutput_)) { return; + } // If the target or an ancestor is controlled by another control, we may // want to delay the output. @@ -230,8 +232,11 @@ onAriaAttributeChanged: function(evt) { if (evt.target.state.editable) return; - // Only report attribute changes on menu list items if it is selected. - if (evt.target.role == RoleType.MENU_LIST_OPTION && !evt.target.selected) + + // Only report attribute changes on some *Option roles if it is selected. + if ((evt.target.role == RoleType.MENU_LIST_OPTION || + evt.target.role == RoleType.LIST_BOX_OPTION) && + !evt.target.selected) return; this.onEventIfInRange(evt); @@ -318,12 +323,11 @@ onActiveDescendantChanged: function(evt) { if (!evt.target.activeDescendant || !evt.target.state.focused) return; - var prevRange = ChromeVoxState.instance.currentRange; - var range = cursors.Range.fromNode(evt.target.activeDescendant); - ChromeVoxState.instance.setCurrentRange(range); - new Output() - .withRichSpeechAndBraille(range, prevRange, Output.EventType.NAVIGATE) - .go(); + + // Various events might come before a key press (which forces flushed + // speech) and this handler. Force output to be at least category flushed. + Output.forceModeForNextSpeechUtterance(cvox.QueueMode.CATEGORY_FLUSH); + this.onEventIfInRange(evt); }, /** @@ -364,27 +368,6 @@ /** * @param {!AutomationEvent} evt */ - onChildrenChanged: function(evt) { - var curRange = ChromeVoxState.instance.currentRange; - - // views::TextField blinks by making its cursor view alternate between - // visible and not visible. This results in a children changed event on its - // parent (the text field itself). In general, text field feedback should be - // given within text field specific events. - if (evt.target.role == RoleType.TEXT_FIELD) - return; - - // Always refresh the braille contents. - if (curRange && curRange.equals(cursors.Range.fromNode(evt.target))) { - new Output() - .withBraille(curRange, curRange, Output.EventType.NAVIGATE) - .go(); - } - }, - - /** - * @param {!AutomationEvent} evt - */ onDocumentSelectionChanged: function(evt) { var anchor = evt.target.anchorObject;
diff --git a/chrome/browser/resources/chromeos/googleg.svg b/chrome/browser/resources/chromeos/googleg.svg new file mode 100644 index 0000000..6a5a473 --- /dev/null +++ b/chrome/browser/resources/chromeos/googleg.svg
@@ -0,0 +1,7 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 104 104" width="104" height="104"> + <path fill="#4285F4" d="M101.93 53.18c0-3.89-.38-7.61-1.04-11.18H52v19.98h28.08c-1.09 6.77-4.79 12.55-10.48 16.38v13.09h16.86c9.82-9.06 15.47-22.44 15.47-38.27z"/> + <path fill="#34A853" d="M52 104c14.03 0 25.85-4.61 34.46-12.55L69.6 78.36c-4.64 3.12-10.61 4.96-17.6 4.96-13.53 0-25.01-9.13-29.11-21.43H5.54v13.46C14.1 92.34 31.68 104 52 104z"/> + <path fill="#FBBC05" d="M22.89 61.89c-1.04-3.12-1.61-6.45-1.61-9.89 0-3.44.57-6.76 1.61-9.89V28.65H5.54C2 35.67 0 43.6 0 52s2 16.33 5.54 23.35l17.35-13.46z"/> + <path fill="#EA4335" d="M52 20.68c7.64 0 14.49 2.63 19.89 7.77l14.9-14.9C77.78 5.15 66.03 0 52 0 31.68 0 14.1 11.66 5.54 28.65l17.35 13.46c4.1-12.3 15.58-21.43 29.11-21.43z"/> + <path fill="none" d="M0 0h104v104H0z"/> +</svg>
diff --git a/chrome/browser/resources/component_extension_resources.grd b/chrome/browser/resources/component_extension_resources.grd index 03694db..67606ba 100644 --- a/chrome/browser/resources/component_extension_resources.grd +++ b/chrome/browser/resources/component_extension_resources.grd
@@ -30,8 +30,8 @@ <include name="IDR_BRAILLE_IME_MAIN_JS" file="chromeos/braille_ime/main.js" type="BINDATA" /> </if> - <!-- Material Design Bookmarks --> - <include name="IDR_COMPONENT_MD_BOOKMARKS_BOOKMARKS_HTML" file="bookmarks/bookmarks.html" type="BINDATA" /> + <!-- Bookmarks --> + <include name="IDR_COMPONENT_BOOKMARKS_BOOKMARKS_HTML" file="bookmarks/bookmarks.html" type="BINDATA" /> <!-- Gaia auth extension --> <include name="IDR_GAIA_AUTH_SUCCESS" file="gaia_auth/success.html" allowexternalscript="true" type="BINDATA" /> <!-- Hangout Services extension, included in Google Chrome builds only. -->
diff --git a/chrome/browser/resources/local_ntp/constants.css b/chrome/browser/resources/local_ntp/constants.css new file mode 100644 index 0000000..72e81b87 --- /dev/null +++ b/chrome/browser/resources/local_ntp/constants.css
@@ -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. */ + +html { + /* Material Design colors. Keep in sync with ui/gfx/color_palette.h. */ + + --dark-mode-bg-rgb: 50, 54, 57; + + /* Google Grey */ + --GG050-rgb: 248, 249, 250; + --GG100-rgb: 241, 243, 244; + --GG200-rgb: 232, 234, 237; + --GG300-rgb: 218, 220, 224; + --GG400-rgb: 189, 193, 198; + --GG500-rgb: 154, 160, 166; + --GG600-rgb: 128, 134, 139; + --GG700-rgb: 95, 99, 104; + --GG800-rgb: 60, 64, 67; + --GG900-rgb: 32, 33, 36; + + /* Google Blue */ + --GB050-rgb: 232, 240, 254; + --GB100-rgb: 210, 227, 252; + --GB200-rgb: 174, 203, 250; + --GB300-rgb: 138, 180, 248; + --GB400-rgb: 102, 157, 246; + --GB500-rgb: 66, 133, 244; + --GB600-rgb: 26, 115, 232; + --GB700-rgb: 25, 103, 210; + --GB800-rgb: 24, 90, 188; + --GB900-rgb: 23, 78, 166; + --GB400-dark-rgb: 107, 165, 237; + --GB600-dark-rgb: 37, 129, 223; + + /* Google Red */ + --GR050-rgb: 252, 142, 230; + --GR100-rgb: 250, 210, 207; + --GR200-rgb: 246, 174, 169; + --GR300-rgb: 242, 139, 130; + --GR400-rgb: 238, 103, 92; + --GR500-rgb: 234, 67, 53; + --GR600-rgb: 217, 48, 37; + --GR700-rgb: 197, 34, 31; + --GR800-rgb: 179, 20, 18; + --GR900-rgb: 165, 14, 14; + --GR500-dark-rgb: 230, 106, 94; + --GR600-dark-rgb: 211, 59, 48; + --GR800-dark-rgb: 180, 27, 26; +}
diff --git a/chrome/browser/resources/local_ntp/custom_backgrounds.css b/chrome/browser/resources/local_ntp/custom_backgrounds.css index 89527d1..80da01e 100644 --- a/chrome/browser/resources/local_ntp/custom_backgrounds.css +++ b/chrome/browser/resources/local_ntp/custom_backgrounds.css
@@ -32,11 +32,11 @@ } #edit-bg:hover { - background-color: rgba(32, 33, 36, .1); + background-color: rgba(var(--GG900-rgb), .1); } #edit-bg:active { - background-color: rgba(32, 33, 36, .16); + background-color: rgba(var(--GG900-rgb), .16); } .non-white-bg #edit-bg:hover { @@ -74,7 +74,8 @@ border-radius: 8px; border-width: thin; bottom: 44px; - box-shadow: 0 1px 3px 0 rgba(60, 64, 67, 0.3), 0 4px 8px 3px rgba(60, 64, 67, 0.15); + box-shadow: 0 1px 3px 0 rgba(var(--GG800-rgb), 0.3), + 0 4px 8px 3px rgba(var(--GG800-rgb), 0.15); left: auto; padding: 0; position: fixed; @@ -92,7 +93,7 @@ } #edit-bg-title { - color: rgb(32, 33, 36); + color: rgb(var(--GG900-rgb)); font-family: 'Roboto', arial, sans-serif; font-size: 15px; height: 30px; @@ -104,7 +105,7 @@ } .bg-option { - color: rgb(60, 64, 67); + color: rgb(var(--GG800-rgb)); font-family: 'Roboto', arial, sans-serif; font-size: 13px; height: 40px; @@ -112,7 +113,7 @@ } .bg-option:hover { - background-color: rgb(241, 243, 244); + background-color: rgb(var(--GG100-rgb)); } .bg-option-img { @@ -151,23 +152,23 @@ } #edit-bg-upload-image .bg-option-img { - background: rgb(241, 243, 244) url(icons/upload.svg) no-repeat center; + background: rgb(var(--GG100-rgb)) url(icons/upload.svg) no-repeat center; border-radius: 50%; } #edit-bg-divider { - border-bottom: 1px solid rgb(232, 234, 237); + border-bottom: 1px solid rgb(var(--GG200-rgb)); margin: 8px 0; width: 100%; } #custom-links-restore-default .bg-option-img { - background: rgb(241, 243, 244) url(icons/link_gray.svg) no-repeat center; + background: rgb(var(--GG100-rgb)) url(icons/link_gray.svg) no-repeat center; border-radius: 50%; } #edit-bg-restore-default .bg-option-img { - background: rgb(241, 243, 244) url(icons/chrome.svg) no-repeat center; + background: rgb(var(--GG100-rgb)) url(icons/chrome.svg) no-repeat center; border-radius: 50%; } @@ -199,7 +200,8 @@ border: none; border-radius: 8px; bottom: 0; - box-shadow: 0 1px 3px 0 rgba(60, 64, 67, 0.3), 0 4px 8px 3px rgba(60, 64, 67, 0.15); + box-shadow: 0 1px 3px 0 rgba(var(--GG800-rgb), 0.3), + 0 4px 8px 3px rgba(var(--GG800-rgb), 0.15); font-family: 'Roboto', arial, sans-serif; height: 400px; left: 0; @@ -247,7 +249,7 @@ } #bg-sel-title-bar { - border-bottom: 1px solid rgb(232, 234, 237); + border-bottom: 1px solid rgb(var(--GG200-rgb)); font-size: 15px; height: 51px; line-height: 52px; @@ -275,7 +277,7 @@ #bg-sel-back-circle:active, #bg-sel-back-circle:focus { - background: rgb(218, 220, 224); + background: rgb(var(--GG300-rgb)); background-position: center; background-size: 36px 36px; } @@ -315,7 +317,7 @@ } #bg-sel-title { - color: rgb(32, 33, 36); + color: rgb(var(--GG900-rgb)); display: inline-block; height: 20px; line-height: 20px; @@ -340,9 +342,9 @@ } #bg-sel-footer { - border-top: 1px solid rgba(232, 234, 237, 1); + border-top: 1px solid rgb(var(--GG200-rgb)); bottom: 0; - color: rgb(60, 64, 67); + color: rgb(var(--GG800-rgb)); height: 64px; padding-left: 0; position: absolute; @@ -379,8 +381,8 @@ } #bg-sel-footer-done { - background-color: rgb(241, 243, 244); - color: rgb(128, 134, 139); + background-color: rgb(var(--GG100-rgb)); + color: rgb(var(--GG600-rgb)); margin-right: 16px; } @@ -391,8 +393,8 @@ #bg-sel-footer-cancel { background-color: white; - border: 1px solid rgb(218, 220, 224); - color: rgb(26, 115, 232); + border: 1px solid rgb(var(--GG300-rgb)); + color: rgb(var(--GB600-rgb)); margin-right: 8px; } @@ -401,31 +403,31 @@ } #bg-sel-footer-cancel:hover { - background-color: rgba(66, 133, 244, 0.04); - border-color: rgb(210, 227, 252); + background-color: rgba(var(--GB500-rgb), 0.04); + border-color: rgb(var(--GB100-rgb)); } #bg-sel-footer-cancel:active { background-color: white; border-color: white; - box-shadow: 0 1px 2px 0 rgba(60, 64, 67, 0.3), - 0 3px 6px 2px rgba(60, 64, 67, 0.15); + box-shadow: 0 1px 2px 0 rgba(var(--GG800-rgb), 0.3), + 0 3px 6px 2px rgba(var(--GG800-rgb), 0.15); } #bg-sel-footer-done:not(:disabled) { - background-color: rgb(26, 115, 232); + background-color: rgb(var(--GB600-rgb)); color: white; } #bg-sel-footer-done:hover:not(:disabled) { background-color: rgb(41, 123, 231); - box-shadow: 0 1px 2px 0 rgba(66, 133, 244, 0.3), - 0 1px 3px 1px rgba(66, 133, 244, 0.15); + box-shadow: 0 1px 2px 0 rgba(var(--GB500-rgb), 0.3), + 0 1px 3px 1px rgba(var(--GB500-rgb), 0.15); } #bg-sel-footer-done:active:not(:disabled) { - box-shadow: 0 1px 2px 0 rgba(66, 133, 244, 0.3), - 0 3px 6px 2px rgba(66, 133, 244, 0.15); + box-shadow: 0 1px 2px 0 rgba(var(--GB500-rgb), 0.3), + 0 3px 6px 2px rgba(var(--GB500-rgb), 0.15); } #bg-sel-footer-toggle-text { @@ -445,7 +447,7 @@ } .bg-sel-tile-bg { - background-color: rgb(241, 243, 244); + background-color: rgb(var(--GG100-rgb)); background-size: cover; display: inline-block; height: 117px; @@ -483,7 +485,7 @@ } .selected-border { - border: 2px solid rgba(26, 115, 232, .4); + border: 2px solid rgba(var(--GB600-rgb), .4); border-radius: 4px; box-sizing: border-box; height: 100%; @@ -522,7 +524,7 @@ } .bg-sel-tile-title { - background-color: rgba(32, 33, 36, 0.71); + background-color: rgba(var(--GG900-rgb), 0.71); bottom: 0; box-sizing: border-box; color: #FFF; @@ -613,7 +615,7 @@ } #custom-bg-attr.attr-link:hover { - background: rgba(32, 33, 36, .1); + background: rgba(var(--GG900-rgb), .1); } .attr1.attr-link,
diff --git a/chrome/browser/resources/local_ntp/custom_links_edit.css b/chrome/browser/resources/local_ntp/custom_links_edit.css index cb87556..a32dcea 100644 --- a/chrome/browser/resources/local_ntp/custom_links_edit.css +++ b/chrome/browser/resources/local_ntp/custom_links_edit.css
@@ -15,8 +15,8 @@ border: none; border-radius: 8px; bottom: 0; - box-shadow: - 0 1px 3px 0 rgba(60, 64, 67, 0.3), 0 4px 8px 3px rgba(60, 64, 67, 0.15); + box-shadow: 0 1px 3px 0 rgba(var(--GG800-rgb), 0.3), + 0 4px 8px 3px rgba(var(--GG800-rgb), 0.15); font-family: 'Roboto', arial, sans-serif; margin: auto; min-width: 320px; @@ -34,7 +34,7 @@ } #dialog-title { - color: rgb(32, 33, 36); + color: rgb(var(--GG900-rgb)); font-family: 'Roboto', arial, sans-serif; font-size: 15px; line-height: 24px; @@ -46,7 +46,7 @@ } .field-title { - color: rgb(95, 99, 104); + color: rgb(var(--GG700-rgb)); font-size: 10px; font-weight: 500; margin-bottom: 4px; @@ -57,11 +57,11 @@ } input { - background-color: rgb(241, 243, 244); + background-color: rgb(var(--GG100-rgb)); border: none; border-radius: 4px; - caret-color: rgb(26, 115, 232); - color: rgb(32, 33, 36); + caret-color: rgb(var(--GB600-rgb)); + color: rgb(var(--GG900-rgb)); font-family: 'Roboto', arial, sans-serif; font-size: 13px; height: 32px; @@ -77,11 +77,11 @@ } input::placeholder { - color: rgba(32, 33, 36, 0.38); + color: rgba(var(--GG900-rgb), 0.38); } .underline { - border-bottom: 2px solid rgb(26, 115, 232); + border-bottom: 2px solid rgb(var(--GB600-rgb)); bottom: 0; box-sizing: border-box; left: 0; @@ -100,11 +100,11 @@ } .field-title.focused { - color: rgb(26, 115, 232); + color: rgb(var(--GB600-rgb)); } .error-msg { - color: rgb(217, 48, 37); + color: rgb(var(--GR600-rgb)); display: none; font-size: 10px; font-weight: 400; @@ -112,7 +112,7 @@ } .invalid label { - color: rgb(217, 48, 37); + color: rgb(var(--GR600-rgb)); } .invalid .error-msg { @@ -120,7 +120,7 @@ } .invalid .underline { - border-color: rgb(217, 48, 37); + border-color: rgb(var(--GR600-rgb)); opacity: 1; transition: width 180ms ease-out, opacity 120ms ease-in; width: 100%; @@ -159,47 +159,47 @@ } button.primary { - background-color: rgb(26, 115, 232); + background-color: rgb(var(--GB600-rgb)); color: white; } button.primary:disabled { - background-color: rgb(241, 243, 244); - color: rgb(128, 134, 139); + background-color: rgb(var(--GG100-rgb)); + color: rgb(var(--GG600-rgb)); } button.primary:hover:not(:disabled) { background-color: rgb(41, 123, 231); - box-shadow: 0 1px 2px 0 rgba(66, 133, 244, 0.3), - 0 1px 3px 1px rgba(66, 133, 244, 0.15); + box-shadow: 0 1px 2px 0 rgba(var(--GB500-rgb), 0.3), + 0 1px 3px 1px rgba(var(--GB500-rgb), 0.15); } button.primary:active:not(:disabled) { - box-shadow: 0 1px 2px 0 rgba(66, 133, 244, 0.3), - 0 3px 6px 2px rgba(66, 133, 244, 0.15); + box-shadow: 0 1px 2px 0 rgba(var(--GB500-rgb), 0.3), + 0 3px 6px 2px rgba(var(--GB500-rgb), 0.15); } button.secondary { background-color: white; - border: 1px solid rgb(218, 220, 224); - color: rgb(26, 115, 232); + border: 1px solid rgb(var(--GG300-rgb)); + color: rgb(var(--GB600-rgb)); } button.secondary:disabled { - border-color: rgb(241, 243, 244); - color: rgb(128, 134, 139); + border-color: rgb(var(--GG100-rgb)); + color: rgb(var(--GG600-rgb)); } button.secondary:hover:not(:disabled) { - background-color: rgba(66, 133, 244, 0.04); - border-color: rgb(210, 227, 252); + background-color: rgba(var(--GB500-rgb), 0.04); + border-color: rgb(var(--GB100-rgb)); } button.secondary:active:not(:disabled) { background-color: white; border-color: white; - box-shadow: 0 1px 2px 0 rgba(60, 64, 67, 0.3), - 0 3px 6px 2px rgba(60, 64, 67, 0.15); + box-shadow: 0 1px 2px 0 rgba(var(--GG800-rgb), 0.3), + 0 3px 6px 2px rgba(var(--GG800-rgb), 0.15); } html:not([dir=rtl]) #cancel {
diff --git a/chrome/browser/resources/local_ntp/custom_links_edit.html b/chrome/browser/resources/local_ntp/custom_links_edit.html index e2b6a3ac..bba8c4d 100644 --- a/chrome/browser/resources/local_ntp/custom_links_edit.html +++ b/chrome/browser/resources/local_ntp/custom_links_edit.html
@@ -7,6 +7,7 @@ <base target="_top"> <meta charset="utf-8"> <link rel="stylesheet" type="text/css" href="animations.css"> + <link rel="stylesheet" type="text/css" href="constants.css"> <link rel="stylesheet" type="text/css" href="edit.css"> <script src="utils.js"></script> <script src="animations.js"></script>
diff --git a/chrome/browser/resources/local_ntp/local_ntp.css b/chrome/browser/resources/local_ntp/local_ntp.css index 242f282..9ef38758 100644 --- a/chrome/browser/resources/local_ntp/local_ntp.css +++ b/chrome/browser/resources/local_ntp/local_ntp.css
@@ -123,7 +123,7 @@ } #fakebox { - background-color: rgb(241, 243, 244); + background-color: rgb(var(--GG100-rgb)); border-radius: 22px; cursor: text; font-size: 18px; @@ -138,7 +138,7 @@ } #fakebox:hover { - background-color: rgb(232, 234, 237); + background-color: rgb(var(--GG200-rgb)); } .non-google-page #fakebox-container { @@ -165,7 +165,7 @@ #fakebox-text { bottom: 4px; - color: rgb(128, 134, 139); + color: rgb(var(--GG600-rgb)); font-family: 'Roboto', arial, sans-serif; font-size: 14px; left: 0; @@ -290,7 +290,7 @@ -webkit-mask-position: 3px 3px; -webkit-mask-repeat: no-repeat; -webkit-mask-size: 10px 10px; - background-color: rgba(90,90,90,0.7); + background-color: rgba(90, 90, 90, 0.7); cursor: pointer; display: inline-block; filter: var(--theme-filter, 'none'); @@ -307,11 +307,11 @@ } #mv-notice-x:hover { - background-color: rgba(90,90,90,1.0); + background-color: rgba(90, 90, 90, 1.0); } #mv-notice-x:active { - background-color: rgb(66,133,244); + background-color: rgb(var(--GB500-rgb)); } .md-icons #mv-notice-x { @@ -359,7 +359,7 @@ .md-icons #mv-notice { background-color: white; - border: 1px solid rgb(218, 220, 224); + border: 1px solid rgb(var(--GG300-rgb)); /* Necessary for a "pill" shape. Using 50% creates an oval. */ border-radius: 16px; font-family: 'Roboto', arial, sans-serif; @@ -379,7 +379,7 @@ } .md-icons #mv-notice span { - color: rgb(95,99,104); + color: rgb(var(--GG700-rgb)); height: auto; line-height: 32px; vertical-align: unset; @@ -397,7 +397,7 @@ .md-icons #mv-notice-links span { /* Necessary for a "pill" shape. Using 50% creates an oval. */ border-radius: 16px; - color: rgb(26, 115, 232); + color: rgb(var(--GB600-rgb)); margin-inline-start: 0; padding: 0 16px; position: relative; @@ -410,7 +410,7 @@ .md-icons #mv-notice-links span:hover, .md-icons #mv-notice-links span:active { - background-color: rgba(26,115,232, 0.1); + background-color: rgba(var(--GB600-rgb), 0.1); text-decoration: none; transition: background-color 200ms; } @@ -556,7 +556,7 @@ } input:checked + .toggle { - background-color: rgba(26, 115, 232, .5); + background-color: rgba(var(--GB600-rgb), .5); box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.4); } @@ -566,7 +566,7 @@ input:checked + .toggle::before { -webkit-transform: translateX(26px); - background-color: rgb(26, 115, 232); + background-color: rgb(var(--GB600-rgb)); transform: translateX(26px); } @@ -585,10 +585,10 @@ #error-notice { background-color: white; - border: 1px solid rgb(218, 220, 224); + border: 1px solid rgb(var(--GG300-rgb)); /* Necessary for a "pill" shape. Using 50% creates an oval. */ border-radius: 16px; - color: rgb(217, 48, 37); + color: rgb(var(--GR600-rgb)); display: flex; font-family: 'Roboto', arial, sans-serif; font-size: 12px; @@ -640,7 +640,7 @@ #error-notice-link { /* Necessary for a "pill" shape. Using 50% creates an oval. */ border-radius: 16px; - color: rgb(26, 115, 232); + color: rgb(var(--GB600-rgb)); cursor: pointer; display: none; outline: none; @@ -659,7 +659,7 @@ #error-notice-link:hover, #error-notice-link:active { - background-color: rgba(26,115,232, 0.1); + background-color: rgba(var(--GB600-rgb), 0.1); text-decoration: none; transition: background-color 200ms; } @@ -680,10 +680,10 @@ #promo > div { background-color: #FFF; - border: 1px solid rgb(218, 220, 224); + border: 1px solid rgb(var(--GG300-rgb)); border-radius: 16px; box-sizing: border-box; - color: rgb(95, 99, 104); + color: rgb(var(--GG700-rgb)); display: inline-block; font-family: 'Roboto', arial, sans-serif; font-size: 12px;
diff --git a/chrome/browser/resources/local_ntp/local_ntp.html b/chrome/browser/resources/local_ntp/local_ntp.html index 92d45cf..073e394 100644 --- a/chrome/browser/resources/local_ntp/local_ntp.html +++ b/chrome/browser/resources/local_ntp/local_ntp.html
@@ -5,6 +5,7 @@ found in the LICENSE file. --> <head> <link rel="stylesheet" href="chrome-search://local-ntp/animations.css"></link> + <link rel="stylesheet" href="chrome-search://local-ntp/constants.css"></link> <link rel="stylesheet" href="chrome-search://local-ntp/custom-backgrounds.css"></link> <link rel="stylesheet" href="chrome-search://local-ntp/doodles.css"></link> <link rel="stylesheet" href="chrome-search://local-ntp/local-ntp.css"></link>
diff --git a/chrome/browser/resources/local_ntp/most_visited_single.css b/chrome/browser/resources/local_ntp/most_visited_single.css index dfb0df76..a224468 100644 --- a/chrome/browser/resources/local_ntp/most_visited_single.css +++ b/chrome/browser/resources/local_ntp/most_visited_single.css
@@ -24,19 +24,6 @@ --md-title-height: 24px; --md-title-max-height: 28px; - /* Material Design colors */ - --dark-mode-bg-rgb: 50, 54, 57; - --GG900-rgb: 32, 33, 36; - --GG800-rgb: 60, 64, 67; - --GG700-rgb: 95, 99, 104; - --GG600-rgb: 128, 134, 139; - --GG500-rgb: 154, 160, 166; - --GG400-rgb: 189, 193, 198; - --GG300-rgb: 218, 220, 224; - --GG200-rgb: 232, 234, 237; - --GG100-rgb: 241, 243, 244; - --GG50-rgb: 248, 249, 250; - /* May be overridden by themes (on the body element). */ --tile-title-color: #323232; } @@ -255,7 +242,7 @@ /* Apply when a custom background is set. */ body.dark-theme .md-tile-container:not(.reorder) .md-title { - color: rgb(var(--GG50-rgb)); + color: rgb(var(--GG050-rgb)); filter: drop-shadow(0 0 6px rgba(0, 0, 0, 0.35)); }
diff --git a/chrome/browser/resources/local_ntp/most_visited_single.html b/chrome/browser/resources/local_ntp/most_visited_single.html index 4d8b174b..92bf1458 100644 --- a/chrome/browser/resources/local_ntp/most_visited_single.html +++ b/chrome/browser/resources/local_ntp/most_visited_single.html
@@ -6,6 +6,7 @@ <head> <base target="_top"> <meta charset="utf-8"> + <link rel="stylesheet" type="text/css" href="constants.css"> <link rel="stylesheet" type="text/css" href="single.css"> <script src="utils.js"></script> <script src="single.js"></script>
diff --git a/chrome/browser/resources/local_ntp_resources.grd b/chrome/browser/resources/local_ntp_resources.grd index 3eae537..a7828b51 100644 --- a/chrome/browser/resources/local_ntp_resources.grd +++ b/chrome/browser/resources/local_ntp_resources.grd
@@ -15,6 +15,7 @@ <include name="IDR_CUSTOM_LINKS_EDIT_CSS" file="local_ntp\custom_links_edit.css" type="BINDATA" /> <include name="IDR_CUSTOM_LINKS_EDIT_JS" file="local_ntp\custom_links_edit.js" type="BINDATA" /> <include name="IDR_CUSTOM_LINKS_EDIT_MENU_SVG" file="local_ntp\icons\edit_menu.svg" type="BINDATA" /> + <include name="IDR_LOCAL_NTP_CONSTANTS_CSS" file="local_ntp\constants.css" type="BINDATA" /> <include name="IDR_LOCAL_NTP_ANIMATIONS_CSS" file="local_ntp\animations.css" flattenhtml="true" type="BINDATA" /> <include name="IDR_LOCAL_NTP_ANIMATIONS_JS" file="local_ntp\animations.js" flattenhtml="true" type="BINDATA" /> <include name="IDR_LOCAL_NTP_CSS" file="local_ntp\local_ntp.css" flattenhtml="true" type="BINDATA" />
diff --git a/chrome/browser/resources/omnibox/omnibox.html b/chrome/browser/resources/omnibox/omnibox.html index c604afdb..60b35f52 100644 --- a/chrome/browser/resources/omnibox/omnibox.html +++ b/chrome/browser/resources/omnibox/omnibox.html
@@ -149,6 +149,14 @@ </span> </label> </div> + <div class="row"> + <label class="checkbox-container"> + <input id="elide-cells" type="checkbox" accesskey="s"> + <span> + Elide Cell<span class="accesskey">s</span> + </span> + </label> + </div> </div> <div class="top-column">
diff --git a/chrome/browser/resources/omnibox/omnibox_input.js b/chrome/browser/resources/omnibox/omnibox_input.js index 72b1063..0c82596 100644 --- a/chrome/browser/resources/omnibox/omnibox_input.js +++ b/chrome/browser/resources/omnibox/omnibox_input.js
@@ -22,6 +22,7 @@ * showIncompleteResults: boolean, * showDetails: boolean, * showAllProviders: boolean, + * elideCells: boolean, * }} */ let DisplayInputs; @@ -66,6 +67,7 @@ ['#show-incomplete-results', '#show-details', '#show-all-providers', + '#elide-cells', ] .forEach( query => this.$$(query).addEventListener( @@ -207,6 +209,7 @@ showIncompleteResults: this.$$('#show-incomplete-results').checked, showDetails: this.$$('#show-details').checked, showAllProviders: this.$$('#show-all-providers').checked, + elideCells: this.$$('#elide-cells').checked, }; } @@ -216,6 +219,7 @@ displayInputs.showIncompleteResults; this.$$('#show-details').checked = displayInputs.showDetails; this.$$('#show-all-providers').checked = displayInputs.showAllProviders; + this.$$('#elide-cells').checked = displayInputs.elideCells; } /** @private */ @@ -279,6 +283,7 @@ showIncompleteResults: false, showDetails: false, showAllProviders: true, + elideCells: true, }; } }
diff --git a/chrome/browser/resources/omnibox/omnibox_output.js b/chrome/browser/resources/omnibox/omnibox_output.js index ed4dbef..9dacef75 100644 --- a/chrome/browser/resources/omnibox/omnibox_output.js +++ b/chrome/browser/resources/omnibox/omnibox_output.js
@@ -48,6 +48,7 @@ updateDisplayInputs(displayInputs) { this.displayInputs_ = displayInputs; this.updateVisibility_(); + this.updateEliding_(); } /** @param {string} filterText */ @@ -146,6 +147,13 @@ } /** @private */ + updateEliding_() { + this.resultsGroups_.forEach( + resultsGroup => + resultsGroup.updateEliding(this.displayInputs_.elideCells)); + } + + /** @private */ updateFilterHighlights_() { this.autocompleteMatches.forEach(match => match.filter(this.filterText_)); } @@ -299,6 +307,12 @@ match => match.updateVisibility(showDetails)); } + /** @param {boolean} elideCells */ + updateEliding(elideCells) { + this.autocompleteMatches.forEach( + match => match.updateEliding(elideCells)); + } + /** * @private * @return {boolean} @@ -457,6 +471,12 @@ }); } + /** @param {boolean} elideCells */ + updateEliding(elideCells) { + Object.values(this.properties) + .forEach(property => property.classList.toggle('elided', elideCells)); + } + /** @param {string} filterText */ filter(filterText) { this.classList.remove('filtered-highlighted');
diff --git a/chrome/browser/resources/omnibox/output_results_group.css b/chrome/browser/resources/omnibox/output_results_group.css index 275aab3c..ebc1f06 100644 --- a/chrome/browser/resources/omnibox/output_results_group.css +++ b/chrome/browser/resources/omnibox/output_results_group.css
@@ -52,7 +52,7 @@ overflow: hidden; } -.body td:not(:hover) { +.body td.elided:not(:hover) { white-space: nowrap; }
diff --git a/chrome/browser/resources/predictors/predictors.html b/chrome/browser/resources/predictors/predictors.html index 34b7a0e..731baa20 100644 --- a/chrome/browser/resources/predictors/predictors.html +++ b/chrome/browser/resources/predictors/predictors.html
@@ -1,5 +1,5 @@ <!doctype html> -<html i18n-values="dir:textdirection;lang:language"> +<html dir="$i18n{textdirection}" lang="$i18n{language}"> <head> <meta charset="utf-8"> <title>Predictors</title>
diff --git a/chrome/browser/resources/set_as_default_browser.html b/chrome/browser/resources/set_as_default_browser.html index 92865ee5..8f65526 100644 --- a/chrome/browser/resources/set_as_default_browser.html +++ b/chrome/browser/resources/set_as_default_browser.html
@@ -2,15 +2,13 @@ <!-- Copyright (c) 2012 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. --> -<html i18n-values="dir:textdirection;lang:language"> +<html dir="$i18n{textdirection}" lang="$i18n{language}"> <head> <meta charset="utf-8"> -<title i18n-content="page-title"></title> +<title>$i18n{pageTitle}</title> <script src="chrome://resources/js/cr.js"></script> -<script src="chrome://resources/js/load_time_data.js"></script> <script src="chrome://resources/js/util.js"></script> <script src="chrome://resources/js/cr/event_target.js"></script> -<script src="strings.js"></script> <script src="set_as_default_browser.js"></script> <link rel="stylesheet" href="chrome://resources/css/chrome_shared.css"> <link rel="stylesheet" href="chrome://resources/css/widgets.css"> @@ -21,21 +19,21 @@ <div id="metro-setup-overlay" class="page"> <div> <div class="content-area"> - <h1 i18n-content="flowTitle"></h1> - <h2 i18n-content="flowDescription"></h2> + <h1>$i18n{flowTitle}</h1> + <h2>$i18n{flowDescription}</h2> </div> <div id="metro-action-box" class="content-area"> <div class="button-strip"> - <button id="launch-button" class="custom-appearance" - i18n-content="flowNext"></button> + <button id="launch-button" class="custom-appearance"> + $i18n{flowNext} + </button> </div> </div> </div> </div> <div id="chrome-logo-box"> - <img src="chrome-logo-faded.png" i18n-values="alt:chromeLogoString"> + <img src="chrome-logo-faded.png" alt="$i18n{chromeLogoString}"> </div> </div> </body> -<script src="chrome://resources/js/i18n_template.js"></script> </html>
diff --git a/chrome/browser/resources/settings/autofill_page/autofill_section.js b/chrome/browser/resources/settings/autofill_page/autofill_section.js index 25bd705..b4d4d46 100644 --- a/chrome/browser/resources/settings/autofill_page/autofill_section.js +++ b/chrome/browser/resources/settings/autofill_page/autofill_section.js
@@ -141,6 +141,9 @@ // Listen for changes. this.autofillManager_.addAddressListChangedListener(setAddressesListener); + + // Record that the user opened the address settings. + chrome.metricsPrivate.recordUserAction('AutofillAddressesViewed'); }, /** @override */
diff --git a/chrome/browser/resources/settings/autofill_page/payments_section.js b/chrome/browser/resources/settings/autofill_page/payments_section.js index 1ac858d..495f065 100644 --- a/chrome/browser/resources/settings/autofill_page/payments_section.js +++ b/chrome/browser/resources/settings/autofill_page/payments_section.js
@@ -265,6 +265,9 @@ this.handleSyncStatus_.bind(this)); this.addWebUIListener( 'sync-status-changed', this.handleSyncStatus_.bind(this)); + + // Record that the user opened the payments settings. + chrome.metricsPrivate.recordUserAction('AutofillCreditCardsViewed'); }, /** @override */
diff --git a/chrome/browser/resources/settings/multidevice_page/multidevice_constants.js b/chrome/browser/resources/settings/multidevice_page/multidevice_constants.js index ee6377c0..f60c837 100644 --- a/chrome/browser/resources/settings/multidevice_page/multidevice_constants.js +++ b/chrome/browser/resources/settings/multidevice_page/multidevice_constants.js
@@ -76,6 +76,7 @@ * instantTetheringState: !settings.MultiDeviceFeatureState, * messagesState: !settings.MultiDeviceFeatureState, * smartLockState: !settings.MultiDeviceFeatureState, + * isAndroidSmsPairingComplete: boolean * }} */ let MultiDevicePageContentData;
diff --git a/chrome/browser/resources/settings/multidevice_page/multidevice_subpage.html b/chrome/browser/resources/settings/multidevice_page/multidevice_subpage.html index 9880744..f93b7cd9 100644 --- a/chrome/browser/resources/settings/multidevice_page/multidevice_subpage.html +++ b/chrome/browser/resources/settings/multidevice_page/multidevice_subpage.html
@@ -85,9 +85,10 @@ feature="[[MultiDeviceFeature.MESSAGES]]" page-content-data="[[pageContentData]]"> <template is="dom-if" - if="[[doesAndroidMessagesRequireSetup_(pageContentData)]]" + if="[[doesAndroidMessagesRequireSetUp_(pageContentData)]]" restamp> - <paper-button on-click="handleAndroidMessagesButtonClick_" + <paper-button disabled$="[[!isSuiteOn(pageContentData)]]" + on-click="handleAndroidMessagesButtonClick_" slot="feature-controller"> $i18n{multideviceSetupButton} </paper-button>
diff --git a/chrome/browser/resources/settings/multidevice_page/multidevice_subpage.js b/chrome/browser/resources/settings/multidevice_page/multidevice_subpage.js index 9579bd23..990c459 100644 --- a/chrome/browser/resources/settings/multidevice_page/multidevice_subpage.js +++ b/chrome/browser/resources/settings/multidevice_page/multidevice_subpage.js
@@ -128,8 +128,10 @@ * @return {boolean} * @private */ - doesAndroidMessagesRequireSetup_: function() { - return this.getFeatureState(settings.MultiDeviceFeature.MESSAGES) == - settings.MultiDeviceFeatureState.FURTHER_SETUP_REQUIRED; + doesAndroidMessagesRequireSetUp_: function() { + // The pairing state is preferred over the FeatureState here since + // FeatureState.UNAVAILABLE_SUITE_DISABLED is returned when the suite is + // disabled, regardless if Messages requires further setup. + return !this.pageContentData.isAndroidSmsPairingComplete; }, });
diff --git a/chrome/browser/resources/signin/signin_error/signin_error.html b/chrome/browser/resources/signin/signin_error/signin_error.html index 37a5c21..b540038 100644 --- a/chrome/browser/resources/signin/signin_error/signin_error.html +++ b/chrome/browser/resources/signin/signin_error/signin_error.html
@@ -1,5 +1,5 @@ <!doctype html> -<html i18n-values="dir:textdirection;lang:language" dir="$i18n{textdirection}"> +<html dir="$i18n{textdirection}" lang="$i18n{language}"> <head> <meta charset="utf-8"> <link rel="import" href="chrome://resources/cr_elements/paper_button_style_css.html">
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/set_as_default/nux_set_as_default.js b/chrome/browser/resources/welcome/onboarding_welcome/set_as_default/nux_set_as_default.js index da6586a0..bb8aa03 100644 --- a/chrome/browser/resources/welcome/onboarding_welcome/set_as_default/nux_set_as_default.js +++ b/chrome/browser/resources/welcome/onboarding_welcome/set_as_default/nux_set_as_default.js
@@ -87,7 +87,15 @@ if (status.isDefault) { this.browserProxy_.recordSuccessfullySetDefault(); this.finished_(); + return; } + + // <if expr="is_macosx"> + // On Mac OS, we do not get a notification when the default browser changes. + // This will fake the notification. + window.setTimeout( + () => this.browserProxy_.requestDefaultBrowserState(), 100); + // </if> }, /** @private */
diff --git a/chrome/browser/search/local_ntp_source.cc b/chrome/browser/search/local_ntp_source.cc index 366724d..7bdfab4 100644 --- a/chrome/browser/search/local_ntp_source.cc +++ b/chrome/browser/search/local_ntp_source.cc
@@ -111,6 +111,7 @@ } kResources[] = { {"animations.css", IDR_LOCAL_NTP_ANIMATIONS_CSS, "text/css"}, {"animations.js", IDR_LOCAL_NTP_ANIMATIONS_JS, "application/javascript"}, + {"constants.css", IDR_LOCAL_NTP_CONSTANTS_CSS, "text/css"}, {"custom-backgrounds.css", IDR_LOCAL_NTP_CUSTOM_BACKGROUNDS_CSS, "text/css"}, {"custom-backgrounds.js", IDR_LOCAL_NTP_CUSTOM_BACKGROUNDS_JS,
diff --git a/chrome/browser/search/most_visited_iframe_source.cc b/chrome/browser/search/most_visited_iframe_source.cc index e5d47db..eda19c26 100644 --- a/chrome/browser/search/most_visited_iframe_source.cc +++ b/chrome/browser/search/most_visited_iframe_source.cc
@@ -39,6 +39,7 @@ // Used in the single-iframe version and the edit custom links dialog iframe. const char kAnimationsCSSPath[] = "/animations.css"; const char kAnimationsJSPath[] = "/animations.js"; +const char kConstantsCSSPath[] = "/constants.css"; const char kLocalNTPUtilsJSPath[] = "/utils.js"; } // namespace @@ -104,6 +105,8 @@ SendResource(IDR_CUSTOM_LINKS_ADD_WHITE_SVG, callback); } else if (path == kEditMenuSvgPath) { SendResource(IDR_CUSTOM_LINKS_EDIT_MENU_SVG, callback); + } else if (path == kConstantsCSSPath) { + SendResource(IDR_LOCAL_NTP_CONSTANTS_CSS, callback); } else if (path == kAnimationsCSSPath) { SendResource(IDR_LOCAL_NTP_ANIMATIONS_CSS, callback); } else if (path == kAnimationsJSPath) { @@ -122,6 +125,6 @@ path == kCommonCSSPath || path == kEditHTMLPath || path == kEditCSSPath || path == kEditJSPath || path == kAddSvgPath || path == kAddWhiteSvgPath || path == kEditMenuSvgPath || - path == kAnimationsCSSPath || path == kAnimationsJSPath || - path == kLocalNTPUtilsJSPath; + path == kConstantsCSSPath || path == kAnimationsCSSPath || + path == kAnimationsJSPath || path == kLocalNTPUtilsJSPath; }
diff --git a/chrome/browser/signin/dice_browsertest.cc b/chrome/browser/signin/dice_browsertest.cc index 9bd1ef1..18d9da54 100644 --- a/chrome/browser/signin/dice_browsertest.cc +++ b/chrome/browser/signin/dice_browsertest.cc
@@ -451,10 +451,10 @@ GetIdentityManager()->AddObserver(this); // Wait for the token service to be ready. - if (!identity::AreAllCredentialsLoaded(GetIdentityManager())) { + if (!GetIdentityManager()->AreRefreshTokensLoaded()) { WaitForClosure(&tokens_loaded_quit_closure_); } - ASSERT_TRUE(identity::AreAllCredentialsLoaded(GetIdentityManager())); + ASSERT_TRUE(GetIdentityManager()->AreRefreshTokensLoaded()); AccountReconcilor* reconcilor = AccountReconcilorFactory::GetForProfile(browser()->profile());
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index 48f33a86..1a8c448 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn
@@ -1082,6 +1082,10 @@ "webui/app_management/app_management_shelf_delegate_chromeos.h", "webui/app_management/app_management_ui.cc", "webui/app_management/app_management_ui.h", + "webui/bookmarks/bookmarks_message_handler.cc", + "webui/bookmarks/bookmarks_message_handler.h", + "webui/bookmarks/bookmarks_ui.cc", + "webui/bookmarks/bookmarks_ui.h", "webui/browsing_history_handler.cc", "webui/browsing_history_handler.h", "webui/chrome_web_contents_handler.cc", @@ -1113,10 +1117,6 @@ "webui/management_ui.h", "webui/management_ui_handler.cc", "webui/management_ui_handler.h", - "webui/bookmarks/bookmarks_message_handler.cc", - "webui/bookmarks/bookmarks_message_handler.h", - "webui/bookmarks/bookmarks_ui.cc", - "webui/bookmarks/bookmarks_ui.h", "webui/md_downloads/downloads_list_tracker.cc", "webui/md_downloads/downloads_list_tracker.h", "webui/md_downloads/md_downloads_dom_handler.cc", @@ -1508,6 +1508,10 @@ "views/touch_selection_menu_chromeos.h", "views/touch_selection_menu_runner_chromeos.cc", "views/touch_selection_menu_runner_chromeos.h", + "webui/chromeos/account_manager_welcome_dialog.cc", + "webui/chromeos/account_manager_welcome_dialog.h", + "webui/chromeos/account_manager_welcome_ui.cc", + "webui/chromeos/account_manager_welcome_ui.h", "webui/chromeos/assistant_optin/assistant_optin_ui.cc", "webui/chromeos/assistant_optin/assistant_optin_ui.h", "webui/chromeos/assistant_optin/assistant_optin_utils.cc",
diff --git a/chrome/browser/ui/tabs/tab_menu_model.cc b/chrome/browser/ui/tabs/tab_menu_model.cc index f6fe2d9..150a1fe 100644 --- a/chrome/browser/ui/tabs/tab_menu_model.cc +++ b/chrome/browser/ui/tabs/tab_menu_model.cc
@@ -43,6 +43,14 @@ IDS_TAB_CXMENU_ADD_TAB_TO_EXISTING_GROUP, add_to_existing_group_submenu_.get()); } + + for (size_t index = 0; index < affected_indices.size(); index++) { + if (tab_strip->GetTabGroupForTab(affected_indices[index]) != nullptr) { + AddItemWithStringId(TabStripModel::CommandRemoveFromGroup, + IDS_TAB_CXMENU_REMOVE_TAB_FROM_GROUP); + break; + } + } } AddSeparator(ui::NORMAL_SEPARATOR); AddItemWithStringId(TabStripModel::CommandReload, IDS_TAB_CXMENU_RELOAD);
diff --git a/chrome/browser/ui/tabs/tab_strip_model.cc b/chrome/browser/ui/tabs/tab_strip_model.cc index c6d6d4f..f37427b 100644 --- a/chrome/browser/ui/tabs/tab_strip_model.cc +++ b/chrome/browser/ui/tabs/tab_strip_model.cc
@@ -1044,6 +1044,25 @@ return new_indices; } +void TabStripModel::RemoveFromGroup(const std::vector<int>& indices) { + // Remove each tab from the group it's in, if any. Go from right to left + // since tabs may move to the right when ungrouped. + for (int i = indices.size() - 1; i >= 0; i--) { + const TabGroupData* group = GetTabGroupForTab(indices[i]); + if (group == nullptr) + continue; + // Move the tab until it's the rightmost tab in its group + int stepsToMove = 0; + while (ContainsIndex(indices[i] + stepsToMove + 1) && + GetTabGroupForTab(indices[i] + stepsToMove + 1) == group) { + stepsToMove++; + } + MoveWebContentsAt(indices[i], indices[i] + stepsToMove, false); + + contents_data_[indices[i] + stepsToMove]->set_group(nullptr); + } +} + // Context menu functions. bool TabStripModel::IsContextMenuCommandEnabled( int context_index, @@ -1110,6 +1129,9 @@ case CommandAddToExistingGroup: return true; + case CommandRemoveFromGroup: + return true; + default: NOTREACHED(); } @@ -1265,6 +1287,13 @@ break; } + case CommandRemoveFromGroup: { + base::RecordAction(UserMetricsAction("TabContextMenu_RemoveFromGroup")); + std::vector<int> indices = GetIndicesForCommand(context_index); + RemoveFromGroup(indices); + break; + } + default: NOTREACHED(); }
diff --git a/chrome/browser/ui/tabs/tab_strip_model.h b/chrome/browser/ui/tabs/tab_strip_model.h index f4e8b20..3626719b 100644 --- a/chrome/browser/ui/tabs/tab_strip_model.h +++ b/chrome/browser/ui/tabs/tab_strip_model.h
@@ -345,17 +345,25 @@ // Create a new tab group and add the set of tabs pointed to be |indices| to // it. Pins all of the tabs if any of them were pinned, and reorders the tabs - // so they are contiguous and do not split an existing group in half. This - // feature is in development and gated behind a feature flag. - // https://crbug.com/915956. + // so they are contiguous and do not split an existing group in half. + // |indices| must be sorted in ascending order. This feature is in development + // and gated behind a feature flag. https://crbug.com/915956. void AddToNewGroup(const std::vector<int>& indices); // Add the set of tabs pointed to by |indices| to the tab group |group|. The // tabs take on the pinnedness of the tabs already in the group, and are moved - // to immediately follow the tabs already in the group. + // to immediately follow the tabs already in the group. |indices| must be + // sorted in ascending order. This feature is in development and gated behind + // a feature flag. https://crbug.com/915956. void AddToExistingGroup(const std::vector<int>& indices, const TabGroupData* group); + // Removes the set of tabs pointed to by |indices| from the the groups they + // are in, if any. The tabs are moved out of the group if necessary. |indices| + // must be sorted in ascending order. This feature is in development and gated + // behind a feature flag. https://crbug.com/915956. + void RemoveFromGroup(const std::vector<int>& indices); + // View API ////////////////////////////////////////////////////////////////// // Context menu functions. Tab groups uses command ids following CommandLast @@ -376,6 +384,7 @@ CommandBookmarkAllTabs, CommandAddToNewGroup, CommandAddToExistingGroup, + CommandRemoveFromGroup, CommandLast };
diff --git a/chrome/browser/ui/tabs/tab_strip_model_unittest.cc b/chrome/browser/ui/tabs/tab_strip_model_unittest.cc index e6f725a..0b43d7e 100644 --- a/chrome/browser/ui/tabs/tab_strip_model_unittest.cc +++ b/chrome/browser/ui/tabs/tab_strip_model_unittest.cc
@@ -2927,3 +2927,107 @@ strip.ActivateTabAt(0, true); strip.CloseAllTabs(); } + +TEST_F(TabStripModelTest, RemoveTabFromGroupNoopForUngroupedTab) { + TabStripDummyDelegate delegate; + TabStripModel strip(&delegate, profile()); + strip.AppendWebContents(CreateWebContents(), false); + + strip.RemoveFromGroup({0}); + + strip.ActivateTabAt(0, true); + strip.CloseAllTabs(); +} + +TEST_F(TabStripModelTest, RemoveTabFromGroup) { + TabStripDummyDelegate delegate; + TabStripModel strip(&delegate, profile()); + strip.AppendWebContents(CreateWebContents(), false); + strip.AddToNewGroup({0}); + + strip.RemoveFromGroup({0}); + + EXPECT_EQ(strip.GetTabGroupForTab(0), nullptr); + + strip.ActivateTabAt(0, true); + strip.CloseAllTabs(); +} + +TEST_F(TabStripModelTest, RemoveTabFromGroupReorders) { + TabStripDummyDelegate delegate; + TabStripModel strip(&delegate, profile()); + strip.AppendWebContents(CreateWebContents(), false); + strip.AppendWebContents(CreateWebContents(), false); + std::vector<WebContents*> orig{strip.GetWebContentsAt(0), + strip.GetWebContentsAt(1)}; + strip.AddToNewGroup({0, 1}); + + strip.RemoveFromGroup({0}); + + EXPECT_EQ(strip.GetTabGroupForTab(1), nullptr); + EXPECT_NE(strip.GetTabGroupForTab(0), nullptr); + EXPECT_EQ(strip.GetWebContentsAt(0), orig[1]); + EXPECT_EQ(strip.GetWebContentsAt(1), orig[0]); + + strip.ActivateTabAt(0, true); + strip.CloseAllTabs(); +} + +TEST_F(TabStripModelTest, RemoveTabFromGroupMaintainsOrderOfSelectedTabs) { + TabStripDummyDelegate delegate; + TabStripModel strip(&delegate, profile()); + strip.AppendWebContents(CreateWebContents(), false); + strip.AppendWebContents(CreateWebContents(), false); + strip.AppendWebContents(CreateWebContents(), false); + strip.AppendWebContents(CreateWebContents(), false); + std::vector<WebContents*> orig{ + strip.GetWebContentsAt(0), strip.GetWebContentsAt(1), + strip.GetWebContentsAt(2), strip.GetWebContentsAt(3)}; + strip.AddToNewGroup({0, 1, 2, 3}); + + strip.RemoveFromGroup({0, 2}); + + EXPECT_NE(strip.GetTabGroupForTab(0), nullptr); + EXPECT_NE(strip.GetTabGroupForTab(1), nullptr); + EXPECT_EQ(strip.GetTabGroupForTab(2), nullptr); + EXPECT_EQ(strip.GetTabGroupForTab(3), nullptr); + EXPECT_EQ(strip.GetWebContentsAt(0), orig[1]); + EXPECT_EQ(strip.GetWebContentsAt(1), orig[3]); + EXPECT_EQ(strip.GetWebContentsAt(2), orig[0]); + EXPECT_EQ(strip.GetWebContentsAt(3), orig[2]); + + strip.ActivateTabAt(0, true); + strip.CloseAllTabs(); +} + +TEST_F(TabStripModelTest, RemoveTabFromGroupMixtureOfGroups) { + TabStripDummyDelegate delegate; + TabStripModel strip(&delegate, profile()); + strip.AppendWebContents(CreateWebContents(), false); + strip.AppendWebContents(CreateWebContents(), false); + strip.AppendWebContents(CreateWebContents(), false); + strip.AppendWebContents(CreateWebContents(), false); + strip.AppendWebContents(CreateWebContents(), false); + std::vector<WebContents*> orig{ + strip.GetWebContentsAt(0), strip.GetWebContentsAt(1), + strip.GetWebContentsAt(2), strip.GetWebContentsAt(3), + strip.GetWebContentsAt(4)}; + strip.AddToNewGroup({0, 1}); + strip.AddToNewGroup({2, 3}); + + strip.RemoveFromGroup({0, 3, 4}); + + EXPECT_NE(strip.GetTabGroupForTab(0), nullptr); + EXPECT_EQ(strip.GetTabGroupForTab(1), nullptr); + EXPECT_NE(strip.GetTabGroupForTab(2), nullptr); + EXPECT_EQ(strip.GetTabGroupForTab(3), nullptr); + EXPECT_EQ(strip.GetTabGroupForTab(4), nullptr); + EXPECT_EQ(strip.GetWebContentsAt(0), orig[1]); + EXPECT_EQ(strip.GetWebContentsAt(1), orig[0]); + EXPECT_EQ(strip.GetWebContentsAt(2), orig[2]); + EXPECT_EQ(strip.GetWebContentsAt(3), orig[3]); + EXPECT_EQ(strip.GetWebContentsAt(4), orig[4]); + + strip.ActivateTabAt(0, true); + strip.CloseAllTabs(); +}
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_drag_drop_views.cc b/chrome/browser/ui/views/bookmarks/bookmark_drag_drop_views.cc index 00e3a5c..655e819 100644 --- a/chrome/browser/ui/views/bookmarks/bookmark_drag_drop_views.cc +++ b/chrome/browser/ui/views/bookmarks/bookmark_drag_drop_views.cc
@@ -48,7 +48,7 @@ // Generates a bookmark drag and drop chip image. class BookmarkDragImageSource : public gfx::CanvasImageSource { public: - // These DIP measurements come from the MD Bookmarks Drag Drop spec. + // These DIP measurements come from the Bookmarks Drag Drop spec. static constexpr int kContainerWidth = 172; static constexpr int kContainerHeight = 40; static constexpr int kContainerRadius = kContainerHeight / 2;
diff --git a/chrome/browser/ui/views/location_bar/icon_label_bubble_view.cc b/chrome/browser/ui/views/location_bar/icon_label_bubble_view.cc index 7c3dadb..5862e9f 100644 --- a/chrome/browser/ui/views/location_bar/icon_label_bubble_view.cc +++ b/chrome/browser/ui/views/location_bar/icon_label_bubble_view.cc
@@ -66,10 +66,9 @@ } void IconLabelBubbleView::SeparatorView::OnPaint(gfx::Canvas* canvas) { - const SkColor plain_text_color = owner_->GetNativeTheme()->GetSystemColor( - ui::NativeTheme::kColorId_TextfieldDefaultColor); + const SkColor background_color = owner_->GetParentBackgroundColor(); const SkColor separator_color = - SkColorSetA(color_utils::GetColorWithMaxContrast(plain_text_color), 0x66); + SkColorSetA(color_utils::GetColorWithMaxContrast(background_color), 0x69); const float x = GetLocalBounds().right() - owner_->GetEndPaddingWithSeparator() - 1.0f / canvas->image_scale(); @@ -181,6 +180,11 @@ label_->SetFontList(font_list); } +SkColor IconLabelBubbleView::GetParentBackgroundColor() const { + return GetNativeTheme()->GetSystemColor( + ui::NativeTheme::kColorId_TextfieldDefaultBackground); +} + bool IconLabelBubbleView::ShouldShowSeparator() const { return ShouldShowLabel(); } @@ -405,11 +409,6 @@ PreferredSizeChanged(); } -SkColor IconLabelBubbleView::GetParentBackgroundColor() const { - return GetNativeTheme()->GetSystemColor( - ui::NativeTheme::kColorId_TextfieldDefaultBackground); -} - gfx::Size IconLabelBubbleView::GetSizeForLabelWidth(int label_width) const { gfx::Size size(image_->GetPreferredSize()); size.Enlarge(GetInsets().left() + GetWidthBetweenIconAndSeparator() +
diff --git a/chrome/browser/ui/views/location_bar/icon_label_bubble_view.h b/chrome/browser/ui/views/location_bar/icon_label_bubble_view.h index 95e2681..84982c1 100644 --- a/chrome/browser/ui/views/location_bar/icon_label_bubble_view.h +++ b/chrome/browser/ui/views/location_bar/icon_label_bubble_view.h
@@ -82,6 +82,9 @@ const views::ImageView* GetImageView() const { return image_; } views::ImageView* GetImageView() { return image_; } + // Returns the color of the IconLabelBubbleView's surrounding context. + SkColor GetParentBackgroundColor() const; + // Exposed for testing. SeparatorView* separator_view() const { return separator_view_; } @@ -155,8 +158,6 @@ const gfx::FontList& font_list() const { return label_->font_list(); } - SkColor GetParentBackgroundColor() const; - gfx::Size GetSizeForLabelWidth(int label_width) const; // Set up for icons that animate their labels in and then out.
diff --git a/chrome/browser/ui/views/omnibox/omnibox_view_views.cc b/chrome/browser/ui/views/omnibox/omnibox_view_views.cc index 8ab5193..8fb246e5 100644 --- a/chrome/browser/ui/views/omnibox/omnibox_view_views.cc +++ b/chrome/browser/ui/views/omnibox/omnibox_view_views.cc
@@ -54,6 +54,8 @@ #include "ui/base/models/simple_menu_model.h" #include "ui/compositor/layer.h" #include "ui/events/event.h" +#include "ui/gfx/animation/animation_delegate.h" +#include "ui/gfx/animation/multi_animation.h" #include "ui/gfx/canvas.h" #include "ui/gfx/font_list.h" #include "ui/gfx/geometry/insets.h" @@ -121,6 +123,52 @@ } // namespace +// Animation chosen to match the default values in the edwardjung prototype. +class OmniboxViewViews::PathFadeAnimation : public gfx::AnimationDelegate { + public: + PathFadeAnimation(OmniboxViewViews* view, SkColor starting_color) + : view_(view), + starting_color_(starting_color), + animation_( + { + gfx::MultiAnimation::Part(4000, gfx::Tween::ZERO), + gfx::MultiAnimation::Part(300, gfx::Tween::FAST_OUT_SLOW_IN), + }, + gfx::MultiAnimation::GetDefaultTimerInterval()) { + DCHECK(view_); + + animation_.set_delegate(this); + animation_.set_continuous(false); + } + + // Starts the animation over |path_bounds|. The caller is responsible for + // calling Stop() if the text changes and |path_bounds| is no longer valid. + void Start(const gfx::Range& path_bounds) { + path_bounds_ = path_bounds; + animation_.Start(); + } + + void Stop() { animation_.Stop(); } + + // gfx::AnimationDelegate: + void AnimationProgressed(const gfx::Animation* animation) override { + DCHECK(!view_->model()->user_input_in_progress()); + + SkColor color = gfx::Tween::ColorValueBetween( + animation->GetCurrentValue(), starting_color_, SK_ColorTRANSPARENT); + view_->ApplyColor(color, path_bounds_); + } + + private: + // Non-owning pointer. |view_| must always outlive this class. + OmniboxViewViews* view_; + SkColor starting_color_; + + // The path text range we are fading. + gfx::Range path_bounds_; + + gfx::MultiAnimation animation_; +}; // OmniboxViewViews ----------------------------------------------------------- @@ -147,6 +195,15 @@ scoped_template_url_service_observer_(this) { set_id(VIEW_ID_OMNIBOX); SetFontList(font_list); + + if (base::FeatureList::IsEnabled( + omnibox::kHideSteadyStateUrlPathQueryAndRef)) { + // The animation only applies when the path is dimmed to begin with. + SkColor starting_color = + location_bar_view_->GetColor(OmniboxPart::LOCATION_BAR_TEXT_DIMMED); + path_fade_animation_ = + std::make_unique<PathFadeAnimation>(this, starting_color); + } } OmniboxViewViews::~OmniboxViewViews() { @@ -259,14 +316,35 @@ if (!location_bar_view_) return; + // Cancel any existing path fading animation. The path style will be reset + // in the following lines, so there should be no ill effects from cancelling + // the animation midway. + if (path_fade_animation_) + path_fade_animation_->Stop(); + // If the current contents is a URL, turn on special URL rendering mode in // RenderText. bool text_is_url = model()->CurrentTextIsURL(); GetRenderText()->SetDirectionalityMode( text_is_url ? gfx::DIRECTIONALITY_AS_URL : gfx::DIRECTIONALITY_FROM_TEXT); SetStyle(gfx::STRIKE, false); - UpdateTextStyle(text(), text_is_url, - model()->client()->GetSchemeClassifier()); + + base::string16 text = GetText(); + bool path_eligible_for_fading = UpdateTextStyle( + text, text_is_url, model()->client()->GetSchemeClassifier()); + + // Only fade the path when everything but the host is de-emphasized. + if (path_fade_animation_ && path_eligible_for_fading && !HasFocus() && + !model()->user_input_in_progress()) { + url::Component scheme, host; + AutocompleteInput::ParseForEmphasizeComponents( + text, model()->client()->GetSchemeClassifier(), &scheme, &host); + gfx::Range path_bounds(host.end(), text.size()); + + // Whenever the text changes, EmphasizeURLComponents is called again, and + // the animation is reset with a new |path_bounds|. + path_fade_animation_->Start(path_bounds); + } } void OmniboxViewViews::Update() {
diff --git a/chrome/browser/ui/views/omnibox/omnibox_view_views.h b/chrome/browser/ui/views/omnibox/omnibox_view_views.h index f690819..0890b887 100644 --- a/chrome/browser/ui/views/omnibox/omnibox_view_views.h +++ b/chrome/browser/ui/views/omnibox/omnibox_view_views.h
@@ -138,6 +138,8 @@ FRIEND_TEST_ALL_PREFIXES(OmniboxViewViewsTest, FriendlyAccessibleLabel); FRIEND_TEST_ALL_PREFIXES(OmniboxViewViewsTest, DoNotNavigateOnDrop); + class PathFadeAnimation; + enum class UnelisionGesture { HOME_KEY_PRESSED, MOUSE_RELEASE, @@ -283,6 +285,9 @@ std::unique_ptr<OmniboxPopupContentsView> popup_view_; + // Animation used to fade out the path under some elision settings. + std::unique_ptr<PathFadeAnimation> path_fade_animation_; + security_state::SecurityLevel security_level_; // Selection persisted across temporary text changes, like popup suggestions.
diff --git a/chrome/browser/ui/webui/bookmarks/bookmarks_browsertest.cc b/chrome/browser/ui/webui/bookmarks/bookmarks_browsertest.cc index 0da10a7..a2d09e1 100644 --- a/chrome/browser/ui/webui/bookmarks/bookmarks_browsertest.cc +++ b/chrome/browser/ui/webui/bookmarks/bookmarks_browsertest.cc
@@ -11,35 +11,34 @@ #include "components/bookmarks/common/bookmark_pref_names.h" #include "components/prefs/pref_service.h" -MdBookmarksBrowserTest::MdBookmarksBrowserTest() {} +BookmarksBrowserTest::BookmarksBrowserTest() {} -MdBookmarksBrowserTest::~MdBookmarksBrowserTest() {} +BookmarksBrowserTest::~BookmarksBrowserTest() {} -void MdBookmarksBrowserTest::RegisterMessages() { +void BookmarksBrowserTest::RegisterMessages() { web_ui()->RegisterMessageCallback( "testSetIncognito", - base::BindRepeating( - &MdBookmarksBrowserTest::HandleSetIncognitoAvailability, - base::Unretained(this))); + base::BindRepeating(&BookmarksBrowserTest::HandleSetIncognitoAvailability, + base::Unretained(this))); web_ui()->RegisterMessageCallback( "testSetCanEdit", - base::BindRepeating(&MdBookmarksBrowserTest::HandleSetCanEditBookmarks, + base::BindRepeating(&BookmarksBrowserTest::HandleSetCanEditBookmarks, base::Unretained(this))); } -void MdBookmarksBrowserTest::SetIncognitoAvailability(int availability) { +void BookmarksBrowserTest::SetIncognitoAvailability(int availability) { ASSERT_TRUE(availability >= 0 && availability < IncognitoModePrefs::AVAILABILITY_NUM_TYPES); browser()->profile()->GetPrefs()->SetInteger( prefs::kIncognitoModeAvailability, availability); } -void MdBookmarksBrowserTest::SetCanEditBookmarks(bool canEdit) { +void BookmarksBrowserTest::SetCanEditBookmarks(bool canEdit) { browser()->profile()->GetPrefs()->SetBoolean( bookmarks::prefs::kEditBookmarksEnabled, canEdit); } -void MdBookmarksBrowserTest::HandleSetIncognitoAvailability( +void BookmarksBrowserTest::HandleSetIncognitoAvailability( const base::ListValue* args) { AllowJavascript(); @@ -54,7 +53,7 @@ ResolveJavascriptCallback(*callback_id, base::Value()); } -void MdBookmarksBrowserTest::HandleSetCanEditBookmarks( +void BookmarksBrowserTest::HandleSetCanEditBookmarks( const base::ListValue* args) { AllowJavascript(); @@ -69,6 +68,6 @@ ResolveJavascriptCallback(*callback_id, base::Value()); } -content::WebUIMessageHandler* MdBookmarksBrowserTest::GetMockMessageHandler() { +content::WebUIMessageHandler* BookmarksBrowserTest::GetMockMessageHandler() { return this; }
diff --git a/chrome/browser/ui/webui/bookmarks/bookmarks_browsertest.h b/chrome/browser/ui/webui/bookmarks/bookmarks_browsertest.h index dc07976..d15170b 100644 --- a/chrome/browser/ui/webui/bookmarks/bookmarks_browsertest.h +++ b/chrome/browser/ui/webui/bookmarks/bookmarks_browsertest.h
@@ -8,11 +8,11 @@ #include "chrome/test/base/web_ui_browser_test.h" #include "content/public/browser/web_ui_message_handler.h" -class MdBookmarksBrowserTest : public WebUIBrowserTest, - public content::WebUIMessageHandler { +class BookmarksBrowserTest : public WebUIBrowserTest, + public content::WebUIMessageHandler { public: - MdBookmarksBrowserTest(); - ~MdBookmarksBrowserTest() override; + BookmarksBrowserTest(); + ~BookmarksBrowserTest() override; void SetIncognitoAvailability(int availability); void SetCanEditBookmarks(bool canEdit); @@ -27,7 +27,7 @@ // WebUIBrowserTest: content::WebUIMessageHandler* GetMockMessageHandler() override; - DISALLOW_COPY_AND_ASSIGN(MdBookmarksBrowserTest); + DISALLOW_COPY_AND_ASSIGN(BookmarksBrowserTest); }; #endif // CHROME_BROWSER_UI_WEBUI_BOOKMARKS_BOOKMARKS_BROWSERTEST_H_
diff --git a/chrome/browser/ui/webui/bookmarks/bookmarks_ui.cc b/chrome/browser/ui/webui/bookmarks/bookmarks_ui.cc index 64b71a85..0f540e8 100644 --- a/chrome/browser/ui/webui/bookmarks/bookmarks_ui.cc +++ b/chrome/browser/ui/webui/bookmarks/bookmarks_ui.cc
@@ -40,7 +40,7 @@ source->AddString(message, str); } -content::WebUIDataSource* CreateMdBookmarksUIHTMLSource(Profile* profile) { +content::WebUIDataSource* CreateBookmarksUIHTMLSource(Profile* profile) { content::WebUIDataSource* source = content::WebUIDataSource::Create(chrome::kChromeUIBookmarksHost); @@ -57,12 +57,11 @@ // Localized strings (alphabetical order). AddLocalizedString(source, "addBookmarkTitle", - IDS_MD_BOOKMARK_MANAGER_ADD_BOOKMARK_TITLE); + IDS_BOOKMARK_MANAGER_ADD_BOOKMARK_TITLE); AddLocalizedString(source, "addFolderTitle", - IDS_MD_BOOKMARK_MANAGER_ADD_FOLDER_TITLE); + IDS_BOOKMARK_MANAGER_ADD_FOLDER_TITLE); AddLocalizedString(source, "cancel", IDS_CANCEL); - AddLocalizedString(source, "clearSearch", - IDS_MD_BOOKMARK_MANAGER_CLEAR_SEARCH); + AddLocalizedString(source, "clearSearch", IDS_BOOKMARK_MANAGER_CLEAR_SEARCH); AddLocalizedString(source, "delete", IDS_DELETE); AddLocalizedString(source, "editBookmarkTitle", IDS_BOOKMARK_EDITOR_TITLE); AddLocalizedString(source, "editDialogInvalidUrl", @@ -71,156 +70,144 @@ IDS_BOOKMARK_MANAGER_NAME_INPUT_PLACE_HOLDER); AddLocalizedString(source, "editDialogUrlInput", IDS_BOOKMARK_MANAGER_URL_INPUT_PLACE_HOLDER); - AddLocalizedString(source, "emptyList", IDS_MD_BOOKMARK_MANAGER_EMPTY_LIST); + AddLocalizedString(source, "emptyList", IDS_BOOKMARK_MANAGER_EMPTY_LIST); AddLocalizedString(source, "emptyUnmodifiableList", - IDS_MD_BOOKMARK_MANAGER_EMPTY_UNMODIFIABLE_LIST); - AddLocalizedString(source, "folderLabel", - IDS_MD_BOOKMARK_MANAGER_FOLDER_LABEL); + IDS_BOOKMARK_MANAGER_EMPTY_UNMODIFIABLE_LIST); + AddLocalizedString(source, "folderLabel", IDS_BOOKMARK_MANAGER_FOLDER_LABEL); AddLocalizedString(source, "itemsSelected", - IDS_MD_BOOKMARK_MANAGER_ITEMS_SELECTED); - AddLocalizedString(source, "listAxLabel", - IDS_MD_BOOKMARK_MANAGER_LIST_AX_LABEL); + IDS_BOOKMARK_MANAGER_ITEMS_SELECTED); + AddLocalizedString(source, "listAxLabel", IDS_BOOKMARK_MANAGER_LIST_AX_LABEL); AddLocalizedString(source, "managedByOrg", IDS_MANAGED_BY_ORG_WITH_HYPERLINK); AddLocalizedString(source, "menuAddBookmark", - IDS_MD_BOOKMARK_MANAGER_MENU_ADD_BOOKMARK); + IDS_BOOKMARK_MANAGER_MENU_ADD_BOOKMARK); AddLocalizedString(source, "menuAddFolder", - IDS_MD_BOOKMARK_MANAGER_MENU_ADD_FOLDER); - AddLocalizedString(source, "menuCopyURL", - IDS_MD_BOOKMARK_MANAGER_MENU_COPY_URL); + IDS_BOOKMARK_MANAGER_MENU_ADD_FOLDER); + AddLocalizedString(source, "menuCopyURL", IDS_BOOKMARK_MANAGER_MENU_COPY_URL); AddLocalizedString(source, "menuDelete", IDS_DELETE); AddLocalizedString(source, "menuEdit", IDS_EDIT); - AddLocalizedString(source, "menuExport", IDS_MD_BOOKMARK_MANAGER_MENU_EXPORT); + AddLocalizedString(source, "menuExport", IDS_BOOKMARK_MANAGER_MENU_EXPORT); AddLocalizedString(source, "menuHelpCenter", - IDS_MD_BOOKMARK_MANAGER_MENU_HELP_CENTER); - AddLocalizedString(source, "menuImport", IDS_MD_BOOKMARK_MANAGER_MENU_IMPORT); + IDS_BOOKMARK_MANAGER_MENU_HELP_CENTER); + AddLocalizedString(source, "menuImport", IDS_BOOKMARK_MANAGER_MENU_IMPORT); AddLocalizedString(source, "menuOpenAllNewTab", - IDS_MD_BOOKMARK_MANAGER_MENU_OPEN_ALL); + IDS_BOOKMARK_MANAGER_MENU_OPEN_ALL); AddLocalizedString(source, "menuOpenAllNewWindow", - IDS_MD_BOOKMARK_MANAGER_MENU_OPEN_ALL_NEW_WINDOW); + IDS_BOOKMARK_MANAGER_MENU_OPEN_ALL_NEW_WINDOW); AddLocalizedString(source, "menuOpenAllIncognito", - IDS_MD_BOOKMARK_MANAGER_MENU_OPEN_ALL_INCOGNITO); + IDS_BOOKMARK_MANAGER_MENU_OPEN_ALL_INCOGNITO); AddLocalizedString(source, "menuOpenNewTab", - IDS_MD_BOOKMARK_MANAGER_MENU_OPEN_IN_NEW_TAB); + IDS_BOOKMARK_MANAGER_MENU_OPEN_IN_NEW_TAB); AddLocalizedString(source, "menuOpenNewWindow", - IDS_MD_BOOKMARK_MANAGER_MENU_OPEN_IN_NEW_WINDOW); + IDS_BOOKMARK_MANAGER_MENU_OPEN_IN_NEW_WINDOW); AddLocalizedString(source, "menuOpenIncognito", - IDS_MD_BOOKMARK_MANAGER_MENU_OPEN_INCOGNITO); - AddLocalizedString(source, "menuRename", IDS_MD_BOOKMARK_MANAGER_MENU_RENAME); + IDS_BOOKMARK_MANAGER_MENU_OPEN_INCOGNITO); + AddLocalizedString(source, "menuRename", IDS_BOOKMARK_MANAGER_MENU_RENAME); AddLocalizedString(source, "menuShowInFolder", - IDS_MD_BOOKMARK_MANAGER_MENU_SHOW_IN_FOLDER); - AddLocalizedString(source, "menuSort", IDS_MD_BOOKMARK_MANAGER_MENU_SORT); + IDS_BOOKMARK_MANAGER_MENU_SHOW_IN_FOLDER); + AddLocalizedString(source, "menuSort", IDS_BOOKMARK_MANAGER_MENU_SORT); AddLocalizedString(source, "moreActionsButtonTitle", - IDS_MD_BOOKMARK_MANAGER_MORE_ACTIONS); + IDS_BOOKMARK_MANAGER_MORE_ACTIONS); AddLocalizedString(source, "moreActionsButtonAxLabel", - IDS_MD_BOOKMARK_MANAGER_MORE_ACTIONS_AX_LABEL); + IDS_BOOKMARK_MANAGER_MORE_ACTIONS_AX_LABEL); AddLocalizedString(source, "noSearchResults", IDS_SEARCH_NO_RESULTS); AddLocalizedString(source, "openDialogBody", IDS_BOOKMARK_BAR_SHOULD_OPEN_ALL); AddLocalizedString(source, "openDialogConfirm", - IDS_MD_BOOKMARK_MANAGER_OPEN_DIALOG_CONFIRM); + IDS_BOOKMARK_MANAGER_OPEN_DIALOG_CONFIRM); AddLocalizedString(source, "openDialogTitle", - IDS_MD_BOOKMARK_MANAGER_OPEN_DIALOG_TITLE); + IDS_BOOKMARK_MANAGER_OPEN_DIALOG_TITLE); AddLocalizedString(source, "organizeButtonTitle", IDS_BOOKMARK_MANAGER_ORGANIZE_MENU); AddLocalizedString(source, "renameFolderTitle", - IDS_MD_BOOKMARK_MANAGER_FOLDER_RENAME_TITLE); + IDS_BOOKMARK_MANAGER_FOLDER_RENAME_TITLE); AddLocalizedString(source, "searchPrompt", IDS_BOOKMARK_MANAGER_SEARCH_BUTTON); AddLocalizedString(source, "sidebarAxLabel", - IDS_MD_BOOKMARK_MANAGER_SIDEBAR_AX_LABEL); + IDS_BOOKMARK_MANAGER_SIDEBAR_AX_LABEL); AddLocalizedString(source, "sidebarNodeCollapseAxLabel", - IDS_MD_BOOKMARK_MANAGER_SIDEBAR_NODE_COLLAPSE_AX_LABEL); + IDS_BOOKMARK_MANAGER_SIDEBAR_NODE_COLLAPSE_AX_LABEL); AddLocalizedString(source, "sidebarNodeExpandAxLabel", - IDS_MD_BOOKMARK_MANAGER_SIDEBAR_NODE_EXPAND_AX_LABEL); + IDS_BOOKMARK_MANAGER_SIDEBAR_NODE_EXPAND_AX_LABEL); AddLocalizedString(source, "searchCleared", IDS_SEARCH_CLEARED); AddLocalizedString(source, "searchResults", IDS_SEARCH_RESULTS); AddLocalizedString(source, "saveEdit", IDS_SAVE); - AddLocalizedString(source, "title", IDS_MD_BOOKMARK_MANAGER_TITLE); + AddLocalizedString(source, "title", IDS_BOOKMARK_MANAGER_TITLE); AddLocalizedString(source, "toastFolderSorted", - IDS_MD_BOOKMARK_MANAGER_TOAST_FOLDER_SORTED); + IDS_BOOKMARK_MANAGER_TOAST_FOLDER_SORTED); AddLocalizedString(source, "toastItemCopied", - IDS_MD_BOOKMARK_MANAGER_TOAST_ITEM_COPIED); + IDS_BOOKMARK_MANAGER_TOAST_ITEM_COPIED); AddLocalizedString(source, "toastItemDeleted", - IDS_MD_BOOKMARK_MANAGER_TOAST_ITEM_DELETED); + IDS_BOOKMARK_MANAGER_TOAST_ITEM_DELETED); AddLocalizedString(source, "toastUrlCopied", - IDS_MD_BOOKMARK_MANAGER_TOAST_URL_COPIED); + IDS_BOOKMARK_MANAGER_TOAST_URL_COPIED); AddLocalizedString(source, "undo", IDS_BOOKMARK_BAR_UNDO); // Resources. source->AddResourcePath("images/folder_open.svg", - IDR_MD_BOOKMARKS_IMAGES_FOLDER_OPEN_SVG); - source->AddResourcePath("images/folder.svg", - IDR_MD_BOOKMARKS_IMAGES_FOLDER_SVG); + IDR_BOOKMARKS_IMAGES_FOLDER_OPEN_SVG); + source->AddResourcePath("images/folder.svg", IDR_BOOKMARKS_IMAGES_FOLDER_SVG); #if BUILDFLAG(OPTIMIZE_WEBUI) - source->AddResourcePath("crisper.js", IDR_MD_BOOKMARKS_CRISPER_JS); + source->AddResourcePath("crisper.js", IDR_BOOKMARKS_CRISPER_JS); source->SetDefaultResource( base::FeatureList::IsEnabled(features::kWebUIPolymer2) - ? IDR_MD_BOOKMARKS_VULCANIZED_P2_HTML - : IDR_MD_BOOKMARKS_VULCANIZED_HTML); + ? IDR_BOOKMARKS_VULCANIZED_P2_HTML + : IDR_BOOKMARKS_VULCANIZED_HTML); source->UseGzip(base::BindRepeating([](const std::string& path) { return path != "images/folder_open.svg" && path != "images/folder.svg"; })); #else - source->AddResourcePath("actions.html", IDR_MD_BOOKMARKS_ACTIONS_HTML); - source->AddResourcePath("actions.js", IDR_MD_BOOKMARKS_ACTIONS_JS); - source->AddResourcePath("api_listener.html", - IDR_MD_BOOKMARKS_API_LISTENER_HTML); - source->AddResourcePath("api_listener.js", IDR_MD_BOOKMARKS_API_LISTENER_JS); - source->AddResourcePath("app.html", IDR_MD_BOOKMARKS_APP_HTML); - source->AddResourcePath("app.js", IDR_MD_BOOKMARKS_APP_JS); + source->AddResourcePath("actions.html", IDR_BOOKMARKS_ACTIONS_HTML); + source->AddResourcePath("actions.js", IDR_BOOKMARKS_ACTIONS_JS); + source->AddResourcePath("api_listener.html", IDR_BOOKMARKS_API_LISTENER_HTML); + source->AddResourcePath("api_listener.js", IDR_BOOKMARKS_API_LISTENER_JS); + source->AddResourcePath("app.html", IDR_BOOKMARKS_APP_HTML); + source->AddResourcePath("app.js", IDR_BOOKMARKS_APP_JS); source->AddResourcePath("command_manager.html", - IDR_MD_BOOKMARKS_COMMAND_MANAGER_HTML); + IDR_BOOKMARKS_COMMAND_MANAGER_HTML); source->AddResourcePath("command_manager.js", - IDR_MD_BOOKMARKS_COMMAND_MANAGER_JS); - source->AddResourcePath("constants.html", IDR_MD_BOOKMARKS_CONSTANTS_HTML); - source->AddResourcePath("constants.js", IDR_MD_BOOKMARKS_CONSTANTS_JS); - source->AddResourcePath("debouncer.html", IDR_MD_BOOKMARKS_DEBOUNCER_HTML); - source->AddResourcePath("debouncer.js", IDR_MD_BOOKMARKS_DEBOUNCER_JS); + IDR_BOOKMARKS_COMMAND_MANAGER_JS); + source->AddResourcePath("constants.html", IDR_BOOKMARKS_CONSTANTS_HTML); + source->AddResourcePath("constants.js", IDR_BOOKMARKS_CONSTANTS_JS); + source->AddResourcePath("debouncer.html", IDR_BOOKMARKS_DEBOUNCER_HTML); + source->AddResourcePath("debouncer.js", IDR_BOOKMARKS_DEBOUNCER_JS); source->AddResourcePath("dialog_focus_manager.html", - IDR_MD_BOOKMARKS_DIALOG_FOCUS_MANAGER_HTML); + IDR_BOOKMARKS_DIALOG_FOCUS_MANAGER_HTML); source->AddResourcePath("dialog_focus_manager.js", - IDR_MD_BOOKMARKS_DIALOG_FOCUS_MANAGER_JS); - source->AddResourcePath("dnd_manager.html", - IDR_MD_BOOKMARKS_DND_MANAGER_HTML); - source->AddResourcePath("dnd_manager.js", IDR_MD_BOOKMARKS_DND_MANAGER_JS); - source->AddResourcePath("edit_dialog.html", - IDR_MD_BOOKMARKS_EDIT_DIALOG_HTML); - source->AddResourcePath("edit_dialog.js", IDR_MD_BOOKMARKS_EDIT_DIALOG_JS); - source->AddResourcePath("folder_node.html", - IDR_MD_BOOKMARKS_FOLDER_NODE_HTML); - source->AddResourcePath("folder_node.js", IDR_MD_BOOKMARKS_FOLDER_NODE_JS); - source->AddResourcePath("item.html", IDR_MD_BOOKMARKS_ITEM_HTML); - source->AddResourcePath("item.js", IDR_MD_BOOKMARKS_ITEM_JS); - source->AddResourcePath("list.html", IDR_MD_BOOKMARKS_LIST_HTML); - source->AddResourcePath("list.js", IDR_MD_BOOKMARKS_LIST_JS); + IDR_BOOKMARKS_DIALOG_FOCUS_MANAGER_JS); + source->AddResourcePath("dnd_manager.html", IDR_BOOKMARKS_DND_MANAGER_HTML); + source->AddResourcePath("dnd_manager.js", IDR_BOOKMARKS_DND_MANAGER_JS); + source->AddResourcePath("edit_dialog.html", IDR_BOOKMARKS_EDIT_DIALOG_HTML); + source->AddResourcePath("edit_dialog.js", IDR_BOOKMARKS_EDIT_DIALOG_JS); + source->AddResourcePath("folder_node.html", IDR_BOOKMARKS_FOLDER_NODE_HTML); + source->AddResourcePath("folder_node.js", IDR_BOOKMARKS_FOLDER_NODE_JS); + source->AddResourcePath("item.html", IDR_BOOKMARKS_ITEM_HTML); + source->AddResourcePath("item.js", IDR_BOOKMARKS_ITEM_JS); + source->AddResourcePath("list.html", IDR_BOOKMARKS_LIST_HTML); + source->AddResourcePath("list.js", IDR_BOOKMARKS_LIST_JS); source->AddResourcePath("mouse_focus_behavior.html", - IDR_MD_BOOKMARKS_MOUSE_FOCUS_BEHAVIOR_HTML); + IDR_BOOKMARKS_MOUSE_FOCUS_BEHAVIOR_HTML); source->AddResourcePath("mouse_focus_behavior.js", - IDR_MD_BOOKMARKS_MOUSE_FOCUS_BEHAVIOR_JS); - source->AddResourcePath("reducers.html", IDR_MD_BOOKMARKS_REDUCERS_HTML); - source->AddResourcePath("reducers.js", IDR_MD_BOOKMARKS_REDUCERS_JS); - source->AddResourcePath("router.html", IDR_MD_BOOKMARKS_ROUTER_HTML); - source->AddResourcePath("router.js", IDR_MD_BOOKMARKS_ROUTER_JS); - source->AddResourcePath("shared_style.html", - IDR_MD_BOOKMARKS_SHARED_STYLE_HTML); - source->AddResourcePath("shared_vars.html", - IDR_MD_BOOKMARKS_SHARED_VARS_HTML); - source->AddResourcePath("store.html", IDR_MD_BOOKMARKS_STORE_HTML); - source->AddResourcePath("store.js", IDR_MD_BOOKMARKS_STORE_JS); - source->AddResourcePath("store_client.html", - IDR_MD_BOOKMARKS_STORE_CLIENT_HTML); - source->AddResourcePath("store_client.js", IDR_MD_BOOKMARKS_STORE_CLIENT_JS); - source->AddResourcePath("strings.html", IDR_MD_BOOKMARKS_STRINGS_HTML); + IDR_BOOKMARKS_MOUSE_FOCUS_BEHAVIOR_JS); + source->AddResourcePath("reducers.html", IDR_BOOKMARKS_REDUCERS_HTML); + source->AddResourcePath("reducers.js", IDR_BOOKMARKS_REDUCERS_JS); + source->AddResourcePath("router.html", IDR_BOOKMARKS_ROUTER_HTML); + source->AddResourcePath("router.js", IDR_BOOKMARKS_ROUTER_JS); + source->AddResourcePath("shared_style.html", IDR_BOOKMARKS_SHARED_STYLE_HTML); + source->AddResourcePath("shared_vars.html", IDR_BOOKMARKS_SHARED_VARS_HTML); + source->AddResourcePath("store.html", IDR_BOOKMARKS_STORE_HTML); + source->AddResourcePath("store.js", IDR_BOOKMARKS_STORE_JS); + source->AddResourcePath("store_client.html", IDR_BOOKMARKS_STORE_CLIENT_HTML); + source->AddResourcePath("store_client.js", IDR_BOOKMARKS_STORE_CLIENT_JS); + source->AddResourcePath("strings.html", IDR_BOOKMARKS_STRINGS_HTML); source->AddResourcePath("toast_manager.html", - IDR_MD_BOOKMARKS_TOAST_MANAGER_HTML); - source->AddResourcePath("toast_manager.js", - IDR_MD_BOOKMARKS_TOAST_MANAGER_JS); - source->AddResourcePath("toolbar.html", IDR_MD_BOOKMARKS_TOOLBAR_HTML); - source->AddResourcePath("toolbar.js", IDR_MD_BOOKMARKS_TOOLBAR_JS); - source->AddResourcePath("util.html", IDR_MD_BOOKMARKS_UTIL_HTML); - source->AddResourcePath("util.js", IDR_MD_BOOKMARKS_UTIL_JS); + IDR_BOOKMARKS_TOAST_MANAGER_HTML); + source->AddResourcePath("toast_manager.js", IDR_BOOKMARKS_TOAST_MANAGER_JS); + source->AddResourcePath("toolbar.html", IDR_BOOKMARKS_TOOLBAR_HTML); + source->AddResourcePath("toolbar.js", IDR_BOOKMARKS_TOOLBAR_JS); + source->AddResourcePath("util.html", IDR_BOOKMARKS_UTIL_HTML); + source->AddResourcePath("util.js", IDR_BOOKMARKS_UTIL_JS); - source->SetDefaultResource(IDR_MD_BOOKMARKS_BOOKMARKS_HTML); + source->SetDefaultResource(IDR_BOOKMARKS_BOOKMARKS_HTML); #endif source->SetJsonPath("strings.js"); @@ -230,20 +217,20 @@ } // namespace -MdBookmarksUI::MdBookmarksUI(content::WebUI* web_ui) : WebUIController(web_ui) { +BookmarksUI::BookmarksUI(content::WebUI* web_ui) : WebUIController(web_ui) { // Set up the chrome://bookmarks/ source. Profile* profile = Profile::FromWebUI(web_ui); - auto* source = CreateMdBookmarksUIHTMLSource(profile); + auto* source = CreateBookmarksUIHTMLSource(profile); DarkModeHandler::Initialize(web_ui, source); content::WebUIDataSource::Add(profile, source); auto plural_string_handler = std::make_unique<PluralStringHandler>(); plural_string_handler->AddLocalizedString( - "listChanged", IDS_MD_BOOKMARK_MANAGER_FOLDER_LIST_CHANGED); + "listChanged", IDS_BOOKMARK_MANAGER_FOLDER_LIST_CHANGED); plural_string_handler->AddLocalizedString( - "toastItemsDeleted", IDS_MD_BOOKMARK_MANAGER_TOAST_ITEMS_DELETED); + "toastItemsDeleted", IDS_BOOKMARK_MANAGER_TOAST_ITEMS_DELETED); plural_string_handler->AddLocalizedString( - "toastItemsCopied", IDS_MD_BOOKMARK_MANAGER_TOAST_ITEMS_COPIED); + "toastItemsCopied", IDS_BOOKMARK_MANAGER_TOAST_ITEMS_COPIED); web_ui->AddMessageHandler(std::move(plural_string_handler)); web_ui->AddMessageHandler(std::make_unique<BookmarksMessageHandler>()); @@ -251,7 +238,7 @@ } // static -base::RefCountedMemory* MdBookmarksUI::GetFaviconResourceBytes( +base::RefCountedMemory* BookmarksUI::GetFaviconResourceBytes( ui::ScaleFactor scale_factor) { return ui::ResourceBundle::GetSharedInstance().LoadDataResourceBytesForScale( IDR_BOOKMARKS_FAVICON, scale_factor);
diff --git a/chrome/browser/ui/webui/bookmarks/bookmarks_ui.h b/chrome/browser/ui/webui/bookmarks/bookmarks_ui.h index 92ce12b..23e4ea5e 100644 --- a/chrome/browser/ui/webui/bookmarks/bookmarks_ui.h +++ b/chrome/browser/ui/webui/bookmarks/bookmarks_ui.h
@@ -13,15 +13,15 @@ class RefCountedMemory; } -class MdBookmarksUI : public content::WebUIController { +class BookmarksUI : public content::WebUIController { public: - explicit MdBookmarksUI(content::WebUI* web_ui); + explicit BookmarksUI(content::WebUI* web_ui); static base::RefCountedMemory* GetFaviconResourceBytes( ui::ScaleFactor scale_factor); private: - DISALLOW_COPY_AND_ASSIGN(MdBookmarksUI); + DISALLOW_COPY_AND_ASSIGN(BookmarksUI); }; #endif // CHROME_BROWSER_UI_WEBUI_BOOKMARKS_BOOKMARKS_UI_H_
diff --git a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc index efb27ee..fe425d5 100644 --- a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc +++ b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc
@@ -23,6 +23,7 @@ #include "chrome/browser/search/suggestions/suggestions_ui.h" #include "chrome/browser/ui/webui/about_ui.h" #include "chrome/browser/ui/webui/bluetooth_internals/bluetooth_internals_ui.h" +#include "chrome/browser/ui/webui/chromeos/account_manager_welcome_ui.h" #include "chrome/browser/ui/webui/components_ui.h" #include "chrome/browser/ui/webui/constrained_web_dialog_ui.h" #include "chrome/browser/ui/webui/crashes_ui.h" @@ -449,7 +450,7 @@ } // Bookmarks are part of NTP on Android. if (url.host_piece() == chrome::kChromeUIBookmarksHost) - return &NewWebUI<MdBookmarksUI>; + return &NewWebUI<BookmarksUI>; // Downloads list on Android uses the built-in download manager. if (url.host_piece() == chrome::kChromeUIDownloadsHost) return &NewWebUI<MdDownloadsUI>; @@ -480,6 +481,8 @@ return &NewWebUI<SetAsDefaultBrowserUI>; #endif #if defined(OS_CHROMEOS) + if (url.host_piece() == chrome::kChromeUIAccountManagerWelcomeHost) + return &NewWebUI<chromeos::AccountManagerWelcomeUI>; if (url.host_piece() == chrome::kChromeUIBluetoothPairingHost) return &NewWebUI<chromeos::BluetoothPairingDialogUI>; if (url.host_piece() == chrome::kChromeUICertificateManagerHost) @@ -862,7 +865,7 @@ // Bookmarks are part of NTP on Android. if (page_url.host_piece() == chrome::kChromeUIBookmarksHost) - return MdBookmarksUI::GetFaviconResourceBytes(scale_factor); + return BookmarksUI::GetFaviconResourceBytes(scale_factor); // Android uses the native download manager. if (page_url.host_piece() == chrome::kChromeUIDownloadsHost)
diff --git a/chrome/browser/ui/webui/chromeos/account_manager_welcome_dialog.cc b/chrome/browser/ui/webui/chromeos/account_manager_welcome_dialog.cc new file mode 100644 index 0000000..65a7f34 --- /dev/null +++ b/chrome/browser/ui/webui/chromeos/account_manager_welcome_dialog.cc
@@ -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. + +#include "chrome/browser/ui/webui/chromeos/account_manager_welcome_dialog.h" + +#include <string> + +#include "base/logging.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/profiles/profile_manager.h" +#include "chrome/browser/ui/settings_window_manager_chromeos.h" +#include "chrome/common/webui_url_constants.h" +#include "ui/aura/window.h" +#include "url/gurl.h" + +namespace chromeos { + +namespace { + +AccountManagerWelcomeDialog* g_dialog = nullptr; +constexpr int kSigninDialogWidth = 600; +constexpr int kSigninDialogHeight = 500; + +} // namespace + +AccountManagerWelcomeDialog::AccountManagerWelcomeDialog() + : SystemWebDialogDelegate(GURL(chrome::kChromeUIAccountManagerWelcomeURL), + base::string16() /* title */) {} + +AccountManagerWelcomeDialog::~AccountManagerWelcomeDialog() { + DCHECK_EQ(this, g_dialog); + g_dialog = nullptr; +} + +// static +bool AccountManagerWelcomeDialog::ShowIfRequired() { + if (g_dialog) { + // If the dialog is already being displayed, bring it to focus instead of + // creating another window. + g_dialog->dialog_window()->Focus(); + return true; + } + + // Will be deleted by |SystemWebDialogDelegate::OnDialogClosed|. + g_dialog = new AccountManagerWelcomeDialog(); + g_dialog->ShowSystemDialog(); + + // TODO(sinhak): Store the number of times the welcome screen has been shown + // in Prefs and check against it before showing it again. + return true; +} + +void AccountManagerWelcomeDialog::OnDialogClosed( + const std::string& json_retval) { + chrome::SettingsWindowManager::GetInstance()->ShowChromePageForProfile( + ProfileManager::GetActiveUserProfile(), + GURL("chrome://settings/accountManager")); + + SystemWebDialogDelegate::OnDialogClosed(json_retval); +} + +void AccountManagerWelcomeDialog::GetDialogSize(gfx::Size* size) const { + size->SetSize(kSigninDialogWidth, kSigninDialogHeight); +} + +std::string AccountManagerWelcomeDialog::GetDialogArgs() const { + return std::string(); +} + +bool AccountManagerWelcomeDialog::ShouldShowDialogTitle() const { + return false; +} + +} // namespace chromeos
diff --git a/chrome/browser/ui/webui/chromeos/account_manager_welcome_dialog.h b/chrome/browser/ui/webui/chromeos/account_manager_welcome_dialog.h new file mode 100644 index 0000000..63e020d --- /dev/null +++ b/chrome/browser/ui/webui/chromeos/account_manager_welcome_dialog.h
@@ -0,0 +1,38 @@ +// 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 CHROME_BROWSER_UI_WEBUI_CHROMEOS_ACCOUNT_MANAGER_WELCOME_DIALOG_H_ +#define CHROME_BROWSER_UI_WEBUI_CHROMEOS_ACCOUNT_MANAGER_WELCOME_DIALOG_H_ + +#include <string> + +#include "base/macros.h" +#include "chrome/browser/ui/webui/chromeos/system_web_dialog_delegate.h" + +namespace chromeos { + +class AccountManagerWelcomeDialog : public SystemWebDialogDelegate { + public: + // Displays the Chrome OS Account Manager welcome screen, if it has not been + // shown "too many times" before. Returns true if the screen was displayed, + // false otherwise. + static bool ShowIfRequired(); + + protected: + AccountManagerWelcomeDialog(); + ~AccountManagerWelcomeDialog() override; + + // ui::SystemWebDialogDelegate overrides. + void OnDialogClosed(const std::string& json_retval) override; + void GetDialogSize(gfx::Size* size) const override; + std::string GetDialogArgs() const override; + bool ShouldShowDialogTitle() const override; + + private: + DISALLOW_COPY_AND_ASSIGN(AccountManagerWelcomeDialog); +}; + +} // namespace chromeos + +#endif // CHROME_BROWSER_UI_WEBUI_CHROMEOS_ACCOUNT_MANAGER_WELCOME_DIALOG_H_
diff --git a/chrome/browser/ui/webui/chromeos/account_manager_welcome_ui.cc b/chrome/browser/ui/webui/chromeos/account_manager_welcome_ui.cc new file mode 100644 index 0000000..d5c803d --- /dev/null +++ b/chrome/browser/ui/webui/chromeos/account_manager_welcome_ui.cc
@@ -0,0 +1,54 @@ +// 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 "chrome/browser/ui/webui/chromeos/account_manager_welcome_ui.h" + +#include "base/bind.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/common/webui_url_constants.h" +#include "chrome/grit/browser_resources.h" +#include "chrome/grit/generated_resources.h" +#include "content/public/browser/web_ui_data_source.h" +#include "ui/strings/grit/ui_strings.h" + +namespace chromeos { + +AccountManagerWelcomeUI::AccountManagerWelcomeUI(content::WebUI* web_ui) + : ui::WebDialogUI(web_ui), weak_factory_(this) { + content::WebUIDataSource* html_source = content::WebUIDataSource::Create( + chrome::kChromeUIAccountManagerWelcomeHost); + + web_ui->RegisterMessageCallback( + "closeDialog", base::BindRepeating(&WebDialogUI::CloseDialog, + weak_factory_.GetWeakPtr())); + + html_source->SetJsonPath("strings.js"); + + // Add localized strings. + html_source->AddLocalizedString("welcomeTitle", + IDS_ACCOUNT_MANAGER_WELCOME_TITLE); + html_source->AddLocalizedString("welcomeMessage", + IDS_ACCOUNT_MANAGER_WELCOME_TEXT); + html_source->AddLocalizedString("okButton", IDS_APP_OK); + + // Add required resources. + html_source->AddResourcePath("account_manager_welcome.css", + IDR_ACCOUNT_MANAGER_WELCOME_CSS); + html_source->AddResourcePath("account_manager_welcome.js", + IDR_ACCOUNT_MANAGER_WELCOME_JS); + html_source->AddResourcePath("account_manager_welcome_1x.png", + IDR_ACCOUNT_MANAGER_WELCOME_1X_PNG); + html_source->AddResourcePath("account_manager_welcome_2x.png", + IDR_ACCOUNT_MANAGER_WELCOME_2X_PNG); + html_source->AddResourcePath("googleg.svg", + IDR_ACCOUNT_MANAGER_WELCOME_GOOGLE_LOGO_SVG); + html_source->SetDefaultResource(IDR_ACCOUNT_MANAGER_WELCOME_HTML); + + Profile* profile = Profile::FromWebUI(web_ui); + content::WebUIDataSource::Add(profile, html_source); +} + +AccountManagerWelcomeUI::~AccountManagerWelcomeUI() = default; + +} // namespace chromeos
diff --git a/chrome/browser/ui/webui/chromeos/account_manager_welcome_ui.h b/chrome/browser/ui/webui/chromeos/account_manager_welcome_ui.h new file mode 100644 index 0000000..6f66e183 --- /dev/null +++ b/chrome/browser/ui/webui/chromeos/account_manager_welcome_ui.h
@@ -0,0 +1,27 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_WEBUI_CHROMEOS_ACCOUNT_MANAGER_WELCOME_UI_H_ +#define CHROME_BROWSER_UI_WEBUI_CHROMEOS_ACCOUNT_MANAGER_WELCOME_UI_H_ + +#include "base/macros.h" +#include "base/memory/weak_ptr.h" +#include "ui/web_dialogs/web_dialog_ui.h" + +namespace chromeos { + +// For chrome:://account-manager-welcome +class AccountManagerWelcomeUI : public ui::WebDialogUI { + public: + explicit AccountManagerWelcomeUI(content::WebUI* web_ui); + ~AccountManagerWelcomeUI() override; + + private: + base::WeakPtrFactory<AccountManagerWelcomeUI> weak_factory_; + DISALLOW_COPY_AND_ASSIGN(AccountManagerWelcomeUI); +}; + +} // namespace chromeos + +#endif // CHROME_BROWSER_UI_WEBUI_CHROMEOS_ACCOUNT_MANAGER_WELCOME_UI_H_
diff --git a/chrome/browser/ui/webui/page_not_available_for_guest/page_not_available_for_guest_ui.cc b/chrome/browser/ui/webui/page_not_available_for_guest/page_not_available_for_guest_ui.cc index 779533a..946af1c1 100644 --- a/chrome/browser/ui/webui/page_not_available_for_guest/page_not_available_for_guest_ui.cc +++ b/chrome/browser/ui/webui/page_not_available_for_guest/page_not_available_for_guest_ui.cc
@@ -23,7 +23,7 @@ base::string16 page_title; if (host_name == chrome::kChromeUIBookmarksHost) - page_title = l10n_util::GetStringUTF16(IDS_MD_BOOKMARK_MANAGER_TITLE); + page_title = l10n_util::GetStringUTF16(IDS_BOOKMARK_MANAGER_TITLE); else if (host_name == chrome::kChromeUIHistoryHost) page_title = l10n_util::GetStringUTF16(IDS_HISTORY_TITLE); else if (host_name == chrome::kChromeUIExtensionsHost)
diff --git a/chrome/browser/ui/webui/set_as_default_browser_ui_win.cc b/chrome/browser/ui/webui/set_as_default_browser_ui_win.cc index c0977b81..c0999a2 100644 --- a/chrome/browser/ui/webui/set_as_default_browser_ui_win.cc +++ b/chrome/browser/ui/webui/set_as_default_browser_ui_win.cc
@@ -71,7 +71,7 @@ content::WebUIDataSource* CreateSetAsDefaultBrowserUIHTMLSource() { content::WebUIDataSource* data_source = content::WebUIDataSource::Create(chrome::kChromeUIMetroFlowHost); - data_source->AddLocalizedString("page-title", IDS_METRO_FLOW_TAB_TITLE); + data_source->AddLocalizedString("pageTitle", IDS_METRO_FLOW_TAB_TITLE); data_source->AddLocalizedString("flowTitle", IDS_METRO_FLOW_TITLE_SHORT); data_source->AddLocalizedString("flowDescription", IDS_METRO_FLOW_DESCRIPTION);
diff --git a/chrome/browser/ui/webui/settings/chromeos/multidevice_handler.cc b/chrome/browser/ui/webui/settings/chromeos/multidevice_handler.cc index 10f7cc69..bb93815 100644 --- a/chrome/browser/ui/webui/settings/chromeos/multidevice_handler.cc +++ b/chrome/browser/ui/webui/settings/chromeos/multidevice_handler.cc
@@ -8,6 +8,7 @@ #include "base/bind_helpers.h" #include "base/logging.h" #include "base/values.h" +#include "chrome/browser/chromeos/android_sms/android_sms_pairing_state_tracker_impl.h" #include "chrome/browser/chromeos/android_sms/android_sms_urls.h" #include "chrome/browser/chromeos/login/quick_unlock/quick_unlock_factory.h" #include "chrome/browser/chromeos/login/quick_unlock/quick_unlock_storage.h" @@ -34,6 +35,7 @@ const char kPageContentDataInstantTetheringStateKey[] = "instantTetheringState"; const char kPageContentDataMessagesStateKey[] = "messagesState"; const char kPageContentDataSmartLockStateKey[] = "smartLockState"; +const char kIsAndroidSmsPairingComplete[] = "isAndroidSmsPairingComplete"; constexpr char kAndroidSmsInfoOriginKey[] = "origin"; constexpr char kAndroidSmsInfoEnabledKey[] = "enabled"; @@ -51,11 +53,15 @@ MultideviceHandler::MultideviceHandler( PrefService* prefs, multidevice_setup::MultiDeviceSetupClient* multidevice_setup_client, + multidevice_setup::AndroidSmsPairingStateTracker* + android_sms_pairing_state_tracker, multidevice_setup::AndroidSmsAppHelperDelegate* android_sms_app_helper) : prefs_(prefs), multidevice_setup_client_(multidevice_setup_client), + android_sms_pairing_state_tracker_(android_sms_pairing_state_tracker), android_sms_app_helper_(android_sms_app_helper), multidevice_setup_observer_(this), + android_sms_pairing_state_tracker_observer_(this), callback_weak_ptr_factory_(this) { RegisterPrefChangeListeners(); } @@ -108,12 +114,18 @@ void MultideviceHandler::OnJavascriptAllowed() { if (multidevice_setup_client_) multidevice_setup_observer_.Add(multidevice_setup_client_); + + if (android_sms_pairing_state_tracker_) + android_sms_pairing_state_tracker_->AddObserver(this); } void MultideviceHandler::OnJavascriptDisallowed() { if (multidevice_setup_client_) multidevice_setup_observer_.Remove(multidevice_setup_client_); + if (android_sms_pairing_state_tracker_) + android_sms_pairing_state_tracker_->RemoveObserver(this); + // Ensure that pending callbacks do not complete and cause JS to be evaluated. callback_weak_ptr_factory_.InvalidateWeakPtrs(); } @@ -132,6 +144,11 @@ NotifyAndroidSmsInfoChange(); } +void MultideviceHandler::OnPairingStateChanged() { + UpdatePageContent(); + NotifyAndroidSmsInfoChange(); +} + void MultideviceHandler::UpdatePageContent() { std::unique_ptr<base::DictionaryValue> page_content_dictionary = GeneratePageContentDataDictionary(); @@ -331,6 +348,12 @@ host_status_with_device.second->name()); } + page_content_dictionary->SetBoolean( + kIsAndroidSmsPairingComplete, + android_sms_pairing_state_tracker_ + ? android_sms_pairing_state_tracker_->IsAndroidSmsPairingComplete() + : false); + return page_content_dictionary; }
diff --git a/chrome/browser/ui/webui/settings/chromeos/multidevice_handler.h b/chrome/browser/ui/webui/settings/chromeos/multidevice_handler.h index 6bef9c4d..64eb9ee6 100644 --- a/chrome/browser/ui/webui/settings/chromeos/multidevice_handler.h +++ b/chrome/browser/ui/webui/settings/chromeos/multidevice_handler.h
@@ -8,6 +8,7 @@ #include "base/macros.h" #include "base/memory/weak_ptr.h" #include "base/scoped_observer.h" +#include "chrome/browser/chromeos/android_sms/android_sms_service_factory.h" #include "chrome/browser/ui/webui/settings/settings_page_ui_handler.h" #include "chromeos/components/multidevice/remote_device_ref.h" #include "chromeos/services/multidevice_setup/public/cpp/multidevice_setup_client.h" @@ -31,11 +32,14 @@ // Chrome "Multidevice" (a.k.a. "Connected Devices") settings page UI handler. class MultideviceHandler : public ::settings::SettingsPageUIHandler, - public multidevice_setup::MultiDeviceSetupClient::Observer { + public multidevice_setup::MultiDeviceSetupClient::Observer, + public multidevice_setup::AndroidSmsPairingStateTracker::Observer { public: MultideviceHandler( PrefService* prefs, multidevice_setup::MultiDeviceSetupClient* multidevice_setup_client, + multidevice_setup::AndroidSmsPairingStateTracker* + android_sms_pairing_state_tracker, multidevice_setup::AndroidSmsAppHelperDelegate* android_sms_app_helper); ~MultideviceHandler() override; @@ -56,6 +60,9 @@ const multidevice_setup::MultiDeviceSetupClient::FeatureStatesMap& feature_states_map) override; + // multidevice_setup::AndroidSmsPairingStateTracker::Observer: + void OnPairingStateChanged() override; + // Sends the most recent PageContentData dictionary to the WebUI page as an // update (e.g., not due to a getPageContent() request). void UpdatePageContent(); @@ -103,11 +110,16 @@ GetFeatureStatesMap(); multidevice_setup::MultiDeviceSetupClient* multidevice_setup_client_; + multidevice_setup::AndroidSmsPairingStateTracker* + android_sms_pairing_state_tracker_; multidevice_setup::AndroidSmsAppHelperDelegate* android_sms_app_helper_; ScopedObserver<multidevice_setup::MultiDeviceSetupClient, multidevice_setup::MultiDeviceSetupClient::Observer> multidevice_setup_observer_; + ScopedObserver<multidevice_setup::AndroidSmsPairingStateTracker, + multidevice_setup::AndroidSmsPairingStateTracker::Observer> + android_sms_pairing_state_tracker_observer_; // Used to cancel callbacks when JavaScript becomes disallowed. base::WeakPtrFactory<MultideviceHandler> callback_weak_ptr_factory_;
diff --git a/chrome/browser/ui/webui/settings/chromeos/multidevice_handler_unittest.cc b/chrome/browser/ui/webui/settings/chromeos/multidevice_handler_unittest.cc index 545cbcd5..b3cd72ff 100644 --- a/chrome/browser/ui/webui/settings/chromeos/multidevice_handler_unittest.cc +++ b/chrome/browser/ui/webui/settings/chromeos/multidevice_handler_unittest.cc
@@ -10,6 +10,7 @@ #include "chrome/browser/chromeos/android_sms/android_sms_urls.h" #include "chromeos/components/multidevice/remote_device_test_util.h" #include "chromeos/services/multidevice_setup/public/cpp/fake_android_sms_app_helper_delegate.h" +#include "chromeos/services/multidevice_setup/public/cpp/fake_android_sms_pairing_state_tracker.h" #include "chromeos/services/multidevice_setup/public/cpp/fake_multidevice_setup_client.h" #include "components/content_settings/core/common/content_settings_pattern.h" #include "components/prefs/testing_pref_service.h" @@ -27,9 +28,12 @@ TestMultideviceHandler( PrefService* prefs, multidevice_setup::MultiDeviceSetupClient* multidevice_setup_client, + multidevice_setup::AndroidSmsPairingStateTracker* + android_sms_pairing_state_tracker, multidevice_setup::AndroidSmsAppHelperDelegate* android_sms_app_helper) : MultideviceHandler(prefs, multidevice_setup_client, + android_sms_pairing_state_tracker, std::move(android_sms_app_helper)) {} ~TestMultideviceHandler() override = default; @@ -115,6 +119,8 @@ fake_multidevice_setup_client_ = std::make_unique<multidevice_setup::FakeMultiDeviceSetupClient>(); + fake_android_sms_pairing_state_tracker_ = std::make_unique< + multidevice_setup::FakeAndroidSmsPairingStateTracker>(); fake_android_sms_app_helper_delegate_ = std::make_unique<multidevice_setup::FakeAndroidSmsAppHelperDelegate>(); @@ -122,6 +128,7 @@ handler_ = std::make_unique<TestMultideviceHandler>( prefs_.get(), fake_multidevice_setup_client_.get(), + fake_android_sms_pairing_state_tracker_.get(), fake_android_sms_app_helper_delegate_.get()); handler_->set_web_ui(test_web_ui_.get()); handler_->RegisterMessages(); @@ -211,6 +218,22 @@ VerifyPageContent(call_data.arg2()); } + void SimulatePairingStateUpdate(bool is_android_sms_pairing_complete) { + size_t call_data_count_before_call = test_web_ui()->call_data().size(); + + fake_android_sms_pairing_state_tracker_->SetPairingComplete( + is_android_sms_pairing_complete); + EXPECT_EQ(call_data_count_before_call + 2u, + test_web_ui()->call_data().size()); + + const content::TestWebUI::CallData& call_data = + CallDataAtIndex(call_data_count_before_call); + EXPECT_EQ("cr.webUIListenerCallback", call_data.function_name()); + EXPECT_EQ("settings.updateMultidevicePageContentData", + call_data.arg1()->GetString()); + VerifyPageContent(call_data.arg2()); + } + void CallRetryPendingHostSetup(bool success) { base::ListValue empty_args; test_web_ui()->HandleReceivedMessage("retryPendingHostSetup", &empty_args); @@ -284,6 +307,8 @@ std::unique_ptr<multidevice_setup::FakeMultiDeviceSetupClient> fake_multidevice_setup_client_; std::unique_ptr<TestMultideviceHandler> handler_; + std::unique_ptr<multidevice_setup::FakeAndroidSmsPairingStateTracker> + fake_android_sms_pairing_state_tracker_; multidevice_setup::MultiDeviceSetupClient::HostStatusWithDevice host_status_with_device_; @@ -320,6 +345,8 @@ feature_states_map[multidevice_setup::mojom::Feature::kBetterTogetherSuite] = multidevice_setup::mojom::FeatureState::kDisabledByUser; SimulateFeatureStatesUpdate(feature_states_map); + + SimulatePairingStateUpdate(/*is_android_sms_pairing_complete=*/true); } TEST_F(MultideviceHandlerTest, RetryPendingHostSetup) {
diff --git a/chrome/browser/ui/webui/settings/md_settings_ui.cc b/chrome/browser/ui/webui/settings/md_settings_ui.cc index 2f4fd75..b20663b 100644 --- a/chrome/browser/ui/webui/settings/md_settings_ui.cc +++ b/chrome/browser/ui/webui/settings/md_settings_ui.cc
@@ -293,6 +293,9 @@ chromeos::multidevice_setup::MultiDeviceSetupClientFactory:: GetForProfile(profile), android_sms_service + ? android_sms_service->android_sms_pairing_state_tracker() + : nullptr, + android_sms_service ? android_sms_service->android_sms_app_helper_delegate() : nullptr)); }
diff --git a/chrome/browser/ui/webui/settings/site_settings_handler.h b/chrome/browser/ui/webui/settings/site_settings_handler.h index 88a2f65c..2092bce 100644 --- a/chrome/browser/ui/webui/settings/site_settings_handler.h +++ b/chrome/browser/ui/webui/settings/site_settings_handler.h
@@ -117,6 +117,8 @@ FRIEND_TEST_ALL_PREFIXES(SiteSettingsHandlerTest, PatternsAndContentType); FRIEND_TEST_ALL_PREFIXES(SiteSettingsHandlerTest, SessionOnlyException); FRIEND_TEST_ALL_PREFIXES(SiteSettingsHandlerTest, ZoomLevels); + FRIEND_TEST_ALL_PREFIXES(SiteSettingsHandlerTest, + HandleClearEtldPlus1DataAndCookies); // Creates the CookiesTreeModel if necessary. void EnsureCookiesTreeModelCreated();
diff --git a/chrome/browser/ui/webui/settings/site_settings_handler_unittest.cc b/chrome/browser/ui/webui/settings/site_settings_handler_unittest.cc index 4a5140b..b1401658 100644 --- a/chrome/browser/ui/webui/settings/site_settings_handler_unittest.cc +++ b/chrome/browser/ui/webui/settings/site_settings_handler_unittest.cc
@@ -385,6 +385,71 @@ incognito_profile_ = nullptr; } + // TODO(https://crbug.com/835712): Currently only set up the cookies and local + // storage nodes, will update all other nodes in the future. + void SetUpCookiesTreeModel() { + scoped_refptr<MockBrowsingDataCookieHelper> + mock_browsing_data_cookie_helper; + scoped_refptr<MockBrowsingDataLocalStorageHelper> + mock_browsing_data_local_storage_helper; + + mock_browsing_data_cookie_helper = + new MockBrowsingDataCookieHelper(profile()); + mock_browsing_data_local_storage_helper = + new MockBrowsingDataLocalStorageHelper(profile()); + + auto container = std::make_unique<LocalDataContainer>( + mock_browsing_data_cookie_helper, + /*database_helper=*/nullptr, mock_browsing_data_local_storage_helper, + /*session_storage_helper=*/nullptr, + /*appcache_helper=*/nullptr, + /*indexed_db_helper=*/nullptr, + /*file_system_helper=*/nullptr, + /*quota_helper=*/nullptr, + /*service_worker_helper=*/nullptr, + /*data_shared_worker_helper=*/nullptr, + /*cache_storage_helper=*/nullptr, + /*flash_lso_helper=*/nullptr, + /*media_license_helper=*/nullptr); + auto mock_cookies_tree_model = std::make_unique<CookiesTreeModel>( + std::move(container), profile()->GetExtensionSpecialStoragePolicy()); + + mock_browsing_data_local_storage_helper->AddLocalStorageForOrigin( + GURL("https://www.example.com/"), 2); + + mock_browsing_data_local_storage_helper->AddLocalStorageForOrigin( + GURL("https://www.google.com/"), 5); + mock_browsing_data_local_storage_helper->Notify(); + + mock_browsing_data_cookie_helper->AddCookieSamples( + GURL("http://example.com"), "A=1"); + mock_browsing_data_cookie_helper->AddCookieSamples( + GURL("http://www.example.com/"), "B=1"); + mock_browsing_data_cookie_helper->AddCookieSamples( + GURL("http://abc.example.com"), "C=1"); + mock_browsing_data_cookie_helper->AddCookieSamples( + GURL("http://google.com"), "A=1"); + mock_browsing_data_cookie_helper->AddCookieSamples( + GURL("http://google.com"), "B=1"); + mock_browsing_data_cookie_helper->AddCookieSamples( + GURL("http://google.com.au"), "A=1"); + mock_browsing_data_cookie_helper->Notify(); + + handler()->SetCookiesTreeModelForTesting( + std::move(mock_cookies_tree_model)); + } + + const base::ListValue* GetOnStorageFetchedSentListValue() { + handler()->ClearAllSitesMapForTesting(); + handler()->OnStorageFetched(); + const content::TestWebUI::CallData& data = *web_ui()->call_data().back(); + std::string callback_id; + data.arg1()->GetAsString(&callback_id); + const base::ListValue* storage_and_cookie_list; + data.arg2()->GetAsList(&storage_and_cookie_list); + return storage_and_cookie_list; + } + // Content setting group name for the relevant ContentSettingsType. const std::string kNotifications; const std::string kCookies; @@ -618,55 +683,9 @@ run_loop.RunUntilIdle(); } -// TODO(https://crbug.com/835712): Currently only set up the cookies and local -// storage nodes, will update all other nodes in the future. TEST_F(SiteSettingsHandlerTest, OnStorageFetched) { - scoped_refptr<MockBrowsingDataCookieHelper> mock_browsing_data_cookie_helper; - scoped_refptr<MockBrowsingDataLocalStorageHelper> - mock_browsing_data_local_storage_helper; + SetUpCookiesTreeModel(); - mock_browsing_data_cookie_helper = - new MockBrowsingDataCookieHelper(profile()); - mock_browsing_data_local_storage_helper = - new MockBrowsingDataLocalStorageHelper(profile()); - - auto container = std::make_unique<LocalDataContainer>( - mock_browsing_data_cookie_helper, - /*database_helper=*/nullptr, mock_browsing_data_local_storage_helper, - /*session_storage_helper=*/nullptr, - /*appcache_helper=*/nullptr, - /*indexed_db_helper=*/nullptr, - /*file_system_helper=*/nullptr, - /*quota_helper=*/nullptr, - /*service_worker_helper=*/nullptr, - /*data_shared_worker_helper=*/nullptr, - /*cache_storage_helper=*/nullptr, - /*flash_lso_helper=*/nullptr, - /*media_license_helper=*/nullptr); - auto mock_cookies_tree_model = std::make_unique<CookiesTreeModel>( - std::move(container), profile()->GetExtensionSpecialStoragePolicy()); - - mock_browsing_data_local_storage_helper->AddLocalStorageForOrigin( - GURL("https://www.example.com/"), 2); - mock_browsing_data_local_storage_helper->AddLocalStorageForOrigin( - GURL("https://www.google.com/"), 5); - mock_browsing_data_local_storage_helper->Notify(); - - mock_browsing_data_cookie_helper->AddCookieSamples(GURL("http://example.com"), - "A=1"); - mock_browsing_data_cookie_helper->AddCookieSamples( - GURL("http://www.example.com/"), "B=1"); - mock_browsing_data_cookie_helper->AddCookieSamples( - GURL("http://abc.example.com"), "C=1"); - mock_browsing_data_cookie_helper->AddCookieSamples(GURL("http://google.com"), - "A=1"); - mock_browsing_data_cookie_helper->AddCookieSamples(GURL("http://google.com"), - "B=1"); - mock_browsing_data_cookie_helper->AddCookieSamples( - GURL("http://google.com.au"), "A=1"); - mock_browsing_data_cookie_helper->Notify(); - - handler()->SetCookiesTreeModelForTesting(std::move(mock_cookies_tree_model)); handler()->ClearAllSitesMapForTesting(); handler()->OnStorageFetched(); @@ -1678,4 +1697,52 @@ } } +TEST_F(SiteSettingsHandlerTest, HandleClearEtldPlus1DataAndCookies) { + SetUpCookiesTreeModel(); + + EXPECT_EQ(22, handler()->cookies_tree_model_->GetRoot()->GetTotalNodeCount()); + + const base::ListValue* storage_and_cookie_list = + GetOnStorageFetchedSentListValue(); + EXPECT_EQ(3U, storage_and_cookie_list->GetSize()); + const base::DictionaryValue* site_group; + ASSERT_TRUE(storage_and_cookie_list->GetDictionary(0, &site_group)); + std::string etld_plus1_string; + ASSERT_TRUE(site_group->GetString("etldPlus1", &etld_plus1_string)); + ASSERT_EQ("example.com", etld_plus1_string); + + base::ListValue args; + args.AppendString("example.com"); + handler()->HandleClearEtldPlus1DataAndCookies(&args); + EXPECT_EQ(11, handler()->cookies_tree_model_->GetRoot()->GetTotalNodeCount()); + + storage_and_cookie_list = GetOnStorageFetchedSentListValue(); + EXPECT_EQ(2U, storage_and_cookie_list->GetSize()); + ASSERT_TRUE(storage_and_cookie_list->GetDictionary(0, &site_group)); + ASSERT_TRUE(site_group->GetString("etldPlus1", &etld_plus1_string)); + ASSERT_EQ("google.com", etld_plus1_string); + + args.Clear(); + args.AppendString("google.com"); + + handler()->HandleClearEtldPlus1DataAndCookies(&args); + + EXPECT_EQ(4, handler()->cookies_tree_model_->GetRoot()->GetTotalNodeCount()); + + storage_and_cookie_list = GetOnStorageFetchedSentListValue(); + EXPECT_EQ(1U, storage_and_cookie_list->GetSize()); + ASSERT_TRUE(storage_and_cookie_list->GetDictionary(0, &site_group)); + ASSERT_TRUE(site_group->GetString("etldPlus1", &etld_plus1_string)); + ASSERT_EQ("google.com.au", etld_plus1_string); + + args.Clear(); + args.AppendString("google.com.au"); + + handler()->HandleClearEtldPlus1DataAndCookies(&args); + + EXPECT_EQ(1, handler()->cookies_tree_model_->GetRoot()->GetTotalNodeCount()); + + storage_and_cookie_list = GetOnStorageFetchedSentListValue(); + EXPECT_EQ(0U, storage_and_cookie_list->GetSize()); +} } // namespace settings
diff --git a/chrome/browser/vr/browser_ui_interface.h b/chrome/browser/vr/browser_ui_interface.h index 67dd786..b82d0ee 100644 --- a/chrome/browser/vr/browser_ui_interface.h +++ b/chrome/browser/vr/browser_ui_interface.h
@@ -46,6 +46,8 @@ const CapturingStateModel& potential_capturing) = 0; virtual void ShowExitVrPrompt(UiUnsupportedMode reason) = 0; virtual void SetSpeechRecognitionEnabled(bool enabled) = 0; + virtual void SetHasOrCanRequestRecordAudioPermission( + bool has_or_can_request_record_audio) = 0; virtual void SetRecognitionResult(const base::string16& result) = 0; virtual void OnSpeechRecognitionStateChanged(int new_state) = 0; virtual void SetOmniboxSuggestions(
diff --git a/chrome/browser/vr/model/model.cc b/chrome/browser/vr/model/model.cc index 018234d..53700cda 100644 --- a/chrome/browser/vr/model/model.cc +++ b/chrome/browser/vr/model/model.cc
@@ -95,7 +95,12 @@ return get_last_opaque_mode() == kModeBrowsing; } -bool Model::voice_search_enabled() const { +bool Model::voice_search_available() const { + return speech.has_or_can_request_record_audio_permission && !incognito && + !active_capturing.audio_capture_enabled; +} + +bool Model::voice_search_active() const { return get_last_opaque_mode() == kModeVoiceSearch; }
diff --git a/chrome/browser/vr/model/model.h b/chrome/browser/vr/model/model.h index 3a0917f..4a04fbe4 100644 --- a/chrome/browser/vr/model/model.h +++ b/chrome/browser/vr/model/model.h
@@ -73,7 +73,8 @@ bool has_mode_in_stack(UiMode mode) const; bool browsing_enabled() const; bool default_browsing_enabled() const; - bool voice_search_enabled() const; + bool voice_search_available() const; + bool voice_search_active() const; bool omnibox_editing_enabled() const; bool editing_enabled() const; bool fullscreen_enabled() const;
diff --git a/chrome/browser/vr/model/speech_recognition_model.h b/chrome/browser/vr/model/speech_recognition_model.h index 88b86b9..603017f8e 100644 --- a/chrome/browser/vr/model/speech_recognition_model.h +++ b/chrome/browser/vr/model/speech_recognition_model.h
@@ -12,7 +12,7 @@ struct VR_BASE_EXPORT SpeechRecognitionModel { int speech_recognition_state = 0; - bool has_or_can_request_audio_permission = true; + bool has_or_can_request_record_audio_permission = true; base::string16 recognition_result; };
diff --git a/chrome/browser/vr/test/mock_browser_ui_interface.h b/chrome/browser/vr/test/mock_browser_ui_interface.h index d313d816..8fdc301 100644 --- a/chrome/browser/vr/test/mock_browser_ui_interface.h +++ b/chrome/browser/vr/test/mock_browser_ui_interface.h
@@ -35,6 +35,8 @@ const CapturingStateModel& potential_state)); MOCK_METHOD1(ShowExitVrPrompt, void(UiUnsupportedMode reason)); MOCK_METHOD1(SetSpeechRecognitionEnabled, void(bool enabled)); + MOCK_METHOD1(SetHasOrCanRequestRecordAudioPermission, + void(bool has_or_can_request_record_audio_permission)); MOCK_METHOD1(SetRecognitionResult, void(const base::string16& result)); MOCK_METHOD1(OnSpeechRecognitionStateChanged, void(int new_state)); void SetOmniboxSuggestions(
diff --git a/chrome/browser/vr/testapp/vr_test_context.cc b/chrome/browser/vr/testapp/vr_test_context.cc index d22a69a..2edaa97b 100644 --- a/chrome/browser/vr/testapp/vr_test_context.cc +++ b/chrome/browser/vr/testapp/vr_test_context.cc
@@ -482,7 +482,7 @@ } void VrTestContext::CreateFakeVoiceSearchResult() { - if (!model_->voice_search_enabled()) + if (!model_->voice_search_active()) return; auto browser_ui = ui_->GetBrowserUiWeakPtr(); browser_ui->SetRecognitionResult(
diff --git a/chrome/browser/vr/ui.cc b/chrome/browser/vr/ui.cc index e641fc8..2949577 100644 --- a/chrome/browser/vr/ui.cc +++ b/chrome/browser/vr/ui.cc
@@ -284,6 +284,12 @@ model_->speech.recognition_result = result; } +void Ui::SetHasOrCanRequestRecordAudioPermission( + bool const has_or_can_request_record_audio) { + model_->speech.has_or_can_request_record_audio_permission = + has_or_can_request_record_audio; +} + void Ui::OnSpeechRecognitionStateChanged(int new_state) { model_->speech.speech_recognition_state = new_state; } @@ -578,8 +584,8 @@ } void Ui::InitializeModel(const UiInitialState& ui_initial_state) { - model_->speech.has_or_can_request_audio_permission = - ui_initial_state.has_or_can_request_audio_permission; + model_->speech.has_or_can_request_record_audio_permission = + ui_initial_state.has_or_can_request_record_audio_permission; model_->ui_modes.clear(); model_->push_mode(kModeBrowsing); if (ui_initial_state.in_web_vr) {
diff --git a/chrome/browser/vr/ui.h b/chrome/browser/vr/ui.h index 8f9ee44..e3a12fc 100644 --- a/chrome/browser/vr/ui.h +++ b/chrome/browser/vr/ui.h
@@ -102,6 +102,8 @@ void ShowExitVrPrompt(UiUnsupportedMode reason) override; void SetSpeechRecognitionEnabled(bool enabled) override; void SetRecognitionResult(const base::string16& result) override; + void SetHasOrCanRequestRecordAudioPermission( + bool has_or_can_request_record_audio) override; void OnSpeechRecognitionStateChanged(int new_state) override; void SetOmniboxSuggestions( std::unique_ptr<OmniboxSuggestions> suggestions) override;
diff --git a/chrome/browser/vr/ui_initial_state.h b/chrome/browser/vr/ui_initial_state.h index 2f64f894..377acf12 100644 --- a/chrome/browser/vr/ui_initial_state.h +++ b/chrome/browser/vr/ui_initial_state.h
@@ -17,7 +17,7 @@ bool in_web_vr = false; bool web_vr_autopresentation_expected = false; bool browsing_disabled = false; - bool has_or_can_request_audio_permission = true; + bool has_or_can_request_record_audio_permission = true; bool assets_supported = false; bool supports_selection = true; bool needs_keyboard_update = false;
diff --git a/chrome/browser/vr/ui_scene_creator.cc b/chrome/browser/vr/ui_scene_creator.cc index 88bb156..a6875eb 100644 --- a/chrome/browser/vr/ui_scene_creator.cc +++ b/chrome/browser/vr/ui_scene_creator.cc
@@ -627,7 +627,7 @@ l10n_util::GetStringUTF16(IDS_VR_BUTTON_BACK), model, element_binding); back_button_label->AddBinding(VR_BIND_FUNC( bool, Model, model, - model->omnibox_editing_enabled() || model->voice_search_enabled(), + model->omnibox_editing_enabled() || model->voice_search_active(), UiElement, back_button_label.get(), SetVisible)); callout_group->AddChild(std::move(back_button_label)); @@ -1731,7 +1731,7 @@ speech_recognition_root->SetTransitionDuration( base::TimeDelta::FromMilliseconds( kSpeechRecognitionOpacityAnimationDurationMs)); - VR_BIND_VISIBILITY(speech_recognition_root, model->voice_search_enabled()); + VR_BIND_VISIBILITY(speech_recognition_root, model->voice_search_active()); auto inner_circle = std::make_unique<Rect>(); inner_circle->SetName(kSpeechRecognitionCircle); @@ -2427,12 +2427,7 @@ // TODO(crbug.com/834308): Refactor this element to be resized by a // fixed-width layout, rather than adjusting based on other elements. omnibox_text_field->AddBinding(std::make_unique<Binding<bool>>( - VR_BIND_LAMBDA( - [](Model* m) { - return m->speech.has_or_can_request_audio_permission && - !m->incognito && !m->active_capturing.audio_capture_enabled; - }, - base::Unretained(model_)), + VR_BIND_LAMBDA(&Model::voice_search_available, base::Unretained(model_)), VR_BIND_LAMBDA( [](TextInput* e, const bool& mic_button_visible) { float width = kOmniboxWidthDMM - 2 * kOmniboxTextMarginDMM; @@ -2537,19 +2532,13 @@ mic_button->SetIconScaleFactor(kUrlBarButtonIconScaleFactor); mic_button->set_hover_offset(kUrlBarButtonHoverOffsetDMM); mic_button->set_corner_radius(kUrlBarItemCornerRadiusDMM); - VR_BIND_VISIBILITY(mic_button, - model->speech.has_or_can_request_audio_permission && - !model->incognito && - !model->active_capturing.audio_capture_enabled); + VR_BIND_VISIBILITY(mic_button, model->voice_search_available()); VR_BIND_BUTTON_COLORS(model_, mic_button.get(), &ColorScheme::url_bar_button, &Button::SetButtonColors); auto mic_button_spacer = CreateSpacer(kOmniboxMicIconRightMarginDMM, kOmniboxHeightDMM); - VR_BIND_VISIBILITY(mic_button_spacer, - model->speech.has_or_can_request_audio_permission && - !model->incognito && - !model->active_capturing.audio_capture_enabled); + VR_BIND_VISIBILITY(mic_button_spacer, model->voice_search_available()); auto text_field_layout = Create<LinearLayout>( kOmniboxTextFieldLayout, kPhaseNone, LinearLayout::kRight);
diff --git a/chrome/browser/vr/ui_unittest.cc b/chrome/browser/vr/ui_unittest.cc index cef39127..3c2c2d25 100644 --- a/chrome/browser/vr/ui_unittest.cc +++ b/chrome/browser/vr/ui_unittest.cc
@@ -293,11 +293,11 @@ CreateScene(kNotInWebVr); model_->push_mode(kModeEditingOmnibox); - model_->speech.has_or_can_request_audio_permission = true; + model_->speech.has_or_can_request_record_audio_permission = true; EXPECT_TRUE(OnBeginFrame()); EXPECT_TRUE(IsVisible(kOmniboxVoiceSearchButton)); - model_->speech.has_or_can_request_audio_permission = false; + model_->speech.has_or_can_request_record_audio_permission = false; EXPECT_TRUE(OnBeginFrame()); EXPECT_FALSE(IsVisible(kOmniboxVoiceSearchButton)); } @@ -306,7 +306,7 @@ CreateScene(kNotInWebVr); model_->push_mode(kModeEditingOmnibox); - model_->speech.has_or_can_request_audio_permission = true; + model_->speech.has_or_can_request_record_audio_permission = true; model_->active_capturing.audio_capture_enabled = false; EXPECT_TRUE(OnBeginFrame()); EXPECT_TRUE(IsVisible(kOmniboxVoiceSearchButton));
diff --git a/chrome/browser/web_applications/web_app_provider_factory.cc b/chrome/browser/web_applications/web_app_provider_factory.cc index 5be01cf3..d17cd91b 100644 --- a/chrome/browser/web_applications/web_app_provider_factory.cc +++ b/chrome/browser/web_applications/web_app_provider_factory.cc
@@ -47,4 +47,10 @@ return true; } +content::BrowserContext* WebAppProviderFactory::GetBrowserContextToUse( + content::BrowserContext* context) const { + Profile* profile = Profile::FromBrowserContext(context); + return profile ? profile->GetOriginalProfile() : nullptr; +} + } // namespace web_app
diff --git a/chrome/browser/web_applications/web_app_provider_factory.h b/chrome/browser/web_applications/web_app_provider_factory.h index d2de433..ec7dc86 100644 --- a/chrome/browser/web_applications/web_app_provider_factory.h +++ b/chrome/browser/web_applications/web_app_provider_factory.h
@@ -37,6 +37,8 @@ KeyedService* BuildServiceInstanceFor( content::BrowserContext* context) const override; bool ServiceIsCreatedWithBrowserContext() const override; + content::BrowserContext* GetBrowserContextToUse( + content::BrowserContext* context) const override; DISALLOW_COPY_AND_ASSIGN(WebAppProviderFactory); };
diff --git a/chrome/chrome_cleaner/chrome_utils/BUILD.gn b/chrome/chrome_cleaner/chrome_utils/BUILD.gn index f7a99c0..85d9bf2 100644 --- a/chrome/chrome_cleaner/chrome_utils/BUILD.gn +++ b/chrome/chrome_cleaner/chrome_utils/BUILD.gn
@@ -45,17 +45,31 @@ ] } +source_set("extension_file_logger_lib") { + sources = [ + "extension_file_logger.cc", + "extension_file_logger.h", + ] + deps = [ + "//base:base", + "//chrome/chrome_cleaner/os:common_os", + ] +} + source_set("unittest_sources") { testonly = true sources = [ + "extension_file_logger_unittest.cc", "extensions_util_unittest.cc", ] deps = [ + ":extension_file_logger_lib", ":extensions_util_lib", "//base:base", "//base/test:test_support", + "//chrome/chrome_cleaner/os:common_os", "//chrome/chrome_cleaner/parsers/json_parser", "//chrome/chrome_cleaner/test:test_extensions", "//chrome/chrome_cleaner/test:test_util",
diff --git a/chrome/chrome_cleaner/chrome_utils/extension_file_logger.cc b/chrome/chrome_cleaner/chrome_utils/extension_file_logger.cc new file mode 100644 index 0000000..0d819fa5 --- /dev/null +++ b/chrome/chrome_cleaner/chrome_utils/extension_file_logger.cc
@@ -0,0 +1,99 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/chrome_cleaner/chrome_utils/extension_file_logger.h" + +#include "base/files/file_enumerator.h" +#include "base/files/file_util.h" +#include "base/path_service.h" +#include "chrome/chrome_cleaner/os/pre_fetched_paths.h" + +namespace chrome_cleaner { +namespace { + +void LogFilesInPath(const base::FilePath& path, + std::vector<internal::FileInformation>* files) { + if (!base::PathExists(path)) + return; + base::FileEnumerator file_enumerator(path, /*recursive=*/true, + base::FileEnumerator::FileType::FILES); + base::FilePath file_path = file_enumerator.Next(); + while (!file_path.empty()) { + internal::FileInformation file_information; + if (RetrieveFileInformation(file_path, /*include_details=*/true, + &file_information)) { + files->push_back(file_information); + } + + file_path = file_enumerator.Next(); + } +} + +} // namespace + +ExtensionFileLogger::ExtensionFileLogger(const base::FilePath& user_data_path) + : user_data_path_(user_data_path) {} + +ExtensionFileLogger::~ExtensionFileLogger() = default; + +bool ExtensionFileLogger::GetExtensionFiles( + const base::string16& extension_id, + std::vector<internal::FileInformation>* files) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + if (!initialized_) + CacheProfilesAndExtensions(); + + bool extension_found = false; + + for (auto it = installed_extensions_.begin(); + it != installed_extensions_.end(); it++) { + if (it->second.find(extension_id) != it->second.end()) { + extension_found = true; + LogFilesInPath(it->first.Append(extension_id), files); + } + } + + return extension_found; +} + +void ExtensionFileLogger::CacheExtensionIdsInProfile( + const base::FilePath& profile_path) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + base::FilePath profile_extensions_path = profile_path.Append(L"Extensions"); + if (!base::PathExists(profile_extensions_path)) + return; + + base::FileEnumerator file_enumerator( + profile_extensions_path, /*recursive=*/false, + base::FileEnumerator::FileType::DIRECTORIES); + + base::FilePath extension_path = file_enumerator.Next(); + + while (!extension_path.empty()) { + installed_extensions_[profile_extensions_path].insert( + extension_path.BaseName().value()); + extension_path = file_enumerator.Next(); + } +} + +void ExtensionFileLogger::CacheProfilesAndExtensions() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + installed_extensions_.clear(); + + // Check all the directories, if one is not a profile then + // CacheExtensionIdsInProfile will return right away because there will + // be no Extensions folder. + base::FileEnumerator file_enumerator( + user_data_path_, /*recursive=*/false, + base::FileEnumerator::FileType::DIRECTORIES); + base::FilePath profile_path = file_enumerator.Next(); + + while (!profile_path.empty()) { + CacheExtensionIdsInProfile(profile_path); + profile_path = file_enumerator.Next(); + } + initialized_ = true; +} + +} // namespace chrome_cleaner
diff --git a/chrome/chrome_cleaner/chrome_utils/extension_file_logger.h b/chrome/chrome_cleaner/chrome_utils/extension_file_logger.h new file mode 100644 index 0000000..068e260 --- /dev/null +++ b/chrome/chrome_cleaner/chrome_utils/extension_file_logger.h
@@ -0,0 +1,55 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_CHROME_CLEANER_CHROME_UTILS_EXTENSION_FILE_LOGGER_H_ +#define CHROME_CHROME_CLEANER_CHROME_UTILS_EXTENSION_FILE_LOGGER_H_ + +#include <map> +#include <set> +#include <vector> + +#include "base/files/file_path.h" +#include "base/sequence_checker.h" +#include "base/strings/string16.h" +#include "chrome/chrome_cleaner/os/disk_util.h" + +namespace chrome_cleaner { + +typedef std::map<base::FilePath, std::set<base::string16>> + ExtensionsInProfilesMap; + +// Utility class to extract the file information of all the files of a given +// extension. +// +// Please note that this class may have negative performance implications if +// used in more than one place, please avoid creating multiple instances of it. +class ExtensionFileLogger { + public: + explicit ExtensionFileLogger(const base::FilePath& user_data_path); + ~ExtensionFileLogger(); + + // Searches through all of the cached user's profiles for an extension with + // id |extension_id|. If one found, fills |files| with data about the + // extension's files. + // Returns false if it cannot find the extension folder. + // + // If two profiles have the same extension installed, both extension's files + // are going to be logged. This is intended since we are not sure if there + // are modified files in one of the extensions. + bool GetExtensionFiles(const base::string16& extension_id, + std::vector<internal::FileInformation>* files); + + private: + void CacheProfilesAndExtensions(); + void CacheExtensionIdsInProfile(const base::FilePath& profile_path); + + ExtensionsInProfilesMap installed_extensions_; + base::FilePath user_data_path_; + bool initialized_ = false; + SEQUENCE_CHECKER(sequence_checker_); +}; + +} // namespace chrome_cleaner + +#endif // CHROME_CHROME_CLEANER_CHROME_UTILS_EXTENSION_FILE_LOGGER_H_
diff --git a/chrome/chrome_cleaner/chrome_utils/extension_file_logger_unittest.cc b/chrome/chrome_cleaner/chrome_utils/extension_file_logger_unittest.cc new file mode 100644 index 0000000..712b01f5 --- /dev/null +++ b/chrome/chrome_cleaner/chrome_utils/extension_file_logger_unittest.cc
@@ -0,0 +1,159 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/chrome_cleaner/chrome_utils/extension_file_logger.h" + +#include <vector> + +#include "base/files/file.h" +#include "base/files/file_util.h" +#include "base/files/scoped_temp_dir.h" +#include "base/strings/string16.h" +#include "chrome/chrome_cleaner/os/disk_util.h" +#include "chrome/chrome_cleaner/test/test_extensions.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace chrome_cleaner { + +namespace { + +const base::char16 kExtensionId1[] = L"extension1"; +const base::char16 kTestFileName1[] = L"file1.file"; + +const base::char16 kExtensionId2[] = L"extension2"; +const base::char16 kTestFileName2[] = L"file2.file"; + +const base::char16 kExtensionId3[] = L"extension3"; +const base::char16 kTestFileName3[] = L"file3.file"; + +const base::char16 kExtensionId4[] = L"generic-extension-name"; + +const base::char16 kExtensionId5[] = L"ghost-extension"; + +} // namespace + +class ExtensionFileLoggerTest : public testing::Test { + public: + void SetUp() override { + ASSERT_TRUE(fake_user_data_dir_.CreateUniqueTempDir()); + + ASSERT_TRUE(CreateProfileWithExtensionAndFiles( + fake_user_data_dir_.GetPath().Append(L"Default"), kExtensionId1, + {kTestFileName1})); + + ASSERT_TRUE(CreateProfileWithExtensionAndFiles( + fake_user_data_dir_.GetPath().Append(L"Profile 1"), kExtensionId2, + {kTestFileName2})); + + ASSERT_TRUE(CreateProfileWithExtensionAndFiles( + fake_user_data_dir_.GetPath().Append(L"Profile 2"), kExtensionId3, + {kTestFileName3})); + + ASSERT_TRUE(CreateProfileWithExtensionAndFiles( + fake_user_data_dir_.GetPath().Append(L"Not Malicious"), kExtensionId3, + {kTestFileName3})); + + ASSERT_TRUE(CreateProfileWithExtensionAndFiles( + fake_user_data_dir_.GetPath().Append(L"Profile N"), kExtensionId4, + {kTestFileName1, kTestFileName2, kTestFileName3})); + + ASSERT_TRUE(CreateProfileWithExtensionAndFiles( + fake_user_data_dir_.GetPath().Append(L"Directory"), kExtensionId5, {})); + + base::FilePath profile_without_extensions_folder = + fake_user_data_dir_.GetPath().Append(L"another dir"); + ASSERT_TRUE(base::CreateDirectory(profile_without_extensions_folder)); + + base::FilePath folder_not_named_extensions = + profile_without_extensions_folder.Append(L"something"); + ASSERT_TRUE(base::CreateDirectory(folder_not_named_extensions)); + + base::FilePath extension_path = + folder_not_named_extensions.Append(kExtensionId1); + ASSERT_TRUE(base::CreateDirectory(extension_path)); + + base::File extension_file( + extension_path.Append(kTestFileName1), + base::File::Flags::FLAG_CREATE | base::File::Flags::FLAG_READ); + + ASSERT_TRUE(extension_file.IsValid()); + + file_logger_ = + std::make_unique<ExtensionFileLogger>(fake_user_data_dir_.GetPath()); + } + + protected: + base::ScopedTempDir fake_user_data_dir_; + + std::unique_ptr<ExtensionFileLogger> file_logger_; +}; + +TEST_F(ExtensionFileLoggerTest, LogExtensionOnDefaultProfile) { + std::vector<internal::FileInformation> logged_files; + + EXPECT_TRUE(file_logger_->GetExtensionFiles(kExtensionId1, &logged_files)); + + ASSERT_EQ(logged_files.size(), 1u); + EXPECT_EQ(base::FilePath(logged_files[0].path).BaseName().value(), + kTestFileName1); +} + +TEST_F(ExtensionFileLoggerTest, LogMultipleExtensions) { + std::vector<internal::FileInformation> logged_files; + + EXPECT_TRUE(file_logger_->GetExtensionFiles(kExtensionId1, &logged_files)); + EXPECT_TRUE(file_logger_->GetExtensionFiles(kExtensionId2, &logged_files)); + + ASSERT_EQ(logged_files.size(), 2u); + + EXPECT_EQ(base::FilePath(logged_files[0].path).BaseName().value(), + kTestFileName1); + EXPECT_EQ(base::FilePath(logged_files[1].path).BaseName().value(), + kTestFileName2); +} + +TEST_F(ExtensionFileLoggerTest, LogExtensionOnTwoProfiles) { + std::vector<internal::FileInformation> logged_files; + + EXPECT_TRUE(file_logger_->GetExtensionFiles(kExtensionId3, &logged_files)); + + ASSERT_EQ(logged_files.size(), 2u); + + EXPECT_EQ(base::FilePath(logged_files[0].path).BaseName().value(), + kTestFileName3); + EXPECT_EQ(base::FilePath(logged_files[1].path).BaseName().value(), + kTestFileName3); +} + +TEST_F(ExtensionFileLoggerTest, DoNotLogNonExistingExtension) { + std::vector<internal::FileInformation> logged_files; + + EXPECT_FALSE( + file_logger_->GetExtensionFiles(L"RandomExtension", &logged_files)); +} + +TEST_F(ExtensionFileLoggerTest, LogExtensionWithMultipleFiles) { + std::vector<internal::FileInformation> logged_files; + + EXPECT_TRUE(file_logger_->GetExtensionFiles(kExtensionId4, &logged_files)); + + ASSERT_EQ(logged_files.size(), 3u); + + std::vector<base::string16> returned_paths = { + base::FilePath(logged_files[0].path).BaseName().value(), + base::FilePath(logged_files[1].path).BaseName().value(), + base::FilePath(logged_files[2].path).BaseName().value()}; + EXPECT_THAT(returned_paths, + testing::UnorderedElementsAreArray( + {kTestFileName1, kTestFileName2, kTestFileName3})); +} + +TEST_F(ExtensionFileLoggerTest, LogExtensionWithoutFiles) { + std::vector<internal::FileInformation> logged_files; + EXPECT_TRUE(file_logger_->GetExtensionFiles(kExtensionId5, &logged_files)); + EXPECT_EQ(logged_files.size(), 0u); +} + +} // namespace chrome_cleaner
diff --git a/chrome/chrome_cleaner/components/BUILD.gn b/chrome/chrome_cleaner/components/BUILD.gn index 422e53f9..0d277f0 100644 --- a/chrome/chrome_cleaner/components/BUILD.gn +++ b/chrome/chrome_cleaner/components/BUILD.gn
@@ -20,6 +20,7 @@ deps = [ "//base:base", "//chrome/chrome_cleaner/chrome_utils:chrome_util_lib", + "//chrome/chrome_cleaner/chrome_utils:extension_file_logger_lib", "//chrome/chrome_cleaner/chrome_utils:extensions_util_lib", "//chrome/chrome_cleaner/constants:common_strings", "//chrome/chrome_cleaner/constants:uws_id", @@ -55,6 +56,7 @@ "//base", "//base/test:test_support", "//chrome/chrome_cleaner/chrome_utils:chrome_util_lib", + "//chrome/chrome_cleaner/chrome_utils:extension_file_logger_lib", "//chrome/chrome_cleaner/constants:common_strings", "//chrome/chrome_cleaner/constants:uws_id", "//chrome/chrome_cleaner/http:mock_http_agent_factory", @@ -65,6 +67,7 @@ "//chrome/chrome_cleaner/parsers/json_parser", "//chrome/chrome_cleaner/test:test_branding_header", "//chrome/chrome_cleaner/test:test_component", + "//chrome/chrome_cleaner/test:test_extensions", "//chrome/chrome_cleaner/test:test_pup_data", "//chrome/chrome_cleaner/test:test_util", "//components/chrome_cleaner/public/constants",
diff --git a/chrome/chrome_cleaner/components/system_report_component.cc b/chrome/chrome_cleaner/components/system_report_component.cc index fcdb5e8..de3b39df 100644 --- a/chrome/chrome_cleaner/components/system_report_component.cc +++ b/chrome/chrome_cleaner/components/system_report_component.cc
@@ -41,6 +41,7 @@ #include "base/win/scoped_variant.h" #include "base/win/windows_version.h" #include "chrome/chrome_cleaner/chrome_utils/chrome_util.h" +#include "chrome/chrome_cleaner/chrome_utils/extension_file_logger.h" #include "chrome/chrome_cleaner/chrome_utils/extensions_util.h" #include "chrome/chrome_cleaner/constants/chrome_cleaner_switches.h" #include "chrome/chrome_cleaner/constants/common_registry_names.h" @@ -683,18 +684,23 @@ } } -void ReportForcelistExtensions() { +void ReportForcelistExtensions(ExtensionFileLogger* extension_file_logger) { std::vector<ExtensionPolicyRegistryEntry> policies; GetExtensionForcelistRegistryPolicies(&policies); for (const ExtensionPolicyRegistryEntry& policy : policies) { + std::vector<internal::FileInformation> extension_files; + extension_file_logger->GetExtensionFiles(policy.extension_id, + &extension_files); + LoggingServiceAPI::GetInstance()->AddInstalledExtension( - policy.extension_id, - ExtensionInstallMethod::POLICY_EXTENSION_FORCELIST); + policy.extension_id, ExtensionInstallMethod::POLICY_EXTENSION_FORCELIST, + extension_files); } } -void ReportInstalledExtensions(JsonParserAPI* json_parser) { +void ReportInstalledExtensions(JsonParserAPI* json_parser, + ExtensionFileLogger* extension_file_logger) { DCHECK(json_parser); // TODO(proberge): Temporarily allowing syncing to avoid crashes in debug // mode. This isn't catastrophic since the cleanup tool doesn't have a UI and @@ -702,7 +708,7 @@ base::ScopedBlockingCall scoped_blocking_call(base::BlockingType::MAY_BLOCK); base::ScopedAllowBaseSyncPrimitivesForTesting allow_sync; - ReportForcelistExtensions(); + ReportForcelistExtensions(extension_file_logger); std::vector<ExtensionPolicyRegistryEntry> extension_settings_policies; WaitableEvent extension_settings_done( @@ -734,23 +740,46 @@ default_extensions_done.TimedWaitUntil(end_time); // Log extensions that were found - for (const ExtensionPolicyRegistryEntry& policy : extension_settings_policies) - LoggingServiceAPI::GetInstance()->AddInstalledExtension( - policy.extension_id, ExtensionInstallMethod::POLICY_EXTENSION_SETTINGS); + for (const ExtensionPolicyRegistryEntry& policy : + extension_settings_policies) { + std::vector<internal::FileInformation> extension_files; + extension_file_logger->GetExtensionFiles(policy.extension_id, + &extension_files); - for (const ExtensionPolicyFile& policy : master_preferences_policies) LoggingServiceAPI::GetInstance()->AddInstalledExtension( - policy.extension_id, ExtensionInstallMethod::POLICY_MASTER_PREFERENCES); + policy.extension_id, ExtensionInstallMethod::POLICY_EXTENSION_SETTINGS, + extension_files); + } - for (const ExtensionPolicyFile& policy : default_extension_policies) + for (const ExtensionPolicyFile& policy : master_preferences_policies) { + std::vector<internal::FileInformation> extension_files; + extension_file_logger->GetExtensionFiles(policy.extension_id, + &extension_files); + LoggingServiceAPI::GetInstance()->AddInstalledExtension( - policy.extension_id, ExtensionInstallMethod::DEFAULT_APPS_EXTENSION); + policy.extension_id, ExtensionInstallMethod::POLICY_MASTER_PREFERENCES, + extension_files); + } + + for (const ExtensionPolicyFile& policy : default_extension_policies) { + std::vector<internal::FileInformation> extension_files; + extension_file_logger->GetExtensionFiles(policy.extension_id, + &extension_files); + + LoggingServiceAPI::GetInstance()->AddInstalledExtension( + policy.extension_id, ExtensionInstallMethod::DEFAULT_APPS_EXTENSION, + extension_files); + } } } // namespace SystemReportComponent::SystemReportComponent(JsonParserAPI* json_parser) - : created_report_(false), json_parser_(json_parser) {} + : created_report_(false), + json_parser_(json_parser), + user_data_path_( + PreFetchedPaths::GetInstance()->GetLocalAppDataFolder().Append( + L"Google\\Chrome\\User Data")) {} void SystemReportComponent::PreScan() {} @@ -785,11 +814,13 @@ if (created_report_) return; + ExtensionFileLogger extension_file_logger(user_data_path_); + // Don't collect a system report if logs won't be uploaded. if (!logging_service->uploads_enabled()) { // TODO(proberge): Remove this by EOQ4 2018. if (base::CommandLine::ForCurrentProcess()->HasSwitch(kDumpRawLogsSwitch)) { - ReportInstalledExtensions(json_parser_); + ReportInstalledExtensions(json_parser_, &extension_file_logger); created_report_ = true; } @@ -825,9 +856,14 @@ ReportInstalledPrograms(); ReportLayeredServiceProviders(); ReportProxySettingsInformation(); - ReportInstalledExtensions(json_parser_); + ReportInstalledExtensions(json_parser_, &extension_file_logger); created_report_ = true; } +void SystemReportComponent::SetUserDataPathForTesting( + const base::FilePath& test_user_data_path) { + user_data_path_ = test_user_data_path; +} + } // namespace chrome_cleaner
diff --git a/chrome/chrome_cleaner/components/system_report_component.h b/chrome/chrome_cleaner/components/system_report_component.h index e9d8366..1923f93 100644 --- a/chrome/chrome_cleaner/components/system_report_component.h +++ b/chrome/chrome_cleaner/components/system_report_component.h
@@ -7,6 +7,7 @@ #include <vector> +#include "chrome/chrome_cleaner/chrome_utils/extension_file_logger.h" #include "chrome/chrome_cleaner/components/component_api.h" #include "chrome/chrome_cleaner/parsers/json_parser/json_parser_api.h" @@ -29,10 +30,12 @@ // Only exposed for tests. bool created_report() { return created_report_; } + void SetUserDataPathForTesting(const base::FilePath& test_user_data_path); private: bool created_report_; JsonParserAPI* json_parser_; + base::FilePath user_data_path_; }; } // namespace chrome_cleaner
diff --git a/chrome/chrome_cleaner/components/system_report_component_unittest.cc b/chrome/chrome_cleaner/components/system_report_component_unittest.cc index 927c1607..1430ccc 100644 --- a/chrome/chrome_cleaner/components/system_report_component_unittest.cc +++ b/chrome/chrome_cleaner/components/system_report_component_unittest.cc
@@ -30,6 +30,7 @@ #include "chrome/chrome_cleaner/os/pre_fetched_paths.h" #include "chrome/chrome_cleaner/os/registry_util.h" #include "chrome/chrome_cleaner/parsers/json_parser/test_json_parser.h" +#include "chrome/chrome_cleaner/test/test_extensions.h" #include "chrome/chrome_cleaner/test/test_file_util.h" #include "chrome/chrome_cleaner/test/test_pup_data.h" #include "chrome/chrome_cleaner/test/test_util.h" @@ -74,48 +75,49 @@ const ReportTestData kExtensionPolicyEmpty{ HKEY_LOCAL_MACHINE, kChromePoliciesWhitelistKeyPath, L"test1", L""}; -constexpr base::char16 kTestExtensionId1[] = +constexpr base::char16 kTestingExtensionId1[] = L"ababababcdcdcdcdefefefefghghghgh"; -constexpr base::char16 kTestExtensionId1WithUpdateUrl[] = +constexpr base::char16 kTestingExtensionId1WithUpdateUrl[] = L"ababababcdcdcdcdefefefefghghghgh;https://clients2.google.com/service/" L"update2/crx"; -constexpr base::char16 kTestExtensionId2[] = +constexpr base::char16 kTestingExtensionId2[] = L"aaaabbbbccccddddeeeeffffgggghhhh"; -constexpr base::char16 kTestExtensionId2WithUpdateUrl[] = +constexpr base::char16 kTestingExtensionId2WithUpdateUrl[] = L"aaaabbbbccccddddeeeeffffgggghhhh;https://clients2.google.com/service/" L"update2/crx"; const ReportTestData extension_policies[] = { {HKEY_LOCAL_MACHINE, kChromePoliciesWhitelistKeyPath, L"test1", - kTestExtensionId1}, + kTestingExtensionId1}, {HKEY_CURRENT_USER, kChromePoliciesWhitelistKeyPath, L"test2", - kTestExtensionId1}, + kTestingExtensionId1}, {HKEY_LOCAL_MACHINE, kChromePoliciesForcelistKeyPath, L"test3", - kTestExtensionId2WithUpdateUrl}, + kTestingExtensionId2WithUpdateUrl}, {HKEY_CURRENT_USER, kChromePoliciesForcelistKeyPath, L"test4", - kTestExtensionId2WithUpdateUrl}, + kTestingExtensionId2WithUpdateUrl}, {HKEY_LOCAL_MACHINE, kChromiumPoliciesWhitelistKeyPath, L"test5", - kTestExtensionId1}, + kTestingExtensionId1}, {HKEY_CURRENT_USER, kChromiumPoliciesWhitelistKeyPath, L"test6", - kTestExtensionId1}, + kTestingExtensionId1}, {HKEY_LOCAL_MACHINE, kChromiumPoliciesForcelistKeyPath, L"test7", - kTestExtensionId2WithUpdateUrl}, + kTestingExtensionId2WithUpdateUrl}, {HKEY_CURRENT_USER, kChromiumPoliciesForcelistKeyPath, L"test8", - kTestExtensionId2WithUpdateUrl}, + kTestingExtensionId2WithUpdateUrl}, }; const ReportTestData extension_forcelist_policies[] = { {HKEY_LOCAL_MACHINE, kChromePoliciesForcelistKeyPath, L"test1", - kTestExtensionId1WithUpdateUrl}, + kTestingExtensionId1WithUpdateUrl}, {HKEY_CURRENT_USER, kChromePoliciesForcelistKeyPath, L"test2", - kTestExtensionId2WithUpdateUrl}, + kTestingExtensionId2WithUpdateUrl}, }; const UwSId kFakePupId = 42; -const wchar_t kFakeChromeFolder[] = L"google\\chrome\\application\\42.12.34.56"; +const wchar_t kFakeChromeFolderForTests[] = + L"google\\chrome\\application\\42.12.34.56"; -const char kDefaultExtensionsJson[] = R"( +const char kDefaultExtensionsJsonForTests[] = R"( { "ababababcdcdcdcdefefefefghghghgh" : { "external_update_url": "https://clients2.google.com/service/update2/crx" @@ -125,7 +127,8 @@ } })"; // Don't include the null-terminator in the length. -const int kDefaultExtensionsJsonSize = sizeof(kDefaultExtensionsJson) - 1; +const int kDefaultExtensionsJsonForTestsSize = + sizeof(kDefaultExtensionsJsonForTests) - 1; // ExtensionSettings that has two force_installed extensions and two not. const wchar_t kExtensionSettingsJson[] = @@ -145,14 +148,14 @@ }, "extensionwithnosettingsabcdefghi": {} })"; + const ReportTestData extension_settings_entry = { HKEY_LOCAL_MACHINE, kChromePoliciesKeyPath, L"ExtensionSettings", kExtensionSettingsJson}; -const wchar_t kChromeExePath[] = L"google\\chrome\\application"; -const wchar_t kMasterPreferencesFileName[] = L"master_preferences"; -const char kMasterPreferencesJson[] = - R"( +const wchar_t kChromeExePathForTests[] = L"google\\chrome\\application"; +const wchar_t kMasterPreferencesFileNameForTests[] = L"master_preferences"; +const char kMasterPreferencesJsonForTests[] = R"( { "homepage": "http://dev.chromium.org/", "extensions": { @@ -173,6 +176,9 @@ } })"; +typedef std::map<base::string16, std::vector<base::string16>> + ExtensionIdToFileNamesMap; + class SystemReportComponentTest : public testing::Test { public: SystemReportComponentTest() : component_(&json_parser_) {} @@ -184,6 +190,21 @@ LoggingServiceAPI::SetInstanceForTesting(cleaner_logging_service_); registry_override_.OverrideRegistry(HKEY_CURRENT_USER); registry_override_.OverrideRegistry(HKEY_LOCAL_MACHINE); + + ASSERT_TRUE(fake_user_data_.CreateUniqueTempDir()); + + extension_id_to_filenames_map_[kTestingExtensionId1] = {L"file1.test", + L"file2.test"}; + ASSERT_TRUE(CreateProfileWithExtensionAndFiles( + fake_user_data_.GetPath().Append(L"Profile 1"), kTestingExtensionId1, + extension_id_to_filenames_map_[kTestingExtensionId1])); + + extension_id_to_filenames_map_[kTestingExtensionId2] = {L"file1.test"}; + ASSERT_TRUE(CreateProfileWithExtensionAndFiles( + fake_user_data_.GetPath().Append(L"Profile 2"), kTestingExtensionId2, + extension_id_to_filenames_map_[kTestingExtensionId2])); + + component_.SetUserDataPathForTesting(fake_user_data_.GetPath()); } void TearDown() override { @@ -201,6 +222,8 @@ SystemReportComponent component_; CleanerLoggingService* cleaner_logging_service_ = nullptr; registry_util::RegistryOverrideManager registry_override_; + base::ScopedTempDir fake_user_data_; + ExtensionIdToFileNamesMap extension_id_to_filenames_map_; }; template <typename Component> @@ -256,6 +279,41 @@ return false; } +// Returns whether |extension_files| contains the expected file information +// of |extension_id|. +::testing::AssertionResult ExtensionsReportedWithExpectedFiles( + const RepeatedPtrField<InstalledExtension>& reported_extensions, + const ExtensionIdToFileNamesMap& extension_id_to_filenames_map) { + for (const auto& installed_extension : reported_extensions) { + const RepeatedPtrField<FileInformation> extension_files = + installed_extension.extension_files(); + + std::unordered_set<base::string16> expected_files( + extension_id_to_filenames_map + .at(base::UTF8ToUTF16(installed_extension.extension_id())) + .begin(), + extension_id_to_filenames_map + .at(base::UTF8ToUTF16(installed_extension.extension_id())) + .end()); + + if (static_cast<size_t>(extension_files.size()) != expected_files.size()) + return ::testing::AssertionFailure() + << "Different number of files than expected for extension " + << installed_extension.extension_id(); + + for (const auto& file : extension_files) { + base::string16 file_name = + base::FilePath(base::UTF8ToUTF16(file.path())).BaseName().value(); + + if (expected_files.find(file_name) == expected_files.end()) + return ::testing::AssertionFailure() + << "file : " << file_name << " not reported for extension " + << installed_extension.extension_id(); + } + } + return ::testing::AssertionSuccess(); +} + // Returns whether |reported_extensions| contains an entry for an extension with // |extension_id| and |install_method|. bool InstalledExtensionReported( @@ -521,13 +579,14 @@ base::PathService::Get(base::DIR_PROGRAM_FILES, &program_files_dir)); base::FilePath fake_apps_dir( - program_files_dir.Append(kFakeChromeFolder).Append(L"default_apps")); + program_files_dir.Append(kFakeChromeFolderForTests) + .Append(L"default_apps")); ASSERT_TRUE(base::CreateDirectoryAndGetError(fake_apps_dir, nullptr)); base::FilePath default_extensions_file = fake_apps_dir.Append(L"external_extensions.json"); - CreateFileWithContent(default_extensions_file, kDefaultExtensionsJson, - kDefaultExtensionsJsonSize); + CreateFileWithContent(default_extensions_file, kDefaultExtensionsJsonForTests, + kDefaultExtensionsJsonForTestsSize); ASSERT_TRUE(base::PathExists(default_extensions_file)); base::test::ScopedCommandLine scoped_command_line; @@ -536,11 +595,15 @@ EXPECT_EQ(2, report.system_report().installed_extensions().size()); EXPECT_TRUE(InstalledExtensionReported( - report.system_report().installed_extensions(), kTestExtensionId1, + report.system_report().installed_extensions(), kTestingExtensionId1, ExtensionInstallMethod::DEFAULT_APPS_EXTENSION)); EXPECT_TRUE(InstalledExtensionReported( - report.system_report().installed_extensions(), kTestExtensionId2, + report.system_report().installed_extensions(), kTestingExtensionId2, ExtensionInstallMethod::DEFAULT_APPS_EXTENSION)); + + EXPECT_TRUE(ExtensionsReportedWithExpectedFiles( + report.system_report().installed_extensions(), + extension_id_to_filenames_map_)); } TEST_F(SystemReportComponentTest, ReportExtensionSettings) { @@ -560,11 +623,15 @@ ChromeCleanerReport report = GetChromeCleanerReport(); EXPECT_TRUE(InstalledExtensionReported( - report.system_report().installed_extensions(), kTestExtensionId1, + report.system_report().installed_extensions(), kTestingExtensionId1, ExtensionInstallMethod::POLICY_EXTENSION_SETTINGS)); EXPECT_TRUE(InstalledExtensionReported( - report.system_report().installed_extensions(), kTestExtensionId2, + report.system_report().installed_extensions(), kTestingExtensionId2, ExtensionInstallMethod::POLICY_EXTENSION_SETTINGS)); + + EXPECT_TRUE(ExtensionsReportedWithExpectedFiles( + report.system_report().installed_extensions(), + extension_id_to_filenames_map_)); } TEST_F(SystemReportComponentTest, ReportMasterPreferencesExtensions) { @@ -576,13 +643,13 @@ ASSERT_TRUE( base::PathService::Get(base::DIR_PROGRAM_FILES, &program_files_dir)); - base::FilePath chrome_dir(program_files_dir.Append(kChromeExePath)); + base::FilePath chrome_dir(program_files_dir.Append(kChromeExePathForTests)); ASSERT_TRUE(base::CreateDirectoryAndGetError(chrome_dir, nullptr)); base::FilePath master_preferences = - chrome_dir.Append(kMasterPreferencesFileName); - CreateFileWithContent(master_preferences, kMasterPreferencesJson, - sizeof(kMasterPreferencesJson) - 1); + chrome_dir.Append(kMasterPreferencesFileNameForTests); + CreateFileWithContent(master_preferences, kMasterPreferencesJsonForTests, + sizeof(kMasterPreferencesJsonForTests) - 1); ASSERT_TRUE(base::PathExists(master_preferences)); base::test::ScopedCommandLine scoped_command_line; @@ -591,11 +658,15 @@ EXPECT_EQ(2, report.system_report().installed_extensions().size()); EXPECT_TRUE(InstalledExtensionReported( - report.system_report().installed_extensions(), kTestExtensionId1, + report.system_report().installed_extensions(), kTestingExtensionId1, ExtensionInstallMethod::POLICY_MASTER_PREFERENCES)); EXPECT_TRUE(InstalledExtensionReported( - report.system_report().installed_extensions(), kTestExtensionId2, + report.system_report().installed_extensions(), kTestingExtensionId2, ExtensionInstallMethod::POLICY_MASTER_PREFERENCES)); + + EXPECT_TRUE(ExtensionsReportedWithExpectedFiles( + report.system_report().installed_extensions(), + extension_id_to_filenames_map_)); } } // namespace chrome_cleaner
diff --git a/chrome/chrome_cleaner/logging/cleaner_logging_service.cc b/chrome/chrome_cleaner/logging/cleaner_logging_service.cc index 57d1d07..61df1ff 100644 --- a/chrome/chrome_cleaner/logging/cleaner_logging_service.cc +++ b/chrome/chrome_cleaner/logging/cleaner_logging_service.cc
@@ -29,6 +29,7 @@ #include "chrome/chrome_cleaner/logging/api_keys.h" #include "chrome/chrome_cleaner/logging/pending_logs_service.h" #include "chrome/chrome_cleaner/logging/proto/removal_status.pb.h" +#include "chrome/chrome_cleaner/logging/proto/shared_data.pb.h" #include "chrome/chrome_cleaner/logging/registry_logger.h" #include "chrome/chrome_cleaner/logging/utils.h" #include "chrome/chrome_cleaner/os/disk_util.h" @@ -585,13 +586,19 @@ void CleanerLoggingService::AddInstalledExtension( const base::string16& extension_id, - ExtensionInstallMethod install_method) { + ExtensionInstallMethod install_method, + const std::vector<internal::FileInformation>& extension_files) { base::AutoLock lock(lock_); ChromeCleanerReport_SystemReport_InstalledExtension* installed_extension = chrome_cleaner_report_.mutable_system_report() ->add_installed_extensions(); installed_extension->set_extension_id(base::UTF16ToUTF8(extension_id)); installed_extension->set_install_method(install_method); + for (const auto& file : extension_files) { + FileInformation proto_file_information; + FileInformationToProtoObject(file, &proto_file_information); + *installed_extension->add_extension_files() = proto_file_information; + } } void CleanerLoggingService::AddScheduledTask(
diff --git a/chrome/chrome_cleaner/logging/cleaner_logging_service.h b/chrome/chrome_cleaner/logging/cleaner_logging_service.h index b0149970..f4a6b8a 100644 --- a/chrome/chrome_cleaner/logging/cleaner_logging_service.h +++ b/chrome/chrome_cleaner/logging/cleaner_logging_service.h
@@ -89,12 +89,15 @@ bool autodetect) override; void SetWinHttpProxySettings(const base::string16& config, const base::string16& bypass) override; - void AddInstalledExtension(const base::string16& extension_id, - ExtensionInstallMethod install_method) override; + void AddInstalledExtension( + const base::string16& extension_id, + ExtensionInstallMethod install_method, + const std::vector<internal::FileInformation>& extension_files) override; void AddScheduledTask( const base::string16& name, const base::string16& description, const std::vector<internal::FileInformation>& actions) override; + void LogProcessInformation(SandboxType process_type, const SystemResourceUsage& usage) override;
diff --git a/chrome/chrome_cleaner/logging/cleaner_logging_service_unittest.cc b/chrome/chrome_cleaner/logging/cleaner_logging_service_unittest.cc index eb94ffa0..a00dbb6 100644 --- a/chrome/chrome_cleaner/logging/cleaner_logging_service_unittest.cc +++ b/chrome/chrome_cleaner/logging/cleaner_logging_service_unittest.cc
@@ -1074,10 +1074,17 @@ ASSERT_TRUE(report.ParseFromString(logging_service_->RawReportContent())); ASSERT_EQ(report.system_report().installed_extensions_size(), 0); + internal::FileInformation file1, file2; + const base::string16 kFilePath1 = L"path/file1"; + const base::string16 kFilePath2 = L"path/file2"; + file1.path = kFilePath1; + file2.path = kFilePath2; logging_service_->AddInstalledExtension( - kExtensionId, ExtensionInstallMethod::POLICY_EXTENSION_FORCELIST); + kExtensionId, ExtensionInstallMethod::POLICY_EXTENSION_FORCELIST, + {file1}); logging_service_->AddInstalledExtension( - kExtensionId2, ExtensionInstallMethod::POLICY_MASTER_PREFERENCES); + kExtensionId2, ExtensionInstallMethod::POLICY_MASTER_PREFERENCES, + {file1, file2}); ASSERT_TRUE(report.ParseFromString(logging_service_->RawReportContent())); ASSERT_EQ(report.system_report().installed_extensions_size(), 2); @@ -1087,12 +1094,23 @@ EXPECT_EQ(base::WideToUTF8(kExtensionId), installed_extension.extension_id()); EXPECT_EQ(ExtensionInstallMethod::POLICY_EXTENSION_FORCELIST, installed_extension.install_method()); + ASSERT_EQ(installed_extension.extension_files().size(), 1); + EXPECT_EQ(installed_extension.extension_files(0).path(), + base::UTF16ToUTF8(kFilePath1)); installed_extension = report.system_report().installed_extensions(1); EXPECT_EQ(base::WideToUTF8(kExtensionId2), installed_extension.extension_id()); EXPECT_EQ(ExtensionInstallMethod::POLICY_MASTER_PREFERENCES, installed_extension.install_method()); + ASSERT_EQ(installed_extension.extension_files().size(), 2); + + std::vector<std::string> reported_files = { + installed_extension.extension_files(0).path(), + installed_extension.extension_files(1).path()}; + EXPECT_THAT(reported_files, testing::UnorderedElementsAreArray( + {base::UTF16ToUTF8(kFilePath1), + base::UTF16ToUTF8(kFilePath2)})); } TEST_P(CleanerLoggingServiceTest, AddScheduledTask) {
diff --git a/chrome/chrome_cleaner/logging/logging_service_api.h b/chrome/chrome_cleaner/logging/logging_service_api.h index 14a4121..a4e80de9 100644 --- a/chrome/chrome_cleaner/logging/logging_service_api.h +++ b/chrome/chrome_cleaner/logging/logging_service_api.h
@@ -161,8 +161,10 @@ const base::string16& bypass) = 0; // Add an installed extension to the system report. - virtual void AddInstalledExtension(const base::string16& extension_id, - ExtensionInstallMethod install_method) = 0; + virtual void AddInstalledExtension( + const base::string16& extension_id, + ExtensionInstallMethod install_method, + const std::vector<internal::FileInformation>& extension_files) = 0; // Add a scheduled task to the system report. virtual void AddScheduledTask(
diff --git a/chrome/chrome_cleaner/logging/mock_logging_service.h b/chrome/chrome_cleaner/logging/mock_logging_service.h index ec0609f..b20bbda 100644 --- a/chrome/chrome_cleaner/logging/mock_logging_service.h +++ b/chrome/chrome_cleaner/logging/mock_logging_service.h
@@ -72,9 +72,11 @@ MOCK_METHOD2(SetWinHttpProxySettings, void(const base::string16& config, const base::string16& bypass)); - MOCK_METHOD2(AddInstalledExtension, - void(const base::string16& extension_id, - ExtensionInstallMethod install_method)); + MOCK_METHOD3( + AddInstalledExtension, + void(const base::string16& extension_id, + ExtensionInstallMethod install_method, + const std::vector<internal::FileInformation>& file_information)); MOCK_METHOD3(AddScheduledTask, void(const base::string16& name, const base::string16& description,
diff --git a/chrome/chrome_cleaner/logging/noop_logging_service.cc b/chrome/chrome_cleaner/logging/noop_logging_service.cc index 9e028a8a..bbaa0cd0 100644 --- a/chrome/chrome_cleaner/logging/noop_logging_service.cc +++ b/chrome/chrome_cleaner/logging/noop_logging_service.cc
@@ -91,7 +91,8 @@ void NoOpLoggingService::AddInstalledExtension( const base::string16& extension_id, - ExtensionInstallMethod install_method) {} + ExtensionInstallMethod install_method, + const std::vector<internal::FileInformation>& extension_files) {} void NoOpLoggingService::AddScheduledTask( const base::string16& /*name*/,
diff --git a/chrome/chrome_cleaner/logging/noop_logging_service.h b/chrome/chrome_cleaner/logging/noop_logging_service.h index c062731..3bc8107 100644 --- a/chrome/chrome_cleaner/logging/noop_logging_service.h +++ b/chrome/chrome_cleaner/logging/noop_logging_service.h
@@ -67,12 +67,15 @@ bool autodetect) override; void SetWinHttpProxySettings(const base::string16& config, const base::string16& bypass) override; - void AddInstalledExtension(const base::string16& extension_id, - ExtensionInstallMethod install_method) override; + void AddInstalledExtension( + const base::string16& extension_id, + ExtensionInstallMethod install_method, + const std::vector<internal::FileInformation>& extension_files) override; void AddScheduledTask( const base::string16& name, const base::string16& description, const std::vector<internal::FileInformation>& actions) override; + void LogProcessInformation(SandboxType process_type, const SystemResourceUsage& usage) override; bool AllExpectedRemovalsConfirmed() const override;
diff --git a/chrome/chrome_cleaner/logging/reporter_logging_service.cc b/chrome/chrome_cleaner/logging/reporter_logging_service.cc index 241c7f6..85d0811 100644 --- a/chrome/chrome_cleaner/logging/reporter_logging_service.cc +++ b/chrome/chrome_cleaner/logging/reporter_logging_service.cc
@@ -276,7 +276,8 @@ void ReporterLoggingService::AddInstalledExtension( const base::string16& extension_id, - ExtensionInstallMethod install_method) {} + ExtensionInstallMethod install_method, + const std::vector<internal::FileInformation>& extension_files) {} void ReporterLoggingService::AddScheduledTask( const base::string16& /*name*/,
diff --git a/chrome/chrome_cleaner/logging/reporter_logging_service.h b/chrome/chrome_cleaner/logging/reporter_logging_service.h index c3170e031..e418fbf 100644 --- a/chrome/chrome_cleaner/logging/reporter_logging_service.h +++ b/chrome/chrome_cleaner/logging/reporter_logging_service.h
@@ -70,12 +70,15 @@ bool autodetect) override; void SetWinHttpProxySettings(const base::string16& config, const base::string16& bypass) override; - void AddInstalledExtension(const base::string16& extension_id, - ExtensionInstallMethod install_method) override; + void AddInstalledExtension( + const base::string16& extension_id, + ExtensionInstallMethod install_method, + const std::vector<internal::FileInformation>& extension_files) override; void AddScheduledTask( const base::string16& name, const base::string16& description, const std::vector<internal::FileInformation>& actions) override; + void LogProcessInformation(SandboxType process_type, const SystemResourceUsage& usage) override; bool AllExpectedRemovalsConfirmed() const override;
diff --git a/chrome/chrome_cleaner/test/test_extensions.cc b/chrome/chrome_cleaner/test/test_extensions.cc index 83375fa..873f1c8 100644 --- a/chrome/chrome_cleaner/test/test_extensions.cc +++ b/chrome/chrome_cleaner/test/test_extensions.cc
@@ -4,6 +4,9 @@ #include "chrome/chrome_cleaner/test/test_extensions.h" +#include "base/files/file.h" +#include "base/files/file_util.h" + namespace chrome_cleaner { TestRegistryEntry::TestRegistryEntry(HKEY hkey, @@ -15,4 +18,31 @@ TestRegistryEntry& TestRegistryEntry::operator=( const TestRegistryEntry& other) = default; +bool CreateProfileWithExtensionAndFiles( + const base::FilePath& profile_path, + const base::string16& extension_id, + const std::vector<base::string16>& extension_files) { + if (!base::CreateDirectory(profile_path)) + return false; + + base::FilePath extensions_folder_path = profile_path.Append(L"Extensions"); + if (!base::CreateDirectory(extensions_folder_path)) + return false; + + base::FilePath extension_path = extensions_folder_path.Append(extension_id); + if (!base::CreateDirectory(extension_path)) + return false; + + for (const base::string16& file_name : extension_files) { + base::File extension_file( + extension_path.Append(file_name), + base::File::Flags::FLAG_CREATE | base::File::Flags::FLAG_READ); + + if (!extension_file.IsValid()) + return false; + } + + return true; +} + } // namespace chrome_cleaner
diff --git a/chrome/chrome_cleaner/test/test_extensions.h b/chrome/chrome_cleaner/test/test_extensions.h index 03e54c8..aa64c42 100644 --- a/chrome/chrome_cleaner/test/test_extensions.h +++ b/chrome/chrome_cleaner/test/test_extensions.h
@@ -5,6 +5,10 @@ #ifndef CHROME_CHROME_CLEANER_TEST_TEST_EXTENSIONS_H_ #define CHROME_CHROME_CLEANER_TEST_TEST_EXTENSIONS_H_ +#include <vector> + +#include "base/files/file_path.h" +#include "base/strings/string16.h" #include "base/win/registry.h" #include "chrome/chrome_cleaner/os/registry_util.h" @@ -127,6 +131,11 @@ "homepage": "http://dev.chromium.org/" })"; +bool CreateProfileWithExtensionAndFiles( + const base::FilePath& profile_path, + const base::string16& extension_id, + const std::vector<base::string16>& extension_files); + } // namespace chrome_cleaner #endif // CHROME_CHROME_CLEANER_TEST_TEST_EXTENSIONS_H_
diff --git a/chrome/common/extensions/manifest_tests/extension_manifests_contentsecuritypolicy_unittest.cc b/chrome/common/extensions/manifest_tests/extension_manifests_contentsecuritypolicy_unittest.cc index 8828b6d..4915458bf 100644 --- a/chrome/common/extensions/manifest_tests/extension_manifests_contentsecuritypolicy_unittest.cc +++ b/chrome/common/extensions/manifest_tests/extension_manifests_contentsecuritypolicy_unittest.cc
@@ -9,6 +9,7 @@ #include "testing/gtest/include/gtest/gtest.h" namespace errors = extensions::manifest_errors; +namespace keys = extensions::manifest_keys; using extensions::ErrorUtils; class ContentSecurityPolicyManifestTest : public ChromeManifestTest { @@ -19,12 +20,15 @@ Testcase( "insecure_contentsecuritypolicy_1.json", ErrorUtils::FormatErrorMessage(errors::kInvalidCSPInsecureValue, + keys::kContentSecurityPolicy, "http://example.com", "script-src")), Testcase("insecure_contentsecuritypolicy_2.json", ErrorUtils::FormatErrorMessage(errors::kInvalidCSPInsecureValue, + keys::kContentSecurityPolicy, "'unsafe-inline'", "script-src")), Testcase("insecure_contentsecuritypolicy_3.json", ErrorUtils::FormatErrorMessage( - errors::kInvalidCSPMissingSecureSrc, "object-src"))}; + errors::kInvalidCSPMissingSecureSrc, + keys::kContentSecurityPolicy, "object-src"))}; RunTestcases(testcases, base::size(testcases), EXPECT_TYPE_WARNING); }
diff --git a/chrome/common/extensions/manifest_tests/extension_manifests_platformapp_unittest.cc b/chrome/common/extensions/manifest_tests/extension_manifests_platformapp_unittest.cc index d6f2436..57e0f5f 100644 --- a/chrome/common/extensions/manifest_tests/extension_manifests_platformapp_unittest.cc +++ b/chrome/common/extensions/manifest_tests/extension_manifests_platformapp_unittest.cc
@@ -20,6 +20,7 @@ namespace extensions { namespace errors = manifest_errors; +namespace keys = manifest_keys; class PlatformAppsManifestTest : public ChromeManifestTest { }; @@ -100,6 +101,7 @@ LoadAndExpectWarning( "init_platform_app_csp_insecure.json", ErrorUtils::FormatErrorMessage(errors::kInvalidCSPInsecureValue, + keys::kPlatformAppContentSecurityPolicy, "http://www.google.com", "default-src")); }
diff --git a/chrome/common/webui_url_constants.cc b/chrome/common/webui_url_constants.cc index 9e6a631..e8615bd 100644 --- a/chrome/common/webui_url_constants.cc +++ b/chrome/common/webui_url_constants.cc
@@ -187,6 +187,9 @@ #endif #if defined(OS_CHROMEOS) +const char kChromeUIAccountManagerWelcomeHost[] = "account-manager-welcome"; +const char kChromeUIAccountManagerWelcomeURL[] = + "chrome://account-manager-welcome"; const char kChromeUIActivationMessageHost[] = "activationmessage"; const char kChromeUIBluetoothPairingHost[] = "bluetooth-pairing"; const char kChromeUIBluetoothPairingURL[] = "chrome://bluetooth-pairing/";
diff --git a/chrome/common/webui_url_constants.h b/chrome/common/webui_url_constants.h index 6d48133..9cdf6ad9 100644 --- a/chrome/common/webui_url_constants.h +++ b/chrome/common/webui_url_constants.h
@@ -186,6 +186,8 @@ #endif // defined(OS_ANDROID) #if defined(OS_CHROMEOS) +extern const char kChromeUIAccountManagerWelcomeHost[]; +extern const char kChromeUIAccountManagerWelcomeURL[]; extern const char kChromeUIActivationMessageHost[]; extern const char kChromeUIBluetoothPairingHost[]; extern const char kChromeUIBluetoothPairingURL[];
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index 77a2699..f581981 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -763,7 +763,6 @@ "../browser/prerender/prerender_nostate_prefetch_browsertest.cc", "../browser/prerender/prerender_test_utils.cc", "../browser/prerender/prerender_test_utils.h", - "../browser/previews/lazyload_browsertest.cc", "../browser/previews/previews_browsertest.cc", "../browser/previews/previews_lite_page_browsertest.cc", "../browser/previews/previews_service_browser_test.cc", @@ -1665,6 +1664,7 @@ "../browser/chromeos/child_accounts/time_limit_test_utils.cc", "../browser/chromeos/customization/customization_document_browsertest.cc", "../browser/chromeos/customization/customization_wallpaper_downloader_browsertest.cc", + "../browser/chromeos/dbus/proxy_resolution_service_provider_browsertest.cc", "../browser/chromeos/display/display_prefs_browsertest.cc", "../browser/chromeos/display/quirks_browsertest.cc", "../browser/chromeos/drive/drive_integration_service_browsertest.cc", @@ -5218,6 +5218,8 @@ sources = [ "../app/chrome_version.rc.version", "../browser/extensions/api/cast_streaming/performance_test.cc", + "../browser/extensions/api/tab_capture/tab_capture_performance_test_base.cc", + "../browser/extensions/api/tab_capture/tab_capture_performance_test_base.h", "../browser/extensions/api/tab_capture/tab_capture_performancetest.cc", "../browser/extensions/chrome_extension_test_notification_observer.cc", "../browser/extensions/chrome_extension_test_notification_observer.h",
diff --git a/chrome/test/data/extensions/api_test/cast_streaming/performance.js b/chrome/test/data/extensions/api_test/cast_streaming/performance.js deleted file mode 100644 index 9cb5bd4..0000000 --- a/chrome/test/data/extensions/api_test/cast_streaming/performance.js +++ /dev/null
@@ -1,161 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Run a cast v2 mirroring session for 15 seconds. - -console.log('Starting eval of performance.js...'); - -chrome.test.runTests([ - function sendTestPatterns() { - console.log('Starting sendTestPatterns()...'); - - const kMaxFrameRate = 30; - const kCallbackTimeoutMillis = 10000; - const kTestRunTimeMillis = 15000; - - const rtpStream = chrome.cast.streaming.rtpStream; - - // The receive port changes between browser_test invocations, and is passed - // as an query parameter in the URL. - let recvPort; - let autoThrottling; - let aesKey; - let aesIvMask; - try { - const params = window.location.search; - recvPort = parseInt(params.match(/(\?|&)port=(\d+)/)[2]); - chrome.test.assertTrue(recvPort > 0); - autoThrottling = (params.match(/(\?|&)autoThrottling=(true|false)/)[2] == - 'true'); - aesKey = params.match(/(\?|&)aesKey=([0-9A-F]{32})/)[2]; - aesIvMask = params.match(/(\?|&)aesIvMask=([0-9A-F]{32})/)[2]; - } catch (err) { - chrome.test.fail("Error parsing params -- " + err.message); - return; - } - - // Start capture and wait up to kCallbackTimeoutMillis for it to start. - const startCapturePromise = new Promise((resolve, reject) => { - const timeoutId = setTimeout(() => { - reject(Error('chrome.tabCapture.capture() did not call back')); - }, kCallbackTimeoutMillis); - - const captureOptions = { - video: true, - audio: true, - videoConstraints: { - mandatory: { - minWidth: autoThrottling ? 320 : 1920, - minHeight: autoThrottling ? 180 : 1080, - maxWidth: 1920, - maxHeight: 1080, - maxFrameRate: kMaxFrameRate, - enableAutoThrottling: autoThrottling, - } - } - }; - console.log('About to call chrome.tabCapture.capture()...'); - chrome.tabCapture.capture(captureOptions, captureStream => { - console.log('chrome.tabCapture.capture() callback is running...'); - clearTimeout(timeoutId); - if (captureStream) { - console.log('Started tab capture.'); - resolve(captureStream); - } else { - if (chrome.runtime.lastError) { - reject(chrome.runtime.lastError); - } else { - reject(Error('null stream')); - } - } - }); - }); - - // Then, start Cast Streaming and wait up to kCallbackTimeoutMillis for it - // to start. - const startStreamingPromise = startCapturePromise.then(captureStream => { - console.log('Starting streaming...'); - return new Promise((resolve, reject) => { - const timeoutId = setTimeout(() => { - reject(Error( - 'chrome.cast.streaming.session.create() did not call back')); - }, kCallbackTimeoutMillis); - - console.log('Creating cast streaming session...'); - chrome.cast.streaming.session.create( - captureStream.getAudioTracks()[0], - captureStream.getVideoTracks()[0], - (audioId, videoId, udpId) => { - console.log('Cast streaming session create callback is running...'); - clearTimeout(timeoutId); - - try { - chrome.cast.streaming.udpTransport.setDestination( - udpId, { address: "127.0.0.1", port: recvPort } ); - rtpStream.onError.addListener(() => { - chrome.test.fail('RTP stream error'); - }); - const audioParams = rtpStream.getSupportedParams(audioId)[0]; - audioParams.payload.aesKey = aesKey; - audioParams.payload.aesIvMask = aesIvMask; - rtpStream.start(audioId, audioParams); - const videoParams = rtpStream.getSupportedParams(videoId)[0]; - videoParams.payload.clockRate = kMaxFrameRate; - videoParams.payload.aesKey = aesKey; - videoParams.payload.aesIvMask = aesIvMask; - rtpStream.start(videoId, videoParams); - - console.log('Started Cast Streaming.'); - resolve([captureStream, audioId, videoId, udpId]); - } catch (error) { - reject(error); - } - }); - }); - }); - - // Then, let the test run for kTestRunTimeMillis, and then shut down the RTP - // streams and MediaStreamTracks. - const doneTestingPromise = startStreamingPromise.then( - ([captureStream, audioId, videoId, udpId]) => { - return new Promise(resolve => { - console.log(`Running test for ${kTestRunTimeMillis} ms.`); - setTimeout(resolve, kTestRunTimeMillis); - }).then(() => { - console.log('Stopping cast streaming...'); - rtpStream.stop(audioId); - rtpStream.stop(videoId); - rtpStream.destroy(audioId); - rtpStream.destroy(videoId); - - chrome.cast.streaming.udpTransport.destroy(udpId); - - console.log('Stopping tab capture (MediaStreamTracks)...'); - const tracks = captureStream.getTracks(); - for (let i = 0; i < tracks.length; ++i) { - tracks[i].stop(); - } - }); - }); - - // If all of the above completed without error, the test run has succeeded. - // Otherwise, flag that the test has failed with the cause. - doneTestingPromise.then(() => { - console.log('About to chrome.test.succeed()...'); - chrome.test.succeed(); - console.log('Did chrome.test.succeed()...'); - }).catch(error => { - if (typeof error === 'object' && - ('stack' in error || 'message' in error)) { - chrome.test.fail(error.stack || error.message); - } else { - chrome.test.fail(String(error)); - } - }); - - console.log('Completed sendTestPatterns(). (Waiting for promises...)'); - } -]); - -console.log('Completed eval of performance.js.');
diff --git a/chrome/test/data/extensions/api_test/cast_streaming/performance24.html b/chrome/test/data/extensions/api_test/cast_streaming/performance24.html deleted file mode 100644 index 32fe264..0000000 --- a/chrome/test/data/extensions/api_test/cast_streaming/performance24.html +++ /dev/null
@@ -1,10 +0,0 @@ -<html> -<head> -<script src="performance.js"></script> -</head> -<body> -<video autoplay width="100%" height="100%"> - <source src="test_video_24fps.webm" type="video/webm"> -</video> -</body> -</html>
diff --git a/chrome/test/data/extensions/api_test/cast_streaming/performance30.html b/chrome/test/data/extensions/api_test/cast_streaming/performance30.html deleted file mode 100644 index 0f18d03..0000000 --- a/chrome/test/data/extensions/api_test/cast_streaming/performance30.html +++ /dev/null
@@ -1,10 +0,0 @@ -<html> -<head> -<script src="performance.js"></script> -</head> -<body> -<video autoplay width="100%" height="100%"> - <source src="test_video_30fps.webm" type="video/webm"> -</video> -</body> -</html>
diff --git a/chrome/test/data/extensions/api_test/cast_streaming/performance60.html b/chrome/test/data/extensions/api_test/cast_streaming/performance60.html deleted file mode 100644 index 3638fd14..0000000 --- a/chrome/test/data/extensions/api_test/cast_streaming/performance60.html +++ /dev/null
@@ -1,10 +0,0 @@ -<html> -<head> -<script src="performance.js"></script> -</head> -<body> -<video autoplay width="100%" height="100%"> - <source src="test_video_60fps.webm" type="video/webm"> -</video> -</body> -</html>
diff --git a/chrome/test/data/extensions/api_test/cast_streaming/perftest_extension/background.js b/chrome/test/data/extensions/api_test/cast_streaming/perftest_extension/background.js new file mode 100644 index 0000000..7a683ec --- /dev/null +++ b/chrome/test/data/extensions/api_test/cast_streaming/perftest_extension/background.js
@@ -0,0 +1,113 @@ +// 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. + +console.log('Registering chrome.runtime message listener...'); + +chrome.runtime.onMessageExternal.addListener((request, from, sendResponse) => { + if (!request.start) { + return; + } + + const kCallbackTimeoutMillis = 10000; + + if (window.currentCaptureStream) { + sendResponse({success: false, reason: 'Already started!'}); + return; + } + + // Start capture and wait up to kCallbackTimeoutMillis for it to start. + const startCapturePromise = new Promise((resolve, reject) => { + const timeoutId = setTimeout(() => { + reject(Error('chrome.tabCapture.capture() did not call back')); + }, kCallbackTimeoutMillis); + + const captureOptions = { + video: true, + audio: true, + videoConstraints: { + mandatory: { + minWidth: request.enableAutoThrottling ? 320 : 1920, + minHeight: request.enableAutoThrottling ? 180 : 1080, + maxWidth: 1920, + maxHeight: 1080, + maxFrameRate: (request.maxFrameRate || 30), + } + } + }; + console.log('Starting tab capture...'); + chrome.tabCapture.capture(captureOptions, captureStream => { + clearTimeout(timeoutId); + if (captureStream) { + console.log('Started tab capture.'); + resolve(captureStream); + } else { + if (chrome.runtime.lastError) { + reject(chrome.runtime.lastError); + } else { + reject(Error('null stream')); + } + } + }); + }); + + // Then, start Cast Streaming and wait up to kCallbackTimeoutMillis for it to + // start. + const startStreamingPromise = startCapturePromise.then(captureStream => { + return new Promise((resolve, reject) => { + const timeoutId = setTimeout(() => { + reject(Error( + 'chrome.cast.streaming.session.create() did not call back')); + }, kCallbackTimeoutMillis); + + console.log('Starting Cast streaming...'); + chrome.cast.streaming.session.create( + captureStream.getAudioTracks()[0], + captureStream.getVideoTracks()[0], + (audioId, videoId, udpId) => { + clearTimeout(timeoutId); + + try { + chrome.cast.streaming.udpTransport.setDestination( + udpId, { address: '127.0.0.1', port: request.recvPort } ); + const rtpStream = chrome.cast.streaming.rtpStream; + rtpStream.onError.addListener(() => { + console.error('RTP stream error'); + }); + const audioParams = rtpStream.getSupportedParams(audioId)[0]; + audioParams.payload.aesKey = request.aesKey; + audioParams.payload.aesIvMask = request.aesIvMask; + rtpStream.start(audioId, audioParams); + const videoParams = rtpStream.getSupportedParams(videoId)[0]; + videoParams.payload.clockRate = (request.maxFrameRate || 30); + videoParams.payload.aesKey = request.aesKey; + videoParams.payload.aesIvMask = request.aesIvMask; + rtpStream.start(videoId, videoParams); + + console.log('Started Cast streaming.'); + window.currentCaptureStream = captureStream; + resolve(); + } catch (error) { + reject(error); + } + }); + }); + }); + + startStreamingPromise.then(() => { + console.log('Sending success response...'); + sendResponse({success: true}); + }).catch(error => { + console.log('Sending error response...'); + let errorMessage; + if (typeof error === 'object' && + ('stack' in error || 'message' in error)) { + errorMessage = (error.stack || error.message); + } else { + errorMessage = String(error); + } + sendResponse({success: false, reason: errorMessage}); + }); + + return true; // Indicate that sendResponse() will be called asynchronously. +});
diff --git a/chrome/test/data/extensions/api_test/cast_streaming/perftest_extension/manifest.json b/chrome/test/data/extensions/api_test/cast_streaming/perftest_extension/manifest.json new file mode 100644 index 0000000..72ea5e8 --- /dev/null +++ b/chrome/test/data/extensions/api_test/cast_streaming/perftest_extension/manifest.json
@@ -0,0 +1,15 @@ +{ + "key": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC8xv6iO+j4kzj1HiBL93+XVJH/CRyAQMUHS/Z0l8nCAzaAFkW/JsNwxJqQhrZspnxLqbQxNncXs6g6bsXAwKHiEs+LSs+bIv0Gc/2ycZdhXJ8GhEsSMakog5dpQd1681c2gLK/8CrAoewE/0GIKhaFcp7a2iZlGh4Am6fgMKy0iQIDAQAB", + "name": "CastV2PerformanceTest extension", + "version": "1", + "manifest_version": 2, + "description": "Launches tabCapture and cast.streaming on an active tab.", + "permissions": ["tabs", "tabCapture", "cast", "cast.streaming"], + "background": { + "scripts": ["background.js"], + "persistent": true + }, + "externally_connectable": { + "matches": ["*://*.chromium.org/*"] + } +}
diff --git a/chrome/test/data/extensions/api_test/tab_capture/balls.html b/chrome/test/data/extensions/api_test/tab_capture/balls.html new file mode 100644 index 0000000..8d2da6b --- /dev/null +++ b/chrome/test/data/extensions/api_test/tab_capture/balls.html
@@ -0,0 +1,53 @@ +<html> +<head> +<style> +html { + width: 100%; + height: 100%; +} + +body { + display: flex; + justify-content: center; + align-items: center; +} + +canvas { + width: 1920px; + height: 1080px; +} +</style> +<script> +let frame_number = 0; + +function drawForever() { + // Request next animation frame. + requestAnimationFrame(drawForever); + ++frame_number; + + const canvas = document.getElementsByTagName('canvas')[0]; + const context = canvas.getContext('2d'); + + // Fill with white background. + context.fillStyle = 'rgb(255,255,255)'; + context.fillRect(0, 0, canvas.width, canvas.height ); + + // Draw 200 balls of various colors at various positions. + for (let j = 0; j < 200; j++) { + const i = (j + frame_number) % 200; + const t = (frame_number + 3000) * (0.01 + i / 8000.0); + const x = (Math.sin( t ) * 0.45 + 0.5) * canvas.width; + const y = (Math.cos( t * 0.9 ) * 0.45 + 0.5) * canvas.height; + context.fillStyle = 'rgb(' + (255 - i) + ',' + (155 +i) + ', ' + i + ')'; + context.beginPath(); + context.arc(x, y, 50, 0, Math.PI * 2, true); + context.closePath(); + context.fill(); + } +} +</script> +</head> +<body onload="requestAnimationFrame(drawForever);"> + <canvas width="1920" height="1080"/> +</body> +</html>
diff --git a/chrome/test/data/extensions/api_test/tab_capture/performance.html b/chrome/test/data/extensions/api_test/tab_capture/performance.html deleted file mode 100644 index 8cdc3406..0000000 --- a/chrome/test/data/extensions/api_test/tab_capture/performance.html +++ /dev/null
@@ -1,7 +0,0 @@ -<html> -<head> -<script src="performance.js"></script> -</head> -<body> -</body> -</html>
diff --git a/chrome/test/data/extensions/api_test/tab_capture/performance.js b/chrome/test/data/extensions/api_test/tab_capture/performance.js deleted file mode 100644 index d869a489e..0000000 --- a/chrome/test/data/extensions/api_test/tab_capture/performance.js +++ /dev/null
@@ -1,142 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// The tests here cover the end-to-end functionality of tab capturing and -// playback as video. The page generates a test patter (moving balls) and -// the rendering output of the tab is captured into a LocalMediaStream. Then, -// the LocalMediaStream is plugged into a video element for playback. -// - -// Global to prevent gc from eating the video tag. -var video = null; -var captureStream = null; - -function stopStream(stream) { - const tracks = stream.getTracks(); - for (let i = 0; i < tracks.length; ++i) { - tracks[i].stop(); - } - chrome.test.assertFalse(stream.active); -} - -function connectToVideoAndRunTest(stream) { - if (!stream) { - chrome.test.fail(chrome.runtime.lastError.message || 'null stream'); - return; - } - - // Create the video element, to play out the captured video; but there's no - // need to append it to the DOM. - video = document.createElement("video"); - video.width = 1920; - video.height = 1080; - video.addEventListener("error", chrome.test.fail); - - // Create a canvas and add it to the test page being captured. The draw() - // function below will update the canvas's content, triggering tab capture for - // each animation frame. - var canvas = document.createElement("canvas"); - canvas.width = video.width; - canvas.height = video.height; - var context = canvas.getContext("2d"); - document.body.appendChild(canvas); - var start_time = new Date().getTime(); - - // Play the LocalMediaStream in the video element. - video.srcObject = stream; - video.play(); - - var frame = 0; - function draw() { - // Run for 15 seconds. - if (new Date().getTime() - start_time > 15000) { - chrome.test.succeed(); - // Note that the API testing framework might not terminate if we keep - // animating and capturing, so we have to make sure that we stop doing - // that here. - if (captureStream) { - stopStream(captureStream); - captureStream = null; - } - stopStream(stream); - return; - } - requestAnimationFrame(draw); - frame = frame + 1; - context.fillStyle = 'rgb(255,255,255)'; - context.fillRect(0, 0, canvas.width, canvas.height ); - for (var j = 0; j < 200; j++) { - var i = (j + frame) % 200; - var t = (frame + 3000) * (0.01 + i / 8000.0); - var x = (Math.sin( t ) * 0.45 + 0.5) * canvas.width; - var y = (Math.cos( t * 0.9 ) * 0.45 + 0.5) * canvas.height; - context.fillStyle = 'rgb(' + (255 - i) + ',' + (155 +i) + ', ' + i + ')'; - context.beginPath(); - context.arc(x, y, 50, 0, Math.PI * 2, true); - context.closePath(); - context.fill(); - } - } - - // Kick it off. - draw(); -} - -// Set up a WebRTC connection and pipe |stream| through it. -function testThroughWebRTC(stream) { - captureStream = stream; - console.log("Testing through webrtc."); - var sender = new RTCPeerConnection(); - var receiver = new RTCPeerConnection(); - sender.onicecandidate = function (event) { - if (event.candidate) { - receiver.addIceCandidate(new RTCIceCandidate(event.candidate)); - } - }; - receiver.onicecandidate = function (event) { - if (event.candidate) { - sender.addIceCandidate(new RTCIceCandidate(event.candidate)); - } - }; - receiver.onaddstream = function (event) { - connectToVideoAndRunTest(event.stream); - }; - sender.addStream(stream); - sender.createOffer(function (sender_description) { - sender.setLocalDescription(sender_description); - receiver.setRemoteDescription(sender_description); - receiver.createAnswer(function (receiver_description) { - receiver.setLocalDescription(receiver_description); - sender.setRemoteDescription(receiver_description); - }, function() { - }); - }, function() { - }); -} - -function tabCapturePerformanceTest() { - var f = connectToVideoAndRunTest; - if (parseInt(window.location.href.split('?WebRTC=')[1])) { - f = testThroughWebRTC; - } - var fps = parseInt(window.location.href.split('&fps=')[1]); - chrome.tabCapture.capture( - { video: true, audio: false, - videoConstraints: { - mandatory: { - minWidth: 1920, - minHeight: 1080, - maxWidth: 1920, - maxHeight: 1080, - maxFrameRate: fps, - } - } - }, - f); -} - -chrome.test.runTests([ tabCapturePerformanceTest ]); - -// TODO(hubbe): Consider capturing audio as well, need to figure out how to -// capture relevant statistics for that though.
diff --git a/chrome/test/data/extensions/api_test/tab_capture/perftest_extension/background.js b/chrome/test/data/extensions/api_test/tab_capture/perftest_extension/background.js new file mode 100644 index 0000000..451aad9 --- /dev/null +++ b/chrome/test/data/extensions/api_test/tab_capture/perftest_extension/background.js
@@ -0,0 +1,123 @@ +// 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. + +console.log('Registering chrome.runtime message listener...'); + +chrome.runtime.onMessageExternal.addListener((request, from, sendResponse) => { + if (!request.start) { + return; + } + + const kCallbackTimeoutMillis = 10000; + + if (window.currentStream) { + sendResponse({success: false, reason: 'Already started!'}); + return; + } + + // Start capture and wait up to kCallbackTimeoutMillis for it to start. + const startCapturePromise = new Promise((resolve, reject) => { + const timeoutId = setTimeout(() => { + reject(Error('chrome.tabCapture.capture() did not call back')); + }, kCallbackTimeoutMillis); + + const captureOptions = { + video: true, + audio: false, + videoConstraints: { + mandatory: { + minWidth: 1920, + minHeight: 1080, + maxWidth: 1920, + maxHeight: 1080, + maxFrameRate: 60, + } + } + }; + console.log('Starting tab capture...'); + chrome.tabCapture.capture(captureOptions, captureStream => { + clearTimeout(timeoutId); + if (captureStream) { + console.log('Started tab capture.'); + resolve(captureStream); + } else { + if (chrome.runtime.lastError) { + reject(chrome.runtime.lastError); + } else { + reject(Error('null stream')); + } + } + }); + }); + + // Then, start streaming the data via WebRTC (or nothing, depending on the + // request). + const startStreamingPromise = startCapturePromise.then(captureStream => { + return new Promise((resolve, reject) => { + if (!request.passThroughWebRTC) { + resolve(captureStream); + return; + } + + const timeoutId = setTimeout(() => { + reject(Error('receiver did not get a stream')); + }, kCallbackTimeoutMillis); + + console.log('Routing through RTCPeerConnection...'); + const sender = new RTCPeerConnection(); + const receiver = new RTCPeerConnection(); + sender.addStream(captureStream); + sender.onicecandidate = (event) => { + if (event.candidate) { + receiver.addIceCandidate(new RTCIceCandidate(event.candidate)); + } + }; + receiver.onicecandidate = (event) => { + if (event.candidate) { + sender.addIceCandidate(new RTCIceCandidate(event.candidate)); + } + }; + receiver.onaddstream = (event) => { + console.log('Receiving stream...'); + resolve(event.stream); + }; + sender.createOffer((sender_description) => { + sender.setLocalDescription(sender_description); + receiver.setRemoteDescription(sender_description); + receiver.createAnswer((receiver_description) => { + receiver.setLocalDescription(receiver_description); + sender.setRemoteDescription(receiver_description); + }, reject); + }, reject); + + window.rtcSender = sender; + window.rtcReceiver = receiver; + }); + }); + + // Plug the capture into a video element to finish assembling the end-to-end + // system. + startStreamingPromise.then(receiveStream => { + console.log('Starting receiver video playback...'); + window.currentStream = receiveStream; + window.receiverVideo = document.createElement('video'); + window.receiverVideo.srcObject = receiveStream; + window.receiverVideo.play(); + + console.log('Sending success response...'); + sendResponse({success: true}); + }).catch(error => { + console.log('Sending error response...'); + let errorMessage; + if (typeof error === 'object' && + ('stack' in error || 'message' in error)) { + errorMessage = (error.stack || error.message); + } else { + errorMessage = String(error); + } + sendResponse({success: false, reason: errorMessage}); + }); + + return true; // Indicate that sendResponse() will be called asynchronously. +});
diff --git a/chrome/test/data/extensions/api_test/tab_capture/perftest_extension/manifest.json b/chrome/test/data/extensions/api_test/tab_capture/perftest_extension/manifest.json new file mode 100644 index 0000000..0a51aaa --- /dev/null +++ b/chrome/test/data/extensions/api_test/tab_capture/perftest_extension/manifest.json
@@ -0,0 +1,15 @@ +{ + "key": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC8xv6iO+j4kzj1HiBL93+XVJH/CRyAQMUHS/Z0l8nCAzaAFkW/JsNwxJqQhrZspnxLqbQxNncXs6g6bsXAwKHiEs+LSs+bIv0Gc/2ycZdhXJ8GhEsSMakog5dpQd1681c2gLK/8CrAoewE/0GIKhaFcp7a2iZlGh4Am6fgMKy0iQIDAQAB", + "name": "TabCapturePerformanceTest extension", + "version": "1", + "manifest_version": 2, + "description": "Launches tabCapture on an active tab.", + "permissions": ["tabs", "tabCapture"], + "background": { + "scripts": ["background.js"], + "persistent": true + }, + "externally_connectable": { + "matches": ["*://*.chromium.org/*"] + } +}
diff --git a/chrome/test/data/lazyload/css-background-image.html b/chrome/test/data/lazyload/css-background-image.html deleted file mode 100644 index 336c596..0000000 --- a/chrome/test/data/lazyload/css-background-image.html +++ /dev/null
@@ -1,22 +0,0 @@ -<!DOCTYPE html> -<html> -<style> -div.css_bg_image { - height: 800px; - background-color: #cccccc; -} -div.a { - background-image: url("images/fruit1.jpg"); -} -div.b { - background-image: url("images/fruit2.jpg"); -} -</style> - -<body> - <div style="height:10000px;"></div> - <a name="images"></a> - <div class="css_bg_image a"></div> - <div class="css_bg_image b"></div> -</body> -</html>
diff --git a/chrome/test/data/lazyload/images/fruit1.jpg b/chrome/test/data/lazyload/images/fruit1.jpg deleted file mode 100644 index 1b7005f..0000000 --- a/chrome/test/data/lazyload/images/fruit1.jpg +++ /dev/null Binary files differ
diff --git a/chrome/test/data/lazyload/images/fruit2.jpg b/chrome/test/data/lazyload/images/fruit2.jpg deleted file mode 100644 index 1b7005f..0000000 --- a/chrome/test/data/lazyload/images/fruit2.jpg +++ /dev/null Binary files differ
diff --git a/chrome/test/data/webui/bookmarks/bookmarks_browsertest.js b/chrome/test/data/webui/bookmarks/bookmarks_browsertest.js index ce10b564..fe0f84d 100644 --- a/chrome/test/data/webui/bookmarks/bookmarks_browsertest.js +++ b/chrome/test/data/webui/bookmarks/bookmarks_browsertest.js
@@ -3,7 +3,7 @@ // found in the LICENSE file. /** - * @fileoverview Test suite for the Material Design bookmarks page. + * @fileoverview Test suite for the bookmarks page. */ const ROOT_PATH = '../../../../../'; @@ -12,14 +12,14 @@ GEN('#include "chrome/browser/prefs/incognito_mode_prefs.h"'); GEN('#include "chrome/browser/ui/webui/bookmarks/bookmarks_browsertest.h"'); -function MaterialBookmarksBrowserTest() {} +function BookmarksBrowserTest() {} -MaterialBookmarksBrowserTest.prototype = { +BookmarksBrowserTest.prototype = { __proto__: PolymerTest.prototype, browsePreload: 'chrome://bookmarks', - typedefCppFixture: 'MdBookmarksBrowserTest', + typedefCppFixture: 'BookmarksBrowserTest', extraLibraries: PolymerTest.getLibraries(ROOT_PATH).concat([ '../test_store.js', @@ -33,56 +33,56 @@ runAccessibilityChecks: true, }; -function MaterialBookmarksActionsTest() {} +function BookmarksActionsTest() {} -MaterialBookmarksActionsTest.prototype = { - __proto__: MaterialBookmarksBrowserTest.prototype, +BookmarksActionsTest.prototype = { + __proto__: BookmarksBrowserTest.prototype, - extraLibraries: MaterialBookmarksBrowserTest.prototype.extraLibraries.concat([ + extraLibraries: BookmarksBrowserTest.prototype.extraLibraries.concat([ 'actions_test.js', ]), }; -TEST_F('MaterialBookmarksActionsTest', 'All', function() { +TEST_F('BookmarksActionsTest', 'All', function() { mocha.run(); }); -function MaterialBookmarksAppTest() {} +function BookmarksAppTest() {} -MaterialBookmarksAppTest.prototype = { - __proto__: MaterialBookmarksBrowserTest.prototype, +BookmarksAppTest.prototype = { + __proto__: BookmarksBrowserTest.prototype, - extraLibraries: MaterialBookmarksBrowserTest.prototype.extraLibraries.concat([ + extraLibraries: BookmarksBrowserTest.prototype.extraLibraries.concat([ 'app_test.js', ROOT_PATH + 'ui/webui/resources/js/util.js', ]), }; -TEST_F('MaterialBookmarksAppTest', 'All', function() { +TEST_F('BookmarksAppTest', 'All', function() { mocha.run(); }); -function MaterialBookmarksCommandManagerTest() {} +function BookmarksCommandManagerTest() {} -MaterialBookmarksCommandManagerTest.prototype = { - __proto__: MaterialBookmarksBrowserTest.prototype, +BookmarksCommandManagerTest.prototype = { + __proto__: BookmarksBrowserTest.prototype, - extraLibraries: MaterialBookmarksBrowserTest.prototype.extraLibraries.concat([ + extraLibraries: BookmarksBrowserTest.prototype.extraLibraries.concat([ '../settings/test_util.js', 'command_manager_test.js', ]), }; -TEST_F('MaterialBookmarksCommandManagerTest', 'All', function() { +TEST_F('BookmarksCommandManagerTest', 'All', function() { mocha.run(); }); -function MaterialBookmarksDNDManagerTest() {} +function BookmarksDNDManagerTest() {} -MaterialBookmarksDNDManagerTest.prototype = { - __proto__: MaterialBookmarksBrowserTest.prototype, +BookmarksDNDManagerTest.prototype = { + __proto__: BookmarksBrowserTest.prototype, - extraLibraries: MaterialBookmarksBrowserTest.prototype.extraLibraries.concat([ + extraLibraries: BookmarksBrowserTest.prototype.extraLibraries.concat([ 'dnd_manager_test.js', ]), }; @@ -94,165 +94,165 @@ GEN('#define MAYBE_All All'); GEN('#endif'); -TEST_F('MaterialBookmarksDNDManagerTest', 'MAYBE_All', function() { +TEST_F('BookmarksDNDManagerTest', 'MAYBE_All', function() { mocha.run(); }); -function MaterialBookmarksEditDialogTest() {} +function BookmarksEditDialogTest() {} -MaterialBookmarksEditDialogTest.prototype = { - __proto__: MaterialBookmarksBrowserTest.prototype, +BookmarksEditDialogTest.prototype = { + __proto__: BookmarksBrowserTest.prototype, - extraLibraries: MaterialBookmarksBrowserTest.prototype.extraLibraries.concat([ + extraLibraries: BookmarksBrowserTest.prototype.extraLibraries.concat([ 'edit_dialog_test.js', ]), }; -TEST_F('MaterialBookmarksEditDialogTest', 'All', function() { +TEST_F('BookmarksEditDialogTest', 'All', function() { mocha.run(); }); -function MaterialBookmarksItemTest() {} +function BookmarksItemTest() {} -MaterialBookmarksItemTest.prototype = { - __proto__: MaterialBookmarksBrowserTest.prototype, +BookmarksItemTest.prototype = { + __proto__: BookmarksBrowserTest.prototype, - extraLibraries: MaterialBookmarksBrowserTest.prototype.extraLibraries.concat([ + extraLibraries: BookmarksBrowserTest.prototype.extraLibraries.concat([ 'item_test.js', ]), }; -TEST_F('MaterialBookmarksItemTest', 'All', function() { +TEST_F('BookmarksItemTest', 'All', function() { mocha.run(); }); -function MaterialBookmarksListTest() {} +function BookmarksListTest() {} -MaterialBookmarksListTest.prototype = { - __proto__: MaterialBookmarksBrowserTest.prototype, +BookmarksListTest.prototype = { + __proto__: BookmarksBrowserTest.prototype, - extraLibraries: MaterialBookmarksBrowserTest.prototype.extraLibraries.concat([ + extraLibraries: BookmarksBrowserTest.prototype.extraLibraries.concat([ 'list_test.js', ]), }; -TEST_F('MaterialBookmarksListTest', 'All', function() { +TEST_F('BookmarksListTest', 'All', function() { mocha.run(); }); -function MaterialBookmarksReducersTest() {} +function BookmarksReducersTest() {} -MaterialBookmarksReducersTest.prototype = { - __proto__: MaterialBookmarksBrowserTest.prototype, +BookmarksReducersTest.prototype = { + __proto__: BookmarksBrowserTest.prototype, - extraLibraries: MaterialBookmarksBrowserTest.prototype.extraLibraries.concat([ + extraLibraries: BookmarksBrowserTest.prototype.extraLibraries.concat([ 'reducers_test.js', ]), }; -TEST_F('MaterialBookmarksReducersTest', 'All', function() { +TEST_F('BookmarksReducersTest', 'All', function() { mocha.run(); }); -function MaterialBookmarksRouterTest() {} +function BookmarksRouterTest() {} -MaterialBookmarksRouterTest.prototype = { - __proto__: MaterialBookmarksBrowserTest.prototype, +BookmarksRouterTest.prototype = { + __proto__: BookmarksBrowserTest.prototype, - extraLibraries: MaterialBookmarksBrowserTest.prototype.extraLibraries.concat([ + extraLibraries: BookmarksBrowserTest.prototype.extraLibraries.concat([ 'router_test.js', ]), }; -TEST_F('MaterialBookmarksRouterTest', 'All', function() { +TEST_F('BookmarksRouterTest', 'All', function() { mocha.run(); }); -function MaterialBookmarksFolderNodeTest() {} +function BookmarksFolderNodeTest() {} -MaterialBookmarksFolderNodeTest.prototype = { - __proto__: MaterialBookmarksBrowserTest.prototype, +BookmarksFolderNodeTest.prototype = { + __proto__: BookmarksBrowserTest.prototype, - extraLibraries: MaterialBookmarksBrowserTest.prototype.extraLibraries.concat([ + extraLibraries: BookmarksBrowserTest.prototype.extraLibraries.concat([ 'folder_node_test.js', ]), }; -TEST_F('MaterialBookmarksFolderNodeTest', 'All', function() { +TEST_F('BookmarksFolderNodeTest', 'All', function() { mocha.run(); }); -function MaterialBookmarksToastManagerTest() {} +function BookmarksToastManagerTest() {} -MaterialBookmarksToastManagerTest.prototype = { - __proto__: MaterialBookmarksBrowserTest.prototype, +BookmarksToastManagerTest.prototype = { + __proto__: BookmarksBrowserTest.prototype, - extraLibraries: MaterialBookmarksBrowserTest.prototype.extraLibraries.concat([ + extraLibraries: BookmarksBrowserTest.prototype.extraLibraries.concat([ 'toast_manager_test.js', ]), }; -TEST_F('MaterialBookmarksToastManagerTest', 'All', function() { +TEST_F('BookmarksToastManagerTest', 'All', function() { mocha.run(); }); -function MaterialBookmarksPolicyTest() {} +function BookmarksPolicyTest() {} -MaterialBookmarksPolicyTest.prototype = { - __proto__: MaterialBookmarksBrowserTest.prototype, +BookmarksPolicyTest.prototype = { + __proto__: BookmarksBrowserTest.prototype, testGenPreamble: function() { GEN('SetIncognitoAvailability(IncognitoModePrefs::DISABLED);'); GEN('SetCanEditBookmarks(false);'); }, - extraLibraries: MaterialBookmarksBrowserTest.prototype.extraLibraries.concat([ + extraLibraries: BookmarksBrowserTest.prototype.extraLibraries.concat([ 'policy_test.js', ]), }; -TEST_F('MaterialBookmarksPolicyTest', 'All', function() { +TEST_F('BookmarksPolicyTest', 'All', function() { mocha.run(); }); -function MaterialBookmarksStoreTest() {} +function BookmarksStoreTest() {} -MaterialBookmarksStoreTest.prototype = { - __proto__: MaterialBookmarksBrowserTest.prototype, +BookmarksStoreTest.prototype = { + __proto__: BookmarksBrowserTest.prototype, - extraLibraries: MaterialBookmarksBrowserTest.prototype.extraLibraries.concat([ + extraLibraries: BookmarksBrowserTest.prototype.extraLibraries.concat([ 'store_test.js', ]), }; -TEST_F('MaterialBookmarksStoreTest', 'All', function() { +TEST_F('BookmarksStoreTest', 'All', function() { mocha.run(); }); -function MaterialBookmarksToolbarTest() {} +function BookmarksToolbarTest() {} -MaterialBookmarksToolbarTest.prototype = { - __proto__: MaterialBookmarksBrowserTest.prototype, +BookmarksToolbarTest.prototype = { + __proto__: BookmarksBrowserTest.prototype, - extraLibraries: MaterialBookmarksBrowserTest.prototype.extraLibraries.concat([ + extraLibraries: BookmarksBrowserTest.prototype.extraLibraries.concat([ 'toolbar_test.js', ]), }; -TEST_F('MaterialBookmarksToolbarTest', 'All', function() { +TEST_F('BookmarksToolbarTest', 'All', function() { mocha.run(); }); -function MaterialBookmarksUtilTest() {} +function BookmarksUtilTest() {} -MaterialBookmarksUtilTest.prototype = { - __proto__: MaterialBookmarksBrowserTest.prototype, +BookmarksUtilTest.prototype = { + __proto__: BookmarksBrowserTest.prototype, - extraLibraries: MaterialBookmarksBrowserTest.prototype.extraLibraries.concat([ + extraLibraries: BookmarksBrowserTest.prototype.extraLibraries.concat([ 'util_test.js', ]), }; -TEST_F('MaterialBookmarksUtilTest', 'All', function() { +TEST_F('BookmarksUtilTest', 'All', function() { mocha.run(); });
diff --git a/chrome/test/data/webui/bookmarks/bookmarks_focus_test.js b/chrome/test/data/webui/bookmarks/bookmarks_focus_test.js index bc6bc905..6743624 100644 --- a/chrome/test/data/webui/bookmarks/bookmarks_focus_test.js +++ b/chrome/test/data/webui/bookmarks/bookmarks_focus_test.js
@@ -3,7 +3,7 @@ // found in the LICENSE file. /** - * @fileoverview Tests for MD Bookmarks which are run as interactive ui tests. + * @fileoverview Tests for Bookmarks which are run as interactive ui tests. * Should be used for tests which care about focus. */ @@ -12,9 +12,9 @@ GEN_INCLUDE( [ROOT_PATH + 'chrome/test/data/webui/polymer_interactive_ui_test.js']); -function MaterialBookmarksFocusTest() {} +function BookmarksFocusTest() {} -MaterialBookmarksFocusTest.prototype = { +BookmarksFocusTest.prototype = { __proto__: PolymerInteractiveUITest.prototype, browsePreload: 'chrome://bookmarks', @@ -29,7 +29,7 @@ ]), }; -TEST_F('MaterialBookmarksFocusTest', 'All', function() { +TEST_F('BookmarksFocusTest', 'All', function() { suite('<bookmarks-folder-node>', function() { let rootNode; let store;
diff --git a/chrome/test/data/webui/settings/multidevice_subpage_tests.js b/chrome/test/data/webui/settings/multidevice_subpage_tests.js index b57edeb..6947216 100644 --- a/chrome/test/data/webui/settings/multidevice_subpage_tests.js +++ b/chrome/test/data/webui/settings/multidevice_subpage_tests.js
@@ -61,6 +61,7 @@ messagesState: pairingComplete ? settings.MultiDeviceFeatureState.ENABLED_BY_USER : settings.MultiDeviceFeatureState.FURTHER_SETUP_REQUIRED, + isAndroidSmsPairingComplete: pairingComplete, }); Polymer.dom.flush(); }
diff --git a/chrome/test/data/webui/settings/site_entry_tests.js b/chrome/test/data/webui/settings/site_entry_tests.js index 62d9518..c558d4dc 100644 --- a/chrome/test/data/webui/settings/site_entry_tests.js +++ b/chrome/test/data/webui/settings/site_entry_tests.js
@@ -140,48 +140,93 @@ assertTrue(overflowMenuButton.closest('.row-aligned').hidden); }); + function resetSettingsViaOverflowMenu(buttonType) { + assertTrue(buttonType == 'cancel-button' || buttonType == 'action-button'); + Polymer.dom.flush(); + const overflowMenuButton = testElement.$.overflowMenuButton; + assertFalse(overflowMenuButton.closest('.row-aligned').hidden); + // Open the reset settings dialog and make sure both cancelling the + // action and resetting all permissions work. + const overflowMenu = testElement.$.menu.get(); + const menuItems = overflowMenu.querySelectorAll('.dropdown-item'); + + // Test clicking on the overflow menu button opens the menu. + assertFalse(overflowMenu.open); + overflowMenuButton.click(); + assertTrue(overflowMenu.open); + + // Open the reset settings dialog and tap the |buttonType| button. + assertFalse(testElement.$.confirmResetSettings.open); + menuItems[0].click(); + assertTrue(testElement.$.confirmResetSettings.open); + const actionButtonList = + testElement.$.confirmResetSettings.getElementsByClassName(buttonType); + assertEquals(1, actionButtonList.length); + actionButtonList[0].click(); + + // Check the dialog and overflow menu are now both closed. + assertFalse(testElement.$.confirmResetSettings.open); + assertFalse(overflowMenu.open); + } + + test('cancelling the confirm dialog on resetting settings works', function() { + testElement.siteGroup = TEST_MULTIPLE_SITE_GROUP; + resetSettingsViaOverflowMenu('cancel-button'); + }); + test( 'with multiple origins can reset settings via overflow menu', function() { - testElement.siteGroup = TEST_MULTIPLE_SITE_GROUP; - Polymer.dom.flush(); - const overflowMenuButton = testElement.$.overflowMenuButton; - assertFalse(overflowMenuButton.closest('.row-aligned').hidden); - - // Open the reset settings dialog and make sure both cancelling the - // action and resetting all permissions work. - const overflowMenu = testElement.$.menu.get(); - const menuItems = overflowMenu.querySelectorAll('.dropdown-item'); - ['cancel-button', 'action-button'].forEach(buttonType => { - // Test clicking on the overflow menu button opens the menu. - assertFalse(overflowMenu.open); - overflowMenuButton.click(); - assertTrue(overflowMenu.open); - - // Open the reset settings dialog and tap the |buttonType| button. - assertFalse(testElement.$.confirmResetSettings.open); - menuItems[0].click(); - assertTrue(testElement.$.confirmResetSettings.open); - const actionButtonList = - testElement.$.confirmResetSettings.getElementsByClassName( - buttonType); - assertEquals(1, actionButtonList.length); - actionButtonList[0].click(); - - // Check the dialog and overflow menu are now both closed. - assertFalse(testElement.$.confirmResetSettings.open); - assertFalse(overflowMenu.open); + let deleteCurrentEntryCalled = false; + testElement.addEventListener('delete-current-entry', function() { + deleteCurrentEntryCalled = true; }); + // Test when entire siteGroup has no data or cookies. + // Clone this object to avoid propagating changes made in this test. + testElement.siteGroup = + JSON.parse(JSON.stringify(TEST_MULTIPLE_SITE_GROUP)); + resetSettingsViaOverflowMenu('action-button'); // Ensure a call was made to setOriginPermissions for each origin. assertEquals( TEST_MULTIPLE_SITE_GROUP.origins.length, browserProxy.getCallCount('setOriginPermissions')); + assertTrue(deleteCurrentEntryCalled); + + // Test when one origin has data and cookies. + // Clone this object to avoid propagating changes made in this test. + testElement.siteGroup = + JSON.parse(JSON.stringify(TEST_MULTIPLE_SITE_GROUP)); + testElement.siteGroup.origins[0].hasPermissionSettings = true; + testElement.siteGroup.origins[0].usage = 100; + testElement.siteGroup.origins[0].numCookies = 2; + deleteCurrentEntryCalled = false; + resetSettingsViaOverflowMenu('action-button'); + assertFalse(deleteCurrentEntryCalled); + assertEquals(1, testElement.siteGroup.origins.length); + assertFalse(testElement.siteGroup.origins[0].hasPermissionSettings); + assertEquals(testElement.siteGroup.origins[0].usage, 100); + assertEquals(testElement.siteGroup.origins[0].numCookies, 2); + + // Test when none of origin have data or cookies, but etld+1 has + // cookies. In this case, a placeholder origin will be created with the + // Etld+1 cookies number. Clone this object to avoid propagating changes + // made in this test. + testElement.siteGroup = + JSON.parse(JSON.stringify(TEST_MULTIPLE_SITE_GROUP)); + testElement.siteGroup.numCookies = 5; + deleteCurrentEntryCalled = false; + resetSettingsViaOverflowMenu('action-button'); + assertFalse(deleteCurrentEntryCalled); + assertEquals(1, testElement.siteGroup.origins.length); + assertFalse(testElement.siteGroup.origins[0].hasPermissionSettings); + assertEquals(testElement.siteGroup.origins[0].usage, 0); + assertEquals(testElement.siteGroup.origins[0].numCookies, 5); }); test( 'moving from grouped to ungrouped does not get stuck in opened state', function() { - // Clone this object to avoid propogating changes made in this test. + // Clone this object to avoid propagating changes made in this test. testElement.siteGroup = JSON.parse(JSON.stringify(TEST_MULTIPLE_SITE_GROUP)); Polymer.dom.flush(); @@ -242,7 +287,7 @@ }); test('data usage shown correctly for grouped entries', function() { - // Clone this object to avoid propogating changes made in this test. + // Clone this object to avoid propagating changes made in this test. const testSiteGroup = JSON.parse(JSON.stringify(TEST_MULTIPLE_SITE_GROUP)); const numBytes1 = 74622; const numBytes2 = 1274; @@ -262,7 +307,7 @@ }); test('data usage shown correctly for ungrouped entries', function() { - // Clone this object to avoid propogating changes made in this test. + // Clone this object to avoid propagating changes made in this test. const testSiteGroup = JSON.parse(JSON.stringify(TEST_SINGLE_SITE_GROUP)); const numBytes = 74622; testSiteGroup.origins[0].usage = numBytes; @@ -276,4 +321,78 @@ }); }); + + function clearDataViaOverflowMenu(buttonType) { + assertTrue(buttonType == 'cancel-button' || buttonType == 'action-button'); + Polymer.dom.flush(); + const overflowMenuButton = testElement.$.overflowMenuButton; + assertFalse(overflowMenuButton.closest('.row-aligned').hidden); + + // Open the clear data dialog and make sure both cancelling the + // action and resetting all permissions work. + const overflowMenu = testElement.$.menu.get(); + const menuItems = overflowMenu.querySelectorAll('.dropdown-item'); + // Test clicking on the overflow menu button opens the menu. + assertFalse(overflowMenu.open); + overflowMenuButton.click(); + assertTrue(overflowMenu.open); + + // Open the clear data dialog and tap the |buttonType| button. + assertFalse(testElement.$.confirmClearData.open); + menuItems[1].click(); + assertTrue(testElement.$.confirmClearData.open); + const actionButtonList = + testElement.$.confirmClearData.getElementsByClassName(buttonType); + assertEquals(1, actionButtonList.length); + actionButtonList[0].click(); + + // Check the dialog and overflow menu are now both closed. + assertFalse(testElement.$.confirmClearData.open); + assertFalse(overflowMenu.open); + } + + test('cancelling the confirm dialog on clear data works', function() { + testElement.siteGroup = TEST_MULTIPLE_SITE_GROUP; + clearDataViaOverflowMenu('cancel-button'); + }); + + test('with multiple origins can clear data via overflow menu', function() { + let deleteCurrentEntryCalled = false; + testElement.addEventListener('delete-current-entry', function() { + deleteCurrentEntryCalled = true; + }); + // Test when all origins has no permission settings and no data. + // Clone this object to avoid propagating changes made in this test. + testElement.siteGroup = + JSON.parse(JSON.stringify(TEST_MULTIPLE_SITE_GROUP)); + clearDataViaOverflowMenu('action-button'); + // Ensure a call was made to clearEtldPlus1DataAndCookies. + assertEquals(1, browserProxy.getCallCount('clearEtldPlus1DataAndCookies')); + assertTrue(deleteCurrentEntryCalled); + + // Test when there is one origin has permissions settings. + // Clone this object to avoid propagating changes made in this test. + testElement.siteGroup = + JSON.parse(JSON.stringify(TEST_MULTIPLE_SITE_GROUP)); + deleteCurrentEntryCalled = false; + testElement.siteGroup.origins[0].hasPermissionSettings = true; + clearDataViaOverflowMenu('action-button'); + assertFalse(deleteCurrentEntryCalled); + assertEquals(testElement.siteGroup.origins.length, 1); + + // Test when one origin has permission settings and data, clear data only + // clears the data and cookies. + testElement.siteGroup = + JSON.parse(JSON.stringify(TEST_MULTIPLE_SITE_GROUP)); + deleteCurrentEntryCalled = false; + testElement.siteGroup.origins[0].hasPermissionSettings = true; + testElement.siteGroup.origins[0].usage = 100; + testElement.siteGroup.origins[0].numCookies = 3; + clearDataViaOverflowMenu('action-button'); + assertFalse(deleteCurrentEntryCalled); + assertEquals(testElement.siteGroup.origins.length, 1); + assertTrue(testElement.siteGroup.origins[0].hasPermissionSettings); + assertEquals(testElement.siteGroup.origins[0].usage, 0); + assertEquals(testElement.siteGroup.origins[0].numCookies, 0); + }); });
diff --git a/chrome/test/data/webui/settings/test_site_settings_prefs_browser_proxy.js b/chrome/test/data/webui/settings/test_site_settings_prefs_browser_proxy.js index e7ac82d..11b26e63 100644 --- a/chrome/test/data/webui/settings/test_site_settings_prefs_browser_proxy.js +++ b/chrome/test/data/webui/settings/test_site_settings_prefs_browser_proxy.js
@@ -49,6 +49,7 @@ 'setOriginPermissions', 'setProtocolDefault', 'updateIncognitoStatus', + 'clearEtldPlus1DataAndCookies', ]); /** @private {boolean} */ @@ -432,4 +433,9 @@ fetchBlockAutoplayStatus() { this.methodCalled('fetchBlockAutoplayStatus'); } + + /** @override */ + clearEtldPlus1DataAndCookies() { + this.methodCalled('clearEtldPlus1DataAndCookies'); + } }
diff --git a/chrome/test/data/webui/settings/test_util.js b/chrome/test/data/webui/settings/test_util.js index df52a80..fcb90f5 100644 --- a/chrome/test/data/webui/settings/test_util.js +++ b/chrome/test/data/webui/settings/test_util.js
@@ -241,6 +241,7 @@ engagement: 0, usage: 0, numCookies: 0, + hasPermissionSettings: false, }, override); }
diff --git a/chromeos/services/device_sync/BUILD.gn b/chromeos/services/device_sync/BUILD.gn index 79b95ed..ce651a8 100644 --- a/chromeos/services/device_sync/BUILD.gn +++ b/chromeos/services/device_sync/BUILD.gn
@@ -26,6 +26,8 @@ "cryptauth_enrollment_manager.h", "cryptauth_enrollment_manager_impl.cc", "cryptauth_enrollment_manager_impl.h", + "cryptauth_enrollment_result.cc", + "cryptauth_enrollment_result.h", "cryptauth_gcm_manager.cc", "cryptauth_gcm_manager.h", "cryptauth_gcm_manager_impl.cc",
diff --git a/chromeos/services/device_sync/cryptauth_enrollment_result.cc b/chromeos/services/device_sync/cryptauth_enrollment_result.cc new file mode 100644 index 0000000..40405b7 --- /dev/null +++ b/chromeos/services/device_sync/cryptauth_enrollment_result.cc
@@ -0,0 +1,53 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chromeos/services/device_sync/cryptauth_enrollment_result.h" + +namespace chromeos { + +namespace device_sync { + +// static +CryptAuthEnrollmentResult::ResultCode +CryptAuthEnrollmentResult::NetworkRequestErrorToResultCode( + NetworkRequestError error) { + switch (error) { + case NetworkRequestError::kOffline: + return CryptAuthEnrollmentResult::ResultCode::kNetworkRequestErrorOffline; + case NetworkRequestError::kEndpointNotFound: + return CryptAuthEnrollmentResult::ResultCode:: + kNetworkRequestErrorEndpointNotFound; + case NetworkRequestError::kAuthenticationError: + return CryptAuthEnrollmentResult::ResultCode:: + kNetworkRequestErrorAuthenticationError; + case NetworkRequestError::kBadRequest: + return CryptAuthEnrollmentResult::ResultCode:: + kNetworkRequestErrorBadRequest; + case NetworkRequestError::kResponseMalformed: + return CryptAuthEnrollmentResult::ResultCode:: + kNetworkRequestErrorResponseMalformed; + case NetworkRequestError::kInternalServerError: + return CryptAuthEnrollmentResult::ResultCode:: + kNetworkRequestErrorInternalServerError; + case NetworkRequestError::kUnknown: + return CryptAuthEnrollmentResult::ResultCode::kNetworkRequestErrorUnknown; + } +} + +CryptAuthEnrollmentResult::CryptAuthEnrollmentResult( + ResultCode result_code, + const base::Optional<cryptauthv2::ClientDirective>& client_directive) + : result_code_(result_code), client_directive_(client_directive) {} + +CryptAuthEnrollmentResult::~CryptAuthEnrollmentResult() = default; + +bool CryptAuthEnrollmentResult::IsSuccess() const { + return result_code_ == ResultCode::kSuccessNoSyncRequired || + result_code_ == ResultCode::kSuccessNewKeysEnrolled || + result_code_ == ResultCode::kSuccessNoNewKeysNeeded; +} + +} // namespace device_sync + +} // namespace chromeos
diff --git a/chromeos/services/device_sync/cryptauth_enrollment_result.h b/chromeos/services/device_sync/cryptauth_enrollment_result.h new file mode 100644 index 0000000..2f23e87f --- /dev/null +++ b/chromeos/services/device_sync/cryptauth_enrollment_result.h
@@ -0,0 +1,82 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROMEOS_SERVICES_DEVICE_SYNC_CRYPTAUTH_ENROLLMENT_RESULT_H_ +#define CHROMEOS_SERVICES_DEVICE_SYNC_CRYPTAUTH_ENROLLMENT_RESULT_H_ + +#include "base/optional.h" +#include "chromeos/services/device_sync/network_request_error.h" +#include "chromeos/services/device_sync/proto/cryptauth_directive.pb.h" + +namespace chromeos { + +namespace device_sync { + +// Information about the result of a CryptAuth v2 Enrollment attempt. +class CryptAuthEnrollmentResult { + public: + // Enum class to denote the result of a CryptAuth v2 Enrollment attempt + enum class ResultCode { + // No SyncKeysRequest was made to CryptAuth because it was not necessary. + kSuccessNoSyncRequired, + // Successfully synced but no new keys were requested by CryptAuth, so no + // EnrollKeysRequest was made. + kSuccessNoNewKeysNeeded, + // Successfully synced and enrolled new key(s) with CryptAuth. + kSuccessNewKeysEnrolled, + // Request could not be completed because the device is offline or has + // issues sending the HTTP request. + kNetworkRequestErrorOffline, + // Server endpoint could not be found. + kNetworkRequestErrorEndpointNotFound, + // Authentication error contacting back-end. + kNetworkRequestErrorAuthenticationError, + // Network request was invalid. + kNetworkRequestErrorBadRequest, + // The server responded, but the response was not formatted correctly. + kNetworkRequestErrorResponseMalformed, + // Internal server error. + kNetworkRequestErrorInternalServerError, + // Unknown network request error. + kNetworkRequestErrorUnknown, + // The CryptAuth server indicated via SyncKeysResponse::server_status that + // it was overloaded and did not process the SyncKeysRequest. + kErrorCryptAuthServerOverloaded, + // An error occurred while performing a cryptographic operation, such as + // generating key proofs. + kErrorCryptographicOperationFailed, + // The size of SyncKeysResponse::sync_single_key_responses does not agree + // with the number of key bundle names. + kErrorSyncKeysResponseIncorrectNumberOfKeys, + // Failed to generate the new keys requested by CryptAuth or the ephemeral + // keys needed for intermediate cryptographic operations. + kErrorKeyCreationFailed + }; + + static ResultCode NetworkRequestErrorToResultCode(NetworkRequestError error); + + CryptAuthEnrollmentResult( + ResultCode result_code, + const base::Optional<cryptauthv2::ClientDirective>& client_directive); + + ~CryptAuthEnrollmentResult(); + + ResultCode result_code() const { return result_code_; } + + const base::Optional<cryptauthv2::ClientDirective>& client_directive() const { + return client_directive_; + }; + + bool IsSuccess() const; + + private: + ResultCode result_code_; + base::Optional<cryptauthv2::ClientDirective> client_directive_; +}; + +} // namespace device_sync + +} // namespace chromeos + +#endif // CHROMEOS_SERVICES_DEVICE_SYNC_CRYPTAUTH_ENROLLMENT_RESULT_H_
diff --git a/components/BUILD.gn b/components/BUILD.gn index f9e89774..6d5a22e 100644 --- a/components/BUILD.gn +++ b/components/BUILD.gn
@@ -128,7 +128,6 @@ "//components/omnibox/browser:unit_tests", "//components/open_from_clipboard:unit_tests", "//components/os_crypt:unit_tests", - "//components/page_image_annotation/core:unit_tests", "//components/password_manager/core/browser:unit_tests", "//components/password_manager/core/common:unit_tests", "//components/payments/core:unit_tests", @@ -239,6 +238,7 @@ "//components/network_hints/renderer:unit_tests", "//components/offline_pages:unit_tests", "//components/optimization_guide:unit_tests", + "//components/page_image_annotation/core:unit_tests", "//components/password_manager/content/browser:unit_tests", "//components/payments/content:unit_tests", "//components/payments/content/utility:unit_tests",
diff --git a/components/cronet/native/cronet.idl b/components/cronet/native/cronet.idl index 0b2d42a6..4470fe1 100644 --- a/components/cronet/native/cronet.idl +++ b/components/cronet/native/cronet.idl
@@ -1181,7 +1181,7 @@ /** * Number of milliseconds since the UNIX epoch. */ - int64 value; + int64 value = 0; }; /*
diff --git a/components/cronet/native/generated/cronet.idl_impl_struct.h b/components/cronet/native/generated/cronet.idl_impl_struct.h index 42e3a2ec34..09264b0 100644 --- a/components/cronet/native/generated/cronet.idl_impl_struct.h +++ b/components/cronet/native/generated/cronet.idl_impl_struct.h
@@ -164,7 +164,7 @@ explicit Cronet_DateTime(Cronet_DateTime&& from); ~Cronet_DateTime(); - int64_t value; + int64_t value = 0; private: DISALLOW_ASSIGN(Cronet_DateTime);
diff --git a/components/cronet/native/generated/cronet.idl_impl_struct_unittest.cc b/components/cronet/native/generated/cronet.idl_impl_struct_unittest.cc index f7e0270..e2d6f1a 100644 --- a/components/cronet/native/generated/cronet.idl_impl_struct_unittest.cc +++ b/components/cronet/native/generated/cronet.idl_impl_struct_unittest.cc
@@ -261,14 +261,8 @@ Cronet_UrlRequestParams_Destroy(second); } -// Fails under MSAN: crbug.com/922842 -#if defined(MEMORY_SANITIZER) -#define MAYBE_TestCronet_DateTime DISABLED_TestCronet_DateTime -#else -#define MAYBE_TestCronet_DateTime TestCronet_DateTime -#endif // Test Struct Cronet_DateTime setters and getters. -TEST_F(CronetStructTest, MAYBE_TestCronet_DateTime) { +TEST_F(CronetStructTest, TestCronet_DateTime) { Cronet_DateTimePtr first = Cronet_DateTime_Create(); Cronet_DateTimePtr second = Cronet_DateTime_Create();
diff --git a/components/leveldb_proto/internal/shared_proto_database.cc b/components/leveldb_proto/internal/shared_proto_database.cc index c8c1a2d7..62211004 100644 --- a/components/leveldb_proto/internal/shared_proto_database.cc +++ b/components/leveldb_proto/internal/shared_proto_database.cc
@@ -58,9 +58,8 @@ db_(std::make_unique<LevelDB>(client_db_id.c_str())), db_wrapper_(std::make_unique<ProtoLevelDBWrapper>(task_runner_)), metadata_db_(std::make_unique<LevelDB>(kMetadataDatabaseName)), - metadata_db_wrapper_(std::make_unique<ProtoLevelDBWrapper>(task_runner_)), - weak_factory_( - std::make_unique<base::WeakPtrFactory<SharedProtoDatabase>>(this)) { + metadata_db_wrapper_( + std::make_unique<ProtoLevelDBWrapper>(task_runner_)) { DETACH_FROM_SEQUENCE(on_task_runner_); } @@ -73,10 +72,9 @@ Callbacks::InitStatusCallback callback) { DCHECK(base::SequencedTaskRunnerHandle::IsSet()); task_runner_->PostTask( - FROM_HERE, - base::BindOnce(&SharedProtoDatabase::RunInitCallback, - weak_factory_->GetWeakPtr(), std::move(callback), - base::SequencedTaskRunnerHandle::Get())); + FROM_HERE, base::BindOnce(&SharedProtoDatabase::RunInitCallback, this, + std::move(callback), + base::SequencedTaskRunnerHandle::Get())); } void SharedProtoDatabase::RunInitCallback( @@ -93,9 +91,8 @@ if (base::SequencedTaskRunnerHandle::Get() != task_runner_) { task_runner_->PostTask( FROM_HERE, - base::BindOnce(&SharedProtoDatabase::UpdateClientMetadataAsync, - weak_factory_->GetWeakPtr(), client_db_id, - migration_status, std::move(callback))); + base::BindOnce(&SharedProtoDatabase::UpdateClientMetadataAsync, this, + client_db_id, migration_status, std::move(callback))); return; } auto update_entries = std::make_unique< @@ -121,9 +118,9 @@ // on the calling sequence. metadata_db_wrapper_->GetEntry<SharedDBMetadataProto>( std::string(client_db_id), - base::BindOnce(&SharedProtoDatabase::OnGetClientMetadata, - weak_factory_->GetWeakPtr(), client_db_id, - std::move(callback), std::move(callback_task_runner))); + base::BindOnce(&SharedProtoDatabase::OnGetClientMetadata, this, + client_db_id, std::move(callback), + std::move(callback_task_runner))); } // As mentioned above, |current_task_runner| is the appropriate calling sequence @@ -251,9 +248,8 @@ metadata_db_wrapper_->InitWithDatabase( metadata_db_.get(), metadata_path, CreateSimpleOptions(), true /* destroy_on_corruption */, - base::BindOnce(&SharedProtoDatabase::OnMetadataInitComplete, - weak_factory_->GetWeakPtr(), create_shared_db_if_missing, - attempt, corruption)); + base::BindOnce(&SharedProtoDatabase::OnMetadataInitComplete, this, + create_shared_db_if_missing, attempt, corruption)); } void SharedProtoDatabase::OnMetadataInitComplete( @@ -282,9 +278,8 @@ // to treat the shared database as corrupt, we can't know for sure anymore. metadata_db_wrapper_->GetEntry<SharedDBMetadataProto>( std::string(kGlobalMetadataKey), - base::BindOnce(&SharedProtoDatabase::OnGetGlobalMetadata, - weak_factory_->GetWeakPtr(), create_shared_db_if_missing, - corruption)); + base::BindOnce(&SharedProtoDatabase::OnGetGlobalMetadata, this, + create_shared_db_if_missing, corruption)); } void SharedProtoDatabase::OnGetGlobalMetadata( @@ -306,8 +301,8 @@ metadata_->set_corruptions(corruption ? 1U : 0U); metadata_->clear_migration_status(); CommitUpdatedGlobalMetadata( - base::BindOnce(&SharedProtoDatabase::OnFinishCorruptionCountWrite, - weak_factory_->GetWeakPtr(), create_shared_db_if_missing)); + base::BindOnce(&SharedProtoDatabase::OnFinishCorruptionCountWrite, this, + create_shared_db_if_missing)); } void SharedProtoDatabase::OnFinishCorruptionCountWrite( @@ -337,8 +332,7 @@ // the InitState will be final after Init is called. db_wrapper_->InitWithDatabase( db_.get(), db_dir_, options, false /* destroy_on_corruption */, - base::BindOnce(&SharedProtoDatabase::OnDatabaseInit, - weak_factory_->GetWeakPtr())); + base::BindOnce(&SharedProtoDatabase::OnDatabaseInit, this)); } void SharedProtoDatabase::OnDatabaseInit(Enums::InitStatus status) { @@ -354,9 +348,8 @@ // serious has gone wrong with the metadata database. metadata_->set_corruptions(metadata_->corruptions() + 1); - CommitUpdatedGlobalMetadata( - base::BindOnce(&SharedProtoDatabase::OnUpdateCorruptionCountAtInit, - weak_factory_->GetWeakPtr())); + CommitUpdatedGlobalMetadata(base::BindOnce( + &SharedProtoDatabase::OnUpdateCorruptionCountAtInit, this)); return; } @@ -410,7 +403,6 @@ SharedProtoDatabase::~SharedProtoDatabase() { task_runner_->DeleteSoon(FROM_HERE, std::move(db_)); task_runner_->DeleteSoon(FROM_HERE, std::move(metadata_db_)); - task_runner_->DeleteSoon(FROM_HERE, std::move(weak_factory_)); } LevelDB* SharedProtoDatabase::GetLevelDBForTesting() const {
diff --git a/components/leveldb_proto/internal/shared_proto_database.h b/components/leveldb_proto/internal/shared_proto_database.h index 074d78a..98107f9 100644 --- a/components/leveldb_proto/internal/shared_proto_database.h +++ b/components/leveldb_proto/internal/shared_proto_database.h
@@ -179,8 +179,6 @@ std::queue<std::unique_ptr<InitRequest>> outstanding_init_requests_; - std::unique_ptr<base::WeakPtrFactory<SharedProtoDatabase>> weak_factory_; - DISALLOW_COPY_AND_ASSIGN(SharedProtoDatabase); }; @@ -218,8 +216,8 @@ SharedProtoDatabaseClient<T>* client_ptr = client.get(); task_runner_->PostTask( FROM_HERE, - base::BindOnce(&SharedProtoDatabase::Init, weak_factory_->GetWeakPtr(), - create_if_missing, client_ptr->client_db_id(), + base::BindOnce(&SharedProtoDatabase::Init, this, create_if_missing, + client_ptr->client_db_id(), base::BindOnce(&GetClientInitCallback<T>, std::move(callback), std::move(client)), std::move(current_task_runner))); @@ -238,9 +236,9 @@ auto client = GetClientInternal<T>(client_namespace, type_prefix); task_runner_->PostTask( FROM_HERE, - base::BindOnce(&SharedProtoDatabase::Init, weak_factory_->GetWeakPtr(), - create_if_missing, client->client_db_id(), - std::move(callback), std::move(current_task_runner))); + base::BindOnce(&SharedProtoDatabase::Init, this, create_if_missing, + client->client_db_id(), std::move(callback), + std::move(current_task_runner))); return client; }
diff --git a/components/leveldb_proto/internal/shared_proto_database_client_unittest.cc b/components/leveldb_proto/internal/shared_proto_database_client_unittest.cc index 4fabc5a..28746d82 100644 --- a/components/leveldb_proto/internal/shared_proto_database_client_unittest.cc +++ b/components/leveldb_proto/internal/shared_proto_database_client_unittest.cc
@@ -25,11 +25,6 @@ const char* kDefaultNamespace2 = "cfd"; const char* kDefaultTypePrefix = "tp"; -void DeleteSoon(scoped_refptr<SharedProtoDatabase> db, - std::unique_ptr<base::ScopedTempDir>) { - db.reset(); -} - } // namespace class SharedProtoDatabaseClientTest : public testing::Test { @@ -42,11 +37,8 @@ } void TearDown() override { - // TODO(ssid): SharedProtoDatabase should use scoped_refptr and this - // shouldn't be required. - db_->database_task_runner_for_testing()->PostTask( - FROM_HERE, - base::BindOnce(&DeleteSoon, std::move(db_), std::move(temp_dir_))); + db_->database_task_runner_for_testing()->DeleteSoon(FROM_HERE, + std::move(temp_dir_)); } protected:
diff --git a/components/leveldb_proto/internal/shared_proto_database_unittest.cc b/components/leveldb_proto/internal/shared_proto_database_unittest.cc index bfdf5c39..d2d2a233 100644 --- a/components/leveldb_proto/internal/shared_proto_database_unittest.cc +++ b/components/leveldb_proto/internal/shared_proto_database_unittest.cc
@@ -56,8 +56,7 @@ SharedClientInitCallback callback) { db_->task_runner_->PostTask( FROM_HERE, - base::BindOnce(&SharedProtoDatabase::Init, - db_->weak_factory_->GetWeakPtr(), create_if_missing, + base::BindOnce(&SharedProtoDatabase::Init, db_, create_if_missing, client_name, std::move(callback), scoped_task_environment_.GetMainThreadTaskRunner())); }
diff --git a/components/omnibox/browser/location_bar_model_impl.cc b/components/omnibox/browser/location_bar_model_impl.cc index 7a1b5b2..377bd973 100644 --- a/components/omnibox/browser/location_bar_model_impl.cc +++ b/components/omnibox/browser/location_bar_model_impl.cc
@@ -50,11 +50,6 @@ #if defined(OS_IOS) format_types |= url_formatter::kFormatUrlTrimAfterHost; -#else - if (base::FeatureList::IsEnabled( - omnibox::kHideSteadyStateUrlPathQueryAndRef)) { - format_types |= url_formatter::kFormatUrlTrimAfterHost; - } #endif if (OmniboxFieldTrial::IsHideSteadyStateUrlSchemeEnabled())
diff --git a/components/omnibox/browser/omnibox_pedal.h b/components/omnibox/browser/omnibox_pedal.h index 578481e..9be53f5 100644 --- a/components/omnibox/browser/omnibox_pedal.h +++ b/components/omnibox/browser/omnibox_pedal.h
@@ -143,6 +143,8 @@ protected: FRIEND_TEST_ALL_PREFIXES(OmniboxPedalTest, SynonymGroupErasesFirstMatchOnly); FRIEND_TEST_ALL_PREFIXES(OmniboxPedalTest, SynonymGroupsDriveConceptMatches); + FRIEND_TEST_ALL_PREFIXES(OmniboxPedalImplementationsTest, + UnorderedSynonymExpressionsAreConceptMatches); // If a sufficient set of triggering synonym groups are present in match_text // then it's a concept match and this returns true. If a required group is
diff --git a/components/omnibox/browser/omnibox_pedal_implementations_unittest.cc b/components/omnibox/browser/omnibox_pedal_implementations_unittest.cc index 59ef623..1127584a 100644 --- a/components/omnibox/browser/omnibox_pedal_implementations_unittest.cc +++ b/components/omnibox/browser/omnibox_pedal_implementations_unittest.cc
@@ -54,3 +54,1902 @@ const GURL& url = omnibox_edit_controller_->destination_url(); EXPECT_EQ(url, GURL("chrome://settings/clearBrowserData")); } + +// Exhaustive test of unordered synonym groups for concept matches; this is +// useful in detecting possible clashes between cross-group synonym strings. +// By ensuring that each set matches for exactly one Pedal, we can also +// prevent clashes between concepts for different Pedals. +TEST_F(OmniboxPedalImplementationsTest, + UnorderedSynonymExpressionsAreConceptMatches) { + const std::vector<std::vector<const char*>> literal_concept_expressions = { + // Note: The lists below are auto-generated from raw synonym group data. + + // Clear Browsing Data + { + "browser cache clear", + "browser cache delete", + "browser cache erase", + "browser cache remove", + "browser cache wipe", + "browser clear cache", + "browser clear data", + "browser clear history", + "browser data clear", + "browser data delete", + "browser data erase", + "browser data remove", + "browser data wipe", + "browser delete cache", + "browser delete data", + "browser delete history", + "browser erase cache", + "browser erase data", + "browser erase history", + "browser history clear", + "browser history delete", + "browser history erase", + "browser history remove", + "browser history wipe", + "browser remove cache", + "browser remove data", + "browser remove history", + "browser wipe cache", + "browser wipe data", + "browser wipe history", + "cache browser clear", + "cache browser delete", + "cache browser erase", + "cache browser remove", + "cache browser wipe", + "cache chrome clear", + "cache chrome delete", + "cache chrome erase", + "cache chrome remove", + "cache chrome wipe", + "cache clear", + "cache clear browser", + "cache clear chrome", + "cache clear google chrome", + "cache delete", + "cache delete browser", + "cache delete chrome", + "cache delete google chrome", + "cache erase", + "cache erase browser", + "cache erase chrome", + "cache erase google chrome", + "cache google chrome clear", + "cache google chrome delete", + "cache google chrome erase", + "cache google chrome remove", + "cache google chrome wipe", + "cache remove", + "cache remove browser", + "cache remove chrome", + "cache remove google chrome", + "cache wipe", + "cache wipe browser", + "cache wipe chrome", + "cache wipe google chrome", + "chrome cache clear", + "chrome cache delete", + "chrome cache erase", + "chrome cache remove", + "chrome cache wipe", + "chrome clear cache", + "chrome clear data", + "chrome clear history", + "chrome data clear", + "chrome data delete", + "chrome data erase", + "chrome data remove", + "chrome data wipe", + "chrome delete cache", + "chrome delete data", + "chrome delete history", + "chrome erase cache", + "chrome erase data", + "chrome erase history", + "chrome history clear", + "chrome history delete", + "chrome history erase", + "chrome history remove", + "chrome history wipe", + "chrome remove cache", + "chrome remove data", + "chrome remove history", + "chrome wipe cache", + "chrome wipe data", + "chrome wipe history", + "clear browser cache", + "clear browser data", + "clear browser history", + "clear cache", + "clear cache browser", + "clear cache chrome", + "clear cache google chrome", + "clear chrome cache", + "clear chrome data", + "clear chrome history", + "clear data", + "clear data browser", + "clear data chrome", + "clear data google chrome", + "clear google chrome cache", + "clear google chrome data", + "clear google chrome history", + "clear history", + "clear history browser", + "clear history chrome", + "clear history google chrome", + "data browser clear", + "data browser delete", + "data browser erase", + "data browser remove", + "data browser wipe", + "data chrome clear", + "data chrome delete", + "data chrome erase", + "data chrome remove", + "data chrome wipe", + "data clear", + "data clear browser", + "data clear chrome", + "data clear google chrome", + "data delete", + "data delete browser", + "data delete chrome", + "data delete google chrome", + "data erase", + "data erase browser", + "data erase chrome", + "data erase google chrome", + "data google chrome clear", + "data google chrome delete", + "data google chrome erase", + "data google chrome remove", + "data google chrome wipe", + "data remove", + "data remove browser", + "data remove chrome", + "data remove google chrome", + "data wipe", + "data wipe browser", + "data wipe chrome", + "data wipe google chrome", + "delete browser cache", + "delete browser data", + "delete browser history", + "delete cache", + "delete cache browser", + "delete cache chrome", + "delete cache google chrome", + "delete chrome cache", + "delete chrome data", + "delete chrome history", + "delete data", + "delete data browser", + "delete data chrome", + "delete data google chrome", + "delete google chrome cache", + "delete google chrome data", + "delete google chrome history", + "delete history", + "delete history browser", + "delete history chrome", + "delete history google chrome", + "erase browser cache", + "erase browser data", + "erase browser history", + "erase cache", + "erase cache browser", + "erase cache chrome", + "erase cache google chrome", + "erase chrome cache", + "erase chrome data", + "erase chrome history", + "erase data", + "erase data browser", + "erase data chrome", + "erase data google chrome", + "erase google chrome cache", + "erase google chrome data", + "erase google chrome history", + "erase history", + "erase history browser", + "erase history chrome", + "erase history google chrome", + "google chrome cache clear", + "google chrome cache delete", + "google chrome cache erase", + "google chrome cache remove", + "google chrome cache wipe", + "google chrome clear cache", + "google chrome clear data", + "google chrome clear history", + "google chrome data clear", + "google chrome data delete", + "google chrome data erase", + "google chrome data remove", + "google chrome data wipe", + "google chrome delete cache", + "google chrome delete data", + "google chrome delete history", + "google chrome erase cache", + "google chrome erase data", + "google chrome erase history", + "google chrome history clear", + "google chrome history delete", + "google chrome history erase", + "google chrome history remove", + "google chrome history wipe", + "google chrome remove cache", + "google chrome remove data", + "google chrome remove history", + "google chrome wipe cache", + "google chrome wipe data", + "google chrome wipe history", + "history browser clear", + "history browser delete", + "history browser erase", + "history browser remove", + "history browser wipe", + "history chrome clear", + "history chrome delete", + "history chrome erase", + "history chrome remove", + "history chrome wipe", + "history clear", + "history clear browser", + "history clear chrome", + "history clear google chrome", + "history delete", + "history delete browser", + "history delete chrome", + "history delete google chrome", + "history erase", + "history erase browser", + "history erase chrome", + "history erase google chrome", + "history google chrome clear", + "history google chrome delete", + "history google chrome erase", + "history google chrome remove", + "history google chrome wipe", + "history remove", + "history remove browser", + "history remove chrome", + "history remove google chrome", + "history wipe", + "history wipe browser", + "history wipe chrome", + "history wipe google chrome", + "remove browser cache", + "remove browser data", + "remove browser history", + "remove cache", + "remove cache browser", + "remove cache chrome", + "remove cache google chrome", + "remove chrome cache", + "remove chrome data", + "remove chrome history", + "remove data", + "remove data browser", + "remove data chrome", + "remove data google chrome", + "remove google chrome cache", + "remove google chrome data", + "remove google chrome history", + "remove history", + "remove history browser", + "remove history chrome", + "remove history google chrome", + "wipe browser cache", + "wipe browser data", + "wipe browser history", + "wipe cache", + "wipe cache browser", + "wipe cache chrome", + "wipe cache google chrome", + "wipe chrome cache", + "wipe chrome data", + "wipe chrome history", + "wipe data", + "wipe data browser", + "wipe data chrome", + "wipe data google chrome", + "wipe google chrome cache", + "wipe google chrome data", + "wipe google chrome history", + "wipe history", + "wipe history browser", + "wipe history chrome", + "wipe history google chrome", + }, + + // Change Search Engine + { + "browser change default search engine", + "browser change search", + "browser change search engine", + "browser change standard search engine", + "browser choose default search engine", + "browser choose search", + "browser choose search engine", + "browser choose standard search engine", + "browser default search engine change", + "browser default search engine choose", + "browser default search engine select", + "browser default search engine switch", + "browser search change", + "browser search choose", + "browser search engine change", + "browser search engine choose", + "browser search engine select", + "browser search engine switch", + "browser search select", + "browser search switch", + "browser select default search engine", + "browser select search", + "browser select search engine", + "browser select standard search engine", + "browser standard search engine change", + "browser standard search engine choose", + "browser standard search engine select", + "browser standard search engine switch", + "browser switch default search engine", + "browser switch search", + "browser switch search engine", + "browser switch standard search engine", + "change browser default search engine", + "change browser search", + "change browser search engine", + "change browser standard search engine", + "change chrome default search engine", + "change chrome search", + "change chrome search engine", + "change chrome standard search engine", + "change default search engine", + "change default search engine browser", + "change default search engine chrome", + "change default search engine google chrome", + "change google chrome default search engine", + "change google chrome search", + "change google chrome search engine", + "change google chrome standard search engine", + "change search", + "change search browser", + "change search chrome", + "change search engine", + "change search engine browser", + "change search engine chrome", + "change search engine google chrome", + "change search google chrome", + "change standard search engine", + "change standard search engine browser", + "change standard search engine chrome", + "change standard search engine google chrome", + "choose browser default search engine", + "choose browser search", + "choose browser search engine", + "choose browser standard search engine", + "choose chrome default search engine", + "choose chrome search", + "choose chrome search engine", + "choose chrome standard search engine", + "choose default search engine", + "choose default search engine browser", + "choose default search engine chrome", + "choose default search engine google chrome", + "choose google chrome default search engine", + "choose google chrome search", + "choose google chrome search engine", + "choose google chrome standard search engine", + "choose search", + "choose search browser", + "choose search chrome", + "choose search engine", + "choose search engine browser", + "choose search engine chrome", + "choose search engine google chrome", + "choose search google chrome", + "choose standard search engine", + "choose standard search engine browser", + "choose standard search engine chrome", + "choose standard search engine google chrome", + "chrome change default search engine", + "chrome change search", + "chrome change search engine", + "chrome change standard search engine", + "chrome choose default search engine", + "chrome choose search", + "chrome choose search engine", + "chrome choose standard search engine", + "chrome default search engine change", + "chrome default search engine choose", + "chrome default search engine select", + "chrome default search engine switch", + "chrome search change", + "chrome search choose", + "chrome search engine change", + "chrome search engine choose", + "chrome search engine select", + "chrome search engine switch", + "chrome search select", + "chrome search switch", + "chrome select default search engine", + "chrome select search", + "chrome select search engine", + "chrome select standard search engine", + "chrome standard search engine change", + "chrome standard search engine choose", + "chrome standard search engine select", + "chrome standard search engine switch", + "chrome switch default search engine", + "chrome switch search", + "chrome switch search engine", + "chrome switch standard search engine", + "default search engine browser change", + "default search engine browser choose", + "default search engine browser select", + "default search engine browser switch", + "default search engine change", + "default search engine change browser", + "default search engine change chrome", + "default search engine change google chrome", + "default search engine choose", + "default search engine choose browser", + "default search engine choose chrome", + "default search engine choose google chrome", + "default search engine chrome change", + "default search engine chrome choose", + "default search engine chrome select", + "default search engine chrome switch", + "default search engine google chrome change", + "default search engine google chrome choose", + "default search engine google chrome select", + "default search engine google chrome switch", + "default search engine select", + "default search engine select browser", + "default search engine select chrome", + "default search engine select google chrome", + "default search engine switch", + "default search engine switch browser", + "default search engine switch chrome", + "default search engine switch google chrome", + "google chrome change default search engine", + "google chrome change search", + "google chrome change search engine", + "google chrome change standard search engine", + "google chrome choose default search engine", + "google chrome choose search", + "google chrome choose search engine", + "google chrome choose standard search engine", + "google chrome default search engine change", + "google chrome default search engine choose", + "google chrome default search engine select", + "google chrome default search engine switch", + "google chrome search change", + "google chrome search choose", + "google chrome search engine change", + "google chrome search engine choose", + "google chrome search engine select", + "google chrome search engine switch", + "google chrome search select", + "google chrome search switch", + "google chrome select default search engine", + "google chrome select search", + "google chrome select search engine", + "google chrome select standard search engine", + "google chrome standard search engine change", + "google chrome standard search engine choose", + "google chrome standard search engine select", + "google chrome standard search engine switch", + "google chrome switch default search engine", + "google chrome switch search", + "google chrome switch search engine", + "google chrome switch standard search engine", + "search browser change", + "search browser choose", + "search browser select", + "search browser switch", + "search change", + "search change browser", + "search change chrome", + "search change google chrome", + "search choose", + "search choose browser", + "search choose chrome", + "search choose google chrome", + "search chrome change", + "search chrome choose", + "search chrome select", + "search chrome switch", + "search engine browser change", + "search engine browser choose", + "search engine browser select", + "search engine browser switch", + "search engine change", + "search engine change browser", + "search engine change chrome", + "search engine change google chrome", + "search engine choose", + "search engine choose browser", + "search engine choose chrome", + "search engine choose google chrome", + "search engine chrome change", + "search engine chrome choose", + "search engine chrome select", + "search engine chrome switch", + "search engine google chrome change", + "search engine google chrome choose", + "search engine google chrome select", + "search engine google chrome switch", + "search engine select", + "search engine select browser", + "search engine select chrome", + "search engine select google chrome", + "search engine switch", + "search engine switch browser", + "search engine switch chrome", + "search engine switch google chrome", + "search google chrome change", + "search google chrome choose", + "search google chrome select", + "search google chrome switch", + "search select", + "search select browser", + "search select chrome", + "search select google chrome", + "search switch", + "search switch browser", + "search switch chrome", + "search switch google chrome", + "select browser default search engine", + "select browser search", + "select browser search engine", + "select browser standard search engine", + "select chrome default search engine", + "select chrome search", + "select chrome search engine", + "select chrome standard search engine", + "select default search engine", + "select default search engine browser", + "select default search engine chrome", + "select default search engine google chrome", + "select google chrome default search engine", + "select google chrome search", + "select google chrome search engine", + "select google chrome standard search engine", + "select search", + "select search browser", + "select search chrome", + "select search engine", + "select search engine browser", + "select search engine chrome", + "select search engine google chrome", + "select search google chrome", + "select standard search engine", + "select standard search engine browser", + "select standard search engine chrome", + "select standard search engine google chrome", + "standard search engine browser change", + "standard search engine browser choose", + "standard search engine browser select", + "standard search engine browser switch", + "standard search engine change", + "standard search engine change browser", + "standard search engine change chrome", + "standard search engine change google chrome", + "standard search engine choose", + "standard search engine choose browser", + "standard search engine choose chrome", + "standard search engine choose google chrome", + "standard search engine chrome change", + "standard search engine chrome choose", + "standard search engine chrome select", + "standard search engine chrome switch", + "standard search engine google chrome change", + "standard search engine google chrome choose", + "standard search engine google chrome select", + "standard search engine google chrome switch", + "standard search engine select", + "standard search engine select browser", + "standard search engine select chrome", + "standard search engine select google chrome", + "standard search engine switch", + "standard search engine switch browser", + "standard search engine switch chrome", + "standard search engine switch google chrome", + "switch browser default search engine", + "switch browser search", + "switch browser search engine", + "switch browser standard search engine", + "switch chrome default search engine", + "switch chrome search", + "switch chrome search engine", + "switch chrome standard search engine", + "switch default search engine", + "switch default search engine browser", + "switch default search engine chrome", + "switch default search engine google chrome", + "switch google chrome default search engine", + "switch google chrome search", + "switch google chrome search engine", + "switch google chrome standard search engine", + "switch search", + "switch search browser", + "switch search chrome", + "switch search engine", + "switch search engine browser", + "switch search engine chrome", + "switch search engine google chrome", + "switch search google chrome", + "switch standard search engine", + "switch standard search engine browser", + "switch standard search engine chrome", + "switch standard search engine google chrome", + }, + + // Manage Passwords + { + "browser change passwords", + "browser manage passwords", + "browser manager passwords", + "browser passwords change", + "browser passwords manage", + "browser passwords manager", + "browser passwords update", + "browser update passwords", + "change browser passwords", + "change chrome passwords", + "change google chrome passwords", + "change passwords", + "change passwords browser", + "change passwords chrome", + "change passwords google chrome", + "chrome change passwords", + "chrome manage passwords", + "chrome manager passwords", + "chrome passwords change", + "chrome passwords manage", + "chrome passwords manager", + "chrome passwords update", + "chrome update passwords", + "google chrome change passwords", + "google chrome manage passwords", + "google chrome manager passwords", + "google chrome passwords change", + "google chrome passwords manage", + "google chrome passwords manager", + "google chrome passwords update", + "google chrome update passwords", + "manage browser passwords", + "manage chrome passwords", + "manage google chrome passwords", + "manage passwords", + "manage passwords browser", + "manage passwords chrome", + "manage passwords google chrome", + "manager browser passwords", + "manager chrome passwords", + "manager google chrome passwords", + "manager passwords", + "manager passwords browser", + "manager passwords chrome", + "manager passwords google chrome", + "passwords browser change", + "passwords browser manage", + "passwords browser manager", + "passwords browser update", + "passwords change", + "passwords change browser", + "passwords change chrome", + "passwords change google chrome", + "passwords chrome change", + "passwords chrome manage", + "passwords chrome manager", + "passwords chrome update", + "passwords google chrome change", + "passwords google chrome manage", + "passwords google chrome manager", + "passwords google chrome update", + "passwords manage", + "passwords manage browser", + "passwords manage chrome", + "passwords manage google chrome", + "passwords manager", + "passwords manager browser", + "passwords manager chrome", + "passwords manager google chrome", + "passwords update", + "passwords update browser", + "passwords update chrome", + "passwords update google chrome", + "update browser passwords", + "update chrome passwords", + "update google chrome passwords", + "update passwords", + "update passwords browser", + "update passwords chrome", + "update passwords google chrome", + }, + + // Change Home Page + { + "browser change home page", + "browser change homepage", + "browser choose home page", + "browser choose homepage", + "browser home page change", + "browser home page choose", + "browser home page set", + "browser homepage change", + "browser homepage choose", + "browser homepage set", + "browser set home page", + "browser set homepage", + "change browser home page", + "change browser homepage", + "change chrome home page", + "change chrome homepage", + "change google chrome home page", + "change google chrome homepage", + "change home page", + "change home page browser", + "change home page chrome", + "change home page google chrome", + "change homepage", + "change homepage browser", + "change homepage chrome", + "change homepage google chrome", + "choose browser home page", + "choose browser homepage", + "choose chrome home page", + "choose chrome homepage", + "choose google chrome home page", + "choose google chrome homepage", + "choose home page", + "choose home page browser", + "choose home page chrome", + "choose home page google chrome", + "choose homepage", + "choose homepage browser", + "choose homepage chrome", + "choose homepage google chrome", + "chrome change home page", + "chrome change homepage", + "chrome choose home page", + "chrome choose homepage", + "chrome home page change", + "chrome home page choose", + "chrome home page set", + "chrome homepage change", + "chrome homepage choose", + "chrome homepage set", + "chrome set home page", + "chrome set homepage", + "google chrome change home page", + "google chrome change homepage", + "google chrome choose home page", + "google chrome choose homepage", + "google chrome home page change", + "google chrome home page choose", + "google chrome home page set", + "google chrome homepage change", + "google chrome homepage choose", + "google chrome homepage set", + "google chrome set home page", + "google chrome set homepage", + "home page browser change", + "home page browser choose", + "home page browser set", + "home page change", + "home page change browser", + "home page change chrome", + "home page change google chrome", + "home page choose", + "home page choose browser", + "home page choose chrome", + "home page choose google chrome", + "home page chrome change", + "home page chrome choose", + "home page chrome set", + "home page google chrome change", + "home page google chrome choose", + "home page google chrome set", + "home page set", + "home page set browser", + "home page set chrome", + "home page set google chrome", + "homepage browser change", + "homepage browser choose", + "homepage browser set", + "homepage change", + "homepage change browser", + "homepage change chrome", + "homepage change google chrome", + "homepage choose", + "homepage choose browser", + "homepage choose chrome", + "homepage choose google chrome", + "homepage chrome change", + "homepage chrome choose", + "homepage chrome set", + "homepage google chrome change", + "homepage google chrome choose", + "homepage google chrome set", + "homepage set", + "homepage set browser", + "homepage set chrome", + "homepage set google chrome", + "set browser home page", + "set browser homepage", + "set chrome home page", + "set chrome homepage", + "set google chrome home page", + "set google chrome homepage", + "set home page", + "set home page browser", + "set home page chrome", + "set home page google chrome", + "set homepage", + "set homepage browser", + "set homepage chrome", + "set homepage google chrome", + }, + + // Update Credit Card + { + "browser card info update", + "browser cards update", + "browser credit card update", + "browser update card info", + "browser update cards", + "browser update credit card", + "card info browser update", + "card info chrome update", + "card info google chrome update", + "card info update", + "card info update browser", + "card info update chrome", + "card info update google chrome", + "cards browser update", + "cards chrome update", + "cards google chrome update", + "cards update", + "cards update browser", + "cards update chrome", + "cards update google chrome", + "chrome card info update", + "chrome cards update", + "chrome credit card update", + "chrome update card info", + "chrome update cards", + "chrome update credit card", + "credit card browser update", + "credit card chrome update", + "credit card google chrome update", + "credit card update", + "credit card update browser", + "credit card update chrome", + "credit card update google chrome", + "google chrome card info update", + "google chrome cards update", + "google chrome credit card update", + "google chrome update card info", + "google chrome update cards", + "google chrome update credit card", + "update browser card info", + "update browser cards", + "update browser credit card", + "update card info", + "update card info browser", + "update card info chrome", + "update card info google chrome", + "update cards", + "update cards browser", + "update cards chrome", + "update cards google chrome", + "update chrome card info", + "update chrome cards", + "update chrome credit card", + "update credit card", + "update credit card browser", + "update credit card chrome", + "update credit card google chrome", + "update google chrome card info", + "update google chrome cards", + "update google chrome credit card", + }, + + // Launch Incognito + { + "browser dark mode enter", + "browser dark mode launch", + "browser dark mode open", + "browser dark mode start", + "browser dark tab enter", + "browser dark tab launch", + "browser dark tab open", + "browser dark tab start", + "browser dark window enter", + "browser dark window launch", + "browser dark window open", + "browser dark window start", + "browser enter dark mode", + "browser enter dark tab", + "browser enter dark window", + "browser enter incognito", + "browser enter incognito mode", + "browser enter incognito tab", + "browser enter incognito window", + "browser enter private mode", + "browser enter private tab", + "browser enter private window", + "browser incognito enter", + "browser incognito launch", + "browser incognito mode enter", + "browser incognito mode launch", + "browser incognito mode open", + "browser incognito mode start", + "browser incognito open", + "browser incognito start", + "browser incognito tab enter", + "browser incognito tab launch", + "browser incognito tab open", + "browser incognito tab start", + "browser incognito window enter", + "browser incognito window launch", + "browser incognito window open", + "browser incognito window start", + "browser launch dark mode", + "browser launch dark tab", + "browser launch dark window", + "browser launch incognito", + "browser launch incognito mode", + "browser launch incognito tab", + "browser launch incognito window", + "browser launch private mode", + "browser launch private tab", + "browser launch private window", + "browser open dark mode", + "browser open dark tab", + "browser open dark window", + "browser open incognito", + "browser open incognito mode", + "browser open incognito tab", + "browser open incognito window", + "browser open private mode", + "browser open private tab", + "browser open private window", + "browser private mode enter", + "browser private mode launch", + "browser private mode open", + "browser private mode start", + "browser private tab enter", + "browser private tab launch", + "browser private tab open", + "browser private tab start", + "browser private window enter", + "browser private window launch", + "browser private window open", + "browser private window start", + "browser start dark mode", + "browser start dark tab", + "browser start dark window", + "browser start incognito", + "browser start incognito mode", + "browser start incognito tab", + "browser start incognito window", + "browser start private mode", + "browser start private tab", + "browser start private window", + "chrome dark mode enter", + "chrome dark mode launch", + "chrome dark mode open", + "chrome dark mode start", + "chrome dark tab enter", + "chrome dark tab launch", + "chrome dark tab open", + "chrome dark tab start", + "chrome dark window enter", + "chrome dark window launch", + "chrome dark window open", + "chrome dark window start", + "chrome enter dark mode", + "chrome enter dark tab", + "chrome enter dark window", + "chrome enter incognito", + "chrome enter incognito mode", + "chrome enter incognito tab", + "chrome enter incognito window", + "chrome enter private mode", + "chrome enter private tab", + "chrome enter private window", + "chrome incognito enter", + "chrome incognito launch", + "chrome incognito mode enter", + "chrome incognito mode launch", + "chrome incognito mode open", + "chrome incognito mode start", + "chrome incognito open", + "chrome incognito start", + "chrome incognito tab enter", + "chrome incognito tab launch", + "chrome incognito tab open", + "chrome incognito tab start", + "chrome incognito window enter", + "chrome incognito window launch", + "chrome incognito window open", + "chrome incognito window start", + "chrome launch dark mode", + "chrome launch dark tab", + "chrome launch dark window", + "chrome launch incognito", + "chrome launch incognito mode", + "chrome launch incognito tab", + "chrome launch incognito window", + "chrome launch private mode", + "chrome launch private tab", + "chrome launch private window", + "chrome open dark mode", + "chrome open dark tab", + "chrome open dark window", + "chrome open incognito", + "chrome open incognito mode", + "chrome open incognito tab", + "chrome open incognito window", + "chrome open private mode", + "chrome open private tab", + "chrome open private window", + "chrome private mode enter", + "chrome private mode launch", + "chrome private mode open", + "chrome private mode start", + "chrome private tab enter", + "chrome private tab launch", + "chrome private tab open", + "chrome private tab start", + "chrome private window enter", + "chrome private window launch", + "chrome private window open", + "chrome private window start", + "chrome start dark mode", + "chrome start dark tab", + "chrome start dark window", + "chrome start incognito", + "chrome start incognito mode", + "chrome start incognito tab", + "chrome start incognito window", + "chrome start private mode", + "chrome start private tab", + "chrome start private window", + "dark mode browser enter", + "dark mode browser launch", + "dark mode browser open", + "dark mode browser start", + "dark mode chrome enter", + "dark mode chrome launch", + "dark mode chrome open", + "dark mode chrome start", + "dark mode enter", + "dark mode enter browser", + "dark mode enter chrome", + "dark mode enter google chrome", + "dark mode google chrome enter", + "dark mode google chrome launch", + "dark mode google chrome open", + "dark mode google chrome start", + "dark mode launch", + "dark mode launch browser", + "dark mode launch chrome", + "dark mode launch google chrome", + "dark mode open", + "dark mode open browser", + "dark mode open chrome", + "dark mode open google chrome", + "dark mode start", + "dark mode start browser", + "dark mode start chrome", + "dark mode start google chrome", + "dark tab browser enter", + "dark tab browser launch", + "dark tab browser open", + "dark tab browser start", + "dark tab chrome enter", + "dark tab chrome launch", + "dark tab chrome open", + "dark tab chrome start", + "dark tab enter", + "dark tab enter browser", + "dark tab enter chrome", + "dark tab enter google chrome", + "dark tab google chrome enter", + "dark tab google chrome launch", + "dark tab google chrome open", + "dark tab google chrome start", + "dark tab launch", + "dark tab launch browser", + "dark tab launch chrome", + "dark tab launch google chrome", + "dark tab open", + "dark tab open browser", + "dark tab open chrome", + "dark tab open google chrome", + "dark tab start", + "dark tab start browser", + "dark tab start chrome", + "dark tab start google chrome", + "dark window browser enter", + "dark window browser launch", + "dark window browser open", + "dark window browser start", + "dark window chrome enter", + "dark window chrome launch", + "dark window chrome open", + "dark window chrome start", + "dark window enter", + "dark window enter browser", + "dark window enter chrome", + "dark window enter google chrome", + "dark window google chrome enter", + "dark window google chrome launch", + "dark window google chrome open", + "dark window google chrome start", + "dark window launch", + "dark window launch browser", + "dark window launch chrome", + "dark window launch google chrome", + "dark window open", + "dark window open browser", + "dark window open chrome", + "dark window open google chrome", + "dark window start", + "dark window start browser", + "dark window start chrome", + "dark window start google chrome", + "enter browser dark mode", + "enter browser dark tab", + "enter browser dark window", + "enter browser incognito", + "enter browser incognito mode", + "enter browser incognito tab", + "enter browser incognito window", + "enter browser private mode", + "enter browser private tab", + "enter browser private window", + "enter chrome dark mode", + "enter chrome dark tab", + "enter chrome dark window", + "enter chrome incognito", + "enter chrome incognito mode", + "enter chrome incognito tab", + "enter chrome incognito window", + "enter chrome private mode", + "enter chrome private tab", + "enter chrome private window", + "enter dark mode", + "enter dark mode browser", + "enter dark mode chrome", + "enter dark mode google chrome", + "enter dark tab", + "enter dark tab browser", + "enter dark tab chrome", + "enter dark tab google chrome", + "enter dark window", + "enter dark window browser", + "enter dark window chrome", + "enter dark window google chrome", + "enter google chrome dark mode", + "enter google chrome dark tab", + "enter google chrome dark window", + "enter google chrome incognito", + "enter google chrome incognito mode", + "enter google chrome incognito tab", + "enter google chrome incognito window", + "enter google chrome private mode", + "enter google chrome private tab", + "enter google chrome private window", + "enter incognito", + "enter incognito browser", + "enter incognito chrome", + "enter incognito google chrome", + "enter incognito mode", + "enter incognito mode browser", + "enter incognito mode chrome", + "enter incognito mode google chrome", + "enter incognito tab", + "enter incognito tab browser", + "enter incognito tab chrome", + "enter incognito tab google chrome", + "enter incognito window", + "enter incognito window browser", + "enter incognito window chrome", + "enter incognito window google chrome", + "enter private mode", + "enter private mode browser", + "enter private mode chrome", + "enter private mode google chrome", + "enter private tab", + "enter private tab browser", + "enter private tab chrome", + "enter private tab google chrome", + "enter private window", + "enter private window browser", + "enter private window chrome", + "enter private window google chrome", + "google chrome dark mode enter", + "google chrome dark mode launch", + "google chrome dark mode open", + "google chrome dark mode start", + "google chrome dark tab enter", + "google chrome dark tab launch", + "google chrome dark tab open", + "google chrome dark tab start", + "google chrome dark window enter", + "google chrome dark window launch", + "google chrome dark window open", + "google chrome dark window start", + "google chrome enter dark mode", + "google chrome enter dark tab", + "google chrome enter dark window", + "google chrome enter incognito", + "google chrome enter incognito mode", + "google chrome enter incognito tab", + "google chrome enter incognito window", + "google chrome enter private mode", + "google chrome enter private tab", + "google chrome enter private window", + "google chrome incognito enter", + "google chrome incognito launch", + "google chrome incognito mode enter", + "google chrome incognito mode launch", + "google chrome incognito mode open", + "google chrome incognito mode start", + "google chrome incognito open", + "google chrome incognito start", + "google chrome incognito tab enter", + "google chrome incognito tab launch", + "google chrome incognito tab open", + "google chrome incognito tab start", + "google chrome incognito window enter", + "google chrome incognito window launch", + "google chrome incognito window open", + "google chrome incognito window start", + "google chrome launch dark mode", + "google chrome launch dark tab", + "google chrome launch dark window", + "google chrome launch incognito", + "google chrome launch incognito mode", + "google chrome launch incognito tab", + "google chrome launch incognito window", + "google chrome launch private mode", + "google chrome launch private tab", + "google chrome launch private window", + "google chrome open dark mode", + "google chrome open dark tab", + "google chrome open dark window", + "google chrome open incognito", + "google chrome open incognito mode", + "google chrome open incognito tab", + "google chrome open incognito window", + "google chrome open private mode", + "google chrome open private tab", + "google chrome open private window", + "google chrome private mode enter", + "google chrome private mode launch", + "google chrome private mode open", + "google chrome private mode start", + "google chrome private tab enter", + "google chrome private tab launch", + "google chrome private tab open", + "google chrome private tab start", + "google chrome private window enter", + "google chrome private window launch", + "google chrome private window open", + "google chrome private window start", + "google chrome start dark mode", + "google chrome start dark tab", + "google chrome start dark window", + "google chrome start incognito", + "google chrome start incognito mode", + "google chrome start incognito tab", + "google chrome start incognito window", + "google chrome start private mode", + "google chrome start private tab", + "google chrome start private window", + "incognito browser enter", + "incognito browser launch", + "incognito browser open", + "incognito browser start", + "incognito chrome enter", + "incognito chrome launch", + "incognito chrome open", + "incognito chrome start", + "incognito enter", + "incognito enter browser", + "incognito enter chrome", + "incognito enter google chrome", + "incognito google chrome enter", + "incognito google chrome launch", + "incognito google chrome open", + "incognito google chrome start", + "incognito launch", + "incognito launch browser", + "incognito launch chrome", + "incognito launch google chrome", + "incognito mode browser enter", + "incognito mode browser launch", + "incognito mode browser open", + "incognito mode browser start", + "incognito mode chrome enter", + "incognito mode chrome launch", + "incognito mode chrome open", + "incognito mode chrome start", + "incognito mode enter", + "incognito mode enter browser", + "incognito mode enter chrome", + "incognito mode enter google chrome", + "incognito mode google chrome enter", + "incognito mode google chrome launch", + "incognito mode google chrome open", + "incognito mode google chrome start", + "incognito mode launch", + "incognito mode launch browser", + "incognito mode launch chrome", + "incognito mode launch google chrome", + "incognito mode open", + "incognito mode open browser", + "incognito mode open chrome", + "incognito mode open google chrome", + "incognito mode start", + "incognito mode start browser", + "incognito mode start chrome", + "incognito mode start google chrome", + "incognito open", + "incognito open browser", + "incognito open chrome", + "incognito open google chrome", + "incognito start", + "incognito start browser", + "incognito start chrome", + "incognito start google chrome", + "incognito tab browser enter", + "incognito tab browser launch", + "incognito tab browser open", + "incognito tab browser start", + "incognito tab chrome enter", + "incognito tab chrome launch", + "incognito tab chrome open", + "incognito tab chrome start", + "incognito tab enter", + "incognito tab enter browser", + "incognito tab enter chrome", + "incognito tab enter google chrome", + "incognito tab google chrome enter", + "incognito tab google chrome launch", + "incognito tab google chrome open", + "incognito tab google chrome start", + "incognito tab launch", + "incognito tab launch browser", + "incognito tab launch chrome", + "incognito tab launch google chrome", + "incognito tab open", + "incognito tab open browser", + "incognito tab open chrome", + "incognito tab open google chrome", + "incognito tab start", + "incognito tab start browser", + "incognito tab start chrome", + "incognito tab start google chrome", + "incognito window browser enter", + "incognito window browser launch", + "incognito window browser open", + "incognito window browser start", + "incognito window chrome enter", + "incognito window chrome launch", + "incognito window chrome open", + "incognito window chrome start", + "incognito window enter", + "incognito window enter browser", + "incognito window enter chrome", + "incognito window enter google chrome", + "incognito window google chrome enter", + "incognito window google chrome launch", + "incognito window google chrome open", + "incognito window google chrome start", + "incognito window launch", + "incognito window launch browser", + "incognito window launch chrome", + "incognito window launch google chrome", + "incognito window open", + "incognito window open browser", + "incognito window open chrome", + "incognito window open google chrome", + "incognito window start", + "incognito window start browser", + "incognito window start chrome", + "incognito window start google chrome", + "launch browser dark mode", + "launch browser dark tab", + "launch browser dark window", + "launch browser incognito", + "launch browser incognito mode", + "launch browser incognito tab", + "launch browser incognito window", + "launch browser private mode", + "launch browser private tab", + "launch browser private window", + "launch chrome dark mode", + "launch chrome dark tab", + "launch chrome dark window", + "launch chrome incognito", + "launch chrome incognito mode", + "launch chrome incognito tab", + "launch chrome incognito window", + "launch chrome private mode", + "launch chrome private tab", + "launch chrome private window", + "launch dark mode", + "launch dark mode browser", + "launch dark mode chrome", + "launch dark mode google chrome", + "launch dark tab", + "launch dark tab browser", + "launch dark tab chrome", + "launch dark tab google chrome", + "launch dark window", + "launch dark window browser", + "launch dark window chrome", + "launch dark window google chrome", + "launch google chrome dark mode", + "launch google chrome dark tab", + "launch google chrome dark window", + "launch google chrome incognito", + "launch google chrome incognito mode", + "launch google chrome incognito tab", + "launch google chrome incognito window", + "launch google chrome private mode", + "launch google chrome private tab", + "launch google chrome private window", + "launch incognito", + "launch incognito browser", + "launch incognito chrome", + "launch incognito google chrome", + "launch incognito mode", + "launch incognito mode browser", + "launch incognito mode chrome", + "launch incognito mode google chrome", + "launch incognito tab", + "launch incognito tab browser", + "launch incognito tab chrome", + "launch incognito tab google chrome", + "launch incognito window", + "launch incognito window browser", + "launch incognito window chrome", + "launch incognito window google chrome", + "launch private mode", + "launch private mode browser", + "launch private mode chrome", + "launch private mode google chrome", + "launch private tab", + "launch private tab browser", + "launch private tab chrome", + "launch private tab google chrome", + "launch private window", + "launch private window browser", + "launch private window chrome", + "launch private window google chrome", + "open browser dark mode", + "open browser dark tab", + "open browser dark window", + "open browser incognito", + "open browser incognito mode", + "open browser incognito tab", + "open browser incognito window", + "open browser private mode", + "open browser private tab", + "open browser private window", + "open chrome dark mode", + "open chrome dark tab", + "open chrome dark window", + "open chrome incognito", + "open chrome incognito mode", + "open chrome incognito tab", + "open chrome incognito window", + "open chrome private mode", + "open chrome private tab", + "open chrome private window", + "open dark mode", + "open dark mode browser", + "open dark mode chrome", + "open dark mode google chrome", + "open dark tab", + "open dark tab browser", + "open dark tab chrome", + "open dark tab google chrome", + "open dark window", + "open dark window browser", + "open dark window chrome", + "open dark window google chrome", + "open google chrome dark mode", + "open google chrome dark tab", + "open google chrome dark window", + "open google chrome incognito", + "open google chrome incognito mode", + "open google chrome incognito tab", + "open google chrome incognito window", + "open google chrome private mode", + "open google chrome private tab", + "open google chrome private window", + "open incognito", + "open incognito browser", + "open incognito chrome", + "open incognito google chrome", + "open incognito mode", + "open incognito mode browser", + "open incognito mode chrome", + "open incognito mode google chrome", + "open incognito tab", + "open incognito tab browser", + "open incognito tab chrome", + "open incognito tab google chrome", + "open incognito window", + "open incognito window browser", + "open incognito window chrome", + "open incognito window google chrome", + "open private mode", + "open private mode browser", + "open private mode chrome", + "open private mode google chrome", + "open private tab", + "open private tab browser", + "open private tab chrome", + "open private tab google chrome", + "open private window", + "open private window browser", + "open private window chrome", + "open private window google chrome", + "private mode browser enter", + "private mode browser launch", + "private mode browser open", + "private mode browser start", + "private mode chrome enter", + "private mode chrome launch", + "private mode chrome open", + "private mode chrome start", + "private mode enter", + "private mode enter browser", + "private mode enter chrome", + "private mode enter google chrome", + "private mode google chrome enter", + "private mode google chrome launch", + "private mode google chrome open", + "private mode google chrome start", + "private mode launch", + "private mode launch browser", + "private mode launch chrome", + "private mode launch google chrome", + "private mode open", + "private mode open browser", + "private mode open chrome", + "private mode open google chrome", + "private mode start", + "private mode start browser", + "private mode start chrome", + "private mode start google chrome", + "private tab browser enter", + "private tab browser launch", + "private tab browser open", + "private tab browser start", + "private tab chrome enter", + "private tab chrome launch", + "private tab chrome open", + "private tab chrome start", + "private tab enter", + "private tab enter browser", + "private tab enter chrome", + "private tab enter google chrome", + "private tab google chrome enter", + "private tab google chrome launch", + "private tab google chrome open", + "private tab google chrome start", + "private tab launch", + "private tab launch browser", + "private tab launch chrome", + "private tab launch google chrome", + "private tab open", + "private tab open browser", + "private tab open chrome", + "private tab open google chrome", + "private tab start", + "private tab start browser", + "private tab start chrome", + "private tab start google chrome", + "private window browser enter", + "private window browser launch", + "private window browser open", + "private window browser start", + "private window chrome enter", + "private window chrome launch", + "private window chrome open", + "private window chrome start", + "private window enter", + "private window enter browser", + "private window enter chrome", + "private window enter google chrome", + "private window google chrome enter", + "private window google chrome launch", + "private window google chrome open", + "private window google chrome start", + "private window launch", + "private window launch browser", + "private window launch chrome", + "private window launch google chrome", + "private window open", + "private window open browser", + "private window open chrome", + "private window open google chrome", + "private window start", + "private window start browser", + "private window start chrome", + "private window start google chrome", + "start browser dark mode", + "start browser dark tab", + "start browser dark window", + "start browser incognito", + "start browser incognito mode", + "start browser incognito tab", + "start browser incognito window", + "start browser private mode", + "start browser private tab", + "start browser private window", + "start chrome dark mode", + "start chrome dark tab", + "start chrome dark window", + "start chrome incognito", + "start chrome incognito mode", + "start chrome incognito tab", + "start chrome incognito window", + "start chrome private mode", + "start chrome private tab", + "start chrome private window", + "start dark mode", + "start dark mode browser", + "start dark mode chrome", + "start dark mode google chrome", + "start dark tab", + "start dark tab browser", + "start dark tab chrome", + "start dark tab google chrome", + "start dark window", + "start dark window browser", + "start dark window chrome", + "start dark window google chrome", + "start google chrome dark mode", + "start google chrome dark tab", + "start google chrome dark window", + "start google chrome incognito", + "start google chrome incognito mode", + "start google chrome incognito tab", + "start google chrome incognito window", + "start google chrome private mode", + "start google chrome private tab", + "start google chrome private window", + "start incognito", + "start incognito browser", + "start incognito chrome", + "start incognito google chrome", + "start incognito mode", + "start incognito mode browser", + "start incognito mode chrome", + "start incognito mode google chrome", + "start incognito tab", + "start incognito tab browser", + "start incognito tab chrome", + "start incognito tab google chrome", + "start incognito window", + "start incognito window browser", + "start incognito window chrome", + "start incognito window google chrome", + "start private mode", + "start private mode browser", + "start private mode chrome", + "start private mode google chrome", + "start private tab", + "start private tab browser", + "start private tab chrome", + "start private tab google chrome", + "start private window", + "start private window browser", + "start private window chrome", + "start private window google chrome", + }, + + // Translate + { + "browser change language page", + "browser change language this", + "browser change language this page", + "browser page change language", + "browser page translate", + "browser this change language", + "browser this page change language", + "browser this page translate", + "browser this translate", + "browser translate page", + "browser translate this", + "browser translate this page", + "change language browser page", + "change language browser this", + "change language browser this page", + "change language chrome page", + "change language chrome this", + "change language chrome this page", + "change language google chrome page", + "change language google chrome this", + "change language google chrome this page", + "change language page", + "change language page browser", + "change language page chrome", + "change language page google chrome", + "change language this", + "change language this browser", + "change language this chrome", + "change language this google chrome", + "change language this page", + "change language this page browser", + "change language this page chrome", + "change language this page google chrome", + "chrome change language page", + "chrome change language this", + "chrome change language this page", + "chrome page change language", + "chrome page translate", + "chrome this change language", + "chrome this page change language", + "chrome this page translate", + "chrome this translate", + "chrome translate page", + "chrome translate this", + "chrome translate this page", + "google chrome change language page", + "google chrome change language this", + "google chrome change language this page", + "google chrome page change language", + "google chrome page translate", + "google chrome this change language", + "google chrome this page change language", + "google chrome this page translate", + "google chrome this translate", + "google chrome translate page", + "google chrome translate this", + "google chrome translate this page", + "page browser change language", + "page browser translate", + "page change language", + "page change language browser", + "page change language chrome", + "page change language google chrome", + "page chrome change language", + "page chrome translate", + "page google chrome change language", + "page google chrome translate", + "page translate", + "page translate browser", + "page translate chrome", + "page translate google chrome", + "this browser change language", + "this browser translate", + "this change language", + "this change language browser", + "this change language chrome", + "this change language google chrome", + "this chrome change language", + "this chrome translate", + "this google chrome change language", + "this google chrome translate", + "this page browser change language", + "this page browser translate", + "this page change language", + "this page change language browser", + "this page change language chrome", + "this page change language google chrome", + "this page chrome change language", + "this page chrome translate", + "this page google chrome change language", + "this page google chrome translate", + "this page translate", + "this page translate browser", + "this page translate chrome", + "this page translate google chrome", + "this translate", + "this translate browser", + "this translate chrome", + "this translate google chrome", + "translate browser page", + "translate browser this", + "translate browser this page", + "translate chrome page", + "translate chrome this", + "translate chrome this page", + "translate google chrome page", + "translate google chrome this", + "translate google chrome this page", + "translate page", + "translate page browser", + "translate page chrome", + "translate page google chrome", + "translate this", + "translate this browser", + "translate this chrome", + "translate this google chrome", + "translate this page", + "translate this page browser", + "translate this page chrome", + "translate this page google chrome", + }, + + // Update Chrome + { + "browser install", + "browser update", + "browser upgrade", + "chrome install", + "chrome update", + "chrome upgrade", + "google chrome install", + "google chrome update", + "google chrome upgrade", + "install browser", + "install chrome", + "install google chrome", + "update browser", + "update chrome", + "update google chrome", + "upgrade browser", + "upgrade chrome", + "upgrade google chrome", + }, + + // End of generated test code + }; + + // The test code below ensures that each element of the outer vector above, + // |literal_concept_expressions|, fully corresponds to exactly one Pedal + // implementation. For each one, the full list of literal expressions are + // confirmed as concept matches for the Pedal. Finally, we verify that every + // implemented Pedal has been tested using set logic. + const auto pedals = GetPedalImplementations(); + std::unordered_set<const OmniboxPedal*> found_pedals(pedals.size()); + for (const auto& pedal_concept : literal_concept_expressions) { + const base::string16 first_trigger = base::ASCIIToUTF16(pedal_concept[0]); + auto iter = + std::find_if(pedals.begin(), pedals.end(), [&](const auto& pedal) { + return pedal->IsConceptMatch(first_trigger); + }); + EXPECT_NE(iter, pedals.end()) + << "Canonical pedal not found for: " << first_trigger; + const OmniboxPedal* canonical_pedal = iter->get(); + const bool is_newly_found = found_pedals.insert(canonical_pedal).second; + EXPECT_TRUE(is_newly_found) + << "Found the same Pedal more than once with: " << first_trigger; + for (const char* literal : pedal_concept) { + const base::string16 expression = base::ASCIIToUTF16(literal); + const auto is_match = [&](const auto& pedal) { + return pedal->IsConceptMatch(expression); + }; + iter = std::find_if(pedals.begin(), pedals.end(), is_match); + EXPECT_NE(iter, pedals.end()) << "Pedal not found for: " << expression; + EXPECT_EQ(iter->get(), canonical_pedal) + << "Found wrong Pedal for: " << expression; + iter = std::find_if(iter + 1, pedals.end(), is_match); + EXPECT_EQ(iter, pedals.end()) + << "Found more than one Pedal match for: " << expression; + } + } + EXPECT_EQ(pedals.size(), found_pedals.size()) + << "Not all implemented Pedals were represented in test cases."; +}
diff --git a/components/omnibox/browser/omnibox_view.cc b/components/omnibox/browser/omnibox_view.cc index 1839db1..db2ea6a 100644 --- a/components/omnibox/browser/omnibox_view.cc +++ b/components/omnibox/browser/omnibox_view.cc
@@ -265,7 +265,7 @@ model_->OnChanged(); } -void OmniboxView::UpdateTextStyle( +bool OmniboxView::UpdateTextStyle( const base::string16& display_text, const bool text_is_url, const AutocompleteSchemeClassifier& classifier) { @@ -320,4 +320,7 @@ // Emphasize the scheme for security UI display purposes (if necessary). if (!model()->user_input_in_progress() && scheme_range.IsValid()) UpdateSchemeStyle(scheme_range); + + // Path is eligible for fading only when the host is the only emphasized part. + return deemphasize == ALL_BUT_HOST; }
diff --git a/components/omnibox/browser/omnibox_view.h b/components/omnibox/browser/omnibox_view.h index 7b419c1d..6c59a0e 100644 --- a/components/omnibox/browser/omnibox_view.h +++ b/components/omnibox/browser/omnibox_view.h
@@ -283,8 +283,8 @@ // everything is emphasized equally, whereas for URLs the scheme may be styled // based on the current security state, with parts of the URL de-emphasized to // draw attention to whatever best represents the "identity" of the current - // URL. - void UpdateTextStyle(const base::string16& display_text, + // URL. Returns true if the path component is eligible for fadeout. + bool UpdateTextStyle(const base::string16& display_text, const bool text_is_url, const AutocompleteSchemeClassifier& classifier);
diff --git a/components/page_image_annotation/DEPS b/components/page_image_annotation/DEPS index e7981184..2ea972b2 100644 --- a/components/page_image_annotation/DEPS +++ b/components/page_image_annotation/DEPS
@@ -2,4 +2,7 @@ # Page image annotation is a layered component; subdirectories must explicitly # introduce the ability to use the content layer as appropriate. "-components/page_image_annotation/content", + "+services/image_annotation/public/mojom", + "+services/image_annotation/public/cpp", + "+third_party/skia", ]
diff --git a/components/page_image_annotation/core/BUILD.gn b/components/page_image_annotation/core/BUILD.gn index 396b16d8..7d36bd6 100644 --- a/components/page_image_annotation/core/BUILD.gn +++ b/components/page_image_annotation/core/BUILD.gn
@@ -2,28 +2,39 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -static_library("core") { - sources = [ - "page_annotator.cc", - "page_annotator.h", - ] +# TODO(crbug.com/916420): this does not compile on iOS, where JPEGCodec (used by +# ImageProcessor) is not supported. We should use an +# alternative encoding scheme or support JPEGCodec on +# iOS. - deps = [ - "//base", - ] -} +if (!is_ios) { + static_library("core") { + sources = [ + "page_annotator.cc", + "page_annotator.h", + ] -source_set("unit_tests") { - testonly = true - sources = [ - "page_annotator_unittest.cc", - ] + deps = [ + "//base", + "//services/image_annotation/public/cpp", + "//skia", + ] + } - deps = [ - ":core", - "//base", - "//base/test:test_support", - "//testing/gmock", - "//testing/gtest", - ] + source_set("unit_tests") { + testonly = true + sources = [ + "page_annotator_unittest.cc", + ] + + deps = [ + ":core", + "//base", + "//base/test:test_support", + "//services/image_annotation/public/cpp", + "//skia", + "//testing/gmock", + "//testing/gtest", + ] + } }
diff --git a/components/page_image_annotation/core/page_annotator.cc b/components/page_image_annotation/core/page_annotator.cc index 3f516ec..7755315 100644 --- a/components/page_image_annotation/core/page_annotator.cc +++ b/components/page_image_annotation/core/page_annotator.cc
@@ -8,59 +8,59 @@ PageAnnotator::Observer::~Observer() {} -PageAnnotator::Subscription::Subscription( - const Observer* const observer, - base::WeakPtr<PageAnnotator> page_annotator) - : observer_(observer), page_annotator_(page_annotator) {} - -PageAnnotator::Subscription::Subscription(Subscription&& subscription) = - default; - -PageAnnotator::Subscription::~Subscription() { - Cancel(); -} - -void PageAnnotator::Subscription::Cancel() { - if (page_annotator_) - page_annotator_->RemoveObserver(observer_); -} - -PageAnnotator::PageAnnotator() : weak_ptr_factory_(this) {} +PageAnnotator::PageAnnotator() {} PageAnnotator::~PageAnnotator() {} -void PageAnnotator::ImageAdded(const uint64_t node_id, - const std::string& source_id) { - // TODO(crbug.com/916363): create a connection to the image annotation service - // for this image. - for (Observer& observer : observers_) { - observer.OnImageAdded(node_id); - } -} +void PageAnnotator::ImageAddedOrPossiblyModified( + const ImageMetadata& metadata, + base::RepeatingCallback<SkBitmap()> pixels_callback) { + const auto lookup = images_.find(metadata.node_id); -void PageAnnotator::ImageModified(const uint64_t node_id, - const std::string& source_id) { - // TODO(crbug.com/916363): reset the service connection for this image. + if (lookup == images_.end()) { + // This is an image addition. - for (Observer& observer : observers_) { - observer.OnImageModified(node_id); + AddNewImage(metadata, std::move(pixels_callback)); + + for (Observer& observer : observers_) { + observer.OnImageAdded(metadata); + } + } else if (lookup->second.first.source_id != metadata.source_id) { + // We already have older data for this node ID; this is an update. + + images_.erase(lookup); + AddNewImage(metadata, std::move(pixels_callback)); + + for (Observer& observer : observers_) { + observer.OnImageModified(metadata); + } } } void PageAnnotator::ImageRemoved(const uint64_t node_id) { - // TODO(crbug.com/916363): close the service connection for this image. + images_.erase(node_id); + for (Observer& observer : observers_) { observer.OnImageRemoved(node_id); } } -PageAnnotator::Subscription PageAnnotator::AddObserver(Observer* observer) { +void PageAnnotator::AddObserver(Observer* const observer) { observers_.AddObserver(observer); - return Subscription(observer, weak_ptr_factory_.GetWeakPtr()); + + // The new observer has not received any previous messages; inform them now of + // all existing images. + for (const auto& image : images_) { + observer->OnImageAdded(image.second.first); + } } -void PageAnnotator::RemoveObserver(const Observer* observer) { - observers_.RemoveObserver(observer); +void PageAnnotator::AddNewImage( + const ImageMetadata& metadata, + base::RepeatingCallback<SkBitmap()> pixels_callback) { + images_.emplace(std::piecewise_construct, + std::forward_as_tuple(metadata.node_id), + std::forward_as_tuple(metadata, std::move(pixels_callback))); } } // namespace page_image_annotation
diff --git a/components/page_image_annotation/core/page_annotator.h b/components/page_image_annotation/core/page_annotator.h index b6edf1e..4469251 100644 --- a/components/page_image_annotation/core/page_annotator.h +++ b/components/page_image_annotation/core/page_annotator.h
@@ -5,10 +5,16 @@ #ifndef COMPONENTS_PAGE_IMAGE_ANNOTATION_CORE_PAGE_ANNOTATOR_H_ #define COMPONENTS_PAGE_IMAGE_ANNOTATION_CORE_PAGE_ANNOTATOR_H_ +#include <map> +#include <utility> + +#include "base/callback.h" #include "base/compiler_specific.h" #include "base/macros.h" #include "base/observer_list.h" #include "base/observer_list_types.h" +#include "services/image_annotation/public/cpp/image_processor.h" +#include "third_party/skia/include/core/SkBitmap.h" namespace page_image_annotation { @@ -19,6 +25,18 @@ // communication with the service). class PageAnnotator { public: + struct ImageMetadata { + // A unique ID identifying an image on this page. Two separate images (even + // with the same URL / pixels) on one page will be given separate node IDs. + uint64_t node_id; + + // The URL or a hash of the data URI of this image. Two (identical) images + // can have the same source ID. + std::string source_id; + + // TODO(crbug.com/916363): add other useful info (e.g. image dimensions). + }; + // Clients (i.e. classes that annotate page images) should implement this // interface. class Observer : public base::CheckedObserver { @@ -31,56 +49,41 @@ // Called exactly once per image, at the point that the image appears on the // page (or at the point that the observer subscribes to the page annotator, // if the image already exists on page). - virtual void OnImageAdded(uint64_t node_id) = 0; + virtual void OnImageAdded(const ImageMetadata& image) = 0; // Called at the point that an image source is updated. - virtual void OnImageModified(uint64_t node_id) = 0; + virtual void OnImageModified(const ImageMetadata& image) = 0; // Called at the point that an image disappears from the page. virtual void OnImageRemoved(uint64_t node_id) = 0; }; - // A subscription instance must be held by each observer of the page - // annotator; an observer will receive updates from the page annotator until - // the Cancel method of the subscription is called (this occurs automatically - // on subscription destruction). - // - // Typically, both the page annotator and its observers are scoped to the - // lifetime of a render frame. Destruction of such objects can proceed in an - // unspecified order, so subscriptions are used to ensure the page annotator - // only communicates with an observers that are still alive. - class Subscription { - public: - Subscription(const Observer* observer, - base::WeakPtr<PageAnnotator> page_annotator); - Subscription(Subscription&& subscription); - ~Subscription(); - - // Unsubscribe from updates from the page annotator. - void Cancel(); - - private: - const Observer* observer_; - base::WeakPtr<PageAnnotator> page_annotator_; - - DISALLOW_COPY_AND_ASSIGN(Subscription); - }; - PageAnnotator(); ~PageAnnotator(); // Called by platform drivers. - void ImageAdded(uint64_t node_id, const std::string& source_id); - void ImageModified(uint64_t node_id, const std::string& source_id); + void ImageAddedOrPossiblyModified( + const ImageMetadata& metadata, + base::RepeatingCallback<SkBitmap()> pixels_callback); void ImageRemoved(uint64_t node_id); - Subscription AddObserver(Observer* observer) WARN_UNUSED_RESULT; + // An observer must outlive the PageAnnotator, or be destructed synchronously + // with the PageAnnotator (e.g. at the same point in the document lifecycle) + // and not reference the PageAnnotator in its destructor. + void AddObserver(Observer* observer); private: - void RemoveObserver(const Observer* observer); + // Add a new entry to |images_|. + // + // The lack of copy/move constructor for ImageProcessor makes this difficult, + // but we limit the complexity to this method. + void AddNewImage(const ImageMetadata& metadata, + base::RepeatingCallback<SkBitmap()> pixels_callback); base::ObserverList<Observer> observers_; - base::WeakPtrFactory<PageAnnotator> weak_ptr_factory_; + + std::map<uint64_t, std::pair<ImageMetadata, image_annotation::ImageProcessor>> + images_; DISALLOW_COPY_AND_ASSIGN(PageAnnotator); };
diff --git a/components/page_image_annotation/core/page_annotator_unittest.cc b/components/page_image_annotation/core/page_annotator_unittest.cc index eca2cbb..c16dcec 100644 --- a/components/page_image_annotation/core/page_annotator_unittest.cc +++ b/components/page_image_annotation/core/page_annotator_unittest.cc
@@ -4,6 +4,7 @@ #include "components/page_image_annotation/core/page_annotator.h" +#include "base/test/scoped_task_environment.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -11,51 +12,57 @@ using testing::Eq; -// Tests that destroying subscriptions successfully prevents notifications. -TEST(PageAnnotatorTest, Subscriptions) { +// Tests that the right messages are sent to observers. +TEST(PageAnnotatorTest, Observers) { class TestObserver : public PageAnnotator::Observer { public: - TestObserver(PageAnnotator* const page_annotator) - : sub_(page_annotator->AddObserver(this)), last_id_(0ul) {} + TestObserver() : last_added_(0), last_modified_(0), last_removed_(0) {} - void OnImageAdded(const uint64_t node_id) override { last_id_ = node_id; } - void OnImageModified(const uint64_t node_id) override { - last_id_ = node_id; + void OnImageAdded(const PageAnnotator::ImageMetadata& metadata) override { + last_added_ = metadata.node_id; } - void OnImageRemoved(const uint64_t node_id) override { last_id_ = node_id; } - PageAnnotator::Subscription sub_; - uint64_t last_id_; + void OnImageModified( + const PageAnnotator::ImageMetadata& metadata) override { + last_modified_ = metadata.node_id; + } + + void OnImageRemoved(const uint64_t node_id) override { + last_removed_ = node_id; + } + + uint64_t last_added_, last_modified_, last_removed_; }; + base::test::ScopedTaskEnvironment test_task_env; + + const auto get_pixels = base::BindRepeating([]() { return SkBitmap(); }); + PageAnnotator page_annotator; - TestObserver o1(&page_annotator), o2(&page_annotator); - page_annotator.ImageAdded(1ul, "test.jpg"); - EXPECT_THAT(o1.last_id_, Eq(1ul)); - EXPECT_THAT(o2.last_id_, Eq(1ul)); + TestObserver o1; + page_annotator.AddObserver(&o1); - page_annotator.ImageAdded(2ul, "example.png"); - EXPECT_THAT(o1.last_id_, Eq(2ul)); - EXPECT_THAT(o2.last_id_, Eq(2ul)); + page_annotator.ImageAddedOrPossiblyModified({1ul, "test.jpg"}, get_pixels); + EXPECT_THAT(o1.last_added_, Eq(1ul)); - page_annotator.ImageModified(1ul, "demo.gif"); - EXPECT_THAT(o1.last_id_, Eq(1ul)); - EXPECT_THAT(o2.last_id_, Eq(1ul)); + page_annotator.ImageAddedOrPossiblyModified({2ul, "example.png"}, get_pixels); + EXPECT_THAT(o1.last_added_, Eq(2ul)); + + page_annotator.ImageAddedOrPossiblyModified({1ul, "demo.gif"}, get_pixels); + EXPECT_THAT(o1.last_added_, Eq(2ul)); + EXPECT_THAT(o1.last_modified_, Eq(1ul)); page_annotator.ImageRemoved(2ul); - EXPECT_THAT(o1.last_id_, Eq(2ul)); - EXPECT_THAT(o2.last_id_, Eq(2ul)); + EXPECT_THAT(o1.last_added_, Eq(2ul)); + EXPECT_THAT(o1.last_modified_, Eq(1ul)); + EXPECT_THAT(o1.last_removed_, Eq(2ul)); - o1.sub_.Cancel(); - page_annotator.ImageAdded(3ul, "placeholder.bmp"); - EXPECT_THAT(o1.last_id_, Eq(2ul)); - EXPECT_THAT(o2.last_id_, Eq(3ul)); + TestObserver o2; + page_annotator.AddObserver(&o2); - o2.sub_.Cancel(); - page_annotator.ImageRemoved(1ul); - EXPECT_THAT(o1.last_id_, Eq(2ul)); - EXPECT_THAT(o2.last_id_, Eq(3ul)); + EXPECT_THAT(o1.last_added_, Eq(2ul)); + EXPECT_THAT(o2.last_added_, Eq(1ul)); } // TODO(crbug.com/916363): add more tests when behavior is added to the
diff --git a/components/password_manager/core/browser/password_store.cc b/components/password_manager/core/browser/password_store.cc index 12e3e58..350d7d7 100644 --- a/components/password_manager/core/browser/password_store.cc +++ b/components/password_manager/core/browser/password_store.cc
@@ -584,6 +584,8 @@ observers_->Notify(FROM_HERE, &Observer::OnLoginsChanged, changes); if (syncable_service_) syncable_service_->ActOnPasswordStoreChanges(changes); + if (sync_bridge_) + sync_bridge_->ActOnPasswordStoreChanges(changes); // TODO(crbug.com/706392): Fix password reuse detection for Android. #if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED) if (reuse_detector_)
diff --git a/components/password_manager/core/browser/sync/password_sync_bridge.cc b/components/password_manager/core/browser/sync/password_sync_bridge.cc index f05fd19..e9475fd 100644 --- a/components/password_manager/core/browser/sync/password_sync_bridge.cc +++ b/components/password_manager/core/browser/sync/password_sync_bridge.cc
@@ -5,6 +5,9 @@ #include "components/password_manager/core/browser/sync/password_sync_bridge.h" #include "base/logging.h" +#include "base/strings/string_number_conversions.h" +#include "base/strings/utf_string_conversions.h" +#include "components/autofill/core/common/password_form.h" #include "components/sync/model/metadata_change_list.h" #include "components/sync/model/model_type_change_processor.h" #include "net/base/escape.h" @@ -12,12 +15,94 @@ namespace password_manager { +namespace { + +sync_pb::PasswordSpecifics SpecificsFromPassword( + const autofill::PasswordForm& password_form) { + sync_pb::PasswordSpecifics specifics; + sync_pb::PasswordSpecificsData* password_data = + specifics.mutable_client_only_encrypted_data(); + password_data->set_scheme(password_form.scheme); + password_data->set_signon_realm(password_form.signon_realm); + password_data->set_origin(password_form.origin.spec()); + password_data->set_action(password_form.action.spec()); + password_data->set_username_element( + base::UTF16ToUTF8(password_form.username_element)); + password_data->set_password_element( + base::UTF16ToUTF8(password_form.password_element)); + password_data->set_username_value( + base::UTF16ToUTF8(password_form.username_value)); + password_data->set_password_value( + base::UTF16ToUTF8(password_form.password_value)); + password_data->set_preferred(password_form.preferred); + password_data->set_date_created( + password_form.date_created.ToDeltaSinceWindowsEpoch().InMicroseconds()); + password_data->set_blacklisted(password_form.blacklisted_by_user); + password_data->set_type(password_form.type); + password_data->set_times_used(password_form.times_used); + password_data->set_display_name( + base::UTF16ToUTF8(password_form.display_name)); + password_data->set_avatar_url(password_form.icon_url.spec()); + password_data->set_federation_url( + password_form.federation_origin.opaque() + ? std::string() + : password_form.federation_origin.Serialize()); + return specifics; +} + +std::unique_ptr<syncer::EntityData> CreateEntityData( + const autofill::PasswordForm& form) { + auto entity_data = std::make_unique<syncer::EntityData>(); + *entity_data->specifics.mutable_password() = SpecificsFromPassword(form); + entity_data->non_unique_name = form.signon_realm; + return entity_data; +} + +} // namespace + PasswordSyncBridge::PasswordSyncBridge( std::unique_ptr<syncer::ModelTypeChangeProcessor> change_processor) : ModelTypeSyncBridge(std::move(change_processor)) {} PasswordSyncBridge::~PasswordSyncBridge() = default; +void PasswordSyncBridge::ActOnPasswordStoreChanges( + const PasswordStoreChangeList& local_changes) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + // It's the responsibility of the callers to call this method within the same + // transaction as the data changes to fulfill atomic writes of data and + // metadata constraint. + + // TODO(mamir):ActOnPasswordStoreChanges() DCHECK we are inside a + // transaction!; + + if (!change_processor()->IsTrackingMetadata()) { + return; // Sync processor not yet ready, don't sync. + } + + // TODO(mamir):ActOnPasswordStoreChanges() can be called from + // ApplySyncChanges(). Do nothing in this case. + std::unique_ptr<syncer::MetadataChangeList> metadata_change_list = + CreateMetadataChangeList(); + + for (const PasswordStoreChange& change : local_changes) { + const std::string storage_key = base::NumberToString(change.primary_key()); + switch (change.type()) { + case PasswordStoreChange::ADD: + case PasswordStoreChange::UPDATE: { + change_processor()->Put(storage_key, CreateEntityData(change.form()), + metadata_change_list.get()); + break; + } + case PasswordStoreChange::REMOVE: { + change_processor()->Delete(storage_key, metadata_change_list.get()); + break; + } + } + } + // TODO(mamir): Persist the metadata. +} + void PasswordSyncBridge::OnSyncStarting( const syncer::DataTypeActivationRequest& request) { NOTIMPLEMENTED();
diff --git a/components/password_manager/core/browser/sync/password_sync_bridge.h b/components/password_manager/core/browser/sync/password_sync_bridge.h index da19693..3a2a031 100644 --- a/components/password_manager/core/browser/sync/password_sync_bridge.h +++ b/components/password_manager/core/browser/sync/password_sync_bridge.h
@@ -6,6 +6,8 @@ #define COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_SYNC_PASSWORD_SYNC_BRIDGE_H_ #include "base/macros.h" +#include "base/sequence_checker.h" +#include "components/password_manager/core/browser/password_store_change.h" #include "components/sync/model/model_type_sync_bridge.h" namespace syncer { @@ -29,6 +31,11 @@ std::unique_ptr<syncer::ModelTypeChangeProcessor> change_processor); ~PasswordSyncBridge() override; + // Notifies the bridge of changes to the password database. Callers are + // responsible for calling this function within the very same transaction as + // the data changes. + void ActOnPasswordStoreChanges(const PasswordStoreChangeList& changes); + // ModelTypeSyncBridge implementation. void OnSyncStarting( const syncer::DataTypeActivationRequest& request) override; @@ -50,6 +57,8 @@ override; private: + SEQUENCE_CHECKER(sequence_checker_); + DISALLOW_COPY_AND_ASSIGN(PasswordSyncBridge); };
diff --git a/components/password_manager/core/browser/sync/password_sync_bridge_unittest.cc b/components/password_manager/core/browser/sync/password_sync_bridge_unittest.cc index 0bd537e..3a52cb4 100644 --- a/components/password_manager/core/browser/sync/password_sync_bridge_unittest.cc +++ b/components/password_manager/core/browser/sync/password_sync_bridge_unittest.cc
@@ -4,16 +4,30 @@ #include "components/password_manager/core/browser/sync/password_sync_bridge.h" -#include "components/sync/model/fake_model_type_change_processor.h" +#include "components/sync/model/metadata_batch.h" +#include "components/sync/model/mock_model_type_change_processor.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" -using testing::Eq; - namespace password_manager { namespace { +using testing::_; +using testing::Eq; +using testing::Return; + +constexpr char kSignonRealm1[] = "abc"; +constexpr char kSignonRealm2[] = "def"; +constexpr char kSignonRealm3[] = "xyz"; + +// |*args| must be of type EntityData. +MATCHER_P(HasSignonRealm, expected_signon_realm, "") { + return arg->specifics.password() + .client_only_encrypted_data() + .signon_realm() == expected_signon_realm; +} + sync_pb::PasswordSpecifics CreateSpecifics(const std::string& origin, const std::string& username_element, const std::string& username_value, @@ -31,17 +45,28 @@ return password_specifics.password(); } +autofill::PasswordForm MakePasswordForm(const std::string& signon_realm) { + autofill::PasswordForm form; + form.signon_realm = signon_realm; + return form; +} + } // namespace class PasswordSyncBridgeTest : public testing::Test { public: PasswordSyncBridgeTest() - : bridge_(std::make_unique<syncer::FakeModelTypeChangeProcessor>()) {} + : bridge_(mock_processor_.CreateForwardingProcessor()) {} ~PasswordSyncBridgeTest() override {} PasswordSyncBridge* bridge() { return &bridge_; } + syncer::MockModelTypeChangeProcessor& mock_processor() { + return mock_processor_; + } + private: + testing::NiceMock<syncer::MockModelTypeChangeProcessor> mock_processor_; PasswordSyncBridge bridge_; }; @@ -57,4 +82,40 @@ "|username_element|username_value|password_element|signon_realm")); } +TEST_F(PasswordSyncBridgeTest, ShouldForwardLocalChangesToTheProcessor) { + ON_CALL(mock_processor(), IsTrackingMetadata()).WillByDefault(Return(true)); + + PasswordStoreChangeList changes; + changes.push_back(PasswordStoreChange( + PasswordStoreChange::ADD, MakePasswordForm(kSignonRealm1), /*id=*/1)); + changes.push_back(PasswordStoreChange( + PasswordStoreChange::UPDATE, MakePasswordForm(kSignonRealm2), /*id=*/2)); + changes.push_back(PasswordStoreChange( + PasswordStoreChange::REMOVE, MakePasswordForm(kSignonRealm3), /*id=*/3)); + + EXPECT_CALL(mock_processor(), Put("1", HasSignonRealm(kSignonRealm1), _)); + EXPECT_CALL(mock_processor(), Put("2", HasSignonRealm(kSignonRealm2), _)); + EXPECT_CALL(mock_processor(), Delete("3", _)); + + bridge()->ActOnPasswordStoreChanges(changes); +} + +TEST_F(PasswordSyncBridgeTest, + ShouldNotForwardLocalChangesToTheProcessorIfSyncDisabled) { + ON_CALL(mock_processor(), IsTrackingMetadata()).WillByDefault(Return(false)); + + PasswordStoreChangeList changes; + changes.push_back(PasswordStoreChange( + PasswordStoreChange::ADD, MakePasswordForm(kSignonRealm1), /*id=*/1)); + changes.push_back(PasswordStoreChange( + PasswordStoreChange::UPDATE, MakePasswordForm(kSignonRealm2), /*id=*/2)); + changes.push_back(PasswordStoreChange( + PasswordStoreChange::REMOVE, MakePasswordForm(kSignonRealm3), /*id=*/3)); + + EXPECT_CALL(mock_processor(), Put(_, _, _)).Times(0); + EXPECT_CALL(mock_processor(), Delete(_, _)).Times(0); + + bridge()->ActOnPasswordStoreChanges(changes); +} + } // namespace password_manager
diff --git a/components/viz/service/display/display_resource_provider.cc b/components/viz/service/display/display_resource_provider.cc index 5dd10c8d..691e2903 100644 --- a/components/viz/service/display/display_resource_provider.cc +++ b/components/viz/service/display/display_resource_provider.cc
@@ -14,6 +14,7 @@ #include "components/viz/common/gpu/context_provider.h" #include "components/viz/common/resources/resource_sizes.h" #include "components/viz/service/display/shared_bitmap_manager.h" +#include "components/viz/service/display/skia_output_surface.h" #include "gpu/command_buffer/client/context_support.h" #include "gpu/command_buffer/client/gles2_interface.h" #include "third_party/skia/include/gpu/GrBackendSurface.h" @@ -648,12 +649,12 @@ // TODO(https://crbug.com/922592): Batch deletion for reduced overhead. auto sk_image_it = resource_sk_images_.find(local_id); if (sk_image_it != resource_sk_images_.end()) { - ResourceSkImage found(std::move(sk_image_it->second)); + sk_sp<SkImage> found(std::move(sk_image_it->second)); resource_sk_images_.erase(sk_image_it); - if (found.destroy_callback.has_value()) { + if (external_use_client_) { gpu::SyncToken token = - found.destroy_callback->Run(std::move(found.image)); + external_use_client_->QueueReleasePromiseSkImage(std::move(found)); resource.UpdateSyncToken(token); } } @@ -723,6 +724,9 @@ DeleteResourceInternal(it, style); } + if (external_use_client_) + external_use_client_->FlushQueuedReleases(); + for (size_t i : to_return_indices_unverified) unverified_sync_tokens.push_back(to_return[i].sync_token.GetData()); @@ -854,7 +858,7 @@ // Use cached SkImage if possible. auto it = resource_provider_->resource_sk_images_.find(resource_id); if (it != resource_provider_->resource_sk_images_.end()) { - sk_image_ = it->second.image; + sk_image_ = it->second; return; } @@ -873,7 +877,7 @@ ResourceFormatToClosestSkColorType(!resource_provider->IsSoftware(), resource->transferable.format), kPremul_SkAlphaType, nullptr); - resource_provider_->resource_sk_images_[resource_id].image = sk_image_; + resource_provider_->resource_sk_images_[resource_id] = sk_image_; return; } @@ -893,7 +897,7 @@ resource_provider->PopulateSkBitmapWithResource(&sk_bitmap, resource); sk_bitmap.setImmutable(); sk_image_ = SkImage::MakeFromBitmap(sk_bitmap); - resource_provider_->resource_sk_images_[resource_id].image = sk_image_; + resource_provider_->resource_sk_images_[resource_id] = sk_image_; } DisplayResourceProvider::ScopedReadLockSkImage::~ScopedReadLockSkImage() { @@ -902,11 +906,11 @@ DisplayResourceProvider::LockSetForExternalUse::LockSetForExternalUse( DisplayResourceProvider* resource_provider, - const CreateSkImageCallback& create_callback, - const DestroySkImageCallback& destroy_callback) - : resource_provider_(resource_provider), - create_sk_image_callback_(create_callback), - destroy_sk_image_callback_(destroy_callback) {} + SkiaOutputSurface* client) + : resource_provider_(resource_provider) { + DCHECK(!resource_provider_->external_use_client_); + resource_provider_->external_use_client_ = client; +} DisplayResourceProvider::LockSetForExternalUse::~LockSetForExternalUse() { DCHECK(resources_.empty()); @@ -924,12 +928,12 @@ ResourceId id) { auto metadata = LockResource(id); auto& resource_sk_image = resource_provider_->resource_sk_images_[id]; - if (!resource_sk_image.image) { - resource_sk_image.image = - create_sk_image_callback_.Run(std::move(metadata)); - resource_sk_image.destroy_callback = destroy_sk_image_callback_; + if (!resource_sk_image) { + resource_sk_image = + resource_provider_->external_use_client_->MakePromiseSkImage( + std::move(metadata)); } - return resource_sk_image.image; + return resource_sk_image; } void DisplayResourceProvider::LockSetForExternalUse::UnlockResources( @@ -997,11 +1001,6 @@ default; DisplayResourceProvider::ChildResource::~ChildResource() = default; -DisplayResourceProvider::ResourceSkImage::ResourceSkImage() = default; -DisplayResourceProvider::ResourceSkImage::ResourceSkImage( - const ResourceSkImage&) = default; -DisplayResourceProvider::ResourceSkImage::~ResourceSkImage() = default; - void DisplayResourceProvider::ChildResource::SetLocallyUsed() { synchronization_state_ = LOCALLY_USED; sync_token_.Clear();
diff --git a/components/viz/service/display/display_resource_provider.h b/components/viz/service/display/display_resource_provider.h index 6a940c881..310e066 100644 --- a/components/viz/service/display/display_resource_provider.h +++ b/components/viz/service/display/display_resource_provider.h
@@ -43,6 +43,7 @@ namespace viz { class ContextProvider; class SharedBitmapManager; +class SkiaOutputSurface; // This class provides abstractions for receiving and using resources from other // modules/threads/processes. It abstracts away GL textures vs GpuMemoryBuffers @@ -185,25 +186,21 @@ DISALLOW_COPY_AND_ASSIGN(ScopedReadLockSkImage); }; - // Maintains set of lock for external use. + // Maintains set of resources locked for external use by SkiaRenderer. class VIZ_SERVICE_EXPORT LockSetForExternalUse { public: - using CreateSkImageCallback = - base::RepeatingCallback<sk_sp<SkImage>(ResourceMetadata)>; - // TODO(https://crbug.com/922595): Remove SyncToken once we always use - // SharedImage and can rely on SharedImage ref-counting. - using DestroySkImageCallback = - base::RepeatingCallback<gpu::SyncToken(sk_sp<SkImage>&&)>; + // There should be at most one instance of this class per + // |resource_provider|. Both |resource_provider| and |client| outlive this + // class. LockSetForExternalUse(DisplayResourceProvider* resource_provider, - const CreateSkImageCallback& create_callback, - const DestroySkImageCallback& destroy_callback); + SkiaOutputSurface* client); ~LockSetForExternalUse(); // Lock a resource for external use. ResourceMetadata LockResource(ResourceId resource_id); - // Lock a resource and create a SkImage from it by using the - // CreateSkImageCallback. + // Lock a resource and create a SkImage from it by using + // Client::CreateImage. sk_sp<SkImage> LockResourceAndCreateSkImage(ResourceId resource_id); // Unlock all locked resources with a |sync_token|. @@ -213,8 +210,6 @@ private: DisplayResourceProvider* const resource_provider_; - CreateSkImageCallback create_sk_image_callback_; - DestroySkImageCallback destroy_sk_image_callback_; std::vector<ResourceId> resources_; DISALLOW_COPY_AND_ASSIGN(LockSetForExternalUse); @@ -483,16 +478,10 @@ ResourceMap resources_; ChildMap children_; - struct ResourceSkImage { - ResourceSkImage(); - ResourceSkImage(const ResourceSkImage&); - ~ResourceSkImage(); + base::flat_map<ResourceId, sk_sp<SkImage>> resource_sk_images_; + // If set, all |resource_sk_images_| were created with this client. + SkiaOutputSurface* external_use_client_ = nullptr; - sk_sp<SkImage> image; - base::Optional<LockSetForExternalUse::DestroySkImageCallback> - destroy_callback; - }; - base::flat_map<ResourceId, ResourceSkImage> resource_sk_images_; base::flat_map<int, std::vector<ResourceId>> batched_returning_resources_; scoped_refptr<ResourceFence> current_read_lock_fence_; // Keep track of whether deleted resources should be batched up or returned
diff --git a/components/viz/service/display/display_resource_provider_unittest.cc b/components/viz/service/display/display_resource_provider_unittest.cc index 82480d7..9cd37ea 100644 --- a/components/viz/service/display/display_resource_provider_unittest.cc +++ b/components/viz/service/display/display_resource_provider_unittest.cc
@@ -479,9 +479,7 @@ unsigned parent_id = resource_map[list.front().id]; DisplayResourceProvider::LockSetForExternalUse lock_set( - resource_provider_.get(), - DisplayResourceProvider::LockSetForExternalUse::CreateSkImageCallback(), - DisplayResourceProvider::LockSetForExternalUse::DestroySkImageCallback()); + resource_provider_.get(), /*client=*/nullptr); ResourceMetadata metadata = lock_set.LockResource(parent_id); ASSERT_EQ(metadata.mailbox_holder.mailbox, mailbox);
diff --git a/components/viz/service/display/skia_output_surface.h b/components/viz/service/display/skia_output_surface.h index 1f46a73..3e203932 100644 --- a/components/viz/service/display/skia_output_surface.h +++ b/components/viz/service/display/skia_output_surface.h
@@ -59,9 +59,13 @@ SkYUVColorSpace yuv_color_space, bool has_alpha) = 0; - // Release SkImage created by MakePromiseSkImage. |image| may or may not - // have been fulfilled. - virtual gpu::SyncToken DestroySkImage(sk_sp<SkImage>&& image) = 0; + // Release SkImage created by MakePromiseSkImage on the thread on which + // it was fulfilled. SyncToken represents point after which SkImage is + // released. + virtual gpu::SyncToken QueueReleasePromiseSkImage(sk_sp<SkImage>&& image) = 0; + + // Flush all the queued releases. No-op if none were queued. + virtual void FlushQueuedReleases() = 0; // Swaps the current backbuffer to the screen. virtual void SkiaSwapBuffers(OutputSurfaceFrame frame) = 0;
diff --git a/components/viz/service/display/skia_renderer.cc b/components/viz/service/display/skia_renderer.cc index bca9aca..54e1614 100644 --- a/components/viz/service/display/skia_renderer.cc +++ b/components/viz/service/display/skia_renderer.cc
@@ -212,12 +212,8 @@ } case DrawMode::DDL: { DCHECK(skia_output_surface_); - lock_set_for_external_use_.emplace( - resource_provider, - base::BindRepeating(&SkiaOutputSurface::MakePromiseSkImage, - base::Unretained(skia_output_surface_)), - base::BindRepeating(&SkiaOutputSurface::DestroySkImage, - base::Unretained(skia_output_surface_))); + lock_set_for_external_use_.emplace(resource_provider, + skia_output_surface); break; } case DrawMode::SKPRECORD: {
diff --git a/components/viz/service/display_embedder/skia_output_surface_impl.cc b/components/viz/service/display_embedder/skia_output_surface_impl.cc index e2d5e25..c9aaf93 100644 --- a/components/viz/service/display_embedder/skia_output_surface_impl.cc +++ b/components/viz/service/display_embedder/skia_output_surface_impl.cc
@@ -455,21 +455,31 @@ this, yuv_color_space, std::move(metadatas), has_alpha); } -gpu::SyncToken SkiaOutputSurfaceImpl::DestroySkImage(sk_sp<SkImage>&& image) { +gpu::SyncToken SkiaOutputSurfaceImpl::QueueReleasePromiseSkImage( + sk_sp<SkImage>&& image) { + images_pending_release_.emplace_back(std::move(image)); + gpu::SyncToken sync_token(gpu::CommandBufferNamespace::VIZ_OUTPUT_SURFACE, impl_on_gpu_->command_buffer_id(), ++sync_fence_release_); sync_token.SetVerifyFlush(); + return sync_token; +} + +void SkiaOutputSurfaceImpl::FlushQueuedReleases() { + if (images_pending_release_.empty()) + return; auto sequence_id = gpu_service_->skia_output_surface_sequence_id(); // impl_on_gpu_ is released on the GPU thread by a posted task from // SkiaOutputSurfaceImpl::dtor. So it is safe to use base::Unretained. - auto callback = base::BindOnce(&SkiaOutputSurfaceImplOnGpu::DestroySkImage, - base::Unretained(impl_on_gpu_.get()), - std::move(image), sync_fence_release_); + auto callback = + base::BindOnce(&SkiaOutputSurfaceImplOnGpu::DestroySkImages, + base::Unretained(impl_on_gpu_.get()), + std::move(images_pending_release_), sync_fence_release_); + images_pending_release_.clear(); gpu_service_->scheduler()->ScheduleTask(gpu::Scheduler::Task( sequence_id, std::move(callback), std::vector<gpu::SyncToken>())); - return sync_token; } void SkiaOutputSurfaceImpl::SkiaSwapBuffers(OutputSurfaceFrame frame) {
diff --git a/components/viz/service/display_embedder/skia_output_surface_impl.h b/components/viz/service/display_embedder/skia_output_surface_impl.h index 0355077..5e95e7e 100644 --- a/components/viz/service/display_embedder/skia_output_surface_impl.h +++ b/components/viz/service/display_embedder/skia_output_surface_impl.h
@@ -74,22 +74,24 @@ // SkiaOutputSurface implementation: SkCanvas* BeginPaintCurrentFrame() override; - sk_sp<SkImage> MakePromiseSkImage(ResourceMetadata metadata) override; sk_sp<SkImage> MakePromiseSkImageFromYUV( std::vector<ResourceMetadata> metadatas, SkYUVColorSpace yuv_color_space, bool has_alpha) override; - gpu::SyncToken DestroySkImage(sk_sp<SkImage>&& image) override; void SkiaSwapBuffers(OutputSurfaceFrame frame) override; SkCanvas* BeginPaintRenderPass(const RenderPassId& id, const gfx::Size& surface_size, ResourceFormat format, bool mipmap) override; gpu::SyncToken SubmitPaint() override; + sk_sp<SkImage> MakePromiseSkImage(ResourceMetadata metadata) override; sk_sp<SkImage> MakePromiseSkImageFromRenderPass(const RenderPassId& id, const gfx::Size& size, ResourceFormat format, bool mipmap) override; + gpu::SyncToken QueueReleasePromiseSkImage(sk_sp<SkImage>&& image) override; + void FlushQueuedReleases() override; + void RemoveRenderPassResource(std::vector<RenderPassId> ids) override; void CopyOutput(RenderPassId id, const gfx::Rect& copy_rect, @@ -154,6 +156,8 @@ // Observers for context lost. base::ObserverList<ContextLostObserver>::Unchecked observers_; + std::vector<sk_sp<SkImage>> images_pending_release_; + THREAD_CHECKER(thread_checker_); base::WeakPtr<SkiaOutputSurfaceImpl> weak_ptr_;
diff --git a/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc b/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc index 4d46da15..702069a9 100644 --- a/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc +++ b/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc
@@ -509,10 +509,11 @@ return gr_context()->threadSafeProxy(); } -void SkiaOutputSurfaceImplOnGpu::DestroySkImage(sk_sp<SkImage>&& image, - uint64_t sync_fence_release) { +void SkiaOutputSurfaceImplOnGpu::DestroySkImages( + std::vector<sk_sp<SkImage>>&& images, + uint64_t sync_fence_release) { MakeCurrent(); - image.reset(); + images.clear(); sync_point_client_state_->ReleaseFenceSync(sync_fence_release); }
diff --git a/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.h b/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.h index a695636..9e875cf7 100644 --- a/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.h +++ b/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.h
@@ -124,7 +124,8 @@ sk_sp<GrContextThreadSafeProxy> GetGrContextThreadSafeProxy(); const gl::GLVersionInfo* gl_version_info() const { return gl_version_info_; } - void DestroySkImage(sk_sp<SkImage>&& image, uint64_t sync_fence_release); + void DestroySkImages(std::vector<sk_sp<SkImage>>&& images, + uint64_t sync_fence_release); private: // gpu::ImageTransportSurfaceDelegate implementation:
diff --git a/content/browser/appcache/appcache_subresource_url_factory.cc b/content/browser/appcache/appcache_subresource_url_factory.cc index 7a7ecf0f..b4d0722 100644 --- a/content/browser/appcache/appcache_subresource_url_factory.cc +++ b/content/browser/appcache/appcache_subresource_url_factory.cc
@@ -4,9 +4,6 @@ #include "content/browser/appcache/appcache_subresource_url_factory.h" -#include <memory> -#include <utility> - #include "base/bind.h" #include "base/logging.h" #include "content/browser/appcache/appcache_host.h" @@ -14,12 +11,9 @@ #include "content/browser/appcache/appcache_url_loader_job.h" #include "content/browser/appcache/appcache_url_loader_request.h" #include "content/public/browser/browser_thread.h" -#include "content/public/browser/content_browser_client.h" -#include "content/public/common/content_client.h" #include "mojo/public/cpp/bindings/binding.h" #include "mojo/public/cpp/bindings/binding_set.h" #include "mojo/public/cpp/bindings/interface_ptr.h" -#include "mojo/public/cpp/bindings/message.h" #include "net/traffic_annotation/network_traffic_annotation.h" #include "net/url_request/url_request.h" #include "services/network/public/cpp/resource_request.h" @@ -364,21 +358,6 @@ network::mojom::URLLoaderClientPtr client, const net::MutableNetworkTrafficAnnotationTag& traffic_annotation) { DCHECK_CURRENTLY_ON(BrowserThread::IO); - if (request.request_initiator.has_value() && - !request.request_initiator.value().opaque() && - request.request_initiator.value() != appcache_host_->origin_in_use()) { - const char* scheme_exception = - GetContentClient() - ->browser() - ->GetInitiatorSchemeBypassingDocumentBlocking(); - if (!scheme_exception || - request.request_initiator.value().scheme() != scheme_exception) { - mojo::ReportBadMessage( - "APP_CACHE_SUBRESOURCE_URL_FACTORY_INVALID_INITIATOR"); - return; - } - } - new SubresourceLoader(std::move(url_loader_request), routing_id, request_id, options, request, std::move(client), traffic_annotation, appcache_host_, network_loader_factory_);
diff --git a/content/browser/loader/cross_site_document_blocking_browsertest.cc b/content/browser/loader/cross_site_document_blocking_browsertest.cc index 05e6cd4..08b603ee 100644 --- a/content/browser/loader/cross_site_document_blocking_browsertest.cc +++ b/content/browser/loader/cross_site_document_blocking_browsertest.cc
@@ -36,7 +36,6 @@ #include "content/public/test/url_loader_interceptor.h" #include "content/shell/browser/shell.h" #include "content/test/test_content_browser_client.h" -#include "mojo/public/cpp/test_support/test_utils.h" #include "net/test/embedded_test_server/controllable_http_response.h" #include "net/test/embedded_test_server/embedded_test_server.h" #include "services/network/cross_origin_read_blocking.h" @@ -107,6 +106,11 @@ is_restricted_uma_expected = true; FetchHistogramsFromChildProcesses(); + // TODO(lukasza): https://crbug.com/910287: Remove the special case below + // after ensuring that |request_initiator| coming through AppCache is + // trustworthy (today kBrowserProcess will be reported in + // NetworkService.URLLoader.RequestInitiatorOriginLockCompatibility UMA when + // AppCache is relaying renderer requests through a browser process). auto expected_lock_compatibility = special_request_initiator_origin_lock_check_for_appcache ? network::InitiatorLockCompatibility::kBrowserProcess @@ -316,10 +320,6 @@ } } - void InjectRequestInitiator(const url::Origin& request_initiator) { - request_initiator_to_inject_ = request_initiator; - } - private: bool InterceptorCallback(URLLoaderInterceptor::RequestParams* params) { DCHECK_CURRENTLY_ON(BrowserThread::IO); @@ -333,10 +333,6 @@ return false; request_intercepted_ = true; - // Modify |params| if requested. - if (request_initiator_to_inject_.has_value()) - params->url_request.request_initiator = request_initiator_to_inject_; - // Inject |test_client_| into the request. DCHECK(!original_client_); original_client_ = std::move(params->client); @@ -383,8 +379,6 @@ const GURL url_to_intercept_; URLLoaderInterceptor interceptor_; - base::Optional<url::Origin> request_initiator_to_inject_; - // |test_client_ptr_info_| below is used to transition results of // |test_client_.CreateInterfacePtr()| into IO thread. network::mojom::URLLoaderClientPtrInfo test_client_ptr_info_; @@ -773,59 +767,6 @@ } } -IN_PROC_BROWSER_TEST_P(CrossSiteDocumentBlockingTest, - AppCache_InitiatorEnforcement) { - embedded_test_server()->StartAcceptingConnections(); - - // Verification of |request_initiator| is only done in the NetworkService code - // path. - if (!base::FeatureList::IsEnabled(network::features::kNetworkService)) - return; - - // Prepare to intercept the network request at the IPC layer. - // in a way, that injects |spoofed_initiator| (simulating a compromised - // renderer that pretends to be making the request on behalf of another - // origin). - // - // Note that RequestInterceptor has to be constructed before the - // RenderFrameHostImpl is created. - GURL cross_site_url("http://cross-origin.com/site_isolation/nosniff.json"); - RequestInterceptor interceptor(cross_site_url); - url::Origin spoofed_initiator = - url::Origin::Create(GURL("https://victim.example.com")); - interceptor.InjectRequestInitiator(spoofed_initiator); - - // Load the main page twice. The second navigation should have AppCache - // initialized for the page. - GURL main_url = embedded_test_server()->GetURL( - "/appcache/simple_page_with_manifest.html"); - EXPECT_TRUE(NavigateToURL(shell(), main_url)); - base::string16 expected_title = base::ASCIIToUTF16("AppCache updated"); - content::TitleWatcher title_watcher(shell()->web_contents(), expected_title); - EXPECT_EQ(expected_title, title_watcher.WaitAndGetTitle()); - EXPECT_TRUE(NavigateToURL(shell(), main_url)); - - // Trigger an AppCache request with an incorrect |request_initiator| and - // verify that this will terminate the renderer process. - // - // Note that during the test, no renderer processes will be actually - // terminated, because the malicious/invalid message originates from within - // the test process (i.e. from URLLoaderInterceptor::Interceptor's - // CreateLoaderAndStart method which forwards the - // InjectRequestInitiator-modified request into - // AppCacheSubresourceURLFactory). This necessitates testing via - // mojo::test::BadMessageObserver rather than via RenderProcessHostWatcher or - // RenderProcessHostKillWaiter. - mojo::test::BadMessageObserver bad_message_observer; - const char kScriptTemplate[] = R"( - var img = document.createElement('img'); - img.src = $1; - document.body.appendChild(img); )"; - EXPECT_TRUE(ExecJs(shell(), JsReplace(kScriptTemplate, cross_site_url))); - EXPECT_EQ("APP_CACHE_SUBRESOURCE_URL_FACTORY_INVALID_INITIATOR", - bad_message_observer.WaitForBadMessage()); -} - IN_PROC_BROWSER_TEST_P(CrossSiteDocumentBlockingTest, PrefetchIsNotImpacted) { // Prepare for intercepting the resource request for testing prefetching. const char* kPrefetchResourcePath = "/prefetch-test";
diff --git a/content/browser/loader/resource_dispatcher_host_impl.cc b/content/browser/loader/resource_dispatcher_host_impl.cc index 14bfd604d..8a67808f 100644 --- a/content/browser/loader/resource_dispatcher_host_impl.cc +++ b/content/browser/loader/resource_dispatcher_host_impl.cc
@@ -924,20 +924,11 @@ report_raw_headers = false; } - // Do not report raw headers if the request's site needs to be isolated - // from the current process. - if (report_raw_headers) { - bool is_isolated = - SiteIsolationPolicy::UseDedicatedProcessesForAllSites() || - // TODO(alexmos): get BrowsingInstance ID from the child_id's - // SecurityState. One way is to expose a version of IsIsolatedOrigin - // that can take child_id instead of IsolationContext, and look up - // the BrowsingInstance ID internally in ChildProcessSecurityPolicy. - policy->IsIsolatedOrigin(IsolationContext(), - url::Origin::Create(request_data.url)); - if (is_isolated && - !policy->CanAccessDataForOrigin(child_id, request_data.url)) - report_raw_headers = false; + // Do not report raw headers if the current process isn't permitted to access + // data for the request's site. + if (report_raw_headers && + !policy->CanAccessDataForOrigin(child_id, request_data.url)) { + report_raw_headers = false; } if (DoNotPromptForLogin(static_cast<ResourceType>(request_data.resource_type),
diff --git a/content/browser/media/session/media_session_impl.cc b/content/browser/media/session/media_session_impl.cc index 74a0e1c..8ec2242 100644 --- a/content/browser/media/session/media_session_impl.cc +++ b/content/browser/media/session/media_session_impl.cc
@@ -180,6 +180,8 @@ RenderFrameHost* rfh = navigation_handle->GetRenderFrameHost(); if (services_.count(rfh)) services_[rfh]->DidFinishNavigation(); + + NotifyMediaSessionMetadataChange(); } void MediaSessionImpl::OnWebContentsFocused( @@ -209,8 +211,9 @@ observer->MediaSessionStateChanged(IsControllable(), IsActuallyPaused()); } -void MediaSessionImpl::NotifyMediaSessionMetadataChange( - const base::Optional<media_session::MediaMetadata>& metadata) { +void MediaSessionImpl::NotifyMediaSessionMetadataChange() { + const media_session::MediaMetadata& metadata = GetMediaMetadata(); + for (auto& observer : observers_) observer.MediaSessionMetadataChanged(metadata); @@ -771,8 +774,7 @@ void MediaSessionImpl::AddObserver( media_session::mojom::MediaSessionObserverPtr observer) { observer->MediaSessionInfoChanged(GetMediaSessionInfoSync()); - observer->MediaSessionMetadataChanged( - routed_service_ ? routed_service_->metadata() : base::nullopt); + observer->MediaSessionMetadataChanged(GetMediaMetadata()); if (routed_service_) { std::vector<media_session::mojom::MediaSessionAction> actions( @@ -928,6 +930,18 @@ return true; } +media_session::MediaMetadata MediaSessionImpl::GetMediaMetadata() const { + media_session::MediaMetadata metadata = + (routed_service_ && routed_service_->metadata()) + ? *routed_service_->metadata() + : media_session::MediaMetadata(); + + metadata.source_title = base::ASCIIToUTF16( + web_contents()->GetLastCommittedURL().GetOrigin().host()); + + return metadata; +} + // MediaSessionService-related methods void MediaSessionImpl::OnServiceCreated(MediaSessionServiceImpl* service) { @@ -961,7 +975,7 @@ if (service != routed_service_) return; - NotifyMediaSessionMetadataChange(routed_service_->metadata()); + NotifyMediaSessionMetadataChange(); } void MediaSessionImpl::OnMediaSessionActionsChanged( @@ -1025,10 +1039,11 @@ return; routed_service_ = new_service; - if (routed_service_) { - NotifyMediaSessionMetadataChange(routed_service_->metadata()); + + if (routed_service_) RebuildAndNotifyActionsChanged(); - } + + NotifyMediaSessionMetadataChange(); } MediaSessionServiceImpl* MediaSessionImpl::ComputeServiceForRouting() {
diff --git a/content/browser/media/session/media_session_impl.h b/content/browser/media/session/media_session_impl.h index 1fd2b202..11fd7576 100644 --- a/content/browser/media/session/media_session_impl.h +++ b/content/browser/media/session/media_session_impl.h
@@ -93,8 +93,7 @@ } #endif // defined(OS_ANDROID) - void NotifyMediaSessionMetadataChange( - const base::Optional<media_session::MediaMetadata>& metadata); + void NotifyMediaSessionMetadataChange(); // Adds the given player to the current media session. Returns whether the // player was successfully added. If it returns false, AddPlayer() should be @@ -336,6 +335,9 @@ CONTENT_EXPORT bool AddOneShotPlayer(MediaSessionPlayerObserver* observer, int player_id); + // Returns the current media metadata associated with this session. + media_session::MediaMetadata GetMediaMetadata() const; + // MediaSessionService-related methods // Called when the routed service may have changed.
diff --git a/content/browser/media/session/media_session_impl_browsertest.cc b/content/browser/media/session/media_session_impl_browsertest.cc index 7faecb7..99148cd 100644 --- a/content/browser/media/session/media_session_impl_browsertest.cc +++ b/content/browser/media/session/media_session_impl_browsertest.cc
@@ -235,6 +235,11 @@ bool IsDucking() const { return media_session_->is_ducking_; } + base::string16 GetExpectedSourceTitle() { + return base::ASCIIToUTF16( + shell()->web_contents()->GetLastCommittedURL().GetOrigin().host()); + } + protected: MediaSessionImpl* media_session_; std::unique_ptr<content::MockMediaSessionObserver> @@ -1853,7 +1858,10 @@ IN_PROC_BROWSER_TEST_P(MediaSessionImplParamBrowserTest, AddingMojoObserverNotifiesCurrentInformation_EmptyInfo) { media_session::test::MockMediaSessionMojoObserver observer(*media_session_); - EXPECT_FALSE(observer.WaitForMetadata()); + + media_session::MediaMetadata expected_metadata; + expected_metadata.source_title = GetExpectedSourceTitle(); + EXPECT_EQ(expected_metadata, observer.WaitForMetadata()); } IN_PROC_BROWSER_TEST_P(MediaSessionImplParamBrowserTest, @@ -1875,6 +1883,8 @@ media_session::test::MockMediaSessionMojoObserver observer(*media_session_); StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent); ResolveAudioFocusSuccess(); + + metadata.source_title = GetExpectedSourceTitle(); EXPECT_EQ(metadata, observer.WaitForNonEmptyMetadata()); } }
diff --git a/content/browser/media/session/media_session_impl_service_routing_unittest.cc b/content/browser/media/session/media_session_impl_service_routing_unittest.cc index c4a99ab..103ba3c 100644 --- a/content/browser/media/session/media_session_impl_service_routing_unittest.cc +++ b/content/browser/media/session/media_session_impl_service_routing_unittest.cc
@@ -131,6 +131,11 @@ ->RemovePlayer(players_[frame].get(), kPlayerId); } + base::string16 GetExpectedSourceTitle() { + return base::ASCIIToUTF16( + contents()->GetLastCommittedURL().GetOrigin().host()); + } + MockMediaSessionPlayerObserver* GetPlayerForFrame( TestRenderFrameHost* frame) { auto iter = players_.find(frame); @@ -279,13 +284,17 @@ TEST_F(MediaSessionImplServiceRoutingTest, NotifyMetadataAndActionsChangeWhenControllable) { + media_session::MediaMetadata empty_metadata; + empty_metadata.source_title = GetExpectedSourceTitle(); + media_session::MediaMetadata expected_metadata; expected_metadata.title = base::ASCIIToUTF16("title"); expected_metadata.artist = base::ASCIIToUTF16("artist"); expected_metadata.album = base::ASCIIToUTF16("album"); + expected_metadata.source_title = GetExpectedSourceTitle(); EXPECT_CALL(*mock_media_session_observer(), - MediaSessionMetadataChanged(Eq(base::nullopt))) + MediaSessionMetadataChanged(Eq(empty_metadata))) .Times(AnyNumber()); EXPECT_CALL(*mock_media_session_observer(), MediaSessionActionsChanged(Eq(default_actions()))) @@ -312,6 +321,7 @@ expected_metadata.title = base::ASCIIToUTF16("title"); expected_metadata.artist = base::ASCIIToUTF16("artist"); expected_metadata.album = base::ASCIIToUTF16("album"); + expected_metadata.source_title = GetExpectedSourceTitle(); EXPECT_CALL(*mock_media_session_observer(), MediaSessionMetadataChanged(Eq(expected_metadata))) @@ -330,11 +340,15 @@ } TEST_F(MediaSessionImplServiceRoutingTest, - DontNotifyMetadataAndActionsChangeWhenTurningUncontrollable) { + NotifyMetadataAndNotActionsChangeWhenTurningUncontrollable) { media_session::MediaMetadata expected_metadata; expected_metadata.title = base::ASCIIToUTF16("title"); expected_metadata.artist = base::ASCIIToUTF16("artist"); expected_metadata.album = base::ASCIIToUTF16("album"); + expected_metadata.source_title = GetExpectedSourceTitle(); + + media_session::MediaMetadata empty_metadata; + empty_metadata.source_title = GetExpectedSourceTitle(); std::set<MediaSessionAction> empty_actions; std::set<MediaSessionAction> expected_actions; @@ -345,8 +359,7 @@ EXPECT_CALL(*mock_media_session_observer(), MediaSessionActionsChanged(_)) .Times(AnyNumber()); EXPECT_CALL(*mock_media_session_observer(), - MediaSessionMetadataChanged(Eq(base::nullopt))) - .Times(0); + MediaSessionMetadataChanged(Eq(empty_metadata))); EXPECT_CALL(*mock_media_session_observer(), MediaSessionActionsChanged(Eq(empty_actions))) .Times(0); @@ -530,6 +543,7 @@ expected_metadata.title = base::ASCIIToUTF16("title"); expected_metadata.artist = base::ASCIIToUTF16("artist"); expected_metadata.album = base::ASCIIToUTF16("album"); + expected_metadata.source_title = GetExpectedSourceTitle(); CreateServiceForFrame(main_frame_); StartPlayerForFrame(main_frame_); @@ -547,15 +561,17 @@ CreateServiceForFrame(main_frame_); StartPlayerForFrame(main_frame_); + media_session::MediaMetadata expected_metadata; + expected_metadata.source_title = GetExpectedSourceTitle(); + { media_session::test::MockMediaSessionMojoObserver observer( *GetMediaSession()); services_[main_frame_]->SetMetadata(base::nullopt); - // When the session becomes controllable we should receive empty metadata - // because we have not set any. The |is_controllable| boolean will also - // become true. - EXPECT_FALSE(observer.WaitForMetadata()); + // When the session becomes controllable we should receive default + // metadata. The |is_controllable| boolean will also become true. + EXPECT_EQ(expected_metadata, observer.WaitForMetadata()); EXPECT_TRUE(observer.session_info()->is_controllable); } } @@ -644,4 +660,14 @@ EXPECT_EQ(expected_actions, observer.actions_set()); } +TEST_F(MediaSessionImplServiceRoutingTest, NotifyMojoObserverOnNavigation) { + media_session::test::MockMediaSessionMojoObserver observer( + *GetMediaSession()); + contents()->NavigateAndCommit(GURL("http://www.google.com")); + + media_session::MediaMetadata expected_metadata; + expected_metadata.source_title = base::ASCIIToUTF16("www.google.com"); + EXPECT_EQ(expected_metadata, observer.WaitForNonEmptyMetadata()); +} + } // namespace content
diff --git a/content/browser/renderer_host/input/mouse_wheel_phase_handler.cc b/content/browser/renderer_host/input/mouse_wheel_phase_handler.cc index 6056b1f..a326261 100644 --- a/content/browser/renderer_host/input/mouse_wheel_phase_handler.cc +++ b/content/browser/renderer_host/input/mouse_wheel_phase_handler.cc
@@ -120,7 +120,8 @@ touchpad_scroll_phase_state_ = TOUCHPAD_SCROLL_STATE_UNKNOWN; } -void MouseWheelPhaseHandler::SendWheelEndForTouchpadScrollingIfNeeded() { +void MouseWheelPhaseHandler::SendWheelEndForTouchpadScrollingIfNeeded( + bool should_route_event) { if (touchpad_scroll_phase_state_ == TOUCHPAD_SCROLL_IN_PROGRESS) { RenderWidgetHostImpl* widget_host = host_view_->host(); if (!widget_host) { @@ -128,8 +129,6 @@ return; } - bool should_route_event = widget_host->delegate() && - widget_host->delegate()->GetInputEventRouter(); TRACE_EVENT_INSTANT0("input", "MouseWheelPhaseHandler Sent touchpad end", TRACE_EVENT_SCOPE_THREAD); SendSyntheticWheelEventWithPhaseEnded(should_route_event);
diff --git a/content/browser/renderer_host/input/mouse_wheel_phase_handler.h b/content/browser/renderer_host/input/mouse_wheel_phase_handler.h index 305095f..fc252b6 100644 --- a/content/browser/renderer_host/input/mouse_wheel_phase_handler.h +++ b/content/browser/renderer_host/input/mouse_wheel_phase_handler.h
@@ -66,7 +66,7 @@ void DispatchPendingWheelEndEvent(); void IgnorePendingWheelEndEvent(); void ResetTouchpadScrollSequence(); - void SendWheelEndForTouchpadScrollingIfNeeded(); + void SendWheelEndForTouchpadScrollingIfNeeded(bool should_route_event); void TouchpadScrollingMayBegin(); // Used to set the timer timeout for testing.
diff --git a/content/browser/renderer_host/render_widget_host_view_event_handler.cc b/content/browser/renderer_host/render_widget_host_view_event_handler.cc index 1191efc..c362e6b 100644 --- a/content/browser/renderer_host/render_widget_host_view_event_handler.cc +++ b/content/browser/renderer_host/render_widget_host_view_event_handler.cc
@@ -120,7 +120,6 @@ RenderWidgetHostViewBase* host_view, Delegate* delegate) : accept_return_character_(false), - disable_input_event_router_for_testing_(false), mouse_locked_(false), pinch_zoom_enabled_(content::IsPinchToZoomEnabled()), set_focus_on_mouse_down_or_key_event_(false), @@ -358,10 +357,11 @@ ui::MakeWebMouseWheelEvent(*event->AsMouseWheelEvent()); if (mouse_wheel_event.delta_x != 0 || mouse_wheel_event.delta_y != 0) { - bool should_route_event = ShouldRouteEvent(event); + const bool should_route_event = ShouldRouteEvents(); // End the touchpad scrolling sequence (if such exists) before handling // a ui::ET_MOUSEWHEEL event. - mouse_wheel_phase_handler_.SendWheelEndForTouchpadScrollingIfNeeded(); + mouse_wheel_phase_handler_.SendWheelEndForTouchpadScrollingIfNeeded( + should_route_event); mouse_wheel_phase_handler_.AddPhaseIfNeededAndScheduleEndEvent( mouse_wheel_event, should_route_event); @@ -383,7 +383,7 @@ blink::WebMouseEvent mouse_event = ui::MakeWebMouseEvent(*event); ModifyEventMovementAndCoords(*event, &mouse_event); - if (ShouldRouteEvent(event)) { + if (ShouldRouteEvents()) { host_->delegate()->GetInputEventRouter()->RouteMouseEvent( host_view_, &mouse_event, *event->latency()); } else { @@ -415,7 +415,7 @@ void RenderWidgetHostViewEventHandler::OnScrollEvent(ui::ScrollEvent* event) { TRACE_EVENT0("input", "RenderWidgetHostViewBase::OnScrollEvent"); - bool should_route_event = ShouldRouteEvent(event); + const bool should_route_event = ShouldRouteEvents(); if (event->type() == ui::ET_SCROLL) { #if !defined(OS_WIN) // TODO(ananta) @@ -513,7 +513,7 @@ // touchcancel to make sure only send one ack per WebTouchEvent. MarkUnchangedTouchPointsAsStationary(&touch_event, event->pointer_details().id); - if (ShouldRouteEvent(event)) { + if (ShouldRouteEvents()) { host_->delegate()->GetInputEventRouter()->RouteTouchEvent( host_view_, &touch_event, *event->latency()); } else { @@ -548,7 +548,7 @@ blink::WebGestureEvent fling_cancel = gesture; fling_cancel.SetType(blink::WebInputEvent::kGestureFlingCancel); fling_cancel.SetSourceDevice(blink::kWebGestureDeviceTouchscreen); - if (ShouldRouteEvent(event)) { + if (ShouldRouteEvents()) { host_->delegate()->GetInputEventRouter()->RouteGestureEvent( host_view_, &fling_cancel, ui::LatencyInfo(ui::SourceEventType::TOUCH)); @@ -563,7 +563,8 @@ // wheel based send a synthetic wheel event with kPhaseEnded to cancel // the current scroll. mouse_wheel_phase_handler_.DispatchPendingWheelEndEvent(); - mouse_wheel_phase_handler_.SendWheelEndForTouchpadScrollingIfNeeded(); + mouse_wheel_phase_handler_.SendWheelEndForTouchpadScrollingIfNeeded( + ShouldRouteEvents()); } else if (event->type() == ui::ET_SCROLL_FLING_START) { RecordAction(base::UserMetricsAction("TouchscreenScrollFling")); } @@ -578,7 +579,7 @@ mouse_wheel_phase_handler_.ResetTouchpadScrollSequence(); } - if (ShouldRouteEvent(event)) { + if (ShouldRouteEvents()) { host_->delegate()->GetInputEventRouter()->RouteGestureEvent( host_view_, &gesture, *event->latency()); } else { @@ -731,7 +732,7 @@ blink::WebMouseWheelEvent mouse_wheel_event = ui::MakeWebMouseWheelEvent(*event->AsMouseWheelEvent()); if (mouse_wheel_event.delta_x != 0 || mouse_wheel_event.delta_y != 0) { - if (ShouldRouteEvent(event)) { + if (ShouldRouteEvents()) { host_->delegate()->GetInputEventRouter()->RouteMouseWheelEvent( host_view_, &mouse_wheel_event, *event->latency()); } else { @@ -791,7 +792,7 @@ // Forward event to renderer. if (CanRendererHandleEvent(event, mouse_locked_, is_selection_popup) && !(event->flags() & ui::EF_FROM_TOUCH)) { - if (ShouldRouteEvent(event)) { + if (ShouldRouteEvents()) { host_->delegate()->GetInputEventRouter()->RouteMouseEvent( host_view_, &mouse_event, *event->latency()); } else { @@ -897,28 +898,17 @@ global_mouse_position_.y() > rect.bottom() - border_y; } -bool RenderWidgetHostViewEventHandler::ShouldRouteEvent( - const ui::Event* event) const { - // We should route an event in two cases: - // 1) Mouse events are routed only if cross-process frames are possible. - // 2) Touch events are always routed. In the absence of a BrowserPlugin - // we expect the routing to always send the event to this view. If - // one or more BrowserPlugins are present, then the event may be targeted - // to one of them, or this view. This allows GuestViews to have access to - // them while still forcing pinch-zoom to be handled by the top-level - // frame. TODO(wjmaclean): At present, this doesn't work for OOPIF, but - // it should be a simple extension to modify RenderWidgetHostViewChildFrame - // in a similar manner to RenderWidgetHostViewGuest. - bool result = host_->delegate() && host_->delegate()->GetInputEventRouter() && - !disable_input_event_router_for_testing_; +bool RenderWidgetHostViewEventHandler::ShouldRouteEvents() const { + if (!host_->delegate()) + return false; // Do not route events that are currently targeted to page popups such as // <select> element drop-downs, since these cannot contain cross-process // frames. - if (host_->delegate() && !host_->delegate()->IsWidgetForMainFrame(host_)) + if (!host_->delegate()->IsWidgetForMainFrame(host_)) return false; - return result; + return !!host_->delegate()->GetInputEventRouter(); } void RenderWidgetHostViewEventHandler::ProcessMouseEvent(
diff --git a/content/browser/renderer_host/render_widget_host_view_event_handler.h b/content/browser/renderer_host/render_widget_host_view_event_handler.h index 1a8d27b..63f2fcb 100644 --- a/content/browser/renderer_host/render_widget_host_view_event_handler.h +++ b/content/browser/renderer_host/render_widget_host_view_event_handler.h
@@ -131,9 +131,6 @@ #endif // defined(OS_WIN) bool accept_return_character() { return accept_return_character_; } - void disable_input_event_router_for_testing() { - disable_input_event_router_for_testing_ = true; - } bool mouse_locked() { return mouse_locked_; } const ui::MotionEventAura& pointer_state() const { return pointer_state_; } void set_focus_on_mouse_down_or_key_event( @@ -219,8 +216,9 @@ // moved to center. bool ShouldMoveToCenter(); - // Returns true when we can do SurfaceHitTesting for the event type. - bool ShouldRouteEvent(const ui::Event* event) const; + // Returns true when we can hit test input events with location data to be + // sent to the targeted RenderWidgetHost. + bool ShouldRouteEvents() const; // Directs events to the |host_|. void ProcessMouseEvent(const blink::WebMouseEvent& event, @@ -236,11 +234,6 @@ // Whether return characters should be passed on to the RenderWidgetHostImpl. bool accept_return_character_; - // Allows tests to send gesture events for testing without first sending a - // corresponding touch sequence, as would be required by - // RenderWidgetHostInputEventRouter. - bool disable_input_event_router_for_testing_; - // Deactivates keyboard lock when destroyed. std::unique_ptr<aura::ScopedKeyboardHook> scoped_keyboard_hook_;
diff --git a/content/browser/renderer_host/render_widget_host_view_mac.h b/content/browser/renderer_host/render_widget_host_view_mac.h index 2714255..4c9994c 100644 --- a/content/browser/renderer_host/render_widget_host_view_mac.h +++ b/content/browser/renderer_host/render_widget_host_view_mac.h
@@ -186,8 +186,9 @@ const viz::FrameSinkId& GetFrameSinkId() const override; const viz::LocalSurfaceIdAllocation& GetLocalSurfaceIdAllocation() const override; - // Returns true when we can do SurfaceHitTesting for the event type. - bool ShouldRouteEvent(const blink::WebInputEvent& event) const; + // Returns true when we can hit test input events with location data to be + // sent to the targeted RenderWidgetHost. + bool ShouldRouteEvents() const; // This method checks |event| to see if a GesturePinch or double tap event // can be routed according to ShouldRouteEvent, and if not, sends it directly // to the view's RenderWidgetHost.
diff --git a/content/browser/renderer_host/render_widget_host_view_mac.mm b/content/browser/renderer_host/render_widget_host_view_mac.mm index 6a40bd5..7bdf6790 100644 --- a/content/browser/renderer_host/render_widget_host_view_mac.mm +++ b/content/browser/renderer_host/render_widget_host_view_mac.mm
@@ -666,7 +666,7 @@ ui::LatencyInfo latency_info(ui::SourceEventType::TOUCH); - if (ShouldRouteEvent(web_gesture)) { + if (ShouldRouteEvents()) { blink::WebGestureEvent gesture_event(web_gesture); host()->delegate()->GetInputEventRouter()->RouteGestureEvent( this, &gesture_event, latency_info); @@ -1241,25 +1241,20 @@ return browser_compositor_->GetDelegatedFrameHost()->frame_sink_id(); } -bool RenderWidgetHostViewMac::ShouldRouteEvent( - const WebInputEvent& event) const { +bool RenderWidgetHostViewMac::ShouldRouteEvents() const { // Event routing requires a valid frame sink (that is, that we be connected to // a ui::Compositor), which is not guaranteed to be the case. // https://crbug.com/844095 if (!browser_compositor_->GetRootFrameSinkId().is_valid()) return false; - // See also RenderWidgetHostViewAura::ShouldRouteEvent. - // TODO(wjmaclean): Update this function if RenderWidgetHostViewMac implements - // OnTouchEvent(), to match what we are doing in RenderWidgetHostViewAura. - // The only touch events and touch gesture events expected here are - // injected synthetic events. + return host()->delegate() && host()->delegate()->GetInputEventRouter(); } void RenderWidgetHostViewMac::SendTouchpadZoomEvent( const WebGestureEvent* event) { DCHECK(event->IsTouchpadZoomEvent()); - if (ShouldRouteEvent(*event)) { + if (ShouldRouteEvents()) { host()->delegate()->GetInputEventRouter()->RouteGestureEvent( this, event, ui::LatencyInfo(ui::SourceEventType::TOUCHPAD)); return; @@ -1275,7 +1270,7 @@ if (!result.succeeded) return; - if (ShouldRouteEvent(event)) { + if (ShouldRouteEvents()) { WebTouchEvent touch_event(event); host()->delegate()->GetInputEventRouter()->RouteTouchEvent( this, &touch_event, latency_info); @@ -1580,7 +1575,7 @@ blink::WebMouseEvent web_event = const_web_event; ui::LatencyInfo latency_info(ui::SourceEventType::OTHER); latency_info.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_UI_COMPONENT); - if (ShouldRouteEvent(web_event)) { + if (ShouldRouteEvents()) { host()->delegate()->GetInputEventRouter()->RouteMouseEvent(this, &web_event, latency_info); } else { @@ -1598,7 +1593,7 @@ ui::LatencyInfo latency_info(ui::SourceEventType::OTHER); latency_info.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_UI_COMPONENT); - if (ShouldRouteEvent(web_event)) { + if (ShouldRouteEvents()) { host()->delegate()->GetInputEventRouter()->RouteTouchEvent(this, &web_event, latency_info); } else { @@ -1612,14 +1607,14 @@ ui::LatencyInfo latency_info(ui::SourceEventType::WHEEL); latency_info.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_UI_COMPONENT); mouse_wheel_phase_handler_.AddPhaseIfNeededAndScheduleEndEvent( - web_event, ShouldRouteEvent(web_event)); + web_event, ShouldRouteEvents()); if (web_event.phase == blink::WebMouseWheelEvent::kPhaseEnded) { // A wheel end event is scheduled and will get dispatched if momentum // phase doesn't start in 100ms. Don't sent the wheel end event // immediately. return; } - if (ShouldRouteEvent(web_event)) { + if (ShouldRouteEvents()) { host()->delegate()->GetInputEventRouter()->RouteMouseWheelEvent( this, &web_event, latency_info); } else {
diff --git a/content/child/runtime_features.cc b/content/child/runtime_features.cc index 1714e14..fe29b7f 100644 --- a/content/child/runtime_features.cc +++ b/content/child/runtime_features.cc
@@ -259,6 +259,10 @@ base::FeatureList::IsEnabled(features::kSecMetadata) || enable_experimental_web_platform_features); + WebRuntimeFeatures::EnableUserActivationSameOriginVisibility( + base::FeatureList::IsEnabled( + features::kUserActivationSameOriginVisibility)); + WebRuntimeFeatures::EnableUserActivationV2( base::FeatureList::IsEnabled(features::kUserActivationV2));
diff --git a/content/renderer/media/stream/webmediaplayer_ms.cc b/content/renderer/media/stream/webmediaplayer_ms.cc index 3e0f2da..e3041ad 100644 --- a/content/renderer/media/stream/webmediaplayer_ms.cc +++ b/content/renderer/media/stream/webmediaplayer_ms.cc
@@ -1097,7 +1097,7 @@ base::BindOnce( &WebMediaPlayerMSCompositor::EnableSubmission, compositor_, bridge_->GetSurfaceId(), bridge_->GetLocalSurfaceIdAllocationTime(), - video_rotation_, IsInPictureInPicture(), opaque_, + video_rotation_, IsInPictureInPicture(), media::BindToCurrentLoop(base::BindRepeating( &WebMediaPlayerMS::OnFrameSinkDestroyed, AsWeakPtr()))));
diff --git a/content/renderer/media/stream/webmediaplayer_ms_compositor.cc b/content/renderer/media/stream/webmediaplayer_ms_compositor.cc index 64d6174..b74a226 100644 --- a/content/renderer/media/stream/webmediaplayer_ms_compositor.cc +++ b/content/renderer/media/stream/webmediaplayer_ms_compositor.cc
@@ -215,7 +215,6 @@ base::TimeTicks local_surface_id_allocation_time, media::VideoRotation rotation, bool force_submit, - bool is_opaque, blink::WebFrameSinkDestroyedCallback frame_sink_destroyed_callback) { DCHECK(video_frame_compositor_task_runner_->BelongsToCurrentThread()); @@ -227,7 +226,6 @@ submitter_->SetRotation(rotation); submitter_->SetForceSubmit(force_submit); - submitter_->SetIsOpaque(is_opaque); submitter_->EnableSubmission(id, local_surface_id_allocation_time, std::move(frame_sink_destroyed_callback)); video_frame_provider_client_ = submitter_.get(); @@ -573,8 +571,6 @@ main_task_runner_->PostTask( FROM_HERE, base::BindOnce(&WebMediaPlayerMS::OnOpacityChanged, player_, new_frame_is_opaque)); - if (submitter_) - submitter_->SetIsOpaque(new_frame_is_opaque); } if (old_frame->natural_size() != new_frame->natural_size()) { main_task_runner_->PostTask(
diff --git a/content/renderer/media/stream/webmediaplayer_ms_compositor.h b/content/renderer/media/stream/webmediaplayer_ms_compositor.h index a99484b..c3a01b6 100644 --- a/content/renderer/media/stream/webmediaplayer_ms_compositor.h +++ b/content/renderer/media/stream/webmediaplayer_ms_compositor.h
@@ -90,7 +90,6 @@ base::TimeTicks local_surface_id_allocation_time, media::VideoRotation rotation, bool force_submit, - bool is_opaque, blink::WebFrameSinkDestroyedCallback frame_sink_destroyed_callback); // Notifies the |submitter_| that the frames must be submitted.
diff --git a/content/renderer/media/stream/webmediaplayer_ms_unittest.cc b/content/renderer/media/stream/webmediaplayer_ms_unittest.cc index 3bd0681..128d2a2 100644 --- a/content/renderer/media/stream/webmediaplayer_ms_unittest.cc +++ b/content/renderer/media/stream/webmediaplayer_ms_unittest.cc
@@ -427,7 +427,6 @@ MOCK_METHOD0(StopRendering, void()); MOCK_METHOD1(MockInitialize, void(cc::VideoFrameProvider*)); MOCK_METHOD1(SetRotation, void(media::VideoRotation)); - MOCK_METHOD1(MockSetIsOpaque, void(bool)); MOCK_METHOD1(SetIsSurfaceVisible, void(bool)); MOCK_METHOD1(SetIsPageVisible, void(bool)); MOCK_METHOD1(SetForceSubmit, void(bool)); @@ -438,13 +437,6 @@ MockInitialize(provider); } - // This method may try accessing frames, see deadlock case in - // https://crbug.com/901744. - void SetIsOpaque(bool opaque) override { - auto frame = provider_->GetCurrentFrame(); - MockSetIsOpaque(opaque); - } - private: cc::VideoFrameProvider* provider_; }; @@ -1188,7 +1180,6 @@ provider->QueueFrames(timestamps, false); if (enable_surface_layer_for_video_) { EXPECT_CALL(*surface_layer_bridge_ptr_, SetContentsOpaque(false)); - EXPECT_CALL(*submitter_ptr_, MockSetIsOpaque(false)); } message_loop_controller_.RunAndWaitForStatus( media::PipelineStatus::PIPELINE_OK); @@ -1203,7 +1194,6 @@ provider->QueueFrames(timestamps, true); if (enable_surface_layer_for_video_) { EXPECT_CALL(*surface_layer_bridge_ptr_, SetContentsOpaque(true)); - EXPECT_CALL(*submitter_ptr_, MockSetIsOpaque(true)); } message_loop_controller_.RunAndWaitForStatus( media::PipelineStatus::PIPELINE_OK);
diff --git a/content/shell/BUILD.gn b/content/shell/BUILD.gn index 657cc79..1a90666 100644 --- a/content/shell/BUILD.gn +++ b/content/shell/BUILD.gn
@@ -10,7 +10,6 @@ import("//media/media_options.gni") import("//mojo/public/tools/bindings/mojom.gni") import("//ppapi/buildflags/buildflags.gni") -import("//services/service_manager/public/service_manifest.gni") import("//tools/grit/grit_rule.gni") import("//tools/grit/repack.gni") import("//tools/v8_context_snapshot/v8_context_snapshot.gni") @@ -261,7 +260,6 @@ "//services/network:network_service", ] deps = [ - ":content_shell_packaged_services_manifest_overlay", ":resources", ":web_test_switches", ":web_test_utils", @@ -296,6 +294,7 @@ "//device/bluetooth", "//device/bluetooth:fake_bluetooth", "//device/bluetooth:mocks", + "//device/bluetooth/public/mojom:fake_bluetooth_interfaces", "//gin", "//gpu", "//media", @@ -312,6 +311,7 @@ "//services/service_manager/embedder:embedder_result_codes", "//services/service_manager/public/cpp", "//services/test/echo:lib", + "//services/test/echo:manifest", "//services/test/echo/public/mojom", "//skia", "//storage/browser", @@ -441,6 +441,7 @@ deps += [ "//chromeos/dbus", "//services/ws/test_ws:lib", + "//services/ws/test_ws:manifest", "//services/ws/test_ws:mojom", "//ui/wm:test_support", ] @@ -472,16 +473,6 @@ "grit/shell_resources.h", "shell_resources.pak", ] - - # Mojo manifest overlays are generated. - source_is_generated = true - grit_flags = [ - "-E", - "root_gen_dir=" + rebase_path(root_gen_dir, root_build_dir), - ] - deps = [ - ":content_shell_packaged_services_manifest_overlay", - ] } copy("copy_shell_resources") { @@ -929,17 +920,6 @@ ] } -service_manifest("content_shell_packaged_services_manifest_overlay") { - testonly = true - - source = "//content/shell/browser/content_shell_packaged_services_manifest_overlay.json" - packaged_services = [ "//services/test/echo:manifest" ] - - if (is_chromeos) { - packaged_services += [ "//services/ws/test_ws:manifest" ] - } -} - group("content_shell_crash_test") { testonly = true data_deps = [
diff --git a/content/shell/browser/DEPS b/content/shell/browser/DEPS index 1d4f62d..0e08b66 100644 --- a/content/shell/browser/DEPS +++ b/content/shell/browser/DEPS
@@ -3,9 +3,10 @@ "+components/keyed_service/content", "+components/network_session_configurator/common", "+services/device/public/cpp", + "+services/network/public", "+services/service_manager/public/cpp", "+services/service_manager/sandbox", - "+services/network/public", + "+services/ws/public", "+ui/ozone/public", ]
diff --git a/content/shell/browser/OWNERS b/content/shell/browser/OWNERS index f606772..ae466884 100644 --- a/content/shell/browser/OWNERS +++ b/content/shell/browser/OWNERS
@@ -1,13 +1,2 @@ per-file shell_android.cc=tedchoc@chromium.org per-file shell_web_contents_view_delegate_android.cc=tedchoc@chromium.org - -per-file content_shell_browser_manifest_overlay.json=set noparent -per-file content_shell_browser_manifest_overlay.json=file://ipc/SECURITY_OWNERS -per-file content_shell_gpu_manifest_overlay.json=set noparent -per-file content_shell_gpu_manifest_overlay.json=file://ipc/SECURITY_OWNERS -per-file content_shell_packaged_services_manifest_overlay.json=set noparent -per-file content_shell_packaged_services_manifest_overlay.json=file://ipc/SECURITY_OWNERS -per-file content_shell_renderer_manifest_overlay.json=set noparent -per-file content_shell_renderer_manifest_overlay.json=file://ipc/SECURITY_OWNERS -per-file content_shell_utility_manifest_overlay.json=set noparent -per-file content_shell_utility_manifest_overlay.json=file://ipc/SECURITY_OWNERS
diff --git a/content/shell/browser/content_shell_browser_manifest_overlay.json b/content/shell/browser/content_shell_browser_manifest_overlay.json deleted file mode 100644 index 48bf90c..0000000 --- a/content/shell/browser/content_shell_browser_manifest_overlay.json +++ /dev/null
@@ -1,29 +0,0 @@ -{ - "name": "content_browser", - "interface_provider_specs": { - "service_manager:connector": { - "provides": { - "renderer": [ - "content.mojom.MojoWebTestHelper", - "content.mojom.FakeBluetoothChooser", - "content.mojom.WebTestBluetoothFakeAdapterSetter", - "bluetooth.mojom.FakeBluetooth" - ] - }, - "requires": { - "echo": [ - "echo" - ], - "ui": [ "test" ], - "test_ws": [ "test" ] - } - }, - "navigation:frame": { - "provides": { - "renderer": [ - "content.mojom.MojoWebTestHelper" - ] - } - } - } -}
diff --git a/content/shell/browser/content_shell_gpu_manifest_overlay.json b/content/shell/browser/content_shell_gpu_manifest_overlay.json deleted file mode 100644 index b3ce24a..0000000 --- a/content/shell/browser/content_shell_gpu_manifest_overlay.json +++ /dev/null
@@ -1,12 +0,0 @@ -{ - "name": "content_gpu", - "interface_provider_specs": { - "service_manager:connector": { - "provides": { - "browser": [ - "content.mojom.PowerMonitorTest" - ] - } - } - } -}
diff --git a/content/shell/browser/content_shell_packaged_services_manifest_overlay.json b/content/shell/browser/content_shell_packaged_services_manifest_overlay.json deleted file mode 100644 index cbd4dec..0000000 --- a/content/shell/browser/content_shell_packaged_services_manifest_overlay.json +++ /dev/null
@@ -1,5 +0,0 @@ -{ - "name": "content_packaged_services", - "display_name": "Content Shell Packaged Services", - "interface_provider_specs": {} -}
diff --git a/content/shell/browser/content_shell_renderer_manifest_overlay.json b/content/shell/browser/content_shell_renderer_manifest_overlay.json deleted file mode 100644 index 47b29360..0000000 --- a/content/shell/browser/content_shell_renderer_manifest_overlay.json +++ /dev/null
@@ -1,20 +0,0 @@ -{ - "name": "content_renderer", - "interface_provider_specs": { - "service_manager:connector": { - "provides": { - "browser": [ - "content.mojom.PowerMonitorTest", - "content.mojom.TestService" - ] - } - }, - "navigation:frame": { - "provides": { - "browser": [ - "content.mojom.WebTestControl" - ] - } - } - } -}
diff --git a/content/shell/browser/content_shell_utility_manifest_overlay.json b/content/shell/browser/content_shell_utility_manifest_overlay.json deleted file mode 100644 index 1beaf4e..0000000 --- a/content/shell/browser/content_shell_utility_manifest_overlay.json +++ /dev/null
@@ -1,13 +0,0 @@ -{ - "name": "content_utility", - "interface_provider_specs": { - "service_manager:connector": { - "provides": { - "browser": [ - "content.mojom.PowerMonitorTest", - "content.mojom.TestService" - ] - } - } - } -}
diff --git a/content/shell/browser/shell_content_browser_client.cc b/content/shell/browser/shell_content_browser_client.cc index d216b50..40dd1b2 100644 --- a/content/shell/browser/shell_content_browser_client.cc +++ b/content/shell/browser/shell_content_browser_client.cc
@@ -12,7 +12,7 @@ #include "base/command_line.h" #include "base/files/file.h" #include "base/files/file_util.h" -#include "base/json/json_reader.h" +#include "base/no_destructor.h" #include "base/path_service.h" #include "base/stl_util.h" #include "base/strings/utf_string_conversions.h" @@ -40,19 +40,26 @@ #include "content/shell/browser/shell_quota_permission_context.h" #include "content/shell/browser/shell_url_request_context_getter.h" #include "content/shell/browser/shell_web_contents_view_delegate_creator.h" +#include "content/shell/common/power_monitor_test.mojom.h" #include "content/shell/common/shell_messages.h" #include "content/shell/common/shell_switches.h" +#include "content/shell/common/web_test.mojom.h" +#include "content/shell/common/web_test/fake_bluetooth_chooser.mojom.h" +#include "content/shell/common/web_test/web_test_bluetooth_fake_adapter_setter.mojom.h" #include "content/shell/common/web_test/web_test_switches.h" -#include "content/shell/grit/shell_resources.h" +#include "content/test/data/mojo_web_test_helper_test.mojom.h" +#include "device/bluetooth/public/mojom/test/fake_bluetooth.mojom.h" #include "media/mojo/buildflags.h" #include "net/ssl/client_cert_identity.h" #include "net/url_request/url_request.h" #include "net/url_request/url_request_context_getter.h" #include "services/network/public/cpp/features.h" #include "services/network/public/mojom/network_service.mojom.h" +#include "services/service_manager/public/cpp/manifest.h" +#include "services/service_manager/public/cpp/manifest_builder.h" +#include "services/test/echo/manifest.h" #include "services/test/echo/public/mojom/echo.mojom.h" #include "storage/browser/quota/quota_settings.h" -#include "ui/base/resource/resource_bundle.h" #include "ui/base/ui_base_features.h" #include "url/gurl.h" #include "url/origin.h" @@ -68,6 +75,8 @@ // TODO(https://crbug.com/784179): Remove nogncheck. #include "content/public/browser/context_factory.h" #include "content/public/browser/gpu_interface_provider_factory.h" +#include "services/ws/public/mojom/constants.mojom.h" // nogncheck +#include "services/ws/test_ws/manifest.h" // nogncheck #include "services/ws/test_ws/test_window_service_factory.h" // nogncheck #include "services/ws/test_ws/test_ws.mojom.h" // nogncheck #endif @@ -146,6 +155,75 @@ } #endif // defined(OS_ANDROID) +const service_manager::Manifest& GetContentBrowserOverlayManifest() { + static base::NoDestructor<service_manager::Manifest> manifest { + service_manager::ManifestBuilder() + .ExposeCapability( + "renderer", + service_manager::Manifest::InterfaceList< + mojom::MojoWebTestHelper, mojom::FakeBluetoothChooser, + mojom::WebTestBluetoothFakeAdapterSetter, + bluetooth::mojom::FakeBluetooth>()) + .RequireCapability(echo::mojom::kServiceName, "echo") +#if defined(OS_CHROMEOS) + .RequireCapability(ws::mojom::kServiceName, "test") + .RequireCapability("test_ws", "test") +#endif + .ExposeInterfaceFilterCapability_Deprecated( + "navigation:frame", "renderer", + service_manager::Manifest::InterfaceList< + mojom::MojoWebTestHelper>()) + .Build() + }; + return *manifest; +} + +const service_manager::Manifest& GetContentGpuOverlayManifest() { + static base::NoDestructor<service_manager::Manifest> manifest{ + service_manager::ManifestBuilder() + .ExposeCapability("browser", service_manager::Manifest::InterfaceList< + mojom::PowerMonitorTest>()) + .Build()}; + return *manifest; +} + +const service_manager::Manifest& GetContentPackagedServicesOverlayManifest() { + static base::NoDestructor<service_manager::Manifest> manifest { + service_manager::ManifestBuilder() + .PackageService(echo::GetManifest()) +#if defined(OS_CHROMEOS) + .PackageService(test_ws::GetManifest()) +#endif + .Build() + }; + return *manifest; +} + +const service_manager::Manifest& GetContentRendererOverlayManifest() { + static base::NoDestructor<service_manager::Manifest> manifest{ + service_manager::ManifestBuilder() + .ExposeCapability( + "browser", + service_manager::Manifest::InterfaceList<mojom::PowerMonitorTest, + mojom::TestService>()) + .ExposeInterfaceFilterCapability_Deprecated( + "navigation:frame", "browser", + service_manager::Manifest::InterfaceList<mojom::WebTestControl>()) + .Build()}; + return *manifest; +} + +const service_manager::Manifest& GetContentUtilityOverlayManifest() { + static base::NoDestructor<service_manager::Manifest> manifest{ + service_manager::ManifestBuilder() + .ExposeCapability( + "browser", + service_manager::Manifest::InterfaceList<mojom::PowerMonitorTest, + mojom::TestService>()) + .Build()}; + return *manifest; +} + } // namespace std::string GetShellUserAgent() { @@ -254,25 +332,18 @@ base::Optional<service_manager::Manifest> ShellContentBrowserClient::GetServiceManifestOverlay(base::StringPiece name) { - int id = -1; if (name == content::mojom::kBrowserServiceName) - id = IDR_CONTENT_SHELL_BROWSER_MANIFEST_OVERLAY; - else if (name == content::mojom::kPackagedServicesServiceName) - id = IDR_CONTENT_SHELL_PACKAGED_SERVICES_MANIFEST_OVERLAY; - else if (name == content::mojom::kGpuServiceName) - id = IDR_CONTENT_SHELL_GPU_MANIFEST_OVERLAY; - else if (name == content::mojom::kRendererServiceName) - id = IDR_CONTENT_SHELL_RENDERER_MANIFEST_OVERLAY; - else if (name == content::mojom::kUtilityServiceName) - id = IDR_CONTENT_SHELL_UTILITY_MANIFEST_OVERLAY; - if (id == -1) - return base::nullopt; + return GetContentBrowserOverlayManifest(); + if (name == content::mojom::kPackagedServicesServiceName) + return GetContentPackagedServicesOverlayManifest(); + if (name == content::mojom::kGpuServiceName) + return GetContentGpuOverlayManifest(); + if (name == content::mojom::kRendererServiceName) + return GetContentRendererOverlayManifest(); + if (name == content::mojom::kUtilityServiceName) + return GetContentUtilityOverlayManifest(); - base::StringPiece manifest_contents = - ui::ResourceBundle::GetSharedInstance().GetRawDataResourceForScale( - id, ui::ScaleFactor::SCALE_FACTOR_NONE); - return service_manager::Manifest::FromValueDeprecated( - base::JSONReader::Read(manifest_contents)); + return base::nullopt; } void ShellContentBrowserClient::AppendExtraCommandLineSwitches(
diff --git a/content/shell/shell_resources.grd b/content/shell/shell_resources.grd index f1843a2..166fc598 100644 --- a/content/shell/shell_resources.grd +++ b/content/shell/shell_resources.grd
@@ -13,12 +13,6 @@ <include name="IDR_CONTENT_SHELL_DEVTOOLS_DISCOVERY_PAGE" file="resources/shell_devtools_discovery_page.html" type="BINDATA" /> <include name="IDR_CONTENT_SHELL_MISSING_IMAGE_GIF" file="resources/missingImage.gif" type="BINDATA" /> <include name="IDR_CONTENT_SHELL_MISSING_IMAGE_PNG" file="resources/missingImage.png" type="BINDATA" /> - <include name="IDR_CONTENT_SHELL_BROWSER_MANIFEST_OVERLAY" file="browser/content_shell_browser_manifest_overlay.json" type="BINDATA" /> - <include name="IDR_CONTENT_SHELL_GPU_MANIFEST_OVERLAY" file="browser/content_shell_gpu_manifest_overlay.json" type="BINDATA" /> - <include name="IDR_CONTENT_SHELL_RENDERER_MANIFEST_OVERLAY" file="browser/content_shell_renderer_manifest_overlay.json" type="BINDATA" /> - <include name="IDR_CONTENT_SHELL_UTILITY_MANIFEST_OVERLAY" file="browser/content_shell_utility_manifest_overlay.json" type="BINDATA" /> - <!-- Generated resources. --> - <include name="IDR_CONTENT_SHELL_PACKAGED_SERVICES_MANIFEST_OVERLAY" file="${root_gen_dir}/content/shell/content_shell_packaged_services_manifest_overlay.json" type="BINDATA" use_base_dir="false"/> </includes> </release> </grit>
diff --git a/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py b/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py index 5a0aab28..42abd1b3 100644 --- a/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py +++ b/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py
@@ -510,6 +510,8 @@ self.Flaky('conformance2/textures/image_bitmap_from_video/' + 'tex-2d-rgba16f-rgba-half_float.html', ['mac', ('nvidia', 0xfe9)], bug=682834) + self.Flaky('conformance2/textures/canvas/tex-3d-rg16f-rg-float.html', + ['mac', ('nvidia', 0xfe9)], bug=922517) self.Fail('conformance/glsl/bugs/init-array-with-loop.html', ['mac', ('nvidia', 0xfe9)], bug=784817)
diff --git a/content/test/gpu/gpu_tests/webgl_conformance_expectations.py b/content/test/gpu/gpu_tests/webgl_conformance_expectations.py index 3219940d3..699d05a 100644 --- a/content/test/gpu/gpu_tests/webgl_conformance_expectations.py +++ b/content/test/gpu/gpu_tests/webgl_conformance_expectations.py
@@ -553,6 +553,8 @@ # Mac Retina NVidia failures self.Fail('conformance/attribs/gl-disabled-vertex-attrib.html', ['mac', ('nvidia', 0xfe9)], bug=635081) + self.Flaky('conformance/ogles/GL/exp2/exp2_001_to_008.html', + ['mac', ('nvidia', 0xfe9)], bug=923080) self.Fail('conformance/programs/' + 'gl-bind-attrib-location-long-names-test.html', ['mac', ('nvidia', 0xfe9)], bug=635081)
diff --git a/content/test/mock_overscroll_refresh_handler_android.cc b/content/test/mock_overscroll_refresh_handler_android.cc index 7337058..0d480642 100644 --- a/content/test/mock_overscroll_refresh_handler_android.cc +++ b/content/test/mock_overscroll_refresh_handler_android.cc
@@ -13,7 +13,7 @@ MockOverscrollRefreshHandlerAndroid::~MockOverscrollRefreshHandlerAndroid() {} -bool MockOverscrollRefreshHandlerAndroid::PullStart() { +bool MockOverscrollRefreshHandlerAndroid::PullStart(float, float) { // The first GestureScrollUpdate starts the pull, but does not update the // pull. For the purpose of testing, we'll be consistent with aura // overscroll and consider this an update. @@ -21,7 +21,7 @@ return true; } -void MockOverscrollRefreshHandlerAndroid::PullUpdate(float) { +void MockOverscrollRefreshHandlerAndroid::PullUpdate(float, float) { OnPullUpdate(); }
diff --git a/content/test/mock_overscroll_refresh_handler_android.h b/content/test/mock_overscroll_refresh_handler_android.h index e74cdb07..708bfc2 100644 --- a/content/test/mock_overscroll_refresh_handler_android.h +++ b/content/test/mock_overscroll_refresh_handler_android.h
@@ -22,8 +22,8 @@ ~MockOverscrollRefreshHandlerAndroid() override; // ui::OverscrollRefreshHandler: - bool PullStart() override; - void PullUpdate(float) override; + bool PullStart(float, float) override; + void PullUpdate(float, float) override; void PullRelease(bool) override; void PullReset() override;
diff --git a/docs/security/rule-of-2.md b/docs/security/rule-of-2.md new file mode 100644 index 0000000..935bd72 --- /dev/null +++ b/docs/security/rule-of-2.md
@@ -0,0 +1,125 @@ +# The Rule Of 2 + +When you write code to parse, evaluate, or otherwise handle untrustworthy inputs +from the Internet — which is almost everything we do in a web browser! — we like +to follow a simple rule to make sure it's safe enough to do so. The Rule Of 2 +is: Pick no more than 2 of + + * untrustworthy inputs; + * unsafe implementation language; and + * high privilege. + +## Why? + +When code that handles untrustworthy inputs at high privilege has bugs, the +resulting vulnerabilities are typically of Critical or High severity. (See our +[Severity Guidelines](severity-guidelines.md).) We'd love to reduce the severity +of such bugs by reducing the amount of damage they can do (lowering their +privilege), avoiding the classes of memory corruption bugs (using a safe +language), or reducing the likelihood that the input is malicious (asserting the +trustworthiness of the source). + +## What? + +_Untrustworthy inputs_ are inputs that + + * have non-trivial grammars; or + * come from untrustworthy sources. + +Unfortunately, essentially no format you will ever come across has a trivial +grammar. And, of course, any arbitrary peer on the Internet is an untrustworthy +source. + +_Unsafe implementation languages_ are languages that lack +[memory safety](https://en.wikipedia.org/wiki/Memory_safety), including at least +C, C++, and assembly language. Memory-safe languages include Go, Rust, Python, +Java, JavaScript, Kotlin, and Swift. + +_High privilege_ is a relative term. The very highest-privilege programs are the +computer's firmware, the bootloader, the kernel, any hypervisor or virtual +machine monitor, and so on. Below that are processes that run as an OS-level +account representing a person; this includes the Chrome browser process. We +consider such processes to have high privilege. (After all, they can do anything +the person can do, with any and all of the person's valuable data and accounts.) + +Processes with slightly reduced privilege include (as of January 2019) the +network process and the GPU process. These are still pretty high-privilege +processes. We are always looking for ways to reduce their privilege without +breaking them. + +Low-privilege processes include sandboxed utility processes and renderer +processes with [Site +Isolation](https://www.chromium.org/Home/chromium-security/site-isolation) (very +good) or [origin +isolation](https://www.chromium.org/administrators/policy-list-3#IsolateOrigins) +(even better). + +## Solutions To This Puzzle + +Chrome Security Team will generally not approve for landing a CL or new feature +that involves all 3 of untrustworthy inputs, unsafe language, and high +privilege. To solve this problem, you need to get rid of at least 1 of those 3 +things. Here are some ways to do that. + +### Privilege Reduction + +Also known as [_sandboxing_](https://cs.chromium.org/chromium/src/sandbox/), +privilege reduction means running the code in a process that has had some or +many of its privileges revoked. + +When appropriate, try to handle the inputs in a renderer process that is Site +Isolated to the same site as the inputs come from. Take care to validate the +parsed (processed) inputs in the browser, since the semantics of the data are +not necessarily trustworthy yet. + +Equivalently, you can launch a sandboxed utility process to handle the data, and +return a well-formed response back to the caller in an IPC message. An example +of launching a utility process to parse an untrustworthy input is [Safe +Browsing's ZIP +analyzer](https://cs.chromium.org/chromium/src/chrome/common/safe_browsing/zip_analyzer.h). + +### Verifying The Trustworthiness Of A Source + +If you can be sure that the input comes from a trustworthy source, it can be OK +to parse/evaluate it at high privilege in an unsafe language. A "trustworthy +source" meets all of these criteria: + + * communication happens via validly-authenticated TLS, HTTPS, or QUIC; + * peer's keys are [pinned in Chrome](https://cs.chromium.org/chromium/src/net/http/transport_security_state_static.json?sq=package:chromium&g=0); and + * peer is operated by a business entity that Chrome should trust (e.g. an [Alphabet](https://abc.xyz) company). + +### Normalization + +You can 'defang' a potentially-malicious input by transforming it into a +_normalized_ or minimal form. For example, consider the PNG image format, which +is complex and whose [C implementation has suffered from memory corruption bugs +in the +past](https://www.cvedetails.com/vulnerability-list/vendor_id-7294/Libpng.html). +An attacker would craft a malicious PNG that could trigger such a bug. But if +you transform the image into a another format (in another, in a low-privilege +process, of course), the malicious nature of the PNG 'should' be eliminated and +then safe for reading at a higher privilege level. + +### Safe Languages + +Where possible, it's great to use a memory-safe language. Of the currently +approved set of implementation languages in Chromium, the most likely candidates +are Java (on Android only) and JavaScript (although we don't currently use it in +high-privilege processes like the browser). One can imagine Swift on iOS or +Kotlin on Android, too, although they are not currently used in Chromium. + +## Existing Code That Violates The Rule + +Obviously, we still have a lot of code that violates this rule. For example, +until very recently, all of the network stack was in the browser process, and +its whole job is to parse complex and untrustworthy inputs (TLS, QUIC, HTTP, +DNS, X.509, and more). This dangerous combination is why bugs in that area of +code are often of Critical severity: + + * [OOB Write in `QuicStreamSequencerBuffer::OnStreamData`](https://bugs.chromium.org/p/chromium/issues/detail?id=778505) + * [Stack Buffer Overflow in `QuicClientPromisedInfo::OnPromiseHeaders`](https://bugs.chromium.org/p/chromium/issues/detail?id=777728) + +We now have the network stack in its own dedicated process, and have begun the +process of reducing that process' privilege. ([macOS +bug](https://bugs.chromium.org/p/chromium/issues/detail?id=915910), [Windows +bug](https://bugs.chromium.org/p/chromium/issues/detail?id=841001))
diff --git a/extensions/common/csp_validator.cc b/extensions/common/csp_validator.cc index 270f829..1b29ff2 100644 --- a/extensions/common/csp_validator.cc +++ b/extensions/common/csp_validator.cc
@@ -9,6 +9,7 @@ #include <algorithm> #include <initializer_list> #include <iterator> +#include <utility> #include <vector> #include "base/bind.h" @@ -202,14 +203,11 @@ return false; } -InstallWarning CSPInstallWarning(const std::string& csp_warning) { - return InstallWarning(csp_warning, manifest_keys::kContentSecurityPolicy); -} - std::string GetSecureDirectiveValues( int options, const std::string& directive_name, const std::vector<base::StringPiece>& directive_values, + const std::string& manifest_key, std::vector<InstallWarning>* warnings) { std::vector<base::StringPiece> sane_csp_parts{directive_name}; for (base::StringPiece source_literal : directive_values) { @@ -248,9 +246,11 @@ if (is_secure_csp_token) { sane_csp_parts.push_back(source_literal); } else if (warnings) { - warnings->push_back(CSPInstallWarning(ErrorUtils::FormatErrorMessage( - manifest_errors::kInvalidCSPInsecureValue, source_literal.as_string(), - directive_name))); + warnings->push_back(InstallWarning( + ErrorUtils::FormatErrorMessage( + manifest_errors::kInvalidCSPInsecureValue, manifest_key, + source_literal.as_string(), directive_name), + manifest_key)); } } // End of CSP directive that was started at the beginning of this method. If @@ -269,6 +269,7 @@ std::string GetAppSandboxSecureDirectiveValues( const std::string& directive_name, const std::vector<base::StringPiece>& directive_values, + const std::string& manifest_key, std::vector<InstallWarning>* warnings) { std::vector<std::string> sane_csp_parts{directive_name}; bool seen_self_or_none = false; @@ -283,9 +284,11 @@ seen_self_or_none |= source_lower == "'none'" || source_lower == "'self'"; sane_csp_parts.push_back(source_lower); } else if (warnings) { - warnings->push_back(CSPInstallWarning(ErrorUtils::FormatErrorMessage( - manifest_errors::kInvalidCSPInsecureValue, source_literal.as_string(), - directive_name))); + warnings->push_back(InstallWarning( + ErrorUtils::FormatErrorMessage( + manifest_errors::kInvalidCSPInsecureValue, manifest_key, + source_literal.as_string(), directive_name), + manifest_key)); } } @@ -332,6 +335,7 @@ using SecureDirectiveValueFunction = base::Callback<std::string( const std::string& directive_name, const std::vector<base::StringPiece>& directive_values, + const std::string& manifest_key, std::vector<InstallWarning>* warnings)>; // Represents a token in CSP string. @@ -347,6 +351,7 @@ // directive values are secured by |secure_function|. bool MatchAndUpdateStatus(DirectiveStatus* status, const SecureDirectiveValueFunction& secure_function, + const std::string& manifest_key, std::vector<InstallWarning>* warnings) { if (!status->Matches(directive_.directive_name)) return false; @@ -355,7 +360,7 @@ status->set_seen_in_policy(); secure_value_ = secure_function.Run( - directive_.directive_name, directive_.directive_values, + directive_.directive_name, directive_.directive_values, manifest_key, // Don't show any errors for duplicate CSP directives, because it will // be ignored by the CSP parser // (http://www.w3.org/TR/CSP2/#policy-parsing). Therefore, set warnings @@ -387,9 +392,11 @@ // will use default secure values (via GetDefaultCSPValue). class CSPEnforcer { public: - CSPEnforcer(bool show_missing_csp_warnings, + CSPEnforcer(std::string manifest_key, + bool show_missing_csp_warnings, const SecureDirectiveValueFunction& secure_function) - : show_missing_csp_warnings_(show_missing_csp_warnings), + : manifest_key_(std::move(manifest_key)), + show_missing_csp_warnings_(show_missing_csp_warnings), secure_function_(secure_function) {} virtual ~CSPEnforcer() {} @@ -407,6 +414,7 @@ std::vector<std::unique_ptr<DirectiveStatus>> secure_directives_; private: + const std::string manifest_key_; const bool show_missing_csp_warnings_; const SecureDirectiveValueFunction secure_function_; @@ -428,14 +436,15 @@ bool matches_enforcing_directive = false; for (const std::unique_ptr<DirectiveStatus>& status : secure_directives_) { if (csp_directive_token.MatchAndUpdateStatus( - status.get(), secure_function_, warnings)) { + status.get(), secure_function_, manifest_key_, warnings)) { matches_enforcing_directive = true; break; } } if (!matches_enforcing_directive) { - csp_directive_token.MatchAndUpdateStatus( - &default_src_status, secure_function_, &default_src_csp_warnings); + csp_directive_token.MatchAndUpdateStatus(&default_src_status, + secure_function_, manifest_key_, + &default_src_csp_warnings); } enforced_csp_parts.push_back(csp_directive_token.ToString()); @@ -464,8 +473,11 @@ enforced_csp_parts.push_back(GetDefaultCSPValue(*status)); if (warnings && show_missing_csp_warnings_) { - warnings->push_back(CSPInstallWarning(ErrorUtils::FormatErrorMessage( - manifest_errors::kInvalidCSPMissingSecureSrc, status->name()))); + warnings->push_back( + InstallWarning(ErrorUtils::FormatErrorMessage( + manifest_errors::kInvalidCSPMissingSecureSrc, + manifest_key_, status->name()), + manifest_key_)); } } } @@ -475,8 +487,12 @@ class ExtensionCSPEnforcer : public CSPEnforcer { public: - ExtensionCSPEnforcer(bool allow_insecure_object_src, int options) - : CSPEnforcer(true, base::Bind(&GetSecureDirectiveValues, options)) { + ExtensionCSPEnforcer(std::string manifest_key, + bool allow_insecure_object_src, + int options) + : CSPEnforcer(std::move(manifest_key), + true, + base::Bind(&GetSecureDirectiveValues, options)) { secure_directives_.emplace_back(new DirectiveStatus({kScriptSrc})); if (!allow_insecure_object_src) secure_directives_.emplace_back(new DirectiveStatus({kObjectSrc})); @@ -496,8 +512,10 @@ class AppSandboxPageCSPEnforcer : public CSPEnforcer { public: - AppSandboxPageCSPEnforcer() - : CSPEnforcer(false, base::Bind(&GetAppSandboxSecureDirectiveValues)) { + AppSandboxPageCSPEnforcer(std::string manifest_key) + : CSPEnforcer(std::move(manifest_key), + false, + base::Bind(&GetAppSandboxSecureDirectiveValues)) { secure_directives_.emplace_back( new DirectiveStatus({kChildSrc, kFrameSrc})); secure_directives_.emplace_back(new DirectiveStatus({kScriptSrc})); @@ -574,6 +592,7 @@ std::string SanitizeContentSecurityPolicy( const std::string& policy, + std::string manifest_key, int options, std::vector<InstallWarning>* warnings) { CSPParser csp_parser(policy); @@ -581,14 +600,16 @@ bool allow_insecure_object_src = AllowedToHaveInsecureObjectSrc(options, csp_parser.directives()); - ExtensionCSPEnforcer csp_enforcer(allow_insecure_object_src, options); + ExtensionCSPEnforcer csp_enforcer(std::move(manifest_key), + allow_insecure_object_src, options); return csp_enforcer.Enforce(csp_parser.directives(), warnings); } std::string GetEffectiveSandoxedPageCSP(const std::string& policy, + std::string manifest_key, std::vector<InstallWarning>* warnings) { CSPParser csp_parser(policy); - AppSandboxPageCSPEnforcer csp_enforcer; + AppSandboxPageCSPEnforcer csp_enforcer(std::move(manifest_key)); return csp_enforcer.Enforce(csp_parser.directives(), warnings); }
diff --git a/extensions/common/csp_validator.h b/extensions/common/csp_validator.h index 6bda17b..dbf9b37 100644 --- a/extensions/common/csp_validator.h +++ b/extensions/common/csp_validator.h
@@ -105,6 +105,7 @@ // Returns the sanitized policy. std::string SanitizeContentSecurityPolicy( const std::string& policy, + std::string manifest_key, int options, std::vector<InstallWarning>* warnings); @@ -118,6 +119,7 @@ // If |warnings| is not nullptr, any validation errors are appended to // |warnings|. std::string GetEffectiveSandoxedPageCSP(const std::string& policy, + std::string manifest_key, std::vector<InstallWarning>* warnings); // Checks whether the given |policy| enforces a unique origin sandbox as
diff --git a/extensions/common/csp_validator_unittest.cc b/extensions/common/csp_validator_unittest.cc index 3599efb..744f48cd 100644 --- a/extensions/common/csp_validator_unittest.cc +++ b/extensions/common/csp_validator_unittest.cc
@@ -26,15 +26,21 @@ namespace { -std::string InsecureValueWarning(const std::string& directive, - const std::string& value) { +std::string InsecureValueWarning( + const std::string& directive, + const std::string& value, + const std::string& manifest_key = + extensions::manifest_keys::kContentSecurityPolicy) { return ErrorUtils::FormatErrorMessage( - extensions::manifest_errors::kInvalidCSPInsecureValue, value, directive); + extensions::manifest_errors::kInvalidCSPInsecureValue, manifest_key, + value, directive); } -std::string MissingSecureSrcWarning(const std::string& directive) { +std::string MissingSecureSrcWarning(const std::string& manifest_key, + const std::string& directive) { return ErrorUtils::FormatErrorMessage( - extensions::manifest_errors::kInvalidCSPMissingSecureSrc, directive); + extensions::manifest_errors::kInvalidCSPMissingSecureSrc, manifest_key, + directive); } bool CSPEquals(const std::string& csp1, const std::string& csp2) { @@ -54,13 +60,16 @@ SanitizedCSPResult SanitizeCSP(const std::string& policy, int options) { SanitizedCSPResult result; - result.csp = SanitizeContentSecurityPolicy(policy, options, &result.warnings); + result.csp = SanitizeContentSecurityPolicy( + policy, extensions::manifest_keys::kContentSecurityPolicy, options, + &result.warnings); return result; } SanitizedCSPResult SanitizeSandboxPageCSP(const std::string& policy) { SanitizedCSPResult result; - result.csp = GetEffectiveSandoxedPageCSP(policy, &result.warnings); + result.csp = GetEffectiveSandoxedPageCSP( + policy, extensions::manifest_keys::kSandboxedPagesCSP, &result.warnings); return result; } @@ -146,62 +155,67 @@ } TEST(ExtensionCSPValidator, IsSecure) { - EXPECT_TRUE(CheckCSP(SanitizeCSP(std::string(), OPTIONS_ALLOW_UNSAFE_EVAL), - "script-src 'self'; object-src 'self';", - MissingSecureSrcWarning("script-src"), - MissingSecureSrcWarning("object-src"))); - EXPECT_TRUE(CheckCSP(SanitizeCSP( - "img-src https://google.com", OPTIONS_ALLOW_UNSAFE_EVAL), - "img-src https://google.com; script-src 'self'; object-src 'self';", - MissingSecureSrcWarning("script-src"), - MissingSecureSrcWarning("object-src"))); - EXPECT_TRUE(CheckCSP(SanitizeCSP( - "script-src a b", OPTIONS_ALLOW_UNSAFE_EVAL), - "script-src; object-src 'self';", - InsecureValueWarning("script-src", "a"), - InsecureValueWarning("script-src", "b"), - MissingSecureSrcWarning("object-src"))); + auto missing_secure_src_warning = [](const std::string& directive) { + return MissingSecureSrcWarning( + extensions::manifest_keys::kContentSecurityPolicy, directive); + }; - EXPECT_TRUE(CheckCSP(SanitizeCSP( - "default-src *", OPTIONS_ALLOW_UNSAFE_EVAL), - "default-src;", - InsecureValueWarning("default-src", "*"))); + EXPECT_TRUE(CheckCSP(SanitizeCSP(std::string(), OPTIONS_ALLOW_UNSAFE_EVAL), + "script-src 'self'; object-src 'self';", + missing_secure_src_warning("script-src"), + missing_secure_src_warning("object-src"))); + EXPECT_TRUE(CheckCSP( + SanitizeCSP("img-src https://google.com", OPTIONS_ALLOW_UNSAFE_EVAL), + "img-src https://google.com; script-src 'self'; object-src 'self';", + missing_secure_src_warning("script-src"), + missing_secure_src_warning("object-src"))); + EXPECT_TRUE(CheckCSP(SanitizeCSP("script-src a b", OPTIONS_ALLOW_UNSAFE_EVAL), + "script-src; object-src 'self';", + InsecureValueWarning("script-src", "a"), + InsecureValueWarning("script-src", "b"), + missing_secure_src_warning("object-src"))); + + EXPECT_TRUE(CheckCSP(SanitizeCSP("default-src *", OPTIONS_ALLOW_UNSAFE_EVAL), + "default-src;", + InsecureValueWarning("default-src", "*"))); EXPECT_TRUE(CheckCSP(SanitizeCSP( "default-src 'self';", OPTIONS_ALLOW_UNSAFE_EVAL))); EXPECT_TRUE(CheckCSP(SanitizeCSP( "default-src 'none';", OPTIONS_ALLOW_UNSAFE_EVAL))); - EXPECT_TRUE(CheckCSP(SanitizeCSP( - "default-src 'self' ftp://google.com", OPTIONS_ALLOW_UNSAFE_EVAL), - "default-src 'self';", - InsecureValueWarning("default-src", "ftp://google.com"))); + EXPECT_TRUE( + CheckCSP(SanitizeCSP("default-src 'self' ftp://google.com", + OPTIONS_ALLOW_UNSAFE_EVAL), + "default-src 'self';", + InsecureValueWarning("default-src", "ftp://google.com"))); EXPECT_TRUE(CheckCSP(SanitizeCSP( "default-src 'self' https://google.com;", OPTIONS_ALLOW_UNSAFE_EVAL))); - EXPECT_TRUE(CheckCSP(SanitizeCSP( - "default-src *; default-src 'self'", OPTIONS_ALLOW_UNSAFE_EVAL), - "default-src; default-src 'self';", - InsecureValueWarning("default-src", "*"))); + EXPECT_TRUE(CheckCSP(SanitizeCSP("default-src *; default-src 'self'", + OPTIONS_ALLOW_UNSAFE_EVAL), + "default-src; default-src 'self';", + InsecureValueWarning("default-src", "*"))); EXPECT_TRUE(CheckCSP(SanitizeCSP( "default-src 'self'; default-src *;", OPTIONS_ALLOW_UNSAFE_EVAL), "default-src 'self'; default-src;")); - EXPECT_TRUE(CheckCSP(SanitizeCSP( - "default-src 'self'; default-src *; script-src *; script-src 'self'", - OPTIONS_ALLOW_UNSAFE_EVAL), + EXPECT_TRUE(CheckCSP( + SanitizeCSP( + "default-src 'self'; default-src *; script-src *; script-src 'self'", + OPTIONS_ALLOW_UNSAFE_EVAL), "default-src 'self'; default-src; script-src; script-src 'self';", InsecureValueWarning("script-src", "*"))); EXPECT_TRUE(CheckCSP(SanitizeCSP( "default-src 'self'; default-src *; script-src 'self'; script-src *;", OPTIONS_ALLOW_UNSAFE_EVAL), "default-src 'self'; default-src; script-src 'self'; script-src;")); - EXPECT_TRUE(CheckCSP(SanitizeCSP( - "default-src *; script-src 'self'", OPTIONS_ALLOW_UNSAFE_EVAL), - "default-src; script-src 'self';", - InsecureValueWarning("default-src", "*"))); - EXPECT_TRUE(CheckCSP(SanitizeCSP( - "default-src *; script-src 'self'; img-src 'self'", - OPTIONS_ALLOW_UNSAFE_EVAL), - "default-src; script-src 'self'; img-src 'self';", - InsecureValueWarning("default-src", "*"))); + EXPECT_TRUE(CheckCSP(SanitizeCSP("default-src *; script-src 'self'", + OPTIONS_ALLOW_UNSAFE_EVAL), + "default-src; script-src 'self';", + InsecureValueWarning("default-src", "*"))); + EXPECT_TRUE( + CheckCSP(SanitizeCSP("default-src *; script-src 'self'; img-src 'self'", + OPTIONS_ALLOW_UNSAFE_EVAL), + "default-src; script-src 'self'; img-src 'self';", + InsecureValueWarning("default-src", "*"))); EXPECT_TRUE(CheckCSP(SanitizeCSP( "default-src *; script-src 'self'; object-src 'self';", OPTIONS_ALLOW_UNSAFE_EVAL), @@ -211,22 +225,21 @@ EXPECT_TRUE(CheckCSP(SanitizeCSP( "default-src 'unsafe-eval';", OPTIONS_ALLOW_UNSAFE_EVAL))); - EXPECT_TRUE(CheckCSP(SanitizeCSP( - "default-src 'unsafe-eval'", OPTIONS_NONE), - "default-src;", - InsecureValueWarning("default-src", "'unsafe-eval'"))); - EXPECT_TRUE(CheckCSP(SanitizeCSP( - "default-src 'unsafe-inline'", OPTIONS_ALLOW_UNSAFE_EVAL), - "default-src;", - InsecureValueWarning("default-src", "'unsafe-inline'"))); - EXPECT_TRUE(CheckCSP(SanitizeCSP( - "default-src 'unsafe-inline' 'none'", OPTIONS_ALLOW_UNSAFE_EVAL), - "default-src 'none';", - InsecureValueWarning("default-src", "'unsafe-inline'"))); - EXPECT_TRUE(CheckCSP(SanitizeCSP( - "default-src 'self' http://google.com", OPTIONS_ALLOW_UNSAFE_EVAL), - "default-src 'self';", - InsecureValueWarning("default-src", "http://google.com"))); + EXPECT_TRUE(CheckCSP(SanitizeCSP("default-src 'unsafe-eval'", OPTIONS_NONE), + "default-src;", + InsecureValueWarning("default-src", "'unsafe-eval'"))); + EXPECT_TRUE(CheckCSP( + SanitizeCSP("default-src 'unsafe-inline'", OPTIONS_ALLOW_UNSAFE_EVAL), + "default-src;", InsecureValueWarning("default-src", "'unsafe-inline'"))); + EXPECT_TRUE(CheckCSP(SanitizeCSP("default-src 'unsafe-inline' 'none'", + OPTIONS_ALLOW_UNSAFE_EVAL), + "default-src 'none';", + InsecureValueWarning("default-src", "'unsafe-inline'"))); + EXPECT_TRUE( + CheckCSP(SanitizeCSP("default-src 'self' http://google.com", + OPTIONS_ALLOW_UNSAFE_EVAL), + "default-src 'self';", + InsecureValueWarning("default-src", "http://google.com"))); EXPECT_TRUE(CheckCSP(SanitizeCSP( "default-src 'self' https://google.com;", OPTIONS_ALLOW_UNSAFE_EVAL))); EXPECT_TRUE(CheckCSP(SanitizeCSP( @@ -237,84 +250,83 @@ EXPECT_TRUE(CheckCSP(SanitizeCSP( "default-src 'self' chrome-extension-resource://aabbcc;", OPTIONS_ALLOW_UNSAFE_EVAL))); - EXPECT_TRUE(CheckCSP(SanitizeCSP( - "default-src 'self' https:", OPTIONS_ALLOW_UNSAFE_EVAL), - "default-src 'self';", - InsecureValueWarning("default-src", "https:"))); - EXPECT_TRUE(CheckCSP(SanitizeCSP( - "default-src 'self' http:", OPTIONS_ALLOW_UNSAFE_EVAL), - "default-src 'self';", - InsecureValueWarning("default-src", "http:"))); - EXPECT_TRUE(CheckCSP(SanitizeCSP( - "default-src 'self' google.com", OPTIONS_ALLOW_UNSAFE_EVAL), + EXPECT_TRUE(CheckCSP( + SanitizeCSP("default-src 'self' https:", OPTIONS_ALLOW_UNSAFE_EVAL), + "default-src 'self';", InsecureValueWarning("default-src", "https:"))); + EXPECT_TRUE(CheckCSP( + SanitizeCSP("default-src 'self' http:", OPTIONS_ALLOW_UNSAFE_EVAL), + "default-src 'self';", InsecureValueWarning("default-src", "http:"))); + EXPECT_TRUE(CheckCSP( + SanitizeCSP("default-src 'self' google.com", OPTIONS_ALLOW_UNSAFE_EVAL), "default-src 'self';", InsecureValueWarning("default-src", "google.com"))); - EXPECT_TRUE(CheckCSP(SanitizeCSP( - "default-src 'self' *", OPTIONS_ALLOW_UNSAFE_EVAL), - "default-src 'self';", - InsecureValueWarning("default-src", "*"))); - EXPECT_TRUE(CheckCSP(SanitizeCSP( - "default-src 'self' *:*", OPTIONS_ALLOW_UNSAFE_EVAL), - "default-src 'self';", - InsecureValueWarning("default-src", "*:*"))); - EXPECT_TRUE(CheckCSP(SanitizeCSP( - "default-src 'self' *:*/", OPTIONS_ALLOW_UNSAFE_EVAL), - "default-src 'self';", - InsecureValueWarning("default-src", "*:*/"))); - EXPECT_TRUE(CheckCSP(SanitizeCSP( - "default-src 'self' *:*/path", OPTIONS_ALLOW_UNSAFE_EVAL), - "default-src 'self';", - InsecureValueWarning("default-src", "*:*/path"))); - EXPECT_TRUE(CheckCSP(SanitizeCSP( - "default-src 'self' https://", OPTIONS_ALLOW_UNSAFE_EVAL), - "default-src 'self';", - InsecureValueWarning("default-src", "https://"))); - EXPECT_TRUE(CheckCSP(SanitizeCSP( - "default-src 'self' https://*:*", OPTIONS_ALLOW_UNSAFE_EVAL), + EXPECT_TRUE(CheckCSP( + SanitizeCSP("default-src 'self' *", OPTIONS_ALLOW_UNSAFE_EVAL), + "default-src 'self';", InsecureValueWarning("default-src", "*"))); + EXPECT_TRUE(CheckCSP( + SanitizeCSP("default-src 'self' *:*", OPTIONS_ALLOW_UNSAFE_EVAL), + "default-src 'self';", InsecureValueWarning("default-src", "*:*"))); + EXPECT_TRUE(CheckCSP( + SanitizeCSP("default-src 'self' *:*/", OPTIONS_ALLOW_UNSAFE_EVAL), + "default-src 'self';", InsecureValueWarning("default-src", "*:*/"))); + EXPECT_TRUE(CheckCSP( + SanitizeCSP("default-src 'self' *:*/path", OPTIONS_ALLOW_UNSAFE_EVAL), + "default-src 'self';", InsecureValueWarning("default-src", "*:*/path"))); + EXPECT_TRUE(CheckCSP( + SanitizeCSP("default-src 'self' https://", OPTIONS_ALLOW_UNSAFE_EVAL), + "default-src 'self';", InsecureValueWarning("default-src", "https://"))); + EXPECT_TRUE(CheckCSP( + SanitizeCSP("default-src 'self' https://*:*", OPTIONS_ALLOW_UNSAFE_EVAL), "default-src 'self';", InsecureValueWarning("default-src", "https://*:*"))); - EXPECT_TRUE(CheckCSP(SanitizeCSP( - "default-src 'self' https://*:*/", OPTIONS_ALLOW_UNSAFE_EVAL), + EXPECT_TRUE(CheckCSP( + SanitizeCSP("default-src 'self' https://*:*/", OPTIONS_ALLOW_UNSAFE_EVAL), "default-src 'self';", InsecureValueWarning("default-src", "https://*:*/"))); - EXPECT_TRUE(CheckCSP(SanitizeCSP( - "default-src 'self' https://*:*/path", OPTIONS_ALLOW_UNSAFE_EVAL), - "default-src 'self';", - InsecureValueWarning("default-src", "https://*:*/path"))); - EXPECT_TRUE(CheckCSP(SanitizeCSP( - "default-src 'self' https://*.com", OPTIONS_ALLOW_UNSAFE_EVAL), - "default-src 'self';", - InsecureValueWarning("default-src", "https://*.com"))); - EXPECT_TRUE(CheckCSP(SanitizeCSP( - "default-src 'self' https://*.*.google.com/", OPTIONS_ALLOW_UNSAFE_EVAL), - "default-src 'self';", - InsecureValueWarning("default-src", "https://*.*.google.com/"))); - EXPECT_TRUE(CheckCSP(SanitizeCSP( - "default-src 'self' https://*.*.google.com:*/", OPTIONS_ALLOW_UNSAFE_EVAL), + EXPECT_TRUE( + CheckCSP(SanitizeCSP("default-src 'self' https://*:*/path", + OPTIONS_ALLOW_UNSAFE_EVAL), + "default-src 'self';", + InsecureValueWarning("default-src", "https://*:*/path"))); + EXPECT_TRUE(CheckCSP(SanitizeCSP("default-src 'self' https://*.com", + OPTIONS_ALLOW_UNSAFE_EVAL), + "default-src 'self';", + InsecureValueWarning("default-src", "https://*.com"))); + EXPECT_TRUE( + CheckCSP(SanitizeCSP("default-src 'self' https://*.*.google.com/", + OPTIONS_ALLOW_UNSAFE_EVAL), + "default-src 'self';", + InsecureValueWarning("default-src", "https://*.*.google.com/"))); + EXPECT_TRUE(CheckCSP( + SanitizeCSP("default-src 'self' https://*.*.google.com:*/", + OPTIONS_ALLOW_UNSAFE_EVAL), "default-src 'self';", InsecureValueWarning("default-src", "https://*.*.google.com:*/"))); - EXPECT_TRUE(CheckCSP(SanitizeCSP( - "default-src 'self' https://www.*.google.com/", OPTIONS_ALLOW_UNSAFE_EVAL), + EXPECT_TRUE(CheckCSP( + SanitizeCSP("default-src 'self' https://www.*.google.com/", + OPTIONS_ALLOW_UNSAFE_EVAL), "default-src 'self';", InsecureValueWarning("default-src", "https://www.*.google.com/"))); - EXPECT_TRUE(CheckCSP(SanitizeCSP( - "default-src 'self' https://www.*.google.com:*/", - OPTIONS_ALLOW_UNSAFE_EVAL), + EXPECT_TRUE(CheckCSP( + SanitizeCSP("default-src 'self' https://www.*.google.com:*/", + OPTIONS_ALLOW_UNSAFE_EVAL), "default-src 'self';", InsecureValueWarning("default-src", "https://www.*.google.com:*/"))); - EXPECT_TRUE(CheckCSP(SanitizeCSP( - "default-src 'self' chrome://*", OPTIONS_ALLOW_UNSAFE_EVAL), + EXPECT_TRUE(CheckCSP( + SanitizeCSP("default-src 'self' chrome://*", OPTIONS_ALLOW_UNSAFE_EVAL), "default-src 'self';", InsecureValueWarning("default-src", "chrome://*"))); - EXPECT_TRUE(CheckCSP(SanitizeCSP( - "default-src 'self' chrome-extension://*", OPTIONS_ALLOW_UNSAFE_EVAL), - "default-src 'self';", - InsecureValueWarning("default-src", "chrome-extension://*"))); - EXPECT_TRUE(CheckCSP(SanitizeCSP( - "default-src 'self' chrome-extension://", OPTIONS_ALLOW_UNSAFE_EVAL), - "default-src 'self';", - InsecureValueWarning("default-src", "chrome-extension://"))); + EXPECT_TRUE( + CheckCSP(SanitizeCSP("default-src 'self' chrome-extension://*", + OPTIONS_ALLOW_UNSAFE_EVAL), + "default-src 'self';", + InsecureValueWarning("default-src", "chrome-extension://*"))); + EXPECT_TRUE( + CheckCSP(SanitizeCSP("default-src 'self' chrome-extension://", + OPTIONS_ALLOW_UNSAFE_EVAL), + "default-src 'self';", + InsecureValueWarning("default-src", "chrome-extension://"))); EXPECT_TRUE(CheckCSP(SanitizeCSP( "default-src 'self' https://*.google.com;", OPTIONS_ALLOW_UNSAFE_EVAL))); @@ -342,28 +354,30 @@ "default-src 'self' http://127.0.0.1:9999;", OPTIONS_ALLOW_UNSAFE_EVAL))); EXPECT_TRUE(CheckCSP(SanitizeCSP( "default-src 'self' http://localhost:8888;", OPTIONS_ALLOW_UNSAFE_EVAL))); - EXPECT_TRUE(CheckCSP(SanitizeCSP( - "default-src 'self' http://127.0.0.1.example.com", - OPTIONS_ALLOW_UNSAFE_EVAL), + EXPECT_TRUE(CheckCSP( + SanitizeCSP("default-src 'self' http://127.0.0.1.example.com", + OPTIONS_ALLOW_UNSAFE_EVAL), "default-src 'self';", InsecureValueWarning("default-src", "http://127.0.0.1.example.com"))); - EXPECT_TRUE(CheckCSP(SanitizeCSP( - "default-src 'self' http://localhost.example.com", - OPTIONS_ALLOW_UNSAFE_EVAL), + EXPECT_TRUE(CheckCSP( + SanitizeCSP("default-src 'self' http://localhost.example.com", + OPTIONS_ALLOW_UNSAFE_EVAL), "default-src 'self';", InsecureValueWarning("default-src", "http://localhost.example.com"))); EXPECT_TRUE(CheckCSP(SanitizeCSP( "default-src 'self' blob:;", OPTIONS_ALLOW_UNSAFE_EVAL))); - EXPECT_TRUE(CheckCSP(SanitizeCSP( - "default-src 'self' blob:http://example.com/XXX", - OPTIONS_ALLOW_UNSAFE_EVAL), "default-src 'self';", + EXPECT_TRUE(CheckCSP( + SanitizeCSP("default-src 'self' blob:http://example.com/XXX", + OPTIONS_ALLOW_UNSAFE_EVAL), + "default-src 'self';", InsecureValueWarning("default-src", "blob:http://example.com/XXX"))); EXPECT_TRUE(CheckCSP(SanitizeCSP( "default-src 'self' filesystem:;", OPTIONS_ALLOW_UNSAFE_EVAL))); - EXPECT_TRUE(CheckCSP(SanitizeCSP( - "default-src 'self' filesystem:http://example.com/XX", - OPTIONS_ALLOW_UNSAFE_EVAL), "default-src 'self';", + EXPECT_TRUE(CheckCSP( + SanitizeCSP("default-src 'self' filesystem:http://example.com/XX", + OPTIONS_ALLOW_UNSAFE_EVAL), + "default-src 'self';", InsecureValueWarning("default-src", "filesystem:http://example.com/XX"))); EXPECT_TRUE(CheckCSP(SanitizeCSP( @@ -373,28 +387,27 @@ "default-src 'self' https://x.googleapis.com;", OPTIONS_ALLOW_UNSAFE_EVAL))); - EXPECT_TRUE(CheckCSP(SanitizeCSP( - "script-src 'self'; object-src *", OPTIONS_NONE), - "script-src 'self'; object-src;", - InsecureValueWarning("object-src", "*"))); - EXPECT_TRUE(CheckCSP(SanitizeCSP( - "script-src 'self'; object-src *", OPTIONS_ALLOW_INSECURE_OBJECT_SRC), - "script-src 'self'; object-src;", - InsecureValueWarning("object-src", "*"))); + EXPECT_TRUE( + CheckCSP(SanitizeCSP("script-src 'self'; object-src *", OPTIONS_NONE), + "script-src 'self'; object-src;", + InsecureValueWarning("object-src", "*"))); + EXPECT_TRUE(CheckCSP(SanitizeCSP("script-src 'self'; object-src *", + OPTIONS_ALLOW_INSECURE_OBJECT_SRC), + "script-src 'self'; object-src;", + InsecureValueWarning("object-src", "*"))); EXPECT_TRUE(CheckCSP(SanitizeCSP( "script-src 'self'; object-src *; plugin-types application/pdf;", OPTIONS_ALLOW_INSECURE_OBJECT_SRC))); - EXPECT_TRUE(CheckCSP(SanitizeCSP( - "script-src 'self'; object-src *; " - "plugin-types application/x-shockwave-flash", - OPTIONS_ALLOW_INSECURE_OBJECT_SRC), - "script-src 'self'; object-src; " - "plugin-types application/x-shockwave-flash;", - InsecureValueWarning("object-src", "*"))); - EXPECT_TRUE(CheckCSP(SanitizeCSP( - "script-src 'self'; object-src *; " - "plugin-types application/x-shockwave-flash application/pdf;", - OPTIONS_ALLOW_INSECURE_OBJECT_SRC), + EXPECT_TRUE(CheckCSP(SanitizeCSP("script-src 'self'; object-src *; " + "plugin-types application/x-shockwave-flash", + OPTIONS_ALLOW_INSECURE_OBJECT_SRC), + "script-src 'self'; object-src; " + "plugin-types application/x-shockwave-flash;", + InsecureValueWarning("object-src", "*"))); + EXPECT_TRUE(CheckCSP( + SanitizeCSP("script-src 'self'; object-src *; " + "plugin-types application/x-shockwave-flash application/pdf;", + OPTIONS_ALLOW_INSECURE_OBJECT_SRC), "script-src 'self'; object-src; " "plugin-types application/x-shockwave-flash application/pdf;", InsecureValueWarning("object-src", "*"))); @@ -410,9 +423,9 @@ "script-src 'self'; object-src http://*.example.com; " "plugin-types application/pdf;", OPTIONS_ALLOW_INSECURE_OBJECT_SRC))); - EXPECT_TRUE(CheckCSP(SanitizeCSP( - "script-src *; object-src *; plugin-types application/pdf;", - OPTIONS_ALLOW_INSECURE_OBJECT_SRC), + EXPECT_TRUE(CheckCSP( + SanitizeCSP("script-src *; object-src *; plugin-types application/pdf;", + OPTIONS_ALLOW_INSECURE_OBJECT_SRC), "script-src; object-src *; plugin-types application/pdf;", InsecureValueWarning("script-src", "*"))); @@ -426,16 +439,20 @@ OPTIONS_NONE))); // Reject non-standard algorithms, even if they are still supported by Blink. - EXPECT_TRUE(CheckCSP(SanitizeCSP( - "default-src; script-src 'sha1-eYyYGmKWdhpUewohaXk9o8IaLSw=';", - OPTIONS_NONE), "default-src; script-src;", + EXPECT_TRUE(CheckCSP( + SanitizeCSP( + "default-src; script-src 'sha1-eYyYGmKWdhpUewohaXk9o8IaLSw=';", + OPTIONS_NONE), + "default-src; script-src;", InsecureValueWarning("script-src", "'sha1-eYyYGmKWdhpUewohaXk9o8IaLSw='"))); - EXPECT_TRUE(CheckCSP(SanitizeCSP( - "default-src; script-src 'sha256-hndjYvzUzy2Ykuad81Cwsl1FOXX/qYs/aDVyUyNZ" - "wBw= sha256-qznLcsROx4GACP2dm0UCKCzCG+HiZ1guq6ZZDob/Tng=';", - OPTIONS_NONE), "default-src; script-src;", + EXPECT_TRUE(CheckCSP( + SanitizeCSP("default-src; script-src " + "'sha256-hndjYvzUzy2Ykuad81Cwsl1FOXX/qYs/aDVyUyNZ" + "wBw= sha256-qznLcsROx4GACP2dm0UCKCzCG+HiZ1guq6ZZDob/Tng=';", + OPTIONS_NONE), + "default-src; script-src;", InsecureValueWarning( "script-src", "'sha256-hndjYvzUzy2Ykuad81Cwsl1FOXX/qYs/aDVyUyNZwBw="), InsecureValueWarning( @@ -478,17 +495,23 @@ } TEST(ExtensionCSPValidator, EffectiveSandboxedPageCSP) { + auto insecure_value_warning = [](const std::string& directive, + const std::string& value) { + return InsecureValueWarning(directive, value, + extensions::manifest_keys::kSandboxedPagesCSP); + }; + EXPECT_TRUE(CheckCSP( SanitizeSandboxPageCSP(""), "child-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval';")); EXPECT_TRUE(CheckCSP( SanitizeSandboxPageCSP("child-src http://www.google.com"), "child-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval';", - InsecureValueWarning("child-src", "http://www.google.com"))); + insecure_value_warning("child-src", "http://www.google.com"))); EXPECT_TRUE(CheckCSP( SanitizeSandboxPageCSP("child-src *"), "child-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval';", - InsecureValueWarning("child-src", "*"))); + insecure_value_warning("child-src", "*"))); EXPECT_TRUE(CheckCSP( SanitizeSandboxPageCSP("child-src 'none'"), "child-src 'none'; script-src 'self' 'unsafe-inline' 'unsafe-eval';")); @@ -501,7 +524,7 @@ SanitizeSandboxPageCSP( "script-src 'none'; frame-src 'self' http://www.google.com;"), "frame-src 'self'; script-src 'none';", - InsecureValueWarning("frame-src", "http://www.google.com"))); + insecure_value_warning("frame-src", "http://www.google.com"))); // script-src will add 'unsafe-inline' and 'unsafe-eval' only if script-src is // not specified. @@ -521,20 +544,20 @@ SanitizeSandboxPageCSP( "script-src 'none'; frame-src 'self' http://www.google.com;"), "frame-src 'self'; script-src 'none';", - InsecureValueWarning("frame-src", "http://www.google.com"))); + insecure_value_warning("frame-src", "http://www.google.com"))); EXPECT_TRUE(CheckCSP( SanitizeSandboxPageCSP( "script-src 'none'; child-src 'self' http://www.google.com;"), "child-src 'self'; script-src 'none';", - InsecureValueWarning("child-src", "http://www.google.com"))); + insecure_value_warning("child-src", "http://www.google.com"))); // Multiple insecure values. EXPECT_TRUE(CheckCSP( SanitizeSandboxPageCSP( "script-src 'none'; child-src http://bar.com 'self' http://foo.com;"), "child-src 'self'; script-src 'none';", - InsecureValueWarning("child-src", "http://bar.com"), - InsecureValueWarning("child-src", "http://foo.com"))); + insecure_value_warning("child-src", "http://bar.com"), + insecure_value_warning("child-src", "http://foo.com"))); } namespace extensions {
diff --git a/extensions/common/manifest_constants.cc b/extensions/common/manifest_constants.cc index b44d3e1..7b198aae 100644 --- a/extensions/common/manifest_constants.cc +++ b/extensions/common/manifest_constants.cc
@@ -358,10 +358,10 @@ const char kInvalidContentScriptsList[] = "Invalid value for 'content_scripts'."; const char kInvalidCSPInsecureValue[] = - "Ignored insecure CSP value \"*\" in directive '*'."; + "'*': Ignored insecure CSP value \"*\" in directive '*'."; const char kInvalidCSPMissingSecureSrc[] = - "CSP directive '*' must be specified (either explicitly, or implicitly via" - " 'default-src') and must whitelist only secure resources."; + "'*': CSP directive '*' must be specified (either explicitly, or " + "implicitly via 'default-src') and must whitelist only secure resources."; const char kInvalidCss[] = "Invalid value for 'content_scripts[*].css[*]'."; const char kInvalidCssList[] =
diff --git a/extensions/common/manifest_constants.h b/extensions/common/manifest_constants.h index a9615a3..761075a 100644 --- a/extensions/common/manifest_constants.h +++ b/extensions/common/manifest_constants.h
@@ -470,7 +470,6 @@ extern const char kInvalidWebURL[]; extern const char kInvalidWebURLs[]; extern const char kInvalidZipHash[]; -extern const char kInsecureContentSecurityPolicy[]; extern const char kKeyIsDeprecatedWithReplacement[]; extern const char kLauncherPagePageRequired[]; extern const char kLaunchPathAndExtentAreExclusive[];
diff --git a/extensions/common/manifest_handlers/csp_info.cc b/extensions/common/manifest_handlers/csp_info.cc index 39b6ac9c..1a55589 100644 --- a/extensions/common/manifest_handlers/csp_info.cc +++ b/extensions/common/manifest_handlers/csp_info.cc
@@ -189,7 +189,7 @@ base::StringPiece manifest_key, const base::Value* content_security_policy) { if (!content_security_policy) - return SetDefaultExtensionPagesCSP(extension); + return SetDefaultExtensionPagesCSP(extension, manifest_key); if (!content_security_policy->is_string()) { *error = GetInvalidManifestKeyError(manifest_key); @@ -208,7 +208,8 @@ // extension provided csp value and raising install warnings, see if we want // to raise errors and prevent the extension from loading. std::string sanitized_content_security_policy = SanitizeContentSecurityPolicy( - content_security_policy_str, GetValidatorOptions(extension), &warnings); + content_security_policy_str, manifest_key.as_string(), + GetValidatorOptions(extension), &warnings); extension->AddInstallWarnings(std::move(warnings)); extension->SetManifestData( @@ -241,13 +242,15 @@ std::vector<InstallWarning> warnings; std::string effective_sandbox_csp = - csp_validator::GetEffectiveSandoxedPageCSP(sandbox_csp_str, &warnings); + csp_validator::GetEffectiveSandoxedPageCSP( + sandbox_csp_str, manifest_key.as_string(), &warnings); SetSandboxCSP(extension, std::move(effective_sandbox_csp)); extension->AddInstallWarnings(std::move(warnings)); return true; } -bool CSPHandler::SetDefaultExtensionPagesCSP(Extension* extension) { +bool CSPHandler::SetDefaultExtensionPagesCSP(Extension* extension, + base::StringPiece manifest_key) { // TODO(abarth): Should we continue to let extensions override the // default Content-Security-Policy? const char* content_security_policy = @@ -255,10 +258,10 @@ ? kDefaultPlatformAppContentSecurityPolicy : kDefaultContentSecurityPolicy; - DCHECK_EQ( - content_security_policy, - SanitizeContentSecurityPolicy(content_security_policy, - GetValidatorOptions(extension), nullptr)); + DCHECK_EQ(content_security_policy, + SanitizeContentSecurityPolicy( + content_security_policy, manifest_key.as_string(), + GetValidatorOptions(extension), nullptr)); extension->SetManifestData( keys::kContentSecurityPolicy, std::make_unique<CSPInfo>(content_security_policy));
diff --git a/extensions/common/manifest_handlers/csp_info.h b/extensions/common/manifest_handlers/csp_info.h index b4c219f..8b4e7d1 100644 --- a/extensions/common/manifest_handlers/csp_info.h +++ b/extensions/common/manifest_handlers/csp_info.h
@@ -76,7 +76,8 @@ const base::Value* sandbox_csp); // Sets the default CSP value for the extension. - bool SetDefaultExtensionPagesCSP(Extension* extension); + bool SetDefaultExtensionPagesCSP(Extension* extension, + base::StringPiece manifest_key); // Helper to set the sandbox content security policy manifest data. void SetSandboxCSP(Extension* extension, std::string sandbox_csp);
diff --git a/webrunner/BUILD.gn b/fuchsia/BUILD.gn similarity index 96% rename from webrunner/BUILD.gn rename to fuchsia/BUILD.gn index 8f973d0..7c93edd 100644 --- a/webrunner/BUILD.gn +++ b/fuchsia/BUILD.gn
@@ -215,9 +215,9 @@ source_set("mem_buffer_common") { sources = [ + "common/fuchsia_export.h", "common/mem_buffer_util.cc", "common/mem_buffer_util.h", - "common/webrunner_export.h", ] deps = [ "//base", @@ -297,6 +297,10 @@ binary = ":service_exe" package_name_override = "chromium" sandbox_policy = "service/sandbox_policy" + excluded_files = [ + "lib/libswiftshader_libEGL.so", + "lib/libswiftshader_libGLESv2.so", + ] } executable("service_exe") { @@ -587,7 +591,7 @@ "license_file", rebase_path(_license_path, root_build_dir), "--gn-target", - "//webrunner:webrunner_pkg", + "//fuchsia:webrunner_pkg", "--gn-out-dir", ".", ] @@ -611,11 +615,11 @@ # Puts copies of files at the top level of the CIPD archive's structure. copy("restaged_packages") { sources = [ - "$root_gen_dir/webrunner/application_config_manager/application_config_manager.far", - "$root_gen_dir/webrunner/cast_runner/cast_runner.far", - "$root_gen_dir/webrunner/chromium/chromium.far", - "$root_gen_dir/webrunner/net_http/http/http.far", - "$root_gen_dir/webrunner/web_runner/web_runner.far", + "$root_gen_dir/fuchsia/application_config_manager/application_config_manager.far", + "$root_gen_dir/fuchsia/cast_runner/cast_runner.far", + "$root_gen_dir/fuchsia/chromium/chromium.far", + "$root_gen_dir/fuchsia/net_http/http/http.far", + "$root_gen_dir/fuchsia/web_runner/web_runner.far", ] outputs = [ "$_artifact_root/{{source_file_part}}",
diff --git a/webrunner/DEPS b/fuchsia/DEPS similarity index 100% rename from webrunner/DEPS rename to fuchsia/DEPS
diff --git a/webrunner/OWNERS b/fuchsia/OWNERS similarity index 100% rename from webrunner/OWNERS rename to fuchsia/OWNERS
diff --git a/webrunner/README.md b/fuchsia/README.md similarity index 100% rename from webrunner/README.md rename to fuchsia/README.md
diff --git a/webrunner/app/cast/application_config_manager/application_config_manager.cc b/fuchsia/app/cast/application_config_manager/application_config_manager.cc similarity index 91% rename from webrunner/app/cast/application_config_manager/application_config_manager.cc rename to fuchsia/app/cast/application_config_manager/application_config_manager.cc index f0aaada..62c0bb1c 100644 --- a/webrunner/app/cast/application_config_manager/application_config_manager.cc +++ b/fuchsia/app/cast/application_config_manager/application_config_manager.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "webrunner/app/cast/application_config_manager/application_config_manager.h" +#include "fuchsia/app/cast/application_config_manager/application_config_manager.h" #include "base/logging.h"
diff --git a/webrunner/app/cast/application_config_manager/application_config_manager.h b/fuchsia/app/cast/application_config_manager/application_config_manager.h similarity index 72% rename from webrunner/app/cast/application_config_manager/application_config_manager.h rename to fuchsia/app/cast/application_config_manager/application_config_manager.h index e760190..64b8232e 100644 --- a/webrunner/app/cast/application_config_manager/application_config_manager.h +++ b/fuchsia/app/cast/application_config_manager/application_config_manager.h
@@ -2,10 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef WEBRUNNER_APP_CAST_APPLICATION_CONFIG_MANAGER_APPLICATION_CONFIG_MANAGER_H_ -#define WEBRUNNER_APP_CAST_APPLICATION_CONFIG_MANAGER_APPLICATION_CONFIG_MANAGER_H_ +#ifndef FUCHSIA_APP_CAST_APPLICATION_CONFIG_MANAGER_APPLICATION_CONFIG_MANAGER_H_ +#define FUCHSIA_APP_CAST_APPLICATION_CONFIG_MANAGER_APPLICATION_CONFIG_MANAGER_H_ -#include <webrunner/fidl/chromium/cast/cpp/fidl.h> +#include <fuchsia/fidl/chromium/cast/cpp/fidl.h> #include "base/macros.h" @@ -28,4 +28,4 @@ } // namespace castrunner -#endif // WEBRUNNER_APP_CAST_APPLICATION_CONFIG_MANAGER_APPLICATION_CONFIG_MANAGER_H_ +#endif // FUCHSIA_APP_CAST_APPLICATION_CONFIG_MANAGER_APPLICATION_CONFIG_MANAGER_H_
diff --git a/webrunner/app/cast/application_config_manager/application_config_manager_unittest.cc b/fuchsia/app/cast/application_config_manager/application_config_manager_unittest.cc similarity index 96% rename from webrunner/app/cast/application_config_manager/application_config_manager_unittest.cc rename to fuchsia/app/cast/application_config_manager/application_config_manager_unittest.cc index 06a5e69d..0d7fbda 100644 --- a/webrunner/app/cast/application_config_manager/application_config_manager_unittest.cc +++ b/fuchsia/app/cast/application_config_manager/application_config_manager_unittest.cc
@@ -7,8 +7,8 @@ #include "base/run_loop.h" #include "base/test/scoped_task_environment.h" +#include "fuchsia/app/cast/application_config_manager/application_config_manager.h" #include "testing/gtest/include/gtest/gtest.h" -#include "webrunner/app/cast/application_config_manager/application_config_manager.h" namespace castrunner {
diff --git a/webrunner/app/cast/application_config_manager/main.cc b/fuchsia/app/cast/application_config_manager/main.cc similarity index 92% rename from webrunner/app/cast/application_config_manager/main.cc rename to fuchsia/app/cast/application_config_manager/main.cc index f752ad49..0e53daae2 100644 --- a/webrunner/app/cast/application_config_manager/main.cc +++ b/fuchsia/app/cast/application_config_manager/main.cc
@@ -7,7 +7,7 @@ #include "base/fuchsia/service_directory.h" #include "base/message_loop/message_loop.h" #include "base/run_loop.h" -#include "webrunner/app/cast/application_config_manager/application_config_manager.h" +#include "fuchsia/app/cast/application_config_manager/application_config_manager.h" int main(int argc, char** argv) { base::MessageLoopForIO message_loop;
diff --git a/webrunner/app/cast/application_config_manager/sandbox_policy b/fuchsia/app/cast/application_config_manager/sandbox_policy similarity index 100% rename from webrunner/app/cast/application_config_manager/sandbox_policy rename to fuchsia/app/cast/application_config_manager/sandbox_policy
diff --git a/webrunner/app/cast/application_config_manager/test/fake_application_config_manager.cc b/fuchsia/app/cast/application_config_manager/test/fake_application_config_manager.cc similarity index 92% rename from webrunner/app/cast/application_config_manager/test/fake_application_config_manager.cc rename to fuchsia/app/cast/application_config_manager/test/fake_application_config_manager.cc index 75a2b50..1f5fddce 100644 --- a/webrunner/app/cast/application_config_manager/test/fake_application_config_manager.cc +++ b/fuchsia/app/cast/application_config_manager/test/fake_application_config_manager.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "webrunner/app/cast/application_config_manager/test/fake_application_config_manager.h" +#include "fuchsia/app/cast/application_config_manager/test/fake_application_config_manager.h" #include "base/logging.h"
diff --git a/webrunner/app/cast/application_config_manager/test/fake_application_config_manager.h b/fuchsia/app/cast/application_config_manager/test/fake_application_config_manager.h similarity index 74% rename from webrunner/app/cast/application_config_manager/test/fake_application_config_manager.h rename to fuchsia/app/cast/application_config_manager/test/fake_application_config_manager.h index 6d275e7..7a490b4 100644 --- a/webrunner/app/cast/application_config_manager/test/fake_application_config_manager.h +++ b/fuchsia/app/cast/application_config_manager/test/fake_application_config_manager.h
@@ -2,10 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef WEBRUNNER_APP_CAST_APPLICATION_CONFIG_MANAGER_TEST_FAKE_APPLICATION_CONFIG_MANAGER_H_ -#define WEBRUNNER_APP_CAST_APPLICATION_CONFIG_MANAGER_TEST_FAKE_APPLICATION_CONFIG_MANAGER_H_ +#ifndef FUCHSIA_APP_CAST_APPLICATION_CONFIG_MANAGER_TEST_FAKE_APPLICATION_CONFIG_MANAGER_H_ +#define FUCHSIA_APP_CAST_APPLICATION_CONFIG_MANAGER_TEST_FAKE_APPLICATION_CONFIG_MANAGER_H_ -#include <webrunner/fidl/chromium/cast/cpp/fidl.h> +#include <fuchsia/fidl/chromium/cast/cpp/fidl.h> #include "base/macros.h" #include "net/test/embedded_test_server/embedded_test_server.h" @@ -36,4 +36,4 @@ } // namespace test } // namespace castrunner -#endif // WEBRUNNER_APP_CAST_APPLICATION_CONFIG_MANAGER_TEST_FAKE_APPLICATION_CONFIG_MANAGER_H_ +#endif // FUCHSIA_APP_CAST_APPLICATION_CONFIG_MANAGER_TEST_FAKE_APPLICATION_CONFIG_MANAGER_H_
diff --git a/webrunner/app/cast/bindings/cast_channel.cc b/fuchsia/app/cast/bindings/cast_channel.cc similarity index 92% rename from webrunner/app/cast/bindings/cast_channel.cc rename to fuchsia/app/cast/bindings/cast_channel.cc index e5a6af1..99980cb 100644 --- a/webrunner/app/cast/bindings/cast_channel.cc +++ b/fuchsia/app/cast/bindings/cast_channel.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "webrunner/app/cast/bindings/cast_channel.h" +#include "fuchsia/app/cast/bindings/cast_channel.h" #include <lib/fit/function.h> #include <string> @@ -15,9 +15,9 @@ #include "base/macros.h" #include "base/path_service.h" #include "base/threading/thread_task_runner_handle.h" -#include "webrunner/common/mem_buffer_util.h" -#include "webrunner/common/named_message_port_connector.h" -#include "webrunner/fidl/chromium/web/cpp/fidl.h" +#include "fuchsia/common/mem_buffer_util.h" +#include "fuchsia/common/named_message_port_connector.h" +#include "fuchsia/fidl/chromium/web/cpp/fidl.h" namespace castrunner { @@ -43,7 +43,7 @@ base::FilePath assets_path; CHECK(base::PathService::Get(base::DIR_ASSETS, &assets_path)); fuchsia::mem::Buffer bindings_buf = webrunner::MemBufferFromFile(base::File( - assets_path.AppendASCII("webrunner/app/cast/bindings/cast_channel.js"), + assets_path.AppendASCII("fuchsia/app/cast/bindings/cast_channel.js"), base::File::FLAG_OPEN | base::File::FLAG_READ)); CHECK(bindings_buf.vmo);
diff --git a/webrunner/app/cast/bindings/cast_channel.h b/fuchsia/app/cast/bindings/cast_channel.h similarity index 84% rename from webrunner/app/cast/bindings/cast_channel.h rename to fuchsia/app/cast/bindings/cast_channel.h index 04bbd0f..f7bb683 100644 --- a/webrunner/app/cast/bindings/cast_channel.h +++ b/fuchsia/app/cast/bindings/cast_channel.h
@@ -2,17 +2,17 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef WEBRUNNER_APP_CAST_BINDINGS_CAST_CHANNEL_H_ -#define WEBRUNNER_APP_CAST_BINDINGS_CAST_CHANNEL_H_ +#ifndef FUCHSIA_APP_CAST_BINDINGS_CAST_CHANNEL_H_ +#define FUCHSIA_APP_CAST_BINDINGS_CAST_CHANNEL_H_ #include <string> #include "base/callback.h" #include "base/macros.h" #include "base/strings/string_piece.h" -#include "webrunner/common/webrunner_export.h" -#include "webrunner/fidl/chromium/cast/cpp/fidl.h" -#include "webrunner/fidl/chromium/web/cpp/fidl.h" +#include "fuchsia/common/fuchsia_export.h" +#include "fuchsia/fidl/chromium/cast/cpp/fidl.h" +#include "fuchsia/fidl/chromium/web/cpp/fidl.h" namespace webrunner { class NamedMessagePortConnector; @@ -23,7 +23,7 @@ // Handles the injection of cast.__platform__.channel bindings into pages' // scripting context, and establishes a bidirectional message pipe over // which the two communicate. -class WEBRUNNER_EXPORT CastChannelImpl : public chromium::cast::CastChannel { +class FUCHSIA_EXPORT CastChannelImpl : public chromium::cast::CastChannel { public: // Attaches CastChannel bindings and port to a |frame|. // |frame|: The frame to be provided with a CastChannel. @@ -68,4 +68,4 @@ } // namespace castrunner -#endif // WEBRUNNER_APP_CAST_BINDINGS_CAST_CHANNEL_H_ +#endif // FUCHSIA_APP_CAST_BINDINGS_CAST_CHANNEL_H_
diff --git a/webrunner/app/cast/bindings/cast_channel.js b/fuchsia/app/cast/bindings/cast_channel.js similarity index 100% rename from webrunner/app/cast/bindings/cast_channel.js rename to fuchsia/app/cast/bindings/cast_channel.js
diff --git a/webrunner/app/cast/bindings/cast_channel_browsertest.cc b/fuchsia/app/cast/bindings/cast_channel_browsertest.cc similarity index 94% rename from webrunner/app/cast/bindings/cast_channel_browsertest.cc rename to fuchsia/app/cast/bindings/cast_channel_browsertest.cc index eec926a..9c146bc 100644 --- a/webrunner/app/cast/bindings/cast_channel_browsertest.cc +++ b/fuchsia/app/cast/bindings/cast_channel_browsertest.cc
@@ -13,12 +13,12 @@ #include "base/threading/thread_restrictions.h" #include "testing/gtest/include/gtest/gtest.h" #include "url/url_constants.h" -#include "webrunner/app/cast/bindings/cast_channel.h" -#include "webrunner/common/mem_buffer_util.h" -#include "webrunner/common/named_message_port_connector.h" -#include "webrunner/common/test/test_common.h" -#include "webrunner/common/test/webrunner_browser_test.h" -#include "webrunner/test/promise.h" +#include "fuchsia/app/cast/bindings/cast_channel.h" +#include "fuchsia/common/mem_buffer_util.h" +#include "fuchsia/common/named_message_port_connector.h" +#include "fuchsia/common/test/test_common.h" +#include "fuchsia/common/test/webrunner_browser_test.h" +#include "fuchsia/test/promise.h" namespace castrunner { @@ -30,7 +30,7 @@ public chromium::web::NavigationEventObserver { public: CastChannelImplTest() : run_timeout_(TestTimeouts::action_timeout()) { - set_test_server_root(base::FilePath("webrunner/app/cast/test/data")); + set_test_server_root(base::FilePath("fuchsia/app/cast/test/data")); } ~CastChannelImplTest() override = default;
diff --git a/webrunner/app/cast/cast_runner.cc b/fuchsia/app/cast/cast_runner.cc similarity index 96% rename from webrunner/app/cast/cast_runner.cc rename to fuchsia/app/cast/cast_runner.cc index 86f32cf..8482ace 100644 --- a/webrunner/app/cast/cast_runner.cc +++ b/fuchsia/app/cast/cast_runner.cc
@@ -2,14 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "webrunner/app/cast/cast_runner.h" +#include "fuchsia/app/cast/cast_runner.h" #include <fuchsia/sys/cpp/fidl.h> #include <utility> #include "base/logging.h" +#include "fuchsia/app/common/web_component.h" #include "url/gurl.h" -#include "webrunner/app/common/web_component.h" namespace castrunner {
diff --git a/webrunner/app/cast/cast_runner.h b/fuchsia/app/cast/cast_runner.h similarity index 82% rename from webrunner/app/cast/cast_runner.h rename to fuchsia/app/cast/cast_runner.h index a90f710b00..47cbe92 100644 --- a/webrunner/app/cast/cast_runner.h +++ b/fuchsia/app/cast/cast_runner.h
@@ -2,14 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef WEBRUNNER_APP_CAST_CAST_RUNNER_H_ -#define WEBRUNNER_APP_CAST_CAST_RUNNER_H_ +#ifndef FUCHSIA_APP_CAST_CAST_RUNNER_H_ +#define FUCHSIA_APP_CAST_CAST_RUNNER_H_ #include "base/callback.h" #include "base/macros.h" -#include "webrunner/app/common/web_content_runner.h" -#include "webrunner/fidl/chromium/cast/cpp/fidl.h" -#include "webrunner/fidl/chromium/web/cpp/fidl.h" +#include "fuchsia/app/common/web_content_runner.h" +#include "fuchsia/fidl/chromium/cast/cpp/fidl.h" +#include "fuchsia/fidl/chromium/web/cpp/fidl.h" namespace castrunner { @@ -43,4 +43,4 @@ } // namespace castrunner -#endif // WEBRUNNER_APP_CAST_CAST_RUNNER_H_ +#endif // FUCHSIA_APP_CAST_CAST_RUNNER_H_
diff --git a/webrunner/app/cast/cast_runner_integration_test.cc b/fuchsia/app/cast/cast_runner_integration_test.cc similarity index 94% rename from webrunner/app/cast/cast_runner_integration_test.cc rename to fuchsia/app/cast/cast_runner_integration_test.cc index ec7cc35..80ebc6a 100644 --- a/webrunner/app/cast/cast_runner_integration_test.cc +++ b/fuchsia/app/cast/cast_runner_integration_test.cc
@@ -11,13 +11,13 @@ #include "base/message_loop/message_loop.h" #include "base/strings/stringprintf.h" #include "base/test/test_timeouts.h" +#include "fuchsia/app/cast/application_config_manager/test/fake_application_config_manager.h" +#include "fuchsia/app/cast/cast_runner.h" +#include "fuchsia/app/cast/test_common.h" +#include "fuchsia/app/common/web_component.h" +#include "fuchsia/app/common/web_content_runner.h" +#include "fuchsia/test/promise.h" #include "testing/gtest/include/gtest/gtest.h" -#include "webrunner/app/cast/application_config_manager/test/fake_application_config_manager.h" -#include "webrunner/app/cast/cast_runner.h" -#include "webrunner/app/cast/test_common.h" -#include "webrunner/app/common/web_component.h" -#include "webrunner/app/common/web_content_runner.h" -#include "webrunner/test/promise.h" namespace castrunner {
diff --git a/webrunner/app/cast/cast_runner_unittest.cc b/fuchsia/app/cast/cast_runner_unittest.cc similarity index 95% rename from webrunner/app/cast/cast_runner_unittest.cc rename to fuchsia/app/cast/cast_runner_unittest.cc index eb69b1f..c10ba17 100644 --- a/webrunner/app/cast/cast_runner_unittest.cc +++ b/fuchsia/app/cast/cast_runner_unittest.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "webrunner/app/cast/cast_runner.h" +#include "fuchsia/app/cast/cast_runner.h" #include <lib/fidl/cpp/binding.h> #include <lib/zx/channel.h> @@ -13,10 +13,10 @@ #include "base/fuchsia/service_directory.h" #include "base/message_loop/message_loop.h" #include "base/strings/stringprintf.h" +#include "fuchsia/app/cast/application_config_manager/test/fake_application_config_manager.h" +#include "fuchsia/app/cast/test_common.h" +#include "fuchsia/test/fake_context.h" #include "testing/gtest/include/gtest/gtest.h" -#include "webrunner/app/cast/application_config_manager/test/fake_application_config_manager.h" -#include "webrunner/app/cast/test_common.h" -#include "webrunner/test/fake_context.h" namespace castrunner {
diff --git a/webrunner/app/cast/main.cc b/fuchsia/app/cast/main.cc similarity index 94% rename from webrunner/app/cast/main.cc rename to fuchsia/app/cast/main.cc index 14844f2..73ff569 100644 --- a/webrunner/app/cast/main.cc +++ b/fuchsia/app/cast/main.cc
@@ -6,7 +6,7 @@ #include "base/fuchsia/service_directory.h" #include "base/message_loop/message_loop.h" #include "base/run_loop.h" -#include "webrunner/app/cast/cast_runner.h" +#include "fuchsia/app/cast/cast_runner.h" int main(int argc, char** argv) { base::MessageLoopForIO message_loop;
diff --git a/webrunner/app/cast/sandbox_policy b/fuchsia/app/cast/sandbox_policy similarity index 100% rename from webrunner/app/cast/sandbox_policy rename to fuchsia/app/cast/sandbox_policy
diff --git a/webrunner/app/cast/test/data/cast_channel.html b/fuchsia/app/cast/test/data/cast_channel.html similarity index 100% rename from webrunner/app/cast/test/data/cast_channel.html rename to fuchsia/app/cast/test/data/cast_channel.html
diff --git a/webrunner/app/cast/test/data/cast_channel_reconnect.html b/fuchsia/app/cast/test/data/cast_channel_reconnect.html similarity index 100% rename from webrunner/app/cast/test/data/cast_channel_reconnect.html rename to fuchsia/app/cast/test/data/cast_channel_reconnect.html
diff --git a/webrunner/app/cast/test_common.cc b/fuchsia/app/cast/test_common.cc similarity index 96% rename from webrunner/app/cast/test_common.cc rename to fuchsia/app/cast/test_common.cc index c1f5f02..cf134bb 100644 --- a/webrunner/app/cast/test_common.cc +++ b/fuchsia/app/cast/test_common.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "webrunner/app/cast/test_common.h" +#include "fuchsia/app/cast/test_common.h" #include "base/fuchsia/fuchsia_logging.h"
diff --git a/webrunner/app/cast/test_common.h b/fuchsia/app/cast/test_common.h similarity index 83% rename from webrunner/app/cast/test_common.h rename to fuchsia/app/cast/test_common.h index daf93cd9..f60295e 100644 --- a/webrunner/app/cast/test_common.h +++ b/fuchsia/app/cast/test_common.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef WEBRUNNER_APP_CAST_TEST_COMMON_H_ -#define WEBRUNNER_APP_CAST_TEST_COMMON_H_ +#ifndef FUCHSIA_APP_CAST_TEST_COMMON_H_ +#define FUCHSIA_APP_CAST_TEST_COMMON_H_ #include <fuchsia/sys/cpp/fidl.h> @@ -21,4 +21,4 @@ } // namespace castrunner -#endif // WEBRUNNER_APP_CAST_TEST_COMMON_H_ \ No newline at end of file +#endif // FUCHSIA_APP_CAST_TEST_COMMON_H_ \ No newline at end of file
diff --git a/webrunner/app/common/web_component.cc b/fuchsia/app/common/web_component.cc similarity index 92% rename from webrunner/app/common/web_component.cc rename to fuchsia/app/common/web_component.cc index 0c451c3cf..0c94772 100644 --- a/webrunner/app/common/web_component.cc +++ b/fuchsia/app/common/web_component.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "webrunner/app/common/web_component.h" +#include "fuchsia/app/common/web_component.h" #include <fuchsia/sys/cpp/fidl.h> #include <lib/fidl/cpp/binding_set.h> @@ -12,8 +12,8 @@ #include "base/fuchsia/scoped_service_binding.h" #include "base/fuchsia/service_directory.h" #include "base/logging.h" -#include "webrunner/app/common/web_content_runner.h" -#include "webrunner/fidl/chromium/web/cpp/fidl.h" +#include "fuchsia/app/common/web_content_runner.h" +#include "fuchsia/fidl/chromium/web/cpp/fidl.h" namespace webrunner { @@ -36,7 +36,9 @@ chromium::web::NavigationControllerPtr navigation_controller; component->frame()->GetNavigationController( navigation_controller.NewRequest()); - navigation_controller->LoadUrl(url.spec(), nullptr); + auto params = std::make_unique<chromium::web::LoadUrlParams>(); + params->was_activated = true; + navigation_controller->LoadUrl(url.spec(), std::move(params)); return component; }
diff --git a/webrunner/app/common/web_component.h b/fuchsia/app/common/web_component.h similarity index 94% rename from webrunner/app/common/web_component.h rename to fuchsia/app/common/web_component.h index b53681c..be0ae57 100644 --- a/webrunner/app/common/web_component.h +++ b/fuchsia/app/common/web_component.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef WEBRUNNER_APP_COMMON_WEB_COMPONENT_H_ -#define WEBRUNNER_APP_COMMON_WEB_COMPONENT_H_ +#ifndef FUCHSIA_APP_COMMON_WEB_COMPONENT_H_ +#define FUCHSIA_APP_COMMON_WEB_COMPONENT_H_ #include <fuchsia/sys/cpp/fidl.h> #include <fuchsia/ui/app/cpp/fidl.h> @@ -17,8 +17,8 @@ #include "base/fuchsia/scoped_service_binding.h" #include "base/fuchsia/service_directory.h" #include "base/logging.h" +#include "fuchsia/fidl/chromium/web/cpp/fidl.h" #include "url/gurl.h" -#include "webrunner/fidl/chromium/web/cpp/fidl.h" namespace webrunner { @@ -111,4 +111,4 @@ } // namespace webrunner -#endif // WEBRUNNER_APP_COMMON_COMPONENT_CONTROLLER_IMPL_H_ +#endif // FUCHSIA_APP_COMMON_COMPONENT_CONTROLLER_IMPL_H_
diff --git a/webrunner/app/common/web_content_runner.cc b/fuchsia/app/common/web_content_runner.cc similarity index 95% rename from webrunner/app/common/web_content_runner.cc rename to fuchsia/app/common/web_content_runner.cc index 6e37d5f..3d78e56 100644 --- a/webrunner/app/common/web_content_runner.cc +++ b/fuchsia/app/common/web_content_runner.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "webrunner/app/common/web_content_runner.h" +#include "fuchsia/app/common/web_content_runner.h" #include <fuchsia/sys/cpp/fidl.h> #include <lib/fidl/cpp/binding_set.h> @@ -15,9 +15,9 @@ #include "base/fuchsia/scoped_service_binding.h" #include "base/fuchsia/service_directory.h" #include "base/logging.h" +#include "fuchsia/app/common/web_component.h" +#include "fuchsia/fidl/chromium/web/cpp/fidl.h" #include "url/gurl.h" -#include "webrunner/app/common/web_component.h" -#include "webrunner/fidl/chromium/web/cpp/fidl.h" namespace webrunner {
diff --git a/webrunner/app/common/web_content_runner.h b/fuchsia/app/common/web_content_runner.h similarity index 93% rename from webrunner/app/common/web_content_runner.h rename to fuchsia/app/common/web_content_runner.h index df1499d..50db91f 100644 --- a/webrunner/app/common/web_content_runner.h +++ b/fuchsia/app/common/web_content_runner.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef WEBRUNNER_APP_COMMON_WEB_CONTENT_RUNNER_H_ -#define WEBRUNNER_APP_COMMON_WEB_CONTENT_RUNNER_H_ +#ifndef FUCHSIA_APP_COMMON_WEB_CONTENT_RUNNER_H_ +#define FUCHSIA_APP_COMMON_WEB_CONTENT_RUNNER_H_ #include <fuchsia/sys/cpp/fidl.h> #include <memory> @@ -14,7 +14,7 @@ #include "base/fuchsia/scoped_service_binding.h" #include "base/fuchsia/service_directory.h" #include "base/macros.h" -#include "webrunner/fidl/chromium/web/cpp/fidl.h" +#include "fuchsia/fidl/chromium/web/cpp/fidl.h" namespace webrunner { @@ -82,4 +82,4 @@ } // namespace webrunner -#endif // WEBRUNNER_APP_COMMON_WEB_CONTENT_RUNNER_H_ +#endif // FUCHSIA_APP_COMMON_WEB_CONTENT_RUNNER_H_
diff --git a/webrunner/app/web/main.cc b/fuchsia/app/web/main.cc similarity index 92% rename from webrunner/app/web/main.cc rename to fuchsia/app/web/main.cc index 29ba321..b640ce0 100644 --- a/webrunner/app/web/main.cc +++ b/fuchsia/app/web/main.cc
@@ -5,7 +5,7 @@ #include "base/fuchsia/service_directory.h" #include "base/message_loop/message_loop.h" #include "base/run_loop.h" -#include "webrunner/app/common/web_content_runner.h" +#include "fuchsia/app/common/web_content_runner.h" int main(int argc, char** argv) { base::MessageLoopForIO message_loop;
diff --git a/webrunner/app/web/sandbox_policy b/fuchsia/app/web/sandbox_policy similarity index 100% rename from webrunner/app/web/sandbox_policy rename to fuchsia/app/web/sandbox_policy
diff --git a/webrunner/app/web/webrunner_smoke_test.cc b/fuchsia/app/web/webrunner_smoke_test.cc similarity index 100% rename from webrunner/app/web/webrunner_smoke_test.cc rename to fuchsia/app/web/webrunner_smoke_test.cc
diff --git a/webrunner/browser/DEPS b/fuchsia/browser/DEPS similarity index 100% rename from webrunner/browser/DEPS rename to fuchsia/browser/DEPS
diff --git a/webrunner/browser/context_impl.cc b/fuchsia/browser/context_impl.cc similarity index 95% rename from webrunner/browser/context_impl.cc rename to fuchsia/browser/context_impl.cc index c3b1ad8..d1f471ad 100644 --- a/webrunner/browser/context_impl.cc +++ b/fuchsia/browser/context_impl.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "webrunner/browser/context_impl.h" +#include "fuchsia/browser/context_impl.h" #include <lib/zx/object.h> #include <memory> @@ -10,7 +10,7 @@ #include "base/fuchsia/fuchsia_logging.h" #include "content/public/browser/web_contents.h" -#include "webrunner/browser/frame_impl.h" +#include "fuchsia/browser/frame_impl.h" namespace webrunner {
diff --git a/webrunner/browser/context_impl.h b/fuchsia/browser/context_impl.h similarity index 83% rename from webrunner/browser/context_impl.h rename to fuchsia/browser/context_impl.h index f46701f..cfa95da 100644 --- a/webrunner/browser/context_impl.h +++ b/fuchsia/browser/context_impl.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef WEBRUNNER_BROWSER_CONTEXT_IMPL_H_ -#define WEBRUNNER_BROWSER_CONTEXT_IMPL_H_ +#ifndef FUCHSIA_BROWSER_CONTEXT_IMPL_H_ +#define FUCHSIA_BROWSER_CONTEXT_IMPL_H_ #include <lib/fidl/cpp/binding_set.h> #include <memory> @@ -11,8 +11,8 @@ #include "base/containers/unique_ptr_adapters.h" #include "base/macros.h" -#include "webrunner/common/webrunner_export.h" -#include "webrunner/fidl/chromium/web/cpp/fidl.h" +#include "fuchsia/common/fuchsia_export.h" +#include "fuchsia/fidl/chromium/web/cpp/fidl.h" namespace content { class BrowserContext; @@ -22,10 +22,10 @@ class FrameImpl; -// Implementation of Context from //webrunner/fidl/context.fidl. +// Implementation of Context from //fuchsia/fidl/context.fidl. // Owns a BrowserContext instance and uses it to create new WebContents/Frames. // All created Frames are owned by this object. -class WEBRUNNER_EXPORT ContextImpl : public chromium::web::Context { +class FUCHSIA_EXPORT ContextImpl : public chromium::web::Context { public: // |browser_context| must outlive ContextImpl. explicit ContextImpl(content::BrowserContext* browser_context); @@ -66,4 +66,4 @@ } // namespace webrunner -#endif // WEBRUNNER_BROWSER_CONTEXT_IMPL_H_ +#endif // FUCHSIA_BROWSER_CONTEXT_IMPL_H_
diff --git a/webrunner/browser/context_impl_browsertest.cc b/fuchsia/browser/context_impl_browsertest.cc similarity index 97% rename from webrunner/browser/context_impl_browsertest.cc rename to fuchsia/browser/context_impl_browsertest.cc index 0b6d335ac..797be530 100644 --- a/webrunner/browser/context_impl_browsertest.cc +++ b/fuchsia/browser/context_impl_browsertest.cc
@@ -11,15 +11,15 @@ #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/storage_partition.h" +#include "fuchsia/common/test/test_common.h" +#include "fuchsia/common/test/webrunner_browser_test.h" +#include "fuchsia/service/common.h" #include "net/cookies/cookie_store.h" #include "net/url_request/url_request_context.h" #include "net/url_request/url_request_context_getter.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "url/url_constants.h" -#include "webrunner/common/test/test_common.h" -#include "webrunner/common/test/webrunner_browser_test.h" -#include "webrunner/service/common.h" namespace webrunner {
diff --git a/webrunner/browser/frame_impl.cc b/fuchsia/browser/frame_impl.cc similarity index 97% rename from webrunner/browser/frame_impl.cc rename to fuchsia/browser/frame_impl.cc index 2e26b4d..e6ca823 100644 --- a/webrunner/browser/frame_impl.cc +++ b/fuchsia/browser/frame_impl.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "webrunner/browser/frame_impl.h" +#include "fuchsia/browser/frame_impl.h" #include <zircon/syscalls.h> @@ -18,6 +18,10 @@ #include "content/public/browser/navigation_handle.h" #include "content/public/browser/web_contents.h" #include "content/public/common/renderer_preferences_util.h" +#include "content/public/common/was_activated_option.h" +#include "fuchsia/browser/context_impl.h" +#include "fuchsia/browser/message_port_impl.h" +#include "fuchsia/common/mem_buffer_util.h" #include "mojo/public/cpp/system/platform_handle.h" #include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h" #include "ui/aura/layout_manager.h" @@ -27,9 +31,6 @@ #include "ui/platform_window/platform_window_init_properties.h" #include "ui/wm/core/base_focus_rules.h" #include "url/gurl.h" -#include "webrunner/browser/context_impl.h" -#include "webrunner/browser/message_port_impl.h" -#include "webrunner/common/mem_buffer_util.h" namespace webrunner { @@ -299,6 +300,9 @@ params_converted.transition_type = ui::PageTransitionFromInt( ui::PAGE_TRANSITION_TYPED | ui::PAGE_TRANSITION_FROM_ADDRESS_BAR); + params_converted.was_activated = (params && params->was_activated) + ? content::WasActivatedOption::kYes + : content::WasActivatedOption::kNo; web_contents_->GetController().LoadURLWithParams(params_converted); }
diff --git a/webrunner/browser/frame_impl.h b/fuchsia/browser/frame_impl.h similarity index 94% rename from webrunner/browser/frame_impl.h rename to fuchsia/browser/frame_impl.h index 920e4e9..65faf0a 100644 --- a/webrunner/browser/frame_impl.h +++ b/fuchsia/browser/frame_impl.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef WEBRUNNER_BROWSER_FRAME_IMPL_H_ -#define WEBRUNNER_BROWSER_FRAME_IMPL_H_ +#ifndef FUCHSIA_BROWSER_FRAME_IMPL_H_ +#define FUCHSIA_BROWSER_FRAME_IMPL_H_ #include <lib/fidl/cpp/binding_set.h> #include <lib/zx/channel.h> @@ -17,11 +17,11 @@ #include "base/memory/platform_shared_memory_region.h" #include "content/public/browser/web_contents_delegate.h" #include "content/public/browser/web_contents_observer.h" +#include "fuchsia/common/on_load_script_injector.mojom.h" +#include "fuchsia/fidl/chromium/web/cpp/fidl.h" #include "ui/aura/window_tree_host.h" #include "ui/wm/core/focus_controller.h" #include "url/gurl.h" -#include "webrunner/common/on_load_script_injector.mojom.h" -#include "webrunner/fidl/chromium/web/cpp/fidl.h" namespace aura { class WindowTreeHost; @@ -35,7 +35,7 @@ class ContextImpl; -// Implementation of Frame from //webrunner/fidl/frame.fidl. +// Implementation of Frame from //fuchsia/fidl/frame.fidl. // Implements a Frame service, which is a wrapper for a WebContents instance. class FrameImpl : public chromium::web::Frame, public chromium::web::NavigationController, @@ -158,4 +158,4 @@ } // namespace webrunner -#endif // WEBRUNNER_BROWSER_FRAME_IMPL_H_ +#endif // FUCHSIA_BROWSER_FRAME_IMPL_H_
diff --git a/webrunner/browser/frame_impl_browsertest.cc b/fuchsia/browser/frame_impl_browsertest.cc similarity index 98% rename from webrunner/browser/frame_impl_browsertest.cc rename to fuchsia/browser/frame_impl_browsertest.cc index 874c366..f2bc371d 100644 --- a/webrunner/browser/frame_impl_browsertest.cc +++ b/fuchsia/browser/frame_impl_browsertest.cc
@@ -10,18 +10,18 @@ #include "content/public/browser/browser_context.h" #include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents_observer.h" +#include "fuchsia/browser/frame_impl.h" +#include "fuchsia/common/mem_buffer_util.h" +#include "fuchsia/common/test/test_common.h" +#include "fuchsia/common/test/webrunner_browser_test.h" +#include "fuchsia/service/common.h" +#include "fuchsia/test/promise.h" #include "net/test/embedded_test_server/embedded_test_server.h" #include "net/test/embedded_test_server/http_request.h" #include "net/url_request/url_request_context.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "url/url_constants.h" -#include "webrunner/browser/frame_impl.h" -#include "webrunner/common/mem_buffer_util.h" -#include "webrunner/common/test/test_common.h" -#include "webrunner/common/test/webrunner_browser_test.h" -#include "webrunner/service/common.h" -#include "webrunner/test/promise.h" namespace webrunner { @@ -42,7 +42,7 @@ const char kPage2Title[] = "title 2"; const char kDataUrl[] = "data:text/html;base64,PGI+SGVsbG8sIHdvcmxkLi4uPC9iPg=="; -const char kTestServerRoot[] = FILE_PATH_LITERAL("webrunner/browser/test/data"); +const char kTestServerRoot[] = FILE_PATH_LITERAL("fuchsia/browser/test/data"); MATCHER(IsSet, "Checks if an optional field is set.") { return !arg.is_null();
diff --git a/webrunner/browser/message_port_impl.cc b/fuchsia/browser/message_port_impl.cc similarity index 96% rename from webrunner/browser/message_port_impl.cc rename to fuchsia/browser/message_port_impl.cc index 7bd3fa3..d416022d 100644 --- a/webrunner/browser/message_port_impl.cc +++ b/fuchsia/browser/message_port_impl.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "webrunner/browser/message_port_impl.h" +#include "fuchsia/browser/message_port_impl.h" #include <stdint.h> @@ -14,13 +14,13 @@ #include "base/fuchsia/fuchsia_logging.h" #include "base/macros.h" +#include "fuchsia/common/mem_buffer_util.h" +#include "fuchsia/fidl/chromium/web/cpp/fidl.h" #include "mojo/public/cpp/system/message_pipe.h" #include "third_party/blink/public/common/messaging/message_port_channel.h" #include "third_party/blink/public/common/messaging/string_message_codec.h" #include "third_party/blink/public/common/messaging/transferable_message_struct_traits.h" #include "third_party/blink/public/mojom/messaging/transferable_message.mojom.h" -#include "webrunner/common/mem_buffer_util.h" -#include "webrunner/fidl/chromium/web/cpp/fidl.h" namespace webrunner { namespace { @@ -149,7 +149,7 @@ if (!pending_client_read_cb_ || message_queue_.empty()) return; - base::ResetAndReturn(&pending_client_read_cb_)( + base::ResetAndReturn (&pending_client_read_cb_)( std::move(message_queue_.front())); message_queue_.pop_front(); }
diff --git a/webrunner/browser/message_port_impl.h b/fuchsia/browser/message_port_impl.h similarity index 92% rename from webrunner/browser/message_port_impl.h rename to fuchsia/browser/message_port_impl.h index ddb7070..835d9fc 100644 --- a/webrunner/browser/message_port_impl.h +++ b/fuchsia/browser/message_port_impl.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef WEBRUNNER_BROWSER_MESSAGE_PORT_IMPL_H_ -#define WEBRUNNER_BROWSER_MESSAGE_PORT_IMPL_H_ +#ifndef FUCHSIA_BROWSER_MESSAGE_PORT_IMPL_H_ +#define FUCHSIA_BROWSER_MESSAGE_PORT_IMPL_H_ #include <lib/fidl/cpp/binding.h> #include <deque> @@ -11,10 +11,10 @@ #include "base/macros.h" #include "base/memory/weak_ptr.h" +#include "fuchsia/fidl/chromium/web/cpp/fidl.h" #include "mojo/public/cpp/bindings/connector.h" #include "mojo/public/cpp/bindings/message.h" #include "mojo/public/cpp/system/message_pipe.h" -#include "webrunner/fidl/chromium/web/cpp/fidl.h" namespace webrunner { @@ -72,4 +72,4 @@ } // namespace webrunner -#endif // WEBRUNNER_BROWSER_MESSAGE_PORT_IMPL_H_ +#endif // FUCHSIA_BROWSER_MESSAGE_PORT_IMPL_H_
diff --git a/webrunner/browser/test/data/dynamic_title.html b/fuchsia/browser/test/data/dynamic_title.html similarity index 100% rename from webrunner/browser/test/data/dynamic_title.html rename to fuchsia/browser/test/data/dynamic_title.html
diff --git a/webrunner/browser/test/data/message_port.html b/fuchsia/browser/test/data/message_port.html similarity index 100% rename from webrunner/browser/test/data/message_port.html rename to fuchsia/browser/test/data/message_port.html
diff --git a/webrunner/browser/test/data/title1.html b/fuchsia/browser/test/data/title1.html similarity index 100% rename from webrunner/browser/test/data/title1.html rename to fuchsia/browser/test/data/title1.html
diff --git a/webrunner/browser/test/data/title2.html b/fuchsia/browser/test/data/title2.html similarity index 100% rename from webrunner/browser/test/data/title2.html rename to fuchsia/browser/test/data/title2.html
diff --git a/webrunner/browser/test/data/window_post_message.html b/fuchsia/browser/test/data/window_post_message.html similarity index 100% rename from webrunner/browser/test/data/window_post_message.html rename to fuchsia/browser/test/data/window_post_message.html
diff --git a/webrunner/browser/webrunner_browser_context.cc b/fuchsia/browser/webrunner_browser_context.cc similarity index 95% rename from webrunner/browser/webrunner_browser_context.cc rename to fuchsia/browser/webrunner_browser_context.cc index 8eb7fd0..93775d2 100644 --- a/webrunner/browser/webrunner_browser_context.cc +++ b/fuchsia/browser/webrunner_browser_context.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "webrunner/browser/webrunner_browser_context.h" +#include "fuchsia/browser/webrunner_browser_context.h" #include <memory> #include <utility> @@ -16,11 +16,11 @@ #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/resource_context.h" +#include "fuchsia/browser/webrunner_net_log.h" +#include "fuchsia/browser/webrunner_url_request_context_getter.h" +#include "fuchsia/service/common.h" #include "net/url_request/url_request_context.h" #include "services/network/public/cpp/network_switches.h" -#include "webrunner/browser/webrunner_net_log.h" -#include "webrunner/browser/webrunner_url_request_context_getter.h" -#include "webrunner/service/common.h" namespace webrunner {
diff --git a/webrunner/browser/webrunner_browser_context.h b/fuchsia/browser/webrunner_browser_context.h similarity index 94% rename from webrunner/browser/webrunner_browser_context.h rename to fuchsia/browser/webrunner_browser_context.h index a4c672d..d1be10e 100644 --- a/webrunner/browser/webrunner_browser_context.h +++ b/fuchsia/browser/webrunner_browser_context.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef WEBRUNNER_BROWSER_WEBRUNNER_BROWSER_CONTEXT_H_ -#define WEBRUNNER_BROWSER_WEBRUNNER_BROWSER_CONTEXT_H_ +#ifndef FUCHSIA_BROWSER_WEBRUNNER_BROWSER_CONTEXT_H_ +#define FUCHSIA_BROWSER_WEBRUNNER_BROWSER_CONTEXT_H_ #include <memory> @@ -70,4 +70,4 @@ } // namespace webrunner -#endif // WEBRUNNER_BROWSER_WEBRUNNER_BROWSER_CONTEXT_H_ +#endif // FUCHSIA_BROWSER_WEBRUNNER_BROWSER_CONTEXT_H_
diff --git a/webrunner/browser/webrunner_browser_main.cc b/fuchsia/browser/webrunner_browser_main.cc similarity index 92% rename from webrunner/browser/webrunner_browser_main.cc rename to fuchsia/browser/webrunner_browser_main.cc index f4e183a1..aaca77df 100644 --- a/webrunner/browser/webrunner_browser_main.cc +++ b/fuchsia/browser/webrunner_browser_main.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "webrunner/browser/webrunner_browser_main.h" +#include "fuchsia/browser/webrunner_browser_main.h" #include <memory>
diff --git a/webrunner/browser/webrunner_browser_main.h b/fuchsia/browser/webrunner_browser_main.h similarity index 70% rename from webrunner/browser/webrunner_browser_main.h rename to fuchsia/browser/webrunner_browser_main.h index 37428a1..50a0858 100644 --- a/webrunner/browser/webrunner_browser_main.h +++ b/fuchsia/browser/webrunner_browser_main.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef WEBRUNNER_BROWSER_WEBRUNNER_BROWSER_MAIN_H_ -#define WEBRUNNER_BROWSER_WEBRUNNER_BROWSER_MAIN_H_ +#ifndef FUCHSIA_BROWSER_WEBRUNNER_BROWSER_MAIN_H_ +#define FUCHSIA_BROWSER_WEBRUNNER_BROWSER_MAIN_H_ #include <memory> @@ -15,4 +15,4 @@ int WebRunnerBrowserMain(const content::MainFunctionParams& parameters); } // namespace webrunner -#endif // WEBRUNNER_BROWSER_WEBRUNNER_BROWSER_MAIN_H_ +#endif // FUCHSIA_BROWSER_WEBRUNNER_BROWSER_MAIN_H_
diff --git a/webrunner/browser/webrunner_browser_main_parts.cc b/fuchsia/browser/webrunner_browser_main_parts.cc similarity index 91% rename from webrunner/browser/webrunner_browser_main_parts.cc rename to fuchsia/browser/webrunner_browser_main_parts.cc index b5402c3..75581a2 100644 --- a/webrunner/browser/webrunner_browser_main_parts.cc +++ b/fuchsia/browser/webrunner_browser_main_parts.cc
@@ -2,19 +2,19 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "webrunner/browser/webrunner_browser_main_parts.h" +#include "fuchsia/browser/webrunner_browser_main_parts.h" #include <utility> #include "base/command_line.h" #include "base/files/file_util.h" #include "content/public/browser/render_frame_host.h" +#include "fuchsia/browser/context_impl.h" +#include "fuchsia/browser/webrunner_browser_context.h" +#include "fuchsia/browser/webrunner_screen.h" +#include "fuchsia/service/common.h" #include "ui/aura/screen_ozone.h" #include "ui/ozone/public/ozone_platform.h" -#include "webrunner/browser/context_impl.h" -#include "webrunner/browser/webrunner_browser_context.h" -#include "webrunner/browser/webrunner_screen.h" -#include "webrunner/service/common.h" namespace webrunner {
diff --git a/webrunner/browser/webrunner_browser_main_parts.h b/fuchsia/browser/webrunner_browser_main_parts.h similarity index 82% rename from webrunner/browser/webrunner_browser_main_parts.h rename to fuchsia/browser/webrunner_browser_main_parts.h index 871c7e2..7c25109 100644 --- a/webrunner/browser/webrunner_browser_main_parts.h +++ b/fuchsia/browser/webrunner_browser_main_parts.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef WEBRUNNER_BROWSER_WEBRUNNER_BROWSER_MAIN_PARTS_H_ -#define WEBRUNNER_BROWSER_WEBRUNNER_BROWSER_MAIN_PARTS_H_ +#ifndef FUCHSIA_BROWSER_WEBRUNNER_BROWSER_MAIN_PARTS_H_ +#define FUCHSIA_BROWSER_WEBRUNNER_BROWSER_MAIN_PARTS_H_ #include <lib/fidl/cpp/binding.h> #include <memory> @@ -11,8 +11,8 @@ #include "base/macros.h" #include "base/optional.h" #include "content/public/browser/browser_main_parts.h" -#include "webrunner/browser/context_impl.h" -#include "webrunner/fidl/chromium/web/cpp/fidl.h" +#include "fuchsia/browser/context_impl.h" +#include "fuchsia/fidl/chromium/web/cpp/fidl.h" namespace display { class Screen; @@ -49,4 +49,4 @@ } // namespace webrunner -#endif // WEBRUNNER_BROWSER_WEBRUNNER_BROWSER_MAIN_PARTS_H_ +#endif // FUCHSIA_BROWSER_WEBRUNNER_BROWSER_MAIN_PARTS_H_
diff --git a/webrunner/browser/webrunner_content_browser_client.cc b/fuchsia/browser/webrunner_content_browser_client.cc similarity index 88% rename from webrunner/browser/webrunner_content_browser_client.cc rename to fuchsia/browser/webrunner_content_browser_client.cc index 7545784..d7cb950b 100644 --- a/webrunner/browser/webrunner_content_browser_client.cc +++ b/fuchsia/browser/webrunner_content_browser_client.cc
@@ -2,13 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "webrunner/browser/webrunner_content_browser_client.h" +#include "fuchsia/browser/webrunner_content_browser_client.h" #include <utility> #include "components/version_info/version_info.h" #include "content/public/common/user_agent.h" -#include "webrunner/browser/webrunner_browser_main_parts.h" +#include "fuchsia/browser/webrunner_browser_main_parts.h" namespace webrunner {
diff --git a/webrunner/browser/webrunner_content_browser_client.h b/fuchsia/browser/webrunner_content_browser_client.h similarity index 83% rename from webrunner/browser/webrunner_content_browser_client.h rename to fuchsia/browser/webrunner_content_browser_client.h index f489d29..84a1ddd 100644 --- a/webrunner/browser/webrunner_content_browser_client.h +++ b/fuchsia/browser/webrunner_content_browser_client.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef WEBRUNNER_BROWSER_WEBRUNNER_CONTENT_BROWSER_CLIENT_H_ -#define WEBRUNNER_BROWSER_WEBRUNNER_CONTENT_BROWSER_CLIENT_H_ +#ifndef FUCHSIA_BROWSER_WEBRUNNER_CONTENT_BROWSER_CLIENT_H_ +#define FUCHSIA_BROWSER_WEBRUNNER_CONTENT_BROWSER_CLIENT_H_ #include <lib/zx/channel.h> @@ -35,4 +35,4 @@ } // namespace webrunner -#endif // WEBRUNNER_BROWSER_WEBRUNNER_CONTENT_BROWSER_CLIENT_H_ +#endif // FUCHSIA_BROWSER_WEBRUNNER_CONTENT_BROWSER_CLIENT_H_
diff --git a/webrunner/browser/webrunner_net_log.cc b/fuchsia/browser/webrunner_net_log.cc similarity index 96% rename from webrunner/browser/webrunner_net_log.cc rename to fuchsia/browser/webrunner_net_log.cc index 7342b0a..ba60913 100644 --- a/webrunner/browser/webrunner_net_log.cc +++ b/fuchsia/browser/webrunner_net_log.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "webrunner/browser/webrunner_net_log.h" +#include "fuchsia/browser/webrunner_net_log.h" #include <string> #include <utility>
diff --git a/webrunner/browser/webrunner_net_log.h b/fuchsia/browser/webrunner_net_log.h similarity index 82% rename from webrunner/browser/webrunner_net_log.h rename to fuchsia/browser/webrunner_net_log.h index ae6ac92..00d736e 100644 --- a/webrunner/browser/webrunner_net_log.h +++ b/fuchsia/browser/webrunner_net_log.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef WEBRUNNER_BROWSER_WEBRUNNER_NET_LOG_H_ -#define WEBRUNNER_BROWSER_WEBRUNNER_NET_LOG_H_ +#ifndef FUCHSIA_BROWSER_WEBRUNNER_NET_LOG_H_ +#define FUCHSIA_BROWSER_WEBRUNNER_NET_LOG_H_ #include <memory> @@ -33,4 +33,4 @@ } // namespace webrunner -#endif // WEBRUNNER_BROWSER_WEBRUNNER_NET_LOG_H_ +#endif // FUCHSIA_BROWSER_WEBRUNNER_NET_LOG_H_
diff --git a/webrunner/browser/webrunner_screen.cc b/fuchsia/browser/webrunner_screen.cc similarity index 90% rename from webrunner/browser/webrunner_screen.cc rename to fuchsia/browser/webrunner_screen.cc index 0a3af0c..18fe947 100644 --- a/webrunner/browser/webrunner_screen.cc +++ b/fuchsia/browser/webrunner_screen.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "webrunner/browser/webrunner_screen.h" +#include "fuchsia/browser/webrunner_screen.h" #include "ui/display/display.h"
diff --git a/webrunner/browser/webrunner_screen.h b/fuchsia/browser/webrunner_screen.h similarity index 78% rename from webrunner/browser/webrunner_screen.h rename to fuchsia/browser/webrunner_screen.h index c028f2a..f44dd9e 100644 --- a/webrunner/browser/webrunner_screen.h +++ b/fuchsia/browser/webrunner_screen.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef WEBRUNNER_BROWSER_WEBRUNNER_SCREEN_H_ -#define WEBRUNNER_BROWSER_WEBRUNNER_SCREEN_H_ +#ifndef FUCHSIA_BROWSER_WEBRUNNER_SCREEN_H_ +#define FUCHSIA_BROWSER_WEBRUNNER_SCREEN_H_ #include "base/macros.h" @@ -23,4 +23,4 @@ } // namespace webrunner -#endif // WEBRUNNER_BROWSER_WEBRUNNER_SCREEN_H_ +#endif // FUCHSIA_BROWSER_WEBRUNNER_SCREEN_H_
diff --git a/webrunner/browser/webrunner_url_request_context_getter.cc b/fuchsia/browser/webrunner_url_request_context_getter.cc similarity index 97% rename from webrunner/browser/webrunner_url_request_context_getter.cc rename to fuchsia/browser/webrunner_url_request_context_getter.cc index d4ddc36..32d2b2d 100644 --- a/webrunner/browser/webrunner_url_request_context_getter.cc +++ b/fuchsia/browser/webrunner_url_request_context_getter.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "webrunner/browser/webrunner_url_request_context_getter.h" +#include "fuchsia/browser/webrunner_url_request_context_getter.h" #include <utility>
diff --git a/webrunner/browser/webrunner_url_request_context_getter.h b/fuchsia/browser/webrunner_url_request_context_getter.h similarity index 88% rename from webrunner/browser/webrunner_url_request_context_getter.h rename to fuchsia/browser/webrunner_url_request_context_getter.h index fc94e4c..d89ec0b 100644 --- a/webrunner/browser/webrunner_url_request_context_getter.h +++ b/fuchsia/browser/webrunner_url_request_context_getter.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef WEBRUNNER_BROWSER_WEBRUNNER_URL_REQUEST_CONTEXT_GETTER_H_ -#define WEBRUNNER_BROWSER_WEBRUNNER_URL_REQUEST_CONTEXT_GETTER_H_ +#ifndef FUCHSIA_BROWSER_WEBRUNNER_URL_REQUEST_CONTEXT_GETTER_H_ +#define FUCHSIA_BROWSER_WEBRUNNER_URL_REQUEST_CONTEXT_GETTER_H_ #include <memory> @@ -54,4 +54,4 @@ } // namespace webrunner -#endif // WEBRUNNER_BROWSER_WEBRUNNER_URL_REQUEST_CONTEXT_GETTER_H_ +#endif // FUCHSIA_BROWSER_WEBRUNNER_URL_REQUEST_CONTEXT_GETTER_H_
diff --git a/webrunner/cipd/build_id.template b/fuchsia/cipd/build_id.template similarity index 100% rename from webrunner/cipd/build_id.template rename to fuchsia/cipd/build_id.template
diff --git a/webrunner/cipd/castrunner.yaml b/fuchsia/cipd/castrunner.yaml similarity index 94% rename from webrunner/cipd/castrunner.yaml rename to fuchsia/cipd/castrunner.yaml index 41070b4..371fd451 100644 --- a/webrunner/cipd/castrunner.yaml +++ b/fuchsia/cipd/castrunner.yaml
@@ -15,7 +15,7 @@ # To create a CIPD package, run the following command from the build output # directory. # -# $ cipd create --pkg-def ../../webrunner/cipd/castrunner.yaml \ +# $ cipd create --pkg-def ../../fuchsia/cipd/castrunner.yaml \ # -pkg-var targetarch:$TARGET_ARCH \ # -pkg-var outdir:`pwd` \ # -ref latest \
diff --git a/webrunner/cipd/fidl.yaml b/fuchsia/cipd/fidl.yaml similarity index 91% rename from webrunner/cipd/fidl.yaml rename to fuchsia/cipd/fidl.yaml index c607b34b..5be7aa6 100644 --- a/webrunner/cipd/fidl.yaml +++ b/fuchsia/cipd/fidl.yaml
@@ -7,7 +7,7 @@ # To create a CIPD package, run the following command from the build output # directory. # -# $ cipd create --pkg-def ../../webrunner/cipd/fidl.yaml \ +# $ cipd create --pkg-def ../../fuchsia/cipd/fidl.yaml \ # -ref latest \ # -tag version:$(cat fuchsia_artifacts/build_id.txt) #
diff --git a/webrunner/cipd/http.yaml b/fuchsia/cipd/http.yaml similarity index 94% rename from webrunner/cipd/http.yaml rename to fuchsia/cipd/http.yaml index a8d8a43..702c6fa 100644 --- a/webrunner/cipd/http.yaml +++ b/fuchsia/cipd/http.yaml
@@ -14,7 +14,7 @@ # To create a CIPD package, run the following command from the build output # directory. # -# $ cipd create --pkg-def ../../webrunner/cipd/http.yaml \ +# $ cipd create --pkg-def ../../fuchsia/cipd/http.yaml \ # -pkg-var targetarch:$TARGET_ARCH \ # -pkg-var outdir:`pwd` \ # -ref latest \
diff --git a/webrunner/cipd/webrunner.yaml b/fuchsia/cipd/webrunner.yaml similarity index 94% rename from webrunner/cipd/webrunner.yaml rename to fuchsia/cipd/webrunner.yaml index 31cd527..9b82992 100644 --- a/webrunner/cipd/webrunner.yaml +++ b/fuchsia/cipd/webrunner.yaml
@@ -14,7 +14,7 @@ # To create a CIPD package, run the following command from the build output # directory. # -# $ cipd create --pkg-def ../../webrunner/cipd/webrunner.yaml \ +# $ cipd create --pkg-def ../../fuchsia/cipd/webrunner.yaml \ # -pkg-var targetarch:$TARGET_ARCH \ # -pkg-var outdir:`pwd` \ # -ref latest \
diff --git a/webrunner/common/DEPS b/fuchsia/common/DEPS similarity index 100% rename from webrunner/common/DEPS rename to fuchsia/common/DEPS
diff --git a/webrunner/common/OWNERS b/fuchsia/common/OWNERS similarity index 100% rename from webrunner/common/OWNERS rename to fuchsia/common/OWNERS
diff --git a/fuchsia/common/fuchsia_export.h b/fuchsia/common/fuchsia_export.h new file mode 100644 index 0000000..3a7f4761 --- /dev/null +++ b/fuchsia/common/fuchsia_export.h
@@ -0,0 +1,20 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef FUCHSIA_COMMON_FUCHSIA_EXPORT_H_ +#define FUCHSIA_COMMON_FUCHSIA_EXPORT_H_ + +#if defined(COMPONENT_BUILD) + +#if defined(WEBRUNNER_IMPLEMENTATION) +#define FUCHSIA_EXPORT __attribute__((visibility("default"))) +#else +#define FUCHSIA_EXPORT +#endif + +#else // defined(COMPONENT_BUILD) +#define FUCHSIA_EXPORT +#endif + +#endif // FUCHSIA_COMMON_FUCHSIA_EXPORT_H_
diff --git a/webrunner/common/mem_buffer_util.cc b/fuchsia/common/mem_buffer_util.cc similarity index 97% rename from webrunner/common/mem_buffer_util.cc rename to fuchsia/common/mem_buffer_util.cc index 1354525..837e4c2c 100644 --- a/webrunner/common/mem_buffer_util.cc +++ b/fuchsia/common/mem_buffer_util.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "webrunner/common/mem_buffer_util.h" +#include "fuchsia/common/mem_buffer_util.h" #include <lib/fdio/io.h>
diff --git a/webrunner/common/mem_buffer_util.h b/fuchsia/common/mem_buffer_util.h similarity index 91% rename from webrunner/common/mem_buffer_util.h rename to fuchsia/common/mem_buffer_util.h index ae18873..c320fcb 100644 --- a/webrunner/common/mem_buffer_util.h +++ b/fuchsia/common/mem_buffer_util.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef WEBRUNNER_COMMON_MEM_BUFFER_UTIL_H_ -#define WEBRUNNER_COMMON_MEM_BUFFER_UTIL_H_ +#ifndef FUCHSIA_COMMON_MEM_BUFFER_UTIL_H_ +#define FUCHSIA_COMMON_MEM_BUFFER_UTIL_H_ #include <fuchsia/mem/cpp/fidl.h> #include <lib/zx/channel.h> @@ -39,4 +39,4 @@ } // namespace webrunner -#endif // WEBRUNNER_COMMON_MEM_BUFFER_UTIL_H_ +#endif // FUCHSIA_COMMON_MEM_BUFFER_UTIL_H_
diff --git a/webrunner/common/named_message_port_connector.cc b/fuchsia/common/named_message_port_connector.cc similarity index 94% rename from webrunner/common/named_message_port_connector.cc rename to fuchsia/common/named_message_port_connector.cc index 5c62a00..41a0eaf1 100644 --- a/webrunner/common/named_message_port_connector.cc +++ b/fuchsia/common/named_message_port_connector.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "webrunner/common/named_message_port_connector.h" +#include "fuchsia/common/named_message_port_connector.h" #include <memory> #include <utility> @@ -13,14 +13,14 @@ #include "base/macros.h" #include "base/path_service.h" #include "base/threading/thread_restrictions.h" -#include "webrunner/common/mem_buffer_util.h" -#include "webrunner/fidl/chromium/web/cpp/fidl.h" +#include "fuchsia/common/mem_buffer_util.h" +#include "fuchsia/fidl/chromium/web/cpp/fidl.h" namespace webrunner { namespace { const char kBindingsJsPath[] = - FILE_PATH_LITERAL("webrunner/common/named_message_port_connector.js"); + FILE_PATH_LITERAL("fuchsia/common/named_message_port_connector.js"); const char kConnectedMessage[] = "connected"; } // namespace
diff --git a/webrunner/common/named_message_port_connector.h b/fuchsia/common/named_message_port_connector.h similarity index 86% rename from webrunner/common/named_message_port_connector.h rename to fuchsia/common/named_message_port_connector.h index f51b388..352903b8 100644 --- a/webrunner/common/named_message_port_connector.h +++ b/fuchsia/common/named_message_port_connector.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef WEBRUNNER_COMMON_NAMED_MESSAGE_PORT_CONNECTOR_H_ -#define WEBRUNNER_COMMON_NAMED_MESSAGE_PORT_CONNECTOR_H_ +#ifndef FUCHSIA_COMMON_NAMED_MESSAGE_PORT_CONNECTOR_H_ +#define FUCHSIA_COMMON_NAMED_MESSAGE_PORT_CONNECTOR_H_ #include <deque> #include <map> @@ -12,8 +12,8 @@ #include "base/callback.h" #include "base/files/file_path.h" #include "base/macros.h" -#include "webrunner/common/webrunner_export.h" -#include "webrunner/fidl/chromium/web/cpp/fidl.h" +#include "fuchsia/common/fuchsia_export.h" +#include "fuchsia/fidl/chromium/web/cpp/fidl.h" namespace webrunner { @@ -21,7 +21,7 @@ // passing them all to the web container every time a page-load occurs. It then // waits for the page to acknowledge each MessagePort, before invoking its // registered |handler| to notify the called that it is ready for use. -class WEBRUNNER_EXPORT NamedMessagePortConnector { +class FUCHSIA_EXPORT NamedMessagePortConnector { public: using PortConnectedCallback = base::RepeatingCallback<void(chromium::web::MessagePortPtr)>; @@ -67,4 +67,4 @@ } // namespace webrunner -#endif // WEBRUNNER_COMMON_NAMED_MESSAGE_PORT_CONNECTOR_H_ +#endif // FUCHSIA_COMMON_NAMED_MESSAGE_PORT_CONNECTOR_H_
diff --git a/webrunner/common/named_message_port_connector.js b/fuchsia/common/named_message_port_connector.js similarity index 100% rename from webrunner/common/named_message_port_connector.js rename to fuchsia/common/named_message_port_connector.js
diff --git a/webrunner/common/named_message_port_connector_browsertest.cc b/fuchsia/common/named_message_port_connector_browsertest.cc similarity index 91% rename from webrunner/common/named_message_port_connector_browsertest.cc rename to fuchsia/common/named_message_port_connector_browsertest.cc index c11aa56..ff5cf38c 100644 --- a/webrunner/common/named_message_port_connector_browsertest.cc +++ b/fuchsia/common/named_message_port_connector_browsertest.cc
@@ -9,15 +9,15 @@ #include "base/macros.h" #include "base/path_service.h" #include "base/test/test_timeouts.h" +#include "fuchsia/common/mem_buffer_util.h" +#include "fuchsia/common/named_message_port_connector.h" +#include "fuchsia/common/test/test_common.h" +#include "fuchsia/common/test/webrunner_browser_test.h" +#include "fuchsia/test/promise.h" #include "testing/gmock/include/gmock/gmock-matchers.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "url/url_constants.h" -#include "webrunner/common/mem_buffer_util.h" -#include "webrunner/common/named_message_port_connector.h" -#include "webrunner/common/test/test_common.h" -#include "webrunner/common/test/webrunner_browser_test.h" -#include "webrunner/test/promise.h" namespace webrunner { @@ -31,7 +31,7 @@ public: NamedMessagePortConnectorTest() : run_timeout_(TestTimeouts::action_timeout()) { - set_test_server_root(base::FilePath("webrunner/common/test/data")); + set_test_server_root(base::FilePath("fuchsia/common/test/data")); } ~NamedMessagePortConnectorTest() override = default;
diff --git a/webrunner/common/on_load_script_injector.mojom b/fuchsia/common/on_load_script_injector.mojom similarity index 100% rename from webrunner/common/on_load_script_injector.mojom rename to fuchsia/common/on_load_script_injector.mojom
diff --git a/webrunner/common/test/data/connector.html b/fuchsia/common/test/data/connector.html similarity index 100% rename from webrunner/common/test/data/connector.html rename to fuchsia/common/test/data/connector.html
diff --git a/webrunner/common/test/test_common.cc b/fuchsia/common/test/test_common.cc similarity index 91% rename from webrunner/common/test/test_common.cc rename to fuchsia/common/test/test_common.cc index 9a426e4..94e23ff 100644 --- a/webrunner/common/test/test_common.cc +++ b/fuchsia/common/test/test_common.cc
@@ -2,14 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "webrunner/common/test/test_common.h" +#include "fuchsia/common/test/test_common.h" #include <string> #include <utility> #include "base/fuchsia/fuchsia_logging.h" #include "base/run_loop.h" -#include "webrunner/common/mem_buffer_util.h" +#include "fuchsia/common/mem_buffer_util.h" namespace webrunner {
diff --git a/webrunner/common/test/test_common.h b/fuchsia/common/test/test_common.h similarity index 90% rename from webrunner/common/test/test_common.h rename to fuchsia/common/test/test_common.h index 852c1a6..594695d 100644 --- a/webrunner/common/test/test_common.h +++ b/fuchsia/common/test/test_common.h
@@ -2,15 +2,15 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef WEBRUNNER_COMMON_TEST_TEST_COMMON_H_ -#define WEBRUNNER_COMMON_TEST_TEST_COMMON_H_ +#ifndef FUCHSIA_COMMON_TEST_TEST_COMMON_H_ +#define FUCHSIA_COMMON_TEST_TEST_COMMON_H_ #include <string> #include <utility> #include "content/public/browser/web_contents_observer.h" +#include "fuchsia/fidl/chromium/web/cpp/fidl.h" #include "testing/gmock/include/gmock/gmock.h" -#include "webrunner/fidl/chromium/web/cpp/fidl.h" namespace webrunner { @@ -53,4 +53,4 @@ } // namespace webrunner -#endif // WEBRUNNER_COMMON_TEST_TEST_COMMON_H_ +#endif // FUCHSIA_COMMON_TEST_TEST_COMMON_H_
diff --git a/webrunner/common/test/webrunner_browser_test.cc b/fuchsia/common/test/webrunner_browser_test.cc similarity index 87% rename from webrunner/common/test/webrunner_browser_test.cc rename to fuchsia/common/test/webrunner_browser_test.cc index 5cd5278..308c525 100644 --- a/webrunner/common/test/webrunner_browser_test.cc +++ b/fuchsia/common/test/webrunner_browser_test.cc
@@ -2,14 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "webrunner/common/test/webrunner_browser_test.h" +#include "fuchsia/common/test/webrunner_browser_test.h" #include "base/fuchsia/fuchsia_logging.h" +#include "fuchsia/browser/webrunner_browser_context.h" +#include "fuchsia/browser/webrunner_browser_main_parts.h" +#include "fuchsia/browser/webrunner_content_browser_client.h" +#include "fuchsia/service/webrunner_main_delegate.h" #include "net/test/embedded_test_server/default_handlers.h" -#include "webrunner/browser/webrunner_browser_context.h" -#include "webrunner/browser/webrunner_browser_main_parts.h" -#include "webrunner/browser/webrunner_content_browser_client.h" -#include "webrunner/service/webrunner_main_delegate.h" namespace webrunner { namespace {
diff --git a/webrunner/common/test/webrunner_browser_test.h b/fuchsia/common/test/webrunner_browser_test.h similarity index 87% rename from webrunner/common/test/webrunner_browser_test.h rename to fuchsia/common/test/webrunner_browser_test.h index bde3cf2..6a7c22b 100644 --- a/webrunner/common/test/webrunner_browser_test.h +++ b/fuchsia/common/test/webrunner_browser_test.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef WEBRUNNER_COMMON_TEST_WEBRUNNER_BROWSER_TEST_H_ -#define WEBRUNNER_COMMON_TEST_WEBRUNNER_BROWSER_TEST_H_ +#ifndef FUCHSIA_COMMON_TEST_WEBRUNNER_BROWSER_TEST_H_ +#define FUCHSIA_COMMON_TEST_WEBRUNNER_BROWSER_TEST_H_ #include <lib/fidl/cpp/binding_set.h> #include <memory> @@ -12,8 +12,8 @@ #include "base/macros.h" #include "content/public/test/browser_test.h" #include "content/public/test/browser_test_base.h" -#include "webrunner/browser/context_impl.h" -#include "webrunner/fidl/chromium/web/cpp/fidl.h" +#include "fuchsia/browser/context_impl.h" +#include "fuchsia/fidl/chromium/web/cpp/fidl.h" namespace webrunner { @@ -64,4 +64,4 @@ } // namespace webrunner -#endif // WEBRUNNER_COMMON_TEST_WEBRUNNER_BROWSER_TEST_H_ +#endif // FUCHSIA_COMMON_TEST_FUCHSIA_BROWSER_TEST_H_
diff --git a/webrunner/common/test/webrunner_test_launcher.cc b/fuchsia/common/test/webrunner_test_launcher.cc similarity index 91% rename from webrunner/common/test/webrunner_test_launcher.cc rename to fuchsia/common/test/webrunner_test_launcher.cc index 8b3837b..ec8ba31f 100644 --- a/webrunner/common/test/webrunner_test_launcher.cc +++ b/fuchsia/common/test/webrunner_test_launcher.cc
@@ -9,11 +9,11 @@ #include "base/test/test_suite.h" #include "content/public/common/content_switches.h" #include "content/public/test/test_launcher.h" +#include "fuchsia/common/test/webrunner_browser_test.h" +#include "fuchsia/fidl/chromium/web/cpp/fidl.h" +#include "fuchsia/service/common.h" +#include "fuchsia/service/webrunner_main_delegate.h" #include "ui/ozone/public/ozone_switches.h" -#include "webrunner/common/test/webrunner_browser_test.h" -#include "webrunner/fidl/chromium/web/cpp/fidl.h" -#include "webrunner/service/common.h" -#include "webrunner/service/webrunner_main_delegate.h" namespace webrunner { namespace {
diff --git a/webrunner/common/webrunner_content_client.cc b/fuchsia/common/webrunner_content_client.cc similarity index 95% rename from webrunner/common/webrunner_content_client.cc rename to fuchsia/common/webrunner_content_client.cc index acf5237..019d7e0 100644 --- a/webrunner/common/webrunner_content_client.cc +++ b/fuchsia/common/webrunner_content_client.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "webrunner/common/webrunner_content_client.h" +#include "fuchsia/common/webrunner_content_client.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/resource/resource_bundle.h"
diff --git a/webrunner/common/webrunner_content_client.h b/fuchsia/common/webrunner_content_client.h similarity index 84% rename from webrunner/common/webrunner_content_client.h rename to fuchsia/common/webrunner_content_client.h index 15bd599..26e36a8 100644 --- a/webrunner/common/webrunner_content_client.h +++ b/fuchsia/common/webrunner_content_client.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef WEBRUNNER_COMMON_WEBRUNNER_CONTENT_CLIENT_H_ -#define WEBRUNNER_COMMON_WEBRUNNER_CONTENT_CLIENT_H_ +#ifndef FUCHSIA_COMMON_WEBRUNNER_CONTENT_CLIENT_H_ +#define FUCHSIA_COMMON_WEBRUNNER_CONTENT_CLIENT_H_ #include "base/macros.h" #include "content/public/common/content_client.h" @@ -30,4 +30,4 @@ } // namespace webrunner -#endif // WEBRUNNER_COMMON_WEBRUNNER_CONTENT_CLIENT_H_ +#endif // FUCHSIA_COMMON_WEBRUNNER_CONTENT_CLIENT_H_
diff --git a/webrunner/fidl/cast/application_config.fidl b/fuchsia/fidl/cast/application_config.fidl similarity index 100% rename from webrunner/fidl/cast/application_config.fidl rename to fuchsia/fidl/cast/application_config.fidl
diff --git a/webrunner/fidl/cast/cast_channel.fidl b/fuchsia/fidl/cast/cast_channel.fidl similarity index 100% rename from webrunner/fidl/cast/cast_channel.fidl rename to fuchsia/fidl/cast/cast_channel.fidl
diff --git a/webrunner/fidl/web/context.fidl b/fuchsia/fidl/web/context.fidl similarity index 100% rename from webrunner/fidl/web/context.fidl rename to fuchsia/fidl/web/context.fidl
diff --git a/webrunner/fidl/web/context_provider.fidl b/fuchsia/fidl/web/context_provider.fidl similarity index 100% rename from webrunner/fidl/web/context_provider.fidl rename to fuchsia/fidl/web/context_provider.fidl
diff --git a/webrunner/fidl/web/frame.fidl b/fuchsia/fidl/web/frame.fidl similarity index 100% rename from webrunner/fidl/web/frame.fidl rename to fuchsia/fidl/web/frame.fidl
diff --git a/webrunner/fidl/web/navigation_controller.fidl b/fuchsia/fidl/web/navigation_controller.fidl similarity index 94% rename from webrunner/fidl/web/navigation_controller.fidl rename to fuchsia/fidl/web/navigation_controller.fidl index 5c18c2b..588b2d2 100644 --- a/webrunner/fidl/web/navigation_controller.fidl +++ b/fuchsia/fidl/web/navigation_controller.fidl
@@ -32,6 +32,9 @@ // The URL that linked to the resource being requested. string referrer; + // Should be set to true if the action was initiated by the user. + bool was_activated = false; + // Custom HTTP headers. vector<vector<uint8>> headers; };
diff --git a/webrunner/fidl/web/navigation_event_observer.fidl b/fuchsia/fidl/web/navigation_event_observer.fidl similarity index 100% rename from webrunner/fidl/web/navigation_event_observer.fidl rename to fuchsia/fidl/web/navigation_event_observer.fidl
diff --git a/webrunner/net_http/BUILD.gn b/fuchsia/net_http/BUILD.gn similarity index 100% rename from webrunner/net_http/BUILD.gn rename to fuchsia/net_http/BUILD.gn
diff --git a/webrunner/net_http/http_service_impl.cc b/fuchsia/net_http/http_service_impl.cc similarity index 88% rename from webrunner/net_http/http_service_impl.cc rename to fuchsia/net_http/http_service_impl.cc index 25145da..a55aff57 100644 --- a/webrunner/net_http/http_service_impl.cc +++ b/fuchsia/net_http/http_service_impl.cc
@@ -2,10 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "webrunner/net_http/http_service_impl.h" +#include "fuchsia/net_http/http_service_impl.h" +#include "fuchsia/net_http/url_loader_impl.h" #include "net/url_request/url_request_context_builder.h" -#include "webrunner/net_http/url_loader_impl.h" namespace net_http {
diff --git a/webrunner/net_http/http_service_impl.h b/fuchsia/net_http/http_service_impl.h similarity index 83% rename from webrunner/net_http/http_service_impl.h rename to fuchsia/net_http/http_service_impl.h index 1742c7d..1b04bb2 100644 --- a/webrunner/net_http/http_service_impl.h +++ b/fuchsia/net_http/http_service_impl.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef WEBRUNNER_NET_HTTP_HTTP_SERVICE_IMPL_H_ -#define WEBRUNNER_NET_HTTP_HTTP_SERVICE_IMPL_H_ +#ifndef FUCHSIA_NET_HTTP_HTTP_SERVICE_IMPL_H_ +#define FUCHSIA_NET_HTTP_HTTP_SERVICE_IMPL_H_ #include <fuchsia/net/oldhttp/cpp/fidl.h> #include <lib/fidl/cpp/interface_request.h> @@ -29,4 +29,4 @@ } // namespace net_http -#endif // WEBRUNNER_NET_HTTP_HTTP_SERVICE_IMPL_H_ +#endif // FUCHSIA_NET_HTTP_HTTP_SERVICE_IMPL_H_
diff --git a/webrunner/net_http/http_service_main.cc b/fuchsia/net_http/http_service_main.cc similarity index 96% rename from webrunner/net_http/http_service_main.cc rename to fuchsia/net_http/http_service_main.cc index 76c9403..3396d86f 100644 --- a/webrunner/net_http/http_service_main.cc +++ b/fuchsia/net_http/http_service_main.cc
@@ -10,7 +10,7 @@ #include "base/message_loop/message_loop.h" #include "base/run_loop.h" #include "base/task/task_scheduler/task_scheduler.h" -#include "webrunner/net_http/http_service_impl.h" +#include "fuchsia/net_http/http_service_impl.h" int main(int argc, char** argv) { // Instantiate various global structures.
diff --git a/webrunner/net_http/http_service_unittest.cc b/fuchsia/net_http/http_service_unittest.cc similarity index 98% rename from webrunner/net_http/http_service_unittest.cc rename to fuchsia/net_http/http_service_unittest.cc index 7feef36..d09ccdf 100644 --- a/webrunner/net_http/http_service_unittest.cc +++ b/fuchsia/net_http/http_service_unittest.cc
@@ -10,12 +10,12 @@ #include "base/fuchsia/service_directory.h" #include "base/run_loop.h" #include "base/test/scoped_task_environment.h" +#include "fuchsia/net_http/http_service_impl.h" +#include "fuchsia/net_http/url_loader_impl.h" #include "net/base/net_errors.h" #include "net/test/embedded_test_server/default_handlers.h" #include "net/test/embedded_test_server/embedded_test_server.h" #include "testing/gtest/include/gtest/gtest.h" -#include "webrunner/net_http/http_service_impl.h" -#include "webrunner/net_http/url_loader_impl.h" namespace net_http { @@ -24,7 +24,7 @@ namespace { const base::FilePath::CharType kTestFilePath[] = - FILE_PATH_LITERAL("webrunner/net_http/testdata"); + FILE_PATH_LITERAL("fuchsia/net_http/testdata"); // Capacity, in bytes, for buffers used to read data off the URLResponse. const size_t kBufferCapacity = 1024;
diff --git a/webrunner/net_http/sandbox_policy b/fuchsia/net_http/sandbox_policy similarity index 100% rename from webrunner/net_http/sandbox_policy rename to fuchsia/net_http/sandbox_policy
diff --git a/webrunner/net_http/testdata/redirect-test.html b/fuchsia/net_http/testdata/redirect-test.html similarity index 100% rename from webrunner/net_http/testdata/redirect-test.html rename to fuchsia/net_http/testdata/redirect-test.html
diff --git a/webrunner/net_http/testdata/redirect-test.html.mock-http-headers b/fuchsia/net_http/testdata/redirect-test.html.mock-http-headers similarity index 100% rename from webrunner/net_http/testdata/redirect-test.html.mock-http-headers rename to fuchsia/net_http/testdata/redirect-test.html.mock-http-headers
diff --git a/webrunner/net_http/testdata/simple.html b/fuchsia/net_http/testdata/simple.html similarity index 100% rename from webrunner/net_http/testdata/simple.html rename to fuchsia/net_http/testdata/simple.html
diff --git a/webrunner/net_http/testdata/simple.html.mock-http-headers b/fuchsia/net_http/testdata/simple.html.mock-http-headers similarity index 100% rename from webrunner/net_http/testdata/simple.html.mock-http-headers rename to fuchsia/net_http/testdata/simple.html.mock-http-headers
diff --git a/webrunner/net_http/testdata/with-duplicate-headers.html b/fuchsia/net_http/testdata/with-duplicate-headers.html similarity index 100% rename from webrunner/net_http/testdata/with-duplicate-headers.html rename to fuchsia/net_http/testdata/with-duplicate-headers.html
diff --git a/webrunner/net_http/testdata/with-duplicate-headers.html.mock-http-headers b/fuchsia/net_http/testdata/with-duplicate-headers.html.mock-http-headers similarity index 100% rename from webrunner/net_http/testdata/with-duplicate-headers.html.mock-http-headers rename to fuchsia/net_http/testdata/with-duplicate-headers.html.mock-http-headers
diff --git a/webrunner/net_http/testdata/with-headers.html b/fuchsia/net_http/testdata/with-headers.html similarity index 100% rename from webrunner/net_http/testdata/with-headers.html rename to fuchsia/net_http/testdata/with-headers.html
diff --git a/webrunner/net_http/testdata/with-headers.html.mock-http-headers b/fuchsia/net_http/testdata/with-headers.html.mock-http-headers similarity index 100% rename from webrunner/net_http/testdata/with-headers.html.mock-http-headers rename to fuchsia/net_http/testdata/with-headers.html.mock-http-headers
diff --git a/webrunner/net_http/url_loader_impl.cc b/fuchsia/net_http/url_loader_impl.cc similarity index 99% rename from webrunner/net_http/url_loader_impl.cc rename to fuchsia/net_http/url_loader_impl.cc index f959561..c4d4468 100644 --- a/webrunner/net_http/url_loader_impl.cc +++ b/fuchsia/net_http/url_loader_impl.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "webrunner/net_http/url_loader_impl.h" +#include "fuchsia/net_http/url_loader_impl.h" #include "base/fuchsia/fuchsia_logging.h" #include "base/message_loop/message_loop_current.h"
diff --git a/webrunner/net_http/url_loader_impl.h b/fuchsia/net_http/url_loader_impl.h similarity index 96% rename from webrunner/net_http/url_loader_impl.h rename to fuchsia/net_http/url_loader_impl.h index d412f750..7405bac 100644 --- a/webrunner/net_http/url_loader_impl.h +++ b/fuchsia/net_http/url_loader_impl.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef WEBRUNNER_NET_HTTP_URL_LOADER_IMPL_H_ -#define WEBRUNNER_NET_HTTP_URL_LOADER_IMPL_H_ +#ifndef FUCHSIA_NET_HTTP_URL_LOADER_IMPL_H_ +#define FUCHSIA_NET_HTTP_URL_LOADER_IMPL_H_ #include <fuchsia/net/oldhttp/cpp/fidl.h> #include <fuchsia/sys/cpp/fidl.h> @@ -122,4 +122,4 @@ } // namespace net_http -#endif // WEBRUNNER_NET_HTTP_URL_LOADER_IMPL_H_ \ No newline at end of file +#endif // FUCHSIA_NET_HTTP_URL_LOADER_IMPL_H_ \ No newline at end of file
diff --git a/webrunner/renderer/DEPS b/fuchsia/renderer/DEPS similarity index 100% rename from webrunner/renderer/DEPS rename to fuchsia/renderer/DEPS
diff --git a/webrunner/renderer/on_load_script_injector.cc b/fuchsia/renderer/on_load_script_injector.cc similarity index 97% rename from webrunner/renderer/on_load_script_injector.cc rename to fuchsia/renderer/on_load_script_injector.cc index 1a5abe9..904fdae85 100644 --- a/webrunner/renderer/on_load_script_injector.cc +++ b/fuchsia/renderer/on_load_script_injector.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "webrunner/renderer/on_load_script_injector.h" +#include "fuchsia/renderer/on_load_script_injector.h" #include <lib/zx/vmo.h> #include <utility>
diff --git a/webrunner/renderer/on_load_script_injector.h b/fuchsia/renderer/on_load_script_injector.h similarity index 87% rename from webrunner/renderer/on_load_script_injector.h rename to fuchsia/renderer/on_load_script_injector.h index 7208a37..f814a2b 100644 --- a/webrunner/renderer/on_load_script_injector.h +++ b/fuchsia/renderer/on_load_script_injector.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef WEBRUNNER_RENDERER_ON_LOAD_SCRIPT_INJECTOR_H_ -#define WEBRUNNER_RENDERER_ON_LOAD_SCRIPT_INJECTOR_H_ +#ifndef FUCHSIA_RENDERER_ON_LOAD_SCRIPT_INJECTOR_H_ +#define FUCHSIA_RENDERER_ON_LOAD_SCRIPT_INJECTOR_H_ #include <lib/zx/vmo.h> #include <vector> @@ -12,8 +12,8 @@ #include "base/memory/shared_memory_handle.h" #include "base/memory/weak_ptr.h" #include "content/public/renderer/render_frame_observer.h" +#include "fuchsia/common/on_load_script_injector.mojom.h" #include "mojo/public/cpp/bindings/associated_binding_set.h" -#include "webrunner/common/on_load_script_injector.mojom.h" namespace webrunner { @@ -47,4 +47,4 @@ } // namespace webrunner -#endif // WEBRUNNER_RENDERER_ON_LOAD_SCRIPT_INJECTOR_H_ +#endif // FUCHSIA_RENDERER_ON_LOAD_SCRIPT_INJECTOR_H_
diff --git a/webrunner/renderer/webrunner_content_renderer_client.cc b/fuchsia/renderer/webrunner_content_renderer_client.cc similarity index 87% rename from webrunner/renderer/webrunner_content_renderer_client.cc rename to fuchsia/renderer/webrunner_content_renderer_client.cc index c335fd9..cd05d13 100644 --- a/webrunner/renderer/webrunner_content_renderer_client.cc +++ b/fuchsia/renderer/webrunner_content_renderer_client.cc
@@ -2,13 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "webrunner/renderer/webrunner_content_renderer_client.h" +#include "fuchsia/renderer/webrunner_content_renderer_client.h" #include "base/macros.h" #include "content/public/renderer/render_frame.h" +#include "fuchsia/renderer/on_load_script_injector.h" #include "services/service_manager/public/cpp/binder_registry.h" #include "third_party/blink/public/common/associated_interfaces/associated_interface_registry.h" -#include "webrunner/renderer/on_load_script_injector.h" namespace webrunner {
diff --git a/webrunner/renderer/webrunner_content_renderer_client.h b/fuchsia/renderer/webrunner_content_renderer_client.h similarity index 77% rename from webrunner/renderer/webrunner_content_renderer_client.h rename to fuchsia/renderer/webrunner_content_renderer_client.h index fd6bd15..fdadb5e 100644 --- a/webrunner/renderer/webrunner_content_renderer_client.h +++ b/fuchsia/renderer/webrunner_content_renderer_client.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef WEBRUNNER_RENDERER_WEBRUNNER_CONTENT_RENDERER_CLIENT_H_ -#define WEBRUNNER_RENDERER_WEBRUNNER_CONTENT_RENDERER_CLIENT_H_ +#ifndef FUCHSIA_RENDERER_WEBRUNNER_CONTENT_RENDERER_CLIENT_H_ +#define FUCHSIA_RENDERER_WEBRUNNER_CONTENT_RENDERER_CLIENT_H_ #include "base/macros.h" #include "content/public/renderer/content_renderer_client.h" @@ -24,4 +24,4 @@ } // namespace webrunner -#endif // WEBRUNNER_RENDERER_WEBRUNNER_CONTENT_RENDERER_CLIENT_H_ +#endif // FUCHSIA_RENDERER_WEBRUNNER_CONTENT_RENDERER_CLIENT_H_
diff --git a/webrunner/service/DEPS b/fuchsia/service/DEPS similarity index 100% rename from webrunner/service/DEPS rename to fuchsia/service/DEPS
diff --git a/webrunner/service/common.cc b/fuchsia/service/common.cc similarity index 87% rename from webrunner/service/common.cc rename to fuchsia/service/common.cc index ccec139..cdccace 100644 --- a/webrunner/service/common.cc +++ b/fuchsia/service/common.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "webrunner/service/common.h" +#include "fuchsia/service/common.h" namespace webrunner {
diff --git a/webrunner/service/common.h b/fuchsia/service/common.h similarity index 74% rename from webrunner/service/common.h rename to fuchsia/service/common.h index 0d3963d..e48ec86 100644 --- a/webrunner/service/common.h +++ b/fuchsia/service/common.h
@@ -2,18 +2,18 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef WEBRUNNER_SERVICE_COMMON_H_ -#define WEBRUNNER_SERVICE_COMMON_H_ +#ifndef FUCHSIA_SERVICE_COMMON_H_ +#define FUCHSIA_SERVICE_COMMON_H_ #include <zircon/processargs.h> -#include "webrunner/common/webrunner_export.h" +#include "fuchsia/common/fuchsia_export.h" namespace webrunner { // Switch passed to content process when running in incognito mode, i.e. when // there is no kWebContextDataPath. -WEBRUNNER_EXPORT extern const char kIncognitoSwitch[]; +FUCHSIA_EXPORT extern const char kIncognitoSwitch[]; // This file contains constants and functions shared between Context and // ContextProvider processes. @@ -24,4 +24,4 @@ } // namespace webrunner -#endif // WEBRUNNER_SERVICE_COMMON_H_ +#endif // FUCHSIA_SERVICE_COMMON_H_
diff --git a/webrunner/service/context_provider_impl.cc b/fuchsia/service/context_provider_impl.cc similarity index 97% rename from webrunner/service/context_provider_impl.cc rename to fuchsia/service/context_provider_impl.cc index 1031d952..4c64a1b 100644 --- a/webrunner/service/context_provider_impl.cc +++ b/fuchsia/service/context_provider_impl.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "webrunner/service/context_provider_impl.h" +#include "fuchsia/service/context_provider_impl.h" #include <fuchsia/sys/cpp/fidl.h> #include <lib/async/default.h> @@ -25,8 +25,8 @@ #include "base/logging.h" #include "base/path_service.h" #include "base/process/launch.h" +#include "fuchsia/service/common.h" #include "services/service_manager/sandbox/fuchsia/sandbox_policy_fuchsia.h" -#include "webrunner/service/common.h" namespace webrunner { namespace {
diff --git a/webrunner/service/context_provider_impl.h b/fuchsia/service/context_provider_impl.h similarity index 89% rename from webrunner/service/context_provider_impl.h rename to fuchsia/service/context_provider_impl.h index 6efb9ce..84239c8 100644 --- a/webrunner/service/context_provider_impl.h +++ b/fuchsia/service/context_provider_impl.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef WEBRUNNER_SERVICE_CONTEXT_PROVIDER_IMPL_H_ -#define WEBRUNNER_SERVICE_CONTEXT_PROVIDER_IMPL_H_ +#ifndef FUCHSIA_SERVICE_CONTEXT_PROVIDER_IMPL_H_ +#define FUCHSIA_SERVICE_CONTEXT_PROVIDER_IMPL_H_ #include <lib/fidl/cpp/binding_set.h> #include <memory> @@ -11,7 +11,7 @@ #include "base/callback.h" #include "base/macros.h" #include "chromium/web/cpp/fidl.h" -#include "webrunner/common/webrunner_export.h" +#include "fuchsia/common/fuchsia_export.h" namespace base { class CommandLine; @@ -21,7 +21,7 @@ namespace webrunner { -class WEBRUNNER_EXPORT ContextProviderImpl +class FUCHSIA_EXPORT ContextProviderImpl : public chromium::web::ContextProvider { public: ContextProviderImpl(); @@ -68,4 +68,4 @@ } // namespace webrunner -#endif // WEBRUNNER_SERVICE_CONTEXT_PROVIDER_IMPL_H_ +#endif // FUCHSIA_SERVICE_CONTEXT_PROVIDER_IMPL_H_
diff --git a/webrunner/service/context_provider_impl_unittest.cc b/fuchsia/service/context_provider_impl_unittest.cc similarity index 97% rename from webrunner/service/context_provider_impl_unittest.cc rename to fuchsia/service/context_provider_impl_unittest.cc index 9142843..ac744c1 100644 --- a/webrunner/service/context_provider_impl_unittest.cc +++ b/fuchsia/service/context_provider_impl_unittest.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "webrunner/service/context_provider_impl.h" +#include "fuchsia/service/context_provider_impl.h" #include <lib/fdio/util.h> #include <lib/fidl/cpp/binding.h> @@ -28,11 +28,11 @@ #include "base/message_loop/message_loop.h" #include "base/path_service.h" #include "base/test/multiprocess_test.h" +#include "fuchsia/fidl/chromium/web/cpp/fidl_test_base.h" +#include "fuchsia/service/common.h" +#include "fuchsia/test/fake_context.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/multiprocess_func_list.h" -#include "webrunner/fidl/chromium/web/cpp/fidl_test_base.h" -#include "webrunner/service/common.h" -#include "webrunner/test/fake_context.h" namespace webrunner { namespace {
diff --git a/webrunner/service/context_provider_main.cc b/fuchsia/service/context_provider_main.cc similarity index 88% rename from webrunner/service/context_provider_main.cc rename to fuchsia/service/context_provider_main.cc index fe0ddc15..dfa1749 100644 --- a/webrunner/service/context_provider_main.cc +++ b/fuchsia/service/context_provider_main.cc
@@ -2,14 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "webrunner/service/context_provider_main.h" +#include "fuchsia/service/context_provider_main.h" #include "base/fuchsia/scoped_service_binding.h" #include "base/fuchsia/service_directory.h" #include "base/logging.h" #include "base/message_loop/message_loop.h" #include "base/run_loop.h" -#include "webrunner/service/context_provider_impl.h" +#include "fuchsia/service/context_provider_impl.h" namespace webrunner {
diff --git a/webrunner/service/context_provider_main.h b/fuchsia/service/context_provider_main.h similarity index 61% rename from webrunner/service/context_provider_main.h rename to fuchsia/service/context_provider_main.h index b15358b7..4ae7b8c 100644 --- a/webrunner/service/context_provider_main.h +++ b/fuchsia/service/context_provider_main.h
@@ -2,18 +2,18 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef WEBRUNNER_SERVICE_CONTEXT_PROVIDER_MAIN_H_ -#define WEBRUNNER_SERVICE_CONTEXT_PROVIDER_MAIN_H_ +#ifndef FUCHSIA_SERVICE_CONTEXT_PROVIDER_MAIN_H_ +#define FUCHSIA_SERVICE_CONTEXT_PROVIDER_MAIN_H_ -#include "webrunner/common/webrunner_export.h" +#include "fuchsia/common/fuchsia_export.h" namespace webrunner { // Main function for the process that implements web::ContextProvider interface. // Called by WebRunnerMainDelegate when the process is started without --type // argument. -WEBRUNNER_EXPORT int ContextProviderMain(); +FUCHSIA_EXPORT int ContextProviderMain(); } // namespace webrunner -#endif // WEBRUNNER_SERVICE_CONTEXT_PROVIDER_MAIN_H_ \ No newline at end of file +#endif // FUCHSIA_SERVICE_CONTEXT_PROVIDER_MAIN_H_ \ No newline at end of file
diff --git a/webrunner/service/sandbox_policy b/fuchsia/service/sandbox_policy similarity index 100% rename from webrunner/service/sandbox_policy rename to fuchsia/service/sandbox_policy
diff --git a/webrunner/service/web_content_service_main.cc b/fuchsia/service/web_content_service_main.cc similarity index 90% rename from webrunner/service/web_content_service_main.cc rename to fuchsia/service/web_content_service_main.cc index 0fa8e2d..6fb4d72 100644 --- a/webrunner/service/web_content_service_main.cc +++ b/fuchsia/service/web_content_service_main.cc
@@ -6,10 +6,10 @@ #include "base/command_line.h" #include "content/public/app/content_main.h" +#include "fuchsia/service/common.h" +#include "fuchsia/service/context_provider_main.h" +#include "fuchsia/service/webrunner_main_delegate.h" #include "services/service_manager/embedder/switches.h" -#include "webrunner/service/common.h" -#include "webrunner/service/context_provider_main.h" -#include "webrunner/service/webrunner_main_delegate.h" int main(int argc, const char** argv) { base::CommandLine::Init(argc, argv);
diff --git a/webrunner/service/webrunner_main_delegate.cc b/fuchsia/service/webrunner_main_delegate.cc similarity index 89% rename from webrunner/service/webrunner_main_delegate.cc rename to fuchsia/service/webrunner_main_delegate.cc index ae772ed..3617114 100644 --- a/webrunner/service/webrunner_main_delegate.cc +++ b/fuchsia/service/webrunner_main_delegate.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "webrunner/service/webrunner_main_delegate.h" +#include "fuchsia/service/webrunner_main_delegate.h" #include <utility> @@ -10,12 +10,12 @@ #include "base/command_line.h" #include "base/path_service.h" #include "content/public/common/content_switches.h" +#include "fuchsia/browser/webrunner_browser_main.h" +#include "fuchsia/browser/webrunner_content_browser_client.h" +#include "fuchsia/common/webrunner_content_client.h" +#include "fuchsia/renderer/webrunner_content_renderer_client.h" +#include "fuchsia/service/common.h" #include "ui/base/resource/resource_bundle.h" -#include "webrunner/browser/webrunner_browser_main.h" -#include "webrunner/browser/webrunner_content_browser_client.h" -#include "webrunner/common/webrunner_content_client.h" -#include "webrunner/renderer/webrunner_content_renderer_client.h" -#include "webrunner/service/common.h" namespace webrunner { namespace {
diff --git a/webrunner/service/webrunner_main_delegate.h b/fuchsia/service/webrunner_main_delegate.h similarity index 85% rename from webrunner/service/webrunner_main_delegate.h rename to fuchsia/service/webrunner_main_delegate.h index 4e4ee5b..c430930c 100644 --- a/webrunner/service/webrunner_main_delegate.h +++ b/fuchsia/service/webrunner_main_delegate.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef WEBRUNNER_SERVICE_WEBRUNNER_MAIN_DELEGATE_H_ -#define WEBRUNNER_SERVICE_WEBRUNNER_MAIN_DELEGATE_H_ +#ifndef FUCHSIA_SERVICE_WEBRUNNER_MAIN_DELEGATE_H_ +#define FUCHSIA_SERVICE_WEBRUNNER_MAIN_DELEGATE_H_ #include <lib/zx/channel.h> #include <memory> @@ -11,7 +11,7 @@ #include "base/macros.h" #include "content/public/app/content_main_delegate.h" -#include "webrunner/common/webrunner_export.h" +#include "fuchsia/common/fuchsia_export.h" namespace content { class ContentClient; @@ -22,7 +22,7 @@ class WebRunnerContentBrowserClient; class WebRunnerContentRendererClient; -class WEBRUNNER_EXPORT WebRunnerMainDelegate +class FUCHSIA_EXPORT WebRunnerMainDelegate : public content::ContentMainDelegate { public: explicit WebRunnerMainDelegate(zx::channel context_channel); @@ -55,4 +55,4 @@ } // namespace webrunner -#endif // WEBRUNNER_SERVICE_WEBRUNNER_MAIN_DELEGATE_H_ +#endif // FUCHSIA_SERVICE_WEBRUNNER_MAIN_DELEGATE_H_
diff --git a/webrunner/test/fake_context.cc b/fuchsia/test/fake_context.cc similarity index 97% rename from webrunner/test/fake_context.cc rename to fuchsia/test/fake_context.cc index b4890eb8..d2eafb6c 100644 --- a/webrunner/test/fake_context.cc +++ b/fuchsia/test/fake_context.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "webrunner/test/fake_context.h" +#include "fuchsia/test/fake_context.h" #include "base/logging.h"
diff --git a/webrunner/test/fake_context.h b/fuchsia/test/fake_context.h similarity index 91% rename from webrunner/test/fake_context.h rename to fuchsia/test/fake_context.h index b4236d4..d0505e9 100644 --- a/webrunner/test/fake_context.h +++ b/fuchsia/test/fake_context.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef WEBRUNNER_TEST_FAKE_CONTEXT_H_ -#define WEBRUNNER_TEST_FAKE_CONTEXT_H_ +#ifndef FUCHSIA_TEST_FAKE_CONTEXT_H_ +#define FUCHSIA_TEST_FAKE_CONTEXT_H_ #include <lib/fidl/cpp/binding.h> #include <lib/fidl/cpp/binding_set.h> @@ -12,8 +12,8 @@ #include "base/callback.h" #include "base/macros.h" -#include "webrunner/fidl/chromium/web/cpp/fidl.h" -#include "webrunner/fidl/chromium/web/cpp/fidl_test_base.h" +#include "fuchsia/fidl/chromium/web/cpp/fidl.h" +#include "fuchsia/fidl/chromium/web/cpp/fidl_test_base.h" namespace webrunner { @@ -87,4 +87,4 @@ } // namespace webrunner -#endif // WEBRUNNER_TEST_FAKE_CONTEXT_H_ +#endif // FUCHSIA_TEST_FAKE_CONTEXT_H_
diff --git a/webrunner/test/promise.h b/fuchsia/test/promise.h similarity index 94% rename from webrunner/test/promise.h rename to fuchsia/test/promise.h index 557c1107..c087f587 100644 --- a/webrunner/test/promise.h +++ b/fuchsia/test/promise.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef WEBRUNNER_TEST_PROMISE_H_ -#define WEBRUNNER_TEST_PROMISE_H_ +#ifndef FUCHSIA_TEST_PROMISE_H_ +#define FUCHSIA_TEST_PROMISE_H_ #include "base/bind_helpers.h" #include "base/optional.h" @@ -66,4 +66,4 @@ } // namespace webrunner -#endif // WEBRUNNER_TEST_PROMISE_H_ \ No newline at end of file +#endif // FUCHSIA_TEST_PROMISE_H_ \ No newline at end of file
diff --git a/gpu/command_buffer/service/shared_image_backing_factory_ahardwarebuffer.cc b/gpu/command_buffer/service/shared_image_backing_factory_ahardwarebuffer.cc index 9bb4b7d2..469e95e 100644 --- a/gpu/command_buffer/service/shared_image_backing_factory_ahardwarebuffer.cc +++ b/gpu/command_buffer/service/shared_image_backing_factory_ahardwarebuffer.cc
@@ -96,6 +96,7 @@ base::ScopedFD gl_write_sync_fd_; base::ScopedFD vk_read_sync_fd_; + sk_sp<SkPromiseImageTexture> cached_promise_texture_; DISALLOW_COPY_AND_ASSIGN(SharedImageBackingAHB); }; @@ -161,16 +162,15 @@ class SharedImageRepresentationSkiaGLAHB : public SharedImageRepresentationSkia { public: - SharedImageRepresentationSkiaGLAHB(SharedImageManager* manager, - SharedImageBacking* backing, - MemoryTypeTracker* tracker, - GLenum target, - GLuint service_id) - : SharedImageRepresentationSkia(manager, backing, tracker) { - GrBackendTexture backend_texture; - GetGrBackendTexture(gl::GLContext::GetCurrent()->GetVersionInfo(), target, - size(), service_id, format(), &backend_texture); - promise_texture_ = SkPromiseImageTexture::Make(backend_texture); + SharedImageRepresentationSkiaGLAHB( + SharedImageManager* manager, + SharedImageBacking* backing, + sk_sp<SkPromiseImageTexture> cached_promise_image_texture, + MemoryTypeTracker* tracker, + GLenum target, + GLuint service_id) + : SharedImageRepresentationSkia(manager, backing, tracker), + promise_texture_(cached_promise_image_texture) { #if DCHECK_IS_ON() context_ = gl::GLContext::GetCurrent(); #endif @@ -538,9 +538,17 @@ if (!GenGLTexture()) return nullptr; + if (!cached_promise_texture_) { + GrBackendTexture backend_texture; + GetGrBackendTexture(gl::GLContext::GetCurrent()->GetVersionInfo(), + texture_->target(), size(), texture_->service_id(), + format(), &backend_texture); + cached_promise_texture_ = SkPromiseImageTexture::Make(backend_texture); + } DCHECK(texture_); return std::make_unique<SharedImageRepresentationSkiaGLAHB>( - manager, this, tracker, texture_->target(), texture_->service_id()); + manager, this, cached_promise_texture_, tracker, texture_->target(), + texture_->service_id()); } bool SharedImageBackingAHB::GenGLTexture() {
diff --git a/gpu/command_buffer/service/shared_image_backing_factory_gl_texture.cc b/gpu/command_buffer/service/shared_image_backing_factory_gl_texture.cc index 98f46e2..63e3150 100644 --- a/gpu/command_buffer/service/shared_image_backing_factory_gl_texture.cc +++ b/gpu/command_buffer/service/shared_image_backing_factory_gl_texture.cc
@@ -229,16 +229,21 @@ class SharedImageRepresentationSkiaImpl : public SharedImageRepresentationSkia { public: - SharedImageRepresentationSkiaImpl(SharedImageManager* manager, - SharedImageBacking* backing, - MemoryTypeTracker* tracker, - GLenum target, - GLuint service_id) - : SharedImageRepresentationSkia(manager, backing, tracker) { - GrBackendTexture backend_texture; - GetGrBackendTexture(gl::GLContext::GetCurrent()->GetVersionInfo(), target, - size(), service_id, format(), &backend_texture); - promise_texture_ = SkPromiseImageTexture::Make(backend_texture); + SharedImageRepresentationSkiaImpl( + SharedImageManager* manager, + SharedImageBacking* backing, + sk_sp<SkPromiseImageTexture> cached_promise_texture, + MemoryTypeTracker* tracker, + GLenum target, + GLuint service_id) + : SharedImageRepresentationSkia(manager, backing, tracker), + promise_texture_(cached_promise_texture) { + if (!promise_texture_) { + GrBackendTexture backend_texture; + GetGrBackendTexture(gl::GLContext::GetCurrent()->GetVersionInfo(), target, + size(), service_id, format(), &backend_texture); + promise_texture_ = SkPromiseImageTexture::Make(backend_texture); + } #if DCHECK_IS_ON() context_ = gl::GLContext::GetCurrent(); #endif @@ -284,6 +289,8 @@ // TODO(ericrk): Handle begin/end correctness checks. } + sk_sp<SkPromiseImageTexture> promise_texture() { return promise_texture_; } + private: void CheckContext() { #if DCHECK_IS_ON() @@ -389,12 +396,16 @@ std::unique_ptr<SharedImageRepresentationSkia> ProduceSkia( SharedImageManager* manager, MemoryTypeTracker* tracker) override { - return std::make_unique<SharedImageRepresentationSkiaImpl>( - manager, this, tracker, texture_->target(), texture_->service_id()); + auto result = std::make_unique<SharedImageRepresentationSkiaImpl>( + manager, this, cached_promise_texture_, tracker, texture_->target(), + texture_->service_id()); + cached_promise_texture_ = result->promise_texture(); + return result; } private: gles2::Texture* texture_ = nullptr; + sk_sp<SkPromiseImageTexture> cached_promise_texture_; }; // Implementation of SharedImageBacking that creates a GL Texture and stores it @@ -485,13 +496,17 @@ std::unique_ptr<SharedImageRepresentationSkia> ProduceSkia( SharedImageManager* manager, MemoryTypeTracker* tracker) override { - return std::make_unique<SharedImageRepresentationSkiaImpl>( - manager, this, tracker, texture_passthrough_->target(), - texture_passthrough_->service_id()); + auto result = std::make_unique<SharedImageRepresentationSkiaImpl>( + manager, this, cached_promise_texture_, tracker, + texture_passthrough_->target(), texture_passthrough_->service_id()); + cached_promise_texture_ = result->promise_texture(); + return result; } private: scoped_refptr<gles2::TexturePassthrough> texture_passthrough_; + sk_sp<SkPromiseImageTexture> cached_promise_texture_; + bool is_cleared_ = false; };
diff --git a/gpu/command_buffer/service/wrapped_sk_image.cc b/gpu/command_buffer/service/wrapped_sk_image.cc index e76fa8b24..cca87d4 100644 --- a/gpu/command_buffer/service/wrapped_sk_image.cc +++ b/gpu/command_buffer/service/wrapped_sk_image.cc
@@ -82,11 +82,7 @@ final_msaa_count, color_type, /*colorSpace=*/nullptr, &surface_props); } - bool GetGrBackendTexture(GrBackendTexture* gr_texture) const { - context_state_->need_context_state_reset = true; - *gr_texture = image_->getBackendTexture(/*flushPendingGrContextIO=*/true); - return gr_texture->isValid(); - } + sk_sp<SkPromiseImageTexture> promise_texture() { return promise_texture_; } protected: std::unique_ptr<SharedImageRepresentationSkia> ProduceSkia( @@ -147,6 +143,7 @@ image_->getBackendTexture(/*flushPendingGrContextIO=*/false); if (!gr_texture.isValid()) return false; + promise_texture_ = SkPromiseImageTexture::Make(gr_texture); switch (gr_texture.backend()) { case GrBackendApi::kOpenGL: { @@ -171,6 +168,8 @@ RasterDecoderContextState* const context_state_; sk_sp<SkImage> image_; + sk_sp<SkPromiseImageTexture> promise_texture_; + bool cleared_ = false; uint64_t tracing_id_ = 0; @@ -207,12 +206,7 @@ } sk_sp<SkPromiseImageTexture> BeginReadAccess(SkSurface* sk_surface) override { - if (!promise_texture_) { - GrBackendTexture backend_texture; - wrapped_sk_image()->GetGrBackendTexture(&backend_texture); - promise_texture_ = SkPromiseImageTexture::Make(backend_texture); - } - return promise_texture_; + return wrapped_sk_image()->promise_texture(); } void EndReadAccess() override { @@ -225,7 +219,6 @@ } SkSurface* write_surface_ = nullptr; - sk_sp<SkPromiseImageTexture> promise_texture_; }; } // namespace
diff --git a/ios/chrome/browser/experimental_flags.mm b/ios/chrome/browser/experimental_flags.mm index c6dd2eb..e072e71 100644 --- a/ios/chrome/browser/experimental_flags.mm +++ b/ios/chrome/browser/experimental_flags.mm
@@ -48,7 +48,7 @@ namespace experimental_flags { const base::Feature kExternalFilesLoadedInWebState{ - "ExternalFilesLoadedInWebState", base::FEATURE_DISABLED_BY_DEFAULT}; + "ExternalFilesLoadedInWebState", base::FEATURE_ENABLED_BY_DEFAULT}; bool AlwaysDisplayFirstRun() { return
diff --git a/ios/chrome/browser/ui/browser_view_controller.mm b/ios/chrome/browser/ui/browser_view_controller.mm index 2faf61b..0055ce60 100644 --- a/ios/chrome/browser/ui/browser_view_controller.mm +++ b/ios/chrome/browser/ui/browser_view_controller.mm
@@ -2376,6 +2376,9 @@ UIViewController* viewController = _ntpCoordinatorsForWebStates[tab.webState].viewController; viewController.view.frame = [self ntpFrameForWebState:tab.webState]; + // TODO(crbug.com/873729): For a newly created WebState, the session will + // not be restored until LoadIfNecessary call. Remove when fixed. + tab.webState->GetNavigationManager()->LoadIfNecessary(); self.browserContainerViewController.contentViewController = viewController; } else {
diff --git a/ios/chrome/browser/ui/side_swipe/BUILD.gn b/ios/chrome/browser/ui/side_swipe/BUILD.gn index 333368ed..6dde15c 100644 --- a/ios/chrome/browser/ui/side_swipe/BUILD.gn +++ b/ios/chrome/browser/ui/side_swipe/BUILD.gn
@@ -36,6 +36,7 @@ "//ios/chrome/browser/ui/tabs/requirements", "//ios/chrome/browser/ui/toolbar/public", "//ios/chrome/browser/web", + "//ios/chrome/browser/web_state_list", "//ios/chrome/common", "//ios/web/public", "//ui/base",
diff --git a/ios/chrome/browser/ui/side_swipe/side_swipe_controller.mm b/ios/chrome/browser/ui/side_swipe/side_swipe_controller.mm index d7e2b842..dc5d335010 100644 --- a/ios/chrome/browser/ui/side_swipe/side_swipe_controller.mm +++ b/ios/chrome/browser/ui/side_swipe/side_swipe_controller.mm
@@ -28,6 +28,7 @@ #include "ios/chrome/browser/ui/util/ui_util.h" #import "ios/chrome/browser/web/page_placeholder_tab_helper.h" #import "ios/chrome/browser/web/web_navigation_util.h" +#import "ios/chrome/browser/web_state_list/web_state_list.h" #import "ios/web/public/navigation_item.h" #import "ios/web/public/web_client.h" #import "ios/web/public/web_state/web_state_observer_bridge.h" @@ -407,10 +408,14 @@ } - (BOOL)canNavigate:(BOOL)goBack { - if (goBack && [[model_ currentTab] canGoBack]) { + WebStateList* webStateList = model_.webStateList; + if (!webStateList || !webStateList->GetActiveWebState()) + return NO; + web::WebState* webState = webStateList->GetActiveWebState(); + if (goBack && webState->GetNavigationManager()->CanGoBack()) { return YES; } - if (!goBack && [[model_ currentTab] canGoForward]) { + if (!goBack && webState->GetNavigationManager()->CanGoForward()) { return YES; } return NO; @@ -455,11 +460,14 @@ animatedFullscreenDisabler_ = nullptr; } - __weak Tab* weakCurrentTab = [model_ currentTab]; [pageSideSwipeView_ handleHorizontalPan:gesture onOverThresholdCompletion:^{ + WebStateList* webStateList = model_.webStateList; + web::WebState* webState = nullptr; + if (webStateList) { + webState = webStateList->GetActiveWebState(); + } BOOL wantsBack = IsSwipingBack(gesture.direction); - web::WebState* webState = [weakCurrentTab webState]; if (webState) { if (wantsBack) { web_navigation_util::GoBack(webState);
diff --git a/ios/chrome/browser/ui/tab_grid/grid/grid_cell.mm b/ios/chrome/browser/ui/tab_grid/grid/grid_cell.mm index ef39d77f..070ffdf 100644 --- a/ios/chrome/browser/ui/tab_grid/grid/grid_cell.mm +++ b/ios/chrome/browser/ui/tab_grid/grid/grid_cell.mm
@@ -61,6 +61,22 @@ @end @implementation GridCell +// Public properties. +@synthesize delegate = _delegate; +@synthesize theme = _theme; +@synthesize itemIdentifier = _itemIdentifier; +@synthesize icon = _icon; +@synthesize snapshot = _snapshot; +@synthesize title = _title; +@synthesize titleHidden = _titleHidden; +// Private properties. +@synthesize topBarHeight = _topBarHeight; +@synthesize topBar = _topBar; +@synthesize snapshotView = _snapshotView; +@synthesize titleLabel = _titleLabel; +@synthesize closeIconView = _closeIconView; +@synthesize closeTapTargetButton = _closeTapTargetButton; +@synthesize border = _border; // |-dequeueReusableCellWithReuseIdentifier:forIndexPath:| calls this method to // initialize a cell. @@ -91,11 +107,15 @@ _snapshotView = snapshotView; _closeTapTargetButton = closeTapTargetButton; + _topBarHeight = + [topBar.heightAnchor constraintEqualToConstant:kGridCellHeaderHeight]; + NSArray* constraints = @[ [topBar.topAnchor constraintEqualToAnchor:contentView.topAnchor], [topBar.leadingAnchor constraintEqualToAnchor:contentView.leadingAnchor], [topBar.trailingAnchor constraintEqualToAnchor:contentView.trailingAnchor], + _topBarHeight, [snapshotView.topAnchor constraintEqualToAnchor:topBar.bottomAnchor], [snapshotView.leadingAnchor constraintEqualToAnchor:contentView.leadingAnchor], @@ -254,8 +274,6 @@ _closeIconView = closeIconView; _accessibilityConstraints = @[ - [topBar.heightAnchor - constraintEqualToConstant:kGridCellHeaderAccessibilityHeight], [titleLabel.leadingAnchor constraintEqualToAnchor:topBar.leadingAnchor constant:kGridCellHeaderLeadingInset], @@ -264,7 +282,6 @@ ]; _nonAccessibilityConstraints = @[ - [topBar.heightAnchor constraintEqualToConstant:kGridCellHeaderHeight], [iconView.leadingAnchor constraintEqualToAnchor:topBar.leadingAnchor constant:kGridCellHeaderLeadingInset], @@ -279,11 +296,10 @@ NSArray* constraints = @[ [titleLabel.centerYAnchor constraintEqualToAnchor:topBar.centerYAnchor], [titleLabel.trailingAnchor - constraintEqualToAnchor:closeIconView.leadingAnchor - constant:-kGridCellTitleLabelContentInset], - [closeIconView.topAnchor - constraintEqualToAnchor:topBar.topAnchor - constant:kGridCellCloseButtonContentInset], + constraintLessThanOrEqualToAnchor:closeIconView.leadingAnchor + constant:-kGridCellTitleLabelContentInset], + [closeIconView.topAnchor constraintEqualToAnchor:topBar.topAnchor], + [closeIconView.bottomAnchor constraintEqualToAnchor:topBar.bottomAnchor], [closeIconView.trailingAnchor constraintEqualToAnchor:topBar.trailingAnchor constant:-kGridCellCloseButtonContentInset], @@ -308,11 +324,9 @@ - (void)updateTopBar { if (UIContentSizeCategoryIsAccessibilityCategory( self.traitCollection.preferredContentSizeCategory)) { - self.titleLabel.numberOfLines = 2; [NSLayoutConstraint deactivateConstraints:_nonAccessibilityConstraints]; [NSLayoutConstraint activateConstraints:_accessibilityConstraints]; } else { - self.titleLabel.numberOfLines = 1; [NSLayoutConstraint deactivateConstraints:_accessibilityConstraints]; [NSLayoutConstraint activateConstraints:_nonAccessibilityConstraints]; }
diff --git a/ios/chrome/browser/ui/tab_grid/grid/grid_constants.h b/ios/chrome/browser/ui/tab_grid/grid/grid_constants.h index 9fe18a6bb..27bdb3d 100644 --- a/ios/chrome/browser/ui/tab_grid/grid/grid_constants.h +++ b/ios/chrome/browser/ui/tab_grid/grid/grid_constants.h
@@ -75,12 +75,10 @@ extern const CGSize kGridCellSizeSmall; extern const CGSize kGridCellSizeMedium; extern const CGSize kGridCellSizeLarge; -extern const CGSize kGridCellSizeAccessibility; extern const CGFloat kGridCellCornerRadius; extern const CGFloat kGridCellIconCornerRadius; // The cell header contains the icon, title, and close button. extern const CGFloat kGridCellHeaderHeight; -extern const CGFloat kGridCellHeaderAccessibilityHeight; extern const CGFloat kGridCellHeaderLeadingInset; extern const CGFloat kGridCellCloseTapTargetWidthHeight; extern const CGFloat kGridCellCloseButtonContentInset;
diff --git a/ios/chrome/browser/ui/tab_grid/grid/grid_constants.mm b/ios/chrome/browser/ui/tab_grid/grid/grid_constants.mm index 04fae2837..5c6310f7 100644 --- a/ios/chrome/browser/ui/tab_grid/grid/grid_constants.mm +++ b/ios/chrome/browser/ui/tab_grid/grid/grid_constants.mm
@@ -69,12 +69,10 @@ const CGSize kGridCellSizeSmall = CGSize{144.0f, 168.0f}; const CGSize kGridCellSizeMedium = CGSize{168.0f, 202.0f}; const CGSize kGridCellSizeLarge = CGSize{228.0f, 256.0f}; -const CGSize kGridCellSizeAccessibility = CGSize{288.0f, 336.0f}; const CGFloat kGridCellCornerRadius = 13.0f; const CGFloat kGridCellIconCornerRadius = 3.0f; // The cell header contains the icon, title, and close button. const CGFloat kGridCellHeaderHeight = 32.0f; -const CGFloat kGridCellHeaderAccessibilityHeight = 108.0f; const CGFloat kGridCellHeaderLeadingInset = 9.0f; const CGFloat kGridCellCloseTapTargetWidthHeight = 44.0f; const CGFloat kGridCellCloseButtonContentInset = 8.5f;
diff --git a/ios/chrome/browser/ui/tab_grid/grid/grid_layout.mm b/ios/chrome/browser/ui/tab_grid/grid/grid_layout.mm index 6ffd1a7..16895e7 100644 --- a/ios/chrome/browser/ui/tab_grid/grid/grid_layout.mm +++ b/ios/chrome/browser/ui/tab_grid/grid/grid_layout.mm
@@ -39,13 +39,8 @@ UIUserInterfaceSizeClass verticalSizeClass = self.collectionView.traitCollection.verticalSizeClass; CGFloat width = CGRectGetWidth(self.collectionView.bounds); - if (UIContentSizeCategoryIsAccessibilityCategory( - UIApplication.sharedApplication.preferredContentSizeCategory)) { - self.itemSize = kGridCellSizeAccessibility; - self.sectionInset = kGridLayoutInsetsRegularCompact; - self.minimumLineSpacing = kGridLayoutLineSpacingRegularCompact; - } else if (horizontalSizeClass == UIUserInterfaceSizeClassCompact && - verticalSizeClass == UIUserInterfaceSizeClassCompact) { + if (horizontalSizeClass == UIUserInterfaceSizeClassCompact && + verticalSizeClass == UIUserInterfaceSizeClassCompact) { self.itemSize = kGridCellSizeSmall; if (width < kGridLayoutCompactCompactLimitedWidth) { self.sectionInset = kGridLayoutInsetsCompactCompactLimitedWidth;
diff --git a/ios/chrome/browser/ui/tab_grid/grid/grid_view_controller.mm b/ios/chrome/browser/ui/tab_grid/grid/grid_view_controller.mm index 6a98c63b..44893f6 100644 --- a/ios/chrome/browser/ui/tab_grid/grid/grid_view_controller.mm +++ b/ios/chrome/browser/ui/tab_grid/grid/grid_view_controller.mm
@@ -100,8 +100,6 @@ return self; } -#pragma mark - UIViewController - - (void)loadView { self.defaultLayout = [[GridLayout alloc] init]; self.reorderingLayout = [[GridReorderingLayout alloc] init]; @@ -167,13 +165,6 @@ [super viewWillDisappear:animated]; } -#pragma mark - UITraitEnvironment - -- (void)traitCollectionDidChange:(UITraitCollection*)previousTraitCollection { - [super traitCollectionDidChange:previousTraitCollection]; - [self.collectionView.collectionViewLayout invalidateLayout]; -} - #pragma mark - Public - (UIScrollView*)gridView {
diff --git a/ios/chrome/browser/ui/webui/inspect/inspect_ui_egtest.mm b/ios/chrome/browser/ui/webui/inspect/inspect_ui_egtest.mm index 47a9efbb..5cc78f3 100644 --- a/ios/chrome/browser/ui/webui/inspect/inspect_ui_egtest.mm +++ b/ios/chrome/browser/ui/webui/inspect/inspect_ui_egtest.mm
@@ -2,11 +2,16 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#import <Foundation/Foundation.h> #import <XCTest/XCTest.h> #import "base/strings/sys_string_conversions.h" #include "ios/chrome/browser/chrome_url_constants.h" +#import "ios/chrome/test/app/chrome_test_util.h" +#import "ios/chrome/test/app/web_view_interaction_test_util.h" +#import "ios/chrome/test/earl_grey/chrome_actions.h" #import "ios/chrome/test/earl_grey/chrome_earl_grey.h" +#import "ios/chrome/test/earl_grey/chrome_matchers.h" #import "ios/chrome/test/earl_grey/chrome_test_case.h" #include "ios/web/public/test/element_selector.h" @@ -14,40 +19,302 @@ #error "This file requires ARC support." #endif -namespace { -// Id of the "Start Logging" button. -const char kStartLoggingButtonId[] = "start-logging"; -// Id of the "Stop Logging" button. -const char kStopLoggingButtonId[] = "stop-logging"; -} // namespace - +using chrome_test_util::GetCurrentWebState; +using chrome_test_util::TapWebViewElementWithIdInIframe; using web::test::ElementSelector; +namespace { +// Directory containing the |kLogoPagePath| and |kLogoPageImageSourcePath| +// resources. +const char kServerFilesDir[] = "ios/testing/data/http_server_files/"; + +// Id of the "Start Logging" button. +NSString* const kStartLoggingButtonId = @"start-logging"; +// Id of the "Stop Logging" button. +NSString* const kStopLoggingButtonId = @"stop-logging"; + +// Test page continaing buttons to test console logging. +const char kConsolePage[] = "/console_with_iframe.html"; +// Id of the console page button to log a debug message. +NSString* const kDebugMessageButtonId = @"debug"; +// Id of the console page button to log an error. +NSString* const kErrorMessageButtonId = @"error"; +// Id of the console page button to log an info message. +NSString* const kInfoMessageButtonId = @"info"; +// Id of the console page button to log a message. +NSString* const kLogMessageButtonId = @"log"; +// Id of the console page button to log a warning. +NSString* const kWarningMessageButtonId = @"warn"; + +// Label for debug console messages. +const char kDebugMessageLabel[] = "DEBUG"; +// Label for error console messages. +const char kErrorMessageLabel[] = "ERROR"; +// Label for info console messages. +const char kInfoMessageLabel[] = "INFO"; +// Label for log console messages. +const char kLogMessageLabel[] = "LOG"; +// Label for warning console messages. +const char kWarningMessageLabel[] = "WARN"; + +// Text of the message emitted from the |kDebugMessageButtonId| button on +// |kConsolePage|. +const char kDebugMessageText[] = "This is a debug message."; +// Text of the message emitted from the |kErrorMessageButtonId| button on +// |kConsolePage|. +const char kErrorMessageText[] = "This is an error message."; +// Text of the message emitted from the |kInfoMessageButtonId| button on +// |kConsolePage|. +const char kInfoMessageText[] = "This is an informative message."; +// Text of the message emitted from the |kLogMessageButtonId| button on +// |kConsolePage|. +const char kLogMessageText[] = "This log is very round."; +// Text of the message emitted from the |kWarningMessageButtonId| button on +// |kConsolePage|. +const char kWarningMessageText[] = "This is a warning message."; + +// Text of the message emitted from the |kDebugMessageButtonId| button within +// the iframe on |kConsolePage|. +const char kIFrameDebugMessageText[] = "This is an iframe debug message."; +// Text of the message emitted from the |kErrorMessageButtonId| button within +// the iframe on |kConsolePage|. +const char kIFrameErrorMessageText[] = "This is an iframe error message."; +// Text of the message emitted from the |kInfoMessageButtonId| button within the +// iframe on |kConsolePage|. +const char kIFrameInfoMessageText[] = "This is an iframe informative message."; +// Text of the message emitted from the |kLogMessageButtonId| button within the +// iframe on |kConsolePage|. +const char kIFrameLogMessageText[] = "This iframe log is very round."; +// Text of the message emitted from the |kWarningMessageButtonId| button within +// the iframe on |kConsolePage|. +const char kIFrameWarningMessageText[] = "This is an iframe warning message."; + +web::test::ElementSelector StartLoggingButton() { + return ElementSelector::ElementSelectorId( + base::SysNSStringToUTF8(kStartLoggingButtonId)); +} + +} // namespace + // Test case for chrome://inspect WebUI page. @interface InspectUITestCase : ChromeTestCase @end @implementation InspectUITestCase +- (void)setUp { + [super setUp]; + self.testServer->ServeFilesFromSourceDirectory( + base::FilePath(kServerFilesDir)); + GREYAssertTrue(self.testServer->Start(), @"Server did not start."); +} + // Tests that chrome://inspect allows the user to enable and disable logging. - (void)testStartStopLogging { [ChromeEarlGrey loadURL:GURL(kChromeUIInspectURL)]; - ElementSelector startLoggingButton = - ElementSelector::ElementSelectorId(kStartLoggingButtonId); - [ChromeEarlGrey waitForWebViewContainingElement:startLoggingButton]; + [ChromeEarlGrey waitForWebViewContainingElement:StartLoggingButton()]; - [ChromeEarlGrey - tapWebViewElementWithID:base::SysUTF8ToNSString(kStartLoggingButtonId)]; + [ChromeEarlGrey tapWebViewElementWithID:kStartLoggingButtonId]; - ElementSelector stopLoggingButton = - ElementSelector::ElementSelectorId(kStopLoggingButtonId); + ElementSelector stopLoggingButton = ElementSelector::ElementSelectorId( + base::SysNSStringToUTF8(kStopLoggingButtonId)); [ChromeEarlGrey waitForWebViewContainingElement:stopLoggingButton]; - [ChromeEarlGrey - tapWebViewElementWithID:base::SysUTF8ToNSString(kStopLoggingButtonId)]; + [ChromeEarlGrey tapWebViewElementWithID:kStopLoggingButtonId]; - [ChromeEarlGrey waitForWebViewContainingElement:startLoggingButton]; + [ChromeEarlGrey waitForWebViewContainingElement:StartLoggingButton()]; +} + +// Tests that log messages from a page's main frame are displayed. +- (void)testMainFrameLogging { + [ChromeEarlGrey loadURL:GURL(kChromeUIInspectURL)]; + + // Start logging. + [ChromeEarlGrey waitForWebViewContainingElement:StartLoggingButton()]; + [ChromeEarlGrey tapWebViewElementWithID:kStartLoggingButtonId]; + + // Open console test page. + [ChromeEarlGrey openNewTab]; + const GURL consoleTestsURL = self.testServer->GetURL(kConsolePage); + [ChromeEarlGrey loadURL:consoleTestsURL]; + std::string debugButtonID = base::SysNSStringToUTF8(kDebugMessageButtonId); + [ChromeEarlGrey + waitForWebViewContainingElement:ElementSelector::ElementSelectorId( + debugButtonID)]; + + // Log messages. + [ChromeEarlGrey tapWebViewElementWithID:kDebugMessageButtonId]; + [ChromeEarlGrey tapWebViewElementWithID:kErrorMessageButtonId]; + [ChromeEarlGrey tapWebViewElementWithID:kInfoMessageButtonId]; + [ChromeEarlGrey tapWebViewElementWithID:kLogMessageButtonId]; + [ChromeEarlGrey tapWebViewElementWithID:kWarningMessageButtonId]; + + [ChromeEarlGrey closeCurrentTab]; + // Validate messages and labels are displayed. + [ChromeEarlGrey waitForWebViewContainingText:kDebugMessageLabel]; + [ChromeEarlGrey waitForWebViewContainingText:kDebugMessageText]; + [ChromeEarlGrey waitForWebViewContainingText:kErrorMessageLabel]; + [ChromeEarlGrey waitForWebViewContainingText:kErrorMessageText]; + [ChromeEarlGrey waitForWebViewContainingText:kInfoMessageLabel]; + [ChromeEarlGrey waitForWebViewContainingText:kInfoMessageText]; + [ChromeEarlGrey waitForWebViewContainingText:kLogMessageLabel]; + [ChromeEarlGrey waitForWebViewContainingText:kLogMessageText]; + [ChromeEarlGrey waitForWebViewContainingText:kWarningMessageLabel]; + [ChromeEarlGrey waitForWebViewContainingText:kWarningMessageText]; +} + +// Tests that log messages from an iframe are displayed. +- (void)testIframeLogging { + [ChromeEarlGrey loadURL:GURL(kChromeUIInspectURL)]; + + // Start logging. + [ChromeEarlGrey waitForWebViewContainingElement:StartLoggingButton()]; + [ChromeEarlGrey tapWebViewElementWithID:kStartLoggingButtonId]; + + // Open console test page. + [ChromeEarlGrey openNewTab]; + const GURL consoleTestsURL = self.testServer->GetURL(kConsolePage); + [ChromeEarlGrey loadURL:consoleTestsURL]; + + std::string debugButtonID = base::SysNSStringToUTF8(kDebugMessageButtonId); + [ChromeEarlGrey + waitForWebViewContainingElement:ElementSelector::ElementSelectorId( + debugButtonID)]; + + // Log messages. + GREYAssertTrue(TapWebViewElementWithIdInIframe(debugButtonID), + @"Failed to tap debug button."); + + std::string errorButtonID = base::SysNSStringToUTF8(kErrorMessageButtonId); + GREYAssertTrue(TapWebViewElementWithIdInIframe(errorButtonID), + @"Failed to tap error button."); + + std::string infoButtonID = base::SysNSStringToUTF8(kInfoMessageButtonId); + GREYAssertTrue(TapWebViewElementWithIdInIframe(infoButtonID), + @"Failed to tap info button."); + + std::string logButtonID = base::SysNSStringToUTF8(kLogMessageButtonId); + GREYAssertTrue(TapWebViewElementWithIdInIframe(logButtonID), + @"Failed to tap log button."); + + std::string warnButtonID = base::SysNSStringToUTF8(kWarningMessageButtonId); + GREYAssertTrue(TapWebViewElementWithIdInIframe(warnButtonID), + @"Failed to tap warn button."); + + [ChromeEarlGrey closeCurrentTab]; + // Validate messages and labels are displayed. + [ChromeEarlGrey waitForWebViewContainingText:kDebugMessageLabel]; + [ChromeEarlGrey waitForWebViewContainingText:kIFrameDebugMessageText]; + [ChromeEarlGrey waitForWebViewContainingText:kErrorMessageLabel]; + [ChromeEarlGrey waitForWebViewContainingText:kIFrameErrorMessageText]; + [ChromeEarlGrey waitForWebViewContainingText:kInfoMessageLabel]; + [ChromeEarlGrey waitForWebViewContainingText:kIFrameInfoMessageText]; + [ChromeEarlGrey waitForWebViewContainingText:kLogMessageLabel]; + [ChromeEarlGrey waitForWebViewContainingText:kIFrameLogMessageText]; + [ChromeEarlGrey waitForWebViewContainingText:kWarningMessageLabel]; + [ChromeEarlGrey waitForWebViewContainingText:kIFrameWarningMessageText]; +} + +// Tests that log messages are correctly displayed from multiple tabs. +- (void)testLoggingFromMultipleTabs { + [ChromeEarlGrey loadURL:GURL(kChromeUIInspectURL)]; + + // Start logging. + [ChromeEarlGrey waitForWebViewContainingElement:StartLoggingButton()]; + [ChromeEarlGrey tapWebViewElementWithID:kStartLoggingButtonId]; + + // Open console test page. + [ChromeEarlGrey openNewTab]; + const GURL consoleTestsURL = self.testServer->GetURL(kConsolePage); + [ChromeEarlGrey loadURL:consoleTestsURL]; + std::string logButtonID = base::SysNSStringToUTF8(kLogMessageButtonId); + [ChromeEarlGrey + waitForWebViewContainingElement:ElementSelector::ElementSelectorId( + logButtonID)]; + + // Log a message and verify it is displayed. + [ChromeEarlGrey tapWebViewElementWithID:kDebugMessageButtonId]; + [ChromeEarlGrey closeCurrentTab]; + [ChromeEarlGrey waitForWebViewContainingText:kDebugMessageLabel]; + [ChromeEarlGrey waitForWebViewContainingText:kDebugMessageText]; + + // Open console test page again. + [ChromeEarlGrey openNewTab]; + [ChromeEarlGrey loadURL:consoleTestsURL]; + [ChromeEarlGrey + waitForWebViewContainingElement:ElementSelector::ElementSelectorId( + logButtonID)]; + + // Log another message and verify it is displayed. + [ChromeEarlGrey tapWebViewElementWithID:kLogMessageButtonId]; + [ChromeEarlGrey closeCurrentTab]; + [ChromeEarlGrey waitForWebViewContainingText:kLogMessageLabel]; + [ChromeEarlGrey waitForWebViewContainingText:kLogMessageText]; + + // Ensure the log from the first tab still exists. + [ChromeEarlGrey waitForWebViewContainingText:kDebugMessageLabel]; + [ChromeEarlGrey waitForWebViewContainingText:kDebugMessageText]; +} + +// Tests that messages are cleared after stopping logging. +- (void)testMessagesClearedOnStopLogging { + [ChromeEarlGrey loadURL:GURL(kChromeUIInspectURL)]; + + // Start logging. + [ChromeEarlGrey waitForWebViewContainingElement:StartLoggingButton()]; + [ChromeEarlGrey tapWebViewElementWithID:kStartLoggingButtonId]; + + // Open console test page. + [ChromeEarlGrey openNewTab]; + const GURL consoleTestsURL = self.testServer->GetURL(kConsolePage); + [ChromeEarlGrey loadURL:consoleTestsURL]; + std::string logButtonID = base::SysNSStringToUTF8(kLogMessageButtonId); + [ChromeEarlGrey + waitForWebViewContainingElement:ElementSelector::ElementSelectorId( + logButtonID)]; + + // Log a message and verify it is displayed. + [ChromeEarlGrey tapWebViewElementWithID:kDebugMessageButtonId]; + [ChromeEarlGrey closeCurrentTab]; + [ChromeEarlGrey waitForWebViewContainingText:kDebugMessageLabel]; + [ChromeEarlGrey waitForWebViewContainingText:kDebugMessageText]; + + // Stop logging. + [ChromeEarlGrey tapWebViewElementWithID:kStopLoggingButtonId]; + // Ensure message was cleared. + [ChromeEarlGrey waitForWebViewNotContainingText:kDebugMessageLabel]; + [ChromeEarlGrey waitForWebViewNotContainingText:kDebugMessageText]; +} + +// Tests that messages are cleared after a page reload. +- (void)testMessagesClearedOnReload { + [ChromeEarlGrey loadURL:GURL(kChromeUIInspectURL)]; + + // Start logging. + [ChromeEarlGrey waitForWebViewContainingElement:StartLoggingButton()]; + [ChromeEarlGrey tapWebViewElementWithID:kStartLoggingButtonId]; + + // Open console test page. + [ChromeEarlGrey openNewTab]; + const GURL consoleTestsURL = self.testServer->GetURL(kConsolePage); + [ChromeEarlGrey loadURL:consoleTestsURL]; + std::string logButtonID = base::SysNSStringToUTF8(kLogMessageButtonId); + [ChromeEarlGrey + waitForWebViewContainingElement:ElementSelector::ElementSelectorId( + logButtonID)]; + + // Log a message and verify it is displayed. + [ChromeEarlGrey tapWebViewElementWithID:kDebugMessageButtonId]; + [ChromeEarlGrey closeCurrentTab]; + [ChromeEarlGrey waitForWebViewContainingText:kDebugMessageLabel]; + [ChromeEarlGrey waitForWebViewContainingText:kDebugMessageText]; + + // Reload page. + [ChromeEarlGrey reload]; + // Ensure message was cleared. + [ChromeEarlGrey waitForWebViewNotContainingText:kDebugMessageLabel]; + [ChromeEarlGrey waitForWebViewNotContainingText:kDebugMessageText]; } @end
diff --git a/ios/chrome/test/app/web_view_interaction_test_util.h b/ios/chrome/test/app/web_view_interaction_test_util.h index cc122969..608822a 100644 --- a/ios/chrome/test/app/web_view_interaction_test_util.h +++ b/ios/chrome/test/app/web_view_interaction_test_util.h
@@ -18,6 +18,12 @@ // was successful. bool TapWebViewElementWithId(const std::string& element_id) WARN_UNUSED_RESULT; +// Attempts to tap the element with |element_id| within window.frames[0] of the +// current WebState using a JavaScript click() event. This only works on +// same-origin iframes. Returns a bool indicating if the tap was successful. +bool TapWebViewElementWithIdInIframe(const std::string& element_id) + WARN_UNUSED_RESULT; + // Attempts to tap the element with |element_id| in the current WebState // using a JavaScript click() event. |error| can be nil. bool TapWebViewElementWithId(const std::string& element_id,
diff --git a/ios/chrome/test/app/web_view_interaction_test_util.mm b/ios/chrome/test/app/web_view_interaction_test_util.mm index 8f872c5..1f5713f8 100644 --- a/ios/chrome/test/app/web_view_interaction_test_util.mm +++ b/ios/chrome/test/app/web_view_interaction_test_util.mm
@@ -17,6 +17,11 @@ return web::test::TapWebViewElementWithId(GetCurrentWebState(), element_id); } +bool TapWebViewElementWithIdInIframe(const std::string& element_id) { + return web::test::TapWebViewElementWithIdInIframe(GetCurrentWebState(), + element_id); +} + bool TapWebViewElementWithId(const std::string& element_id, NSError* __autoreleasing* error) { return web::test::TapWebViewElementWithId(GetCurrentWebState(), element_id,
diff --git a/ios/testing/BUILD.gn b/ios/testing/BUILD.gn index 0cf33c8..f936550 100644 --- a/ios/testing/BUILD.gn +++ b/ios/testing/BUILD.gn
@@ -70,6 +70,8 @@ "data/http_server_files/browsing_prevent_default_test_page.html", "data/http_server_files/chromium_logo.png", "data/http_server_files/chromium_logo_page.html", + "data/http_server_files/console.html", + "data/http_server_files/console_with_iframe.html", "data/http_server_files/destination.html", "data/http_server_files/fullscreen.html", "data/http_server_files/generic.pkpass",
diff --git a/ios/testing/data/http_server_files/console.html b/ios/testing/data/http_server_files/console.html new file mode 100644 index 0000000..347baf5 --- /dev/null +++ b/ios/testing/data/http_server_files/console.html
@@ -0,0 +1,20 @@ +<!DOCTYPE html> +<!-- 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. + +This file contains buttons which send log messages to the JavaScript console. It +is embedded as an iframe on console.html. +--> + +<html> +<body> + +<button id="debug" onclick="console.debug('This is an iframe debug message.')">Debug</button> +<button id="error" onclick="console.error('This is an iframe error message.')">Error</button> +<button id="info" onclick="console.info('This is an iframe informative message.')">Info</button> +<button id="log" onclick="console.log('This iframe log is very round.')">Log</button> +<button id="warn" onclick="console.warn('This is an iframe warning message.')">Warn</button> + +</body> +</html> \ No newline at end of file
diff --git a/ios/testing/data/http_server_files/console_with_iframe.html b/ios/testing/data/http_server_files/console_with_iframe.html new file mode 100644 index 0000000..b205519 --- /dev/null +++ b/ios/testing/data/http_server_files/console_with_iframe.html
@@ -0,0 +1,21 @@ +<!DOCTYPE html> +<!-- 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. + +This file contains buttons which send log messages to the JavaScript console. +--> + +<html> +<body> + +<button id="debug" onclick="console.debug('This is a debug message.')">Debug</button> +<button id="error" onclick="console.error('This is an error message.')">Error</button> +<button id="info" onclick="console.info('This is an informative message.')">Info</button> +<button id="log" onclick="console.log('This log is very round.')">Log</button> +<button id="warn" onclick="console.warn('This is a warning message.')">Warn</button> + +<iframe src="console.html"></iframe> + +</body> +</html> \ No newline at end of file
diff --git a/ios/third_party/earl_grey2/BUILD.gn b/ios/third_party/earl_grey2/BUILD.gn index 8633180..0d8f4051 100644 --- a/ios/third_party/earl_grey2/BUILD.gn +++ b/ios/third_party/earl_grey2/BUILD.gn
@@ -177,7 +177,7 @@ ios_framework_bundle("app_framework") { testonly = true - output_name = "EarlGreyAppFramework" + output_name = "AppFramework" info_plist = "Info.plist" sources = [
diff --git a/media/blink/video_frame_compositor.cc b/media/blink/video_frame_compositor.cc index 97958d8..32ccd6f 100644 --- a/media/blink/video_frame_compositor.cc +++ b/media/blink/video_frame_compositor.cc
@@ -75,7 +75,6 @@ base::TimeTicks local_surface_id_allocation_time, VideoRotation rotation, bool force_submit, - bool is_opaque, blink::WebFrameSinkDestroyedCallback frame_sink_destroyed_callback) { DCHECK(task_runner_->BelongsToCurrentThread()); @@ -85,7 +84,6 @@ submitter_->SetRotation(rotation); submitter_->SetForceSubmit(force_submit); - submitter_->SetIsOpaque(is_opaque); submitter_->EnableSubmission(id, local_surface_id_allocation_time, std::move(frame_sink_destroyed_callback)); client_ = submitter_.get(); @@ -294,11 +292,6 @@ submitter_->SetForceSubmit(force_submit); } -void VideoFrameCompositor::UpdateIsOpaque(bool is_opaque) { - DCHECK(task_runner_->BelongsToCurrentThread()); - submitter_->SetIsOpaque(is_opaque); -} - void VideoFrameCompositor::BackgroundRender() { DCHECK(task_runner_->BelongsToCurrentThread()); const base::TimeTicks now = tick_clock_->NowTicks();
diff --git a/media/blink/video_frame_compositor.h b/media/blink/video_frame_compositor.h index 2da9bc6..a13801e 100644 --- a/media/blink/video_frame_compositor.h +++ b/media/blink/video_frame_compositor.h
@@ -83,7 +83,6 @@ base::TimeTicks local_surface_id_allocation_time, VideoRotation rotation, bool force_submit, - bool is_opaque, blink::WebFrameSinkDestroyedCallback frame_sink_destroyed_callback); // cc::VideoFrameProvider implementation. These methods must be called on the @@ -136,9 +135,6 @@ // Notifies the |submitter_| that the frames must be submitted. void SetForceSubmit(bool force_submit); - // Updates the opacity information for frames given to |submitter_|. - void UpdateIsOpaque(bool is_opaque); - void set_tick_clock_for_testing(const base::TickClock* tick_clock) { tick_clock_ = tick_clock; }
diff --git a/media/blink/video_frame_compositor_unittest.cc b/media/blink/video_frame_compositor_unittest.cc index 823a038..3044409 100644 --- a/media/blink/video_frame_compositor_unittest.cc +++ b/media/blink/video_frame_compositor_unittest.cc
@@ -37,7 +37,6 @@ MOCK_CONST_METHOD0(IsDrivingFrameUpdates, bool(void)); MOCK_METHOD1(Initialize, void(cc::VideoFrameProvider*)); MOCK_METHOD1(SetRotation, void(media::VideoRotation)); - MOCK_METHOD1(SetIsOpaque, void(bool)); MOCK_METHOD1(SetIsSurfaceVisible, void(bool)); MOCK_METHOD1(SetIsPageVisible, void(bool)); MOCK_METHOD1(SetForceSubmit, void(bool)); @@ -79,10 +78,9 @@ SetRotation(Eq(media::VideoRotation::VIDEO_ROTATION_90))); EXPECT_CALL(*submitter_, SetForceSubmit(false)); EXPECT_CALL(*submitter_, EnableSubmission(Eq(viz::SurfaceId()), _, _)); - EXPECT_CALL(*submitter_, SetIsOpaque(true)); compositor_->EnableSubmission(viz::SurfaceId(), base::TimeTicks(), media::VideoRotation::VIDEO_ROTATION_90, - false, true, base::BindRepeating([] {})); + false, base::BindRepeating([] {})); } compositor_->set_tick_clock_for_testing(&tick_clock_);
diff --git a/media/blink/webmediaplayer_impl.cc b/media/blink/webmediaplayer_impl.cc index 0b87ac2b5..0dd569b 100644 --- a/media/blink/webmediaplayer_impl.cc +++ b/media/blink/webmediaplayer_impl.cc
@@ -1875,7 +1875,7 @@ base::Unretained(compositor_.get()), bridge_->GetSurfaceId(), bridge_->GetLocalSurfaceIdAllocationTime(), pipeline_metadata_.video_decoder_config.video_rotation(), - IsInPictureInPicture(), opaque_, + IsInPictureInPicture(), BindToCurrentLoop(base::BindRepeating( &WebMediaPlayerImpl::OnFrameSinkDestroyed, AsWeakPtr())))); bridge_->SetContentsOpaque(opaque_); @@ -2151,16 +2151,10 @@ DCHECK_NE(ready_state_, WebMediaPlayer::kReadyStateHaveNothing); opaque_ = opaque; - if (!surface_layer_for_video_enabled_) { - if (video_layer_) - video_layer_->SetContentsOpaque(opaque_); - } else if (bridge_->GetCcLayer()) { + if (!surface_layer_for_video_enabled_ && video_layer_) + video_layer_->SetContentsOpaque(opaque_); + else if (bridge_->GetCcLayer()) bridge_->SetContentsOpaque(opaque_); - vfc_task_runner_->PostTask( - FROM_HERE, - base::BindOnce(&VideoFrameCompositor::UpdateIsOpaque, - base::Unretained(compositor_.get()), opaque_)); - } } void WebMediaPlayerImpl::OnAudioConfigChange(const AudioDecoderConfig& config) {
diff --git a/media/blink/webmediaplayer_impl_unittest.cc b/media/blink/webmediaplayer_impl_unittest.cc index 5ca0364..ec47046 100644 --- a/media/blink/webmediaplayer_impl_unittest.cc +++ b/media/blink/webmediaplayer_impl_unittest.cc
@@ -340,12 +340,11 @@ void SetOnNewProcessedFrameCallback(OnNewProcessedFrameCB cb) override {} MOCK_METHOD1(SetIsPageVisible, void(bool)); MOCK_METHOD0(GetCurrentFrameAndUpdateIfStale, scoped_refptr<VideoFrame>()); - MOCK_METHOD6(EnableSubmission, + MOCK_METHOD5(EnableSubmission, void(const viz::SurfaceId&, base::TimeTicks, media::VideoRotation, bool, - bool, blink::WebFrameSinkDestroyedCallback)); }; @@ -907,7 +906,7 @@ .WillOnce(ReturnRef(surface_id_)); EXPECT_CALL(*surface_layer_bridge_ptr_, GetLocalSurfaceIdAllocationTime()) .WillOnce(Return(base::TimeTicks())); - EXPECT_CALL(*compositor_, EnableSubmission(_, _, _, _, false, _)); + EXPECT_CALL(*compositor_, EnableSubmission(_, _, _, _, _)); EXPECT_CALL(*surface_layer_bridge_ptr_, SetContentsOpaque(false)); } @@ -939,7 +938,7 @@ .WillOnce(ReturnRef(surface_id_)); EXPECT_CALL(*surface_layer_bridge_ptr_, GetLocalSurfaceIdAllocationTime()) .WillOnce(Return(base::TimeTicks())); - EXPECT_CALL(*compositor_, EnableSubmission(_, _, _, _, false, _)); + EXPECT_CALL(*compositor_, EnableSubmission(_, _, _, _, _)); EXPECT_CALL(*surface_layer_bridge_ptr_, SetContentsOpaque(false)); } @@ -1369,7 +1368,7 @@ if (base::FeatureList::IsEnabled(media::kUseSurfaceLayerForVideo)) { EXPECT_CALL(*surface_layer_bridge_ptr_, CreateSurfaceLayer()).Times(0); EXPECT_CALL(*surface_layer_bridge_ptr_, GetSurfaceId()).Times(0); - EXPECT_CALL(*compositor_, EnableSubmission(_, _, _, _, _, _)).Times(0); + EXPECT_CALL(*compositor_, EnableSubmission(_, _, _, _, _)).Times(0); } // Nothing should happen. In particular, no assertions should fail. @@ -1422,7 +1421,7 @@ .WillOnce(ReturnRef(surface_id_)); EXPECT_CALL(*surface_layer_bridge_ptr_, GetLocalSurfaceIdAllocationTime()) .WillOnce(Return(base::TimeTicks())); - EXPECT_CALL(*compositor_, EnableSubmission(_, _, _, _, false, _)); + EXPECT_CALL(*compositor_, EnableSubmission(_, _, _, _, _)); EXPECT_CALL(*surface_layer_bridge_ptr_, SetContentsOpaque(false)); } else { EXPECT_CALL(client_, SetCcLayer(NotNull())); @@ -1451,7 +1450,7 @@ .WillOnce(ReturnRef(surface_id_)); EXPECT_CALL(*surface_layer_bridge_ptr_, GetLocalSurfaceIdAllocationTime()) .WillOnce(Return(base::TimeTicks())); - EXPECT_CALL(*compositor_, EnableSubmission(_, _, _, _, false, _)); + EXPECT_CALL(*compositor_, EnableSubmission(_, _, _, _, _)); EXPECT_CALL(*surface_layer_bridge_ptr_, SetContentsOpaque(false)); } else { EXPECT_CALL(client_, SetCcLayer(NotNull())); @@ -1481,7 +1480,7 @@ .WillOnce(ReturnRef(surface_id_)); EXPECT_CALL(*surface_layer_bridge_ptr_, GetLocalSurfaceIdAllocationTime()) .WillOnce(Return(base::TimeTicks())); - EXPECT_CALL(*compositor_, EnableSubmission(_, _, _, _, false, _)); + EXPECT_CALL(*compositor_, EnableSubmission(_, _, _, _, _)); EXPECT_CALL(*surface_layer_bridge_ptr_, SetContentsOpaque(false)); } else { EXPECT_CALL(client_, SetCcLayer(NotNull())); @@ -1559,7 +1558,7 @@ .WillOnce(ReturnRef(surface_id_)); EXPECT_CALL(*surface_layer_bridge_ptr_, GetLocalSurfaceIdAllocationTime()) .WillOnce(Return(base::TimeTicks())); - EXPECT_CALL(*compositor_, EnableSubmission(_, _, _, _, false, _)); + EXPECT_CALL(*compositor_, EnableSubmission(_, _, _, _, _)); EXPECT_CALL(*surface_layer_bridge_ptr_, SetContentsOpaque(false)); } else { EXPECT_CALL(client_, SetCcLayer(NotNull())); @@ -1600,7 +1599,7 @@ EXPECT_CALL(*surface_layer_bridge_ptr_, GetLocalSurfaceIdAllocationTime()) .WillOnce(Return(base::TimeTicks())); EXPECT_CALL(*surface_layer_bridge_ptr_, SetContentsOpaque(false)); - EXPECT_CALL(*compositor_, EnableSubmission(_, _, _, _, false, _)); + EXPECT_CALL(*compositor_, EnableSubmission(_, _, _, _, _)); // We only call the callback to create the bridge in OnMetadata, so we need // to call it. @@ -1645,7 +1644,7 @@ .WillRepeatedly(ReturnRef(surface_id_)); EXPECT_CALL(*surface_layer_bridge_ptr_, GetLocalSurfaceIdAllocationTime()) .WillRepeatedly(Return(base::TimeTicks())); - EXPECT_CALL(*compositor_, EnableSubmission(_, _, _, _, false, _)); + EXPECT_CALL(*compositor_, EnableSubmission(_, _, _, _, _)); EXPECT_CALL(*surface_layer_bridge_ptr_, SetContentsOpaque(false)); PipelineMetadata metadata; @@ -1690,7 +1689,7 @@ .WillRepeatedly(ReturnRef(surface_id_)); EXPECT_CALL(*surface_layer_bridge_ptr_, GetLocalSurfaceIdAllocationTime()) .WillRepeatedly(Return(base::TimeTicks())); - EXPECT_CALL(*compositor_, EnableSubmission(_, _, _, _, false, _)); + EXPECT_CALL(*compositor_, EnableSubmission(_, _, _, _, _)); EXPECT_CALL(*surface_layer_bridge_ptr_, SetContentsOpaque(false)); PipelineMetadata metadata;
diff --git a/media/gpu/fake_jpeg_decode_accelerator.cc b/media/gpu/fake_jpeg_decode_accelerator.cc index 6f6b3537..b12b52f4 100644 --- a/media/gpu/fake_jpeg_decode_accelerator.cc +++ b/media/gpu/fake_jpeg_decode_accelerator.cc
@@ -45,8 +45,6 @@ new WritableUnalignedMapping(bitstream_buffer.handle(), bitstream_buffer.size(), bitstream_buffer.offset())); - // The handle is no longer needed. - bitstream_buffer.handle().Close(); if (!src_shm->IsValid()) { DLOG(ERROR) << "Unable to map shared memory in FakeJpegDecodeAccelerator"; NotifyError(bitstream_buffer.id(), JpegDecodeAccelerator::UNREADABLE_INPUT);
diff --git a/media/gpu/h264_decoder.cc b/media/gpu/h264_decoder.cc index dc2c76cf..0fa01797 100644 --- a/media/gpu/h264_decoder.cc +++ b/media/gpu/h264_decoder.cc
@@ -26,12 +26,6 @@ return H264Decoder::H264Accelerator::Status::kNotSupported; } -H264Decoder::H264Accelerator::Status -H264Decoder::H264Accelerator::ParseSliceHeader(const H264NALU& slice_nalu, - H264SliceHeader* slice_header) { - return H264Decoder::H264Accelerator::Status::kNotSupported; -} - H264Decoder::H264Decoder(std::unique_ptr<H264Accelerator> accelerator, const VideoColorSpace& container_color_space) : state_(kNeedStreamMetadata), @@ -1319,32 +1313,12 @@ // the call that failed previously. If it succeeds (it may not if no // additional key has been provided, for example), then the remaining // steps will be executed. - if (!curr_slice_hdr_) { curr_slice_hdr_.reset(new H264SliceHeader()); - // If the accelerator handles the slice header, let it handle it. - // If not, use the parser. - H264Accelerator::Status result = accelerator_->ParseSliceHeader( - *curr_nalu_, curr_slice_hdr_.get()); - switch (result) { - case H264Accelerator::Status::kOk: - break; - case H264Accelerator::Status::kTryAgain: - DVLOG(1) << "ParseSliceHeader() needs to try again"; - // reset |curr_slice_hdr_| so ParseSliceHeader() is tried again. - curr_slice_hdr_.reset(); - return H264Decoder::kTryAgain; - case H264Accelerator::Status::kNotSupported: - // Let the parser try to handle it. - par_res = - parser_.ParseSliceHeader(*curr_nalu_, curr_slice_hdr_.get()); - if (par_res == H264Parser::kOk) - break; - FALLTHROUGH; - case H264Accelerator::Status::kFail: - SET_ERROR_AND_RETURN(); - } - + par_res = + parser_.ParseSliceHeader(*curr_nalu_, curr_slice_hdr_.get()); + if (par_res != H264Parser::kOk) + SET_ERROR_AND_RETURN(); state_ = kTryPreprocessCurrentSlice; }
diff --git a/media/gpu/h264_decoder.h b/media/gpu/h264_decoder.h index e77ede18..66bb089 100644 --- a/media/gpu/h264_decoder.h +++ b/media/gpu/h264_decoder.h
@@ -54,8 +54,8 @@ // operation later, once the data has been provided. kTryAgain, - // Operation is not supported. Used by SetStream() and ParseSliceHeader() - // to indicate that the Accelerator can not handle this operation. + // Operation is not supported. Used by SetStream() to indicate that the + // Accelerator can not handle this operation. kNotSupported, }; @@ -142,14 +142,6 @@ virtual Status SetStream(base::span<const uint8_t> stream, const DecryptConfig* decrypt_config); - // Parse a slice header, returning it in |*slice_header|. |slice_nalu| must - // be a slice NALU. On success, this populates |*slice_header|. If the - // Accelerator doesn't handle this slice header, then it should return - // kNotSupported. This method has a default implementation that returns - // kNotSupported. - virtual Status ParseSliceHeader(const H264NALU& slice_nalu, - H264SliceHeader* slice_header); - private: DISALLOW_COPY_AND_ASSIGN(H264Accelerator); };
diff --git a/media/gpu/h264_decoder_unittest.cc b/media/gpu/h264_decoder_unittest.cc index bd0ca1e..f48003f 100644 --- a/media/gpu/h264_decoder_unittest.cc +++ b/media/gpu/h264_decoder_unittest.cc
@@ -129,9 +129,6 @@ MOCK_METHOD2(SetStream, Status(base::span<const uint8_t> stream, const DecryptConfig* decrypt_config)); - MOCK_METHOD2(ParseSliceHeader, - Status(const H264NALU& slice_nalu, - H264SliceHeader* slice_header)); void Reset() override {} }; @@ -182,9 +179,6 @@ ON_CALL(*accelerator_, SetStream(_, _)) .WillByDefault( Return(H264Decoder::H264Accelerator::Status::kNotSupported)); - ON_CALL(*accelerator_, ParseSliceHeader(_, _)) - .WillByDefault( - Return(H264Decoder::H264Accelerator::Status::kNotSupported)); } void H264DecoderTest::SetInputFrameFiles( @@ -592,7 +586,6 @@ { InSequence sequence; - EXPECT_CALL(*accelerator_, ParseSliceHeader(_, _)); EXPECT_CALL(*accelerator_, CreateH264Picture()); EXPECT_CALL(*accelerator_, SubmitFrameMetadata(_, _, _, _, _, _, _)); EXPECT_CALL(*accelerator_, SubmitSlice(_, _, _, _, _, _, _, _)); @@ -607,36 +600,5 @@ ASSERT_TRUE(decoder_->Flush()); } -TEST_F(H264DecoderTest, ParseSliceHeaderRetry) { - SetInputFrameFiles({kBaselineFrame0}); - ASSERT_EQ(AcceleratedVideoDecoder::kAllocateNewSurfaces, Decode()); - EXPECT_EQ(gfx::Size(320, 192), decoder_->GetPicSize()); - EXPECT_LE(9u, decoder_->GetRequiredNumOfPictures()); - - EXPECT_CALL(*accelerator_, ParseSliceHeader(_, _)) - .WillOnce(Return(H264Decoder::H264Accelerator::Status::kTryAgain)); - ASSERT_EQ(AcceleratedVideoDecoder::kTryAgain, Decode()); - - H264SliceHeader slice_header = {}; - { - InSequence sequence; - - EXPECT_CALL(*accelerator_, ParseSliceHeader(_, _)) - .WillOnce(ComputeSliceHeader(&slice_header)); - EXPECT_CALL(*accelerator_, CreateH264Picture()); - EXPECT_CALL(*accelerator_, SubmitFrameMetadata(_, _, _, _, _, _, _)); - EXPECT_CALL(*accelerator_, SubmitSlice(_, SliceHeaderMatches(&slice_header), - _, _, _, _, _, _)); - } - ASSERT_EQ(AcceleratedVideoDecoder::kRanOutOfStreamData, Decode()); - - { - InSequence sequence; - EXPECT_CALL(*accelerator_, SubmitDecode(WithPoc(0))); - EXPECT_CALL(*accelerator_, OutputPicture(WithPoc(0))); - } - ASSERT_TRUE(decoder_->Flush()); -} - } // namespace } // namespace media
diff --git a/media/gpu/jpeg_encode_accelerator_unittest.cc b/media/gpu/jpeg_encode_accelerator_unittest.cc index 85d864d2..920e5c2e 100644 --- a/media/gpu/jpeg_encode_accelerator_unittest.cc +++ b/media/gpu/jpeg_encode_accelerator_unittest.cc
@@ -19,6 +19,7 @@ #include "base/strings/string_split.h" #include "base/strings/stringprintf.h" #include "base/test/scoped_task_environment.h" +#include "base/test/test_timeouts.h" #include "base/threading/thread.h" #include "base/threading/thread_task_runner_handle.h" #include "build/build_config.h" @@ -131,6 +132,11 @@ }; void JpegEncodeAcceleratorTestEnvironment::SetUp() { + // Since base::test::ScopedTaskEnvironment will call + // TestTimeouts::action_max_timeout(), TestTimeouts::Initialize() needs to be + // called in advance. + TestTimeouts::Initialize(); + if (!log_path_.empty()) { log_file_.reset(new base::File( log_path_, base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE));
diff --git a/media/gpu/video_encode_accelerator_unittest.cc b/media/gpu/video_encode_accelerator_unittest.cc index 22b12ee7..5ef5169 100644 --- a/media/gpu/video_encode_accelerator_unittest.cc +++ b/media/gpu/video_encode_accelerator_unittest.cc
@@ -2636,12 +2636,17 @@ public: VEATestSuite(int argc, char** argv) : base::TestSuite(argc, argv) {} - int Run() { + private: + void Initialize() override { + base::TestSuite::Initialize(); + #if defined(OS_CHROMEOS) - base::test::ScopedTaskEnvironment scoped_task_environment( - base::test::ScopedTaskEnvironment::MainThreadType::UI); + scoped_task_environment_ = + std::make_unique<base::test::ScopedTaskEnvironment>( + base::test::ScopedTaskEnvironment::MainThreadType::UI); #else - base::test::ScopedTaskEnvironment scoped_task_environment; + scoped_task_environment_ = + std::make_unique<base::test::ScopedTaskEnvironment>(); #endif media::g_env = reinterpret_cast<media::VideoEncodeAcceleratorTestEnvironment*>( @@ -2657,8 +2662,15 @@ #elif defined(OS_WIN) media::MediaFoundationVideoEncodeAccelerator::PreSandboxInitialization(); #endif - return base::TestSuite::Run(); } + + void Shutdown() override { + scoped_task_environment_.reset(); + base::TestSuite::Shutdown(); + } + + private: + std::unique_ptr<base::test::ScopedTaskEnvironment> scoped_task_environment_; }; } // namespace
diff --git a/media/renderers/paint_canvas_video_renderer.cc b/media/renderers/paint_canvas_video_renderer.cc index 93de42e1..8bdeb82 100644 --- a/media/renderers/paint_canvas_video_renderer.cc +++ b/media/renderers/paint_canvas_video_renderer.cc
@@ -342,6 +342,12 @@ bool QueryYUVA8(SkYUVASizeInfo* sizeInfo, SkYUVAIndex indices[SkYUVAIndex::kIndexCount], SkYUVColorSpace* color_space) const override { + // Temporarily disabling this path to avoid creating YUV ImageData in + // GpuImageDecodeCache. + // TODO(crbug.com/921636): Restore the code below once YUV rendering support + // is added for VideoImageGenerator. + return false; +#if 0 if (!media::IsYuvPlanar(frame_->format()) || // TODO(rileya): Skia currently doesn't support YUVA conversion. Remove // this case once it does. As-is we will fall back on the pure-software @@ -376,6 +382,7 @@ indices[SkYUVAIndex::kA_Index] = {-1, SkColorChannel::kR}; return true; +#endif } bool GetYUVA8Planes(const SkYUVASizeInfo& sizeInfo,
diff --git a/net/dns/BUILD.gn b/net/dns/BUILD.gn index a7f5e99..741a5b56 100644 --- a/net/dns/BUILD.gn +++ b/net/dns/BUILD.gn
@@ -54,6 +54,8 @@ "host_cache.cc", "host_resolver.cc", "host_resolver_impl.cc", + "host_resolver_mdns_listener_impl.cc", + "host_resolver_mdns_listener_impl.h", "host_resolver_mdns_task.cc", "host_resolver_mdns_task.h", "host_resolver_proc.cc",
diff --git a/net/dns/host_cache.cc b/net/dns/host_cache.cc index 1c5fc00..6fe37c7 100644 --- a/net/dns/host_cache.cc +++ b/net/dns/host_cache.cc
@@ -13,6 +13,7 @@ #include "base/strings/string_number_conversions.h" #include "base/time/default_tick_clock.h" #include "base/trace_event/trace_event.h" +#include "net/base/ip_endpoint.h" #include "net/base/net_errors.h" #include "net/base/trace_constants.h" #include "net/dns/host_resolver.h" @@ -192,6 +193,40 @@ base::Unretained(this)); } +HostCache::Entry HostCache::Entry::CopyWithDefaultPort(uint16_t port) const { + Entry copy(*this); + + if (addresses() && + std::any_of(addresses().value().begin(), addresses().value().end(), + [](const IPEndPoint& e) { return e.port() == 0; })) { + AddressList addresses_with_port; + addresses_with_port.set_canonical_name( + addresses().value().canonical_name()); + for (const IPEndPoint& endpoint : addresses().value()) { + if (endpoint.port() == 0) + addresses_with_port.push_back(IPEndPoint(endpoint.address(), port)); + else + addresses_with_port.push_back(endpoint); + } + copy.set_addresses(addresses_with_port); + } + + if (hostnames() && + std::any_of(hostnames().value().begin(), hostnames().value().end(), + [](const HostPortPair& h) { return h.port() == 0; })) { + std::vector<HostPortPair> hostnames_with_port; + for (const HostPortPair& hostname : hostnames().value()) { + if (hostname.port() == 0) + hostnames_with_port.push_back(HostPortPair(hostname.host(), port)); + else + hostnames_with_port.push_back(hostname); + } + copy.set_hostnames(std::move(hostnames_with_port)); + } + + return copy; +} + HostCache::Entry& HostCache::Entry::operator=(const Entry& entry) = default; HostCache::Entry& HostCache::Entry::operator=(Entry&& entry) = default;
diff --git a/net/dns/host_cache.h b/net/dns/host_cache.h index f7400b2..926dcf09 100644 --- a/net/dns/host_cache.h +++ b/net/dns/host_cache.h
@@ -167,6 +167,10 @@ // |this| is. NetLogParametersCallback CreateNetLogCallback() const; + // Creates a copy of |this| with the port of all address and hostname values + // set to |port| if the current port is 0. Preserves any non-zero ports. + HostCache::Entry CopyWithDefaultPort(uint16_t port) const; + private: friend class HostCache;
diff --git a/net/dns/host_resolver.cc b/net/dns/host_resolver.cc index 9b8daa3c..60e28e4 100644 --- a/net/dns/host_resolver.cc +++ b/net/dns/host_resolver.cc
@@ -114,6 +114,15 @@ HostResolver::~HostResolver() = default; +std::unique_ptr<HostResolver::MdnsListener> HostResolver::CreateMdnsListener( + const HostPortPair& host, + DnsQueryType query_type) { + // Should be overridden in any HostResolver implementation where this method + // may be called. + NOTREACHED(); + return nullptr; +} + void HostResolver::SetDnsClientEnabled(bool enabled) {} HostCache* HostResolver::GetHostCache() {
diff --git a/net/dns/host_resolver.h b/net/dns/host_resolver.h index a985f68..b08ebef 100644 --- a/net/dns/host_resolver.h +++ b/net/dns/host_resolver.h
@@ -242,6 +242,45 @@ bool is_speculative = false; }; + // Handler for an ongoing MDNS listening operation. Created by + // HostResolver::CreateMdnsListener(). + class MdnsListener { + public: + // Delegate type for result update notifications from MdnsListener. All + // methods have a |result_type| field to allow a single delegate to be + // passed to multiple MdnsListeners and be used to listen for updates for + // multiple types for the same host. + class Delegate { + public: + enum class UpdateType { ADDED, CHANGED, REMOVED }; + + virtual ~Delegate() {} + + virtual void OnAddressResult(UpdateType update_type, + DnsQueryType result_type, + IPEndPoint address) = 0; + virtual void OnTextResult(UpdateType update_type, + DnsQueryType result_type, + std::vector<std::string> text_records) = 0; + virtual void OnHostnameResult(UpdateType update_type, + DnsQueryType result_type, + HostPortPair host) = 0; + + // For results which may be valid MDNS but are not handled/parsed by + // HostResolver, e.g. pointers to the root domain. + virtual void OnUnhandledResult(UpdateType update_type, + DnsQueryType result_type) = 0; + }; + + // Destruction cancels the listening operation. + virtual ~MdnsListener() {} + + // Begins the listening operation, invoking |delegate| whenever results are + // updated. |delegate| will no longer be called once the listening operation + // is cancelled (via destruction of |this|). + virtual int Start(Delegate* delegate) = 0; + }; + // Set Options.max_concurrent_resolves to this to select a default level // of concurrency. static const size_t kDefaultParallelism = 0; @@ -320,6 +359,11 @@ HostCache::EntryStaleness* stale_info, const NetLogWithSource& source_net_log) = 0; + // Create a listener to watch for updates to an MDNS result. + virtual std::unique_ptr<MdnsListener> CreateMdnsListener( + const HostPortPair& host, + DnsQueryType query_type); + // Enable or disable the built-in asynchronous DnsClient. virtual void SetDnsClientEnabled(bool enabled);
diff --git a/net/dns/host_resolver_impl.cc b/net/dns/host_resolver_impl.cc index fc570e71..9503444 100644 --- a/net/dns/host_resolver_impl.cc +++ b/net/dns/host_resolver_impl.cc
@@ -23,7 +23,6 @@ #include <memory> #include <unordered_set> #include <utility> -#include <vector> #include "base/bind.h" #include "base/bind_helpers.h" @@ -33,6 +32,7 @@ #include "base/containers/linked_list.h" #include "base/debug/debugger.h" #include "base/debug/stack_trace.h" +#include "base/logging.h" #include "base/macros.h" #include "base/memory/ptr_util.h" #include "base/metrics/field_trial.h" @@ -67,6 +67,7 @@ #include "net/dns/dns_response.h" #include "net/dns/dns_transaction.h" #include "net/dns/dns_util.h" +#include "net/dns/host_resolver_mdns_listener_impl.h" #include "net/dns/host_resolver_mdns_task.h" #include "net/dns/host_resolver_proc.h" #include "net/dns/mdns_client.h" @@ -197,42 +198,6 @@ //----------------------------------------------------------------------------- -// Creates a copy of |results| with the port of all address and hostname values -// set to |port| if the current port is 0. Preserves any non-zero ports. -HostCache::Entry SetPortOnResults(HostCache::Entry results, uint16_t port) { - if (results.addresses() && - std::any_of(results.addresses().value().begin(), - results.addresses().value().end(), - [](const IPEndPoint& e) { return e.port() == 0; })) { - AddressList addresses_with_port; - addresses_with_port.set_canonical_name( - results.addresses().value().canonical_name()); - for (const IPEndPoint& endpoint : results.addresses().value()) { - if (endpoint.port() == 0) - addresses_with_port.push_back(IPEndPoint(endpoint.address(), port)); - else - addresses_with_port.push_back(endpoint); - } - results.set_addresses(addresses_with_port); - } - - if (results.hostnames() && - std::any_of(results.hostnames().value().begin(), - results.hostnames().value().end(), - [](const HostPortPair& h) { return h.port() == 0; })) { - std::vector<HostPortPair> hostnames_with_port; - for (const HostPortPair& hostname : results.hostnames().value()) { - if (hostname.port() == 0) - hostnames_with_port.push_back(HostPortPair(hostname.host(), port)); - else - hostnames_with_port.push_back(hostname); - } - results.set_hostnames(std::move(hostnames_with_port)); - } - - return results; -} - // Returns true if |addresses| contains only IPv4 loopback addresses. bool IsAllIPv4Loopback(const AddressList& addresses) { for (unsigned i = 0; i < addresses.size(); ++i) { @@ -2125,7 +2090,8 @@ tick_clock_->NowTicks() - req->request_time()); } if (results.error() == OK && !req->parameters().is_speculative) { - req->set_results(SetPortOnResults(results, req->request_host().port())); + req->set_results( + results.CopyWithDefaultPort(req->request_host().port())); } req->OnJobCompleted(this, results.error()); @@ -2408,6 +2374,22 @@ return results.error(); } +std::unique_ptr<HostResolver::MdnsListener> +HostResolverImpl::CreateMdnsListener(const HostPortPair& host, + DnsQueryType query_type) { + DCHECK_NE(DnsQueryType::UNSPECIFIED, query_type); + + auto listener = + std::make_unique<HostResolverMdnsListenerImpl>(host, query_type); + + MDnsClient* client = GetOrCreateMdnsClient(); + std::unique_ptr<net::MDnsListener> inner_listener = client->CreateListener( + DnsQueryTypeToQtype(query_type), host.host(), listener.get()); + + listener->set_inner_listener(std::move(inner_listener)); + return listener; +} + void HostResolverImpl::SetDnsClientEnabled(bool enabled) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); #if defined(ENABLE_BUILT_IN_DNS) @@ -2557,7 +2539,7 @@ nullptr /* stale_info */, request->source_net_log(), &key); if (results.error() == OK && !request->parameters().is_speculative) { request->set_results( - SetPortOnResults(results, request->request_host().port())); + results.CopyWithDefaultPort(request->request_host().port())); } if (results.error() != ERR_DNS_CACHE_MISS) { LogFinishRequest(request->source_net_log(), results.error());
diff --git a/net/dns/host_resolver_impl.h b/net/dns/host_resolver_impl.h index 1d4579f9..e2d0c94 100644 --- a/net/dns/host_resolver_impl.h +++ b/net/dns/host_resolver_impl.h
@@ -36,6 +36,7 @@ class AddressList; class DnsClient; +class HostPortPair; class IPAddress; class MDnsClient; class MDnsSocketFactory; @@ -157,6 +158,9 @@ AddressList* addresses, HostCache::EntryStaleness* stale_info, const NetLogWithSource& source_net_log) override; + std::unique_ptr<MdnsListener> CreateMdnsListener( + const HostPortPair& host, + DnsQueryType query_type) override; void SetDnsClientEnabled(bool enabled) override; HostCache* GetHostCache() override;
diff --git a/net/dns/host_resolver_impl_unittest.cc b/net/dns/host_resolver_impl_unittest.cc index 4abc892..fdde5e38 100644 --- a/net/dns/host_resolver_impl_unittest.cc +++ b/net/dns/host_resolver_impl_unittest.cc
@@ -24,14 +24,18 @@ #include "base/synchronization/condition_variable.h" #include "base/synchronization/lock.h" #include "base/test/bind_test_util.h" +#include "base/test/simple_test_clock.h" #include "base/test/test_mock_time_task_runner.h" #include "base/test/test_timeouts.h" #include "base/threading/thread_restrictions.h" #include "base/threading/thread_task_runner_handle.h" #include "base/time/time.h" +#include "base/timer/mock_timer.h" #include "base/values.h" #include "net/base/address_list.h" +#include "net/base/host_port_pair.h" #include "net/base/ip_address.h" +#include "net/base/ip_endpoint.h" #include "net/base/mock_network_change_notifier.h" #include "net/base/net_errors.h" #include "net/dns/dns_client.h" @@ -50,6 +54,10 @@ #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" +#if BUILDFLAG(ENABLE_MDNS) +#include "net/dns/mdns_client_impl.h" +#endif // BUILDFLAG(ENABLE_MDNS) + using net::test::IsError; using net::test::IsOk; using ::testing::_; @@ -3040,6 +3048,46 @@ 0x01, 0x02, 0x03, 0x04, // 1.2.3.4 }; +const uint8_t kMdnsResponseA2[] = { + // Header + 0x00, 0x00, // ID is zeroed out + 0x81, 0x80, // Standard query response, RA, no error + 0x00, 0x00, // No questions (for simplicity) + 0x00, 0x01, // 1 RR (answers) + 0x00, 0x00, // 0 authority RRs + 0x00, 0x00, // 0 additional RRs + + // "myhello.local." + 0x07, 'm', 'y', 'h', 'e', 'l', 'l', 'o', 0x05, 'l', 'o', 'c', 'a', 'l', + 0x00, + + 0x00, 0x01, // TYPE is A. + 0x00, 0x01, // CLASS is IN. + 0x00, 0x00, 0x00, 0x10, // TTL is 16 (seconds) + 0x00, 0x04, // RDLENGTH is 4 bytes. + 0x05, 0x06, 0x07, 0x08, // 5.6.7.8 +}; + +const uint8_t kMdnsResponseA2Goodbye[] = { + // Header + 0x00, 0x00, // ID is zeroed out + 0x81, 0x80, // Standard query response, RA, no error + 0x00, 0x00, // No questions (for simplicity) + 0x00, 0x01, // 1 RR (answers) + 0x00, 0x00, // 0 authority RRs + 0x00, 0x00, // 0 additional RRs + + // "myhello.local." + 0x07, 'm', 'y', 'h', 'e', 'l', 'l', 'o', 0x05, 'l', 'o', 'c', 'a', 'l', + 0x00, + + 0x00, 0x01, // TYPE is A. + 0x00, 0x01, // CLASS is IN. + 0x00, 0x00, 0x00, 0x00, // TTL is 0 (signaling "goodbye" removal of result) + 0x00, 0x04, // RDLENGTH is 4 bytes. + 0x05, 0x06, 0x07, 0x08, // 5.6.7.8 +}; + const uint8_t kMdnsResponseAAAA[] = { // Header 0x00, 0x00, // ID is zeroed out @@ -3134,6 +3182,27 @@ // "foo.com." 0x03, 'f', 'o', 'o', 0x03, 'c', 'o', 'm', 0x00}; +const uint8_t kMdnsResponsePtrRoot[] = { + // Header + 0x00, 0x00, // ID is zeroed out + 0x81, 0x80, // Standard query response, RA, no error + 0x00, 0x00, // No questions (for simplicity) + 0x00, 0x01, // 1 RR (answers) + 0x00, 0x00, // 0 authority RRs + 0x00, 0x00, // 0 additional RRs + + // "myhello.local." + 0x07, 'm', 'y', 'h', 'e', 'l', 'l', 'o', 0x05, 'l', 'o', 'c', 'a', 'l', + 0x00, + + 0x00, 0x0c, // TYPE is PTR. + 0x00, 0x01, // CLASS is IN. + 0x00, 0x00, 0x00, 0x13, // TTL is 19 (seconds) + 0x00, 0x01, // RDLENGTH is 1 byte. + + // "." (the root domain) + 0x00}; + const uint8_t kMdnsResponseSrv[] = { // Header 0x00, 0x00, // ID is zeroed out @@ -3474,6 +3543,299 @@ EXPECT_THAT(response.result_error(), IsError(ERR_FAILED)); EXPECT_FALSE(response.request()->GetAddressResults()); } + +// Implementation of HostResolver::MdnsListenerDelegate that records all +// received results in maps. +class TestMdnsListenerDelegate : public HostResolver::MdnsListener::Delegate { + public: + using UpdateKey = + std::pair<HostResolver::MdnsListener::Delegate::UpdateType, DnsQueryType>; + + void OnAddressResult( + HostResolver::MdnsListener::Delegate::UpdateType update_type, + DnsQueryType result_type, + IPEndPoint address) override { + address_results_.insert({{update_type, result_type}, std::move(address)}); + } + + void OnTextResult( + HostResolver::MdnsListener::Delegate::UpdateType update_type, + DnsQueryType result_type, + std::vector<std::string> text_records) override { + for (auto& text_record : text_records) { + text_results_.insert( + {{update_type, result_type}, std::move(text_record)}); + } + } + + void OnHostnameResult( + HostResolver::MdnsListener::Delegate::UpdateType update_type, + DnsQueryType result_type, + HostPortPair host) override { + hostname_results_.insert({{update_type, result_type}, std::move(host)}); + } + + void OnUnhandledResult( + HostResolver::MdnsListener::Delegate::UpdateType update_type, + DnsQueryType result_type) override { + unhandled_results_.insert({update_type, result_type}); + } + + const std::multimap<UpdateKey, IPEndPoint>& address_results() { + return address_results_; + } + + const std::multimap<UpdateKey, std::string>& text_results() { + return text_results_; + } + + const std::multimap<UpdateKey, HostPortPair>& hostname_results() { + return hostname_results_; + } + + const std::multiset<UpdateKey>& unhandled_results() { + return unhandled_results_; + } + + template <typename T> + static std::pair<UpdateKey, T> CreateExpectedResult( + HostResolver::MdnsListener::Delegate::UpdateType update_type, + DnsQueryType query_type, + T result) { + return std::make_pair(std::make_pair(update_type, query_type), result); + } + + private: + std::multimap<UpdateKey, IPEndPoint> address_results_; + std::multimap<UpdateKey, std::string> text_results_; + std::multimap<UpdateKey, HostPortPair> hostname_results_; + std::multiset<UpdateKey> unhandled_results_; +}; + +TEST_F(HostResolverImplTest, MdnsListener) { + auto socket_factory = std::make_unique<MockMDnsSocketFactory>(); + base::SimpleTestClock clock; + clock.SetNow(base::Time::Now()); + auto cache_cleanup_timer = std::make_unique<base::MockOneShotTimer>(); + auto* cache_cleanup_timer_ptr = cache_cleanup_timer.get(); + auto mdns_client = + std::make_unique<MDnsClientImpl>(&clock, std::move(cache_cleanup_timer)); + mdns_client->StartListening(socket_factory.get()); + resolver_->SetMdnsClientForTesting(std::move(mdns_client)); + + std::unique_ptr<HostResolver::MdnsListener> listener = + resolver_->CreateMdnsListener(HostPortPair("myhello.local", 80), + DnsQueryType::A); + + TestMdnsListenerDelegate delegate; + ASSERT_THAT(listener->Start(&delegate), IsOk()); + ASSERT_THAT(delegate.address_results(), testing::IsEmpty()); + + socket_factory->SimulateReceive(kMdnsResponseA, sizeof(kMdnsResponseA)); + socket_factory->SimulateReceive(kMdnsResponseA2, sizeof(kMdnsResponseA2)); + socket_factory->SimulateReceive(kMdnsResponseA2Goodbye, + sizeof(kMdnsResponseA2Goodbye)); + + // Per RFC6762 section 10.1, removals take effect 1 second after receiving the + // goodbye message. + clock.Advance(base::TimeDelta::FromSeconds(1)); + cache_cleanup_timer_ptr->Fire(); + + // Expect 1 record adding "1.2.3.4", another changing to "5.6.7.8", and a + // final removing "5.6.7.8". + EXPECT_THAT(delegate.address_results(), + testing::ElementsAre( + TestMdnsListenerDelegate::CreateExpectedResult( + HostResolver::MdnsListener::Delegate::UpdateType::ADDED, + DnsQueryType::A, CreateExpected("1.2.3.4", 80)), + TestMdnsListenerDelegate::CreateExpectedResult( + HostResolver::MdnsListener::Delegate::UpdateType::CHANGED, + DnsQueryType::A, CreateExpected("5.6.7.8", 80)), + TestMdnsListenerDelegate::CreateExpectedResult( + HostResolver::MdnsListener::Delegate::UpdateType::REMOVED, + DnsQueryType::A, CreateExpected("5.6.7.8", 80)))); + + EXPECT_THAT(delegate.text_results(), testing::IsEmpty()); + EXPECT_THAT(delegate.hostname_results(), testing::IsEmpty()); + EXPECT_THAT(delegate.unhandled_results(), testing::IsEmpty()); +} + +// Test that removal notifications are sent on natural expiration of MDNS +// records. +TEST_F(HostResolverImplTest, MdnsListener_Expiration) { + auto socket_factory = std::make_unique<MockMDnsSocketFactory>(); + base::SimpleTestClock clock; + clock.SetNow(base::Time::Now()); + auto cache_cleanup_timer = std::make_unique<base::MockOneShotTimer>(); + auto* cache_cleanup_timer_ptr = cache_cleanup_timer.get(); + auto mdns_client = + std::make_unique<MDnsClientImpl>(&clock, std::move(cache_cleanup_timer)); + mdns_client->StartListening(socket_factory.get()); + resolver_->SetMdnsClientForTesting(std::move(mdns_client)); + + std::unique_ptr<HostResolver::MdnsListener> listener = + resolver_->CreateMdnsListener(HostPortPair("myhello.local", 100), + DnsQueryType::A); + + TestMdnsListenerDelegate delegate; + ASSERT_THAT(listener->Start(&delegate), IsOk()); + ASSERT_THAT(delegate.address_results(), testing::IsEmpty()); + + socket_factory->SimulateReceive(kMdnsResponseA, sizeof(kMdnsResponseA)); + + EXPECT_THAT( + delegate.address_results(), + testing::ElementsAre(TestMdnsListenerDelegate::CreateExpectedResult( + HostResolver::MdnsListener::Delegate::UpdateType::ADDED, + DnsQueryType::A, CreateExpected("1.2.3.4", 100)))); + + clock.Advance(base::TimeDelta::FromSeconds(16)); + cache_cleanup_timer_ptr->Fire(); + + EXPECT_THAT(delegate.address_results(), + testing::ElementsAre( + TestMdnsListenerDelegate::CreateExpectedResult( + HostResolver::MdnsListener::Delegate::UpdateType::ADDED, + DnsQueryType::A, CreateExpected("1.2.3.4", 100)), + TestMdnsListenerDelegate::CreateExpectedResult( + HostResolver::MdnsListener::Delegate::UpdateType::REMOVED, + DnsQueryType::A, CreateExpected("1.2.3.4", 100)))); + + EXPECT_THAT(delegate.text_results(), testing::IsEmpty()); + EXPECT_THAT(delegate.hostname_results(), testing::IsEmpty()); + EXPECT_THAT(delegate.unhandled_results(), testing::IsEmpty()); +} + +TEST_F(HostResolverImplTest, MdnsListener_Txt) { + auto socket_factory = std::make_unique<MockMDnsSocketFactory>(); + MockMDnsSocketFactory* socket_factory_ptr = socket_factory.get(); + resolver_->SetMdnsSocketFactoryForTesting(std::move(socket_factory)); + + std::unique_ptr<HostResolver::MdnsListener> listener = + resolver_->CreateMdnsListener(HostPortPair("myhello.local", 12), + DnsQueryType::TXT); + + TestMdnsListenerDelegate delegate; + ASSERT_THAT(listener->Start(&delegate), IsOk()); + ASSERT_THAT(delegate.text_results(), testing::IsEmpty()); + + socket_factory_ptr->SimulateReceive(kMdnsResponseTxt, + sizeof(kMdnsResponseTxt)); + + EXPECT_THAT(delegate.text_results(), + testing::ElementsAre( + TestMdnsListenerDelegate::CreateExpectedResult( + HostResolver::MdnsListener::Delegate::UpdateType::ADDED, + DnsQueryType::TXT, "foo"), + TestMdnsListenerDelegate::CreateExpectedResult( + HostResolver::MdnsListener::Delegate::UpdateType::ADDED, + DnsQueryType::TXT, "bar"))); + + EXPECT_THAT(delegate.address_results(), testing::IsEmpty()); + EXPECT_THAT(delegate.hostname_results(), testing::IsEmpty()); + EXPECT_THAT(delegate.unhandled_results(), testing::IsEmpty()); +} + +TEST_F(HostResolverImplTest, MdnsListener_Ptr) { + auto socket_factory = std::make_unique<MockMDnsSocketFactory>(); + MockMDnsSocketFactory* socket_factory_ptr = socket_factory.get(); + resolver_->SetMdnsSocketFactoryForTesting(std::move(socket_factory)); + + std::unique_ptr<HostResolver::MdnsListener> listener = + resolver_->CreateMdnsListener(HostPortPair("myhello.local", 13), + DnsQueryType::PTR); + + TestMdnsListenerDelegate delegate; + ASSERT_THAT(listener->Start(&delegate), IsOk()); + ASSERT_THAT(delegate.text_results(), testing::IsEmpty()); + + socket_factory_ptr->SimulateReceive(kMdnsResponsePtr, + sizeof(kMdnsResponsePtr)); + + EXPECT_THAT( + delegate.hostname_results(), + testing::ElementsAre(TestMdnsListenerDelegate::CreateExpectedResult( + HostResolver::MdnsListener::Delegate::UpdateType::ADDED, + DnsQueryType::PTR, HostPortPair("foo.com", 13)))); + + EXPECT_THAT(delegate.address_results(), testing::IsEmpty()); + EXPECT_THAT(delegate.text_results(), testing::IsEmpty()); + EXPECT_THAT(delegate.unhandled_results(), testing::IsEmpty()); +} + +TEST_F(HostResolverImplTest, MdnsListener_Srv) { + auto socket_factory = std::make_unique<MockMDnsSocketFactory>(); + MockMDnsSocketFactory* socket_factory_ptr = socket_factory.get(); + resolver_->SetMdnsSocketFactoryForTesting(std::move(socket_factory)); + + std::unique_ptr<HostResolver::MdnsListener> listener = + resolver_->CreateMdnsListener(HostPortPair("myhello.local", 14), + DnsQueryType::SRV); + + TestMdnsListenerDelegate delegate; + ASSERT_THAT(listener->Start(&delegate), IsOk()); + ASSERT_THAT(delegate.text_results(), testing::IsEmpty()); + + socket_factory_ptr->SimulateReceive(kMdnsResponseSrv, + sizeof(kMdnsResponseSrv)); + + EXPECT_THAT( + delegate.hostname_results(), + testing::ElementsAre(TestMdnsListenerDelegate::CreateExpectedResult( + HostResolver::MdnsListener::Delegate::UpdateType::ADDED, + DnsQueryType::SRV, HostPortPair("foo.com", 8265)))); + + EXPECT_THAT(delegate.address_results(), testing::IsEmpty()); + EXPECT_THAT(delegate.text_results(), testing::IsEmpty()); + EXPECT_THAT(delegate.unhandled_results(), testing::IsEmpty()); +} + +// Ensure query types we are not listening for do not affect MdnsListener. +TEST_F(HostResolverImplTest, MdnsListener_NonListeningTypes) { + auto socket_factory = std::make_unique<MockMDnsSocketFactory>(); + MockMDnsSocketFactory* socket_factory_ptr = socket_factory.get(); + resolver_->SetMdnsSocketFactoryForTesting(std::move(socket_factory)); + + std::unique_ptr<HostResolver::MdnsListener> listener = + resolver_->CreateMdnsListener(HostPortPair("myhello.local", 41), + DnsQueryType::A); + + TestMdnsListenerDelegate delegate; + ASSERT_THAT(listener->Start(&delegate), IsOk()); + + socket_factory_ptr->SimulateReceive(kMdnsResponseAAAA, + sizeof(kMdnsResponseAAAA)); + + EXPECT_THAT(delegate.address_results(), testing::IsEmpty()); + EXPECT_THAT(delegate.text_results(), testing::IsEmpty()); + EXPECT_THAT(delegate.hostname_results(), testing::IsEmpty()); + EXPECT_THAT(delegate.unhandled_results(), testing::IsEmpty()); +} + +TEST_F(HostResolverImplTest, MdnsListener_RootDomain) { + auto socket_factory = std::make_unique<MockMDnsSocketFactory>(); + MockMDnsSocketFactory* socket_factory_ptr = socket_factory.get(); + resolver_->SetMdnsSocketFactoryForTesting(std::move(socket_factory)); + + std::unique_ptr<HostResolver::MdnsListener> listener = + resolver_->CreateMdnsListener(HostPortPair("myhello.local", 5), + DnsQueryType::PTR); + + TestMdnsListenerDelegate delegate; + ASSERT_THAT(listener->Start(&delegate), IsOk()); + + socket_factory_ptr->SimulateReceive(kMdnsResponsePtrRoot, + sizeof(kMdnsResponsePtrRoot)); + + EXPECT_THAT(delegate.unhandled_results(), + testing::ElementsAre(std::make_pair( + HostResolver::MdnsListener::Delegate::UpdateType::ADDED, + DnsQueryType::PTR))); + + EXPECT_THAT(delegate.address_results(), testing::IsEmpty()); + EXPECT_THAT(delegate.text_results(), testing::IsEmpty()); + EXPECT_THAT(delegate.hostname_results(), testing::IsEmpty()); +} #endif // BUILDFLAG(ENABLE_MDNS) DnsConfig CreateValidDnsConfig() {
diff --git a/net/dns/host_resolver_mdns_listener_impl.cc b/net/dns/host_resolver_mdns_listener_impl.cc new file mode 100644 index 0000000..607c5c8 --- /dev/null +++ b/net/dns/host_resolver_mdns_listener_impl.cc
@@ -0,0 +1,101 @@ +// 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 "net/dns/host_resolver_mdns_listener_impl.h" + +#include "base/logging.h" +#include "net/base/host_port_pair.h" +#include "net/base/net_errors.h" +#include "net/dns/host_cache.h" +#include "net/dns/host_resolver_mdns_task.h" +#include "net/dns/record_parsed.h" + +namespace net { + +namespace { + +HostResolver::MdnsListener::Delegate::UpdateType ConvertUpdateType( + net::MDnsListener::UpdateType type) { + switch (type) { + case net::MDnsListener::RECORD_ADDED: + return HostResolver::MdnsListener::Delegate::UpdateType::ADDED; + case net::MDnsListener::RECORD_CHANGED: + return HostResolver::MdnsListener::Delegate::UpdateType::CHANGED; + case net::MDnsListener::RECORD_REMOVED: + return HostResolver::MdnsListener::Delegate::UpdateType::REMOVED; + } +} + +} // namespace + +HostResolverMdnsListenerImpl::HostResolverMdnsListenerImpl( + const HostPortPair& query_host, + DnsQueryType query_type) + : query_host_(query_host), query_type_(query_type) { + DCHECK_NE(DnsQueryType::UNSPECIFIED, query_type_); +} + +HostResolverMdnsListenerImpl::~HostResolverMdnsListenerImpl() { + // Destroy |inner_listener_| first to cancel listening and callbacks to |this| + // before anything else becomes invalid. + inner_listener_ = nullptr; +} + +int HostResolverMdnsListenerImpl::Start(Delegate* delegate) { + DCHECK(delegate); + DCHECK(inner_listener_); + + delegate_ = delegate; + return inner_listener_->Start() ? OK : ERR_FAILED; +} + +void HostResolverMdnsListenerImpl::OnRecordUpdate( + net::MDnsListener::UpdateType update, + const RecordParsed* record) { + DCHECK(delegate_); + + HostCache::Entry parsed_entry = + HostResolverMdnsTask::ParseResult(OK, query_type_, record, + query_host_.host()) + .CopyWithDefaultPort(query_host_.port()); + if (parsed_entry.error() != OK) { + delegate_->OnUnhandledResult(ConvertUpdateType(update), query_type_); + return; + } + + switch (query_type_) { + case DnsQueryType::UNSPECIFIED: + NOTREACHED(); + break; + case DnsQueryType::A: + case DnsQueryType::AAAA: + DCHECK(parsed_entry.addresses()); + DCHECK_EQ(1u, parsed_entry.addresses().value().size()); + delegate_->OnAddressResult(ConvertUpdateType(update), query_type_, + parsed_entry.addresses().value().front()); + break; + case DnsQueryType::TXT: + DCHECK(parsed_entry.text_records()); + delegate_->OnTextResult(ConvertUpdateType(update), query_type_, + parsed_entry.text_records().value()); + break; + case DnsQueryType::PTR: + case DnsQueryType::SRV: + DCHECK(parsed_entry.hostnames()); + delegate_->OnHostnameResult(ConvertUpdateType(update), query_type_, + parsed_entry.hostnames().value().front()); + break; + } +} + +void HostResolverMdnsListenerImpl::OnNsecRecord(const std::string& name, + unsigned type) { + // Do nothing. HostResolver does not support listening for NSEC records. +} + +void HostResolverMdnsListenerImpl::OnCachePurged() { + // Do nothing. HostResolver does not support listening for cache purges. +} + +} // namespace net
diff --git a/net/dns/host_resolver_mdns_listener_impl.h b/net/dns/host_resolver_mdns_listener_impl.h new file mode 100644 index 0000000..66eaf85d --- /dev/null +++ b/net/dns/host_resolver_mdns_listener_impl.h
@@ -0,0 +1,55 @@ +// 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 NET_DNS_HOST_RESOLVER_MDNS_LISTENER_IMPL_H_ +#define NET_DNS_HOST_RESOLVER_MDNS_LISTENER_IMPL_H_ + +#include <memory> +#include <string> +#include <utility> + +#include "net/dns/host_resolver.h" +#include "net/dns/mdns_client.h" +#include "net/dns/public/dns_query_type.h" + +namespace net { + +class HostPortPair; +class RecordParsed; + +// Intermediary between the HostResolver::CreateMdnsListener API and the +// underlying listener functionality in MDnsClient. +class HostResolverMdnsListenerImpl : public HostResolver::MdnsListener, + public net::MDnsListener::Delegate { + public: + using Delegate = HostResolver::MdnsListener::Delegate; + + HostResolverMdnsListenerImpl(const HostPortPair& query_host, + DnsQueryType query_type); + ~HostResolverMdnsListenerImpl() override; + + void set_inner_listener(std::unique_ptr<net::MDnsListener> inner_listener) { + inner_listener_ = std::move(inner_listener); + } + + // HostResolver::MdnsListener implementation + int Start(Delegate* delegate) override; + + // net::MDnsListener::Delegate implementation + void OnRecordUpdate(net::MDnsListener::UpdateType update, + const RecordParsed* record) override; + void OnNsecRecord(const std::string& name, unsigned type) override; + void OnCachePurged() override; + + private: + HostPortPair query_host_; + DnsQueryType query_type_; + + std::unique_ptr<net::MDnsListener> inner_listener_; + Delegate* delegate_; +}; + +} // namespace net + +#endif // NET_DNS_HOST_RESOLVER_MDNS_LISTENER_IMPL_H_
diff --git a/net/dns/host_resolver_mdns_task.cc b/net/dns/host_resolver_mdns_task.cc index b1373fa..c280b256 100644 --- a/net/dns/host_resolver_mdns_task.cc +++ b/net/dns/host_resolver_mdns_task.cc
@@ -17,6 +17,20 @@ namespace net { +namespace { +HostCache::Entry ParseHostnameResult(const std::string& host, uint16_t port) { + // Filter out root domain. Depending on the type, it either means no-result + // or is simply not a result important to any expected Chrome usecases. + if (host.empty()) { + return HostCache::Entry(ERR_NAME_NOT_RESOLVED, + HostCache::Entry::SOURCE_UNKNOWN); + } + return HostCache::Entry(OK, + std::vector<HostPortPair>({HostPortPair(host, port)}), + HostCache::Entry::SOURCE_UNKNOWN); +} +} // namespace + class HostResolverMdnsTask::Transaction { public: Transaction(DnsQueryType query_type, HostResolverMdnsTask* task) @@ -75,6 +89,7 @@ int error = ERR_UNEXPECTED; switch (result) { case MDnsTransaction::RESULT_RECORD: + DCHECK(parsed); error = OK; break; case MDnsTransaction::RESULT_NO_RESULTS: @@ -86,48 +101,8 @@ NOTREACHED(); } - if (error == net::OK) { - // Expected to be validated by MDnsClient. - DCHECK_EQ(DnsQueryTypeToQtype(query_type_), parsed->type()); - DCHECK( - base::EqualsCaseInsensitiveASCII(task_->hostname_, parsed->name())); - - switch (query_type_) { - case DnsQueryType::UNSPECIFIED: - // Should create two separate transactions with specified type. - NOTREACHED(); - break; - case DnsQueryType::A: - results_ = HostCache::Entry( - OK, - AddressList( - IPEndPoint(parsed->rdata<ARecordRdata>()->address(), 0)), - HostCache::Entry::SOURCE_UNKNOWN); - break; - case DnsQueryType::AAAA: - results_ = HostCache::Entry( - OK, - AddressList( - IPEndPoint(parsed->rdata<AAAARecordRdata>()->address(), 0)), - HostCache::Entry::SOURCE_UNKNOWN); - break; - case DnsQueryType::TXT: - results_ = - HostCache::Entry(OK, parsed->rdata<TxtRecordRdata>()->texts(), - HostCache::Entry::SOURCE_UNKNOWN); - break; - case DnsQueryType::PTR: - ParseHostnameResult(parsed->rdata<PtrRecordRdata>()->ptrdomain(), - 0 /* port */); - break; - case DnsQueryType::SRV: - ParseHostnameResult(parsed->rdata<SrvRecordRdata>()->target(), - parsed->rdata<SrvRecordRdata>()->port()); - break; - } - } else { - results_ = HostCache::Entry(error, HostCache::Entry::SOURCE_UNKNOWN); - } + results_ = HostResolverMdnsTask::ParseResult(error, query_type_, parsed, + task_->hostname_); // If we don't have a saved async_transaction, it means OnComplete was // invoked inline in MDnsTransaction::Start. Callbacks will need to be @@ -135,19 +110,6 @@ task_->CheckCompletion(!async_transaction_); } - void ParseHostnameResult(const std::string& host, uint16_t port) { - // Filter out root domain. Depending on the type, it either means no-result - // or is simply not a result important to any expected Chrome usecases. - if (host.empty()) { - results_ = HostCache::Entry(ERR_NAME_NOT_RESOLVED, - HostCache::Entry::SOURCE_UNKNOWN); - } else { - results_ = HostCache::Entry( - OK, std::vector<HostPortPair>({HostPortPair(host, port)}), - HostCache::Entry::SOURCE_UNKNOWN); - } - } - const DnsQueryType query_type_; // ERR_IO_PENDING until transaction completes (or is cancelled). @@ -215,6 +177,50 @@ return combined_results; } +// static +HostCache::Entry HostResolverMdnsTask::ParseResult( + int error, + DnsQueryType query_type, + const RecordParsed* parsed, + const std::string& expected_hostname) { + if (error != OK) { + return HostCache::Entry(error, HostCache::Entry::SOURCE_UNKNOWN); + } + DCHECK(parsed); + + // Expected to be validated by MDnsClient. + DCHECK_EQ(DnsQueryTypeToQtype(query_type), parsed->type()); + DCHECK(base::EqualsCaseInsensitiveASCII(expected_hostname, parsed->name())); + + switch (query_type) { + case DnsQueryType::UNSPECIFIED: + // Should create two separate transactions with specified type. + NOTREACHED(); + return HostCache::Entry(ERR_FAILED, HostCache::Entry::SOURCE_UNKNOWN); + case DnsQueryType::A: + return HostCache::Entry( + OK, + AddressList( + IPEndPoint(parsed->rdata<net::ARecordRdata>()->address(), 0)), + HostCache::Entry::SOURCE_UNKNOWN); + case DnsQueryType::AAAA: + return HostCache::Entry( + OK, + AddressList( + IPEndPoint(parsed->rdata<net::AAAARecordRdata>()->address(), 0)), + HostCache::Entry::SOURCE_UNKNOWN); + case DnsQueryType::TXT: + return HostCache::Entry(OK, parsed->rdata<net::TxtRecordRdata>()->texts(), + HostCache::Entry::SOURCE_UNKNOWN); + case DnsQueryType::PTR: + return ParseHostnameResult(parsed->rdata<PtrRecordRdata>()->ptrdomain(), + 0 /* port */); + case DnsQueryType::SRV: + return ParseHostnameResult(parsed->rdata<SrvRecordRdata>()->target(), + parsed->rdata<SrvRecordRdata>()->port()); + } +} + void HostResolverMdnsTask::CheckCompletion(bool post_needed) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
diff --git a/net/dns/host_resolver_mdns_task.h b/net/dns/host_resolver_mdns_task.h index c4f9058..5a1c829 100644 --- a/net/dns/host_resolver_mdns_task.h +++ b/net/dns/host_resolver_mdns_task.h
@@ -21,6 +21,8 @@ namespace net { +class RecordParsed; + // Representation of a single HostResolverImpl::Job task to resolve the hostname // using multicast DNS transactions. Destruction cancels the task and prevents // any callbacks from being invoked. @@ -40,6 +42,11 @@ // Results only available after invocation of the completion closure. HostCache::Entry GetResults() const; + static HostCache::Entry ParseResult(int error, + DnsQueryType query_type, + const RecordParsed* parsed, + const std::string& expected_hostname); + private: class Transaction;
diff --git a/net/dns/mdns_client.h b/net/dns/mdns_client.h index 53889373..89011cc 100644 --- a/net/dns/mdns_client.h +++ b/net/dns/mdns_client.h
@@ -89,6 +89,10 @@ // A listener listens for updates regarding a specific record or set of records. // Created by the MDnsClient (see |MDnsClient::CreateListener|) and used to keep // track of listeners. +// +// TODO(ericorth@chromium.org): Consider moving this inside MDnsClient to better +// organize the namespace and avoid confusion with +// net::HostResolver::MdnsListener. class NET_EXPORT MDnsListener { public: // Used in the MDnsListener delegate to signify what type of change has been
diff --git a/net/dns/mdns_client_impl.h b/net/dns/mdns_client_impl.h index 7230855..5627193 100644 --- a/net/dns/mdns_client_impl.h +++ b/net/dns/mdns_client_impl.h
@@ -190,6 +190,11 @@ }; MDnsClientImpl(); + + // Test constructor, takes a mock clock and mock timer. + MDnsClientImpl(base::Clock* clock, + std::unique_ptr<base::OneShotTimer> cleanup_timer); + ~MDnsClientImpl() override; // MDnsClient implementation: @@ -211,12 +216,6 @@ Core* core() { return core_.get(); } private: - FRIEND_TEST_ALL_PREFIXES(MDnsTest, CacheCleanupWithShortTTL); - - // Test constructor, takes a mock clock and mock timer. - MDnsClientImpl(base::Clock* clock, - std::unique_ptr<base::OneShotTimer> cleanup_timer); - std::unique_ptr<Core> core_; base::Clock* clock_; std::unique_ptr<base::OneShotTimer> cleanup_timer_;
diff --git a/net/http/http_auth_handler_negotiate.cc b/net/http/http_auth_handler_negotiate.cc index 96940f4..5eacf4c 100644 --- a/net/http/http_auth_handler_negotiate.cc +++ b/net/http/http_auth_handler_negotiate.cc
@@ -13,9 +13,10 @@ #include "base/strings/stringprintf.h" #include "base/values.h" #include "net/base/address_family.h" +#include "net/base/address_list.h" +#include "net/base/host_port_pair.h" #include "net/base/net_errors.h" #include "net/cert/x509_util.h" -#include "net/dns/host_resolver.h" #include "net/http/http_auth_filter.h" #include "net/http/http_auth_preferences.h" #include "net/log/net_log_capture_mode.h" @@ -137,56 +138,6 @@ HttpAuthHandlerNegotiate::~HttpAuthHandlerNegotiate() = default; -std::string HttpAuthHandlerNegotiate::CreateSPN(const AddressList& address_list, - const GURL& origin) { - // Kerberos Web Server SPNs are in the form HTTP/<host>:<port> through SSPI, - // and in the form HTTP@<host>:<port> through GSSAPI - // http://msdn.microsoft.com/en-us/library/ms677601%28VS.85%29.aspx - // - // However, reality differs from the specification. A good description of - // the problems can be found here: - // http://blog.michelbarneveld.nl/michel/archive/2009/11/14/the-reason-why-kb911149-and-kb908209-are-not-the-soluton.aspx - // - // Typically the <host> portion should be the canonical FQDN for the service. - // If this could not be resolved, the original hostname in the URL will be - // attempted instead. However, some intranets register SPNs using aliases - // for the same canonical DNS name to allow multiple web services to reside - // on the same host machine without requiring different ports. IE6 and IE7 - // have hotpatches that allow the default behavior to be overridden. - // http://support.microsoft.com/kb/911149 - // http://support.microsoft.com/kb/938305 - // - // According to the spec, the <port> option should be included if it is a - // non-standard port (i.e. not 80 or 443 in the HTTP case). However, - // historically browsers have not included the port, even on non-standard - // ports. IE6 required a hotpatch and a registry setting to enable - // including non-standard ports, and IE7 and IE8 also require the same - // registry setting, but no hotpatch. Firefox does not appear to have an - // option to include non-standard ports as of 3.6. - // http://support.microsoft.com/kb/908209 - // - // Without any command-line flags, Chrome matches the behavior of Firefox - // and IE. Users can override the behavior so aliases are allowed and - // non-standard ports are included. - int port = origin.EffectiveIntPort(); - std::string server = address_list.canonical_name(); - if (server.empty()) - server = origin.host(); -#if defined(OS_WIN) - static const char kSpnSeparator = '/'; -#elif defined(OS_POSIX) - static const char kSpnSeparator = '@'; -#endif - if (port != 80 && port != 443 && - (http_auth_preferences_ && - http_auth_preferences_->NegotiateEnablePort())) { - return base::StringPrintf("HTTP%c%s:%d", kSpnSeparator, server.c_str(), - port); - } else { - return base::StringPrintf("HTTP%c%s", kSpnSeparator, server.c_str()); - } -} - HttpAuth::AuthorizationResult HttpAuthHandlerNegotiate::HandleAnotherChallenge( HttpAuthChallengeTokenizer* challenge) { return auth_system_.ParseChallenge(challenge); @@ -273,6 +224,53 @@ return rv; } +std::string HttpAuthHandlerNegotiate::CreateSPN(const std::string& server, + const GURL& origin) { + // Kerberos Web Server SPNs are in the form HTTP/<host>:<port> through SSPI, + // and in the form HTTP@<host>:<port> through GSSAPI + // http://msdn.microsoft.com/en-us/library/ms677601%28VS.85%29.aspx + // + // However, reality differs from the specification. A good description of + // the problems can be found here: + // http://blog.michelbarneveld.nl/michel/archive/2009/11/14/the-reason-why-kb911149-and-kb908209-are-not-the-soluton.aspx + // + // Typically the <host> portion should be the canonical FQDN for the service. + // If this could not be resolved, the original hostname in the URL will be + // attempted instead. However, some intranets register SPNs using aliases + // for the same canonical DNS name to allow multiple web services to reside + // on the same host machine without requiring different ports. IE6 and IE7 + // have hotpatches that allow the default behavior to be overridden. + // http://support.microsoft.com/kb/911149 + // http://support.microsoft.com/kb/938305 + // + // According to the spec, the <port> option should be included if it is a + // non-standard port (i.e. not 80 or 443 in the HTTP case). However, + // historically browsers have not included the port, even on non-standard + // ports. IE6 required a hotpatch and a registry setting to enable + // including non-standard ports, and IE7 and IE8 also require the same + // registry setting, but no hotpatch. Firefox does not appear to have an + // option to include non-standard ports as of 3.6. + // http://support.microsoft.com/kb/908209 + // + // Without any command-line flags, Chrome matches the behavior of Firefox + // and IE. Users can override the behavior so aliases are allowed and + // non-standard ports are included. + int port = origin.EffectiveIntPort(); +#if defined(OS_WIN) + static const char kSpnSeparator = '/'; +#elif defined(OS_POSIX) + static const char kSpnSeparator = '@'; +#endif + if (port != 80 && port != 443 && + (http_auth_preferences_ && + http_auth_preferences_->NegotiateEnablePort())) { + return base::StringPrintf("HTTP%c%s:%d", kSpnSeparator, server.c_str(), + port); + } else { + return base::StringPrintf("HTTP%c%s", kSpnSeparator, server.c_str()); + } +} + void HttpAuthHandlerNegotiate::OnIOComplete(int result) { int rv = DoLoop(result); if (rv != ERR_IO_PENDING) @@ -325,27 +323,36 @@ return OK; // TODO(cbentzel): Add reverse DNS lookup for numeric addresses. - HostResolver::RequestInfo info(HostPortPair(origin_.host(), 0)); - info.set_host_resolver_flags(HOST_RESOLVER_CANONNAME); - return resolver_->Resolve(info, DEFAULT_PRIORITY, &address_list_, - base::Bind(&HttpAuthHandlerNegotiate::OnIOComplete, - base::Unretained(this)), - &request_, net_log_); + HostResolver::ResolveHostParameters parameters; + parameters.include_canonical_name = true; + resolve_host_request_ = resolver_->CreateRequest( + HostPortPair(origin_.host(), 0), net_log_, parameters); + return resolve_host_request_->Start(base::BindOnce( + &HttpAuthHandlerNegotiate::OnIOComplete, base::Unretained(this))); } int HttpAuthHandlerNegotiate::DoResolveCanonicalNameComplete(int rv) { DCHECK_NE(ERR_IO_PENDING, rv); - if (rv != OK) { - // Even in the error case, try to use origin_.host instead of - // passing the failure on to the caller. - VLOG(1) << "Problem finding canonical name for SPN for host " - << origin_.host() << ": " << ErrorToString(rv); - rv = OK; + std::string server = origin_.host(); + if (resolve_host_request_) { + if (rv == OK) { + DCHECK(resolve_host_request_->GetAddressResults()); + const std::string& canonical_name = + resolve_host_request_->GetAddressResults().value().canonical_name(); + if (!canonical_name.empty()) + server = canonical_name; + } else { + // Even in the error case, try to use origin_.host instead of + // passing the failure on to the caller. + VLOG(1) << "Problem finding canonical name for SPN for host " + << origin_.host() << ": " << ErrorToString(rv); + rv = OK; + } } next_state_ = STATE_GENERATE_AUTH_TOKEN; - spn_ = CreateSPN(address_list_, origin_); - address_list_ = AddressList(); + spn_ = CreateSPN(server, origin_); + resolve_host_request_ = nullptr; return rv; }
diff --git a/net/http/http_auth_handler_negotiate.h b/net/http/http_auth_handler_negotiate.h index 0cd2e9d..de65976 100644 --- a/net/http/http_auth_handler_negotiate.h +++ b/net/http/http_auth_handler_negotiate.h
@@ -5,11 +5,11 @@ #ifndef NET_HTTP_HTTP_AUTH_HANDLER_NEGOTIATE_H_ #define NET_HTTP_HTTP_AUTH_HANDLER_NEGOTIATE_H_ +#include <memory> #include <string> #include <utility> #include "build/build_config.h" -#include "net/base/address_list.h" #include "net/base/completion_once_callback.h" #include "net/base/net_export.h" #include "net/dns/host_resolver.h" @@ -107,10 +107,6 @@ ~HttpAuthHandlerNegotiate() override; - // These are public for unit tests - std::string CreateSPN(const AddressList& address_list, const GURL& orign); - const std::string& spn() const { return spn_; } - // HttpAuthHandler: HttpAuth::AuthorizationResult HandleAnotherChallenge( HttpAuthChallengeTokenizer* challenge) override; @@ -118,6 +114,8 @@ bool AllowsDefaultCredentials() override; bool AllowsExplicitCredentials() override; + const std::string& spn_for_testing() const { return spn_; } + protected: bool Init(HttpAuthChallengeTokenizer* challenge, const SSLInfo& ssl_info) override; @@ -136,6 +134,8 @@ STATE_NONE, }; + std::string CreateSPN(const std::string& server, const GURL& orign); + void OnIOComplete(int result); void DoCallback(int result); int DoLoop(int result); @@ -150,8 +150,7 @@ HostResolver* const resolver_; // Members which are needed for DNS lookup + SPN. - AddressList address_list_; - std::unique_ptr<net::HostResolver::Request> request_; + std::unique_ptr<HostResolver::ResolveHostRequest> resolve_host_request_; // Things which should be consistent after first call to GenerateAuthToken. bool already_called_;
diff --git a/net/http/http_auth_handler_negotiate_unittest.cc b/net/http/http_auth_handler_negotiate_unittest.cc index ad4f9b0..d4a932ff 100644 --- a/net/http/http_auth_handler_negotiate_unittest.cc +++ b/net/http/http_auth_handler_negotiate_unittest.cc
@@ -51,7 +51,7 @@ void SetUp() override { auth_library_ = new MockAuthLibrary(); resolver_.reset(new MockHostResolver()); - resolver_->rules_map()[HostResolverSource::SYSTEM]->AddIPLiteralRule( + resolver_->rules_map()[HostResolverSource::ANY]->AddIPLiteralRule( "alias", "10.0.0.2", "canonical.example.com"); http_auth_preferences_.reset(new MockAllowHttpAuthPreferences()); @@ -259,9 +259,9 @@ EXPECT_EQ(OK, callback.GetResult(auth_handler->GenerateAuthToken( NULL, &request_info, callback.callback(), &token))); #if defined(OS_WIN) - EXPECT_EQ("HTTP/alias", auth_handler->spn()); + EXPECT_EQ("HTTP/alias", auth_handler->spn_for_testing()); #elif defined(OS_POSIX) - EXPECT_EQ("HTTP@alias", auth_handler->spn()); + EXPECT_EQ("HTTP@alias", auth_handler->spn_for_testing()); #endif } @@ -277,9 +277,9 @@ EXPECT_EQ(OK, callback.GetResult(auth_handler->GenerateAuthToken( NULL, &request_info, callback.callback(), &token))); #if defined(OS_WIN) - EXPECT_EQ("HTTP/alias", auth_handler->spn()); + EXPECT_EQ("HTTP/alias", auth_handler->spn_for_testing()); #elif defined(OS_POSIX) - EXPECT_EQ("HTTP@alias", auth_handler->spn()); + EXPECT_EQ("HTTP@alias", auth_handler->spn_for_testing()); #endif } @@ -295,9 +295,9 @@ EXPECT_EQ(OK, callback.GetResult(auth_handler->GenerateAuthToken( NULL, &request_info, callback.callback(), &token))); #if defined(OS_WIN) - EXPECT_EQ("HTTP/alias:500", auth_handler->spn()); + EXPECT_EQ("HTTP/alias:500", auth_handler->spn_for_testing()); #elif defined(OS_POSIX) - EXPECT_EQ("HTTP@alias:500", auth_handler->spn()); + EXPECT_EQ("HTTP@alias:500", auth_handler->spn_for_testing()); #endif } @@ -313,9 +313,9 @@ EXPECT_EQ(OK, callback.GetResult(auth_handler->GenerateAuthToken( NULL, &request_info, callback.callback(), &token))); #if defined(OS_WIN) - EXPECT_EQ("HTTP/canonical.example.com", auth_handler->spn()); + EXPECT_EQ("HTTP/canonical.example.com", auth_handler->spn_for_testing()); #elif defined(OS_POSIX) - EXPECT_EQ("HTTP@canonical.example.com", auth_handler->spn()); + EXPECT_EQ("HTTP@canonical.example.com", auth_handler->spn_for_testing()); #endif } @@ -332,9 +332,9 @@ NULL, &request_info, callback.callback(), &token)); EXPECT_THAT(callback.WaitForResult(), IsOk()); #if defined(OS_WIN) - EXPECT_EQ("HTTP/canonical.example.com", auth_handler->spn()); + EXPECT_EQ("HTTP/canonical.example.com", auth_handler->spn_for_testing()); #elif defined(OS_POSIX) - EXPECT_EQ("HTTP@canonical.example.com", auth_handler->spn()); + EXPECT_EQ("HTTP@canonical.example.com", auth_handler->spn_for_testing()); #endif }
diff --git a/net/proxy_resolution/pac_file_decider.cc b/net/proxy_resolution/pac_file_decider.cc index 9eb3640..8b5b37c7 100644 --- a/net/proxy_resolution/pac_file_decider.cc +++ b/net/proxy_resolution/pac_file_decider.cc
@@ -16,7 +16,9 @@ #include "base/strings/utf_string_conversions.h" #include "base/values.h" #include "net/base/completion_repeating_callback.h" +#include "net/base/host_port_pair.h" #include "net/base/net_errors.h" +#include "net/base/request_priority.h" #include "net/log/net_log_capture_mode.h" #include "net/log/net_log_event_type.h" #include "net/log/net_log_source_type.h" @@ -266,8 +268,20 @@ quick_check_start_time_ = base::Time::Now(); std::string host = current_pac_source().url.host(); - HostResolver::RequestInfo reqinfo(HostPortPair(host, 80)); - reqinfo.set_host_resolver_flags(HOST_RESOLVER_SYSTEM_ONLY); + + HostResolver::ResolveHostParameters parameters; + // We use HIGHEST here because proxy decision blocks doing any other requests. + parameters.initial_priority = HIGHEST; + // Only resolve via the system resolver for maximum compatibility with DNS + // suffix search paths, because for security, we are relying on suffix search + // paths rather than WPAD-standard DNS devolution. + parameters.source = HostResolverSource::SYSTEM; + + HostResolver* host_resolver = + pac_file_fetcher_->GetRequestContext()->host_resolver(); + resolve_request_ = host_resolver->CreateRequest(HostPortPair(host, 80), + net_log_, parameters); + CompletionRepeatingCallback callback = base::BindRepeating( &PacFileDecider::OnIOCompletion, base::Unretained(this)); @@ -276,12 +290,7 @@ FROM_HERE, base::TimeDelta::FromMilliseconds(kQuickCheckDelayMs), base::BindRepeating(callback, ERR_NAME_NOT_RESOLVED)); - HostResolver* host_resolver = - pac_file_fetcher_->GetRequestContext()->host_resolver(); - - // We use HIGHEST here because proxy decision blocks doing any other requests. - return host_resolver->Resolve(reqinfo, HIGHEST, &wpad_addresses_, callback, - &request_, net_log_); + return resolve_request_->Start(callback); } int PacFileDecider::DoQuickCheckComplete(int result) { @@ -291,7 +300,7 @@ UMA_HISTOGRAM_TIMES("Net.WpadQuickCheckSuccess", delta); else UMA_HISTOGRAM_TIMES("Net.WpadQuickCheckFailure", delta); - request_.reset(); + resolve_request_.reset(); quick_check_timer_.Stop(); if (result != OK) return TryToFallbackPacSource(result); @@ -473,7 +482,7 @@ switch (next_state_) { case STATE_QUICK_CHECK_COMPLETE: - request_.reset(); + resolve_request_.reset(); break; case STATE_WAIT_COMPLETE: wait_timer_.Stop(); @@ -491,7 +500,7 @@ if (dhcp_pac_file_fetcher_) dhcp_pac_file_fetcher_->Cancel(); - DCHECK(!request_); + DCHECK(!resolve_request_); DidComplete(); }
diff --git a/net/proxy_resolution/pac_file_decider.h b/net/proxy_resolution/pac_file_decider.h index af8438d41..e1f038d 100644 --- a/net/proxy_resolution/pac_file_decider.h +++ b/net/proxy_resolution/pac_file_decider.h
@@ -7,6 +7,7 @@ #include <stddef.h> +#include <memory> #include <string> #include <vector> @@ -15,7 +16,6 @@ #include "base/strings/string16.h" #include "base/time/time.h" #include "base/timer/timer.h" -#include "net/base/address_list.h" #include "net/base/completion_once_callback.h" #include "net/base/net_export.h" #include "net/dns/host_resolver.h" @@ -199,9 +199,9 @@ ProxyConfigWithAnnotation effective_config_; scoped_refptr<PacFileData> script_data_; - AddressList wpad_addresses_; + std::unique_ptr<HostResolver::ResolveHostRequest> resolve_request_; + base::OneShotTimer quick_check_timer_; - std::unique_ptr<HostResolver::Request> request_; base::Time quick_check_start_time_; DISALLOW_COPY_AND_ASSIGN(PacFileDecider);
diff --git a/net/socket/tcp_socket_unittest.cc b/net/socket/tcp_socket_unittest.cc index 62ce898..359426d 100644 --- a/net/socket/tcp_socket_unittest.cc +++ b/net/socket/tcp_socket_unittest.cc
@@ -22,6 +22,7 @@ #include "net/base/sockaddr_storage.h" #include "net/base/test_completion_callback.h" #include "net/log/net_log_source.h" +#include "net/socket/socket_descriptor.h" #include "net/socket/socket_performance_watcher.h" #include "net/socket/socket_test_util.h" #include "net/socket/tcp_client_socket.h" @@ -596,13 +597,7 @@ ASSERT_EQ(0, memcmp(&kMsg, read_buffer->data(), msg_size)); } -// Flaky on iOS device, see crbug.com/921852 -#if defined(OS_IOS) && !(TARGET_OS_SIMULATOR) -#define MAYBE_IsConnected FLAKY_IsConnected -#else -#define MAYBE_IsConnected IsConnected -#endif // defined(OS_IOS) && !(TARGET_OS_SIMULATOR) -TEST_F(TCPSocketTest, MAYBE_IsConnected) { +TEST_F(TCPSocketTest, IsConnected) { ASSERT_NO_FATAL_FAILURE(SetUpListenIPv4()); TestCompletionCallback accept_callback; @@ -642,8 +637,16 @@ 1); accepted_socket.reset(); - // |connecting_socket| should have data to read, so should still be reported - // as connected, but not idle. + // Wait until |connecting_socket| is signalled as having data to read. + fd_set read_fds; + FD_ZERO(&read_fds); + SocketDescriptor connecting_fd = + connecting_socket.SocketDescriptorForTesting(); + FD_SET(connecting_fd, &read_fds); + ASSERT_EQ(select(FD_SETSIZE, &read_fds, nullptr, nullptr, nullptr), 1); + ASSERT_TRUE(FD_ISSET(connecting_fd, &read_fds)); + + // It should now be reported as connected, but not as idle. EXPECT_TRUE(connecting_socket.IsConnected()); EXPECT_FALSE(connecting_socket.IsConnectedAndIdle());
diff --git a/remoting/host/remoting_me2me_host.cc b/remoting/host/remoting_me2me_host.cc index 105fc13..925065c 100644 --- a/remoting/host/remoting_me2me_host.cc +++ b/remoting/host/remoting_me2me_host.cc
@@ -466,10 +466,7 @@ // And remove the same line from me2me_desktop_environment.cc. - // TODO(jarhar): Replace this ifdef with a chrome policy. -#ifdef CHROME_REMOTE_DESKTOP_FILE_TRANSFER_ENABLED desktop_environment_options_.set_enable_file_transfer(true); -#endif StartOnUiThread(); }
diff --git a/remoting/protocol/webrtc_audio_stream.cc b/remoting/protocol/webrtc_audio_stream.cc index 46b996e..3028b01 100644 --- a/remoting/protocol/webrtc_audio_stream.cc +++ b/remoting/protocol/webrtc_audio_stream.cc
@@ -24,11 +24,8 @@ WebrtcAudioStream::WebrtcAudioStream() = default; WebrtcAudioStream::~WebrtcAudioStream() { - if (stream_) { - for (const auto& track : stream_->GetAudioTracks()) { - stream_->RemoveTrack(track.get()); - } - peer_connection_->RemoveStream(stream_.get()); + if (audio_sender_) { + peer_connection_->RemoveTrack(audio_sender_.get()); } } @@ -50,17 +47,11 @@ peer_connection_factory->CreateAudioTrack(kAudioTrackLabel, source_adapter_.get()); - stream_ = peer_connection_factory->CreateLocalMediaStream(kAudioStreamLabel); - - // AddTrack() may fail only if there is another track with the same name, - // which is impossible because it's a brand new stream. - bool result = stream_->AddTrack(audio_track.get()); - DCHECK(result); - - // AddStream() may fail if there is another stream with the same name or when - // the PeerConnection is closed, neither is expected. - result = peer_connection_->AddStream(stream_.get()); - DCHECK(result); + // value() DCHECKs if AddTrack() fails, which only happens if a track was + // already added with the stream label. + audio_sender_ = + peer_connection_->AddTrack(audio_track.get(), {kAudioStreamLabel}) + .value(); } void WebrtcAudioStream::Pause(bool pause) {
diff --git a/remoting/protocol/webrtc_audio_stream.h b/remoting/protocol/webrtc_audio_stream.h index 6c5981a..75ac45e 100644 --- a/remoting/protocol/webrtc_audio_stream.h +++ b/remoting/protocol/webrtc_audio_stream.h
@@ -16,8 +16,8 @@ } // namespace webrtc namespace webrtc { -class MediaStreamInterface; class PeerConnectionInterface; +class RtpSenderInterface; } // namespace webrtc namespace remoting { @@ -43,7 +43,7 @@ scoped_refptr<WebrtcAudioSourceAdapter> source_adapter_; scoped_refptr<webrtc::PeerConnectionInterface> peer_connection_; - scoped_refptr<webrtc::MediaStreamInterface> stream_; + scoped_refptr<webrtc::RtpSenderInterface> audio_sender_; DISALLOW_COPY_AND_ASSIGN(WebrtcAudioStream); };
diff --git a/remoting/protocol/webrtc_transport.cc b/remoting/protocol/webrtc_transport.cc index 23efe17..a682eb8f 100644 --- a/remoting/protocol/webrtc_transport.cc +++ b/remoting/protocol/webrtc_transport.cc
@@ -264,11 +264,7 @@ rtc_config.media_config.video.periodic_alr_bandwidth_probing = true; - // Currently, the host only supports the deprecated "Plan B" semantics, so - // specify it here. - // TODO(crbug.com/903012): Change to kUnifiedPlan and make any necessary - // changes for this to work. - rtc_config.sdp_semantics = webrtc::SdpSemantics::kPlanB; + rtc_config.sdp_semantics = webrtc::SdpSemantics::kUnifiedPlan; peer_connection_ = peer_connection_factory_->CreatePeerConnection( rtc_config, std::move(port_allocator), nullptr, this);
diff --git a/remoting/protocol/webrtc_video_stream.cc b/remoting/protocol/webrtc_video_stream.cc index b26fdb24..570c794 100644 --- a/remoting/protocol/webrtc_video_stream.cc +++ b/remoting/protocol/webrtc_video_stream.cc
@@ -100,11 +100,8 @@ WebrtcVideoStream::~WebrtcVideoStream() { DCHECK(thread_checker_.CalledOnValidThread()); - if (stream_) { - for (const auto& track : stream_->GetVideoTracks()) { - stream_->RemoveTrack(track.get()); - } - peer_connection_->RemoveStream(stream_.get()); + if (video_sender_) { + peer_connection_->RemoveTrack(video_sender_.get()); } } @@ -138,17 +135,10 @@ rtc::scoped_refptr<webrtc::VideoTrackInterface> video_track = peer_connection_factory->CreateVideoTrack(kVideoLabel, src); - stream_ = peer_connection_factory->CreateLocalMediaStream(kStreamLabel); - - // AddTrack() may fail only if there is another track with the same name, - // which is impossible because it's a brand new stream. - bool result = stream_->AddTrack(video_track.get()); - DCHECK(result); - - // AddStream() may fail if there is another stream with the same name or when - // the PeerConnection is closed, neither is expected. - result = peer_connection_->AddStream(stream_.get()); - DCHECK(result); + // value() DCHECKs if AddTrack() fails, which only happens if a track was + // already added with the stream label. + video_sender_ = + peer_connection_->AddTrack(video_track.get(), {kStreamLabel}).value(); scheduler_.reset(new WebrtcFrameSchedulerSimple(session_options_)); scheduler_->Start(
diff --git a/remoting/protocol/webrtc_video_stream.h b/remoting/protocol/webrtc_video_stream.h index 736b645..b19c8ae1 100644 --- a/remoting/protocol/webrtc_video_stream.h +++ b/remoting/protocol/webrtc_video_stream.h
@@ -25,8 +25,8 @@ #include "third_party/webrtc/modules/desktop_capture/desktop_capturer.h" namespace webrtc { -class MediaStreamInterface; class PeerConnectionInterface; +class RtpSenderInterface; } // namespace webrtc namespace remoting { @@ -87,7 +87,7 @@ scoped_refptr<InputEventTimestampsSource> event_timestamps_source_; scoped_refptr<webrtc::PeerConnectionInterface> peer_connection_; - scoped_refptr<webrtc::MediaStreamInterface> stream_; + scoped_refptr<webrtc::RtpSenderInterface> video_sender_; HostVideoStatsDispatcher video_stats_dispatcher_;
diff --git a/services/identity/public/cpp/identity_manager.cc b/services/identity/public/cpp/identity_manager.cc index 603b820..95b2734 100644 --- a/services/identity/public/cpp/identity_manager.cc +++ b/services/identity/public/cpp/identity_manager.cc
@@ -132,6 +132,10 @@ return HasAccountWithRefreshToken(GetPrimaryAccountId()); } +bool IdentityManager::AreRefreshTokensLoaded() const { + return token_service_->AreAllCredentialsLoaded(); +} + base::Optional<AccountInfo> IdentityManager::FindAccountInfoForAccountWithRefreshTokenByAccountId( const std::string& account_id) const {
diff --git a/services/identity/public/cpp/identity_manager.h b/services/identity/public/cpp/identity_manager.h index 96f9b413..cb2d38f 100644 --- a/services/identity/public/cpp/identity_manager.h +++ b/services/identity/public/cpp/identity_manager.h
@@ -230,6 +230,9 @@ // exists for the primary account. bool HasPrimaryAccountWithRefreshToken() const; + // Returns true if all refresh tokens have been loaded from disk. + bool AreRefreshTokensLoaded() const; + // Looks up and returns information for account with given |account_id|. If // the account cannot be found, return an empty optional. This is equivalent // to searching on the vector returned by GetAccountsWithRefreshTokens() but @@ -342,7 +345,6 @@ const std::string& account_id); friend void RemoveRefreshTokenForAccount(IdentityManager* identity_manager, const std::string& account_id); - friend bool AreAllCredentialsLoaded(IdentityManager* identity_manager); friend void UpdateAccountInfoForAccount(IdentityManager* identity_manager, AccountInfo account_info); friend void UpdatePersistentErrorOfRefreshTokenForAccount(
diff --git a/services/identity/public/cpp/identity_manager_unittest.cc b/services/identity/public/cpp/identity_manager_unittest.cc index 80a91d9..1f50efa 100644 --- a/services/identity/public/cpp/identity_manager_unittest.cc +++ b/services/identity/public/cpp/identity_manager_unittest.cc
@@ -2083,4 +2083,21 @@ EXPECT_EQ(foo_account_info.gaia, maybe_account_info.value().gaia); } +// Checks that AreRefreshTokensLoaded() returns true after LoadCredentials. +TEST_F(IdentityManagerTest, AreRefreshTokensLoaded) { + base::RunLoop run_loop; + identity_manager_observer()->set_on_refresh_tokens_loaded_callback( + run_loop.QuitClosure()); + + // Credentials are already loaded in SigninManager::Initialize() + // which runs even before the IdentityManager is created. That's why + // we fake the credentials loaded state and force another load in + // order to test AreRefreshTokensLoaded. + token_service()->set_all_credentials_loaded_for_testing(false); + EXPECT_FALSE(identity_manager()->AreRefreshTokensLoaded()); + token_service()->LoadCredentials(""); + run_loop.Run(); + EXPECT_TRUE(identity_manager()->AreRefreshTokensLoaded()); +} + } // namespace identity
diff --git a/services/identity/public/cpp/identity_test_utils.cc b/services/identity/public/cpp/identity_test_utils.cc index 529f678..b9048576 100644 --- a/services/identity/public/cpp/identity_test_utils.cc +++ b/services/identity/public/cpp/identity_test_utils.cc
@@ -306,10 +306,6 @@ run_loop.Run(); } -bool AreAllCredentialsLoaded(IdentityManager* identity_manager) { - return identity_manager->GetTokenService()->AreAllCredentialsLoaded(); -} - void SetCookieAccounts(FakeGaiaCookieManagerService* cookie_manager, IdentityManager* identity_manager, const std::vector<CookieParams>& cookie_accounts) {
diff --git a/services/identity/public/cpp/identity_test_utils.h b/services/identity/public/cpp/identity_test_utils.h index 29ef957..6e71aef5 100644 --- a/services/identity/public/cpp/identity_test_utils.h +++ b/services/identity/public/cpp/identity_test_utils.h
@@ -119,9 +119,6 @@ void RemoveRefreshTokenForAccount(IdentityManager* identity_manager, const std::string& account_id); -// Returns true if all credentials have been loaded from disk. -bool AreAllCredentialsLoaded(IdentityManager* identity_manager); - // Puts the given accounts into the Gaia cookie, replacing any previous // accounts. Blocks until the accounts have been set. // NOTE: See disclaimer at top of file re: direct usage.
diff --git a/services/media_session/public/cpp/media_metadata.cc b/services/media_session/public/cpp/media_metadata.cc index 79468f9..0d07d04e8 100644 --- a/services/media_session/public/cpp/media_metadata.cc +++ b/services/media_session/public/cpp/media_metadata.cc
@@ -28,7 +28,8 @@ bool MediaMetadata::operator==(const MediaMetadata& other) const { return title == other.title && artist == other.artist && - album == other.album && artwork == other.artwork; + album == other.album && artwork == other.artwork && + source_title == other.source_title; } bool MediaMetadata::operator!=(const MediaMetadata& other) const {
diff --git a/services/media_session/public/cpp/media_metadata.h b/services/media_session/public/cpp/media_metadata.h index db2ff7c..6716521 100644 --- a/services/media_session/public/cpp/media_metadata.h +++ b/services/media_session/public/cpp/media_metadata.h
@@ -75,6 +75,11 @@ // Artwork associated to the MediaSession. std::vector<MediaImage> artwork; + + // The |source_title| is a human readable title for the source of the media + // session. This could be the name of the app or the name of the site playing + // media. + base::string16 source_title; }; } // namespace media_session
diff --git a/services/media_session/public/cpp/media_session_mojom_traits.cc b/services/media_session/public/cpp/media_session_mojom_traits.cc index 067c7a2..cfddaea1 100644 --- a/services/media_session/public/cpp/media_session_mojom_traits.cc +++ b/services/media_session/public/cpp/media_session_mojom_traits.cc
@@ -32,13 +32,19 @@ media_session::MediaMetadata* out) { if (!data.ReadTitle(&out->title)) return false; + if (!data.ReadArtist(&out->artist)) return false; + if (!data.ReadAlbum(&out->album)) return false; + if (!data.ReadArtwork(&out->artwork)) return false; + if (!data.ReadSourceTitle(&out->source_title)) + return false; + return true; }
diff --git a/services/media_session/public/cpp/media_session_mojom_traits.h b/services/media_session/public/cpp/media_session_mojom_traits.h index b49dfa7..e96b276 100644 --- a/services/media_session/public/cpp/media_session_mojom_traits.h +++ b/services/media_session/public/cpp/media_session_mojom_traits.h
@@ -54,6 +54,11 @@ return metadata.artwork; } + static const base::string16& source_title( + const media_session::MediaMetadata& metadata) { + return metadata.source_title; + } + static bool Read(media_session::mojom::MediaMetadataDataView data, media_session::MediaMetadata* out); };
diff --git a/services/media_session/public/cpp/test/mock_media_session.cc b/services/media_session/public/cpp/test/mock_media_session.cc index 12ae3caf..9af4e118 100644 --- a/services/media_session/public/cpp/test/mock_media_session.cc +++ b/services/media_session/public/cpp/test/mock_media_session.cc
@@ -11,6 +11,19 @@ namespace media_session { namespace test { +namespace { + +bool IsMetadataNonEmpty(const base::Optional<MediaMetadata>& metadata) { + if (!metadata.has_value()) + return false; + + return !metadata->title.empty() || !metadata->artist.empty() || + !metadata->album.empty() || !metadata->source_title.empty() || + !metadata->artwork.empty(); +} + +} // namespace + MockMediaSessionMojoObserver::MockMediaSessionMojoObserver( mojom::MediaSession& media_session) : binding_(this) { @@ -46,7 +59,7 @@ if (waiting_for_metadata_) { run_loop_->Quit(); waiting_for_metadata_ = false; - } else if (waiting_for_non_empty_metadata_ && metadata.has_value()) { + } else if (waiting_for_non_empty_metadata_ && IsMetadataNonEmpty(metadata)) { run_loop_->Quit(); waiting_for_non_empty_metadata_ = false; }
diff --git a/services/media_session/public/mojom/media_session.mojom b/services/media_session/public/mojom/media_session.mojom index 7d9e4b2a..148bcfa 100644 --- a/services/media_session/public/mojom/media_session.mojom +++ b/services/media_session/public/mojom/media_session.mojom
@@ -38,12 +38,17 @@ }; // MediaMetadata -// Spec: https://wicg.github.io/mediasession/ struct MediaMetadata { + // These are defined in the spec: https://wicg.github.io/mediasession/ mojo_base.mojom.String16 title; mojo_base.mojom.String16 artist; mojo_base.mojom.String16 album; array<MediaImage> artwork; + + // The |source_title| is a human readable title for the source of the media + // session. This could be the name of the app or the name of the site playing + // media. + mojo_base.mojom.String16 source_title; }; // Contains state information about a MediaSession.
diff --git a/services/service_manager/public/cpp/manifest.h b/services/service_manager/public/cpp/manifest.h index 59434b9..85fe136 100644 --- a/services/service_manager/public/cpp/manifest.h +++ b/services/service_manager/public/cpp/manifest.h
@@ -111,7 +111,7 @@ // The type of sandboxing required by instances of this service. // // TODO(https://crbug.com/915806): Make this field a SandboxType enum. - std::string sandbox_type{"none"}; + std::string sandbox_type{"utility"}; }; // Represents a file required by instances of the service despite being
diff --git a/testing/buildbot/filters/mojo.fyi.chromeos.network_browser_tests.filter b/testing/buildbot/filters/mojo.fyi.chromeos.network_browser_tests.filter index f4a098e..af057de 100644 --- a/testing/buildbot/filters/mojo.fyi.chromeos.network_browser_tests.filter +++ b/testing/buildbot/filters/mojo.fyi.chromeos.network_browser_tests.filter
@@ -12,6 +12,11 @@ # Crashing on Mash. https://crbug.com/919108 -ChromeBrowserMainBrowserTest.VariationsServiceStartsRequestOnNetworkChange +# https://crbug.com/921814 +# ProxyResolutionServiceProvider needs to be converted to NetworkService. +-ProxyResolutionServiceProviderPacBrowserTest.ResolveProxy +-ProxyResolutionServiceProviderManualProxyBrowserTest.ResolveProxy + # NOTE: if adding an exclusion for an existing failure (e.g. additional test for # feature X that is already not working), please add it beside the existing # failures. Otherwise please reach out to network-service-dev@.
diff --git a/testing/buildbot/filters/mojo.fyi.network_webview_instrumentation_test_apk.filter b/testing/buildbot/filters/mojo.fyi.network_webview_instrumentation_test_apk.filter index 509a543..47a7e25 100644 --- a/testing/buildbot/filters/mojo.fyi.network_webview_instrumentation_test_apk.filter +++ b/testing/buildbot/filters/mojo.fyi.network_webview_instrumentation_test_apk.filter
@@ -48,7 +48,6 @@ -org.chromium.android_webview.test.AwContentsClientShouldInterceptRequestTest.testDoesNotChangeReportedUrl # https://crbug.com/893568 --org.chromium.android_webview.test.AwContentsTest.testCanInjectHeaders -org.chromium.android_webview.test.AwContentsTest.testDownload -org.chromium.android_webview.test.AwContentsTest.testEscapingOfErrorPage @@ -58,17 +57,10 @@ # https://crbug.com/893570 -org.chromium.android_webview.test.AwSettingsTest.testAssetUrl --org.chromium.android_webview.test.AwSettingsTest.testBlockNetworkLoadsWithAudio --org.chromium.android_webview.test.AwSettingsTest.testBlockNetworkLoadsWithHttpResources --org.chromium.android_webview.test.AwSettingsTest.testCacheModeWithBlockedNetworkLoads -org.chromium.android_webview.test.AwSettingsTest.testContentUrlAccessWithTwoViews -org.chromium.android_webview.test.AwSettingsTest.testContentUrlFromFileWithTwoViews --org.chromium.android_webview.test.AwSettingsTest.testFileAccessFromFilesIframeWithTwoViews --org.chromium.android_webview.test.AwSettingsTest.testFileAccessFromFilesImage --org.chromium.android_webview.test.AwSettingsTest.testFileAccessFromFilesXhrWithTwoViews -org.chromium.android_webview.test.AwSettingsTest.testFileUrlAccessToggleDoesNotBlockAssetUrls -org.chromium.android_webview.test.AwSettingsTest.testFileUrlAccessToggleDoesNotBlockResourceUrls --org.chromium.android_webview.test.AwSettingsTest.testFileUrlAccessWithTwoViews -org.chromium.android_webview.test.AwSettingsTest.testResourceUrl # https://crbug.com/893572
diff --git a/testing/buildbot/filters/webui_polymer2_browser_tests.filter b/testing/buildbot/filters/webui_polymer2_browser_tests.filter index 1a0ed89..a4c74a67 100644 --- a/testing/buildbot/filters/webui_polymer2_browser_tests.filter +++ b/testing/buildbot/filters/webui_polymer2_browser_tests.filter
@@ -40,6 +40,22 @@ AudioPlayerBrowserTest.* AutofillBrowserTest.* BluetoothInternalsTest.* +BookmarksActionsTest.* +BookmarksAppTest.* +BookmarksCommandManagerTest.* +BookmarksDNDManagerTest.* +BookmarksEditDialogTest.* +BookmarksFocusTest.* +BookmarksFolderNodeTest.* +BookmarksItemTest.* +BookmarksListTest.* +BookmarksPolicyTest.* +BookmarksReducersTest.* +BookmarksRouterTest.* +BookmarksStoreTest.* +BookmarksToastManagerTest.* +BookmarksToolbarTest.* +BookmarksUtilTest.* CertificateViewerModalUITest.* CertificateViewerModalUITestAsync.* CertificateViewerUITest.* @@ -210,22 +226,6 @@ LoadTimeDataTest.* LocalAndDriveFileSystemExtensionApiTest.* LocalFileSystemExtensionApiTest.* -MaterialBookmarksActionsTest.* -MaterialBookmarksAppTest.* -MaterialBookmarksCommandManagerTest.* -MaterialBookmarksDNDManagerTest.* -MaterialBookmarksEditDialogTest.* -MaterialBookmarksFocusTest.* -MaterialBookmarksFolderNodeTest.* -MaterialBookmarksItemTest.* -MaterialBookmarksListTest.* -MaterialBookmarksPolicyTest.* -MaterialBookmarksReducersTest.* -MaterialBookmarksRouterTest.* -MaterialBookmarksStoreTest.* -MaterialBookmarksToastManagerTest.* -MaterialBookmarksToolbarTest.* -MaterialBookmarksUtilTest.* MaterialHistoryBrowserServiceTest.* MaterialHistoryDrawerTest.* MaterialHistoryFocusTest.*
diff --git a/testing/buildbot/filters/webui_polymer2_interactive_ui_tests.filter b/testing/buildbot/filters/webui_polymer2_interactive_ui_tests.filter index b1325e6..61cf9be3 100644 --- a/testing/buildbot/filters/webui_polymer2_interactive_ui_tests.filter +++ b/testing/buildbot/filters/webui_polymer2_interactive_ui_tests.filter
@@ -36,6 +36,7 @@ # # There are overall very few WebUI interactive_ui_tests, so list them here # explicitly, instead of running all interactive_ui_tests. +BookmarksFocusTest.All CrElementsActionMenuTest.All CrElementsCheckboxTest.All CrElementsInputTest.All @@ -44,7 +45,6 @@ CrSettingsAnimatedPagesTest.All CrSettingsFocusRowBehavior.FocusTest CrSettingsSyncPageTest.All -MaterialBookmarksFocusTest.All MaterialHistoryFocusTest.All PrintPreviewDestinationDialogInteractiveTest.* PrintPreviewNumberSettingsSectionInteractiveTest.BlurResetsEmptyInput
diff --git a/testing/buildbot/gn_isolate_map.pyl b/testing/buildbot/gn_isolate_map.pyl index 596ced9..4d596c9 100644 --- a/testing/buildbot/gn_isolate_map.pyl +++ b/testing/buildbot/gn_isolate_map.pyl
@@ -416,11 +416,11 @@ "type": "console_test_launcher", }, "castrunner_integration_tests": { - "label": "//webrunner:castrunner_integration_tests", + "label": "//fuchsia:castrunner_integration_tests", "type": "console_test_launcher", }, "castrunner_unittests": { - "label": "//webrunner:castrunner_unittests", + "label": "//fuchsia:castrunner_unittests", "type": "console_test_launcher", }, "cast_audio_backend_unittests": { @@ -1109,7 +1109,7 @@ "type": "fuzzer", }, "http_service_tests": { - "label": "//webrunner/net_http:http_service_tests", + "label": "//fuchsia/net_http:http_service_tests", "type": "console_test_launcher", }, "hunspell_fuzzer": { @@ -2735,15 +2735,15 @@ "type": "console_test_launcher", }, "webrunner_browsertests": { - "label": "//webrunner:webrunner_browsertests", + "label": "//fuchsia:webrunner_browsertests", "type": "console_test_launcher", }, "webrunner_smoketests": { - "label": "//webrunner:webrunner_smoketests", + "label": "//fuchsia:webrunner_smoketests", "type": "console_test_launcher", }, "webrunner_unittests": { - "label": "//webrunner:webrunner_unittests", + "label": "//fuchsia:webrunner_unittests", "type": "console_test_launcher", }, "webusb_descriptors_fuzzer": {
diff --git a/third_party/android_swipe_refresh/README.chromium b/third_party/android_swipe_refresh/README.chromium index 3f23083..aa10d32 100644 --- a/third_party/android_swipe_refresh/README.chromium +++ b/third_party/android_swipe_refresh/README.chromium
@@ -13,6 +13,8 @@ CircleImageView * The package has been changed, and most ViewCompat dependencies removed. + * The class has been made visible outside of the package. + * Scalable outer circle can be drawn with a specified color. MaterialProgressDrawable * The package has been changed, and most ViewCompat dependencies removed.
diff --git a/third_party/android_swipe_refresh/java/src/org/chromium/third_party/android/swiperefresh/CircleImageView.java b/third_party/android_swipe_refresh/java/src/org/chromium/third_party/android/swiperefresh/CircleImageView.java index c5611fe1..50db63cb 100644 --- a/third_party/android_swipe_refresh/java/src/org/chromium/third_party/android/swiperefresh/CircleImageView.java +++ b/third_party/android_swipe_refresh/java/src/org/chromium/third_party/android/swiperefresh/CircleImageView.java
@@ -25,8 +25,10 @@ import android.graphics.Shader; import android.graphics.drawable.ShapeDrawable; import android.graphics.drawable.shapes.OvalShape; -import android.view.animation.Animation; +import android.support.annotation.ColorInt; +import android.support.annotation.ColorRes; import android.view.View; +import android.view.animation.Animation; import android.widget.ImageView; /** @@ -36,8 +38,7 @@ * * @hide */ -class CircleImageView extends ImageView { - +public class CircleImageView extends ImageView { private static final int KEY_SHADOW_COLOR = 0x1E000000; private static final int FILL_SHADOW_COLOR = 0x3D000000; // PX @@ -48,16 +49,27 @@ private Animation.AnimationListener mListener; private int mShadowRadius; + private int mOuterRadius; + private @ColorInt int mOuterColor; + private float mDensity; + private int mViewDimension; + + public CircleImageView(Context context, int color, final float radius) { + this(context, color, radius, 0.f, 0); + } @SuppressWarnings("deprecation") - public CircleImageView(Context context, int color, final float radius) { + public CircleImageView(Context context, @ColorRes int color, float radius, float maxRadius, + @ColorInt int outerColor) { super(context); final float density = getContext().getResources().getDisplayMetrics().density; mShadowRadius = (int) (density * SHADOW_RADIUS); + mViewDimension = (int) (maxRadius > 0.f ? (maxRadius + radius) * density : mShadowRadius); + mOuterColor = outerColor; ShapeDrawable circle; - if (elevationSupported()) { + if (elevationSupported() && maxRadius == 0.f) { circle = initializeElevated(density); } else { circle = initializeNonElevated(radius, density); @@ -68,6 +80,7 @@ } else { setBackground(circle); } + mDensity = density; } ShapeDrawable initializeElevated(float density) { @@ -85,7 +98,8 @@ setLayerType(View.LAYER_TYPE_SOFTWARE, circle.getPaint()); circle.getPaint().setShadowLayer(mShadowRadius, shadowXOffset, shadowYOffset, KEY_SHADOW_COLOR); - final int padding = mShadowRadius; + + final int padding = mViewDimension; // set padding so the inner image sits correctly within the shadow. setPadding(padding, padding, padding, padding); return circle; @@ -98,9 +112,9 @@ @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); - if (!elevationSupported()) { - setMeasuredDimension(getMeasuredWidth() + mShadowRadius*2, getMeasuredHeight() - + mShadowRadius*2); + if (!elevationSupported() || mViewDimension > mShadowRadius) { + setMeasuredDimension(getMeasuredWidth() + mViewDimension * 2, + getMeasuredHeight() + mViewDimension * 2); } } @@ -140,10 +154,15 @@ } } + public void setProgress(float progress) { + mOuterRadius = (int) (progress * mViewDimension); + } + private class OvalShadow extends OvalShape { private RadialGradient mRadialGradient; private int mShadowRadius; private Paint mShadowPaint; + private Paint mOuterPaint; private int mCircleDiameter; public OvalShadow(int shadowRadius, int circleDiameter) { @@ -164,6 +183,14 @@ final int viewHeight = CircleImageView.this.getHeight(); canvas.drawCircle(viewWidth / 2f, viewHeight / 2f, (mCircleDiameter / 2f + mShadowRadius), mShadowPaint); + if (mOuterRadius > 0.f) { + if (mOuterPaint == null) { + mOuterPaint = new Paint(); + mOuterPaint.setColor(getResources().getColor(mOuterColor)); + mOuterPaint.setAlpha(0x80); + } + canvas.drawCircle(viewWidth / 2f, viewHeight / 2f, mOuterRadius, mOuterPaint); + } canvas.drawCircle(viewWidth / 2f, viewHeight / 2f, (mCircleDiameter / 2f), paint); } }
diff --git a/third_party/blink/public/platform/web_feature.mojom b/third_party/blink/public/platform/web_feature.mojom index 146d8ea..d8e0456 100644 --- a/third_party/blink/public/platform/web_feature.mojom +++ b/third_party/blink/public/platform/web_feature.mojom
@@ -2170,6 +2170,7 @@ kV8HTMLMediaElement_CaptureStream_Method = 2729, kQuirkyLineBoxBackgroundSize = 2730, kDirectlyCompositedImage = 2731, + kForbiddenSyncXhrInPageDismissal = 2732, // Add new features immediately above this line. Don't change assigned // numbers of any item, and don't reuse removed slots.
diff --git a/third_party/blink/public/platform/web_resource_timing_info.h b/third_party/blink/public/platform/web_resource_timing_info.h index 835372cb..65e7f29 100644 --- a/third_party/blink/public/platform/web_resource_timing_info.h +++ b/third_party/blink/public/platform/web_resource_timing_info.h
@@ -53,6 +53,7 @@ uint64_t decoded_body_size; bool did_reuse_connection; + bool is_secure_context; // TODO(dcheng): The way this code works is fairly confusing: it might seem // unusual to store policy members like |allow_timing_details| inline, rather
diff --git a/third_party/blink/public/platform/web_runtime_features.h b/third_party/blink/public/platform/web_runtime_features.h index 5f95096..cc9ad06 100644 --- a/third_party/blink/public/platform/web_runtime_features.h +++ b/third_party/blink/public/platform/web_runtime_features.h
@@ -165,6 +165,8 @@ BLINK_PLATFORM_EXPORT static void EnableSharedArrayBuffer(bool); BLINK_PLATFORM_EXPORT static void EnableSharedWorker(bool); BLINK_PLATFORM_EXPORT static void EnableTouchEventFeatureDetection(bool); + BLINK_PLATFORM_EXPORT static void EnableUserActivationSameOriginVisibility( + bool); BLINK_PLATFORM_EXPORT static void EnableUserActivationV2(bool); BLINK_PLATFORM_EXPORT static void EnableV8IdleTasks(bool); BLINK_PLATFORM_EXPORT static void EnableWebAuth(bool);
diff --git a/third_party/blink/public/platform/web_video_frame_submitter.h b/third_party/blink/public/platform/web_video_frame_submitter.h index 4a9b5a74..1678f1a 100644 --- a/third_party/blink/public/platform/web_video_frame_submitter.h +++ b/third_party/blink/public/platform/web_video_frame_submitter.h
@@ -50,11 +50,11 @@ virtual void Initialize(cc::VideoFrameProvider*) = 0; // Set the rotation state of the video to be used while appending frames. + // + // TODO(dalecurtis): This could be removed in favor of getting it from each + // VideoFrame, but today that information isn't set everywhere. virtual void SetRotation(media::VideoRotation) = 0; - // Set if the video is opaque or not. - virtual void SetIsOpaque(bool) = 0; - // Prepares the compositor frame sink to accept frames by providing // a SurfaceId, with its associated allocation time. The callback is to be // used when on context loss to prevent the submitter from continuing to
diff --git a/third_party/blink/renderer/core/BUILD.gn b/third_party/blink/renderer/core/BUILD.gn index 2a1ca29..7bced7dd 100644 --- a/third_party/blink/renderer/core/BUILD.gn +++ b/third_party/blink/renderer/core/BUILD.gn
@@ -1953,7 +1953,6 @@ "html/image_document_test.cc", "html/imports/html_import_sheets_test.cc", "html/lazy_load_frame_observer_test.cc", - "html/lazy_load_image_observer_test.cc", "html/link_element_loading_test.cc", "html/link_rel_attribute_test.cc", "html/list_item_ordinal_test.cc",
diff --git a/third_party/blink/renderer/core/clipboard/system_clipboard.cc b/third_party/blink/renderer/core/clipboard/system_clipboard.cc index f696ad8..a889c15 100644 --- a/third_party/blink/renderer/core/clipboard/system_clipboard.cc +++ b/third_party/blink/renderer/core/clipboard/system_clipboard.cc
@@ -169,7 +169,7 @@ SkBitmap bitmap; if (sk_sp<SkImage> sk_image = paint_image.GetSkImage()) sk_image->asLegacyBitmap(&bitmap); - WriteImageNoCommit(bitmap); + clipboard_->WriteImage(mojom::ClipboardBuffer::kStandard, bitmap); if (url.IsValid() && !url.IsEmpty()) { #if !defined(OS_MACOSX) @@ -192,8 +192,7 @@ } void SystemClipboard::WriteImage(const SkBitmap& bitmap) { - WriteImageNoCommit(bitmap); - + clipboard_->WriteImage(mojom::ClipboardBuffer::kStandard, bitmap); clipboard_->CommitWrite(mojom::ClipboardBuffer::kStandard); } @@ -256,13 +255,4 @@ return true; } -void SystemClipboard::WriteImageNoCommit(const SkBitmap& bitmap) { - if (bitmap.isNull()) - return; - // TODO(crbug.com/918717): Remove CHECK if no crashes occur on it in canary. - CHECK(bitmap.getPixels()); - - clipboard_->WriteImage(mojom::ClipboardBuffer::kStandard, bitmap); -} - } // namespace blink
diff --git a/third_party/blink/renderer/core/clipboard/system_clipboard.h b/third_party/blink/renderer/core/clipboard/system_clipboard.h index e266a08..ca65a4414 100644 --- a/third_party/blink/renderer/core/clipboard/system_clipboard.h +++ b/third_party/blink/renderer/core/clipboard/system_clipboard.h
@@ -61,7 +61,6 @@ private: SystemClipboard(); bool IsValidBufferType(mojom::ClipboardBuffer); - void WriteImageNoCommit(const SkBitmap&); mojom::blink::ClipboardHostPtr clipboard_; mojom::ClipboardBuffer buffer_ = mojom::ClipboardBuffer::kStandard;
diff --git a/third_party/blink/renderer/core/css/css_image_value.cc b/third_party/blink/renderer/core/css/css_image_value.cc index 7627124ae..b8521faa 100644 --- a/third_party/blink/renderer/core/css/css_image_value.cc +++ b/third_party/blink/renderer/core/css/css_image_value.cc
@@ -78,16 +78,13 @@ document.GetFrame()->IsClientLoFiAllowed(params.GetResourceRequest())) { params.SetClientLoFiPlaceholder(); } - bool is_lazily_loaded = - image_request_optimization == FetchParameters::kDeferImageLoad && + cached_image_ = StyleFetchedImage::Create( + document, params, // Only http/https images are eligible to be lazily loaded. - params.Url().ProtocolIsInHTTPFamily(); - if (is_lazily_loaded) - params.SetLazyImageDeferred(); - - cached_image_ = - StyleFetchedImage::Create(document, params, is_lazily_loaded); + params.Url().ProtocolIsInHTTPFamily() && + image_request_optimization == FetchParameters::kDeferImageLoad); } + return cached_image_.Get(); }
diff --git a/third_party/blink/renderer/core/exported/web_remote_frame_impl.cc b/third_party/blink/renderer/core/exported/web_remote_frame_impl.cc index fee07e3..6386fc5 100644 --- a/third_party/blink/renderer/core/exported/web_remote_frame_impl.cc +++ b/third_party/blink/renderer/core/exported/web_remote_frame_impl.cc
@@ -301,8 +301,7 @@ ToHTMLFrameOwnerElement(frame_->Owner()); DCHECK(owner_element); DOMWindowPerformance::performance(*parent_frame->GetFrame()->DomWindow()) - ->AddResourceTiming(info, owner_element->localName(), - owner_element->GetDocument().IsSecureContext()); + ->AddResourceTiming(info, owner_element->localName()); } void WebRemoteFrameImpl::DispatchLoadEventForFrameOwner() {
diff --git a/third_party/blink/renderer/core/exported/web_shared_worker_impl.cc b/third_party/blink/renderer/core/exported/web_shared_worker_impl.cc index cb192069..94973cfa 100644 --- a/third_party/blink/renderer/core/exported/web_shared_worker_impl.cc +++ b/third_party/blink/renderer/core/exported/web_shared_worker_impl.cc
@@ -320,8 +320,11 @@ auto global_scope_creation_params = std::make_unique<GlobalScopeCreationParams>( - script_response_url, script_type, document->UserAgent(), - std::move(web_worker_fetch_context), + script_response_url, script_type, + // TODO(nhiroki): Implement off-the-main-thread worker script fetch + // for shared workers (https://crbug.com/835717). + OffMainThreadWorkerScriptFetchOption::kDisabled, + document->UserAgent(), std::move(web_worker_fetch_context), content_security_policy ? content_security_policy->Headers() : Vector<CSPHeaderAndType>(), referrer_policy, outside_settings_object->GetSecurityOrigin(),
diff --git a/third_party/blink/renderer/core/frame/frame.cc b/third_party/blink/renderer/core/frame/frame.cc index 3739269..ec10f62c 100644 --- a/third_party/blink/renderer/core/frame/frame.cc +++ b/third_party/blink/renderer/core/frame/frame.cc
@@ -188,6 +188,22 @@ void Frame::NotifyUserActivationInLocalTree() { for (Frame* node = this; node; node = node->Tree().Parent()) node->user_activation_state_.Activate(); + + // See FrameTreeNode::NotifyUserActivation() for details about this block. + if (IsLocalFrame() && RuntimeEnabledFeatures::UserActivationV2Enabled() && + RuntimeEnabledFeatures::UserActivationSameOriginVisibilityEnabled()) { + const SecurityOrigin* security_origin = + ToLocalFrame(this)->GetSecurityContext()->GetSecurityOrigin(); + + Frame& root = Tree().Top(); + for (Frame* node = &root; node; node = node->Tree().TraverseNext(&root)) { + if (node->IsLocalFrame() && + security_origin->CanAccess( + ToLocalFrame(node)->GetSecurityContext()->GetSecurityOrigin())) { + node->user_activation_state_.Activate(); + } + } + } } bool Frame::ConsumeTransientUserActivationInLocalTree() {
diff --git a/third_party/blink/renderer/core/frame/reporting_context.cc b/third_party/blink/renderer/core/frame/reporting_context.cc index 7692ab2..e749011 100644 --- a/third_party/blink/renderer/core/frame/reporting_context.cc +++ b/third_party/blink/renderer/core/frame/reporting_context.cc
@@ -33,12 +33,16 @@ void ReportingContext::QueueReport(Report* report) { CountReport(report); - report_buffer_.insert(report); - // Only the most recent 100 reports will remain buffered. + // Buffer the report. + if (!report_buffer_.Contains(report->type())) + report_buffer_.insert(report->type(), HeapListHashSet<Member<Report>>()); + report_buffer_.find(report->type())->value.insert(report); + + // Only the most recent 100 reports will remain buffered, per report type. // https://w3c.github.io/reporting/#notify-observers - if (report_buffer_.size() > 100) - report_buffer_.RemoveFirst(); + if (report_buffer_.at(report->type()).size() > 100) + report_buffer_.find(report->type())->value.RemoveFirst(); for (auto observer : observers_) observer->QueueReport(report); @@ -69,8 +73,11 @@ return; observer->ClearBuffered(); - for (auto report : report_buffer_) - observer->QueueReport(report); + for (auto type : report_buffer_) { + for (Report* report : type.value) { + observer->QueueReport(report); + } + } } void ReportingContext::UnregisterObserver(ReportingObserver* observer) {
diff --git a/third_party/blink/renderer/core/frame/reporting_context.h b/third_party/blink/renderer/core/frame/reporting_context.h index 9332439b..4b86d99 100644 --- a/third_party/blink/renderer/core/frame/reporting_context.h +++ b/third_party/blink/renderer/core/frame/reporting_context.h
@@ -8,6 +8,7 @@ #include "third_party/blink/renderer/core/core_export.h" #include "third_party/blink/renderer/core/execution_context/execution_context.h" #include "third_party/blink/renderer/platform/supplementable.h" +#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" namespace blink { @@ -46,7 +47,7 @@ private: HeapListHashSet<Member<ReportingObserver>> observers_; - HeapListHashSet<Member<Report>> report_buffer_; + HeapHashMap<String, HeapListHashSet<Member<Report>>> report_buffer_; Member<ExecutionContext> execution_context_; };
diff --git a/third_party/blink/renderer/core/html/lazy_load_image_observer_test.cc b/third_party/blink/renderer/core/html/lazy_load_image_observer_test.cc deleted file mode 100644 index 887dae0..0000000 --- a/third_party/blink/renderer/core/html/lazy_load_image_observer_test.cc +++ /dev/null
@@ -1,99 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "third_party/blink/renderer/core/html/lazy_load_image_observer.h" - -#include "third_party/blink/renderer/core/dom/node_computed_style.h" -#include "third_party/blink/renderer/core/frame/local_frame_view.h" -#include "third_party/blink/renderer/core/frame/settings.h" -#include "third_party/blink/renderer/core/html/html_element.h" -#include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h" -#include "third_party/blink/renderer/core/style/computed_style.h" -#include "third_party/blink/renderer/core/style/style_image.h" -#include "third_party/blink/renderer/core/testing/sim/sim_compositor.h" -#include "third_party/blink/renderer/core/testing/sim/sim_request.h" -#include "third_party/blink/renderer/core/testing/sim/sim_test.h" -#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h" -#include "third_party/blink/renderer/platform/testing/unit_test_helpers.h" - -namespace blink { - -namespace { - -class LazyLoadImagesSimTest : public SimTest { - protected: - LazyLoadImagesSimTest() : scoped_lazy_image_loading_for_test_(true) {} - void SetLazyLoadEnabled(bool enabled) { - WebView().GetPage()->GetSettings().SetLazyLoadEnabled(enabled); - } - - void LoadMainResource() { - SimRequest main_resource("https://example.com/", "text/html"); - LoadURL("https://example.com/"); - - main_resource.Complete(String::Format(R"HTML( - <style> - #deferred_image { - height:200px; - background-image: url('img.jpg'); - } - </style> - <div style='height:10000px;'></div> - <div id="deferred_image"></div> - )HTML")); - } - - void ExpectCSSBackgroundImageDeferredState(bool deferred) { - const ComputedStyle* deferred_image_style = - GetDocument().getElementById("deferred_image")->GetComputedStyle(); - EXPECT_TRUE(deferred_image_style->HasBackgroundImage()); - bool is_background_image_found = false; - for (const FillLayer* background_layer = - &deferred_image_style->BackgroundLayers(); - background_layer; background_layer = background_layer->Next()) { - if (StyleImage* deferred_image = background_layer->GetImage()) { - EXPECT_TRUE(deferred_image->IsImageResource()); - EXPECT_EQ(deferred, deferred_image->IsLazyloadPossiblyDeferred()); - EXPECT_NE(deferred, deferred_image->IsLoaded()); - is_background_image_found = true; - } - } - EXPECT_TRUE(is_background_image_found); - } - - private: - ScopedLazyImageLoadingForTest scoped_lazy_image_loading_for_test_; -}; - -TEST_F(LazyLoadImagesSimTest, CSSBackgroundImageLoadedWithoutLazyLoad) { - SetLazyLoadEnabled(false); - SimRequest image_resource("https://example.com/img.jpg", "image/jpeg"); - LoadMainResource(); - image_resource.Complete(""); - Compositor().BeginFrame(); - test::RunPendingTasks(); - ExpectCSSBackgroundImageDeferredState(false); -} - -TEST_F(LazyLoadImagesSimTest, CSSBackgroundImageDeferredWithLazyLoad) { - SetLazyLoadEnabled(true); - LoadMainResource(); - Compositor().BeginFrame(); - test::RunPendingTasks(); - - ExpectCSSBackgroundImageDeferredState(true); - - // Scroll down until the background image is visible. - GetDocument().View()->LayoutViewport()->SetScrollOffset( - ScrollOffset(0, 10000), kProgrammaticScroll); - SimRequest image_resource("https://example.com/img.jpg", "image/jpeg"); - Compositor().BeginFrame(); - test::RunPendingTasks(); - image_resource.Complete(""); - ExpectCSSBackgroundImageDeferredState(false); -} - -} // namespace - -} // namespace blink
diff --git a/third_party/blink/renderer/core/layout/custom/layout_worklet_global_scope_proxy.cc b/third_party/blink/renderer/core/layout/custom/layout_worklet_global_scope_proxy.cc index 89a5b15d..bd07119b 100644 --- a/third_party/blink/renderer/core/layout/custom/layout_worklet_global_scope_proxy.cc +++ b/third_party/blink/renderer/core/layout/custom/layout_worklet_global_scope_proxy.cc
@@ -41,7 +41,8 @@ worker_clients, frame->Client()->CreateWorkerContentSettingsClient()); auto creation_params = std::make_unique<GlobalScopeCreationParams>( - document->Url(), mojom::ScriptType::kModule, document->UserAgent(), + document->Url(), mojom::ScriptType::kModule, + OffMainThreadWorkerScriptFetchOption::kEnabled, document->UserAgent(), frame->Client()->CreateWorkerFetchContext(), document->GetContentSecurityPolicy()->Headers(), document->GetReferrerPolicy(), document->GetSecurityOrigin(),
diff --git a/third_party/blink/renderer/core/loader/modulescript/module_script_loader_test.cc b/third_party/blink/renderer/core/loader/modulescript/module_script_loader_test.cc index b163374..2830a2a 100644 --- a/third_party/blink/renderer/core/loader/modulescript/module_script_loader_test.cc +++ b/third_party/blink/renderer/core/loader/modulescript/module_script_loader_test.cc
@@ -183,7 +183,8 @@ ResourceFetcherInit(*properties, fetch_context)); reporting_proxy_ = std::make_unique<MockWorkerReportingProxy>(); auto creation_params = std::make_unique<GlobalScopeCreationParams>( - url_, mojom::ScriptType::kModule, "UserAgent", + url_, mojom::ScriptType::kModule, + OffMainThreadWorkerScriptFetchOption::kEnabled, "UserAgent", nullptr /* web_worker_fetch_context */, Vector<CSPHeaderAndType>(), network::mojom::ReferrerPolicy::kDefault, security_origin_.get(), true /* is_secure_context */, HttpsState::kModern,
diff --git a/third_party/blink/renderer/core/paint/box_paint_invalidator.cc b/third_party/blink/renderer/core/paint/box_paint_invalidator.cc index 1b965c0..af885a2f 100644 --- a/third_party/blink/renderer/core/paint/box_paint_invalidator.cc +++ b/third_party/blink/renderer/core/paint/box_paint_invalidator.cc
@@ -244,13 +244,8 @@ new_background_rect.Size() != old_background_rect.Size(); if (background_location_changed || background_size_changed) { for (auto* object : - layout_view.GetFrameView()->BackgroundAttachmentFixedObjects()) { - if (background_location_changed || - ShouldFullyInvalidateFillLayersOnSizeChange( - object->StyleRef().BackgroundLayers(), old_background_rect.Size(), - new_background_rect.Size())) - object->SetBackgroundNeedsFullPaintInvalidation(); - } + layout_view.GetFrameView()->BackgroundAttachmentFixedObjects()) + object->SetBackgroundNeedsFullPaintInvalidation(); } if (background_location_changed ||
diff --git a/third_party/blink/renderer/core/timing/performance.cc b/third_party/blink/renderer/core/timing/performance.cc index 547eac2..2d6a700 100644 --- a/third_party/blink/renderer/core/timing/performance.cc +++ b/third_party/blink/renderer/core/timing/performance.cc
@@ -480,8 +480,7 @@ return; AddResourceTiming( GenerateResourceTiming(*security_origin, info, *context), - !initiator_type.IsNull() ? initiator_type : info.InitiatorType(), - context->IsSecureContext()); + !initiator_type.IsNull() ? initiator_type : info.InitiatorType()); } WebResourceTimingInfo Performance::GenerateResourceTiming( @@ -537,6 +536,8 @@ result.encoded_body_size = final_response.EncodedBodyLength(); result.decoded_body_size = final_response.DecodedBodyLength(); result.did_reuse_connection = final_response.ConnectionReused(); + result.is_secure_context = + SecurityOrigin::IsSecure(final_response.ResponseUrl()); result.allow_negative_values = info.NegativeAllowed(); if (result.allow_timing_details) { @@ -551,10 +552,9 @@ } void Performance::AddResourceTiming(const WebResourceTimingInfo& info, - const AtomicString& initiator_type, - bool is_secure_context) { - PerformanceEntry* entry = PerformanceResourceTiming::Create( - info, time_origin_, initiator_type, is_secure_context); + const AtomicString& initiator_type) { + PerformanceEntry* entry = + PerformanceResourceTiming::Create(info, time_origin_, initiator_type); NotifyObserversOfEntry(*entry); // https://w3c.github.io/resource-timing/#dfn-add-a-performanceresourcetiming-entry if (CanAddResourceTimingEntry() &&
diff --git a/third_party/blink/renderer/core/timing/performance.h b/third_party/blink/renderer/core/timing/performance.h index ab0e171..40f15693 100644 --- a/third_party/blink/renderer/core/timing/performance.h +++ b/third_party/blink/renderer/core/timing/performance.h
@@ -149,8 +149,7 @@ const ResourceTimingInfo&, ExecutionContext& context_for_use_counter); void AddResourceTiming(const WebResourceTimingInfo&, - const AtomicString& initiator_type, - bool is_secure_context); + const AtomicString& initiator_type); void NotifyNavigationTimingToObservers();
diff --git a/third_party/blink/renderer/core/timing/performance_resource_timing.cc b/third_party/blink/renderer/core/timing/performance_resource_timing.cc index 5bd7d15..bb8cb0d3 100644 --- a/third_party/blink/renderer/core/timing/performance_resource_timing.cc +++ b/third_party/blink/renderer/core/timing/performance_resource_timing.cc
@@ -45,8 +45,7 @@ PerformanceResourceTiming::PerformanceResourceTiming( const WebResourceTimingInfo& info, TimeTicks time_origin, - const AtomicString& initiator_type, - bool is_secure_context) + const AtomicString& initiator_type) : PerformanceEntry(info.name, Performance::MonotonicTimeToDOMHighResTimeStamp( time_origin, @@ -73,7 +72,7 @@ allow_timing_details_(info.allow_timing_details), allow_redirect_details_(info.allow_redirect_details), allow_negative_value_(info.allow_negative_values), - is_secure_context_(is_secure_context), + is_secure_context_(info.is_secure_context), server_timing_( PerformanceServerTiming::FromParsedServerTiming(info.server_timing)) { }
diff --git a/third_party/blink/renderer/core/timing/performance_resource_timing.h b/third_party/blink/renderer/core/timing/performance_resource_timing.h index 21405a4..6057885 100644 --- a/third_party/blink/renderer/core/timing/performance_resource_timing.h +++ b/third_party/blink/renderer/core/timing/performance_resource_timing.h
@@ -56,15 +56,13 @@ const WebVector<WebServerTimingInfo>&); PerformanceResourceTiming(const WebResourceTimingInfo&, TimeTicks time_origin, - const AtomicString& initiator_type, - bool is_secure_context); + const AtomicString& initiator_type); ~PerformanceResourceTiming() override; static PerformanceResourceTiming* Create(const WebResourceTimingInfo& info, TimeTicks time_origin, - const AtomicString& initiator_type, - bool is_secure_context) { - return MakeGarbageCollected<PerformanceResourceTiming>( - info, time_origin, initiator_type, is_secure_context); + const AtomicString& initiator_type) { + return MakeGarbageCollected<PerformanceResourceTiming>(info, time_origin, + initiator_type); } AtomicString entryType() const override;
diff --git a/third_party/blink/renderer/core/workers/dedicated_worker.cc b/third_party/blink/renderer/core/workers/dedicated_worker.cc index e05d63b7..3447a81 100644 --- a/third_party/blink/renderer/core/workers/dedicated_worker.cc +++ b/third_party/blink/renderer/core/workers/dedicated_worker.cc
@@ -225,7 +225,8 @@ .GetFetchClientSettingsObject()); context_proxy_->StartWorkerGlobalScope( CreateGlobalScopeCreationParams( - script_request_url_, network::mojom::ReferrerPolicy::kDefault), + script_request_url_, OffMainThreadWorkerScriptFetchOption::kEnabled, + network::mojom::ReferrerPolicy::kDefault), options_, script_request_url_, outside_settings_object, stack_id, String() /* source_code */); return; @@ -358,7 +359,9 @@ ->Context() .GetFetchClientSettingsObject()); context_proxy_->StartWorkerGlobalScope( - CreateGlobalScopeCreationParams(script_response_url, referrer_policy), + CreateGlobalScopeCreationParams( + script_response_url, + OffMainThreadWorkerScriptFetchOption::kDisabled, referrer_policy), options_, script_response_url, outside_settings_object, stack_id, classic_script_loader_->SourceText()); probe::scriptImported(GetExecutionContext(), @@ -371,6 +374,7 @@ std::unique_ptr<GlobalScopeCreationParams> DedicatedWorker::CreateGlobalScopeCreationParams( const KURL& script_url, + OffMainThreadWorkerScriptFetchOption off_main_thread_fetch_option, network::mojom::ReferrerPolicy referrer_policy) { base::UnguessableToken parent_devtools_token; std::unique_ptr<WorkerSettings> settings; @@ -409,8 +413,8 @@ } return std::make_unique<GlobalScopeCreationParams>( - script_url, script_type, GetExecutionContext()->UserAgent(), - std::move(web_worker_fetch_context), + script_url, script_type, off_main_thread_fetch_option, + GetExecutionContext()->UserAgent(), std::move(web_worker_fetch_context), GetExecutionContext()->GetContentSecurityPolicy()->Headers(), referrer_policy, GetExecutionContext()->GetSecurityOrigin(), GetExecutionContext()->IsSecureContext(),
diff --git a/third_party/blink/renderer/core/workers/dedicated_worker.h b/third_party/blink/renderer/core/workers/dedicated_worker.h index 80e7073..0a17083 100644 --- a/third_party/blink/renderer/core/workers/dedicated_worker.h +++ b/third_party/blink/renderer/core/workers/dedicated_worker.h
@@ -12,6 +12,7 @@ #include "third_party/blink/renderer/core/dom/events/event_target.h" #include "third_party/blink/renderer/core/messaging/message_port.h" #include "third_party/blink/renderer/core/workers/abstract_worker.h" +#include "third_party/blink/renderer/core/workers/global_scope_creation_params.h" #include "third_party/blink/renderer/core/workers/worker_options.h" #include "third_party/blink/renderer/platform/graphics/begin_frame_provider.h" #include "third_party/blink/renderer/platform/weborigin/kurl.h" @@ -30,7 +31,6 @@ class ScriptState; class WorkerClassicScriptLoader; class WorkerClients; -struct GlobalScopeCreationParams; // Implementation of the Worker interface defined in the WebWorker HTML spec: // https://html.spec.whatwg.org/multipage/workers.html#worker @@ -90,6 +90,7 @@ std::unique_ptr<GlobalScopeCreationParams> CreateGlobalScopeCreationParams( const KURL& script_url, + OffMainThreadWorkerScriptFetchOption, network::mojom::ReferrerPolicy); WorkerClients* CreateWorkerClients();
diff --git a/third_party/blink/renderer/core/workers/dedicated_worker_messaging_proxy.cc b/third_party/blink/renderer/core/workers/dedicated_worker_messaging_proxy.cc index 8a78aa6c..0663b31f 100644 --- a/third_party/blink/renderer/core/workers/dedicated_worker_messaging_proxy.cc +++ b/third_party/blink/renderer/core/workers/dedicated_worker_messaging_proxy.cc
@@ -51,6 +51,9 @@ return; } + OffMainThreadWorkerScriptFetchOption off_main_thread_fetch_option = + creation_params->off_main_thread_fetch_option; + InitializeWorkerThread( std::move(creation_params), CreateBackingThreadStartupData(GetExecutionContext()->GetIsolate())); @@ -60,15 +63,20 @@ if (options->type() == "classic") { // "classic: Fetch a classic worker script given url, outside settings, // destination, and inside settings." - if (RuntimeEnabledFeatures::OffMainThreadWorkerScriptFetchEnabled()) { - GetWorkerThread()->ImportClassicScript(script_url, - outside_settings_object, stack_id); - } else { - // Legacy code path (to be deprecated, see https://crbug.com/835717): - GetWorkerThread()->EvaluateClassicScript( - script_url, source_code, nullptr /* cached_meta_data */, stack_id); + switch (off_main_thread_fetch_option) { + case OffMainThreadWorkerScriptFetchOption::kEnabled: + GetWorkerThread()->ImportClassicScript( + script_url, outside_settings_object, stack_id); + break; + case OffMainThreadWorkerScriptFetchOption::kDisabled: + // Legacy code path (to be deprecated, see https://crbug.com/835717): + GetWorkerThread()->EvaluateClassicScript( + script_url, source_code, nullptr /* cached_meta_data */, stack_id); + break; } } else if (options->type() == "module") { + DCHECK_EQ(off_main_thread_fetch_option, + OffMainThreadWorkerScriptFetchOption::kEnabled); // "module: Fetch a module worker script graph given url, outside settings, // destination, the value of the credentials member of options, and inside // settings."
diff --git a/third_party/blink/renderer/core/workers/dedicated_worker_test.cc b/third_party/blink/renderer/core/workers/dedicated_worker_test.cc index ab02737e..6ee8ad3 100644 --- a/third_party/blink/renderer/core/workers/dedicated_worker_test.cc +++ b/third_party/blink/renderer/core/workers/dedicated_worker_test.cc
@@ -134,7 +134,8 @@ To<Document>(GetExecutionContext())->GetSettings()); InitializeWorkerThread( std::make_unique<GlobalScopeCreationParams>( - script_url, mojom::ScriptType::kClassic, "fake user agent", + script_url, mojom::ScriptType::kClassic, + OffMainThreadWorkerScriptFetchOption::kDisabled, "fake user agent", nullptr /* web_worker_fetch_context */, headers, network::mojom::ReferrerPolicy::kDefault, security_origin_.get(), false /* starter_secure_context */,
diff --git a/third_party/blink/renderer/core/workers/experimental/thread_pool.cc b/third_party/blink/renderer/core/workers/experimental/thread_pool.cc index 0a93e758..93e729cb 100644 --- a/third_party/blink/renderer/core/workers/experimental/thread_pool.cc +++ b/third_party/blink/renderer/core/workers/experimental/thread_pool.cc
@@ -112,7 +112,8 @@ // WebWorkerFetchContext is provided later in // ThreadedMessagingProxyBase::InitializeWorkerThread(). proxy->StartWorker(std::make_unique<GlobalScopeCreationParams>( - context->Url(), mojom::ScriptType::kClassic, context->UserAgent(), + context->Url(), mojom::ScriptType::kClassic, + OffMainThreadWorkerScriptFetchOption::kDisabled, context->UserAgent(), nullptr /* web_worker_fetch_context */, context->GetContentSecurityPolicy()->Headers(), network::mojom::ReferrerPolicy::kDefault, context->GetSecurityOrigin(),
diff --git a/third_party/blink/renderer/core/workers/global_scope_creation_params.cc b/third_party/blink/renderer/core/workers/global_scope_creation_params.cc index 51b2c32b..0e51209 100644 --- a/third_party/blink/renderer/core/workers/global_scope_creation_params.cc +++ b/third_party/blink/renderer/core/workers/global_scope_creation_params.cc
@@ -6,12 +6,14 @@ #include <memory> #include "third_party/blink/renderer/platform/network/content_security_policy_parsers.h" +#include "third_party/blink/renderer/platform/runtime_enabled_features.h" namespace blink { GlobalScopeCreationParams::GlobalScopeCreationParams( const KURL& script_url, mojom::ScriptType script_type, + OffMainThreadWorkerScriptFetchOption off_main_thread_fetch_option, const String& user_agent, scoped_refptr<WebWorkerFetchContext> web_worker_fetch_context, const Vector<CSPHeaderAndType>& content_security_policy_parsed_headers, @@ -33,6 +35,7 @@ base::UnguessableToken agent_cluster_id) : script_url(script_url.Copy()), script_type(script_type), + off_main_thread_fetch_option(off_main_thread_fetch_option), user_agent(user_agent.IsolatedCopy()), web_worker_fetch_context(std::move(web_worker_fetch_context)), referrer_policy(referrer_policy), @@ -54,6 +57,19 @@ ParsedFeaturePolicy() /* container_policy */, starter_origin->ToUrlOrigin())), agent_cluster_id(agent_cluster_id) { + switch (this->script_type) { + case mojom::ScriptType::kClassic: + if (this->off_main_thread_fetch_option == + OffMainThreadWorkerScriptFetchOption::kEnabled) { + DCHECK(RuntimeEnabledFeatures::OffMainThreadWorkerScriptFetchEnabled()); + } + break; + case mojom::ScriptType::kModule: + DCHECK_EQ(this->off_main_thread_fetch_option, + OffMainThreadWorkerScriptFetchOption::kEnabled); + break; + } + this->content_security_policy_parsed_headers.ReserveInitialCapacity( content_security_policy_parsed_headers.size()); for (const auto& header : content_security_policy_parsed_headers) {
diff --git a/third_party/blink/renderer/core/workers/global_scope_creation_params.h b/third_party/blink/renderer/core/workers/global_scope_creation_params.h index 395e3bf..af7ed99 100644 --- a/third_party/blink/renderer/core/workers/global_scope_creation_params.h +++ b/third_party/blink/renderer/core/workers/global_scope_creation_params.h
@@ -29,6 +29,10 @@ class WorkerClients; +// TODO(nhiroki): Remove this option after off-the-main-thread worker script +// fetch is enabled for all worker types (https://crbug.com/835717). +enum class OffMainThreadWorkerScriptFetchOption { kDisabled, kEnabled }; + // GlobalScopeCreationParams contains parameters for initializing // WorkerGlobalScope or WorkletGlobalScope. struct CORE_EXPORT GlobalScopeCreationParams final { @@ -38,6 +42,7 @@ GlobalScopeCreationParams( const KURL& script_url, mojom::ScriptType script_type, + OffMainThreadWorkerScriptFetchOption, const String& user_agent, scoped_refptr<WebWorkerFetchContext>, const Vector<CSPHeaderAndType>& content_security_policy_parsed_headers, @@ -74,6 +79,8 @@ KURL script_url; mojom::ScriptType script_type; + OffMainThreadWorkerScriptFetchOption off_main_thread_fetch_option; + String user_agent; scoped_refptr<WebWorkerFetchContext> web_worker_fetch_context;
diff --git a/third_party/blink/renderer/core/workers/main_thread_worklet_test.cc b/third_party/blink/renderer/core/workers/main_thread_worklet_test.cc index d07a313..70fc818 100644 --- a/third_party/blink/renderer/core/workers/main_thread_worklet_test.cc +++ b/third_party/blink/renderer/core/workers/main_thread_worklet_test.cc
@@ -64,7 +64,8 @@ reporting_proxy_ = std::make_unique<MainThreadWorkletReportingProxyForTest>(document); auto creation_params = std::make_unique<GlobalScopeCreationParams>( - document->Url(), mojom::ScriptType::kModule, document->UserAgent(), + document->Url(), mojom::ScriptType::kModule, + OffMainThreadWorkerScriptFetchOption::kEnabled, document->UserAgent(), nullptr /* web_worker_fetch_context */, document->GetContentSecurityPolicy()->Headers(), document->GetReferrerPolicy(), document->GetSecurityOrigin(),
diff --git a/third_party/blink/renderer/core/workers/threaded_worklet_messaging_proxy.cc b/third_party/blink/renderer/core/workers/threaded_worklet_messaging_proxy.cc index dc7d022c..6eeb1fca 100644 --- a/third_party/blink/renderer/core/workers/threaded_worklet_messaging_proxy.cc +++ b/third_party/blink/renderer/core/workers/threaded_worklet_messaging_proxy.cc
@@ -54,7 +54,8 @@ auto global_scope_creation_params = std::make_unique<GlobalScopeCreationParams>( - document->Url(), mojom::ScriptType::kModule, document->UserAgent(), + document->Url(), mojom::ScriptType::kModule, + OffMainThreadWorkerScriptFetchOption::kEnabled, document->UserAgent(), document->GetFrame()->Client()->CreateWorkerFetchContext(), csp->Headers(), document->GetReferrerPolicy(), document->GetSecurityOrigin(), document->IsSecureContext(),
diff --git a/third_party/blink/renderer/core/workers/threaded_worklet_test.cc b/third_party/blink/renderer/core/workers/threaded_worklet_test.cc index 79c2172..45198d0 100644 --- a/third_party/blink/renderer/core/workers/threaded_worklet_test.cc +++ b/third_party/blink/renderer/core/workers/threaded_worklet_test.cc
@@ -203,8 +203,9 @@ std::unique_ptr<WorkerSettings> worker_settings = nullptr; InitializeWorkerThread( std::make_unique<GlobalScopeCreationParams>( - document->Url(), mojom::ScriptType::kModule, document->UserAgent(), - nullptr /* web_worker_fetch_context */, + document->Url(), mojom::ScriptType::kModule, + OffMainThreadWorkerScriptFetchOption::kEnabled, + document->UserAgent(), nullptr /* web_worker_fetch_context */, document->GetContentSecurityPolicy()->Headers(), document->GetReferrerPolicy(), document->GetSecurityOrigin(), document->IsSecureContext(), document->GetHttpsState(),
diff --git a/third_party/blink/renderer/core/workers/worker_global_scope.cc b/third_party/blink/renderer/core/workers/worker_global_scope.cc index dc742622..64448f5 100644 --- a/third_party/blink/renderer/core/workers/worker_global_scope.cc +++ b/third_party/blink/renderer/core/workers/worker_global_scope.cc
@@ -528,7 +528,8 @@ // Set the referrer policy here for workers whose script is fetched on the // main thread. For off-the-main-thread fetches, it is instead set after the // script is fetched. - if (IsScriptFetchedOnMainThread()) + if (creation_params->off_main_thread_fetch_option == + OffMainThreadWorkerScriptFetchOption::kDisabled) SetReferrerPolicy(creation_params->referrer_policy); SetAddressSpace(creation_params->address_space); @@ -609,20 +610,6 @@ worker_settings_->GetGenericFontFamilySettings()); } -bool WorkerGlobalScope::IsScriptFetchedOnMainThread() { - if (script_type_ == mojom::ScriptType::kModule) - return false; - // It's now supported only for dedicated workers to load top-level classic - // worker script off the main thread. - // TODO(nhiroki): Support loading top-level classic worker script off the main - // thread for shared workers and service workers. - if (IsDedicatedWorkerGlobalScope() && - RuntimeEnabledFeatures::OffMainThreadWorkerScriptFetchEnabled()) { - return false; - } - return true; -} - TrustedTypePolicyFactory* WorkerGlobalScope::trustedTypes() { if (!trusted_types_) { trusted_types_ = TrustedTypePolicyFactory::Create(this);
diff --git a/third_party/blink/renderer/core/workers/worker_global_scope.h b/third_party/blink/renderer/core/workers/worker_global_scope.h index f0d0c98b..92c77ed 100644 --- a/third_party/blink/renderer/core/workers/worker_global_scope.h +++ b/third_party/blink/renderer/core/workers/worker_global_scope.h
@@ -205,10 +205,6 @@ void SetWorkerSettings(std::unique_ptr<WorkerSettings>); - // Returns true if this worker script is supposed to be fetched on the main - // thread and passed to the worker thread. - bool IsScriptFetchedOnMainThread(); - void DidReceiveResponseForClassicScript( WorkerClassicScriptLoader* classic_script_loader); void DidImportClassicScript(WorkerClassicScriptLoader* classic_script_loader,
diff --git a/third_party/blink/renderer/core/workers/worker_thread_test.cc b/third_party/blink/renderer/core/workers/worker_thread_test.cc index 35c2fe1e..0df86fe 100644 --- a/third_party/blink/renderer/core/workers/worker_thread_test.cc +++ b/third_party/blink/renderer/core/workers/worker_thread_test.cc
@@ -364,7 +364,8 @@ auto global_scope_creation_params = std::make_unique<GlobalScopeCreationParams>( KURL("http://fake.url/"), mojom::ScriptType::kClassic, - "fake user agent", nullptr /* web_worker_fetch_context */, headers, + OffMainThreadWorkerScriptFetchOption::kDisabled, "fake user agent", + nullptr /* web_worker_fetch_context */, headers, network::mojom::ReferrerPolicy::kDefault, security_origin_.get(), false /* starter_secure_context */, CalculateHttpsState(security_origin_.get()), WorkerClients::Create(),
diff --git a/third_party/blink/renderer/core/workers/worker_thread_test_helper.h b/third_party/blink/renderer/core/workers/worker_thread_test_helper.h index 7e41bf8..9eae2789 100644 --- a/third_party/blink/renderer/core/workers/worker_thread_test_helper.h +++ b/third_party/blink/renderer/core/workers/worker_thread_test_helper.h
@@ -91,7 +91,8 @@ Vector<CSPHeaderAndType> headers{ {"contentSecurityPolicy", kContentSecurityPolicyHeaderTypeReport}}; auto creation_params = std::make_unique<GlobalScopeCreationParams>( - script_url, mojom::ScriptType::kClassic, "fake user agent", + script_url, mojom::ScriptType::kClassic, + OffMainThreadWorkerScriptFetchOption::kDisabled, "fake user agent", nullptr /* web_worker_fetch_context */, headers, network::mojom::ReferrerPolicy::kDefault, security_origin, false /* starter_secure_context */,
diff --git a/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.cc b/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.cc index 6ee2d70..87bdb599 100644 --- a/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.cc +++ b/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.cc
@@ -1128,17 +1128,25 @@ // Update histogram for usage of sync xhr within pagedismissal. auto pagedismissal = GetDocument()->PageDismissalEventBeingDispatched(); if (pagedismissal != Document::kNoDismissal) { - UseCounter::Count(GetDocument(), WebFeature::kSyncXhrInPageDismissal); - DEFINE_STATIC_LOCAL(EnumerationHistogram, syncxhr_pagedismissal_histogram, - ("XHR.Sync.PageDismissal", 5)); - syncxhr_pagedismissal_histogram.Count(pagedismissal); // Disallow synchronous requests on page dismissal if (base::FeatureList::IsEnabled( features::kForbidSyncXHRInPageDismissal)) { + UseCounter::Count(GetDocument(), + WebFeature::kForbiddenSyncXhrInPageDismissal); + DEFINE_STATIC_LOCAL(EnumerationHistogram, + forbidden_syncxhr_pagedismissal_histogram, + ("XHR.Sync.PageDismissal_forbidden", 5)); + forbidden_syncxhr_pagedismissal_histogram.Count(pagedismissal); HandleNetworkError(); ThrowForLoadFailureIfNeeded(exception_state, "Synchronous XHR in page dismissal."); return; + } else { + UseCounter::Count(GetDocument(), WebFeature::kSyncXhrInPageDismissal); + DEFINE_STATIC_LOCAL(EnumerationHistogram, + syncxhr_pagedismissal_histogram, + ("XHR.Sync.PageDismissal", 5)); + syncxhr_pagedismissal_histogram.Count(pagedismissal); } } }
diff --git a/third_party/blink/renderer/devtools/front_end/elements_test_runner/ElementsTestRunner.js b/third_party/blink/renderer/devtools/front_end/elements_test_runner/ElementsTestRunner.js index 7195398b9..c660186 100644 --- a/third_party/blink/renderer/devtools/front_end/elements_test_runner/ElementsTestRunner.js +++ b/third_party/blink/renderer/devtools/front_end/elements_test_runner/ElementsTestRunner.js
@@ -613,8 +613,8 @@ }; ElementsTestRunner.dumpStyleTreeItem = function(treeItem, prefix, depth) { - if (treeItem.listItemElement.textContent.indexOf(' width:') !== -1 || - treeItem.listItemElement.textContent.indexOf(' height:') !== -1) + const textContent = TestRunner.textContentWithoutStyles(treeItem.listItemElement); + if (textContent.indexOf(' width:') !== -1 || textContent.indexOf(' height:') !== -1) return; if (treeItem.listItemElement.classList.contains('inherited')) @@ -630,7 +630,6 @@ if (treeItem.listItemElement.classList.contains('disabled')) typePrefix += '/-- disabled --/ '; - const textContent = treeItem.listItemElement.textContent; TestRunner.addResult(prefix + typePrefix + textContent); if (--depth) {
diff --git a/third_party/blink/renderer/devtools/front_end/emulation/SensorsView.js b/third_party/blink/renderer/devtools/front_end/emulation/SensorsView.js index 18dab20..514b5657e 100644 --- a/third_party/blink/renderer/devtools/front_end/emulation/SensorsView.js +++ b/third_party/blink/renderer/devtools/front_end/emulation/SensorsView.js
@@ -125,6 +125,11 @@ this._fieldsetElement.disabled = true; } else if (value === Emulation.SensorsView.NonPresetOptions.Custom) { this._geolocationOverrideEnabled = true; + const geolocation = SDK.EmulationModel.Geolocation.parseUserInput( + this._latitudeInput.value.trim(), this._longitudeInput.value.trim(), ''); + if (!geolocation) + return; + this._geolocation = geolocation; } else if (value === Emulation.SensorsView.NonPresetOptions.Unavailable) { this._geolocationOverrideEnabled = true; this._geolocation = new SDK.EmulationModel.Geolocation(0, 0, true);
diff --git a/third_party/blink/renderer/devtools/front_end/emulation/sensors.css b/third_party/blink/renderer/devtools/front_end/emulation/sensors.css index a261d73..e7177d9 100644 --- a/third_party/blink/renderer/devtools/front_end/emulation/sensors.css +++ b/third_party/blink/renderer/devtools/front_end/emulation/sensors.css
@@ -310,6 +310,6 @@ margin-left: 10px; } -button[is=text-button] { +button.text-button { margin: 0 10px; }
diff --git a/third_party/blink/renderer/devtools/front_end/ui/TextPrompt.js b/third_party/blink/renderer/devtools/front_end/ui/TextPrompt.js index f3305be..9aeaf15 100644 --- a/third_party/blink/renderer/devtools/front_end/ui/TextPrompt.js +++ b/third_party/blink/renderer/devtools/front_end/ui/TextPrompt.js
@@ -110,12 +110,11 @@ this._boundOnMouseWheel = this.onMouseWheel.bind(this); this._boundClearAutocomplete = this.clearAutocomplete.bind(this); this._proxyElement = element.ownerDocument.createElement('span'); - const shadowRoot = UI.createShadowRootWithCoreStyles(this._proxyElement, 'ui/textPrompt.css'); - this._contentElement = shadowRoot.createChild('div', 'text-prompt-root'); - this._contentElement.createChild('content'); + UI.appendStyle(this._proxyElement, 'ui/textPrompt.css'); + this._contentElement = this._proxyElement.createChild('div', 'text-prompt-root'); this._proxyElement.style.display = this._proxyElementDisplay; element.parentElement.insertBefore(this._proxyElement, element); - this._proxyElement.appendChild(element); + this._contentElement.appendChild(element); this._element.classList.add('text-prompt'); UI.ARIAUtils.markAsTextBox(this._element); this._element.setAttribute('contenteditable', 'plaintext-only');
diff --git a/third_party/blink/renderer/devtools/front_end/ui/UIUtils.js b/third_party/blink/renderer/devtools/front_end/ui/UIUtils.js index 1f2aeb17..45d2074 100644 --- a/third_party/blink/renderer/devtools/front_end/ui/UIUtils.js +++ b/third_party/blink/renderer/devtools/front_end/ui/UIUtils.js
@@ -674,9 +674,7 @@ * @param {!Element} element */ UI.installComponentRootStyles = function(element) { - UI.appendStyle(element, 'ui/inspectorCommon.css'); - UI.themeSupport.injectHighlightStyleSheets(element); - UI.themeSupport.injectCustomStyleSheets(element); + UI._injectCoreStyles(element); element.classList.add('platform-' + Host.platform()); // Detect overlay scrollbar enable by checking for nonzero scrollbar width. @@ -708,9 +706,7 @@ */ UI.createShadowRootWithCoreStyles = function(element, cssFile) { const shadowRoot = element.createShadowRoot(); - UI.appendStyle(shadowRoot, 'ui/inspectorCommon.css'); - UI.themeSupport.injectHighlightStyleSheets(shadowRoot); - UI.themeSupport.injectCustomStyleSheets(shadowRoot); + UI._injectCoreStyles(shadowRoot); if (cssFile) UI.appendStyle(shadowRoot, cssFile); shadowRoot.addEventListener('focus', UI._focusChanged.bind(UI), true); @@ -718,6 +714,16 @@ }; /** + * @param {!Element|!ShadowRoot} root + */ +UI._injectCoreStyles = function(root) { + UI.appendStyle(root, 'ui/inspectorCommon.css'); + UI.appendStyle(root, 'ui/textButton.css'); + UI.themeSupport.injectHighlightStyleSheets(root); + UI.themeSupport.injectCustomStyleSheets(root); +}; + +/** * @param {!Document} document * @param {!Event} event */ @@ -1183,12 +1189,14 @@ * @return {!Element} */ UI.createTextButton = function(text, clickHandler, className, primary) { - const element = createElementWithClass('button', className || '', 'text-button'); + const element = createElementWithClass('button', className || ''); element.textContent = text; + element.classList.add('text-button'); if (primary) element.classList.add('primary-button'); if (clickHandler) element.addEventListener('click', clickHandler, false); + element.type = 'button'; return element; }; @@ -1350,19 +1358,6 @@ }; (function() { - UI.registerCustomElement('button', 'text-button', { - /** - * @this {Element} - */ - createdCallback: function() { - this.type = 'button'; - const root = UI.createShadowRootWithCoreStyles(this, 'ui/textButton.css'); - root.createChild('content'); - }, - - __proto__: HTMLButtonElement.prototype - }); - UI.registerCustomElement('label', 'dt-radio', { /** * @this {Element} @@ -1681,7 +1676,7 @@ } /** - * @param {!Element} element + * @param {!Element|!ShadowRoot} element */ injectHighlightStyleSheets(element) { this._injectingStyleSheet = true;
diff --git a/third_party/blink/renderer/devtools/front_end/ui/textButton.css b/third_party/blink/renderer/devtools/front_end/ui/textButton.css index b18868b..05fd2ca 100644 --- a/third_party/blink/renderer/devtools/front_end/ui/textButton.css +++ b/third_party/blink/renderer/devtools/front_end/ui/textButton.css
@@ -4,7 +4,7 @@ * found in the LICENSE file. */ -:host { +.text-button { margin: 2px; height: 24px; font-size: 12px; @@ -18,49 +18,49 @@ white-space: nowrap; } -:host(:not(:disabled):focus), -:host(:not(:disabled):hover), -:host(:not(:disabled):active) { +.text-button:not(:disabled):focus, +.text-button:not(:disabled):hover, +.text-button:not(:disabled):active { background-color: var(--toolbar-bg-color); box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1); cursor: pointer; } -:host(:not(:disabled):active) { +.text-button:not(:disabled):active { background-color: #f2f2f2; } -:host(:not(:disabled):focus) { +.text-button:not(:disabled):focus { box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1), 0 0 0 2px rgba(66, 133, 244, 0.4); } -:host(:disabled) { +.text-button:disabled { opacity: 0.38; } -:host(.primary-button), -theme-preserve { +.text-button.primary-button, -theme-preserve { background-color: var(--accent-color); border: none; color: #fff; } -:host(.primary-button:not(:disabled):focus), -:host(.primary-button:not(:disabled):hover), -:host(.primary-button:not(:disabled):active), -theme-preserve { +.text-button.primary-button:not(:disabled):focus, +.text-button.primary-button:not(:disabled):hover, +.text-button.primary-button:not(:disabled):active, -theme-preserve { background-color: var(--accent-color-hover); } -:host-context(.-theme-with-dark-background):host(:not(.primary-button):not(:disabled):focus), -:host-context(.-theme-with-dark-background):host(:not(.primary-button):not(:disabled):hover), -:host-context(.-theme-with-dark-background):host(:not(.primary-button):not(:disabled):active) { +.-theme-with-dark-background .text-button:not(.primary-button):not(:disabled):focus, +.-theme-with-dark-background .text-button:not(.primary-button):not(:disabled):hover, +.-theme-with-dark-background .text-button:not(.primary-button):not(:disabled):active { background-color: #313131; box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1); } -:host-context(.-theme-with-dark-background):host(:not(.primary-button):not(:disabled):focus) { +.-theme-with-dark-background .text-button:not(.primary-button):not(:disabled):focus { box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1), 0 0 0 2px rgba(94, 151, 246, 0.6); } -:host-context(.-theme-with-dark-background):host(:not(.primary-button):not(:disabled):active) { +.-theme-with-dark-background .text-button:not(.primary-button):not(:disabled):active { background-color: #3e3e3e; }
diff --git a/third_party/blink/renderer/devtools/front_end/ui/textPrompt.css b/third_party/blink/renderer/devtools/front_end/ui/textPrompt.css index 5fb0dd61..b229032 100644 --- a/third_party/blink/renderer/devtools/front_end/ui/textPrompt.css +++ b/third_party/blink/renderer/devtools/front_end/ui/textPrompt.css
@@ -4,7 +4,7 @@ * found in the LICENSE file. */ -.text-prompt-root { + .text-prompt-root { display: flex; align-items: center; } @@ -22,46 +22,45 @@ opacity: 1.0 !important; } -.text-prompt-editing, -.text-prompt-editing ::content * { +.text-prompt-editing > .text-prompt { color: #222 !important; text-decoration: none !important; white-space: pre; } -::content .auto-complete-text { +.text-prompt > .auto-complete-text { color: rgb(128, 128, 128) !important; } -::content .text-prompt[data-placeholder]:empty::before { +.text-prompt[data-placeholder]:empty::before { content: attr(data-placeholder); color: rgb(128, 128, 128); } -::content .text-prompt:not([data-placeholder]):empty::after { +.text-prompt:not([data-placeholder]):empty::after { content: '\00A0'; width: 0; display: block; } -::content .text-prompt { +.text-prompt { cursor: text; overflow-x: visible; } -::content .text-prompt::-webkit-scrollbar { +.text-prompt::-webkit-scrollbar { display: none; } -::content .text-prompt.disabled { +.text-prompt.disabled { opacity: 0.5; cursor: default; } -.text-prompt-editing ::content br { +.text-prompt-editing br { display: none; } -:host-context(:not(:focus-within)) ::content ::selection { +.text-prompt-root:not(:focus-within) ::selection { background: transparent; }
diff --git a/third_party/blink/renderer/modules/animationworklet/animation_worklet_global_scope_test.cc b/third_party/blink/renderer/modules/animationworklet/animation_worklet_global_scope_test.cc index 099c296..718d367b 100644 --- a/third_party/blink/renderer/modules/animationworklet/animation_worklet_global_scope_test.cc +++ b/third_party/blink/renderer/modules/animationworklet/animation_worklet_global_scope_test.cc
@@ -79,11 +79,12 @@ Document* document = &GetDocument(); thread->Start( std::make_unique<GlobalScopeCreationParams>( - document->Url(), mojom::ScriptType::kModule, document->UserAgent(), - nullptr /* web_worker_fetch_context */, Vector<CSPHeaderAndType>(), - document->GetReferrerPolicy(), document->GetSecurityOrigin(), - document->IsSecureContext(), document->GetHttpsState(), clients, - document->AddressSpace(), + document->Url(), mojom::ScriptType::kModule, + OffMainThreadWorkerScriptFetchOption::kEnabled, + document->UserAgent(), nullptr /* web_worker_fetch_context */, + Vector<CSPHeaderAndType>(), document->GetReferrerPolicy(), + document->GetSecurityOrigin(), document->IsSecureContext(), + document->GetHttpsState(), clients, document->AddressSpace(), OriginTrialContext::GetTokens(document).get(), base::UnguessableToken::Create(), nullptr /* worker_settings */, kV8CacheOptionsDefault,
diff --git a/third_party/blink/renderer/modules/cache_storage/cache.cc b/third_party/blink/renderer/modules/cache_storage/cache.cc index 2ae91d9..8f8750f 100644 --- a/third_party/blink/renderer/modules/cache_storage/cache.cc +++ b/third_party/blink/renderer/modules/cache_storage/cache.cc
@@ -31,6 +31,7 @@ #include "third_party/blink/renderer/core/frame/deprecation.h" #include "third_party/blink/renderer/core/html/parser/text_resource_decoder.h" #include "third_party/blink/renderer/core/inspector/console_message.h" +#include "third_party/blink/renderer/modules/cache_storage/cache_storage.h" #include "third_party/blink/renderer/modules/cache_storage/cache_storage_error.h" #include "third_party/blink/renderer/modules/service_worker/service_worker_global_scope.h" #include "third_party/blink/renderer/platform/bindings/exception_state.h" @@ -496,13 +497,6 @@ base::Time response_time, base::TimeTicks) { ServiceWorkerGlobalScope* global_scope = GetServiceWorkerGlobalScope(); - // |cache_ptr_| can be disconnected when the wrapper of CacheStorage is - // gone. - if (!cache_->cache_ptr_.is_bound()) { - global_scope->DidEndTask(task_id); - return; - } - scoped_refptr<CachedMetadata> cached_metadata = GenerateFullCodeCache(array_buffer); if (!cached_metadata) { @@ -534,9 +528,11 @@ Cache* Cache::Create( GlobalFetch::ScopedFetcher* fetcher, + CacheStorage* cache_storage, mojom::blink::CacheStorageCacheAssociatedPtrInfo cache_ptr_info, scoped_refptr<base::SingleThreadTaskRunner> task_runner) { - return MakeGarbageCollected<Cache>(fetcher, std::move(cache_ptr_info), + return MakeGarbageCollected<Cache>(fetcher, cache_storage, + std::move(cache_ptr_info), std::move(task_runner)); } @@ -671,14 +667,16 @@ } Cache::Cache(GlobalFetch::ScopedFetcher* fetcher, + CacheStorage* cache_storage, mojom::blink::CacheStorageCacheAssociatedPtrInfo cache_ptr_info, scoped_refptr<base::SingleThreadTaskRunner> task_runner) - : scoped_fetcher_(fetcher) { + : scoped_fetcher_(fetcher), cache_storage_(cache_storage) { cache_ptr_.Bind(std::move(cache_ptr_info), std::move(task_runner)); } void Cache::Trace(blink::Visitor* visitor) { visitor->Trace(scoped_fetcher_); + visitor->Trace(cache_storage_); ScriptWrappable::Trace(visitor); }
diff --git a/third_party/blink/renderer/modules/cache_storage/cache.h b/third_party/blink/renderer/modules/cache_storage/cache.h index ce0bffb4..e7fe158 100644 --- a/third_party/blink/renderer/modules/cache_storage/cache.h +++ b/third_party/blink/renderer/modules/cache_storage/cache.h
@@ -20,6 +20,7 @@ namespace blink { +class CacheStorage; class ExceptionState; class Response; class Request; @@ -32,10 +33,12 @@ public: static Cache* Create(GlobalFetch::ScopedFetcher*, + CacheStorage*, mojom::blink::CacheStorageCacheAssociatedPtrInfo, scoped_refptr<base::SingleThreadTaskRunner>); Cache(GlobalFetch::ScopedFetcher*, + CacheStorage*, mojom::blink::CacheStorageCacheAssociatedPtrInfo, scoped_refptr<base::SingleThreadTaskRunner>); @@ -101,6 +104,10 @@ const CacheQueryOptions*); Member<GlobalFetch::ScopedFetcher> scoped_fetcher_; + // Hold a reference to CacheStorage to keep |cache_ptr_| alive. + // This is required because |cache_ptr_| is associated with CacheStorage's + // mojo message pipe. + Member<CacheStorage> cache_storage_; mojom::blink::CacheStorageCacheAssociatedPtr cache_ptr_;
diff --git a/third_party/blink/renderer/modules/cache_storage/cache_storage.cc b/third_party/blink/renderer/modules/cache_storage/cache_storage.cc index 7420328..2f6303f 100644 --- a/third_party/blink/renderer/modules/cache_storage/cache_storage.cc +++ b/third_party/blink/renderer/modules/cache_storage/cache_storage.cc
@@ -40,7 +40,7 @@ WTF::Bind( [](ScriptPromiseResolver* resolver, GlobalFetch::ScopedFetcher* fetcher, TimeTicks start_time, - CacheStorage*, mojom::blink::OpenResultPtr result) { + CacheStorage* cache_storage, mojom::blink::OpenResultPtr result) { if (!resolver->GetExecutionContext() || resolver->GetExecutionContext()->IsContextDestroyed()) { return; @@ -60,10 +60,10 @@ UMA_HISTOGRAM_TIMES("ServiceWorkerCache.CacheStorage.Open", TimeTicks::Now() - start_time); // See https://bit.ly/2S0zRAS for task types. - resolver->Resolve( - Cache::Create(fetcher, std::move(result->get_cache()), - resolver->GetExecutionContext()->GetTaskRunner( - blink::TaskType::kMiscPlatformAPI))); + resolver->Resolve(Cache::Create( + fetcher, cache_storage, std::move(result->get_cache()), + resolver->GetExecutionContext()->GetTaskRunner( + blink::TaskType::kMiscPlatformAPI))); } }, WrapPersistent(resolver), WrapPersistent(scoped_fetcher_.Get()),
diff --git a/third_party/blink/renderer/modules/cache_storage/cache_test.cc b/third_party/blink/renderer/modules/cache_storage/cache_test.cc index 229ed0a..7a15862 100644 --- a/third_party/blink/renderer/modules/cache_storage/cache_test.cc +++ b/third_party/blink/renderer/modules/cache_storage/cache_test.cc
@@ -278,7 +278,7 @@ mojo::AssociatedBinding<mojom::blink::CacheStorageCache>>( cache_.get(), std::move(request)); return Cache::Create( - fetcher, cache_ptr.PassInterface(), + fetcher, nullptr /* cache_storage */, cache_ptr.PassInterface(), blink::scheduler::GetSingleThreadTaskRunnerForTesting()); }
diff --git a/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope_proxy.cc b/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope_proxy.cc index 833e827..523e734 100644 --- a/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope_proxy.cc +++ b/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope_proxy.cc
@@ -41,7 +41,8 @@ worker_clients, frame->Client()->CreateWorkerContentSettingsClient()); auto creation_params = std::make_unique<GlobalScopeCreationParams>( - document->Url(), mojom::ScriptType::kModule, document->UserAgent(), + document->Url(), mojom::ScriptType::kModule, + OffMainThreadWorkerScriptFetchOption::kEnabled, document->UserAgent(), frame->Client()->CreateWorkerFetchContext(), document->GetContentSecurityPolicy()->Headers(), document->GetReferrerPolicy(), document->GetSecurityOrigin(),
diff --git a/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope_test.cc b/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope_test.cc index 60b4911a..7ba26c6 100644 --- a/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope_test.cc +++ b/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope_test.cc
@@ -61,11 +61,12 @@ Document* document = &GetDocument(); thread->Start( std::make_unique<GlobalScopeCreationParams>( - document->Url(), mojom::ScriptType::kModule, document->UserAgent(), - nullptr /* web_worker_fetch_context */, Vector<CSPHeaderAndType>(), - document->GetReferrerPolicy(), document->GetSecurityOrigin(), - document->IsSecureContext(), document->GetHttpsState(), clients, - document->AddressSpace(), + document->Url(), mojom::ScriptType::kModule, + OffMainThreadWorkerScriptFetchOption::kEnabled, + document->UserAgent(), nullptr /* web_worker_fetch_context */, + Vector<CSPHeaderAndType>(), document->GetReferrerPolicy(), + document->GetSecurityOrigin(), document->IsSecureContext(), + document->GetHttpsState(), clients, document->AddressSpace(), OriginTrialContext::GetTokens(document).get(), base::UnguessableToken::Create(), nullptr /* worker_settings */, kV8CacheOptionsDefault,
diff --git a/third_party/blink/renderer/modules/exported/web_embedded_worker_impl.cc b/third_party/blink/renderer/modules/exported/web_embedded_worker_impl.cc index d5f411ca3..7282eebe 100644 --- a/third_party/blink/renderer/modules/exported/web_embedded_worker_impl.cc +++ b/third_party/blink/renderer/modules/exported/web_embedded_worker_impl.cc
@@ -395,6 +395,13 @@ String source_code; std::unique_ptr<Vector<uint8_t>> cached_meta_data; + // TODO(nhiroki): Implement off-the-main-thread worker script fetch for + // service workers (https://crbug.com/835717). + const OffMainThreadWorkerScriptFetchOption off_main_thread_fetch_option = + worker_start_data_.script_type == mojom::ScriptType::kModule + ? OffMainThreadWorkerScriptFetchOption::kEnabled + : OffMainThreadWorkerScriptFetchOption::kDisabled; + // |main_script_loader_| isn't created if the InstalledScriptsManager had the // script. if (main_script_loader_) { @@ -409,7 +416,8 @@ } global_scope_creation_params = std::make_unique<GlobalScopeCreationParams>( worker_start_data_.script_url, worker_start_data_.script_type, - worker_start_data_.user_agent, std::move(web_worker_fetch_context), + off_main_thread_fetch_option, worker_start_data_.user_agent, + std::move(web_worker_fetch_context), content_security_policy ? content_security_policy->Headers() : Vector<CSPHeaderAndType>(), referrer_policy, starter_origin, starter_secure_context, @@ -428,12 +436,12 @@ // served by the installed scripts manager on the worker thread. global_scope_creation_params = std::make_unique<GlobalScopeCreationParams>( worker_start_data_.script_url, worker_start_data_.script_type, - worker_start_data_.user_agent, std::move(web_worker_fetch_context), - Vector<CSPHeaderAndType>(), network::mojom::ReferrerPolicy::kDefault, - starter_origin, starter_secure_context, starter_https_state, - worker_clients, worker_start_data_.address_space, - nullptr /* OriginTrialTokens */, devtools_worker_token_, - std::move(worker_settings), + off_main_thread_fetch_option, worker_start_data_.user_agent, + std::move(web_worker_fetch_context), Vector<CSPHeaderAndType>(), + network::mojom::ReferrerPolicy::kDefault, starter_origin, + starter_secure_context, starter_https_state, worker_clients, + worker_start_data_.address_space, nullptr /* OriginTrialTokens */, + devtools_worker_token_, std::move(worker_settings), static_cast<V8CacheOptions>(worker_start_data_.v8_cache_options), nullptr /* worklet_module_respones_map */, std::move(interface_provider_info_));
diff --git a/third_party/blink/renderer/modules/mediasession/media_metadata_sanitizer.cc b/third_party/blink/renderer/modules/mediasession/media_metadata_sanitizer.cc index c94931b..501686f 100644 --- a/third_party/blink/renderer/modules/mediasession/media_metadata_sanitizer.cc +++ b/third_party/blink/renderer/modules/mediasession/media_metadata_sanitizer.cc
@@ -100,6 +100,9 @@ mojo_metadata->artist = metadata->artist().Left(kMaxStringLength); mojo_metadata->album = metadata->album().Left(kMaxStringLength); + // |source_title_| is populated by content::MediaSessionImpl. + mojo_metadata->source_title = g_empty_string16_bit; + for (const MediaImage* image : metadata->artwork()) { media_session::mojom::blink::MediaImagePtr mojo_image = SanitizeMediaImageAndConvertToMojo(image, context);
diff --git a/third_party/blink/renderer/modules/webaudio/audio_worklet_global_scope_test.cc b/third_party/blink/renderer/modules/webaudio/audio_worklet_global_scope_test.cc index 1e10cd0d..5beab54f 100644 --- a/third_party/blink/renderer/modules/webaudio/audio_worklet_global_scope_test.cc +++ b/third_party/blink/renderer/modules/webaudio/audio_worklet_global_scope_test.cc
@@ -68,11 +68,13 @@ Document* document = &GetDocument(); thread->Start( std::make_unique<GlobalScopeCreationParams>( - document->Url(), mojom::ScriptType::kModule, document->UserAgent(), - nullptr /* web_worker_fetch_context */, Vector<CSPHeaderAndType>(), - document->GetReferrerPolicy(), document->GetSecurityOrigin(), - document->IsSecureContext(), document->GetHttpsState(), - nullptr /* worker_clients */, document->AddressSpace(), + document->Url(), mojom::ScriptType::kModule, + OffMainThreadWorkerScriptFetchOption::kEnabled, + document->UserAgent(), nullptr /* web_worker_fetch_context */, + Vector<CSPHeaderAndType>(), document->GetReferrerPolicy(), + document->GetSecurityOrigin(), document->IsSecureContext(), + document->GetHttpsState(), nullptr /* worker_clients */, + document->AddressSpace(), OriginTrialContext::GetTokens(document).get(), base::UnguessableToken::Create(), nullptr /* worker_settings */, kV8CacheOptionsDefault,
diff --git a/third_party/blink/renderer/modules/webaudio/audio_worklet_thread_test.cc b/third_party/blink/renderer/modules/webaudio/audio_worklet_thread_test.cc index 3847c25..52503a9 100644 --- a/third_party/blink/renderer/modules/webaudio/audio_worklet_thread_test.cc +++ b/third_party/blink/renderer/modules/webaudio/audio_worklet_thread_test.cc
@@ -52,11 +52,13 @@ Document* document = &GetDocument(); thread->Start( std::make_unique<GlobalScopeCreationParams>( - document->Url(), mojom::ScriptType::kModule, document->UserAgent(), - nullptr /* web_worker_fetch_context */, Vector<CSPHeaderAndType>(), - document->GetReferrerPolicy(), document->GetSecurityOrigin(), - document->IsSecureContext(), document->GetHttpsState(), - nullptr /* worker_clients */, document->AddressSpace(), + document->Url(), mojom::ScriptType::kModule, + OffMainThreadWorkerScriptFetchOption::kEnabled, + document->UserAgent(), nullptr /* web_worker_fetch_context */, + Vector<CSPHeaderAndType>(), document->GetReferrerPolicy(), + document->GetSecurityOrigin(), document->IsSecureContext(), + document->GetHttpsState(), nullptr /* worker_clients */, + document->AddressSpace(), OriginTrialContext::GetTokens(document).get(), base::UnguessableToken::Create(), nullptr /* worker_settings */, kV8CacheOptionsDefault,
diff --git a/third_party/blink/renderer/modules/worklet/animation_and_paint_worklet_thread_test.cc b/third_party/blink/renderer/modules/worklet/animation_and_paint_worklet_thread_test.cc index bab1a0b65..f021033a 100644 --- a/third_party/blink/renderer/modules/worklet/animation_and_paint_worklet_thread_test.cc +++ b/third_party/blink/renderer/modules/worklet/animation_and_paint_worklet_thread_test.cc
@@ -67,11 +67,12 @@ Document* document = &GetDocument(); thread->Start( std::make_unique<GlobalScopeCreationParams>( - document->Url(), mojom::ScriptType::kModule, document->UserAgent(), - nullptr /* web_worker_fetch_context */, Vector<CSPHeaderAndType>(), - document->GetReferrerPolicy(), document->GetSecurityOrigin(), - document->IsSecureContext(), document->GetHttpsState(), clients, - document->AddressSpace(), + document->Url(), mojom::ScriptType::kModule, + OffMainThreadWorkerScriptFetchOption::kEnabled, + document->UserAgent(), nullptr /* web_worker_fetch_context */, + Vector<CSPHeaderAndType>(), document->GetReferrerPolicy(), + document->GetSecurityOrigin(), document->IsSecureContext(), + document->GetHttpsState(), clients, document->AddressSpace(), OriginTrialContext::GetTokens(document).get(), base::UnguessableToken::Create(), nullptr /* worker_settings */, kV8CacheOptionsDefault,
diff --git a/third_party/blink/renderer/platform/exported/web_runtime_features.cc b/third_party/blink/renderer/platform/exported/web_runtime_features.cc index 74216d6..fe1f8dd3 100644 --- a/third_party/blink/renderer/platform/exported/web_runtime_features.cc +++ b/third_party/blink/renderer/platform/exported/web_runtime_features.cc
@@ -364,6 +364,10 @@ return RuntimeEnabledFeatures::CompositeAfterPaintEnabled(); } +void WebRuntimeFeatures::EnableUserActivationSameOriginVisibility(bool enable) { + RuntimeEnabledFeatures::SetUserActivationSameOriginVisibilityEnabled(enable); +} + void WebRuntimeFeatures::EnableUserActivationV2(bool enable) { RuntimeEnabledFeatures::SetUserActivationV2Enabled(enable); }
diff --git a/third_party/blink/renderer/platform/graphics/DEPS b/third_party/blink/renderer/platform/graphics/DEPS index a0ce109..e341255 100644 --- a/third_party/blink/renderer/platform/graphics/DEPS +++ b/third_party/blink/renderer/platform/graphics/DEPS
@@ -22,6 +22,7 @@ "+gpu/ipc/common/mailbox.mojom-blink.h", "+media/base/media_switches.h", "+media/base/video_frame.h", + "+media/base/video_types.h", "+media/renderers/video_resource_updater.h", "+services/viz/public/interfaces", "+services/ws/public/cpp/gpu/context_provider_command_buffer.h",
diff --git a/third_party/blink/renderer/platform/graphics/video_frame_submitter.cc b/third_party/blink/renderer/platform/graphics/video_frame_submitter.cc index 48bec8070..e2bf49c 100644 --- a/third_party/blink/renderer/platform/graphics/video_frame_submitter.cc +++ b/third_party/blink/renderer/platform/graphics/video_frame_submitter.cc
@@ -14,6 +14,7 @@ #include "components/viz/common/resources/resource_id.h" #include "components/viz/common/resources/returned_resource.h" #include "media/base/video_frame.h" +#include "media/base/video_types.h" #include "services/viz/public/interfaces/compositing/compositor_frame_sink.mojom-blink.h" #include "services/ws/public/cpp/gpu/context_provider_command_buffer.h" #include "third_party/blink/public/platform/interface_provider.h" @@ -41,30 +42,30 @@ enable_surface_synchronization_( ::features::IsSurfaceSynchronizationEnabled()), weak_ptr_factory_(this) { - DETACH_FROM_THREAD(media_thread_checker_); + DETACH_FROM_THREAD(thread_checker_); } VideoFrameSubmitter::~VideoFrameSubmitter() { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); if (context_provider_) context_provider_->RemoveObserver(this); + + // Release VideoFrameResourceProvider early since its destruction will make + // calls back into this class via the viz::SharedBitmapReporter interface. + resource_provider_.reset(); } void VideoFrameSubmitter::SetRotation(media::VideoRotation rotation) { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); rotation_ = rotation; } -void VideoFrameSubmitter::SetIsOpaque(bool is_opaque) { - if (is_opaque_ == is_opaque) - return; - - is_opaque_ = is_opaque; - UpdateSubmissionStateInternal(); -} - void VideoFrameSubmitter::EnableSubmission( viz::SurfaceId surface_id, base::TimeTicks local_surface_id_allocation_time, WebFrameSinkDestroyedCallback frame_sink_destroyed_callback) { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + // TODO(lethalantidote): Set these fields earlier in the constructor. Will // need to construct VideoFrameSubmitter later in order to do this. frame_sink_id_ = surface_id.frame_sink_id(); @@ -77,74 +78,90 @@ } void VideoFrameSubmitter::SetIsSurfaceVisible(bool is_visible) { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); is_surface_visible_ = is_visible; - UpdateSubmissionStateInternal(); + UpdateSubmissionState(); } void VideoFrameSubmitter::SetIsPageVisible(bool is_visible) { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); is_page_visible_ = is_visible; - UpdateSubmissionStateInternal(); + UpdateSubmissionState(); } void VideoFrameSubmitter::SetForceSubmit(bool force_submit) { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); force_submit_ = force_submit; - UpdateSubmissionStateInternal(); + UpdateSubmissionState(); } -void VideoFrameSubmitter::UpdateSubmissionStateInternal() { - if (compositor_frame_sink_) { - compositor_frame_sink_->SetNeedsBeginFrame(IsDrivingFrameUpdates()); - if (ShouldSubmit()) - SubmitSingleFrame(); - else if (!frame_size_.IsEmpty()) - SubmitEmptyFrame(); - } +void VideoFrameSubmitter::UpdateSubmissionState() { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + if (!compositor_frame_sink_) + return; + + compositor_frame_sink_->SetNeedsBeginFrame(IsDrivingFrameUpdates()); + + // TODO(dalecurtis): Document how these are responsible for saving significant + // amounts of cc memory by dealing with off-screen resources more efficiently. + if (ShouldSubmit()) + SubmitSingleFrame(); + else if (!frame_size_.IsEmpty()) + SubmitEmptyFrame(); } void VideoFrameSubmitter::StopUsingProvider() { - DCHECK_CALLED_ON_VALID_THREAD(media_thread_checker_); + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); if (is_rendering_) StopRendering(); video_frame_provider_ = nullptr; } void VideoFrameSubmitter::StopRendering() { - DCHECK_CALLED_ON_VALID_THREAD(media_thread_checker_); + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); DCHECK(is_rendering_); DCHECK(video_frame_provider_); is_rendering_ = false; - UpdateSubmissionStateInternal(); + UpdateSubmissionState(); } void VideoFrameSubmitter::SubmitSingleFrame() { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + // If we haven't gotten a valid result yet from |context_provider_callback_| - // |resource_provider_| will remain uninitalized. + // |resource_provider_| will remain uninitialized. // |video_frame_provider_| may be null if StopUsingProvider has been called, // which could happen if the |video_frame_provider_| is destructing while we // are waiting for the ContextProvider. if (!resource_provider_->IsInitialized() || !video_frame_provider_) return; - viz::BeginFrameAck current_begin_frame_ack = - viz::BeginFrameAck::CreateManualAckWithDamage(); - scoped_refptr<media::VideoFrame> video_frame = - video_frame_provider_->GetCurrentFrame(); - if (video_frame) { - base::SequencedTaskRunnerHandle::Get()->PostTask( - FROM_HERE, - base::BindOnce(base::IgnoreResult(&VideoFrameSubmitter::SubmitFrame), - weak_ptr_factory_.GetWeakPtr(), current_begin_frame_ack, - video_frame)); - video_frame_provider_->PutCurrentFrame(); - } + auto video_frame = video_frame_provider_->GetCurrentFrame(); + if (!video_frame) + return; + + // TODO(dalecurtis): This probably shouldn't be posted since it runs the risk + // of having state change out from under it. All call sites into this method + // should be from posted tasks so it should be safe to remove the post. + base::SequencedTaskRunnerHandle::Get()->PostTask( + FROM_HERE, + base::BindOnce(base::IgnoreResult(&VideoFrameSubmitter::SubmitFrame), + weak_ptr_factory_.GetWeakPtr(), + viz::BeginFrameAck::CreateManualAckWithDamage(), + std::move(video_frame))); + + video_frame_provider_->PutCurrentFrame(); } bool VideoFrameSubmitter::ShouldSubmit() const { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); return (is_surface_visible_ && is_page_visible_) || force_submit_; } bool VideoFrameSubmitter::IsDrivingFrameUpdates() const { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + // We drive frame updates only when we believe that something is consuming // them. This is different than VideoLayer, which drives updates any time // they're in the layer tree. @@ -152,18 +169,17 @@ } void VideoFrameSubmitter::DidReceiveFrame() { - DCHECK_CALLED_ON_VALID_THREAD(media_thread_checker_); + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); DCHECK(video_frame_provider_); - // DidReceiveFrame is called before renderering has started, as a part of - // PaintSingleFrame. - if (!is_rendering_) { + // DidReceiveFrame is called before rendering has started, as a part of + // VideoRendererSink::PaintSingleFrame. + if (!is_rendering_) SubmitSingleFrame(); - } } void VideoFrameSubmitter::StartRendering() { - DCHECK_CALLED_ON_VALID_THREAD(media_thread_checker_); + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); DCHECK(!is_rendering_); is_rendering_ = true; @@ -172,19 +188,21 @@ } void VideoFrameSubmitter::Initialize(cc::VideoFrameProvider* provider) { - DCHECK_CALLED_ON_VALID_THREAD(media_thread_checker_); - if (provider) { - DCHECK(!video_frame_provider_); - video_frame_provider_ = provider; - context_provider_callback_.Run( - nullptr, base::BindOnce(&VideoFrameSubmitter::OnReceivedContextProvider, - weak_ptr_factory_.GetWeakPtr())); - } + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + if (!provider) + return; + + DCHECK(!video_frame_provider_); + video_frame_provider_ = provider; + context_provider_callback_.Run( + nullptr, base::BindOnce(&VideoFrameSubmitter::OnReceivedContextProvider, + weak_ptr_factory_.GetWeakPtr())); } void VideoFrameSubmitter::OnReceivedContextProvider( bool use_gpu_compositing, scoped_refptr<viz::ContextProvider> context_provider) { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); if (!use_gpu_compositing) { resource_provider_->Initialize(nullptr, this); return; @@ -222,7 +240,7 @@ } void VideoFrameSubmitter::StartSubmitting() { - DCHECK_CALLED_ON_VALID_THREAD(media_thread_checker_); + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); DCHECK(frame_sink_id_.is_valid()); mojom::blink::EmbeddedFrameSinkProviderPtr provider; @@ -239,15 +257,16 @@ compositor_frame_sink_.set_connection_error_handler(base::BindOnce( &VideoFrameSubmitter::OnContextLost, base::Unretained(this))); - UpdateSubmissionStateInternal(); + UpdateSubmissionState(); } bool VideoFrameSubmitter::SubmitFrame( const viz::BeginFrameAck& begin_frame_ack, scoped_refptr<media::VideoFrame> video_frame) { - TRACE_EVENT0("media", "VideoFrameSubmitter::SubmitFrame"); + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); DCHECK(video_frame); - DCHECK_CALLED_ON_VALID_THREAD(media_thread_checker_); + TRACE_EVENT0("media", "VideoFrameSubmitter::SubmitFrame"); + if (!compositor_frame_sink_ || !ShouldSubmit()) return false; @@ -276,9 +295,10 @@ gfx::Transform()); render_pass->filters = cc::FilterOperations(); resource_provider_->AppendQuads(render_pass.get(), video_frame, rotation_, - is_opaque_); + media::IsOpaque(video_frame->format())); compositor_frame.metadata.begin_frame_ack = begin_frame_ack; compositor_frame.metadata.frame_token = ++next_frame_token_; + // We don't assume that the ack is marked as having damage. However, we're // definitely emitting a CompositorFrame that damages the entire surface. compositor_frame.metadata.begin_frame_ack.has_damage = true; @@ -286,25 +306,24 @@ compositor_frame.metadata.may_contain_video = true; std::vector<viz::ResourceId> resources; - DCHECK_LE(render_pass->quad_list.size(), 1u); if (!render_pass->quad_list.empty()) { - for (viz::ResourceId resource_id : - render_pass->quad_list.front()->resources) { - resources.push_back(resource_id); - } + DCHECK_EQ(render_pass->quad_list.size(), 1u); + resources.assign(render_pass->quad_list.front()->resources.begin(), + render_pass->quad_list.front()->resources.end()); } resource_provider_->PrepareSendToParent(resources, &compositor_frame.resource_list); compositor_frame.render_pass_list.push_back(std::move(render_pass)); + + const auto& current_surface = + child_local_surface_id_allocator_.GetCurrentLocalSurfaceIdAllocation(); compositor_frame.metadata.local_surface_id_allocation_time = - child_local_surface_id_allocator_.GetCurrentLocalSurfaceIdAllocation() - .allocation_time(); + current_surface.allocation_time(); // TODO(lethalantidote): Address third/fourth arg in SubmitCompositorFrame. compositor_frame_sink_->SubmitCompositorFrame( - child_local_surface_id_allocator_.GetCurrentLocalSurfaceIdAllocation() - .local_surface_id(), - std::move(compositor_frame), nullptr, 0); + current_surface.local_surface_id(), std::move(compositor_frame), nullptr, + 0); resource_provider_->ReleaseFrameResources(); waiting_for_compositor_ack_ = true; @@ -312,10 +331,10 @@ } void VideoFrameSubmitter::SubmitEmptyFrame() { - TRACE_EVENT0("media", "VideoFrameSubmitter::SubmitEmptyFrame"); - DCHECK_CALLED_ON_VALID_THREAD(media_thread_checker_); + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); DCHECK(compositor_frame_sink_ && !ShouldSubmit()); DCHECK(!frame_size_.IsEmpty()); + TRACE_EVENT0("media", "VideoFrameSubmitter::SubmitEmptyFrame"); viz::CompositorFrame compositor_frame; @@ -324,9 +343,12 @@ compositor_frame.metadata.frame_token = ++next_frame_token_; compositor_frame.metadata.device_scale_factor = 1; compositor_frame.metadata.may_contain_video = true; + + const auto& current_surface = + child_local_surface_id_allocator_.GetCurrentLocalSurfaceIdAllocation(); + compositor_frame.metadata.local_surface_id_allocation_time = - child_local_surface_id_allocator_.GetCurrentLocalSurfaceIdAllocation() - .allocation_time(); + current_surface.allocation_time(); std::unique_ptr<viz::RenderPass> render_pass = viz::RenderPass::Create(); render_pass->SetNew(1, gfx::Rect(frame_size_), gfx::Rect(frame_size_), @@ -334,17 +356,17 @@ compositor_frame.render_pass_list.push_back(std::move(render_pass)); compositor_frame_sink_->SubmitCompositorFrame( - child_local_surface_id_allocator_.GetCurrentLocalSurfaceIdAllocation() - .local_surface_id(), - std::move(compositor_frame), nullptr, 0); + current_surface.local_surface_id(), std::move(compositor_frame), nullptr, + 0); waiting_for_compositor_ack_ = true; } void VideoFrameSubmitter::OnBeginFrame( const viz::BeginFrameArgs& args, WTF::HashMap<uint32_t, ::gfx::mojom::blink::PresentationFeedbackPtr>) { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); TRACE_EVENT0("media", "VideoFrameSubmitter::OnBeginFrame"); - DCHECK_CALLED_ON_VALID_THREAD(media_thread_checker_); + viz::BeginFrameAck current_begin_frame_ack(args, false); if (args.type == viz::BeginFrameArgs::MISSED) { compositor_frame_sink_->DidNotProduceFrame(current_begin_frame_ack); @@ -383,6 +405,8 @@ } void VideoFrameSubmitter::OnContextLost() { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + // TODO(lethalantidote): This check will be obsolete once other TODO to move // field initialization earlier is fulfilled. if (frame_sink_destroyed_callback_) @@ -391,9 +415,9 @@ if (binding_.is_bound()) binding_.Unbind(); - if (context_provider_) { + if (context_provider_) context_provider_->RemoveObserver(this); - } + waiting_for_compositor_ack_ = false; resource_provider_->OnContextLost(); @@ -418,15 +442,14 @@ void VideoFrameSubmitter::DidReceiveCompositorFrameAck( const WTF::Vector<viz::ReturnedResource>& resources) { - DCHECK_CALLED_ON_VALID_THREAD(media_thread_checker_); + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); ReclaimResources(resources); - waiting_for_compositor_ack_ = false; } void VideoFrameSubmitter::ReclaimResources( const WTF::Vector<viz::ReturnedResource>& resources) { - DCHECK_CALLED_ON_VALID_THREAD(media_thread_checker_); + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); WebVector<viz::ReturnedResource> temp_resources = resources; std::vector<viz::ReturnedResource> std_resources = temp_resources.ReleaseVector(); @@ -436,12 +459,14 @@ void VideoFrameSubmitter::DidAllocateSharedBitmap( mojo::ScopedSharedBufferHandle buffer, const viz::SharedBitmapId& id) { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); DCHECK(compositor_frame_sink_); compositor_frame_sink_->DidAllocateSharedBitmap( std::move(buffer), SharedBitmapIdToGpuMailboxPtr(id)); } void VideoFrameSubmitter::DidDeleteSharedBitmap(const viz::SharedBitmapId& id) { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); DCHECK(compositor_frame_sink_); compositor_frame_sink_->DidDeleteSharedBitmap( SharedBitmapIdToGpuMailboxPtr(id)); @@ -450,6 +475,7 @@ void VideoFrameSubmitter::SetSurfaceIdForTesting( const viz::SurfaceId& surface_id, base::TimeTicks allocation_time) { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); frame_sink_id_ = surface_id.frame_sink_id(); child_local_surface_id_allocator_.UpdateFromParent( viz::LocalSurfaceIdAllocation(surface_id.local_surface_id(),
diff --git a/third_party/blink/renderer/platform/graphics/video_frame_submitter.h b/third_party/blink/renderer/platform/graphics/video_frame_submitter.h index 42df64a..e81bfcd5 100644 --- a/third_party/blink/renderer/platform/graphics/video_frame_submitter.h +++ b/third_party/blink/renderer/platform/graphics/video_frame_submitter.h
@@ -28,19 +28,18 @@ // This single-threaded class facilitates the communication between the media // stack and browser renderer, providing compositor frames containing video -// frames and corresponding resources to the |compositor_frame_sink_|. This -// class has dependencies on classes that use the media thread's OpenGL -// ContextProvider, and thus, besides construction, should be consistently ran -// from the same media SingleThreadTaskRunner. +// frames and corresponding resources to the |compositor_frame_sink_|. +// +// This class requires and uses a viz::ContextProvider, and thus, besides +// construction, must be consistently accessed from the same thread. class PLATFORM_EXPORT VideoFrameSubmitter : public WebVideoFrameSubmitter, public viz::ContextLostObserver, public viz::SharedBitmapReporter, public viz::mojom::blink::CompositorFrameSinkClient { public: - explicit VideoFrameSubmitter(WebContextProviderCallback, - std::unique_ptr<VideoFrameResourceProvider>); - + VideoFrameSubmitter(WebContextProviderCallback, + std::unique_ptr<VideoFrameResourceProvider>); ~VideoFrameSubmitter() override; bool Rendering() { return is_rendering_; } @@ -61,7 +60,6 @@ // WebVideoFrameSubmitter implementation. void Initialize(cc::VideoFrameProvider*) override; void SetRotation(media::VideoRotation) override; - void SetIsOpaque(bool) override; void EnableSubmission(viz::SurfaceId, base::TimeTicks local_surface_id_allocation_time, WebFrameSinkDestroyedCallback) override; @@ -102,15 +100,15 @@ friend class VideoFrameSubmitterTest; void StartSubmitting(); - void UpdateSubmissionStateInternal(); + void UpdateSubmissionState(); + // Returns whether a frame was submitted. bool SubmitFrame(const viz::BeginFrameAck&, scoped_refptr<media::VideoFrame>); void SubmitEmptyFrame(); - // Pulls frame and submits it to compositor. - // Used in cases like PaintSingleFrame, which occurs before video rendering - // has started to post a poster image, or to submit a final frame before - // ending rendering. + // Pulls frame and submits it to compositor. Used in cases like + // DidReceiveFrame(), which occurs before video rendering has started to post + // the first frame or to submit a final frame before ending rendering. void SubmitSingleFrame(); // Return whether the submitter should submit frames based on its current @@ -142,7 +140,6 @@ // Needs to be initialized in implementation because media isn't a public_dep // of blink/platform. media::VideoRotation rotation_; - bool is_opaque_ = true; viz::FrameSinkId frame_sink_id_; @@ -158,7 +155,7 @@ const bool enable_surface_synchronization_; viz::FrameTokenGenerator next_frame_token_; - THREAD_CHECKER(media_thread_checker_); + THREAD_CHECKER(thread_checker_); base::WeakPtrFactory<VideoFrameSubmitter> weak_ptr_factory_;
diff --git a/third_party/blink/renderer/platform/graphics/video_frame_submitter_test.cc b/third_party/blink/renderer/platform/graphics/video_frame_submitter_test.cc index 5123814..62e37f91 100644 --- a/third_party/blink/renderer/platform/graphics/video_frame_submitter_test.cc +++ b/third_party/blink/renderer/platform/graphics/video_frame_submitter_test.cc
@@ -145,9 +145,6 @@ video_frame_provider_(new StrictMock<MockVideoFrameProvider>()), context_provider_(viz::TestContextProvider::Create()) { context_provider_->BindToCurrentThread(); - } - - void SetUp() override { MakeSubmitter(); scoped_task_environment_.RunUntilIdle(); } @@ -473,138 +470,6 @@ scoped_task_environment_.RunUntilIdle(); } -TEST_F(VideoFrameSubmitterTest, IsOpaquePassedToResourceProvider) { - // Check to see if is_opaque is communicated pre-rendering. - EXPECT_FALSE(submitter_->Rendering()); - - // We submit a frame on opacity change. - EXPECT_CALL(*sink_, SetNeedsBeginFrame(false)); - EXPECT_CALL(*video_frame_provider_, GetCurrentFrame()) - .WillOnce(Return(media::VideoFrame::CreateFrame( - media::PIXEL_FORMAT_YV12, gfx::Size(8, 8), gfx::Rect(gfx::Size(8, 8)), - gfx::Size(8, 8), base::TimeDelta()))); - EXPECT_CALL(*sink_, DoSubmitCompositorFrame(_, _)).Times(1); - EXPECT_CALL(*video_frame_provider_, PutCurrentFrame()); - EXPECT_CALL(*resource_provider_, AppendQuads(_, _, _, _)); - EXPECT_CALL(*resource_provider_, PrepareSendToParent(_, _)); - EXPECT_CALL(*resource_provider_, ReleaseFrameResources()); - - submitter_->SetIsOpaque(false); - scoped_task_environment_.RunUntilIdle(); - - { - WTF::Vector<viz::ReturnedResource> resources; - EXPECT_CALL(*resource_provider_, ReceiveReturnsFromParent(_)); - submitter_->DidReceiveCompositorFrameAck(resources); - } - - EXPECT_CALL(*video_frame_provider_, GetCurrentFrame()) - .WillOnce(Return(media::VideoFrame::CreateFrame( - media::PIXEL_FORMAT_YV12, gfx::Size(8, 8), gfx::Rect(gfx::Size(8, 8)), - gfx::Size(8, 8), base::TimeDelta()))); - EXPECT_CALL(*sink_, DoSubmitCompositorFrame(_, _)); - EXPECT_CALL(*video_frame_provider_, PutCurrentFrame()); - EXPECT_CALL(*resource_provider_, AppendQuads(_, _, _, false)); - EXPECT_CALL(*resource_provider_, PrepareSendToParent(_, _)); - EXPECT_CALL(*resource_provider_, ReleaseFrameResources()); - - submitter_->DidReceiveFrame(); - scoped_task_environment_.RunUntilIdle(); - - { - WTF::Vector<viz::ReturnedResource> resources; - EXPECT_CALL(*resource_provider_, ReceiveReturnsFromParent(_)); - submitter_->DidReceiveCompositorFrameAck(resources); - } - - // Check to see if an update to is_opaque just before rendering is - // communicated. - EXPECT_CALL(*sink_, SetNeedsBeginFrame(false)); - EXPECT_CALL(*video_frame_provider_, GetCurrentFrame()) - .WillOnce(Return(media::VideoFrame::CreateFrame( - media::PIXEL_FORMAT_YV12, gfx::Size(8, 8), gfx::Rect(gfx::Size(8, 8)), - gfx::Size(8, 8), base::TimeDelta()))); - EXPECT_CALL(*sink_, DoSubmitCompositorFrame(_, _)).Times(1); - EXPECT_CALL(*video_frame_provider_, PutCurrentFrame()); - EXPECT_CALL(*resource_provider_, AppendQuads(_, _, _, _)); - EXPECT_CALL(*resource_provider_, PrepareSendToParent(_, _)); - EXPECT_CALL(*resource_provider_, ReleaseFrameResources()); - submitter_->SetIsOpaque(true); - scoped_task_environment_.RunUntilIdle(); - - EXPECT_CALL(*sink_, SetNeedsBeginFrame(true)); - submitter_->StartRendering(); - scoped_task_environment_.RunUntilIdle(); - - { - WTF::Vector<viz::ReturnedResource> resources; - EXPECT_CALL(*resource_provider_, ReceiveReturnsFromParent(_)); - submitter_->DidReceiveCompositorFrameAck(resources); - } - - EXPECT_CALL(*video_frame_provider_, UpdateCurrentFrame(_, _)) - .WillOnce(Return(true)); - EXPECT_CALL(*video_frame_provider_, GetCurrentFrame()) - .WillOnce(Return(media::VideoFrame::CreateFrame( - media::PIXEL_FORMAT_YV12, gfx::Size(8, 8), gfx::Rect(gfx::Size(8, 8)), - gfx::Size(8, 8), base::TimeDelta()))); - EXPECT_CALL(*sink_, DoSubmitCompositorFrame(_, _)); - EXPECT_CALL(*video_frame_provider_, PutCurrentFrame()); - EXPECT_CALL(*resource_provider_, AppendQuads(_, _, _, true)); - EXPECT_CALL(*resource_provider_, PrepareSendToParent(_, _)); - EXPECT_CALL(*resource_provider_, ReleaseFrameResources()); - - viz::BeginFrameArgs args = begin_frame_source_->CreateBeginFrameArgs( - BEGINFRAME_FROM_HERE, now_src_.get()); - submitter_->OnBeginFrame(args, {}); - scoped_task_environment_.RunUntilIdle(); - - { - WTF::Vector<viz::ReturnedResource> resources; - EXPECT_CALL(*resource_provider_, ReceiveReturnsFromParent(_)); - submitter_->DidReceiveCompositorFrameAck(resources); - } - - // Check to see if changing is_opaque while rendering is handled. - EXPECT_CALL(*sink_, SetNeedsBeginFrame(true)); - EXPECT_CALL(*video_frame_provider_, GetCurrentFrame()) - .WillOnce(Return(media::VideoFrame::CreateFrame( - media::PIXEL_FORMAT_YV12, gfx::Size(8, 8), gfx::Rect(gfx::Size(8, 8)), - gfx::Size(8, 8), base::TimeDelta()))); - EXPECT_CALL(*sink_, DoSubmitCompositorFrame(_, _)).Times(1); - EXPECT_CALL(*video_frame_provider_, PutCurrentFrame()); - EXPECT_CALL(*resource_provider_, AppendQuads(_, _, _, _)); - EXPECT_CALL(*resource_provider_, PrepareSendToParent(_, _)); - EXPECT_CALL(*resource_provider_, ReleaseFrameResources()); - - submitter_->SetIsOpaque(false); - scoped_task_environment_.RunUntilIdle(); - - { - WTF::Vector<viz::ReturnedResource> resources; - EXPECT_CALL(*resource_provider_, ReceiveReturnsFromParent(_)); - submitter_->DidReceiveCompositorFrameAck(resources); - } - - EXPECT_CALL(*video_frame_provider_, UpdateCurrentFrame(_, _)) - .WillOnce(Return(true)); - EXPECT_CALL(*video_frame_provider_, GetCurrentFrame()) - .WillOnce(Return(media::VideoFrame::CreateFrame( - media::PIXEL_FORMAT_YV12, gfx::Size(8, 8), gfx::Rect(gfx::Size(8, 8)), - gfx::Size(8, 8), base::TimeDelta()))); - EXPECT_CALL(*sink_, DoSubmitCompositorFrame(_, _)); - EXPECT_CALL(*video_frame_provider_, PutCurrentFrame()); - EXPECT_CALL(*resource_provider_, AppendQuads(_, _, _, false)); - EXPECT_CALL(*resource_provider_, PrepareSendToParent(_, _)); - EXPECT_CALL(*resource_provider_, ReleaseFrameResources()); - - submitter_->OnBeginFrame(args, {}); - scoped_task_environment_.RunUntilIdle(); - - // Updating |is_opaque_| with the same value should not cause a frame submit. - submitter_->SetIsOpaque(false); -} - TEST_F(VideoFrameSubmitterTest, OnBeginFrameSubmitsFrame) { EXPECT_CALL(*sink_, SetNeedsBeginFrame(true));
diff --git a/third_party/blink/renderer/platform/loader/fetch/fetch_parameters.cc b/third_party/blink/renderer/platform/loader/fetch/fetch_parameters.cc index 01674de..497d88b 100644 --- a/third_party/blink/renderer/platform/loader/fetch/fetch_parameters.cc +++ b/third_party/blink/renderer/platform/loader/fetch/fetch_parameters.cc
@@ -123,13 +123,6 @@ SetAllowImagePlaceholder(); } -void FetchParameters::SetLazyImageDeferred() { - resource_request_.SetPreviewsState(resource_request_.GetPreviewsState() | - WebURLRequest::kLazyImageLoadDeferred); - DCHECK_EQ(kNone, image_request_optimization_); - image_request_optimization_ = kDeferImageLoad; -} - void FetchParameters::SetAllowImagePlaceholder() { DCHECK_EQ(kNone, image_request_optimization_); if (!resource_request_.Url().ProtocolIsInHTTPFamily() ||
diff --git a/third_party/blink/renderer/platform/loader/fetch/fetch_parameters.h b/third_party/blink/renderer/platform/loader/fetch/fetch_parameters.h index 76b6099..229410e 100644 --- a/third_party/blink/renderer/platform/loader/fetch/fetch_parameters.h +++ b/third_party/blink/renderer/platform/loader/fetch/fetch_parameters.h
@@ -182,10 +182,9 @@ // Client LoFi preview bit. void SetClientLoFiPlaceholder(); - // Configures the request to load an image as a placeholder or defers the - // image and sets the lazy image load bit. + // Configures the request to load an image as a placeholder and sets the + // lazy image load bit. void SetLazyImagePlaceholder(); - void SetLazyImageDeferred(); // Configures the request to load an image placeholder if the request is // eligible (e.g. the url's protocol is HTTP, etc.). If this request is
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5 index 0c6f40f..84a1b98 100644 --- a/third_party/blink/renderer/platform/runtime_enabled_features.json5 +++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -1308,6 +1308,9 @@ status: "stable", }, { + name: "UserActivationSameOriginVisibility", + }, + { name: "UserActivationV2", }, {
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations index 463c38e..b3cc6d4 100644 --- a/third_party/blink/web_tests/TestExpectations +++ b/third_party/blink/web_tests/TestExpectations
@@ -81,6 +81,17 @@ # The following tests passes only with User Activation v2 (UAv2) disabled. crbug.com/908841 external/wpt/fullscreen/api/element-ready-check-containing-iframe-manual.html [ Timeout ] +# The following tests fail with UserActivationSameOriginVisibility plus UAv2. +crbug.com/922725 external/wpt/fullscreen/api/element-ready-check-containing-iframe-manual.tentative.html [ Failure ] +crbug.com/922725 external/wpt/html/user-activation/activation-api-iframe-no-activate.tenative.html [ Failure ] +crbug.com/922725 fullscreen/full-screen-iframe-zIndex.html [ Timeout ] +crbug.com/922725 virtual/android/fullscreen/full-screen-iframe-zIndex.html [ Timeout ] +crbug.com/922725 virtual/user-activation-v2/fullscreen/full-screen-iframe-zIndex.html [ Timeout ] +crbug.com/922725 http/tests/media/autoplay/document-user-activation-cross-origin-feature-policy-disabled.html [ Failure ] +crbug.com/922725 http/tests/media/autoplay/document-user-activation-cross-origin-feature-policy-header.html [ Failure ] +crbug.com/922725 virtual/user-activation-v2/http/tests/media/autoplay/document-user-activation-cross-origin-feature-policy-disabled.html [ Failure ] +crbug.com/922725 virtual/user-activation-v2/http/tests/media/autoplay/document-user-activation-cross-origin-feature-policy-header.html [ Failure ] + # The following fail only on Mac. crbug.com/891427 [ Mac ] fast/events/touch/gesture/touch-gesture-scroll-listbox.html [ Pass Failure Timeout Crash ] crbug.com/891427 [ Mac ] virtual/scroll_customization/fast/events/touch/gesture/touch-gesture-scroll-listbox.html [ Pass Failure Timeout Crash ]
diff --git a/third_party/blink/web_tests/VirtualTestSuites b/third_party/blink/web_tests/VirtualTestSuites index 5d233a7..2dd79ac 100644 --- a/third_party/blink/web_tests/VirtualTestSuites +++ b/third_party/blink/web_tests/VirtualTestSuites
@@ -29,11 +29,6 @@ "base": "animations/animationworklet", "args": ["--enable-threaded-compositing"] }, - { - "prefix": "threaded", - "base": "external/wpt/animation-worklet", - "args": ["--enable-threaded-compositing"] - }, { "prefix": "threaded", "base": "lifecycle",
diff --git a/third_party/blink/web_tests/external/wpt/resource-timing/resource_connection_reuse.html b/third_party/blink/web_tests/external/wpt/resource-timing/resource_connection_reuse.html index 7a31a7e1..f347a0b 100644 --- a/third_party/blink/web_tests/external/wpt/resource-timing/resource_connection_reuse.html +++ b/third_party/blink/web_tests/external/wpt/resource-timing/resource_connection_reuse.html
@@ -41,7 +41,7 @@ test_equals(entry.fetchStart, entry.connectStart, 'connectStart and fetchStart should be the same'); test_equals(entry.fetchStart, entry.connectEnd, 'connectEnd and fetchStart should be the same'); if(!window.isSecureConnection) { - test_equals(entry.secureConnectionStart, 0, 'secureConnectStart should be zero'); + test_equals(entry.secureConnectionStart, 0, 'secureConnectionStart should be zero'); } test_equals(entry.fetchStart, entry.domainLookupStart, 'domainLookupStart and fetchStart should be the same') test_equals(entry.fetchStart, entry.domainLookupEnd, 'domainLookupEnd and fetchStart should be the same')
diff --git a/third_party/blink/web_tests/external/wpt/resource-timing/resource_connection_reuse.https.html b/third_party/blink/web_tests/external/wpt/resource-timing/resource_connection_reuse.https.html index bc79a851..8686409 100644 --- a/third_party/blink/web_tests/external/wpt/resource-timing/resource_connection_reuse.https.html +++ b/third_party/blink/web_tests/external/wpt/resource-timing/resource_connection_reuse.https.html
@@ -40,7 +40,7 @@ const entry = entries[1]; test_equals(entry.fetchStart, entry.connectStart, 'connectStart and fetchStart should be the same'); test_equals(entry.fetchStart, entry.connectEnd, 'connectEnd and fetchStart should be the same'); - test_equals(entry.fetchStart, entry.secureConnectionStart, 'secureConnectStart and fetchStart should be the same'); + test_equals(entry.fetchStart, entry.secureConnectionStart, 'secureConnectionStart and fetchStart should be the same'); test_equals(entry.fetchStart, entry.domainLookupStart, 'domainLookupStart and fetchStart should be the same') test_equals(entry.fetchStart, entry.domainLookupEnd, 'domainLookupEnd and fetchStart should be the same') }
diff --git a/third_party/blink/web_tests/external/wpt/resource-timing/resource_connection_reuse_mixed_content.html b/third_party/blink/web_tests/external/wpt/resource-timing/resource_connection_reuse_mixed_content.html new file mode 100644 index 0000000..51c04ee --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/resource-timing/resource_connection_reuse_mixed_content.html
@@ -0,0 +1,55 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8" /> +<title>Resource Timing connection reuse</title> +<link rel="author" title="Google" href="http://www.google.com/" /> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/webperftestharness.js"></script> +<script src="resources/webperftestharnessextension.js"></script> +<script> +setup({explicit_done: true}); +let iframe; +let d; +let body; + +// Explicitly test the namespace before we start testing. +test_namespace('getEntriesByType'); + +function setup_iframe() { + iframe = document.getElementById('frameContext'); + d = iframe.contentWindow.document; + iframe.addEventListener('load', onload_test, false); +} + +function onload_test() { + const entries = iframe.contentWindow.performance.getEntriesByType('resource'); + + // When a persistent connection is used, follow-on resources should be included as PerformanceResourceTiming objects. + test_equals(entries.length, 2, 'There should be 2 PerformanceEntries'); + + if (entries.length >= 2) { + // When a persistent connection is used, for the resource that reuses the socket, connectStart and connectEnd should have the same value as fetchStart. + const entry = entries[1]; + test_equals(entry.fetchStart, entry.connectStart, 'connectStart and fetchStart should be the same'); + test_equals(entry.fetchStart, entry.connectEnd, 'connectEnd and fetchStart should be the same'); + // secureConnectionStart is the same as fetchStart since the subresource is fetched over https + test_equals(entry.fetchStart, entry.secureConnectionStart, 'secureConnectionStart and fetchStart should be the same'); + test_equals(entry.fetchStart, entry.domainLookupStart, 'domainLookupStart and fetchStart should be the same') + test_equals(entry.fetchStart, entry.domainLookupEnd, 'domainLookupEnd and fetchStart should be the same') + } + + done(); +} + +window.setup_iframe = setup_iframe; +</script> +</head> +<body> +<h1>Description</h1> +<p>This test validates that connectStart and connectEnd are the same when a connection is reused (e.g. when a persistent connection is used).</p> +<div id="log"></div> +<iframe id="frameContext" src="resources/fake_responses_https.sub.html"></iframe> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/resource-timing/resource_connection_reuse_mixed_content_redirect.html b/third_party/blink/web_tests/external/wpt/resource-timing/resource_connection_reuse_mixed_content_redirect.html new file mode 100644 index 0000000..a46d14c --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/resource-timing/resource_connection_reuse_mixed_content_redirect.html
@@ -0,0 +1,55 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8" /> +<title>Resource Timing connection reuse</title> +<link rel="author" title="Google" href="http://www.google.com/" /> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/webperftestharness.js"></script> +<script src="resources/webperftestharnessextension.js"></script> +<script> +setup({explicit_done: true}); +let iframe; +let d; +let body; + +// Explicitly test the namespace before we start testing. +test_namespace('getEntriesByType'); + +function setup_iframe() { + iframe = document.getElementById('frameContext'); + d = iframe.contentWindow.document; + iframe.addEventListener('load', onload_test, false); +} + +function onload_test() { + const entries = iframe.contentWindow.performance.getEntriesByType('resource'); + + // When a persistent connection is used, follow-on resources should be included as PerformanceResourceTiming objects. + test_equals(entries.length, 2, 'There should be 2 PerformanceEntries'); + + if (entries.length >= 2) { + // When a persistent connection is used, for the resource that reuses the socket, connectStart and connectEnd should have the same value as fetchStart. + const entry = entries[1]; + test_equals(entry.fetchStart, entry.connectStart, 'connectStart and fetchStart should be the same'); + test_equals(entry.fetchStart, entry.connectEnd, 'connectEnd and fetchStart should be the same'); + // secureConnectionStart is the same as fetchStart since the subresource is eventually redirected to https. + test_equals(entry.fetchStart, entry.secureConnectionStart, 'secureConnectionStart and fetchStart should be the same'); + test_equals(entry.fetchStart, entry.domainLookupStart, 'domainLookupStart and fetchStart should be the same') + test_equals(entry.fetchStart, entry.domainLookupEnd, 'domainLookupEnd and fetchStart should be the same') + } + + done(); +} + +window.setup_iframe = setup_iframe; +</script> +</head> +<body> +<h1>Description</h1> +<p>This test validates that connectStart and connectEnd are the same when a connection is reused (e.g. when a persistent connection is used).</p> +<div id="log"></div> +<iframe id="frameContext" src="resources/fake_responses_https_redirect.sub.html"></iframe> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/resource-timing/resources/fake_responses.py b/third_party/blink/web_tests/external/wpt/resource-timing/resources/fake_responses.py index f7169381..289c179 100644 --- a/third_party/blink/web_tests/external/wpt/resource-timing/resources/fake_responses.py +++ b/third_party/blink/web_tests/external/wpt/resource-timing/resources/fake_responses.py
@@ -2,13 +2,20 @@ def main(request, response): tag = request.GET.first("tag", None) + redirect = request.GET.first("redirect", None) match = request.headers.get("If-None-Match", None) date = request.GET.first("date", "") modified = request.headers.get("If-Modified-Since", None) + response.headers.set("Access-Control-Allow-Origin", "*"); + response.headers.set("Timing-Allow-Origin", "*"); if tag: response.headers.set("ETag", '"%s"' % tag) elif date: response.headers.set("Last-Modified", date) + if redirect: + response.headers.set("Location", redirect) + response.status = (302, "Moved") + return "" if ((match is not None and match == tag) or (modified is not None and modified == date)): @@ -16,4 +23,4 @@ return "" else: response.headers.set("Content-Type", "text/plain") - return "MAYBE NOT" \ No newline at end of file + return "MAYBE NOT"
diff --git a/third_party/blink/web_tests/external/wpt/resource-timing/resources/fake_responses_https.sub.html b/third_party/blink/web_tests/external/wpt/resource-timing/resources/fake_responses_https.sub.html new file mode 100644 index 0000000..cf49fb9 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/resource-timing/resources/fake_responses_https.sub.html
@@ -0,0 +1,18 @@ +<body> +<script> +function request() { + var client = new XMLHttpRequest, + baseurl = "https://{{hosts[][www]}}:{{ports[https][0]}}{{location[pathname]}}", + url = new URL("fake_responses.py", baseurl).href; + client.open("GET", url, false) + client.send(null) + client.open("GET", url, false) + client.send(null) +} + +if(window.parent.setup_iframe) { + window.parent.setup_iframe(); + request(); +} +</script> +</body>
diff --git a/third_party/blink/web_tests/external/wpt/resource-timing/resources/fake_responses_https_redirect.sub.html b/third_party/blink/web_tests/external/wpt/resource-timing/resources/fake_responses_https_redirect.sub.html new file mode 100644 index 0000000..c55e037d --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/resource-timing/resources/fake_responses_https_redirect.sub.html
@@ -0,0 +1,20 @@ +<body> +<script> +function request() { + var client = new XMLHttpRequest, + baseurl = "http://{{hosts[][www]}}:{{ports[http][0]}}{{location[pathname]}}", + subresource = "fake_responses.py", + redirecturl = new URL(subresource, "https://{{hosts[][www]}}:{{ports[https][0]}}{{location[pathname]}}").href, + url = new URL(subresource + "?redirect=" + redirecturl, baseurl).href; + client.open("GET", url, false) + client.send(null) + client.open("GET", url, false) + client.send(null) +} + +if(window.parent.setup_iframe) { + window.parent.setup_iframe(); + request(); +} +</script> +</body>
diff --git a/third_party/blink/web_tests/external/wpt/workers/README.md b/third_party/blink/web_tests/external/wpt/workers/README.md index 78cc74371..b78a05e 100644 --- a/third_party/blink/web_tests/external/wpt/workers/README.md +++ b/third_party/blink/web_tests/external/wpt/workers/README.md
@@ -1,2 +1,137 @@ +# Worker WPT tests + These are the workers (`Worker`, `SharedWorker`) tests for the [Web workers chapter of the HTML Standard](https://html.spec.whatwg.org/multipage/workers.html). + +See also +[testharness.js API > Web Workers](https://web-platform-tests.org/writing-tests/testharness-api.html#web-workers). + +## Writing `*.any.js` + +The easiest and most recommended way to write tests for workers +is to create .any.js-style tests. + +Official doc: +[WPT > File Name Flags > Test Features](https://web-platform-tests.org/writing-tests/file-names.html#test-features). + +- Standard `testharness.js`-style can be used (and is enforced). +- The same test can be run on window and many types of workers. +- All glue code are automatically generated. +- No need to care about how to create and communicate with each type of workers, + thanks to `fetch_tests_from_worker` in `testharness.js`. + +Converting existing tests into `.any.js`-style also has benefits: + +- Multiple tests can be merged into one. +- Tests written for window can be run on workers + with a very low development cost. + +### How to write tests + +If you write `testharness.js`-based tests in `foo.any.js` and +specify types of workers to be tested, +the test can run on any of dedicated, shared and service workers. + +See `examples/general.any.js` for example. + +Even for testing specific features in a specific type of workers +(e.g. shared worker's `onconnect`), `.any.js`-style tests can be used. + +See `examples/onconnect.any.js` for example. + +### How to debug tests + +Whether each individual test passed or failed, +and its assertion failures (if any) are all reported in the final results. + +`console.log()` might not appear in the test results and +thus might not be useful for printf debugging. +For example, in Chromium, this message + +- Appears (in stderr) on a window or a dedicated worker, but +- Does NOT appear on a shared worker or a service worker. + +### How it works + +`.any.js`-style tests use +`fetch_tests_from_worker` functionality of `testharness.js`. + +The WPT test server generates necessary glue code +(including generated Document HTML and worker top-level scripts). +See +[serve.py](https://github.com/web-platform-tests/wpt/blob/master/tools/serve/serve.py) +for the actual glue code. + +Note that `.any.js` file is not the worker top-level script, +and currently we cannot set response headers to the worker top-level script, +e.g. to set Referrer Policy of the workers. + +## Writing `*.worker.js` + +Similar to `.any.js`, you can also write `.worker.js` +for tests only for dedicated workers. +Almost the same as `.any.js`, except for the things listed below. + +Official doc: +[WPT > File Name Flags > Test Features](https://web-platform-tests.org/writing-tests/file-names.html#test-features). + +### How to write tests + +You have to write two things manually (which is generated in `.any.js` tests): + +- `importScripts("/resources/testharness.js");` at the beginning. +- `done();` at the bottom. + +Note: Even if you write `async_test()` or `promise_test()`, +this global `done()` is always needed +(this is different from async_test's `done()`) +for dedicated workers and shared workers. +See official doc: +[testharness.js API > Determining when all tests are complete](https://web-platform-tests.org/writing-tests/testharness-api.html#determining-when-all-tests-are-complete). + +See `examples/general.worker.js` for example. + +### How it works + +`.worker.js`-style tests also use +`fetch_tests_from_worker` functionality of `testharness.js`. + +The WPT test server generates glue code in Document HTML-side, +but not for worker top-level scripts. +This is why you have to manually write `importScripts()` etc. +See +[serve.py](https://github.com/web-platform-tests/wpt/blob/master/tools/serve/serve.py) +for the actual glue code. + +Unlike `*.any.js` cases, the `*.worker.js` is the worker top-level script. + +## Using `fetch_tests_from_worker` + +If you need more flexibility, +writing tests using `fetch_tests_from_worker` is the way to go. +For example, when + +- Additional processing is needed on the parent Document. +- Workers should be created in a specific way. +- You are writing non-WPT tests using `testharness.js`. + +You have to write the main HTMLs and the worker scripts, +but most of the glue code needed for running tests on workers +are provided by `fetch_tests_from_worker`. + +### How to write tests + +See + +- `examples/fetch_tests_from_worker.html` and + `examples/fetch_tests_from_worker.js`. + +## Writing the whole tests manually + +If `fetch_tests_from_worker` isn't suitable for your specific case +(which should be rare but might be still possible), +you have to write the whole tests, +including the main Document HTML, worker scripts, +and message passing code between them. + +TODO: Supply the templates for writing this kind of tests.
diff --git a/third_party/blink/web_tests/external/wpt/workers/examples/fetch_tests_from_worker.html b/third_party/blink/web_tests/external/wpt/workers/examples/fetch_tests_from_worker.html new file mode 100644 index 0000000..5ac765c7 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/workers/examples/fetch_tests_from_worker.html
@@ -0,0 +1,21 @@ +<!doctype html> +<!-- + This file is an example of a hand-written test using + fetch_tests_from_worker(). + Unlike *.any.js or *.worker.js tests, fetch_tests_from_worker.html/js files + are manually written and no generated glue code are involved. +--> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> +fetch_tests_from_worker(new Worker("fetch_tests_from_worker.js")); + +// If you want to test on SharedWorker, +// fetch_tests_from_worker(new SharedWorker("fetch_tests_from_worker.js")); + +// See ServiceWorkersHandler in +// https://github.com/web-platform-tests/wpt/blob/master/tools/serve/serve.py +// for the generated snippet used in .any.js for service workers. +// Note: when testing service workers, also add ".https." file flag in the +// main HTML's file name to run the test on HTTPS. +</script>
diff --git a/third_party/blink/web_tests/external/wpt/workers/examples/fetch_tests_from_worker.js b/third_party/blink/web_tests/external/wpt/workers/examples/fetch_tests_from_worker.js new file mode 100644 index 0000000..01ba12a --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/workers/examples/fetch_tests_from_worker.js
@@ -0,0 +1,28 @@ +// This file is an example of a hand-written test using +// fetch_tests_from_worker(). +// Unlike *.any.js or *.worker.js tests, fetch_tests_from_worker.html/js files +// are manually written and no generated glue code are involved. + +// fetch_tests_from_worker() requires testharness.js both on the parent +// document and on the worker. +importScripts("/resources/testharness.js"); + +// ============================================================================ + +// Test body. +test(() => { + assert_equals(1, 1, "1 == 1"); + }, + "Test that should pass" +); + +// ============================================================================ + +// `done()` is always needed at the bottom for dedicated workers and shared +// workers, even if you write `async_test()` or `promise_test()`. +// `async_test()` and `promise_test()` called before this `done()` +// will continue and assertions/failures after this `done()` are not ignored. +// See +// https://web-platform-tests.org/writing-tests/testharness-api.html#determining-when-all-tests-are-complete +// for details. +done();
diff --git a/third_party/blink/web_tests/external/wpt/workers/examples/general.any.js b/third_party/blink/web_tests/external/wpt/workers/examples/general.any.js new file mode 100644 index 0000000..2aa82e3d --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/workers/examples/general.any.js
@@ -0,0 +1,34 @@ +// META: global=!default,worker + +// See +// https://web-platform-tests.org/writing-tests/testharness.html#multi-global-tests +// for how to specify in which global scopes to run this tests, +// how to specify additional scripts needed, etc. + +// testharness.js is imported (via importScripts()) by generated glue code by +// WPT server. +// See AnyWorkerHandler in +// https://github.com/web-platform-tests/wpt/blob/master/tools/serve/serve.py. + +// ============================================================================ + +// Test body. +// .any.js tests are always testharness.js-based. +test(() => { + assert_equals(1, 1, "1 == 1"); + }, + "Test that should pass" +); + +test(() => { + // This file is "general.any.js" but the worker top-level script is + // "general.any.worker.js", which is generated by the WPT server. + assert_equals(location.pathname, "/workers/examples/general.any.worker.js"); + }, + "Worker top-level script is a generated script." +); + +// done() is NOT needed in .any.js tests, as it is called by generated +// glue code by the WPT server. +// See AnyWorkerHandler in +// https://github.com/web-platform-tests/wpt/blob/master/tools/serve/serve.py.
diff --git a/third_party/blink/web_tests/external/wpt/workers/examples/general.worker.js b/third_party/blink/web_tests/external/wpt/workers/examples/general.worker.js new file mode 100644 index 0000000..aeca236 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/workers/examples/general.worker.js
@@ -0,0 +1,35 @@ +// This file is an example of a test using *.worker.js mechanism. +// The parent document that calls fetch_tests_from_worker() is auto-generated +// but there are no generated code in the worker side. + +// fetch_tests_from_worker() requires testharness.js both on the parent +// document and on the worker. +importScripts("/resources/testharness.js"); + +// ============================================================================ + +// Test body. +test(() => { + assert_equals(1, 1, "1 == 1"); + }, + "Test that should pass" +); + +test(() => { + // This file is "general.worker.js" and this file itself is the worker + // top-level script (which is different from the .any.js case). + assert_equals(location.pathname, "/workers/examples/general.worker.js"); + }, + "Worker top-level script is the .worker.js file itself." +); + +// ============================================================================ + +// `done()` is always needed at the bottom for dedicated workers and shared +// workers, even if you write `async_test()` or `promise_test()`. +// `async_test()` and `promise_test()` called before this `done()` +// will continue and assertions/failures after this `done()` are not ignored. +// See +// https://web-platform-tests.org/writing-tests/testharness-api.html#determining-when-all-tests-are-complete +// for details. +done();
diff --git a/third_party/blink/web_tests/external/wpt/workers/examples/onconnect.any.js b/third_party/blink/web_tests/external/wpt/workers/examples/onconnect.any.js new file mode 100644 index 0000000..85546f2 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/workers/examples/onconnect.any.js
@@ -0,0 +1,4 @@ +// META: global=!default,sharedworker +const t = async_test("onconnect is called"); +onconnect = t.step_func_done((event) => { +});
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/paint/invalidation/window-resize/window-resize-child-background-image-fixed-tiled-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/paint/invalidation/window-resize/window-resize-child-background-image-fixed-tiled-expected.txt new file mode 100644 index 0000000..627612a --- /dev/null +++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/paint/invalidation/window-resize/window-resize-child-background-image-fixed-tiled-expected.txt
@@ -0,0 +1,191 @@ +{ + "layers": [ + { + "name": "Scrolling background of LayoutView #document", + "bounds": [1008, 1016], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF" + }, + { + "name": "HorizontalScrollbar", + "bounds": [600, 250], + "paintInvalidations": [ + { + "object": "LayoutView #document", + "rect": [0, 0, 600, 250], + "reason": "geometry" + }, + { + "object": "HorizontalScrollbar", + "rect": [0, 235, 585, 15], + "reason": "scroll control" + }, + { + "object": "VerticalScrollbar", + "rect": [585, 0, 15, 250], + "reason": "scroll control" + } + ] + }, + { + "name": "LayoutBlockFlow HTML", + "position": [8, 8], + "bounds": [1000, 1000], + "contentsOpaque": true, + "backgroundColor": "#000000", + "paintInvalidations": [ + { + "object": "LayoutBlockFlow DIV id='target'", + "rect": [0, 0, 1000, 1000], + "reason": "background" + } + ] + } + ] +} +{ + "layers": [ + { + "name": "Scrolling background of LayoutView #document", + "bounds": [1008, 1016], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF" + }, + { + "name": "HorizontalScrollbar", + "bounds": [400, 250], + "paintInvalidations": [ + { + "object": "LayoutView #document", + "rect": [0, 0, 400, 250], + "reason": "geometry" + }, + { + "object": "HorizontalScrollbar", + "rect": [0, 235, 400, 15], + "reason": "scroll control" + }, + { + "object": "VerticalScrollbar", + "rect": [385, 0, 15, 235], + "reason": "scroll control" + } + ] + }, + { + "name": "LayoutBlockFlow HTML", + "position": [8, 8], + "bounds": [1000, 1000], + "contentsOpaque": true, + "backgroundColor": "#000000", + "paintInvalidations": [ + { + "object": "LayoutBlockFlow DIV id='target'", + "rect": [0, 0, 1000, 1000], + "reason": "background" + } + ] + } + ] +} +{ + "layers": [ + { + "name": "Scrolling background of LayoutView #document", + "bounds": [1008, 1016], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF" + }, + { + "name": "HorizontalScrollbar", + "bounds": [400, 600], + "paintInvalidations": [ + { + "object": "LayoutView #document", + "rect": [0, 0, 400, 600], + "reason": "geometry" + }, + { + "object": "HorizontalScrollbar", + "rect": [0, 585, 385, 15], + "reason": "scroll control" + }, + { + "object": "HorizontalScrollbar", + "rect": [0, 235, 385, 15], + "reason": "scroll control" + }, + { + "object": "VerticalScrollbar", + "rect": [385, 0, 15, 585], + "reason": "scroll control" + } + ] + }, + { + "name": "LayoutBlockFlow HTML", + "position": [8, 8], + "bounds": [1000, 1000], + "contentsOpaque": true, + "backgroundColor": "#000000", + "paintInvalidations": [ + { + "object": "LayoutBlockFlow DIV id='target'", + "rect": [0, 0, 1000, 1000], + "reason": "background" + } + ] + } + ] +} +{ + "layers": [ + { + "name": "Scrolling background of LayoutView #document", + "bounds": [1008, 1016], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF" + }, + { + "name": "HorizontalScrollbar", + "bounds": [800, 600], + "paintInvalidations": [ + { + "object": "LayoutView #document", + "rect": [0, 0, 800, 600], + "reason": "geometry" + }, + { + "object": "HorizontalScrollbar", + "rect": [0, 585, 785, 15], + "reason": "scroll control" + }, + { + "object": "VerticalScrollbar", + "rect": [785, 0, 15, 585], + "reason": "scroll control" + }, + { + "object": "VerticalScrollbar", + "rect": [385, 0, 15, 585], + "reason": "scroll control" + } + ] + }, + { + "name": "LayoutBlockFlow HTML", + "position": [8, 8], + "bounds": [1000, 1000], + "contentsOpaque": true, + "backgroundColor": "#000000", + "paintInvalidations": [ + { + "object": "LayoutBlockFlow DIV id='target'", + "rect": [0, 0, 1000, 1000], + "reason": "background" + } + ] + } + ] +} +
diff --git a/third_party/blink/web_tests/http/tests/devtools/elements/styles/styles-mouse-test.js b/third_party/blink/web_tests/http/tests/devtools/elements/styles/styles-mouse-test.js index d7a3878..a0dc655 100644 --- a/third_party/blink/web_tests/http/tests/devtools/elements/styles/styles-mouse-test.js +++ b/third_party/blink/web_tests/http/tests/devtools/elements/styles/styles-mouse-test.js
@@ -69,11 +69,11 @@ TestRunner.addResult('Not editing'); return; } - TestRunner.addResult('Editing: "' + document.deepActiveElement().textContent + '"'); + TestRunner.addResult('Editing: "' + TestRunner.textContentWithoutStyles(document.deepActiveElement()) + '"'); } function mouseDown(element, offset = 0) { - TestRunner.addResult('mouse down: ' + element.tagName + ':' + element.textContent); + TestRunner.addResult('mouse down: ' + element.tagName + ':' + TestRunner.textContentWithoutStyles(element)); var rect = element.getBoundingClientRect(); eventSender.mouseMoveTo((rect.left + rect.right) / 2 + offset, (rect.top + rect.bottom) / 2); eventSender.mouseDown(); @@ -81,7 +81,7 @@ } function mouseUp(element, offset = 0) { - TestRunner.addResult('mouse up: ' + element.tagName + ':' + element.textContent); + TestRunner.addResult('mouse up: ' + element.tagName + ':' + TestRunner.textContentWithoutStyles(element)); var rect = element.getBoundingClientRect(); eventSender.mouseMoveTo((rect.left + rect.right) / 2 + offset, (rect.top + rect.bottom) / 2); eventSender.mouseUp();
diff --git a/third_party/blink/web_tests/http/tests/devtools/elements/styles/up-down-numerics-and-colors.js b/third_party/blink/web_tests/http/tests/devtools/elements/styles/up-down-numerics-and-colors.js index bc9cff46..217a980b 100644 --- a/third_party/blink/web_tests/http/tests/devtools/elements/styles/up-down-numerics-and-colors.js +++ b/third_party/blink/web_tests/http/tests/devtools/elements/styles/up-down-numerics-and-colors.js
@@ -36,7 +36,7 @@ colorTreeElement.valueElement.dispatchEvent( TestRunner.createKeyEvent('ArrowDown', /*Ctrl*/ true, /*Alt*/ false, /*Shift*/ true, /*Meta*/ false)); - TestRunner.addResult(colorTreeElement.listItemElement.textContent); + TestRunner.addResult(TestRunner.textContentWithoutStyles(colorTreeElement.listItemElement)); next(); }, @@ -51,7 +51,7 @@ // Shift + PageUp should change to 11.6 opacityTreeElement.valueElement.dispatchEvent( TestRunner.createKeyEvent('PageUp', /*Ctrl*/ false, /*Alt*/ false, /*Shift*/ true)); - TestRunner.addResult(opacityTreeElement.listItemElement.textContent); + TestRunner.addResult(TestRunner.textContentWithoutStyles(opacityTreeElement.listItemElement)); next(); }, @@ -67,7 +67,7 @@ selection.addRange(newRange); treeElement.valueElement.dispatchEvent(TestRunner.createKeyEvent('ArrowUp')); treeElement.valueElement.dispatchEvent(TestRunner.createKeyEvent('PageUp')); - TestRunner.addResult(treeElement.listItemElement.textContent); + TestRunner.addResult(TestRunner.textContentWithoutStyles(treeElement.listItemElement)); next(); } ]);
diff --git a/third_party/blink/web_tests/http/tests/devtools/security/interstitial-sidebar-expected.txt b/third_party/blink/web_tests/http/tests/devtools/security/interstitial-sidebar-expected.txt index decd73e..95b45ff 100644 --- a/third_party/blink/web_tests/http/tests/devtools/security/interstitial-sidebar-expected.txt +++ b/third_party/blink/web_tests/http/tests/devtools/security/interstitial-sidebar-expected.txt
@@ -9,6 +9,8 @@ </STYLE> <STYLE type=text/css > </STYLE> + <STYLE type=text/css > + </STYLE> <DIV class=tree-outline-disclosure > <OL class=tree-outline role=tree tabindex=-1 > <LI role=treeitem class=security-main-view-sidebar-tree-item selected force-white-icons tabindex=0 > @@ -128,6 +130,8 @@ </STYLE> <STYLE type=text/css > </STYLE> + <STYLE type=text/css > + </STYLE> <DIV class=tree-outline-disclosure > <OL class=tree-outline role=tree tabindex=-1 > <LI role=treeitem class=security-main-view-sidebar-tree-item selected force-white-icons tabindex=0 > @@ -247,6 +251,8 @@ </STYLE> <STYLE type=text/css > </STYLE> + <STYLE type=text/css > + </STYLE> <DIV class=tree-outline-disclosure > <OL class=tree-outline role=tree tabindex=-1 > <LI role=treeitem class=security-main-view-sidebar-tree-item selected force-white-icons tabindex=0 >
diff --git a/third_party/blink/web_tests/http/tests/devtools/security/origin-view-ct-compliance-expected.txt b/third_party/blink/web_tests/http/tests/devtools/security/origin-view-ct-compliance-expected.txt index af134f2d..ba9f064 100644 --- a/third_party/blink/web_tests/http/tests/devtools/security/origin-view-ct-compliance-expected.txt +++ b/third_party/blink/web_tests/http/tests/devtools/security/origin-view-ct-compliance-expected.txt
@@ -26,18 +26,8 @@ </SPAN> </DIV> <DIV class=view-network-button > - <BUTTON is=text-button type=button class=origin-button > + <BUTTON class=origin-button text-button type=button > View requests in Network Panel - <#document-fragment > - <STYLE type=text/css > - </STYLE> - <STYLE type=text/css > - </STYLE> - <STYLE type=text/css > - </STYLE> - <CONTENT > - </CONTENT> - </#document-fragment> </BUTTON> </DIV> </DIV> @@ -128,18 +118,8 @@ <DIV > </DIV> <DIV > - <BUTTON is=text-button type=button class=origin-button > + <BUTTON class=origin-button text-button type=button > Open full certificate details - <#document-fragment > - <STYLE type=text/css > - </STYLE> - <STYLE type=text/css > - </STYLE> - <STYLE type=text/css > - </STYLE> - <CONTENT > - </CONTENT> - </#document-fragment> </BUTTON> </DIV> </DIV>
diff --git a/third_party/blink/web_tests/http/tests/devtools/security/origin-view-then-interstitial-expected.txt b/third_party/blink/web_tests/http/tests/devtools/security/origin-view-then-interstitial-expected.txt index b525227..1a6bee5 100644 --- a/third_party/blink/web_tests/http/tests/devtools/security/origin-view-then-interstitial-expected.txt +++ b/third_party/blink/web_tests/http/tests/devtools/security/origin-view-then-interstitial-expected.txt
@@ -54,18 +54,8 @@ </SPAN> </DIV> <DIV class=view-network-button > - <BUTTON is=text-button type=button class=origin-button > + <BUTTON class=origin-button text-button type=button > View requests in Network Panel - <#document-fragment > - <STYLE type=text/css > - </STYLE> - <STYLE type=text/css > - </STYLE> - <STYLE type=text/css > - </STYLE> - <CONTENT > - </CONTENT> - </#document-fragment> </BUTTON> </DIV> </DIV>
diff --git a/third_party/blink/web_tests/http/tests/devtools/security/security-details-updated-with-security-state-expected.txt b/third_party/blink/web_tests/http/tests/devtools/security/security-details-updated-with-security-state-expected.txt index 5638d88..9877d71 100644 --- a/third_party/blink/web_tests/http/tests/devtools/security/security-details-updated-with-security-state-expected.txt +++ b/third_party/blink/web_tests/http/tests/devtools/security/security-details-updated-with-security-state-expected.txt
@@ -70,18 +70,8 @@ </SPAN> </DIV> <DIV class=view-network-button > - <BUTTON is=text-button type=button class=origin-button > + <BUTTON class=origin-button text-button type=button > View requests in Network Panel - <#document-fragment > - <STYLE type=text/css > - </STYLE> - <STYLE type=text/css > - </STYLE> - <STYLE type=text/css > - </STYLE> - <CONTENT > - </CONTENT> - </#document-fragment> </BUTTON> </DIV> </DIV> @@ -172,18 +162,8 @@ <DIV > </DIV> <DIV > - <BUTTON is=text-button type=button class=origin-button > + <BUTTON class=origin-button text-button type=button > Open full certificate details - <#document-fragment > - <STYLE type=text/css > - </STYLE> - <STYLE type=text/css > - </STYLE> - <STYLE type=text/css > - </STYLE> - <CONTENT > - </CONTENT> - </#document-fragment> </BUTTON> </DIV> </DIV>
diff --git a/third_party/blink/web_tests/http/tests/devtools/security/security-explanation-ordering-expected.txt b/third_party/blink/web_tests/http/tests/devtools/security/security-explanation-ordering-expected.txt index 104c328..56baad85 100644 --- a/third_party/blink/web_tests/http/tests/devtools/security/security-explanation-ordering-expected.txt +++ b/third_party/blink/web_tests/http/tests/devtools/security/security-explanation-ordering-expected.txt
@@ -10,18 +10,8 @@ <DIV > The connection to this site is using a valid, trusted server certificate. </DIV> - <BUTTON is=text-button type=button class=security-certificate-button > + <BUTTON class=security-certificate-button text-button type=button > View certificate - <#document-fragment > - <STYLE type=text/css > - </STYLE> - <STYLE type=text/css > - </STYLE> - <STYLE type=text/css > - </STYLE> - <CONTENT > - </CONTENT> - </#document-fragment> </BUTTON> </DIV> </DIV>
diff --git a/third_party/blink/web_tests/http/tests/devtools/unit/text-prompt-hint.js b/third_party/blink/web_tests/http/tests/devtools/unit/text-prompt-hint.js index ad715484..109e8b9e 100644 --- a/third_party/blink/web_tests/http/tests/devtools/unit/text-prompt-hint.js +++ b/third_party/blink/web_tests/http/tests/devtools/unit/text-prompt-hint.js
@@ -91,22 +91,6 @@ function typeCharacter(character) { - var keyboardEvent = new KeyboardEvent("keydown", { - key: character || "Backspace", - charCode: character ? character.charCodeAt(0) : "" - }); - element.dispatchEvent(keyboardEvent); - - var selection = element.getComponentSelection(); - var range = selection.getRangeAt(0); - var textNode = prompt._ghostTextElement.parentNode ? prompt._ghostTextElement.previousSibling : element.childTextNodes()[element.childTextNodes().length - 1]; - if (!character) - textNode.textContent = textNode.textContent.substring(0,textNode.textContent.length-1); - else - textNode.textContent += character; - range.setStart(range.startContainer, range.startContainer.textContent.length); - selection.removeAllRanges(); - selection.addRange(range); - element.dispatchEvent(new Event("input", {bubbles: true, cancelable: false})); + eventSender.keyDown(character || 'Backspace'); } })();
diff --git a/third_party/blink/web_tests/paint/invalidation/window-resize/window-resize-child-background-image-fixed-tiled-expected.html b/third_party/blink/web_tests/paint/invalidation/window-resize/window-resize-child-background-image-fixed-tiled-expected.html new file mode 100644 index 0000000..af649c18 --- /dev/null +++ b/third_party/blink/web_tests/paint/invalidation/window-resize/window-resize-child-background-image-fixed-tiled-expected.html
@@ -0,0 +1,10 @@ +<!DOCTYPE html> +<style> +#target { + width: 1000px; + height: 1000px; + background-image: url(../resources/apple.jpg); + background-attachment: fixed; +} +</style> +<div id="target"></div>
diff --git a/third_party/blink/web_tests/paint/invalidation/window-resize/window-resize-child-background-image-fixed-tiled-expected.txt b/third_party/blink/web_tests/paint/invalidation/window-resize/window-resize-child-background-image-fixed-tiled-expected.txt new file mode 100644 index 0000000..13a87c0e --- /dev/null +++ b/third_party/blink/web_tests/paint/invalidation/window-resize/window-resize-child-background-image-fixed-tiled-expected.txt
@@ -0,0 +1,113 @@ +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [600, 250], + "drawsContent": false, + "backgroundColor": "#FFFFFF" + }, + { + "name": "Scrolling Layer", + "bounds": [585, 235], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [1008, 1016], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF", + "paintInvalidations": [ + { + "object": "LayoutBlockFlow DIV id='target'", + "rect": [8, 8, 1000, 1000], + "reason": "background" + } + ] + } + ] +} +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [400, 250], + "drawsContent": false, + "backgroundColor": "#FFFFFF" + }, + { + "name": "Scrolling Layer", + "bounds": [385, 235], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [1008, 1016], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF", + "paintInvalidations": [ + { + "object": "LayoutBlockFlow DIV id='target'", + "rect": [8, 8, 1000, 1000], + "reason": "background" + } + ] + } + ] +} +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [400, 600], + "drawsContent": false, + "backgroundColor": "#FFFFFF" + }, + { + "name": "Scrolling Layer", + "bounds": [385, 585], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [1008, 1016], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF", + "paintInvalidations": [ + { + "object": "LayoutBlockFlow DIV id='target'", + "rect": [8, 8, 1000, 1000], + "reason": "background" + } + ] + } + ] +} +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [800, 600], + "drawsContent": false, + "backgroundColor": "#FFFFFF" + }, + { + "name": "Scrolling Layer", + "bounds": [785, 585], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [1008, 1016], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF", + "paintInvalidations": [ + { + "object": "LayoutBlockFlow DIV id='target'", + "rect": [8, 8, 1000, 1000], + "reason": "background" + } + ] + } + ] +} +
diff --git a/third_party/blink/web_tests/paint/invalidation/window-resize/window-resize-child-background-image-fixed-tiled.html b/third_party/blink/web_tests/paint/invalidation/window-resize/window-resize-child-background-image-fixed-tiled.html new file mode 100644 index 0000000..cbc1912 --- /dev/null +++ b/third_party/blink/web_tests/paint/invalidation/window-resize/window-resize-child-background-image-fixed-tiled.html
@@ -0,0 +1,12 @@ +<!DOCTYPE html> +<script src="../../../resources/run-after-layout-and-paint.js"></script> +<script src="../resources/window-resize-repaint.js"></script> +<style> +#target { + width: 1000px; + height: 1000px; + background-image: url(../resources/apple.jpg); + background-attachment: fixed; +} +</style> +<div id="target"></div>
diff --git a/third_party/blink/web_tests/reporting-observer/buffer-overflow.html b/third_party/blink/web_tests/reporting-observer/buffer-overflow.html new file mode 100644 index 0000000..8815c546 --- /dev/null +++ b/third_party/blink/web_tests/reporting-observer/buffer-overflow.html
@@ -0,0 +1,31 @@ +<!doctype html> +<script src="../resources/testharness.js"></script> +<script src="../resources/testharnessreport.js"></script> +<script src="resources/intervention.js"></script> + +<div id="target" style="padding: 10px; background-color: blue;"> + <p>Testing ReportingObserver's buffer size.</p> +</div> + +<script> +async_test(function(test) { + var observer3 = new ReportingObserver(function(reports, observer) { + test.step(function() { + // All 101 buffered reports should be received. + assert_equals(reports.length, 101); + }); + + test.done(); + }, { buffered: true }); + + // Generate 110 intervention reports and 1 deprecation report. Only 100 + // reports should be buffered per report type, so 101 total. + for (var i = 0; i != 110; ++i) { + causeIntervention(); + } + window.webkitStorageInfo; + + observer3.observe(); + observer3.disconnect(); +}, "Buffer overflow"); +</script>
diff --git a/third_party/blink/web_tests/reporting-observer/resources/intervention.js b/third_party/blink/web_tests/reporting-observer/resources/intervention.js index 4b2fe00..dc883cbb 100644 --- a/third_party/blink/web_tests/reporting-observer/resources/intervention.js +++ b/third_party/blink/web_tests/reporting-observer/resources/intervention.js
@@ -21,7 +21,7 @@ }; var event = new TouchEvent('touchstart', touchEventInit); - var deadline = performance.now() + 100; + var deadline = performance.now() + 1; while (performance.now() < deadline) {}; document.body.dispatchEvent(event);
diff --git a/third_party/blink/web_tests/virtual/threaded/external/wpt/animation-worklet/README.txt b/third_party/blink/web_tests/virtual/threaded/external/wpt/animation-worklet/README.txt deleted file mode 100644 index 7f4b48be..0000000 --- a/third_party/blink/web_tests/virtual/threaded/external/wpt/animation-worklet/README.txt +++ /dev/null
@@ -1,2 +0,0 @@ -# This suite runs external/wpt/animation-worklet tests with threaded -# compositing enabled.
diff --git a/tools/metrics/actions/actions.xml b/tools/metrics/actions/actions.xml index 5a25c9dd..b45ab03 100644 --- a/tools/metrics/actions/actions.xml +++ b/tools/metrics/actions/actions.xml
@@ -19870,6 +19870,14 @@ <description>Please enter the description of this user action.</description> </action> +<action name="TabContextMenu_RemoveFromGroup"> + <owner>bsep@google.com</owner> + <owner>tbergquist@google.com</owner> + <description> + User selected Remove from group from the tab context menu. + </description> +</action> + <action name="TabContextMenu_RestoreTab"> <owner>Please list the metric's owners. Add more owner tags as needed.</owner> <description>Please enter the description of this user action.</description>
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index 9ad0783..07c73d30 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -21299,6 +21299,7 @@ <int value="2729" label="V8HTMLMediaElement_CaptureStream_Method"/> <int value="2730" label="QuirkyLineBoxBackgroundSize"/> <int value="2731" label="DirectlyCompositedImage"/> + <int value="2732" label="ForbiddenSyncXhrInPageDismissal"/> </enum> <enum name="FeaturePolicyFeature"> @@ -31663,6 +31664,8 @@ <int value="316182183" label="MediaDocumentDownloadButton:disabled"/> <int value="319683583" label="ContentSuggestionsDebugLog:enabled"/> <int value="323605372" label="ui-disable-compositor-animation-timelines"/> + <int value="324060906" + label="enable-experimental-accessibility-language-detection"/> <int value="324522065" label="app-menu-icon"/> <int value="324631366" label="enable-drive-search-in-app-launcher"/> <int value="326876883" label="HappinessTrackingSurveysForDesktop:disabled"/> @@ -39868,6 +39871,15 @@ </int> </enum> +<enum name="OSXStagingDirectoryStep"> + <int value="0" label="failure"/> + <int value="1" label="NSItemReplacementDirectory"/> + <int value="2" label="Sibling directory"/> + <int value="3" label="NSTemporaryDirectory"/> + <int value="4" label="TMPDIR"/> + <int value="5" label="/tmp"/> +</enum> + <enum name="OtherPossibleUsernamesUsage"> <int value="0" label="Nothing to Autofill"/> <int value="1" label="No other possible usernames"/>
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index 8067dd1..4352103 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -75076,6 +75076,14 @@ </summary> </histogram> +<histogram name="OSX.StagingDirectoryLocation" enum="OSXStagingDirectoryStep" + expires_after="2019-12-31"> + <owner>avi@chromium.org</owner> + <owner>rsesek@chromium.org</owner> + <owner>mark@chromium.org</owner> + <summary>Records first staging directory location that works.</summary> +</histogram> + <histogram name="OSX.SystemHotkeyMap.LoadSuccess" enum="BooleanSuccess" expires_after="2018-08-30"> <owner>erikchen@chromium.org</owner>
diff --git a/ui/accessibility/accessibility_switches.cc b/ui/accessibility/accessibility_switches.cc index 06315d994..4aae94c9 100644 --- a/ui/accessibility/accessibility_switches.cc +++ b/ui/accessibility/accessibility_switches.cc
@@ -21,6 +21,11 @@ const char kEnableExperimentalAccessibilityLabels[] = "enable-experimental-accessibility-labels"; +// Enables language detection on in-page text content which is then exposed to +// accessibility technology such as screen readers. +const char kEnableExperimentalAccessibilityLanguageDetection[] = + "enable-experimental-accessibility-language-detection"; + // Shows setting to enable Switch Access before it has launched. const char kEnableExperimentalAccessibilitySwitchAccess[] = "enable-experimental-accessibility-switch-access"; @@ -30,4 +35,9 @@ ::switches::kEnableExperimentalAccessibilityFeatures); } +bool AreExperimentalAccessibilityLanguageDetectionEnabled() { + return base::CommandLine::ForCurrentProcess()->HasSwitch( + ::switches::kEnableExperimentalAccessibilityLanguageDetection); +} + } // namespace switches
diff --git a/ui/accessibility/accessibility_switches.h b/ui/accessibility/accessibility_switches.h index 31e05d9..c8678de 100644 --- a/ui/accessibility/accessibility_switches.h +++ b/ui/accessibility/accessibility_switches.h
@@ -13,11 +13,14 @@ AX_EXPORT extern const char kEnableExperimentalAccessibilityFeatures[]; AX_EXPORT extern const char kEnableExperimentalAccessibilityAutoclick[]; AX_EXPORT extern const char kEnableExperimentalAccessibilityLabels[]; +AX_EXPORT extern const char kEnableExperimentalAccessibilityLanguageDetection[]; AX_EXPORT extern const char kEnableExperimentalAccessibilitySwitchAccess[]; // Returns true if experimental accessibility features are enabled. AX_EXPORT bool AreExperimentalAccessibilityFeaturesEnabled(); +// Returns true if experimental accessibility language detection is enabled. +AX_EXPORT bool AreExperimentalAccessibilityLanguageDetectionEnabled(); } // namespace switches #endif // UI_ACCESSIBILITY_ACCESSIBILITY_SWITCHES_H_
diff --git a/ui/accessibility/ax_language_info_unittest.cc b/ui/accessibility/ax_language_info_unittest.cc index 464aa59..f2d9b7a4 100644 --- a/ui/accessibility/ax_language_info_unittest.cc +++ b/ui/accessibility/ax_language_info_unittest.cc
@@ -3,6 +3,8 @@ // found in the LICENSE file. #include "ui/accessibility/ax_language_info.h" +#include "base/command_line.h" +#include "ui/accessibility/accessibility_switches.h" #include "ui/accessibility/ax_node.h" #include "ui/accessibility/ax_tree.h" @@ -15,6 +17,18 @@ namespace ui { +TEST(AXLanguageInfoTest, TestSwitch) { + // TODO(crbug/889370): Remove this test once this feature is stable + EXPECT_FALSE( + ::switches::AreExperimentalAccessibilityLanguageDetectionEnabled()); + + base::CommandLine::ForCurrentProcess()->AppendSwitch( + ::switches::kEnableExperimentalAccessibilityLanguageDetection); + + EXPECT_TRUE( + ::switches::AreExperimentalAccessibilityLanguageDetectionEnabled()); +} + // Tests that AXNode::GetLanguage() terminates when there is no lang attribute. TEST(AXLanguageInfoTest, TestGetLanguageNoLangAttr) { // build tree including parenting, this is to exercise the code paths within
diff --git a/ui/android/java/src/org/chromium/ui/OverscrollRefreshHandler.java b/ui/android/java/src/org/chromium/ui/OverscrollRefreshHandler.java index 85b45d11..333d6cd 100644 --- a/ui/android/java/src/org/chromium/ui/OverscrollRefreshHandler.java +++ b/ui/android/java/src/org/chromium/ui/OverscrollRefreshHandler.java
@@ -12,17 +12,22 @@ public interface OverscrollRefreshHandler { /** * Signals the start of an overscrolling pull. + * @param xDelta The change in horizontal pull distance (positive if pulling down, negative if + * up). + * @param yDelta The change in vertical pull distance. * @return Whether the handler will consume the overscroll sequence. */ @CalledByNative - public boolean start(); + public boolean start(float xDelta, float yDelta); /** * Signals a pull update. - * @param delta The change in pull distance (positive if pulling down, negative if up). + * @param xDelta The change in horizontal pull distance (positive if pulling down, negative if + * up). + * @param yDelta The change in vertical pull distance. */ @CalledByNative - public void pull(float delta); + public void pull(float xDelta, float yDelta); /** * Signals the release of the pull.
diff --git a/ui/android/overscroll_refresh.cc b/ui/android/overscroll_refresh.cc index 60b54aa..2b6077dc 100644 --- a/ui/android/overscroll_refresh.cc +++ b/ui/android/overscroll_refresh.cc
@@ -18,6 +18,7 @@ OverscrollRefresh::OverscrollRefresh(OverscrollRefreshHandler* handler) : scrolled_to_top_(true), + top_at_scroll_start_(true), overflow_y_hidden_(false), scroll_consumption_state_(DISABLED), handler_(handler) { @@ -35,13 +36,15 @@ void OverscrollRefresh::Reset() { scroll_consumption_state_ = DISABLED; + cumulative_scroll_.set_x(0); + cumulative_scroll_.set_y(0); handler_->PullReset(); } void OverscrollRefresh::OnScrollBegin() { + top_at_scroll_start_ = scrolled_to_top_; ReleaseWithoutActivation(); - if (scrolled_to_top_ && !overflow_y_hidden_) - scroll_consumption_state_ = AWAITING_SCROLL_UPDATE_ACK; + scroll_consumption_state_ = AWAITING_SCROLL_UPDATE_ACK; } void OverscrollRefresh::OnScrollEnd(const gfx::Vector2dF& scroll_velocity) { @@ -53,7 +56,10 @@ if (scroll_consumption_state_ != AWAITING_SCROLL_UPDATE_ACK) return; - scroll_consumption_state_ = handler_->PullStart() ? ENABLED : DISABLED; + scroll_consumption_state_ = + handler_->PullStart(cumulative_scroll_.x(), cumulative_scroll_.y()) + ? ENABLED + : DISABLED; } bool OverscrollRefresh::WillHandleScrollUpdate( @@ -63,13 +69,21 @@ return false; case AWAITING_SCROLL_UPDATE_ACK: - // If the initial scroll motion is downward, never allow activation. - if (scroll_delta.y() <= 0) - scroll_consumption_state_ = DISABLED; + // Check applies for the pull-to-refresh condition only. + if (std::abs(scroll_delta.y()) > std::abs(scroll_delta.x())) { + // If the initial scroll motion is downward, or we're in other cases + // where activation shouldn't have happened, stop here. + if (scroll_delta.y() <= 0 || !top_at_scroll_start_ || + overflow_y_hidden_) { + scroll_consumption_state_ = DISABLED; + return false; + } + } + cumulative_scroll_.Add(scroll_delta); return false; case ENABLED: - handler_->PullUpdate(scroll_delta.y()); + handler_->PullUpdate(scroll_delta.x(), scroll_delta.y()); return true; } @@ -101,6 +115,8 @@ if (scroll_consumption_state_ == ENABLED) handler_->PullRelease(allow_refresh); scroll_consumption_state_ = DISABLED; + cumulative_scroll_.set_x(0); + cumulative_scroll_.set_y(0); } } // namespace ui
diff --git a/ui/android/overscroll_refresh.h b/ui/android/overscroll_refresh.h index b9067f1..25bc168 100644 --- a/ui/android/overscroll_refresh.h +++ b/ui/android/overscroll_refresh.h
@@ -77,6 +77,9 @@ void Release(bool allow_refresh); bool scrolled_to_top_; + // True if the content y offset was zero before scroll began. Overscroll + // should not be triggered for the scroll that started from non-zero offset. + bool top_at_scroll_start_; bool overflow_y_hidden_; enum ScrollConsumptionState { @@ -85,6 +88,7 @@ ENABLED, } scroll_consumption_state_; + gfx::Vector2dF cumulative_scroll_; OverscrollRefreshHandler* const handler_; DISALLOW_COPY_AND_ASSIGN(OverscrollRefresh);
diff --git a/ui/android/overscroll_refresh_handler.cc b/ui/android/overscroll_refresh_handler.cc index 49b2f71..63e9873 100644 --- a/ui/android/overscroll_refresh_handler.cc +++ b/ui/android/overscroll_refresh_handler.cc
@@ -19,14 +19,14 @@ OverscrollRefreshHandler::~OverscrollRefreshHandler() {} -bool OverscrollRefreshHandler::PullStart() { - return Java_OverscrollRefreshHandler_start(AttachCurrentThread(), - j_overscroll_refresh_handler_); +bool OverscrollRefreshHandler::PullStart(float x_delta, float y_delta) { + return Java_OverscrollRefreshHandler_start( + AttachCurrentThread(), j_overscroll_refresh_handler_, x_delta, y_delta); } -void OverscrollRefreshHandler::PullUpdate(float delta) { - Java_OverscrollRefreshHandler_pull(AttachCurrentThread(), - j_overscroll_refresh_handler_, delta); +void OverscrollRefreshHandler::PullUpdate(float x_delta, float y_delta) { + Java_OverscrollRefreshHandler_pull( + AttachCurrentThread(), j_overscroll_refresh_handler_, x_delta, y_delta); } void OverscrollRefreshHandler::PullRelease(bool allow_refresh) {
diff --git a/ui/android/overscroll_refresh_handler.h b/ui/android/overscroll_refresh_handler.h index 60184bf..7b4b7fa 100644 --- a/ui/android/overscroll_refresh_handler.h +++ b/ui/android/overscroll_refresh_handler.h
@@ -23,10 +23,10 @@ // Signals the start of an overscrolling pull. Returns whether the handler // will consume the overscroll gesture, in which case it will receive the // remaining pull updates. - virtual bool PullStart(); + virtual bool PullStart(float x_delta, float y_delta); - // Signals a pull update, where |delta| is in device pixels. - virtual void PullUpdate(float delta); + // Signals a pull update, where |x_delta| and |y_delta| are in device pixels. + virtual void PullUpdate(float x_delta, float y_delta); // Signals the release of the pull, and whether the release is allowed to // trigger the refresh action.
diff --git a/ui/android/overscroll_refresh_unittest.cc b/ui/android/overscroll_refresh_unittest.cc index f31b85f4..bcd1e657 100644 --- a/ui/android/overscroll_refresh_unittest.cc +++ b/ui/android/overscroll_refresh_unittest.cc
@@ -16,12 +16,12 @@ OverscrollRefreshTest() : OverscrollRefreshHandler(nullptr) {} // OverscrollRefreshHandler implementation. - bool PullStart() override { + bool PullStart(float, float) override { started_ = true; return true; } - void PullUpdate(float delta) override { delta_ += delta; } + void PullUpdate(float x_delta, float y_delta) override { delta_ += y_delta; } void PullRelease(bool allow_refresh) override { released_ = true;
diff --git a/ui/base/clipboard/scoped_clipboard_writer.cc b/ui/base/clipboard/scoped_clipboard_writer.cc index 12680a6..3932401f 100644 --- a/ui/base/clipboard/scoped_clipboard_writer.cc +++ b/ui/base/clipboard/scoped_clipboard_writer.cc
@@ -88,9 +88,11 @@ } void ScopedClipboardWriter::WriteImage(const SkBitmap& bitmap) { - if (bitmap.drawsNothing()) { + if (bitmap.drawsNothing()) return; - } + // TODO(crbug.com/918717): Remove CHECK if no crashes occur on it in canary. + CHECK(bitmap.getPixels()); + bitmap_ = bitmap; // TODO(dcheng): This is slightly less horrible than what we used to do, but // only very slightly less.
diff --git a/ui/base/ime/BUILD.gn b/ui/base/ime/BUILD.gn index 6b8e71f..d686d1d 100644 --- a/ui/base/ime/BUILD.gn +++ b/ui/base/ime/BUILD.gn
@@ -143,7 +143,6 @@ "//net", "//third_party/icu", "//ui/base", - "//ui/base/ime/chromeos/public/interfaces", "//ui/display", "//ui/events", "//ui/gfx", @@ -189,6 +188,7 @@ deps += [ "//chromeos", "//services/ws/public/cpp/input_devices", + "//ui/base/ime/chromeos/public/interfaces", "//ui/chromeos/strings", "//ui/events:dom_keycode_converter", ]
diff --git a/ui/base/ime/chromeos/public/interfaces/BUILD.gn b/ui/base/ime/chromeos/public/interfaces/BUILD.gn index 625cdd4c..3f07e550 100644 --- a/ui/base/ime/chromeos/public/interfaces/BUILD.gn +++ b/ui/base/ime/chromeos/public/interfaces/BUILD.gn
@@ -4,6 +4,8 @@ import("//mojo/public/tools/bindings/mojom.gni") +assert(is_chromeos) + mojom("interfaces") { sources = [ "ime_keyset.mojom",
diff --git a/ui/webui/resources/cr_elements/cr_dialog/cr_dialog.html b/ui/webui/resources/cr_elements/cr_dialog/cr_dialog.html index d9dcfac..7f5b1360 100644 --- a/ui/webui/resources/cr_elements/cr_dialog/cr_dialog.html +++ b/ui/webui/resources/cr_elements/cr_dialog/cr_dialog.html
@@ -24,6 +24,14 @@ @apply --cr-dialog-native; } + :host-context([dark]) dialog { + background-color: var(--google-grey-refresh-900); + /* Note: the colors in linear-gradient() are intentionally the same to + * add a 4% white layer on top of the fully opaque background-color. */ + background-image: linear-gradient(rgba(255, 255, 255, .04), + rgba(255, 255, 255, .04)); + } + dialog[open] #content-wrapper { /* Keep max-height within viewport, and flex content accordingly. */ display: flex;
diff --git a/ui/webui/resources/cr_elements/cr_toolbar/cr_toolbar_selection_overlay.html b/ui/webui/resources/cr_elements/cr_toolbar/cr_toolbar_selection_overlay.html index 53dfb4a..acd1f036 100644 --- a/ui/webui/resources/cr_elements/cr_toolbar/cr_toolbar_selection_overlay.html +++ b/ui/webui/resources/cr_elements/cr_toolbar/cr_toolbar_selection_overlay.html
@@ -3,6 +3,7 @@ <link rel="import" href="../cr_icons_css.html"> <link rel="import" href="../icons.html"> <link rel="import" href="../paper_button_style_css.html"> +<link rel="import" href="../shared_vars_css.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html"> @@ -27,6 +28,14 @@ visibility: hidden; } + :host-context([dark]) { + background: var(--google-grey-refresh-900); + background-image: linear-gradient(rgba(255, 255, 255, .04), + rgba(255, 255, 255, .04)); + border-bottom-color: var(--google-grey-refresh-700); + color: var(--cr-secondary-text-color); + } + :host([show]) { opacity: 1; pointer-events: initial;
diff --git a/webrunner/common/webrunner_export.h b/webrunner/common/webrunner_export.h deleted file mode 100644 index aaa3242..0000000 --- a/webrunner/common/webrunner_export.h +++ /dev/null
@@ -1,20 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef WEBRUNNER_COMMON_WEBRUNNER_EXPORT_H_ -#define WEBRUNNER_COMMON_WEBRUNNER_EXPORT_H_ - -#if defined(COMPONENT_BUILD) - -#if defined(WEBRUNNER_IMPLEMENTATION) -#define WEBRUNNER_EXPORT __attribute__((visibility("default"))) -#else -#define WEBRUNNER_EXPORT -#endif - -#else // defined(COMPONENT_BUILD) -#define WEBRUNNER_EXPORT -#endif - -#endif // WEBRUNNER_COMMON_WEBRUNNER_EXPORT_H_