diff --git a/DEPS b/DEPS index 4852a29..ab8992f 100644 --- a/DEPS +++ b/DEPS
@@ -137,7 +137,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. - 'v8_revision': '382308145fae4cf8c95e95355c93bb0028b5d63e', + 'v8_revision': 'a74147972b6713fbd1d99ebd789dfef29067281c', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling swarming_client # and whatever else without interference from each other. @@ -145,15 +145,15 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ANGLE # and whatever else without interference from each other. - 'angle_revision': '064b1625059a66f15240412e084f2948b2d24e1b', + 'angle_revision': 'cd078c3392560dd9712a4d4b91a05c1111b26f66', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling SwiftShader # and whatever else without interference from each other. - 'swiftshader_revision': '3e6f60b3096f71903f88cc53d1b7b65bb60d1d28', + 'swiftshader_revision': '3e511440e7747f25d84e89e32eb30b1060076eff', # 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': '00714a05fb5d4766e9f460d9764191eda9706db9', + 'pdfium_revision': '706619bb28a48276e7ea870995df6a80acf3860d', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling BoringSSL # and whatever else without interference from each other. @@ -196,7 +196,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling catapult # and whatever else without interference from each other. - 'catapult_revision': '2cf3aa8e54dbe385c6d1ba4e2b885801d1031bba', + 'catapult_revision': '09537e93fddd868ee04a8e2a8a665a12c21de3fa', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libFuzzer # and whatever else without interference from each other. @@ -264,7 +264,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. - 'shaderc_revision': '5cf297dfa77c0cd76cfdb4bf4c290c0408d0e958', + 'shaderc_revision': 'dce7a4bc30c035c8c575488676ff8071977cd5ce', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. @@ -272,7 +272,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. - 'quiche_revision': 'ff86db3f4a3d59250eeafbb9787fb52b70e6ac31', + 'quiche_revision': '7eef071bd3d6738a167533695485c559310435bf', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ios_webkit # and whatever else without interference from each other. @@ -802,7 +802,7 @@ # Build tools for Chrome OS. Note: This depends on third_party/pyelftools. 'src/third_party/chromite': { - 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '4b03532de07b8ae91b0c8a27e2ff15246981bf3d', + 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '694e64da2e571052b7f34ae799e815a8385b0049', 'condition': 'checkout_linux', }, @@ -827,7 +827,7 @@ }, 'src/third_party/depot_tools': - Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '370d193c8e46d8ff67d9581afb639c095cc7ded4', + Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '1b52d87ab5367886500c91a92cf310d5aa76e284', 'src/third_party/devtools-node-modules': Var('chromium_git') + '/external/github.com/ChromeDevTools/devtools-node-modules' + '@' + Var('devtools_node_modules_revision'), @@ -1177,7 +1177,7 @@ }, 'src/third_party/perfetto': - Var('android_git') + '/platform/external/perfetto.git' + '@' + '77f9a12a3f08f3228a4333371e919ad9fd88f213', + Var('android_git') + '/platform/external/perfetto.git' + '@' + '4585cc846e0fd319415af841cef9baa3b1846da3', 'src/third_party/perl': { 'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + 'ac0d98b5cee6c024b0cffeb4f8f45b6fc5ccdb78', @@ -1389,7 +1389,7 @@ Var('chromium_git') + '/v8/v8.git' + '@' + Var('v8_revision'), 'src-internal': { - 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@e932f4a7787d061c8b94d84b14d631314ddaa7f7', + 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@f86c9af41fc797f83f027f80a3d768113590b57e', 'condition': 'checkout_src_internal', },
diff --git a/android_webview/java/src/org/chromium/android_webview/AwBrowserProcess.java b/android_webview/java/src/org/chromium/android_webview/AwBrowserProcess.java index 34a29e85..73732a80 100644 --- a/android_webview/java/src/org/chromium/android_webview/AwBrowserProcess.java +++ b/android_webview/java/src/org/chromium/android_webview/AwBrowserProcess.java
@@ -62,12 +62,6 @@ private static FileLock sExclusiveFileLock; private static String sWebViewPackageName; - // TODO(ksolt): This is a temporary solution to avoid lifetime check errors. - // Will be fixed after we decide how to handle the destruction of static TaskRunners. - static { - sSequencedTaskRunner.disableLifetimeCheck(); - } - /** * Loads the native library, and performs basic static construction of objects needed * to run webview in this process. Does not create threads; safe to call from zygote.
diff --git a/ash/BUILD.gn b/ash/BUILD.gn index 8633288..6b64b5a 100644 --- a/ash/BUILD.gn +++ b/ash/BUILD.gn
@@ -337,8 +337,6 @@ "ime/ime_controller.h", "ime/ime_engine_factory_registry.cc", "ime/ime_engine_factory_registry.h", - "ime/ime_focus_handler.cc", - "ime/ime_focus_handler.h", "ime/ime_mode_indicator_view.cc", "ime/ime_mode_indicator_view.h", "ime/ime_switch_type.h", @@ -1106,8 +1104,6 @@ "wm/mru_window_tracker.cc", "wm/native_cursor_manager_ash.cc", "wm/native_cursor_manager_ash.h", - "wm/non_client_frame_controller.cc", - "wm/non_client_frame_controller.h", "wm/overlay_event_filter.cc", "wm/overlay_event_filter.h", "wm/overlay_layout_manager.cc", @@ -1150,8 +1146,6 @@ "wm/pip/pip_positioner.h", "wm/pip/pip_window_resizer.cc", "wm/pip/pip_window_resizer.h", - "wm/property_util.cc", - "wm/property_util.h", "wm/resize_shadow.cc", "wm/resize_shadow.h", "wm/resize_shadow_controller.cc", @@ -1209,8 +1203,6 @@ "wm/tablet_mode/tablet_mode_window_manager.h", "wm/tablet_mode/tablet_mode_window_state.cc", "wm/tablet_mode/tablet_mode_window_state.h", - "wm/top_level_window_factory.cc", - "wm/top_level_window_factory.h", "wm/toplevel_window_event_handler.cc", "wm/toplevel_window_event_handler.h", "wm/video_detector.cc", @@ -1369,6 +1361,7 @@ "//components/prefs", "//components/quirks", "//components/session_manager:base", + "//components/startup_metric_utils/browser:lib", "//components/strings", "//components/sync", "//components/user_manager",
diff --git a/ash/DEPS b/ash/DEPS index deae74a..bae9dde 100644 --- a/ash/DEPS +++ b/ash/DEPS
@@ -13,6 +13,7 @@ "+components/prefs", "+components/quirks", "+components/session_manager", + "+components/startup_metric_utils", "+components/strings", "+components/sync", "+components/ui_devtools",
diff --git a/ash/accelerators/accelerator_commands.cc b/ash/accelerators/accelerator_commands.cc index ea039f0..a6466a1 100644 --- a/ash/accelerators/accelerator_commands.cc +++ b/ash/accelerators/accelerator_commands.cc
@@ -81,11 +81,11 @@ } bool CanUnpinWindow() { - // WindowStateType::TRUSTED_PINNED does not allow the user to press a key to + // WindowStateType::kTrustedPinned does not allow the user to press a key to // exit pinned mode. wm::WindowState* window_state = wm::GetActiveWindowState(); return window_state && - window_state->GetStateType() == mojom::WindowStateType::PINNED; + window_state->GetStateType() == WindowStateType::kPinned; } void UnpinWindow() {
diff --git a/ash/app_list/app_list_controller_impl_unittest.cc b/ash/app_list/app_list_controller_impl_unittest.cc index ed15ca0..cbf28b301 100644 --- a/ash/app_list/app_list_controller_impl_unittest.cc +++ b/ash/app_list/app_list_controller_impl_unittest.cc
@@ -121,7 +121,7 @@ ->home_screen_controller() ->home_launcher_gesture_handler() ->ShowHomeLauncher(display::Screen::GetScreen()->GetPrimaryDisplay()); - EXPECT_EQ(mojom::WindowStateType::MINIMIZED, + EXPECT_EQ(WindowStateType::kMinimized, wm::GetWindowState(w1.get())->GetStateType()); EXPECT_TRUE(GetExpandArrowViewVisibility());
diff --git a/ash/app_list/views/search_result_answer_card_view.cc b/ash/app_list/views/search_result_answer_card_view.cc index 9aa9ece..397f5f2 100644 --- a/ash/app_list/views/search_result_answer_card_view.cc +++ b/ash/app_list/views/search_result_answer_card_view.cc
@@ -28,7 +28,6 @@ #include "ui/accessibility/ax_node.h" #include "ui/accessibility/ax_node_data.h" #include "ui/aura/window.h" -#include "ui/base/ui_base_features.h" #include "ui/gfx/canvas.h" #include "ui/views/background.h" #include "ui/views/layout/fill_layout.h" @@ -122,8 +121,6 @@ params->background_color = SK_ColorTRANSPARENT; contents_ = std::make_unique<content::NavigableContents>( contents_factory_.get(), std::move(params)); - if (features::IsUsingWindowService()) - contents_->ForceUseWindowService(); contents_->AddObserver(this); } @@ -370,6 +367,12 @@ return num_results() <= 0 ? nullptr : search_answer_container_view_; } +SearchResultBaseView* SearchResultAnswerCardView::GetResultViewAt( + size_t index) { + DCHECK_EQ(index, 0u); + return search_answer_container_view_; +} + views::View* SearchResultAnswerCardView::GetAnswerCardResultViewForTest() const { return search_answer_container_view_;
diff --git a/ash/app_list/views/search_result_answer_card_view.h b/ash/app_list/views/search_result_answer_card_view.h index 16e8c147..f56e92a 100644 --- a/ash/app_list/views/search_result_answer_card_view.h +++ b/ash/app_list/views/search_result_answer_card_view.h
@@ -30,6 +30,7 @@ int DoUpdate() override; bool OnKeyPressed(const ui::KeyEvent& event) override; SearchResultBaseView* GetFirstResultView() override; + SearchResultBaseView* GetResultViewAt(size_t index) override; views::View* GetAnswerCardResultViewForTest() const;
diff --git a/ash/app_list/views/search_result_base_view.cc b/ash/app_list/views/search_result_base_view.cc index 6ac992d..8ec35d0b 100644 --- a/ash/app_list/views/search_result_base_view.cc +++ b/ash/app_list/views/search_result_base_view.cc
@@ -3,7 +3,9 @@ // found in the LICENSE file. #include "ash/app_list/views/search_result_base_view.h" + #include "ash/app_list/model/search/search_result.h" +#include "base/strings/utf_string_conversions.h" namespace app_list { @@ -40,6 +42,22 @@ SetResult(nullptr); } +base::string16 SearchResultBaseView::ComputeAccessibleName() const { + if (!result()) + return base::string16(); + + base::string16 accessible_name = result()->title(); + if (!result()->title().empty() && !result()->details().empty()) + accessible_name += base::ASCIIToUTF16(", "); + accessible_name += result()->details(); + + return accessible_name; +} + +void SearchResultBaseView::UpdateAccessibleName() { + SetAccessibleName(ComputeAccessibleName()); +} + void SearchResultBaseView::ClearResult() { if (result_) result_->RemoveObserver(this);
diff --git a/ash/app_list/views/search_result_base_view.h b/ash/app_list/views/search_result_base_view.h index 48aab70..0b8e689 100644 --- a/ash/app_list/views/search_result_base_view.h +++ b/ash/app_list/views/search_result_base_view.h
@@ -7,6 +7,7 @@ #include "ash/app_list/app_list_export.h" #include "ash/app_list/model/search/search_result_observer.h" +#include "base/optional.h" #include "ui/views/controls/button/button.h" namespace app_list { @@ -35,20 +36,32 @@ // Overridden from SearchResultObserver: void OnResultDestroying() override; + // Computes the button's spoken feedback name. + virtual base::string16 ComputeAccessibleName() const; + // Clears the result without calling |OnResultChanged| or |OnResultChanging| void ClearResult(); bool background_highlighted() const { return background_highlighted_; } + int index_in_container() const { return index_in_container_.value(); } + + void set_index_in_container(size_t index) { index_in_container_ = index; } + // views::Button: bool SkipDefaultKeyEventProcessing(const ui::KeyEvent& event) override; protected: ~SearchResultBaseView() override; + void UpdateAccessibleName(); + private: bool background_highlighted_ = false; + // The index of this view within a |SearchResultContainerView| that holds it. + base::Optional<int> index_in_container_; + SearchResult* result_ = nullptr; // Owned by SearchModel::SearchResults. DISALLOW_COPY_AND_ASSIGN(SearchResultBaseView);
diff --git a/ash/app_list/views/search_result_container_view.h b/ash/app_list/views/search_result_container_view.h index 9e9dfeea..1d86dc0 100644 --- a/ash/app_list/views/search_result_container_view.h +++ b/ash/app_list/views/search_result_container_view.h
@@ -50,6 +50,15 @@ int num_results() const { return num_results_; } + virtual SearchResultBaseView* GetResultViewAt(size_t index) = 0; + + bool horizontally_traversable() const { return horizontally_traversable_; } + + // Allows a container to define its traversal behavior + void set_horizontally_traversable(bool horizontally_traversable) { + horizontally_traversable_ = horizontally_traversable; + } + void set_container_score(double score) { container_score_ = score; } double container_score() const { return container_score_; } @@ -108,6 +117,9 @@ int num_results_ = 0; + // If true, left/right key events will traverse this container + bool horizontally_traversable_ = false; + double container_score_; SearchModel::SearchResults* results_ = nullptr; // Owned by SearchModel.
diff --git a/ash/app_list/views/search_result_list_view.cc b/ash/app_list/views/search_result_list_view.cc index ef3fbd9..74d663b 100644 --- a/ash/app_list/views/search_result_list_view.cc +++ b/ash/app_list/views/search_result_list_view.cc
@@ -13,7 +13,6 @@ #include "ash/app_list/model/search/search_result.h" #include "ash/app_list/views/app_list_main_view.h" #include "ash/app_list/views/search_box_view.h" -#include "ash/app_list/views/search_result_view.h" #include "ash/public/cpp/app_list/app_list_config.h" #include "ash/public/cpp/app_list/app_list_features.h" #include "ash/public/cpp/app_list/vector_icons/vector_icons.h" @@ -125,7 +124,7 @@ for (int i = 0; i < kMaxResults; ++i) { search_result_views_.emplace_back( new SearchResultView(this, view_delegate_)); - search_result_views_.back()->set_index_in_search_result_list_view(i); + search_result_views_.back()->set_index_in_container(i); results_container_->AddChildView(search_result_views_.back()); AddObservedResultView(search_result_views_.back()); } @@ -134,11 +133,6 @@ SearchResultListView::~SearchResultListView() = default; -SearchResultView* SearchResultListView::GetResultViewAt(size_t index) { - DCHECK(index >= 0 && index < search_result_views_.size()); - return search_result_views_[index]; -} - void SearchResultListView::ListItemsRemoved(size_t start, size_t count) { size_t last = std::min(start + count, search_result_views_.size()); for (size_t i = start; i < last; ++i) @@ -147,6 +141,11 @@ SearchResultContainerView::ListItemsRemoved(start, count); } +SearchResultView* SearchResultListView::GetResultViewAt(size_t index) { + DCHECK(index >= 0 && index < search_result_views_.size()); + return search_result_views_[index]; +} + void SearchResultListView::NotifyFirstResultYIndex(int y_index) { for (size_t i = 0; i < static_cast<size_t>(num_results()); ++i) GetResultViewAt(i)->result()->set_distance_from_origin(i + y_index); @@ -175,7 +174,6 @@ for (size_t i = 0; i < results_container_->children().size(); ++i) { SearchResultView* result_view = GetResultViewAt(i); - result_view->set_is_last_result(i == display_size - 1); if (i < display_results.size()) { if (assistant_item_icons[i]) { result_view->SetDisplayIcon(gfx::CreateVectorIcon( @@ -225,8 +223,7 @@ RecordSearchResultOpenSource(view->result(), view_delegate_->GetModel(), view_delegate_->GetSearchModel()); view_delegate_->LogResultLaunchHistogram( - SearchResultLaunchLocation::kResultList, - view->get_index_in_search_result_list_view()); + SearchResultLaunchLocation::kResultList, view->index_in_container()); view_delegate_->OpenSearchResult( view->result()->id(), event_flags, ash::mojom::AppListLaunchedFrom::kLaunchedFromSearchBox, @@ -262,7 +259,7 @@ bool arrow_up) { int view_index = -1; for (int i = 0; i < num_results(); ++i) { - if (view == search_result_views_[i]) { + if (view == GetResultViewAt(i)) { view_index = i; break; } @@ -277,7 +274,7 @@ if (arrow_up) { // VKEY_UP if (view_index > 0) { // Move to the previous result if the current one is not the first result. - search_result_views_[view_index - 1]->RequestFocus(); + GetResultViewAt(view_index - 1)->RequestFocus(); return true; } } else { // VKEY_DOWN @@ -286,7 +283,7 @@ if (view_index == num_results() - 1) main_view_->search_box_view()->search_box()->RequestFocus(); else - search_result_views_[view_index + 1]->RequestFocus(); + GetResultViewAt(view_index + 1)->RequestFocus(); return true; }
diff --git a/ash/app_list/views/search_result_list_view.h b/ash/app_list/views/search_result_list_view.h index e68b046e..783bafa 100644 --- a/ash/app_list/views/search_result_list_view.h +++ b/ash/app_list/views/search_result_list_view.h
@@ -9,6 +9,7 @@ #include <vector> #include "ash/app_list/views/search_result_container_view.h" +#include "ash/app_list/views/search_result_view.h" #include "base/macros.h" #include "base/memory/weak_ptr.h" #include "ui/views/view.h" @@ -20,7 +21,6 @@ class AppListMainView; class AppListViewDelegate; -class SearchResultView; // SearchResultListView displays SearchResultList with a list of // SearchResultView. @@ -30,9 +30,6 @@ AppListViewDelegate* view_delegate); ~SearchResultListView() override; - // Helper function to get SearchResultView at given |index|. - SearchResultView* GetResultViewAt(size_t index); - void SearchResultActivated(SearchResultView* view, int event_flags); void SearchResultActionActivated(SearchResultView* view, @@ -52,6 +49,7 @@ void ListItemsRemoved(size_t start, size_t count) override; // Overridden from SearchResultContainerView: + SearchResultView* GetResultViewAt(size_t index) override; void NotifyFirstResultYIndex(int y_index) override; int GetYSize() override; SearchResultBaseView* GetFirstResultView() override;
diff --git a/ash/app_list/views/search_result_list_view_unittest.cc b/ash/app_list/views/search_result_list_view_unittest.cc index 614aced..89f12ec 100644 --- a/ash/app_list/views/search_result_list_view_unittest.cc +++ b/ash/app_list/views/search_result_list_view_unittest.cc
@@ -18,7 +18,6 @@ #include "base/macros.h" #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" -#include "ui/views/controls/progress_bar.h" #include "ui/views/test/views_test_base.h" namespace app_list { @@ -97,10 +96,6 @@ } } - views::ProgressBar* GetProgressBarAt(size_t index) const { - return GetResultViewAt(index)->progress_bar_; - } - private: AppListTestViewDelegate view_delegate_; std::unique_ptr<SearchResultListView> view_; @@ -146,19 +141,5 @@ ExpectConsistent(); } -// Regression test for http://crbug.com/402859 to ensure ProgressBar is -// initialized properly in SearchResultListView::SetResult(). -TEST_F(SearchResultListViewTest, ProgressBar) { - SetUpSearchResults(); - - GetResults()->GetItemAt(0)->SetIsInstalling(true); - EXPECT_EQ(0.0f, GetProgressBarAt(0)->current_value()); - GetResults()->GetItemAt(0)->SetPercentDownloaded(10); - - DeleteResultAt(0); - RunPendingMessages(); - EXPECT_EQ(0.0f, GetProgressBarAt(0)->current_value()); -} - } // namespace test } // namespace app_list
diff --git a/ash/app_list/views/search_result_suggestion_chip_view.cc b/ash/app_list/views/search_result_suggestion_chip_view.cc index 23f81332..0edcd55 100644 --- a/ash/app_list/views/search_result_suggestion_chip_view.cc +++ b/ash/app_list/views/search_result_suggestion_chip_view.cc
@@ -44,10 +44,10 @@ constexpr int kPreferredHeightDip = 32; // Records an app being launched. -void LogAppLaunch(int index_in_suggestion_chip_container) { - DCHECK_GE(index_in_suggestion_chip_container, 0); +void LogAppLaunch(int index_in_container) { + DCHECK_GE(index_in_container, 0); base::UmaHistogramSparse("Apps.AppListSuggestedChipLaunched", - index_in_suggestion_chip_container); + index_in_container); base::RecordAction(base::UserMetricsAction("AppList_OpenSuggestedApp")); } @@ -95,11 +95,6 @@ UpdateSuggestionChipView(); } -void SearchResultSuggestionChipView::SetIndexInSuggestionChipContainer( - size_t index) { - index_in_suggestion_chip_container_ = index; -} - void SearchResultSuggestionChipView::OnMetadataChanged() { UpdateSuggestionChipView(); } @@ -107,14 +102,13 @@ void SearchResultSuggestionChipView::ButtonPressed(views::Button* sender, const ui::Event& event) { DCHECK(result()); - LogAppLaunch(index_in_suggestion_chip_container_); + LogAppLaunch(index_in_container()); RecordSearchResultOpenSource(result(), view_delegate_->GetModel(), view_delegate_->GetSearchModel()); view_delegate_->OpenSearchResult( result()->id(), event.flags(), ash::mojom::AppListLaunchedFrom::kLaunchedFromSuggestionChip, - ash::mojom::AppListLaunchType::kAppSearchResult, - index_in_suggestion_chip_container_); + ash::mojom::AppListLaunchType::kAppSearchResult, index_in_container()); } const char* SearchResultSuggestionChipView::GetClassName() const {
diff --git a/ash/app_list/views/search_result_suggestion_chip_view.h b/ash/app_list/views/search_result_suggestion_chip_view.h index afd4f5bd..105fbec 100644 --- a/ash/app_list/views/search_result_suggestion_chip_view.h +++ b/ash/app_list/views/search_result_suggestion_chip_view.h
@@ -35,7 +35,6 @@ void SetBackgroundBlurEnabled(bool enabled); void OnResultChanged() override; - void SetIndexInSuggestionChipContainer(size_t index); // SearchResultObserver: void OnMetadataChanged() override; @@ -84,9 +83,6 @@ views::BoxLayout* layout_manager_; // Owned by view hierarchy. - // The index of this view in the suggestion_chip_container, only used for uma - // logging. - int index_in_suggestion_chip_container_ = -1; base::WeakPtrFactory<SearchResultSuggestionChipView> weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(SearchResultSuggestionChipView);
diff --git a/ash/app_list/views/search_result_tile_item_list_view.cc b/ash/app_list/views/search_result_tile_item_list_view.cc index 69af32e1..063c2e0 100644 --- a/ash/app_list/views/search_result_tile_item_list_view.cc +++ b/ash/app_list/views/search_result_tile_item_list_view.cc
@@ -15,7 +15,6 @@ #include "ash/app_list/app_list_view_delegate.h" #include "ash/app_list/model/search/search_result.h" #include "ash/app_list/views/search_result_page_view.h" -#include "ash/app_list/views/search_result_tile_item_view.h" #include "ash/public/cpp/app_list/app_list_config.h" #include "ash/public/cpp/app_list/app_list_features.h" #include "ash/public/cpp/app_list/internal_app_id_constants.h" @@ -90,20 +89,29 @@ SearchResultTileItemView* tile_item = new SearchResultTileItemView( view_delegate, nullptr /* pagination model */, false /* show_in_apps_page */); - tile_item->SetIndexInItemListView(i); + tile_item->set_index_in_container(i); tile_item->SetParentBackgroundColor( AppListConfig::instance().card_background_color()); tile_views_.push_back(tile_item); AddChildView(tile_item); AddObservedResultView(tile_item); } + + // Tile items are shown horizontally. + set_horizontally_traversable(true); } SearchResultTileItemListView::~SearchResultTileItemListView() = default; +SearchResultTileItemView* SearchResultTileItemListView::GetResultViewAt( + size_t index) { + DCHECK(index >= 0 && index < tile_views_.size()); + return tile_views_[index]; +} + void SearchResultTileItemListView::NotifyFirstResultYIndex(int y_index) { for (size_t i = 0; i < static_cast<size_t>(num_results()); ++i) - tile_views_[i]->result()->set_distance_from_origin(i + y_index); + GetResultViewAt(i)->result()->set_distance_from_origin(i + y_index); } int SearchResultTileItemListView::GetYSize() { @@ -135,13 +143,13 @@ separator_views_[i]->SetVisible(false); } - tile_views_[i]->SetResult(nullptr); + GetResultViewAt(i)->SetResult(nullptr); continue; } SearchResult* item = display_results[i]; - tile_views_[i]->SetResult(item); + GetResultViewAt(i)->SetResult(item); result_id_added.insert(item->id()); is_result_an_installable_app = IsResultAnInstallableApp(item);
diff --git a/ash/app_list/views/search_result_tile_item_list_view.h b/ash/app_list/views/search_result_tile_item_list_view.h index 27faa06..7e4815d 100644 --- a/ash/app_list/views/search_result_tile_item_list_view.h +++ b/ash/app_list/views/search_result_tile_item_list_view.h
@@ -8,6 +8,7 @@ #include <vector> #include "ash/app_list/views/search_result_container_view.h" +#include "ash/app_list/views/search_result_tile_item_view.h" #include "base/macros.h" namespace views { @@ -19,7 +20,6 @@ class AppListViewDelegate; class SearchResultPageView; -class SearchResultTileItemView; // Displays a list of SearchResultTileItemView. class APP_LIST_EXPORT SearchResultTileItemListView @@ -31,6 +31,7 @@ ~SearchResultTileItemListView() override; // Overridden from SearchResultContainerView: + SearchResultTileItemView* GetResultViewAt(size_t index) override; void NotifyFirstResultYIndex(int y_index) override; int GetYSize() override; SearchResultBaseView* GetFirstResultView() override;
diff --git a/ash/app_list/views/search_result_tile_item_view.cc b/ash/app_list/views/search_result_tile_item_view.cc index 05fda46..0d80c9b 100644 --- a/ash/app_list/views/search_result_tile_item_view.cc +++ b/ash/app_list/views/search_result_tile_item_view.cc
@@ -213,6 +213,10 @@ if (!result()->icon().isNull()) OnMetadataChanged(); + UpdateAccessibleName(); +} + +base::string16 SearchResultTileItemView::ComputeAccessibleName() const { base::string16 accessible_name; if (!result()->accessible_name().empty()) accessible_name = result()->accessible_name(); @@ -234,11 +238,7 @@ base::UTF8ToUTF16(", ") + l10n_util::GetStringUTF16(IDS_APP_ACCESSIBILITY_APP_RECOMMENDATION_ARC); } - SetAccessibleName(accessible_name); -} - -void SearchResultTileItemView::SetIndexInItemListView(size_t index) { - index_in_item_list_view_ = index; + return accessible_name; } void SearchResultTileItemView::SetParentBackgroundColor(SkColor color) { @@ -396,10 +396,9 @@ view_delegate_->OpenSearchResult( result()->id(), event_flags, ash::mojom::AppListLaunchedFrom::kLaunchedFromSearchBox, - ash::mojom::AppListLaunchType::kAppSearchResult, - index_in_item_list_view_); + ash::mojom::AppListLaunchType::kAppSearchResult, index_in_container()); view_delegate_->LogResultLaunchHistogram( - SearchResultLaunchLocation::kTileList, index_in_item_list_view_); + SearchResultLaunchLocation::kTileList, index_in_container()); } void SearchResultTileItemView::SetIcon(const gfx::ImageSkia& icon) {
diff --git a/ash/app_list/views/search_result_tile_item_view.h b/ash/app_list/views/search_result_tile_item_view.h index ceab83bd..8afa742 100644 --- a/ash/app_list/views/search_result_tile_item_view.h +++ b/ash/app_list/views/search_result_tile_item_view.h
@@ -42,7 +42,9 @@ ~SearchResultTileItemView() override; void OnResultChanged() override; - void SetIndexInItemListView(size_t index); + + // Overridden from SearchResultBaseView: + base::string16 ComputeAccessibleName() const override; // Informs the SearchResultTileItemView of its parent's background color. The // controls within the SearchResultTileItemView will adapt to suit the given @@ -126,9 +128,6 @@ std::unique_ptr<AppListMenuModelAdapter> context_menu_; - // The index of this item in the search_result_tile_item_list_view, only used - // for logging. - int index_in_item_list_view_ = -1; base::WeakPtrFactory<SearchResultTileItemView> weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(SearchResultTileItemView);
diff --git a/ash/app_list/views/search_result_view.cc b/ash/app_list/views/search_result_view.cc index 22cfd6f..5d51ae2 100644 --- a/ash/app_list/views/search_result_view.cc +++ b/ash/app_list/views/search_result_view.cc
@@ -19,7 +19,6 @@ #include "ash/public/cpp/app_list/app_list_switches.h" #include "ash/public/interfaces/app_list.mojom.h" #include "base/bind.h" -#include "base/strings/utf_string_conversions.h" #include "ui/gfx/canvas.h" #include "ui/gfx/color_palette.h" #include "ui/gfx/font.h" @@ -28,7 +27,6 @@ #include "ui/views/controls/button/image_button.h" #include "ui/views/controls/image_view.h" #include "ui/views/controls/menu/menu_runner.h" -#include "ui/views/controls/progress_bar.h" namespace app_list { @@ -71,7 +69,6 @@ display_icon_(new views::ImageView), badge_icon_(new views::ImageView), actions_view_(new SearchResultActionsView(this)), - progress_bar_(new views::ProgressBar), weak_ptr_factory_(this) { SetFocusBehavior(FocusBehavior::ALWAYS); icon_->set_can_process_events_within_subtree(false); @@ -83,7 +80,6 @@ AddChildView(display_icon_); AddChildView(badge_icon_); AddChildView(actions_view_); - AddChildView(progress_bar_); set_context_menu_controller(this); set_notify_enter_exit_on_child(true); } @@ -96,8 +92,6 @@ OnMetadataChanged(); UpdateTitleText(); UpdateDetailsText(); - OnIsInstallingChanged(); - OnPercentDownloadedChanged(); SchedulePaint(); } @@ -119,22 +113,6 @@ UpdateAccessibleName(); } -base::string16 SearchResultView::ComputeAccessibleName() const { - if (!result()) - return base::string16(); - - base::string16 accessible_name = result()->title(); - if (!result()->title().empty() && !result()->details().empty()) - accessible_name += base::ASCIIToUTF16(", "); - accessible_name += result()->details(); - - return accessible_name; -} - -void SearchResultView::UpdateAccessibleName() { - SetAccessibleName(ComputeAccessibleName()); -} - void SearchResultView::CreateTitleRenderText() { auto render_text = gfx::RenderText::CreateHarfBuzzInstance(); render_text->SetText(result()->title()); @@ -241,14 +219,6 @@ actions_bounds.set_x(rect.right() - kActionButtonRightMargin - actions_width); actions_bounds.set_width(actions_width); actions_view_->SetBoundsRect(actions_bounds); - - const int progress_width = rect.width() / 5; - const int progress_height = progress_bar_->GetPreferredSize().height(); - const gfx::Rect progress_bounds( - rect.right() - kActionButtonRightMargin - progress_width, - rect.y() + (rect.height() - progress_height) / 2, progress_width, - progress_height); - progress_bar_->SetBoundsRect(progress_bounds); } bool SearchResultView::OnKeyPressed(const ui::KeyEvent& event) { @@ -285,8 +255,7 @@ (actions_view_->children().empty() ? 0 : kActionButtonRightMargin)); } else { text_bounds.set_width(rect.width() - kPreferredIconViewWidth - - kTextTrailPadding - progress_bar_->bounds().width() - - kActionButtonRightMargin); + kTextTrailPadding - kActionButtonRightMargin); } text_bounds.set_x( GetMirroredXWithWidthInView(text_bounds.x(), text_bounds.width())); @@ -433,21 +402,6 @@ icon->SetImage(image); } -void SearchResultView::OnIsInstallingChanged() { - const bool is_installing = result() && result()->is_installing(); - actions_view_->SetVisible(!is_installing); - progress_bar_->SetVisible(is_installing); -} - -void SearchResultView::OnPercentDownloadedChanged() { - progress_bar_->SetValue(result() ? result()->percent_downloaded() / 100.0 - : 0); -} - -void SearchResultView::OnItemInstalled() { - list_view_->OnSearchResultInstalled(this); -} - void SearchResultView::OnSearchResultActionActivated(size_t index, int event_flags) { // |result()| could be NULL when result list is changing.
diff --git a/ash/app_list/views/search_result_view.h b/ash/app_list/views/search_result_view.h index 5a1ef54..3dde73d 100644 --- a/ash/app_list/views/search_result_view.h +++ b/ash/app_list/views/search_result_view.h
@@ -28,7 +28,6 @@ namespace views { class ImageView; -class ProgressBar; } // namespace views namespace app_list { @@ -58,21 +57,6 @@ // Sets/gets SearchResult displayed by this view. void OnResultChanged() override; - // Computes the button's spoken feedback name. - base::string16 ComputeAccessibleName() const; - - // Gets the index of this result in the |SearchResultListView|. - int get_index_in_search_result_list_view() const { - return index_in_search_result_list_view_; - } - - // Stores the index of this result in the |SearchResultListView|. - void set_index_in_search_result_list_view(size_t index) { - index_in_search_result_list_view_ = index; - } - - void set_is_last_result(bool is_last) { is_last_result_ = is_last; } - // AppListMenuModelAdapter::Delegate overrides: void ExecuteCommand(int command_id, int event_flags) override; @@ -85,7 +69,6 @@ void UpdateTitleText(); void UpdateDetailsText(); - void UpdateAccessibleName(); // Creates title/details render text. void CreateTitleRenderText(); @@ -126,9 +109,6 @@ // SearchResultObserver overrides: void OnMetadataChanged() override; - void OnIsInstallingChanged() override; - void OnPercentDownloadedChanged() override; - void OnItemInstalled() override; void SetIconImage(const gfx::ImageSkia& source, views::ImageView* const icon, @@ -138,8 +118,6 @@ void OnSearchResultActionActivated(size_t index, int event_flags) override; bool IsSearchResultHoveredOrSelected() override; - bool is_last_result_ = false; - // Parent list view. Owned by views hierarchy. SearchResultListView* list_view_; @@ -152,7 +130,6 @@ std::unique_ptr<gfx::RenderText> title_text_; std::unique_ptr<gfx::RenderText> details_text_; SearchResultActionsView* actions_view_; // Owned by the views hierarchy. - views::ProgressBar* progress_bar_; // Owned by views hierarchy. std::unique_ptr<AppListMenuModelAdapter> context_menu_; @@ -161,10 +138,6 @@ // Whether the removal confirmation dialog is invoked by long press touch. bool confirm_remove_by_long_press_ = false; - // The index of this item in the search_result_tile_item_list_view, only - // used for logging. - int index_in_search_result_list_view_ = -1; - base::WeakPtrFactory<SearchResultView> weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(SearchResultView);
diff --git a/ash/app_list/views/suggestion_chip_container_view.cc b/ash/app_list/views/suggestion_chip_container_view.cc index 60733ca7..a52f19b 100644 --- a/ash/app_list/views/suggestion_chip_container_view.cc +++ b/ash/app_list/views/suggestion_chip_container_view.cc
@@ -10,7 +10,6 @@ #include "ash/app_list/views/app_list_main_view.h" #include "ash/app_list/views/contents_view.h" #include "ash/app_list/views/search_box_view.h" -#include "ash/app_list/views/search_result_suggestion_chip_view.h" #include "ash/public/cpp/app_list/app_list_config.h" #include "ash/public/cpp/app_list/app_list_features.h" #include "base/bind.h" @@ -53,7 +52,7 @@ SearchResultSuggestionChipView* chip = new SearchResultSuggestionChipView(view_delegate()); chip->SetVisible(false); - chip->SetIndexInSuggestionChipContainer(i); + chip->set_index_in_container(i); suggestion_chip_views_.emplace_back(chip); AddChildView(chip); } @@ -61,6 +60,12 @@ SuggestionChipContainerView::~SuggestionChipContainerView() = default; +SearchResultSuggestionChipView* SuggestionChipContainerView::GetResultViewAt( + size_t index) { + DCHECK(index >= 0 && index < suggestion_chip_views_.size()); + return suggestion_chip_views_[index]; +} + int SuggestionChipContainerView::DoUpdate() { if (IgnoreUpdateAndLayout()) return num_results();
diff --git a/ash/app_list/views/suggestion_chip_container_view.h b/ash/app_list/views/suggestion_chip_container_view.h index 546d5d8..3054eca 100644 --- a/ash/app_list/views/suggestion_chip_container_view.h +++ b/ash/app_list/views/suggestion_chip_container_view.h
@@ -8,12 +8,12 @@ #include <vector> #include "ash/app_list/views/search_result_container_view.h" +#include "ash/app_list/views/search_result_suggestion_chip_view.h" #include "base/macros.h" namespace app_list { class ContentsView; -class SearchResultSuggestionChipView; // A container that holds the suggestion chips. class SuggestionChipContainerView : public SearchResultContainerView { @@ -22,6 +22,7 @@ ~SuggestionChipContainerView() override; // SearchResultContainerView: + SearchResultSuggestionChipView* GetResultViewAt(size_t index) override; int DoUpdate() override; const char* GetClassName() const override;
diff --git a/ash/app_menu/app_menu_model_adapter.cc b/ash/app_menu/app_menu_model_adapter.cc index 75c0552c..3d1c1071 100644 --- a/ash/app_menu/app_menu_model_adapter.cc +++ b/ash/app_menu/app_menu_model_adapter.cc
@@ -5,6 +5,7 @@ #include "ash/app_menu/app_menu_model_adapter.h" #include "ash/app_menu/notification_menu_controller.h" +#include "ash/public/cpp/shelf_model.h" #include "base/metrics/histogram_functions.h" #include "base/metrics/histogram_macros.h" #include "ui/base/models/simple_menu_model.h" @@ -100,16 +101,17 @@ } void AppMenuModelAdapter::RecordExecuteCommandHistogram(int command_id) { - base::UmaHistogramSparse(app_id().empty() ? kNonAppContextMenuExecuteCommand - : kAppContextMenuExecuteCommand, + const bool is_not_from_app = app_id().empty() || app_id() == kAppListId; + base::UmaHistogramSparse(is_not_from_app ? kNonAppContextMenuExecuteCommand + : kAppContextMenuExecuteCommand, command_id); if (is_tablet_mode_) { - base::UmaHistogramSparse(app_id().empty() + base::UmaHistogramSparse(is_not_from_app ? kNonAppContextMenuExecuteCommandInTablet : kAppContextMenuExecuteCommandInTablet, command_id); } else { - base::UmaHistogramSparse(app_id().empty() + base::UmaHistogramSparse(is_not_from_app ? kNonAppContextMenuExecuteCommandInClamshell : kAppContextMenuExecuteCommandInClamshell, command_id);
diff --git a/ash/assistant/model/assistant_ui_element.cc b/ash/assistant/model/assistant_ui_element.cc index 1d7554b..b9762b59 100644 --- a/ash/assistant/model/assistant_ui_element.cc +++ b/ash/assistant/model/assistant_ui_element.cc
@@ -6,7 +6,6 @@ #include "ash/assistant/ui/assistant_ui_constants.h" #include "base/base64.h" -#include "ui/base/ui_base_features.h" namespace ash { @@ -66,8 +65,6 @@ contents_ = std::make_unique<content::NavigableContents>( contents_factory_, std::move(contents_params)); - if (features::IsUsingWindowService()) - contents_->ForceUseWindowService(); // Observe |contents_| so that we are notified when loading is complete. contents_->AddObserver(this);
diff --git a/ash/assistant/ui/assistant_web_view.cc b/ash/assistant/ui/assistant_web_view.cc index 3c4d8ba..bc5a4d8 100644 --- a/ash/assistant/ui/assistant_web_view.cc +++ b/ash/assistant/ui/assistant_web_view.cc
@@ -16,7 +16,6 @@ #include "base/callback.h" #include "services/content/public/cpp/navigable_contents_view.h" #include "ui/aura/window.h" -#include "ui/base/ui_base_features.h" #include "ui/compositor/layer.h" #include "ui/display/display.h" #include "ui/display/screen.h" @@ -146,8 +145,6 @@ contents_ = std::make_unique<content::NavigableContents>( contents_factory_.get(), std::move(contents_params)); - if (features::IsUsingWindowService()) - contents_->ForceUseWindowService(); // We observe |contents_| so that we can handle events from the underlying // web contents.
diff --git a/ash/frame/caption_buttons/frame_size_button_unittest.cc b/ash/frame/caption_buttons/frame_size_button_unittest.cc index 47e41d39..6962098 100644 --- a/ash/frame/caption_buttons/frame_size_button_unittest.cc +++ b/ash/frame/caption_buttons/frame_size_button_unittest.cc
@@ -93,7 +93,7 @@ } // Returns true if the window has |state_type|. - bool HasStateType(mojom::WindowStateType state_type) const { + bool HasStateType(WindowStateType state_type) const { return window_state()->GetStateType() == state_type; } @@ -214,7 +214,7 @@ generator->MoveMouseTo(CenterPointInScreen(close_button())); generator->ReleaseLeftButton(); base::RunLoop().RunUntilIdle(); - EXPECT_TRUE(HasStateType(mojom::WindowStateType::RIGHT_SNAPPED)); + EXPECT_TRUE(HasStateType(WindowStateType::kRightSnapped)); // Snap left. generator->MoveMouseTo(CenterPointInScreen(size_button())); @@ -222,7 +222,7 @@ generator->MoveMouseTo(CenterPointInScreen(minimize_button())); generator->ReleaseLeftButton(); base::RunLoop().RunUntilIdle(); - EXPECT_TRUE(HasStateType(mojom::WindowStateType::LEFT_SNAPPED)); + EXPECT_TRUE(HasStateType(WindowStateType::kLeftSnapped)); // 2) Test with scroll gestures. // Snap right. @@ -230,14 +230,14 @@ CenterPointInScreen(close_button()), base::TimeDelta::FromMilliseconds(100), 3); base::RunLoop().RunUntilIdle(); - EXPECT_TRUE(HasStateType(mojom::WindowStateType::RIGHT_SNAPPED)); + EXPECT_TRUE(HasStateType(WindowStateType::kRightSnapped)); // Snap left. generator->GestureScrollSequence(CenterPointInScreen(size_button()), CenterPointInScreen(minimize_button()), base::TimeDelta::FromMilliseconds(100), 3); base::RunLoop().RunUntilIdle(); - EXPECT_TRUE(HasStateType(mojom::WindowStateType::LEFT_SNAPPED)); + EXPECT_TRUE(HasStateType(WindowStateType::kLeftSnapped)); // 3) Test with tap gestures. const float touch_default_radius = @@ -247,12 +247,12 @@ generator->MoveMouseTo(CenterPointInScreen(size_button())); generator->PressMoveAndReleaseTouchTo(CenterPointInScreen(close_button())); base::RunLoop().RunUntilIdle(); - EXPECT_TRUE(HasStateType(mojom::WindowStateType::RIGHT_SNAPPED)); + EXPECT_TRUE(HasStateType(WindowStateType::kRightSnapped)); // Snap left. generator->MoveMouseTo(CenterPointInScreen(size_button())); generator->PressMoveAndReleaseTouchTo(CenterPointInScreen(minimize_button())); base::RunLoop().RunUntilIdle(); - EXPECT_TRUE(HasStateType(mojom::WindowStateType::LEFT_SNAPPED)); + EXPECT_TRUE(HasStateType(WindowStateType::kLeftSnapped)); ui::GestureConfiguration::GetInstance()->set_default_radius( touch_default_radius); } @@ -272,7 +272,7 @@ generator->MoveMouseBy(-minimize_button()->width(), 0); generator->ReleaseLeftButton(); base::RunLoop().RunUntilIdle(); - EXPECT_TRUE(HasStateType(mojom::WindowStateType::LEFT_SNAPPED)); + EXPECT_TRUE(HasStateType(WindowStateType::kLeftSnapped)); } // Test that right clicking the size button has no effect. @@ -354,7 +354,7 @@ // Release the mouse, snapping the window left. generator->ReleaseLeftButton(); base::RunLoop().RunUntilIdle(); - EXPECT_TRUE(HasStateType(mojom::WindowStateType::LEFT_SNAPPED)); + EXPECT_TRUE(HasStateType(WindowStateType::kLeftSnapped)); // None of the buttons should stay pressed and the buttons should have their // regular icons. @@ -386,7 +386,7 @@ // Release the mouse. The window should stay snapped left. generator->ReleaseLeftButton(); base::RunLoop().RunUntilIdle(); - EXPECT_TRUE(HasStateType(mojom::WindowStateType::LEFT_SNAPPED)); + EXPECT_TRUE(HasStateType(WindowStateType::kLeftSnapped)); // The buttons should stay unpressed and the buttons should now have their // regular icons. @@ -493,7 +493,7 @@ // Releasing should snap the window right. generator->ReleaseLeftButton(); base::RunLoop().RunUntilIdle(); - EXPECT_TRUE(HasStateType(mojom::WindowStateType::RIGHT_SNAPPED)); + EXPECT_TRUE(HasStateType(WindowStateType::kRightSnapped)); // None of the buttons should stay pressed and the buttons should have their // regular icons.
diff --git a/ash/frame/non_client_frame_view_ash.cc b/ash/frame/non_client_frame_view_ash.cc index c31a73d..2dff6e4 100644 --- a/ash/frame/non_client_frame_view_ash.cc +++ b/ash/frame/non_client_frame_view_ash.cc
@@ -107,7 +107,7 @@ // wm::WindowStateObserver: void OnPostWindowStateTypeChange(wm::WindowState* window_state, - mojom::WindowStateType old_type) override { + WindowStateType old_type) override { views::Widget* widget = views::Widget::GetWidgetForNativeWindow(window_state->window()); if (immersive_fullscreen_controller_ &&
diff --git a/ash/ime/ime_focus_handler.cc b/ash/ime/ime_focus_handler.cc deleted file mode 100644 index 90ac32b..0000000 --- a/ash/ime/ime_focus_handler.cc +++ /dev/null
@@ -1,42 +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. - -#include "ash/ime/ime_focus_handler.h" - -#include "base/logging.h" -#include "services/ws/window_service.h" -#include "ui/aura/client/focus_client.h" -#include "ui/base/ime/input_method.h" - -namespace ash { - -ImeFocusHandler::ImeFocusHandler(aura::client::FocusClient* focus_client, - ui::InputMethod* input_method) - : focus_client_(focus_client), input_method_(input_method) { - DCHECK(input_method_); - - focus_client_->AddObserver(this); -} - -ImeFocusHandler::~ImeFocusHandler() { - focus_client_->RemoveObserver(this); -} - -void ImeFocusHandler::OnWindowFocused(aura::Window* gained_focus, - aura::Window* lost_focus) { - const bool proxy_window_gaining_focus = - ws::WindowService::IsProxyWindow(gained_focus); - const bool proxy_window_losing_focus = - ws::WindowService::IsProxyWindow(lost_focus); - - // Focus moves to a ProxyWindow from an ash window. - if (proxy_window_gaining_focus && !proxy_window_losing_focus) - input_method_->OnBlur(); - - // Focus moves to an ash window from a ProxyWindow. - if (!proxy_window_gaining_focus && proxy_window_losing_focus) - input_method_->OnFocus(); -} - -} // namespace ash
diff --git a/ash/ime/ime_focus_handler.h b/ash/ime/ime_focus_handler.h deleted file mode 100644 index 56fc8eae..0000000 --- a/ash/ime/ime_focus_handler.h +++ /dev/null
@@ -1,47 +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 ASH_IME_IME_FOCUS_HANDLER_H_ -#define ASH_IME_IME_FOCUS_HANDLER_H_ - -#include "ash/ash_export.h" -#include "base/macros.h" -#include "ui/aura/client/focus_change_observer.h" - -namespace aura { -namespace client { -class FocusClient; -} // namespace client -} // namespace aura - -namespace ui { -class InputMethod; -} - -namespace ash { - -// Updates the focus state of the shared IME instance of ash when the focus -// moves between ash windows and ClientWindows. -class ASH_EXPORT ImeFocusHandler : public aura::client::FocusChangeObserver { - public: - ImeFocusHandler(aura::client::FocusClient* focus_client, - ui::InputMethod* input_method); - ~ImeFocusHandler() override; - - private: - // aura::client::FocusChangeObserver: - void OnWindowFocused(aura::Window* gained_focus, - aura::Window* lost_focus) override; - - aura::client::FocusClient* const focus_client_; - - // IME instance to update. This is the shared IME instance in production. - ui::InputMethod* const input_method_; - - DISALLOW_COPY_AND_ASSIGN(ImeFocusHandler); -}; - -} // namespace ash - -#endif // ASH_IME_IME_FOCUS_HANDLER_H_
diff --git a/ash/ime/ime_mode_indicator_view.cc b/ash/ime/ime_mode_indicator_view.cc index 5f477dd9..53bfac4 100644 --- a/ash/ime/ime_mode_indicator_view.cc +++ b/ash/ime/ime_mode_indicator_view.cc
@@ -9,8 +9,6 @@ #include "ash/wm/window_util.h" #include "base/logging.h" #include "base/macros.h" -#include "services/ws/public/cpp/property_type_converters.h" -#include "services/ws/public/mojom/window_manager.mojom.h" #include "ui/display/display.h" #include "ui/display/screen.h" #include "ui/views/bubble/bubble_frame_view.h"
diff --git a/ash/login/ui/login_test_base.cc b/ash/login/ui/login_test_base.cc index e825398..d0c6da6 100644 --- a/ash/login/ui/login_test_base.cc +++ b/ash/login/ui/login_test_base.cc
@@ -16,8 +16,6 @@ #include "ash/wallpaper/wallpaper_controller.h" #include "base/bind.h" #include "base/strings/strcat.h" -#include "services/ws/public/cpp/property_type_converters.h" -#include "services/ws/public/mojom/window_manager.mojom.h" #include "ui/views/widget/widget.h" #include "ui/views/widget/widget_delegate.h"
diff --git a/ash/metrics/time_to_first_present_recorder.cc b/ash/metrics/time_to_first_present_recorder.cc index f03d7f7..92406c9 100644 --- a/ash/metrics/time_to_first_present_recorder.cc +++ b/ash/metrics/time_to_first_present_recorder.cc
@@ -8,6 +8,7 @@ #include "base/bind_helpers.h" #include "base/metrics/histogram_macros.h" #include "base/time/time.h" +#include "components/startup_metric_utils/browser/startup_metric_utils.h" #include "ui/aura/window.h" #include "ui/aura/window_tree_host.h" #include "ui/compositor/compositor.h" @@ -15,6 +16,10 @@ namespace ash { +// static +const char TimeToFirstPresentRecorder::kMetricName[] = + "Ash.ProcessCreationToFirstPresent"; + TimeToFirstPresentRecorder::TimeToFirstPresentRecorder(aura::Window* window) { aura::WindowTreeHost* window_tree_host = window->GetHost(); DCHECK(window_tree_host); @@ -25,42 +30,13 @@ TimeToFirstPresentRecorder::~TimeToFirstPresentRecorder() = default; -void TimeToFirstPresentRecorder::Bind( - mojom::ProcessCreationTimeRecorderRequest request) { - // Process createion time should only be set once. - if (binding_.is_bound() || !process_creation_time_.is_null()) - return; - - binding_.Bind(std::move(request)); -} - -void TimeToFirstPresentRecorder::SetMainProcessCreationTime( - base::TimeTicks start_time) { - if (!process_creation_time_.is_null()) - return; - - process_creation_time_ = start_time; - LogTime(); - - // Process creation time should be set only once. - binding_.Close(); -} - -void TimeToFirstPresentRecorder::LogTime() { - if (present_time_.is_null() || process_creation_time_.is_null()) - return; - - UMA_HISTOGRAM_TIMES("Ash.ProcessCreationToFirstPresent", - time_to_first_present()); - if (log_callback_) - std::move(log_callback_).Run(); -} - void TimeToFirstPresentRecorder::DidPresentCompositorFrame( const gfx::PresentationFeedback& feedback) { - DCHECK(present_time_.is_null()); // This should only be called once. - present_time_ = feedback.timestamp; - LogTime(); + const base::TimeDelta time_to_first_present = + feedback.timestamp - startup_metric_utils::MainEntryPointTicks(); + UMA_HISTOGRAM_TIMES(kMetricName, time_to_first_present); + if (log_callback_) + std::move(log_callback_).Run(); } } // namespace ash
diff --git a/ash/metrics/time_to_first_present_recorder.h b/ash/metrics/time_to_first_present_recorder.h index 1e5c453..463923e 100644 --- a/ash/metrics/time_to_first_present_recorder.h +++ b/ash/metrics/time_to_first_present_recorder.h
@@ -7,11 +7,9 @@ #include <stdint.h> -#include "ash/public/interfaces/process_creation_time_recorder.mojom.h" +#include "ash/ash_export.h" #include "base/callback.h" #include "base/macros.h" -#include "base/time/time.h" -#include "mojo/public/cpp/bindings/binding.h" namespace aura { class Window; @@ -26,41 +24,26 @@ class TimeToFirstPresentRecorderTestApi; // Used for tracking the time main started to the time the first bits make it -// the screen and logging a histogram of the time. Chrome is responsible for -// providing the start time by way of ProcessCreationTimeRecorder. +// the screen and logging a histogram of the time. // // This only logs the time to present the primary root window. -class TimeToFirstPresentRecorder : public mojom::ProcessCreationTimeRecorder { +class ASH_EXPORT TimeToFirstPresentRecorder { public: - explicit TimeToFirstPresentRecorder(aura::Window* window); - ~TimeToFirstPresentRecorder() override; + // The name of the histogram the time is logged against. + static const char kMetricName[]; - void Bind(mojom::ProcessCreationTimeRecorderRequest request); + explicit TimeToFirstPresentRecorder(aura::Window* window); + ~TimeToFirstPresentRecorder(); private: friend class TimeToFirstPresentRecorderTestApi; - // If both times are available the time to present is logged. - void LogTime(); - // Callback from the compositor when it presented a valid frame. void DidPresentCompositorFrame(const gfx::PresentationFeedback& feedback); - base::TimeDelta time_to_first_present() const { - return present_time_ - process_creation_time_; - } - - // mojom::ProcessCreationTimeRecorder: - void SetMainProcessCreationTime(base::TimeTicks start_time) override; - - base::TimeTicks process_creation_time_; - base::TimeTicks present_time_; - - // Only used by tests. If valid it's Run() when both times are determined. + // Only used by tests. If valid it's Run() when the time is recorded. base::OnceClosure log_callback_; - mojo::Binding<mojom::ProcessCreationTimeRecorder> binding_{this}; - DISALLOW_COPY_AND_ASSIGN(TimeToFirstPresentRecorder); };
diff --git a/ash/metrics/time_to_first_present_recorder_test_api.cc b/ash/metrics/time_to_first_present_recorder_test_api.cc index c00be7d..7be2485 100644 --- a/ash/metrics/time_to_first_present_recorder_test_api.cc +++ b/ash/metrics/time_to_first_present_recorder_test_api.cc
@@ -7,52 +7,14 @@ #include "ash/metrics/time_to_first_present_recorder.h" #include "ash/shell.h" #include "base/bind.h" -#include "base/bind_helpers.h" -#include "mojo/public/cpp/bindings/strong_binding.h" namespace ash { -TimeToFirstPresentRecorderTestApi::TimeToFirstPresentRecorderTestApi() = - default; - -TimeToFirstPresentRecorderTestApi::~TimeToFirstPresentRecorderTestApi() = - default; - // static -void TimeToFirstPresentRecorderTestApi::BindRequest( - mojom::TimeToFirstPresentRecorderTestApiRequest request) { - mojo::MakeStrongBinding(std::make_unique<TimeToFirstPresentRecorderTestApi>(), - std::move(request)); -} - -void TimeToFirstPresentRecorderTestApi::GetProcessCreationToFirstPresentTime( - GetProcessCreationToFirstPresentTimeCallback callback) { - TimeToFirstPresentRecorder* recorder = - Shell::Get()->time_to_first_present_recorder(); - if (recorder->process_creation_time_.is_null() || - recorder->present_time_.is_null()) { - // Still waiting for time. Schedule a callback with - // TimeToFirstPresentRecorder. This only supports one callback at a time, - // which should be fine for tests. - DCHECK(recorder->log_callback_.is_null()); - recorder->log_callback_ = base::BindOnce( - &TimeToFirstPresentRecorderTestApi::OnLog, base::Unretained(this)); - DCHECK(!get_creation_time_callback_); - get_creation_time_callback_ = std::move(callback); - return; - } - std::move(callback).Run(recorder->time_to_first_present()); -} - -void TimeToFirstPresentRecorderTestApi::OnLog() { - TimeToFirstPresentRecorder* recorder = - Shell::Get()->time_to_first_present_recorder(); - DCHECK(!recorder->process_creation_time_.is_null() && - !recorder->present_time_.is_null()); - std::move(get_creation_time_callback_) - .Run(Shell::Get() - ->time_to_first_present_recorder() - ->time_to_first_present()); +void TimeToFirstPresentRecorderTestApi::SetTimeToFirstPresentCallback( + base::OnceClosure callback) { + Shell::Get()->time_to_first_present_recorder()->log_callback_ = + std::move(callback); } } // namespace ash
diff --git a/ash/metrics/time_to_first_present_recorder_test_api.h b/ash/metrics/time_to_first_present_recorder_test_api.h index 0b1240d8..98d6da7 100644 --- a/ash/metrics/time_to_first_present_recorder_test_api.h +++ b/ash/metrics/time_to_first_present_recorder_test_api.h
@@ -5,33 +5,17 @@ #ifndef ASH_METRICS_TIME_TO_FIRST_PRESENT_RECORDER_TEST_API_H_ #define ASH_METRICS_TIME_TO_FIRST_PRESENT_RECORDER_TEST_API_H_ -#include "ash/public/interfaces/time_to_first_present_recorder_test_api.test-mojom.h" +#include "base/callback_forward.h" #include "base/macros.h" namespace ash { -class TimeToFirstPresentRecorderTestApi - : public mojom::TimeToFirstPresentRecorderTestApi { +class TimeToFirstPresentRecorderTestApi { public: - TimeToFirstPresentRecorderTestApi(); - ~TimeToFirstPresentRecorderTestApi() override; - - // Creates and binds an instance from a remote request (e.g. from chrome). - static void BindRequest( - mojom::TimeToFirstPresentRecorderTestApiRequest request); - - // mojom::TimeToFirstPresentRecorderTestApi: - void GetProcessCreationToFirstPresentTime( - GetProcessCreationToFirstPresentTimeCallback callback) override; + static void SetTimeToFirstPresentCallback(base::OnceClosure callback); private: - void OnLog(); - - // If valid GetProcessCreationToFirstPresentTimeCallback() was called and - // we're waiting for TimeToFirstPresentRecorder to see the first log. - GetProcessCreationToFirstPresentTimeCallback get_creation_time_callback_; - - DISALLOW_COPY_AND_ASSIGN(TimeToFirstPresentRecorderTestApi); + DISALLOW_IMPLICIT_CONSTRUCTORS(TimeToFirstPresentRecorderTestApi); }; } // namespace ash
diff --git a/ash/metrics/user_metrics_recorder.cc b/ash/metrics/user_metrics_recorder.cc index 9dd9ac2..13c7b6cb 100644 --- a/ash/metrics/user_metrics_recorder.cc +++ b/ash/metrics/user_metrics_recorder.cc
@@ -15,7 +15,6 @@ #include "ash/public/cpp/shelf_model.h" #include "ash/public/cpp/shell_window_ids.h" #include "ash/public/interfaces/accessibility_controller.mojom-shared.h" -#include "ash/public/interfaces/window_state_type.mojom.h" #include "ash/session/session_controller_impl.h" #include "ash/shelf/shelf.h" #include "ash/shelf/shelf_view.h" @@ -51,30 +50,30 @@ wm::WindowState* active_window_state = ash::wm::GetActiveWindowState(); if (active_window_state) { switch (active_window_state->GetStateType()) { - case mojom::WindowStateType::MAXIMIZED: + case WindowStateType::kMaximized: active_window_state_type = ACTIVE_WINDOW_STATE_TYPE_MAXIMIZED; break; - case mojom::WindowStateType::FULLSCREEN: + case WindowStateType::kFullscreen: active_window_state_type = ACTIVE_WINDOW_STATE_TYPE_FULLSCREEN; break; - case mojom::WindowStateType::LEFT_SNAPPED: - case mojom::WindowStateType::RIGHT_SNAPPED: + case WindowStateType::kLeftSnapped: + case WindowStateType::kRightSnapped: active_window_state_type = ACTIVE_WINDOW_STATE_TYPE_SNAPPED; break; - case mojom::WindowStateType::PINNED: + case WindowStateType::kPinned: active_window_state_type = ACTIVE_WINDOW_STATE_TYPE_PINNED; break; - case mojom::WindowStateType::TRUSTED_PINNED: + case WindowStateType::kTrustedPinned: active_window_state_type = ACTIVE_WINDOW_STATE_TYPE_TRUSTED_PINNED; break; - case mojom::WindowStateType::PIP: + case WindowStateType::kPip: active_window_state_type = ACTIVE_WINDOW_STATE_TYPE_PIP; break; - case mojom::WindowStateType::DEFAULT: - case mojom::WindowStateType::NORMAL: - case mojom::WindowStateType::MINIMIZED: - case mojom::WindowStateType::INACTIVE: - case mojom::WindowStateType::AUTO_POSITIONED: + case WindowStateType::kDefault: + case WindowStateType::kNormal: + case WindowStateType::kMinimized: + case WindowStateType::kInactive: + case WindowStateType::kAutoPositioned: active_window_state_type = ACTIVE_WINDOW_STATE_TYPE_OTHER; break; }
diff --git a/ash/mojo_interface_factory.cc b/ash/mojo_interface_factory.cc index fb10ab6..aa85befd 100644 --- a/ash/mojo_interface_factory.cc +++ b/ash/mojo_interface_factory.cc
@@ -210,11 +210,6 @@ Shell::Get()->note_taking_controller()->BindRequest(std::move(request)); } -void BindProcessCreationTimeRecorderOnMainThread( - mojom::ProcessCreationTimeRecorderRequest request) { - Shell::Get()->time_to_first_present_recorder()->Bind(std::move(request)); -} - void BindShelfRequestOnMainThread(mojom::ShelfControllerRequest request) { Shell::Get()->shelf_controller()->BindRequest(std::move(request)); } @@ -352,9 +347,6 @@ registry->AddInterface( base::BindRepeating(&BindNoteTakingControllerRequestOnMainThread), main_thread_task_runner); - registry->AddInterface( - base::BindRepeating(&BindProcessCreationTimeRecorderOnMainThread), - main_thread_task_runner); registry->AddInterface(base::BindRepeating(&BindShelfRequestOnMainThread), main_thread_task_runner); registry->AddInterface(
diff --git a/ash/mojo_test_interface_factory.cc b/ash/mojo_test_interface_factory.cc index 026e60d35..ef512d3 100644 --- a/ash/mojo_test_interface_factory.cc +++ b/ash/mojo_test_interface_factory.cc
@@ -13,7 +13,6 @@ #include "ash/public/interfaces/shell_test_api.test-mojom.h" #include "ash/public/interfaces/status_area_widget_test_api.test-mojom.h" #include "ash/public/interfaces/system_tray_test_api.test-mojom.h" -#include "ash/public/interfaces/time_to_first_present_recorder_test_api.test-mojom.h" #include "ash/shelf/shelf_test_api.h" #include "ash/shell_test_api.h" #include "ash/system/status_area_widget_test_api.h" @@ -51,11 +50,6 @@ UnifiedSystemTrayTestApi::BindRequest(std::move(request)); } -void BindTimeToFirstPresentRecorderTestApiOnMainThread( - mojom::TimeToFirstPresentRecorderTestApiRequest request) { - TimeToFirstPresentRecorderTestApi::BindRequest(std::move(request)); -} - } // namespace void RegisterInterfaces( @@ -71,9 +65,6 @@ main_thread_task_runner); registry->AddInterface(base::Bind(&BindSystemTrayTestApiOnMainThread), main_thread_task_runner); - registry->AddInterface( - base::Bind(&BindTimeToFirstPresentRecorderTestApiOnMainThread), - main_thread_task_runner); } } // namespace mojo_test_interface_factory
diff --git a/ash/public/cpp/manifest.cc b/ash/public/cpp/manifest.cc index 196a363c..a45866c 100644 --- a/ash/public/cpp/manifest.cc +++ b/ash/public/cpp/manifest.cc
@@ -29,7 +29,6 @@ #include "ash/public/interfaces/night_light_controller.mojom.h" #include "ash/public/interfaces/note_taking_controller.mojom.h" #include "ash/public/interfaces/pref_connector.mojom.h" -#include "ash/public/interfaces/process_creation_time_recorder.mojom.h" #include "ash/public/interfaces/shelf.mojom.h" #include "ash/public/interfaces/shelf_integration_test_api.mojom.h" #include "ash/public/interfaces/shutdown.mojom.h" @@ -91,8 +90,7 @@ mojom::KeyboardController, mojom::LocaleUpdateController, mojom::LoginScreen, mojom::MediaController, mojom::NewWindowController, mojom::NightLightController, - mojom::NoteTakingController, - mojom::ProcessCreationTimeRecorder, mojom::ShelfController, + mojom::NoteTakingController, mojom::ShelfController, mojom::ShutdownController, mojom::SystemTray, mojom::TabletModeController, mojom::TrayAction, mojom::VoiceInteractionController, mojom::VpnList,
diff --git a/ash/public/cpp/mus_property_mirror_ash.cc b/ash/public/cpp/mus_property_mirror_ash.cc index f2c7f20..b8ff27eb 100644 --- a/ash/public/cpp/mus_property_mirror_ash.cc +++ b/ash/public/cpp/mus_property_mirror_ash.cc
@@ -44,8 +44,7 @@ int32_t value = window->GetProperty(kShelfItemTypeKey); root_window->SetProperty(kShelfItemTypeKey, value); } else if (key == kWindowStateTypeKey) { - ash::mojom::WindowStateType value = - window->GetProperty(kWindowStateTypeKey); + ash::WindowStateType value = window->GetProperty(kWindowStateTypeKey); root_window->SetProperty(kWindowStateTypeKey, value); } else if (key == kWindowPinTypeKey) { ash::mojom::WindowPinType value = window->GetProperty(kWindowPinTypeKey); @@ -53,7 +52,7 @@ } else if (key == kRestoreBoundsOverrideKey) { MirrorOwnedProperty(window, root_window, kRestoreBoundsOverrideKey); } else if (key == kRestoreWindowStateTypeOverrideKey) { - ash::mojom::WindowStateType value = + ash::WindowStateType value = window->GetProperty(kRestoreWindowStateTypeOverrideKey); root_window->SetProperty(kRestoreWindowStateTypeOverrideKey, value); } else if (key == kShelfIDKey) {
diff --git a/ash/public/cpp/test_manifest.cc b/ash/public/cpp/test_manifest.cc index 6bacb0f1e0..61f07ff4 100644 --- a/ash/public/cpp/test_manifest.cc +++ b/ash/public/cpp/test_manifest.cc
@@ -9,7 +9,6 @@ #include "ash/public/interfaces/shell_test_api.test-mojom.h" #include "ash/public/interfaces/status_area_widget_test_api.test-mojom.h" #include "ash/public/interfaces/system_tray_test_api.test-mojom.h" -#include "ash/public/interfaces/time_to_first_present_recorder_test_api.test-mojom.h" #include "base/no_destructor.h" #include "services/service_manager/public/cpp/manifest_builder.h" @@ -22,8 +21,7 @@ "test", service_manager::Manifest::InterfaceList< mojom::LoginScreenTestApi, mojom::ShelfTestApi, mojom::ShellTestApi, mojom::StatusAreaWidgetTestApi, - mojom::SystemTrayTestApi, - mojom::TimeToFirstPresentRecorderTestApi>()) + mojom::SystemTrayTestApi>()) .Build()}; return *manifest; }
diff --git a/ash/public/cpp/window_properties.cc b/ash/public/cpp/window_properties.cc index afc72a44..cc2f5bd 100644 --- a/ash/public/cpp/window_properties.cc +++ b/ash/public/cpp/window_properties.cc
@@ -10,7 +10,6 @@ #include "ash/public/cpp/window_state_type.h" #include "ash/public/interfaces/window_pin_type.mojom.h" #include "ash/public/interfaces/window_properties.mojom.h" -#include "ash/public/interfaces/window_state_type.mojom.h" #include "base/bind.h" #include "base/unguessable_token.h" #include "services/ws/public/mojom/window_manager.mojom.h" @@ -25,8 +24,7 @@ DEFINE_EXPORTED_UI_CLASS_PROPERTY_TYPE(ASH_PUBLIC_EXPORT, ash::mojom::WindowPinType) -DEFINE_EXPORTED_UI_CLASS_PROPERTY_TYPE(ASH_PUBLIC_EXPORT, - ash::mojom::WindowStateType) +DEFINE_EXPORTED_UI_CLASS_PROPERTY_TYPE(ASH_PUBLIC_EXPORT, ash::WindowStateType) DEFINE_EXPORTED_UI_CLASS_PROPERTY_TYPE(ASH_PUBLIC_EXPORT, ash::BackdropWindowMode) @@ -99,9 +97,6 @@ kIsShowingInOverviewKey, mojom::kIsShowingInOverview_Property, aura::PropertyConverter::CreateAcceptAnyValueCallback()); property_converter->RegisterPrimitiveProperty( - kPrePipWindowStateTypeKey, mojom::kPrePipWindowStateType_Property, - base::BindRepeating(&IsValidWindowStateType)); - property_converter->RegisterPrimitiveProperty( kRenderTitleAreaProperty, ws::mojom::WindowManager::kRenderParentTitleArea_Property, aura::PropertyConverter::CreateAcceptAnyValueCallback()); @@ -112,9 +107,6 @@ aura::client::kTopViewInset, mojom::kTopViewInset_Property, aura::PropertyConverter::CreateAcceptAnyValueCallback()); property_converter->RegisterPrimitiveProperty( - kWindowStateTypeKey, mojom::kWindowStateType_Property, - base::BindRepeating(&IsValidWindowStateType)); - property_converter->RegisterPrimitiveProperty( kWindowPinTypeKey, mojom::kWindowPinType_Property, base::BindRepeating(&IsValidWindowPinType)); property_converter->RegisterPrimitiveProperty( @@ -176,23 +168,22 @@ DEFINE_UI_CLASS_PROPERTY_KEY(bool, kIsDeferredTabDraggingTargetWindowKey, false) DEFINE_UI_CLASS_PROPERTY_KEY(bool, kIsDraggingTabsKey, false) DEFINE_UI_CLASS_PROPERTY_KEY(bool, kIsShowingInOverviewKey, false) -DEFINE_UI_CLASS_PROPERTY_KEY(mojom::WindowStateType, +DEFINE_UI_CLASS_PROPERTY_KEY(WindowStateType, kPrePipWindowStateTypeKey, - mojom::WindowStateType::DEFAULT) + WindowStateType::kDefault) DEFINE_UI_CLASS_PROPERTY_KEY(bool, kRenderTitleAreaProperty, false) DEFINE_OWNED_UI_CLASS_PROPERTY_KEY(gfx::Rect, kRestoreBoundsOverrideKey, nullptr) -DEFINE_UI_CLASS_PROPERTY_KEY(mojom::WindowStateType, +DEFINE_UI_CLASS_PROPERTY_KEY(WindowStateType, kRestoreWindowStateTypeOverrideKey, - mojom::WindowStateType::DEFAULT) + WindowStateType::kDefault) DEFINE_UI_CLASS_PROPERTY_KEY(bool, kSearchKeyAcceleratorReservedKey, false) DEFINE_OWNED_UI_CLASS_PROPERTY_KEY(std::string, kShelfIDKey, nullptr) DEFINE_UI_CLASS_PROPERTY_KEY(int32_t, kShelfItemTypeKey, TYPE_UNDEFINED) DEFINE_UI_CLASS_PROPERTY_KEY(aura::Window*, kTabDraggingSourceWindowKey, nullptr) - DEFINE_UI_CLASS_PROPERTY_KEY(SkColor, kFrameActiveColorKey, kDefaultFrameColor) DEFINE_UI_CLASS_PROPERTY_KEY(SkColor, kFrameInactiveColorKey, @@ -201,9 +192,9 @@ kWindowPinTypeKey, mojom::WindowPinType::NONE) DEFINE_UI_CLASS_PROPERTY_KEY(bool, kWindowPositionManagedTypeKey, false) -DEFINE_UI_CLASS_PROPERTY_KEY(mojom::WindowStateType, +DEFINE_UI_CLASS_PROPERTY_KEY(WindowStateType, kWindowStateTypeKey, - mojom::WindowStateType::DEFAULT) + WindowStateType::kDefault) DEFINE_UI_CLASS_PROPERTY_KEY(bool, kWindowPipTypeKey, false) } // namespace ash
diff --git a/ash/public/cpp/window_properties.h b/ash/public/cpp/window_properties.h index a834c2f..81db1ec2 100644 --- a/ash/public/cpp/window_properties.h +++ b/ash/public/cpp/window_properties.h
@@ -25,9 +25,10 @@ namespace ash { +enum class WindowStateType; + namespace mojom { enum class WindowPinType; -enum class WindowStateType; } enum class BackdropWindowMode { @@ -113,8 +114,8 @@ kIsShowingInOverviewKey; // A property key to store the window state the window had before entering PIP. -ASH_PUBLIC_EXPORT extern const aura::WindowProperty< - mojom::WindowStateType>* const kPrePipWindowStateTypeKey; +ASH_PUBLIC_EXPORT extern const aura::WindowProperty<WindowStateType>* const + kPrePipWindowStateTypeKey; // Maps to ws::mojom::WindowManager::kRenderParentTitleArea_Property. ASH_PUBLIC_EXPORT extern const aura::WindowProperty<bool>* const @@ -130,8 +131,8 @@ // take preference over the current state if // |kRestoreWindowStateTypeOverrideKey| is set. This is used by e.g. the tablet // mode window manager. -ASH_PUBLIC_EXPORT extern const aura::WindowProperty< - mojom::WindowStateType>* const kRestoreWindowStateTypeOverrideKey; +ASH_PUBLIC_EXPORT extern const aura::WindowProperty<WindowStateType>* const + kRestoreWindowStateTypeOverrideKey; // A property key to store whether search key accelerator is reserved for a // window. This is used to pass through search key accelerators to Android @@ -175,8 +176,8 @@ kWindowPositionManagedTypeKey; // A property key to indicate ash's extended window state. -ASH_PUBLIC_EXPORT extern const aura::WindowProperty< - mojom::WindowStateType>* const kWindowStateTypeKey; +ASH_PUBLIC_EXPORT extern const aura::WindowProperty<WindowStateType>* const + kWindowStateTypeKey; // A property key to indicate pip window state. ASH_PUBLIC_EXPORT extern const aura::WindowProperty<bool>* const
diff --git a/ash/public/cpp/window_state_type.cc b/ash/public/cpp/window_state_type.cc index b9f37b13..aee4481 100644 --- a/ash/public/cpp/window_state_type.cc +++ b/ash/public/cpp/window_state_type.cc
@@ -4,85 +4,116 @@ #include "ash/public/cpp/window_state_type.h" -#include "ash/public/interfaces/window_state_type.mojom.h" +#include "base/logging.h" namespace ash { -mojom::WindowStateType ToWindowStateType(ui::WindowShowState state) { +std::ostream& operator<<(std::ostream& stream, WindowStateType state) { + switch (state) { + case WindowStateType::kDefault: + return stream << "kDefault"; + case WindowStateType::kNormal: + return stream << "kNormal"; + case WindowStateType::kMinimized: + return stream << "kMinimized"; + case WindowStateType::kMaximized: + return stream << "kMaximized"; + case WindowStateType::kInactive: + return stream << "kInactive"; + case WindowStateType::kFullscreen: + return stream << "kFullscreen"; + case WindowStateType::kLeftSnapped: + return stream << "kLeftSnapped"; + case WindowStateType::kRightSnapped: + return stream << "kRightSnapped"; + case WindowStateType::kAutoPositioned: + return stream << "kAutoPositioned"; + case WindowStateType::kPinned: + return stream << "kPinned"; + case WindowStateType::kTrustedPinned: + return stream << "kTrustedPinned"; + case WindowStateType::kPip: + return stream << "kPip"; + } + + NOTREACHED(); + return stream; +} + +WindowStateType ToWindowStateType(ui::WindowShowState state) { switch (state) { case ui::SHOW_STATE_DEFAULT: - return mojom::WindowStateType::DEFAULT; + return WindowStateType::kDefault; case ui::SHOW_STATE_NORMAL: - return mojom::WindowStateType::NORMAL; + return WindowStateType::kNormal; case ui::SHOW_STATE_MINIMIZED: - return mojom::WindowStateType::MINIMIZED; + return WindowStateType::kMinimized; case ui::SHOW_STATE_MAXIMIZED: - return mojom::WindowStateType::MAXIMIZED; + return WindowStateType::kMaximized; case ui::SHOW_STATE_INACTIVE: - return mojom::WindowStateType::INACTIVE; + return WindowStateType::kInactive; case ui::SHOW_STATE_FULLSCREEN: - return mojom::WindowStateType::FULLSCREEN; + return WindowStateType::kFullscreen; case ui::SHOW_STATE_END: NOTREACHED(); - return mojom::WindowStateType::DEFAULT; + return WindowStateType::kDefault; } } -ui::WindowShowState ToWindowShowState(mojom::WindowStateType type) { +ui::WindowShowState ToWindowShowState(WindowStateType type) { switch (type) { - case mojom::WindowStateType::DEFAULT: + case WindowStateType::kDefault: return ui::SHOW_STATE_DEFAULT; - case mojom::WindowStateType::NORMAL: - case mojom::WindowStateType::RIGHT_SNAPPED: - case mojom::WindowStateType::LEFT_SNAPPED: - case mojom::WindowStateType::AUTO_POSITIONED: - case mojom::WindowStateType::PIP: + case WindowStateType::kNormal: + case WindowStateType::kRightSnapped: + case WindowStateType::kLeftSnapped: + case WindowStateType::kAutoPositioned: + case WindowStateType::kPip: return ui::SHOW_STATE_NORMAL; - case mojom::WindowStateType::MINIMIZED: + case WindowStateType::kMinimized: return ui::SHOW_STATE_MINIMIZED; - case mojom::WindowStateType::MAXIMIZED: + case WindowStateType::kMaximized: return ui::SHOW_STATE_MAXIMIZED; - case mojom::WindowStateType::INACTIVE: + case WindowStateType::kInactive: return ui::SHOW_STATE_INACTIVE; - case mojom::WindowStateType::FULLSCREEN: - case mojom::WindowStateType::PINNED: - case mojom::WindowStateType::TRUSTED_PINNED: + case WindowStateType::kFullscreen: + case WindowStateType::kPinned: + case WindowStateType::kTrustedPinned: return ui::SHOW_STATE_FULLSCREEN; } NOTREACHED(); return ui::SHOW_STATE_DEFAULT; } -bool IsFullscreenOrPinnedWindowStateType(mojom::WindowStateType type) { - return type == mojom::WindowStateType::FULLSCREEN || - type == mojom::WindowStateType::PINNED || - type == mojom::WindowStateType::TRUSTED_PINNED; +bool IsFullscreenOrPinnedWindowStateType(WindowStateType type) { + return type == WindowStateType::kFullscreen || + type == WindowStateType::kPinned || + type == WindowStateType::kTrustedPinned; } -bool IsMaximizedOrFullscreenOrPinnedWindowStateType( - mojom::WindowStateType type) { - return type == mojom::WindowStateType::MAXIMIZED || +bool IsMaximizedOrFullscreenOrPinnedWindowStateType(WindowStateType type) { + return type == WindowStateType::kMaximized || IsFullscreenOrPinnedWindowStateType(type); } -bool IsMinimizedWindowStateType(mojom::WindowStateType type) { - return type == mojom::WindowStateType::MINIMIZED; +bool IsMinimizedWindowStateType(WindowStateType type) { + return type == WindowStateType::kMinimized; } bool IsValidWindowStateType(int64_t value) { - return value == int64_t(mojom::WindowStateType::DEFAULT) || - value == int64_t(mojom::WindowStateType::NORMAL) || - value == int64_t(mojom::WindowStateType::MINIMIZED) || - value == int64_t(mojom::WindowStateType::MAXIMIZED) || - value == int64_t(mojom::WindowStateType::INACTIVE) || - value == int64_t(mojom::WindowStateType::FULLSCREEN) || - value == int64_t(mojom::WindowStateType::LEFT_SNAPPED) || - value == int64_t(mojom::WindowStateType::RIGHT_SNAPPED) || - value == int64_t(mojom::WindowStateType::AUTO_POSITIONED) || - value == int64_t(mojom::WindowStateType::PINNED) || - value == int64_t(mojom::WindowStateType::TRUSTED_PINNED) || - value == int64_t(mojom::WindowStateType::PIP); + return value == int64_t(WindowStateType::kDefault) || + value == int64_t(WindowStateType::kNormal) || + value == int64_t(WindowStateType::kMinimized) || + value == int64_t(WindowStateType::kMaximized) || + value == int64_t(WindowStateType::kInactive) || + value == int64_t(WindowStateType::kFullscreen) || + value == int64_t(WindowStateType::kLeftSnapped) || + value == int64_t(WindowStateType::kRightSnapped) || + value == int64_t(WindowStateType::kAutoPositioned) || + value == int64_t(WindowStateType::kPinned) || + value == int64_t(WindowStateType::kTrustedPinned) || + value == int64_t(WindowStateType::kPip); } } // namespace ash
diff --git a/ash/public/cpp/window_state_type.h b/ash/public/cpp/window_state_type.h index 8f019aeb..dc1619b 100644 --- a/ash/public/cpp/window_state_type.h +++ b/ash/public/cpp/window_state_type.h
@@ -6,34 +6,65 @@ #define ASH_PUBLIC_CPP_WINDOW_STATE_TYPE_H_ #include <cstdint> +#include <ostream> #include "ash/public/cpp/ash_public_export.h" #include "ui/base/ui_base_types.h" namespace ash { -namespace mojom { -enum class WindowStateType; -} +// A superset of ui::WindowShowState. Ash has more states than the general +// ui::WindowShowState enum. These need to be communicated back to Chrome. +// The separate enum is defined here because we don't want to leak these type to +// ui/base until they're stable and we know for sure that they'll persist over +// time. +enum class WindowStateType { + // States which correspond to ui.mojom.ShowState. + kDefault, + kNormal, + kMinimized, + kMaximized, + kInactive, + kFullscreen, -// Utility functions to convert mojom::WindowStateType <-> ui::WindowShowState. + // Additional ash states. + kLeftSnapped, + kRightSnapped, + + // A window is in this state when it is automatically placed and + // sized by the window manager. (it's newly opened, or pushed to the side + // due to new window, for example). + kAutoPositioned, + + // A window is pinned on top of other windows with fullscreenized. + // Corresponding shelf should be hidden, also most of windows other than the + // pinned one should be hidden. + kPinned, + kTrustedPinned, + + // A window in Picture-in-Picture mode (PIP). + kPip, +}; + +ASH_PUBLIC_EXPORT std::ostream& operator<<(std::ostream& stream, + WindowStateType state); + +// Utility functions to convert WindowStateType <-> ui::WindowShowState. // Note: LEFT/RIGHT MAXIMIZED, AUTO_POSITIONED types will be lost when // converting to ui::WindowShowState. -ASH_PUBLIC_EXPORT mojom::WindowStateType ToWindowStateType( - ui::WindowShowState state); -ASH_PUBLIC_EXPORT ui::WindowShowState ToWindowShowState( - mojom::WindowStateType type); +ASH_PUBLIC_EXPORT WindowStateType ToWindowStateType(ui::WindowShowState state); +ASH_PUBLIC_EXPORT ui::WindowShowState ToWindowShowState(WindowStateType type); // Returns true if |type| is FULLSCREEN, PINNED, or TRUSTED_PINNED. ASH_PUBLIC_EXPORT bool IsFullscreenOrPinnedWindowStateType( - mojom::WindowStateType type); + WindowStateType type); // Returns true if |type| is MAXIMIZED, FULLSCREEN, PINNED, or TRUSTED_PINNED. ASH_PUBLIC_EXPORT bool IsMaximizedOrFullscreenOrPinnedWindowStateType( - mojom::WindowStateType type); + WindowStateType type); // Returns true if |type| is MINIMIZED. -ASH_PUBLIC_EXPORT bool IsMinimizedWindowStateType(mojom::WindowStateType type); +ASH_PUBLIC_EXPORT bool IsMinimizedWindowStateType(WindowStateType type); ASH_PUBLIC_EXPORT bool IsValidWindowStateType(int64_t value);
diff --git a/ash/public/interfaces/BUILD.gn b/ash/public/interfaces/BUILD.gn index 9a812ba..88d9afc 100644 --- a/ash/public/interfaces/BUILD.gn +++ b/ash/public/interfaces/BUILD.gn
@@ -50,7 +50,6 @@ "night_light_controller.mojom", "note_taking_controller.mojom", "pref_connector.mojom", - "process_creation_time_recorder.mojom", "shelf.mojom", "shelf_integration_test_api.mojom", "shutdown.mojom", @@ -64,7 +63,6 @@ "wallpaper.mojom", "window_pin_type.mojom", "window_properties.mojom", - "window_state_type.mojom", ] public_deps = [ @@ -105,7 +103,6 @@ "shell_test_api.test-mojom", "status_area_widget_test_api.test-mojom", "system_tray_test_api.test-mojom", - "time_to_first_present_recorder_test_api.test-mojom", ] deps = [ "//ash/public/interfaces:interfaces_internal",
diff --git a/ash/public/interfaces/process_creation_time_recorder.mojom b/ash/public/interfaces/process_creation_time_recorder.mojom deleted file mode 100644 index 9e13caf3..0000000 --- a/ash/public/interfaces/process_creation_time_recorder.mojom +++ /dev/null
@@ -1,12 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -module ash.mojom; - -import "mojo/public/mojom/base/time.mojom"; - -interface ProcessCreationTimeRecorder { - // Sets the time the main process was created at, used for logging metrics. - SetMainProcessCreationTime(mojo_base.mojom.TimeTicks start_time); -};
diff --git a/ash/public/interfaces/time_to_first_present_recorder_test_api.test-mojom b/ash/public/interfaces/time_to_first_present_recorder_test_api.test-mojom deleted file mode 100644 index a4f0c02..0000000 --- a/ash/public/interfaces/time_to_first_present_recorder_test_api.test-mojom +++ /dev/null
@@ -1,14 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -module ash.mojom; - -import "mojo/public/mojom/base/time.mojom"; - -// Used to test internal state of TimeToFirstPresentRecorder. -interface TimeToFirstPresentRecorderTestApi { - // Returns the time between process creation and the first pixels shown on - // screen. - GetProcessCreationToFirstPresentTime() => (mojo_base.mojom.TimeDelta delta); -};
diff --git a/ash/public/interfaces/window_properties.mojom b/ash/public/interfaces/window_properties.mojom index f488089..fa05ba6 100644 --- a/ash/public/interfaces/window_properties.mojom +++ b/ash/public/interfaces/window_properties.mojom
@@ -56,9 +56,6 @@ // If true, the window is currently showing in overview mode. const string kIsShowingInOverview_Property = "ash:is-showing-in-overview"; -// A property key to store the window state the window had before entering PIP. -const string kPrePipWindowStateType_Property = "ash:pre-pip-window-state-type"; - // A property key to store the address of the source window that the drag // originated from if the window is currently in tab-dragging process. const string kTabDraggingSourceWindow_Property =
diff --git a/ash/public/interfaces/window_state_type.mojom b/ash/public/interfaces/window_state_type.mojom deleted file mode 100644 index 8c2d4f5..0000000 --- a/ash/public/interfaces/window_state_type.mojom +++ /dev/null
@@ -1,41 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -module ash.mojom; - -// A superset of ui.mojom.ShowState. Ash has more states than the general -// ui::ShowState enum. These need to be communicated back to chrome. -// The separate enum is defined here because we don't want to leak -// these type to ui/base until they're stable and we know for sure -// that they'll persist over time. -enum WindowStateType { - // States which correspond to ui.mojom.ShowState. - DEFAULT, - NORMAL, - MINIMIZED, - MAXIMIZED, - INACTIVE, - FULLSCREEN, - - // Additional ash states. - LEFT_SNAPPED, - RIGHT_SNAPPED, - - // A window is in this state when it is automatically placed and - // sized by the window manager. (it's newly opened, or pushed to the side - // due to new window, for example). - AUTO_POSITIONED, - - // A window is pinned on top of other windows with fullscreenized. - // Corresponding shelf should be hidden, also most of windows other than the - // pinned one should be hidden. - PINNED, - TRUSTED_PINNED, - - // A window in Picture-in-Picture mode (PIP). - PIP, -}; - -// The window's extended state. Maps to ash::kWindowStateTypeKey. -const string kWindowStateType_Property = "ash:window-state-type";
diff --git a/ash/session/session_controller_impl.cc b/ash/session/session_controller_impl.cc index 9e0b73e..0d51b19 100644 --- a/ash/session/session_controller_impl.cc +++ b/ash/session/session_controller_impl.cc
@@ -31,7 +31,6 @@ #include "base/bind_helpers.h" #include "base/command_line.h" #include "base/logging.h" -#include "chromeos/constants/chromeos_switches.h" #include "components/account_id/account_id.h" #include "components/prefs/pref_registry_simple.h" #include "components/prefs/pref_service.h" @@ -45,32 +44,9 @@ namespace ash { -namespace { - -// Get the default session state. Default session state is ACTIVE when the -// process starts with a user session, i.e. the process has kLoginUser command -// line switch. This is needed because ash focus rules depends on whether -// session is blocked to pick an activatable window and chrome needs to create a -// focused browser window when starting with a user session (both in production -// and in tests). Using ACTIVE as default in this situation allows chrome to run -// without having to wait for session state to reach to ash. For other cases -// (oobe/login), there is only one login window. The login window always gets -// focus so default session state does not matter. Use UNKNOWN and wait for -// chrome to update ash for such cases. -SessionState GetDefaultSessionState() { - const bool start_with_user = - base::CommandLine::ForCurrentProcess()->HasSwitch( - chromeos::switches::kLoginUser); - return start_with_user ? SessionState::ACTIVE : SessionState::UNKNOWN; -} - -} // namespace - SessionControllerImpl::SessionControllerImpl( service_manager::Connector* connector) - : state_(GetDefaultSessionState()), - connector_(connector), - weak_ptr_factory_(this) {} + : connector_(connector) {} SessionControllerImpl::~SessionControllerImpl() { // Abort pending start lock request.
diff --git a/ash/session/session_controller_impl.h b/ash/session/session_controller_impl.h index 0d12f172..6688309 100644 --- a/ash/session/session_controller_impl.h +++ b/ash/session/session_controller_impl.h
@@ -270,7 +270,7 @@ bool is_running_in_app_mode_ = false; bool is_demo_session_ = false; AddUserSessionPolicy add_user_session_policy_ = AddUserSessionPolicy::ALLOWED; - session_manager::SessionState state_; + session_manager::SessionState state_ = session_manager::SessionState::UNKNOWN; // Cached user session info sorted by the order from SetUserSessionOrder. // Currently the session manager code (chrome) sets a LRU order with the @@ -324,7 +324,7 @@ std::map<AccountId, std::unique_ptr<PrefService>> per_user_prefs_; PrefService* last_active_user_prefs_ = nullptr; - base::WeakPtrFactory<SessionControllerImpl> weak_ptr_factory_; + base::WeakPtrFactory<SessionControllerImpl> weak_ptr_factory_{this}; DISALLOW_COPY_AND_ASSIGN(SessionControllerImpl); };
diff --git a/ash/shell.cc b/ash/shell.cc index eaf0f6c..138fa02 100644 --- a/ash/shell.cc +++ b/ash/shell.cc
@@ -58,7 +58,6 @@ #include "ash/host/ash_window_tree_host_init_params.h" #include "ash/ime/ime_controller.h" #include "ash/ime/ime_engine_factory_registry.h" -#include "ash/ime/ime_focus_handler.h" #include "ash/keyboard/ash_keyboard_controller.h" #include "ash/kiosk_next/kiosk_next_shell_controller.h" #include "ash/laser/laser_pointer_controller.h" @@ -142,7 +141,6 @@ #include "ash/wm/lock_state_controller.h" #include "ash/wm/mru_window_tracker.h" #include "ash/wm/native_cursor_manager_ash.h" -#include "ash/wm/non_client_frame_controller.h" #include "ash/wm/overlay_event_filter.h" #include "ash/wm/overview/overview_controller.h" #include "ash/wm/resize_shadow_controller.h" @@ -867,9 +865,6 @@ // Similarly for DockedMagnifierController. docked_magnifier_controller_ = nullptr; - // Must be released before |focus_controller_|. - ime_focus_handler_.reset(); - // Stop observing window activation changes before closing all windows. focus_controller_->RemoveObserver(this); @@ -951,17 +946,6 @@ std::unique_ptr<base::Value> initial_display_prefs, std::unique_ptr<keyboard::KeyboardUIFactory> keyboard_ui_factory, scoped_refptr<dbus::Bus> dbus_bus) { - if (::features::IsSingleProcessMash()) { - // In SingleProcessMash mode ScreenMus is not created, which means Ash needs - // to set the WindowManagerFrameValues. - views::WindowManagerFrameValues frame_values; - frame_values.normal_insets = frame_values.maximized_insets = - NonClientFrameController::GetPreferredClientAreaInsets(); - frame_values.max_title_bar_button_width = - NonClientFrameController::GetMaxTitleBarButtonWidth(); - views::WindowManagerFrameValues::SetInstance(frame_values); - } - if (!::features::IsMultiProcessMash()) { // DBus clients only needed in Ash. For MultiProcessMash these are // initialized in AshService::InitializeDBusClients. @@ -1257,11 +1241,6 @@ // is started. display_manager_->CreateMirrorWindowAsyncIfAny(); - if (!::features::IsMultiProcessMash()) { - ime_focus_handler_ = std::make_unique<ImeFocusHandler>( - focus_controller(), window_tree_host_manager_->input_method()); - } - if (base::FeatureList::IsEnabled(features::kMediaSessionNotification)) { media_notification_controller_ = std::make_unique<MediaNotificationController>(connector_);
diff --git a/ash/shell.h b/ash/shell.h index d9f3320..e561b7b 100644 --- a/ash/shell.h +++ b/ash/shell.h
@@ -131,7 +131,6 @@ class HomeScreenController; class ImeController; class ImeEngineFactoryRegistry; -class ImeFocusHandler; class ImmersiveContext; class KeyAccessibilityEnabler; class KeyboardBrightnessControlDelegate; @@ -725,7 +724,6 @@ std::unique_ptr<HomeScreenController> home_screen_controller_; std::unique_ptr<ImeController> ime_controller_; std::unique_ptr<ImeEngineFactoryRegistry> ime_engine_factory_registry_; - std::unique_ptr<ImeFocusHandler> ime_focus_handler_; std::unique_ptr<ImmersiveContext> immersive_context_; std::unique_ptr<KeyboardBrightnessControlDelegate> keyboard_brightness_control_delegate_;
diff --git a/ash/shell/content/client/shell_content_browser_client.cc b/ash/shell/content/client/shell_content_browser_client.cc index 8b4ce62..4b5ec277 100644 --- a/ash/shell/content/client/shell_content_browser_client.cc +++ b/ash/shell/content/client/shell_content_browser_client.cc
@@ -30,7 +30,6 @@ #include "services/ws/ime/test_ime_driver/public/cpp/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"
diff --git a/ash/shell_test_api.h b/ash/shell_test_api.h index b8256c7..1f83fa9 100644 --- a/ash/shell_test_api.h +++ b/ash/shell_test_api.h
@@ -9,7 +9,6 @@ #include "ash/public/interfaces/shell_test_api.test-mojom.h" #include "base/macros.h" -#include "services/ws/common/types.h" class PrefService;
diff --git a/ash/test/ash_test_base.cc b/ash/test/ash_test_base.cc index 5d717d5..83bbea9 100644 --- a/ash/test/ash_test_base.cc +++ b/ash/test/ash_test_base.cc
@@ -30,7 +30,6 @@ #include "ash/test_shell_delegate.h" #include "ash/utility/screenshot_controller.h" #include "ash/window_factory.h" -#include "ash/wm/top_level_window_factory.h" #include "ash/wm/window_positioner.h" #include "ash/wm/work_area_insets.h" #include "base/memory/ptr_util.h"
diff --git a/ash/test/ash_test_helper.cc b/ash/test/ash_test_helper.cc index 1bec61e..39aafc83 100644 --- a/ash/test/ash_test_helper.cc +++ b/ash/test/ash_test_helper.cc
@@ -25,7 +25,6 @@ #include "ash/test_shell_delegate.h" #include "ash/wm/overview/overview_controller.h" #include "base/bind.h" -#include "base/guid.h" #include "base/run_loop.h" #include "base/strings/string_split.h" #include "base/token.h" @@ -38,11 +37,6 @@ #include "components/prefs/testing_pref_service.h" #include "device/bluetooth/bluetooth_adapter_factory.h" #include "device/bluetooth/dbus/bluez_dbus_manager.h" -#include "mojo/public/cpp/bindings/binding_set.h" -#include "mojo/public/cpp/bindings/interface_request.h" -#include "services/service_manager/public/cpp/bind_source_info.h" -#include "services/ws/public/mojom/constants.mojom.h" -#include "services/ws/public/mojom/gpu.mojom.h" #include "ui/aura/env.h" #include "ui/aura/input_state_lookup.h" #include "ui/aura/test/env_test_helper.h"
diff --git a/ash/utility/screenshot_controller.cc b/ash/utility/screenshot_controller.cc index 7ecec51..99a2a86 100644 --- a/ash/utility/screenshot_controller.cc +++ b/ash/utility/screenshot_controller.cc
@@ -13,7 +13,6 @@ #include "ash/screenshot_delegate.h" #include "ash/shell.h" #include "ash/wm/window_util.h" -#include "services/ws/window_service.h" #include "ui/aura/client/capture_client.h" #include "ui/aura/client/screen_position_client.h" #include "ui/aura/window_targeter.h" @@ -75,8 +74,6 @@ !window->delegate()) { return false; } - if (ws::WindowService::IsProxyWindow(window)) - return ws::WindowService::IsTopLevelWindow(window); return true; }
diff --git a/ash/utility/screenshot_controller_unittest.cc b/ash/utility/screenshot_controller_unittest.cc index cf0a702..c08f0ff 100644 --- a/ash/utility/screenshot_controller_unittest.cc +++ b/ash/utility/screenshot_controller_unittest.cc
@@ -14,7 +14,6 @@ #include "ash/test_screenshot_delegate.h" #include "ash/wm/window_util.h" #include "base/run_loop.h" -#include "services/ws/window_tree_test_helper.h" #include "ui/aura/env.h" #include "ui/aura/window_event_dispatcher.h" #include "ui/base/cursor/cursor.h"
diff --git a/ash/wm/always_on_top_controller.cc b/ash/wm/always_on_top_controller.cc index 3d7f1a1..92b1798 100644 --- a/ash/wm/always_on_top_controller.cc +++ b/ash/wm/always_on_top_controller.cc
@@ -122,7 +122,7 @@ void AlwaysOnTopController::OnPreWindowStateTypeChange( wm::WindowState* window_state, - mojom::WindowStateType old_type) { + WindowStateType old_type) { ReparentWindow(window_state->window()); }
diff --git a/ash/wm/always_on_top_controller.h b/ash/wm/always_on_top_controller.h index 8ee362ae..0a4e342 100644 --- a/ash/wm/always_on_top_controller.h +++ b/ash/wm/always_on_top_controller.h
@@ -49,7 +49,7 @@ // Overridden from wm::WindowStateObserver: void OnPreWindowStateTypeChange(wm::WindowState* window_state, - mojom::WindowStateType old_type) override; + WindowStateType old_type) override; aura::Window* always_on_top_container_; aura::Window* pip_container_;
diff --git a/ash/wm/base_state.cc b/ash/wm/base_state.cc index d062c929e..c6e5c49 100644 --- a/ash/wm/base_state.cc +++ b/ash/wm/base_state.cc
@@ -20,7 +20,7 @@ namespace ash { namespace wm { -BaseState::BaseState(mojom::WindowStateType initial_state_type) +BaseState::BaseState(WindowStateType initial_state_type) : state_type_(initial_state_type) {} BaseState::~BaseState() = default; @@ -55,34 +55,33 @@ HandleTransitionEvents(window_state, event); } -mojom::WindowStateType BaseState::GetType() const { +WindowStateType BaseState::GetType() const { return state_type_; } // static -mojom::WindowStateType BaseState::GetStateForTransitionEvent( - const WMEvent* event) { +WindowStateType BaseState::GetStateForTransitionEvent(const WMEvent* event) { switch (event->type()) { case WM_EVENT_NORMAL: - return mojom::WindowStateType::NORMAL; + return WindowStateType::kNormal; case WM_EVENT_MAXIMIZE: - return mojom::WindowStateType::MAXIMIZED; + return WindowStateType::kMaximized; case WM_EVENT_MINIMIZE: - return mojom::WindowStateType::MINIMIZED; + return WindowStateType::kMinimized; case WM_EVENT_FULLSCREEN: - return mojom::WindowStateType::FULLSCREEN; + return WindowStateType::kFullscreen; case WM_EVENT_SNAP_LEFT: - return mojom::WindowStateType::LEFT_SNAPPED; + return WindowStateType::kLeftSnapped; case WM_EVENT_SNAP_RIGHT: - return mojom::WindowStateType::RIGHT_SNAPPED; + return WindowStateType::kRightSnapped; case WM_EVENT_SHOW_INACTIVE: - return mojom::WindowStateType::INACTIVE; + return WindowStateType::kInactive; case WM_EVENT_PIN: - return mojom::WindowStateType::PINNED; + return WindowStateType::kPinned; case WM_EVENT_PIP: - return mojom::WindowStateType::PIP; + return WindowStateType::kPip; case WM_EVENT_TRUSTED_PIN: - return mojom::WindowStateType::TRUSTED_PINNED; + return WindowStateType::kTrustedPinned; default: break; } @@ -94,7 +93,7 @@ if (event->IsBoundsEvent()) NOTREACHED() << "Can't get the state for Bounds event:" << event->type(); #endif - return mojom::WindowStateType::NORMAL; + return WindowStateType::kNormal; } // static @@ -126,14 +125,13 @@ // static void BaseState::CycleSnap(WindowState* window_state, WMEventType event) { - mojom::WindowStateType desired_snap_state = - event == WM_EVENT_CYCLE_SNAP_LEFT ? mojom::WindowStateType::LEFT_SNAPPED - : mojom::WindowStateType::RIGHT_SNAPPED; + WindowStateType desired_snap_state = event == WM_EVENT_CYCLE_SNAP_LEFT + ? WindowStateType::kLeftSnapped + : WindowStateType::kRightSnapped; if (window_state->CanSnap() && window_state->GetStateType() != desired_snap_state) { - const wm::WMEvent event(desired_snap_state == - mojom::WindowStateType::LEFT_SNAPPED + const wm::WMEvent event(desired_snap_state == WindowStateType::kLeftSnapped ? wm::WM_EVENT_SNAP_LEFT : wm::WM_EVENT_SNAP_RIGHT); window_state->OnWMEvent(&event); @@ -148,21 +146,20 @@ ::wm::WINDOW_ANIMATION_TYPE_BOUNCE); } -void BaseState::UpdateMinimizedState( - WindowState* window_state, - mojom::WindowStateType previous_state_type) { +void BaseState::UpdateMinimizedState(WindowState* window_state, + WindowStateType previous_state_type) { aura::Window* window = window_state->window(); if (window_state->IsMinimized()) { // Save the previous show state when it is not minimized so that we can // correctly restore it after exiting the minimized mode. if (!IsMinimizedWindowStateType(previous_state_type)) { // We must not save PIP to |kPreMinimizedShowStateKey|. - if (previous_state_type != mojom::WindowStateType::PIP) + if (previous_state_type != WindowStateType::kPip) window->SetProperty(aura::client::kPreMinimizedShowStateKey, ToWindowShowState(previous_state_type)); // We must not save MINIMIZED to |kPreMinimizedShowStateKey|. else if (window->GetProperty(ash::kPrePipWindowStateTypeKey) != - mojom::WindowStateType::MINIMIZED) + WindowStateType::kMinimized) window->SetProperty(aura::client::kPreMinimizedShowStateKey, ToWindowShowState(window->GetProperty( ash::kPrePipWindowStateTypeKey))); @@ -171,7 +168,7 @@ // don't exit when they are dismissed, they just go back to being a regular // app, but minimized. ::wm::SetWindowVisibilityAnimationType( - window, previous_state_type == mojom::WindowStateType::PIP + window, previous_state_type == WindowStateType::kPip ? WINDOW_VISIBILITY_ANIMATION_TYPE_FADE_IN_SLIDE_OUT : WINDOW_VISIBILITY_ANIMATION_TYPE_MINIMIZE); @@ -193,16 +190,16 @@ gfx::Rect BaseState::GetSnappedWindowBoundsInParent( aura::Window* window, - const mojom::WindowStateType state_type) { + const WindowStateType state_type) { gfx::Rect bounds_in_parent; if (ShouldAllowSplitView()) { bounds_in_parent = Shell::Get()->split_view_controller()->GetSnappedWindowBoundsInParent( - window, (state_type == mojom::WindowStateType::LEFT_SNAPPED) + window, (state_type == WindowStateType::kLeftSnapped) ? SplitViewController::LEFT : SplitViewController::RIGHT); } else { - bounds_in_parent = (state_type == mojom::WindowStateType::LEFT_SNAPPED) + bounds_in_parent = (state_type == WindowStateType::kLeftSnapped) ? GetDefaultLeftSnappedWindowBoundsInParent(window) : GetDefaultRightSnappedWindowBoundsInParent(window); }
diff --git a/ash/wm/base_state.h b/ash/wm/base_state.h index d85d4c9..5e6dfb6b9 100644 --- a/ash/wm/base_state.h +++ b/ash/wm/base_state.h
@@ -19,17 +19,16 @@ // BaseState implements the common framework for WindowState::State. class BaseState : public WindowState::State { public: - explicit BaseState(mojom::WindowStateType initial_state_type); + explicit BaseState(WindowStateType initial_state_type); ~BaseState() override; // WindowState::State: void OnWMEvent(WindowState* window_state, const WMEvent* event) override; - mojom::WindowStateType GetType() const override; + WindowStateType GetType() const override; protected: // Returns the WindowStateType corresponds to the WMEvent type. - static mojom::WindowStateType GetStateForTransitionEvent( - const WMEvent* event); + static WindowStateType GetStateForTransitionEvent(const WMEvent* event); static void CenterWindow(WindowState* window_state); static void CycleSnap(WindowState* window_state, WMEventType event); @@ -53,15 +52,14 @@ // Shows/Hides window when minimized state changes. void UpdateMinimizedState(WindowState* window_state, - mojom::WindowStateType previous_state_type); + WindowStateType previous_state_type); // Returns the window bounds for snapped window state. - gfx::Rect GetSnappedWindowBoundsInParent( - aura::Window* window, - const mojom::WindowStateType state_type); + gfx::Rect GetSnappedWindowBoundsInParent(aura::Window* window, + const WindowStateType state_type); // The current type of the window. - mojom::WindowStateType state_type_; + WindowStateType state_type_; private: DISALLOW_COPY_AND_ASSIGN(BaseState);
diff --git a/ash/wm/client_controlled_state.cc b/ash/wm/client_controlled_state.cc index d681cd8..2175d765 100644 --- a/ash/wm/client_controlled_state.cc +++ b/ash/wm/client_controlled_state.cc
@@ -43,8 +43,7 @@ } ClientControlledState::ClientControlledState(std::unique_ptr<Delegate> delegate) - : BaseState(mojom::WindowStateType::DEFAULT), - delegate_(std::move(delegate)) {} + : BaseState(WindowStateType::kDefault), delegate_(std::move(delegate)) {} ClientControlledState::~ClientControlledState() = default; @@ -61,9 +60,9 @@ Shell::Get()->screen_pinning_controller()->IsPinned()) { return; } - mojom::WindowStateType next_state_type = GetStateForTransitionEvent(event); + WindowStateType next_state_type = GetStateForTransitionEvent(event); delegate_->HandleWindowStateRequest(window_state, next_state_type); - mojom::WindowStateType old_state_type = state_type_; + WindowStateType old_state_type = state_type_; bool was_pinned = window_state->IsPinned(); bool was_trusted_pinned = window_state->IsTrustedPinned(); @@ -86,7 +85,7 @@ case WM_EVENT_FULLSCREEN: { // Reset window state window_state->UpdateWindowPropertiesFromStateType(); - mojom::WindowStateType next_state = GetStateForTransitionEvent(event); + WindowStateType next_state = GetStateForTransitionEvent(event); VLOG(1) << "Processing State Transtion: event=" << event->type() << ", state=" << state_type_ << ", next_state=" << next_state; // Then ask delegate to handle the window state change. @@ -98,14 +97,13 @@ if (window_state->CanSnap()) { // Get the desired window bounds for the snap state. gfx::Rect bounds = GetSnappedWindowBoundsInParent( - window_state->window(), - event->type() == WM_EVENT_SNAP_LEFT - ? mojom::WindowStateType::LEFT_SNAPPED - : mojom::WindowStateType::RIGHT_SNAPPED); + window_state->window(), event->type() == WM_EVENT_SNAP_LEFT + ? WindowStateType::kLeftSnapped + : WindowStateType::kRightSnapped); window_state->set_bounds_changed_by_user(true); window_state->UpdateWindowPropertiesFromStateType(); - mojom::WindowStateType next_state = GetStateForTransitionEvent(event); + WindowStateType next_state = GetStateForTransitionEvent(event); VLOG(1) << "Processing State Transtion: event=" << event->type() << ", state=" << state_type_ << ", next_state=" << next_state; @@ -230,14 +228,13 @@ delegate_.reset(); } -bool ClientControlledState::EnterNextState( - WindowState* window_state, - mojom::WindowStateType next_state_type) { +bool ClientControlledState::EnterNextState(WindowState* window_state, + WindowStateType next_state_type) { // Do nothing if we're already in the same state, or delegate has already // been deleted. if (state_type_ == next_state_type || !delegate_) return false; - mojom::WindowStateType previous_state_type = state_type_; + WindowStateType previous_state_type = state_type_; state_type_ = next_state_type; window_state->UpdateWindowPropertiesFromStateType(); @@ -252,10 +249,10 @@ window_state->NotifyPostStateTypeChange(previous_state_type); - if (next_state_type == mojom::WindowStateType::PINNED || - previous_state_type == mojom::WindowStateType::PINNED || - next_state_type == mojom::WindowStateType::TRUSTED_PINNED || - previous_state_type == mojom::WindowStateType::TRUSTED_PINNED) { + if (next_state_type == WindowStateType::kPinned || + previous_state_type == WindowStateType::kPinned || + next_state_type == WindowStateType::kTrustedPinned || + previous_state_type == WindowStateType::kTrustedPinned) { Shell::Get()->screen_pinning_controller()->SetPinnedWindow( window_state->window()); }
diff --git a/ash/wm/client_controlled_state.h b/ash/wm/client_controlled_state.h index d1bf73c4..b5dac5d 100644 --- a/ash/wm/client_controlled_state.h +++ b/ash/wm/client_controlled_state.h
@@ -33,15 +33,14 @@ // Handles the state change of |window_state| to |requested_state|. // Delegate may decide to ignore the state change, proceed with the state // change, or can move to a different state. - virtual void HandleWindowStateRequest( - WindowState* window_state, - mojom::WindowStateType requested_state) = 0; + virtual void HandleWindowStateRequest(WindowState* window_state, + WindowStateType requested_state) = 0; // Handles the bounds change request for |window_state|. The bounds change // might come from a state change request |requested_state| (currently it // should only be a snapped window state). Delegate may choose to ignore the // request, set the given bounds, or set the different bounds. virtual void HandleBoundsRequest(WindowState* window_state, - mojom::WindowStateType requested_state, + WindowStateType requested_state, const gfx::Rect& requested_bounds) = 0; }; @@ -95,7 +94,7 @@ // within the same desktop mode. Returns true if the state has changed, or // false otherwise. bool EnterNextState(wm::WindowState* window_state, - mojom::WindowStateType next_state_type); + WindowStateType next_state_type); private: std::unique_ptr<Delegate> delegate_;
diff --git a/ash/wm/client_controlled_state_unittest.cc b/ash/wm/client_controlled_state_unittest.cc index 4cbaa0d..d5dc56da 100644 --- a/ash/wm/client_controlled_state_unittest.cc +++ b/ash/wm/client_controlled_state_unittest.cc
@@ -31,41 +31,41 @@ ~TestClientControlledStateDelegate() override = default; void HandleWindowStateRequest(WindowState* window_state, - mojom::WindowStateType next_state) override { + WindowStateType next_state) override { EXPECT_FALSE(deleted_); old_state_ = window_state->GetStateType(); new_state_ = next_state; } void HandleBoundsRequest(WindowState* window_state, - ash::mojom::WindowStateType requested_state, + ash::WindowStateType requested_state, const gfx::Rect& bounds) override { requested_bounds_ = bounds; if (requested_state != window_state->GetStateType()) { - DCHECK(requested_state == ash::mojom::WindowStateType::LEFT_SNAPPED || - requested_state == ash::mojom::WindowStateType::RIGHT_SNAPPED); + DCHECK(requested_state == ash::WindowStateType::kLeftSnapped || + requested_state == ash::WindowStateType::kRightSnapped); old_state_ = window_state->GetStateType(); new_state_ = requested_state; } } - mojom::WindowStateType old_state() const { return old_state_; } + WindowStateType old_state() const { return old_state_; } - mojom::WindowStateType new_state() const { return new_state_; } + WindowStateType new_state() const { return new_state_; } const gfx::Rect& requested_bounds() const { return requested_bounds_; } void Reset() { - old_state_ = mojom::WindowStateType::DEFAULT; - new_state_ = mojom::WindowStateType::DEFAULT; + old_state_ = WindowStateType::kDefault; + new_state_ = WindowStateType::kDefault; requested_bounds_.SetRect(0, 0, 0, 0); } void mark_as_deleted() { deleted_ = true; } private: - mojom::WindowStateType old_state_ = mojom::WindowStateType::DEFAULT; - mojom::WindowStateType new_state_ = mojom::WindowStateType::DEFAULT; + WindowStateType old_state_ = WindowStateType::kDefault; + WindowStateType new_state_ = WindowStateType::kDefault; gfx::Rect requested_bounds_; bool deleted_ = false; @@ -158,8 +158,8 @@ // The state shouldn't be updated until EnterToNextState is called. EXPECT_FALSE(widget()->IsMaximized()); EXPECT_EQ(kInitialBounds, widget()->GetWindowBoundsInScreen()); - EXPECT_EQ(mojom::WindowStateType::DEFAULT, delegate()->old_state()); - EXPECT_EQ(mojom::WindowStateType::MAXIMIZED, delegate()->new_state()); + EXPECT_EQ(WindowStateType::kDefault, delegate()->old_state()); + EXPECT_EQ(WindowStateType::kMaximized, delegate()->new_state()); // Now enters the new state. state()->EnterNextState(window_state(), delegate()->new_state()); EXPECT_TRUE(widget()->IsMaximized()); @@ -174,8 +174,8 @@ widget()->Restore(); EXPECT_TRUE(widget()->IsMaximized()); EXPECT_EQ(kInitialBounds, widget()->GetWindowBoundsInScreen()); - EXPECT_EQ(mojom::WindowStateType::MAXIMIZED, delegate()->old_state()); - EXPECT_EQ(mojom::WindowStateType::NORMAL, delegate()->new_state()); + EXPECT_EQ(WindowStateType::kMaximized, delegate()->old_state()); + EXPECT_EQ(WindowStateType::kNormal, delegate()->new_state()); state()->EnterNextState(window_state(), delegate()->new_state()); EXPECT_FALSE(widget()->IsMaximized()); EXPECT_EQ(kInitialBounds, widget()->GetWindowBoundsInScreen()); @@ -185,8 +185,8 @@ widget()->Minimize(); EXPECT_FALSE(widget()->IsMinimized()); EXPECT_EQ(kInitialBounds, widget()->GetWindowBoundsInScreen()); - EXPECT_EQ(mojom::WindowStateType::DEFAULT, delegate()->old_state()); - EXPECT_EQ(mojom::WindowStateType::MINIMIZED, delegate()->new_state()); + EXPECT_EQ(WindowStateType::kDefault, delegate()->old_state()); + EXPECT_EQ(WindowStateType::kMinimized, delegate()->new_state()); state()->EnterNextState(window_state(), delegate()->new_state()); EXPECT_TRUE(widget()->IsMinimized()); EXPECT_EQ(kInitialBounds, widget()->GetWindowBoundsInScreen()); @@ -194,8 +194,8 @@ widget()->Restore(); EXPECT_TRUE(widget()->IsMinimized()); EXPECT_EQ(kInitialBounds, widget()->GetWindowBoundsInScreen()); - EXPECT_EQ(mojom::WindowStateType::MINIMIZED, delegate()->old_state()); - EXPECT_EQ(mojom::WindowStateType::NORMAL, delegate()->new_state()); + EXPECT_EQ(WindowStateType::kMinimized, delegate()->old_state()); + EXPECT_EQ(WindowStateType::kNormal, delegate()->new_state()); state()->EnterNextState(window_state(), delegate()->new_state()); EXPECT_FALSE(widget()->IsMinimized()); EXPECT_EQ(kInitialBounds, widget()->GetWindowBoundsInScreen()); @@ -204,8 +204,8 @@ widget()->Minimize(); EXPECT_FALSE(widget()->IsMinimized()); EXPECT_EQ(kInitialBounds, widget()->GetWindowBoundsInScreen()); - EXPECT_EQ(mojom::WindowStateType::NORMAL, delegate()->old_state()); - EXPECT_EQ(mojom::WindowStateType::MINIMIZED, delegate()->new_state()); + EXPECT_EQ(WindowStateType::kNormal, delegate()->old_state()); + EXPECT_EQ(WindowStateType::kMinimized, delegate()->new_state()); state()->EnterNextState(window_state(), delegate()->new_state()); EXPECT_TRUE(widget()->IsMinimized()); EXPECT_EQ(kInitialBounds, widget()->GetWindowBoundsInScreen()); @@ -216,8 +216,8 @@ widget()->GetNativeWindow()->GetProperty( aura::client::kPreMinimizedShowStateKey)); EXPECT_EQ(kInitialBounds, widget()->GetWindowBoundsInScreen()); - EXPECT_EQ(mojom::WindowStateType::MINIMIZED, delegate()->old_state()); - EXPECT_EQ(mojom::WindowStateType::NORMAL, delegate()->new_state()); + EXPECT_EQ(WindowStateType::kMinimized, delegate()->old_state()); + EXPECT_EQ(WindowStateType::kNormal, delegate()->new_state()); state()->EnterNextState(window_state(), delegate()->new_state()); EXPECT_FALSE(widget()->IsMinimized()); EXPECT_EQ(kInitialBounds, widget()->GetWindowBoundsInScreen()); @@ -227,16 +227,16 @@ widget()->SetFullscreen(true); EXPECT_FALSE(widget()->IsFullscreen()); EXPECT_EQ(kInitialBounds, widget()->GetWindowBoundsInScreen()); - EXPECT_EQ(mojom::WindowStateType::DEFAULT, delegate()->old_state()); - EXPECT_EQ(mojom::WindowStateType::FULLSCREEN, delegate()->new_state()); + EXPECT_EQ(WindowStateType::kDefault, delegate()->old_state()); + EXPECT_EQ(WindowStateType::kFullscreen, delegate()->new_state()); state()->EnterNextState(window_state(), delegate()->new_state()); EXPECT_TRUE(widget()->IsFullscreen()); EXPECT_EQ(kInitialBounds, widget()->GetWindowBoundsInScreen()); widget()->SetFullscreen(false); EXPECT_TRUE(widget()->IsFullscreen()); - EXPECT_EQ(mojom::WindowStateType::FULLSCREEN, delegate()->old_state()); - EXPECT_EQ(mojom::WindowStateType::NORMAL, delegate()->new_state()); + EXPECT_EQ(WindowStateType::kFullscreen, delegate()->old_state()); + EXPECT_EQ(WindowStateType::kNormal, delegate()->new_state()); state()->EnterNextState(window_state(), delegate()->new_state()); EXPECT_FALSE(widget()->IsFullscreen()); EXPECT_EQ(kInitialBounds, widget()->GetWindowBoundsInScreen()); @@ -248,8 +248,8 @@ widget()->Maximize(); EXPECT_FALSE(widget()->IsMaximized()); EXPECT_EQ(kInitialBounds, widget()->GetWindowBoundsInScreen()); - EXPECT_EQ(mojom::WindowStateType::DEFAULT, delegate()->old_state()); - EXPECT_EQ(mojom::WindowStateType::MAXIMIZED, delegate()->new_state()); + EXPECT_EQ(WindowStateType::kDefault, delegate()->old_state()); + EXPECT_EQ(WindowStateType::kMaximized, delegate()->new_state()); state()->EnterNextState(window_state(), delegate()->new_state()); EXPECT_TRUE(widget()->IsMaximized()); EXPECT_EQ(kInitialBounds, widget()->GetWindowBoundsInScreen()); @@ -257,24 +257,24 @@ widget()->SetFullscreen(true); EXPECT_TRUE(widget()->IsMaximized()); EXPECT_EQ(kInitialBounds, widget()->GetWindowBoundsInScreen()); - EXPECT_EQ(mojom::WindowStateType::MAXIMIZED, delegate()->old_state()); - EXPECT_EQ(mojom::WindowStateType::FULLSCREEN, delegate()->new_state()); + EXPECT_EQ(WindowStateType::kMaximized, delegate()->old_state()); + EXPECT_EQ(WindowStateType::kFullscreen, delegate()->new_state()); state()->EnterNextState(window_state(), delegate()->new_state()); EXPECT_TRUE(widget()->IsFullscreen()); EXPECT_EQ(kInitialBounds, widget()->GetWindowBoundsInScreen()); widget()->SetFullscreen(false); EXPECT_TRUE(widget()->IsFullscreen()); - EXPECT_EQ(mojom::WindowStateType::FULLSCREEN, delegate()->old_state()); - EXPECT_EQ(mojom::WindowStateType::MAXIMIZED, delegate()->new_state()); + EXPECT_EQ(WindowStateType::kFullscreen, delegate()->old_state()); + EXPECT_EQ(WindowStateType::kMaximized, delegate()->new_state()); state()->EnterNextState(window_state(), delegate()->new_state()); EXPECT_TRUE(widget()->IsMaximized()); EXPECT_EQ(kInitialBounds, widget()->GetWindowBoundsInScreen()); widget()->Restore(); EXPECT_TRUE(widget()->IsMaximized()); - EXPECT_EQ(mojom::WindowStateType::MAXIMIZED, delegate()->old_state()); - EXPECT_EQ(mojom::WindowStateType::NORMAL, delegate()->new_state()); + EXPECT_EQ(WindowStateType::kMaximized, delegate()->old_state()); + EXPECT_EQ(WindowStateType::kNormal, delegate()->new_state()); state()->EnterNextState(window_state(), delegate()->new_state()); EXPECT_FALSE(widget()->IsMaximized()); EXPECT_EQ(kInitialBounds, widget()->GetWindowBoundsInScreen()); @@ -291,8 +291,8 @@ // Client is responsible to handle workspace change, so // no action should be taken. EXPECT_EQ(kInitialBounds, widget()->GetWindowBoundsInScreen()); - EXPECT_EQ(mojom::WindowStateType::DEFAULT, delegate()->old_state()); - EXPECT_EQ(mojom::WindowStateType::DEFAULT, delegate()->new_state()); + EXPECT_EQ(WindowStateType::kDefault, delegate()->old_state()); + EXPECT_EQ(WindowStateType::kDefault, delegate()->new_state()); EXPECT_EQ(gfx::Rect(), delegate()->requested_bounds()); } @@ -347,8 +347,8 @@ delegate()->requested_bounds().right(), 1); EXPECT_EQ(work_area.height(), delegate()->requested_bounds().height()); EXPECT_TRUE(delegate()->requested_bounds().origin().IsOrigin()); - EXPECT_EQ(mojom::WindowStateType::DEFAULT, delegate()->old_state()); - EXPECT_EQ(mojom::WindowStateType::LEFT_SNAPPED, delegate()->new_state()); + EXPECT_EQ(WindowStateType::kDefault, delegate()->old_state()); + EXPECT_EQ(WindowStateType::kLeftSnapped, delegate()->new_state()); delegate()->Reset(); @@ -358,8 +358,8 @@ EXPECT_EQ(work_area.height(), delegate()->requested_bounds().height()); EXPECT_EQ(work_area.bottom_right(), delegate()->requested_bounds().bottom_right()); - EXPECT_EQ(mojom::WindowStateType::DEFAULT, delegate()->old_state()); - EXPECT_EQ(mojom::WindowStateType::RIGHT_SNAPPED, delegate()->new_state()); + EXPECT_EQ(WindowStateType::kDefault, delegate()->old_state()); + EXPECT_EQ(WindowStateType::kRightSnapped, delegate()->new_state()); } // Pin events should be applied immediately. @@ -371,22 +371,22 @@ window_state()->OnWMEvent(&pin_event); EXPECT_TRUE(window_state()->IsPinned()); EXPECT_TRUE(GetScreenPinningController()->IsPinned()); - EXPECT_EQ(mojom::WindowStateType::PINNED, window_state()->GetStateType()); - EXPECT_EQ(mojom::WindowStateType::DEFAULT, delegate()->old_state()); - EXPECT_EQ(mojom::WindowStateType::PINNED, delegate()->new_state()); + EXPECT_EQ(WindowStateType::kPinned, window_state()->GetStateType()); + EXPECT_EQ(WindowStateType::kDefault, delegate()->old_state()); + EXPECT_EQ(WindowStateType::kPinned, delegate()->new_state()); // All state transition events are ignored except for NORMAL. widget()->Maximize(); - EXPECT_EQ(mojom::WindowStateType::PINNED, window_state()->GetStateType()); + EXPECT_EQ(WindowStateType::kPinned, window_state()->GetStateType()); EXPECT_TRUE(GetScreenPinningController()->IsPinned()); widget()->Minimize(); - EXPECT_EQ(mojom::WindowStateType::PINNED, window_state()->GetStateType()); + EXPECT_EQ(WindowStateType::kPinned, window_state()->GetStateType()); EXPECT_TRUE(GetScreenPinningController()->IsPinned()); EXPECT_TRUE(window()->IsVisible()); widget()->SetFullscreen(true); - EXPECT_EQ(mojom::WindowStateType::PINNED, window_state()->GetStateType()); + EXPECT_EQ(WindowStateType::kPinned, window_state()->GetStateType()); EXPECT_TRUE(GetScreenPinningController()->IsPinned()); // WM/User cannot change the bounds of the pinned window. @@ -401,7 +401,7 @@ widget()->Restore(); EXPECT_FALSE(window_state()->IsPinned()); - EXPECT_EQ(mojom::WindowStateType::NORMAL, window_state()->GetStateType()); + EXPECT_EQ(WindowStateType::kNormal, window_state()->GetStateType()); EXPECT_FALSE(GetScreenPinningController()->IsPinned()); // Two windows cannot be pinned simultaneously. @@ -426,26 +426,22 @@ EXPECT_TRUE(window_state()->IsPinned()); EXPECT_TRUE(GetScreenPinningController()->IsPinned()); - EXPECT_EQ(mojom::WindowStateType::TRUSTED_PINNED, - window_state()->GetStateType()); - EXPECT_EQ(mojom::WindowStateType::DEFAULT, delegate()->old_state()); - EXPECT_EQ(mojom::WindowStateType::TRUSTED_PINNED, delegate()->new_state()); + EXPECT_EQ(WindowStateType::kTrustedPinned, window_state()->GetStateType()); + EXPECT_EQ(WindowStateType::kDefault, delegate()->old_state()); + EXPECT_EQ(WindowStateType::kTrustedPinned, delegate()->new_state()); // All state transition events are ignored except for NORMAL. widget()->Maximize(); - EXPECT_EQ(mojom::WindowStateType::TRUSTED_PINNED, - window_state()->GetStateType()); + EXPECT_EQ(WindowStateType::kTrustedPinned, window_state()->GetStateType()); EXPECT_TRUE(GetScreenPinningController()->IsPinned()); widget()->Minimize(); - EXPECT_EQ(mojom::WindowStateType::TRUSTED_PINNED, - window_state()->GetStateType()); + EXPECT_EQ(WindowStateType::kTrustedPinned, window_state()->GetStateType()); EXPECT_TRUE(GetScreenPinningController()->IsPinned()); EXPECT_TRUE(window()->IsVisible()); widget()->SetFullscreen(true); - EXPECT_EQ(mojom::WindowStateType::TRUSTED_PINNED, - window_state()->GetStateType()); + EXPECT_EQ(WindowStateType::kTrustedPinned, window_state()->GetStateType()); EXPECT_TRUE(GetScreenPinningController()->IsPinned()); // WM/User cannot change the bounds of the trusted-pinned window. @@ -460,7 +456,7 @@ widget()->Restore(); EXPECT_FALSE(window_state()->IsPinned()); - EXPECT_EQ(mojom::WindowStateType::NORMAL, window_state()->GetStateType()); + EXPECT_EQ(WindowStateType::kNormal, window_state()->GetStateType()); EXPECT_FALSE(GetScreenPinningController()->IsPinned()); // Two windows cannot be trusted-pinned simultaneously.
diff --git a/ash/wm/default_state.cc b/ash/wm/default_state.cc index ea0533c..2e642e4 100644 --- a/ash/wm/default_state.cc +++ b/ash/wm/default_state.cc
@@ -75,7 +75,7 @@ } // namespace -DefaultState::DefaultState(mojom::WindowStateType initial_state_type) +DefaultState::DefaultState(WindowStateType initial_state_type) : BaseState(initial_state_type), stored_window_state_(nullptr) {} DefaultState::~DefaultState() = default; @@ -344,8 +344,8 @@ void DefaultState::HandleTransitionEvents(WindowState* window_state, const WMEvent* event) { - mojom::WindowStateType current_state_type = window_state->GetStateType(); - mojom::WindowStateType next_state_type = GetStateForTransitionEvent(event); + WindowStateType current_state_type = window_state->GetStateType(); + WindowStateType next_state_type = GetStateForTransitionEvent(event); if (event->IsPinEvent()) { // If there already is a pinned window, it is not allowed to set it // to this window. @@ -361,8 +361,8 @@ if (next_state_type == current_state_type && window_state->IsSnapped()) { gfx::Rect snapped_bounds = GetSnappedWindowBoundsInParent( window_state->window(), event->type() == WM_EVENT_SNAP_LEFT - ? mojom::WindowStateType::LEFT_SNAPPED - : mojom::WindowStateType::RIGHT_SNAPPED); + ? WindowStateType::kLeftSnapped + : WindowStateType::kRightSnapped); window_state->SetBoundsDirectAnimated(snapped_bounds); return; } @@ -421,12 +421,12 @@ } void DefaultState::EnterToNextState(WindowState* window_state, - mojom::WindowStateType next_state_type) { + WindowStateType next_state_type) { // Do nothing if we're already in the same state. if (state_type_ == next_state_type) return; - mojom::WindowStateType previous_state_type = state_type_; + WindowStateType previous_state_type = state_type_; state_type_ = next_state_type; window_state->UpdateWindowPropertiesFromStateType(); @@ -438,8 +438,8 @@ // we still need this. if (window_state->window()->parent()) { if (!window_state->HasRestoreBounds() && - (previous_state_type == mojom::WindowStateType::DEFAULT || - previous_state_type == mojom::WindowStateType::NORMAL) && + (previous_state_type == WindowStateType::kDefault || + previous_state_type == WindowStateType::kNormal) && !window_state->IsMinimized() && !window_state->IsNormalStateType()) { window_state->SaveCurrentBoundsForRestore(); } @@ -449,7 +449,7 @@ // (The restore bounds are set if a user maximized the window in one // axis by double clicking the window border for example). gfx::Rect restore_bounds_in_screen; - if (previous_state_type == mojom::WindowStateType::MINIMIZED && + if (previous_state_type == WindowStateType::kMinimized && window_state->IsNormalStateType() && window_state->HasRestoreBounds() && !window_state->unminimize_to_restore_bounds()) { restore_bounds_in_screen = window_state->GetRestoreBoundsInScreen(); @@ -471,10 +471,10 @@ } window_state->NotifyPostStateTypeChange(previous_state_type); - if (next_state_type == mojom::WindowStateType::PINNED || - previous_state_type == mojom::WindowStateType::PINNED || - next_state_type == mojom::WindowStateType::TRUSTED_PINNED || - previous_state_type == mojom::WindowStateType::TRUSTED_PINNED) { + if (next_state_type == WindowStateType::kPinned || + previous_state_type == WindowStateType::kPinned || + next_state_type == WindowStateType::kTrustedPinned || + previous_state_type == WindowStateType::kTrustedPinned) { Shell::Get()->screen_pinning_controller()->SetPinnedWindow( window_state->window()); } @@ -483,27 +483,26 @@ void DefaultState::ReenterToCurrentState( WindowState* window_state, WindowState::State* state_in_previous_mode) { - mojom::WindowStateType previous_state_type = - state_in_previous_mode->GetType(); + WindowStateType previous_state_type = state_in_previous_mode->GetType(); // A state change should not move a window into or out of full screen or // pinned since these are "special mode" the user wanted to be in and // should be respected as such. - if (previous_state_type == mojom::WindowStateType::FULLSCREEN || - previous_state_type == mojom::WindowStateType::PINNED || - previous_state_type == mojom::WindowStateType::TRUSTED_PINNED) { + if (previous_state_type == WindowStateType::kFullscreen || + previous_state_type == WindowStateType::kPinned || + previous_state_type == WindowStateType::kTrustedPinned) { state_type_ = previous_state_type; - } else if (state_type_ == mojom::WindowStateType::FULLSCREEN || - state_type_ == mojom::WindowStateType::PINNED || - state_type_ == mojom::WindowStateType::TRUSTED_PINNED) { + } else if (state_type_ == WindowStateType::kFullscreen || + state_type_ == WindowStateType::kPinned || + state_type_ == WindowStateType::kTrustedPinned) { state_type_ = previous_state_type; } window_state->UpdateWindowPropertiesFromStateType(); window_state->NotifyPreStateTypeChange(previous_state_type); - if ((state_type_ == mojom::WindowStateType::NORMAL || - state_type_ == mojom::WindowStateType::DEFAULT) && + if ((state_type_ == WindowStateType::kNormal || + state_type_ == WindowStateType::kDefault) && !stored_bounds_.IsEmpty()) { // Use the restore mechanism to set the bounds for // the window in normal state. This also covers unminimize case. @@ -522,20 +521,19 @@ window_state->NotifyPostStateTypeChange(previous_state_type); } -void DefaultState::UpdateBoundsFromState( - WindowState* window_state, - mojom::WindowStateType previous_state_type) { +void DefaultState::UpdateBoundsFromState(WindowState* window_state, + WindowStateType previous_state_type) { aura::Window* window = window_state->window(); gfx::Rect bounds_in_parent; switch (state_type_) { - case mojom::WindowStateType::LEFT_SNAPPED: - case mojom::WindowStateType::RIGHT_SNAPPED: + case WindowStateType::kLeftSnapped: + case WindowStateType::kRightSnapped: bounds_in_parent = GetSnappedWindowBoundsInParent(window_state->window(), state_type_); break; - case mojom::WindowStateType::DEFAULT: - case mojom::WindowStateType::NORMAL: { + case WindowStateType::kDefault: + case WindowStateType::kNormal: { gfx::Rect work_area_in_parent = screen_util::GetDisplayWorkAreaBoundsInParent(window); if (window_state->HasRestoreBounds()) { @@ -543,7 +541,7 @@ // Check if the |window|'s restored size is bigger than the working area // This may happen if a window was resized to maximized bounds or if the // display resolution changed while the window was maximized. - if (previous_state_type == mojom::WindowStateType::MAXIMIZED && + if (previous_state_type == WindowStateType::kMaximized && bounds_in_parent.width() >= work_area_in_parent.width() && bounds_in_parent.height() >= work_area_in_parent.height()) { bounds_in_parent = work_area_in_parent; @@ -563,21 +561,21 @@ } break; } - case mojom::WindowStateType::MAXIMIZED: + case WindowStateType::kMaximized: bounds_in_parent = screen_util::GetMaximizedWindowBoundsInParent(window); break; - case mojom::WindowStateType::FULLSCREEN: - case mojom::WindowStateType::PINNED: - case mojom::WindowStateType::TRUSTED_PINNED: + case WindowStateType::kFullscreen: + case WindowStateType::kPinned: + case WindowStateType::kTrustedPinned: bounds_in_parent = screen_util::GetFullscreenWindowBoundsInParent(window); break; - case mojom::WindowStateType::MINIMIZED: + case WindowStateType::kMinimized: break; - case mojom::WindowStateType::INACTIVE: - case mojom::WindowStateType::AUTO_POSITIONED: - case mojom::WindowStateType::PIP: + case WindowStateType::kInactive: + case WindowStateType::kAutoPositioned: + case WindowStateType::kPip: return; }
diff --git a/ash/wm/default_state.h b/ash/wm/default_state.h index 8679532..953c597 100644 --- a/ash/wm/default_state.h +++ b/ash/wm/default_state.h
@@ -22,7 +22,7 @@ // DefaultState implements Ash behavior without state machine. class DefaultState : public BaseState { public: - explicit DefaultState(mojom::WindowStateType initial_state_type); + explicit DefaultState(WindowStateType initial_state_type); ~DefaultState() override; // WindowState::State overrides: @@ -50,7 +50,7 @@ // Enters next state. This is used when the state moves from one to another // within the same desktop mode. void EnterToNextState(wm::WindowState* window_state, - mojom::WindowStateType next_state_type); + WindowStateType next_state_type); // Reenters the current state. This is called when migrating from // previous desktop mode, and the window's state needs to re-construct the @@ -60,7 +60,7 @@ // Animates to new window bounds based on the current and previous state type. void UpdateBoundsFromState(wm::WindowState* window_state, - mojom::WindowStateType old_state_type); + WindowStateType old_state_type); // The saved window state for the case that the state gets de-/activated. gfx::Rect stored_bounds_;
diff --git a/ash/wm/drag_details.h b/ash/wm/drag_details.h index 03131704..68556e3 100644 --- a/ash/wm/drag_details.h +++ b/ash/wm/drag_details.h
@@ -6,7 +6,7 @@ #define ASH_WM_DRAG_DETAILS_H_ #include "ash/ash_export.h" -#include "ash/public/interfaces/window_state_type.mojom.h" +#include "ash/public/cpp/window_state_type.h" #include "ui/gfx/geometry/rect.h" #include "ui/wm/public/window_move_client.h" @@ -24,7 +24,7 @@ ::wm::WindowMoveSource source); ~DragDetails(); - ash::mojom::WindowStateType initial_state_type; + ash::WindowStateType initial_state_type; // Initial bounds of the window in parent coordinates. const gfx::Rect initial_bounds_in_parent;
diff --git a/ash/wm/lock_window_state.cc b/ash/wm/lock_window_state.cc index 6450a613..d3aada61 100644 --- a/ash/wm/lock_window_state.cc +++ b/ash/wm/lock_window_state.cc
@@ -37,7 +37,7 @@ ToggleFullScreen(window_state, window_state->delegate()); break; case wm::WM_EVENT_FULLSCREEN: - UpdateWindow(window_state, mojom::WindowStateType::FULLSCREEN); + UpdateWindow(window_state, WindowStateType::kFullscreen); break; case wm::WM_EVENT_PIP: case wm::WM_EVENT_PIN: @@ -59,7 +59,7 @@ GetMaximizedOrCenteredWindowType(window_state)); return; case wm::WM_EVENT_MINIMIZE: - UpdateWindow(window_state, mojom::WindowStateType::MINIMIZED); + UpdateWindow(window_state, WindowStateType::kMinimized); return; case wm::WM_EVENT_SHOW_INACTIVE: return; @@ -73,9 +73,9 @@ } break; case wm::WM_EVENT_ADDED_TO_WORKSPACE: - if (current_state_type_ != mojom::WindowStateType::MAXIMIZED && - current_state_type_ != mojom::WindowStateType::MINIMIZED && - current_state_type_ != mojom::WindowStateType::FULLSCREEN) { + if (current_state_type_ != WindowStateType::kMaximized && + current_state_type_ != WindowStateType::kMinimized && + current_state_type_ != WindowStateType::kFullscreen) { UpdateWindow(window_state, GetMaximizedOrCenteredWindowType(window_state)); } else { @@ -91,7 +91,7 @@ } } -mojom::WindowStateType LockWindowState::GetType() const { +WindowStateType LockWindowState::GetType() const { return current_state_type_; } @@ -100,9 +100,9 @@ current_state_type_ = previous_state->GetType(); // Initialize the state to a good preset. - if (current_state_type_ != mojom::WindowStateType::MAXIMIZED && - current_state_type_ != mojom::WindowStateType::MINIMIZED && - current_state_type_ != mojom::WindowStateType::FULLSCREEN) { + if (current_state_type_ != WindowStateType::kMaximized && + current_state_type_ != WindowStateType::kMinimized && + current_state_type_ != WindowStateType::kFullscreen) { UpdateWindow(window_state, GetMaximizedOrCenteredWindowType(window_state)); } } @@ -131,15 +131,15 @@ } void LockWindowState::UpdateWindow(wm::WindowState* window_state, - mojom::WindowStateType target_state) { - DCHECK(target_state == mojom::WindowStateType::MINIMIZED || - target_state == mojom::WindowStateType::MAXIMIZED || - (target_state == mojom::WindowStateType::NORMAL && + WindowStateType target_state) { + DCHECK(target_state == WindowStateType::kMinimized || + target_state == WindowStateType::kMaximized || + (target_state == WindowStateType::kNormal && !window_state->CanMaximize()) || - target_state == mojom::WindowStateType::FULLSCREEN); + target_state == WindowStateType::kFullscreen); - if (target_state == mojom::WindowStateType::MINIMIZED) { - if (current_state_type_ == mojom::WindowStateType::MINIMIZED) + if (target_state == WindowStateType::kMinimized) { + if (current_state_type_ == WindowStateType::kMinimized) return; current_state_type_ = target_state; @@ -157,7 +157,7 @@ return; } - const mojom::WindowStateType old_state_type = current_state_type_; + const WindowStateType old_state_type = current_state_type_; current_state_type_ = target_state; window_state->UpdateWindowPropertiesFromStateType(); window_state->NotifyPreStateTypeChange(old_state_type); @@ -165,7 +165,7 @@ window_state->NotifyPostStateTypeChange(old_state_type); if ((window_state->window()->TargetVisibility() || - old_state_type == mojom::WindowStateType::MINIMIZED) && + old_state_type == WindowStateType::kMinimized) && !window_state->window()->layer()->visible()) { // The layer may be hidden if the window was previously minimized. Make // sure it's visible. @@ -173,10 +173,10 @@ } } -mojom::WindowStateType LockWindowState::GetMaximizedOrCenteredWindowType( +WindowStateType LockWindowState::GetMaximizedOrCenteredWindowType( wm::WindowState* window_state) { - return window_state->CanMaximize() ? mojom::WindowStateType::MAXIMIZED - : mojom::WindowStateType::NORMAL; + return window_state->CanMaximize() ? WindowStateType::kMaximized + : WindowStateType::kNormal; } gfx::Rect LockWindowState::GetWindowBounds(aura::Window* window) {
diff --git a/ash/wm/lock_window_state.h b/ash/wm/lock_window_state.h index b09d6ad..4f3d6fd6 100644 --- a/ash/wm/lock_window_state.h +++ b/ash/wm/lock_window_state.h
@@ -30,7 +30,7 @@ // WindowState::State overrides: void OnWMEvent(wm::WindowState* window_state, const wm::WMEvent* event) override; - mojom::WindowStateType GetType() const override; + WindowStateType GetType() const override; void AttachState(wm::WindowState* window_state, wm::WindowState::State* previous_state) override; void DetachState(wm::WindowState* window_state) override; @@ -45,11 +45,11 @@ // Either full screen, maximized centered or minimized. If the state does not // change, only the bounds will be changed. void UpdateWindow(wm::WindowState* window_state, - mojom::WindowStateType new_state_type); + WindowStateType new_state_type); // Depending on the capabilities of the window we either return - // |WindowStateType::MAXIMIZED| or |WindowStateType::NORMAL|. - mojom::WindowStateType GetMaximizedOrCenteredWindowType( + // |WindowStateType::kMaximized| or |WindowStateType::kNormal|. + WindowStateType GetMaximizedOrCenteredWindowType( wm::WindowState* window_state); // Returns boudns to be used for the provided window. @@ -60,7 +60,7 @@ // The current state type. Due to the nature of this state, this can only be // WM_STATE_TYPE{NORMAL, MINIMIZED, MAXIMIZED}. - mojom::WindowStateType current_state_type_; + WindowStateType current_state_type_; // Restrict window size to the work area defined by the shelf - i.e. window // bounds exclude system shelf bounds.
diff --git a/ash/wm/non_client_frame_controller.cc b/ash/wm/non_client_frame_controller.cc deleted file mode 100644 index e1ced8f..0000000 --- a/ash/wm/non_client_frame_controller.cc +++ /dev/null
@@ -1,395 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "ash/wm/non_client_frame_controller.h" - -#include <stdint.h> - -#include <memory> -#include <string> -#include <vector> - -#include "ash/accessibility/accessibility_controller.h" -#include "ash/frame/non_client_frame_view_ash.h" -#include "ash/public/cpp/ash_constants.h" -#include "ash/public/cpp/frame_utils.h" -#include "ash/public/cpp/window_properties.h" -#include "ash/shell.h" -#include "ash/wm/property_util.h" -#include "ash/wm/window_properties.h" -#include "ash/wm/window_util.h" -#include "base/macros.h" -#include "base/strings/string16.h" -#include "base/strings/utf_string_conversions.h" -#include "services/ws/public/cpp/property_type_converters.h" -#include "services/ws/public/mojom/window_manager.mojom.h" -#include "services/ws/top_level_proxy_window.h" -#include "services/ws/window_properties.h" -#include "services/ws/window_utils.h" -#include "ui/accessibility/ax_node_data.h" -#include "ui/accessibility/ax_tree_id.h" -#include "ui/accessibility/platform/aura_window_properties.h" -#include "ui/aura/client/aura_constants.h" -#include "ui/aura/mus/property_converter.h" -#include "ui/aura/mus/property_utils.h" -#include "ui/aura/mus/window_port_mus.h" -#include "ui/aura/window.h" -#include "ui/base/class_property.h" -#include "ui/base/hit_test.h" -#include "ui/compositor/layer.h" -#include "ui/gfx/geometry/vector2d.h" -#include "ui/views/widget/native_widget_aura.h" -#include "ui/views/widget/widget.h" -#include "ui/views/window/caption_button_layout_constants.h" -#include "ui/wm/core/coordinate_conversion.h" - -DEFINE_UI_CLASS_PROPERTY_TYPE(ash::NonClientFrameController*) - -namespace ash { -namespace { - -DEFINE_UI_CLASS_PROPERTY_KEY(NonClientFrameController*, - kNonClientFrameControllerKey, - nullptr) - -bool DoesClientProvideFrame( - std::map<std::string, std::vector<uint8_t>>* properties) { - auto iter = properties->find( - ws::mojom::WindowManager::kClientProvidesFrame_InitProperty); - return iter != properties->end() && mojo::ConvertTo<bool>(iter->second); -} - -// This class supports draggable app windows that paint their own custom frames. -// It uses empty insets and doesn't paint anything. -class EmptyDraggableNonClientFrameView : public views::NonClientFrameView { - public: - EmptyDraggableNonClientFrameView() = default; - ~EmptyDraggableNonClientFrameView() override = default; - - // views::NonClientFrameView: - gfx::Rect GetBoundsForClientView() const override { return bounds(); } - gfx::Rect GetWindowBoundsForClientBounds( - const gfx::Rect& client_bounds) const override { - return bounds(); - } - int NonClientHitTest(const gfx::Point& point) override { - int component = FrameBorderNonClientHitTest(this, point); - - // For non-standard frame window, the located event in the non-client area - // in the window should be used for window dragging to allow dragging - // frameless app windows. See https://crbug.com/920469 - if (component == HTCLIENT && - ws::IsLocationInNonClientArea(GetWidget()->GetNativeWindow(), point)) { - return HTCAPTION; - } - return component; - } - void GetWindowMask(const gfx::Size& size, SkPath* window_mask) override {} - void ResetWindowControls() override {} - void UpdateWindowIcon() override {} - void UpdateWindowTitle() override {} - void SizeConstraintsChanged() override {} - - private: - DISALLOW_COPY_AND_ASSIGN(EmptyDraggableNonClientFrameView); -}; - -class WmNativeWidgetAura : public views::NativeWidgetAura { - public: - WmNativeWidgetAura(views::internal::NativeWidgetDelegate* delegate, - bool client_provides_frame) - // The NativeWidget is mirroring the real Widget created in client code. - // |is_parallel_widget_in_window_manager| is used to indicate this - : views::NativeWidgetAura(delegate, - true /* is_parallel_widget_in_window_manager */, - Shell::Get()->aura_env()), - client_provides_frame_(client_provides_frame) {} - ~WmNativeWidgetAura() override = default; - - void set_cursor(const ui::Cursor& cursor) { cursor_ = cursor; } - - // views::NativeWidgetAura: - views::NonClientFrameView* CreateNonClientFrameView() override { - // TODO(sky): investigate why we have this. Seems this should be the same - // as not specifying client area insets. - if (client_provides_frame_) { - wm::InstallResizeHandleWindowTargeterForWindow(GetNativeWindow()); - return new EmptyDraggableNonClientFrameView(); - } - - // See description for details on ownership. - auto* custom_frame_view = new NonClientFrameViewAsh(GetWidget()); - - // Only the header actually paints any content. So the rest of the region is - // marked as transparent content (see below in NonClientFrameController() - // ctor). So, it is necessary to provide a texture-layer for the header - // view. - views::View* header_view = custom_frame_view->GetHeaderView(); - if (header_view) { - header_view->SetPaintToLayer(ui::LAYER_TEXTURED); - header_view->layer()->set_name("WindowService Frame Header"); - header_view->layer()->SetFillsBoundsOpaquely(false); - } - - return custom_frame_view; - } - - gfx::NativeCursor GetCursor(const gfx::Point& point) override { - return cursor_; - } - - gfx::Size GetMaximumSize() const override { - aura::Window* window = GetNativeWindow(); - if (window && client_provides_frame_ && - window->GetProperty(aura::client::kMaximumSize)) { - return *window->GetProperty(aura::client::kMaximumSize); - } - return views::NativeWidgetAura::GetMaximumSize(); - } - - gfx::Size GetMinimumSize() const override { - aura::Window* window = GetNativeWindow(); - if (window && client_provides_frame_ && - window->GetProperty(aura::client::kMinimumSize)) { - return *window->GetProperty(aura::client::kMinimumSize); - } - return views::NativeWidgetAura::GetMinimumSize(); - } - - private: - // True if the client has asked to be responsible for the window's frame. In - // this case, Ash won't create a NonClientFrameViewAsh. - const bool client_provides_frame_; - - // The cursor for this widget. CompoundEventFilter will retrieve this cursor - // via GetCursor and update the CursorManager's active cursor as appropriate - // (i.e. when the mouse pointer is over this widget). - ui::Cursor cursor_; - - DISALLOW_COPY_AND_ASSIGN(WmNativeWidgetAura); -}; - -// ContentsViewMus links the ash Widget's accessibility node tree with the one -// inside a remote process app. This is needed to support focus; ash needs to -// have "focus" on a leaf node in its Widget/View hierarchy in order for the -// accessibility subsystem to see focused nodes in the remote app. -class ContentsViewMus : public views::View { - public: - ContentsViewMus() = default; - ~ContentsViewMus() override = default; - - // views::View: - const char* GetClassName() const override { return "ContentsViewMus"; } - void GetAccessibleNodeData(ui::AXNodeData* node_data) override { - std::string* tree_id = - GetWidget()->GetNativeWindow()->GetProperty(ui::kChildAXTreeID); - // Property may not be available immediately, but focus is eventually - // consistent. - if (!tree_id) - return; - node_data->AddStringAttribute(ax::mojom::StringAttribute::kChildTreeId, - *tree_id); - node_data->role = ax::mojom::Role::kClient; - } - - private: - DISALLOW_COPY_AND_ASSIGN(ContentsViewMus); -}; - -class ClientViewMus : public views::ClientView { - public: - ClientViewMus(views::Widget* widget, - views::View* contents_view, - ws::TopLevelProxyWindow* top_level_proxy_window) - : views::ClientView(widget, contents_view), - top_level_proxy_window_(top_level_proxy_window) {} - ~ClientViewMus() override = default; - - // views::ClientView: - bool CanClose() override { - // CanClose() is called when the user requests the window to close (such as - // clicking the close button). As this window is managed by a remote client - // pass the request to the remote client and return false (to cancel the - // close). If the remote client wants the window to close, it will close it - // in a way that does not reenter this code path. - top_level_proxy_window_->RequestClose(); - return false; - } - - // views::View: - const char* GetClassName() const override { return "ClientViewMus"; } - - private: - ws::TopLevelProxyWindow* top_level_proxy_window_; - - DISALLOW_COPY_AND_ASSIGN(ClientViewMus); -}; - -} // namespace - -NonClientFrameController::NonClientFrameController( - ws::TopLevelProxyWindow* top_level_proxy_window, - aura::Window* parent, - aura::Window* context, - const gfx::Rect& bounds, - aura::PropertyConverter* property_converter, - std::map<std::string, std::vector<uint8_t>>* properties) - : widget_(new views::Widget), - top_level_proxy_window_(top_level_proxy_window) { - // To simplify things this code creates a Widget. While a Widget is created - // we need to ensure we don't inadvertently change random properties of the - // underlying ui::Window. For example, showing the Widget shouldn't change - // the bounds of the ui::Window in anyway. - views::Widget::InitParams params; - DCHECK((parent && !context) || (!parent && context)); - params.parent = parent; - params.context = context; - // TODO: properly set |params.activatable|. Should key off whether underlying - // (mus) window can have focus. - params.delegate = this; - params.bounds = bounds; - params.opacity = views::Widget::InitParams::OPAQUE_WINDOW; - params.layer_type = ui::LAYER_NOT_DRAWN; - WmNativeWidgetAura* native_widget = - new WmNativeWidgetAura(widget_, DoesClientProvideFrame(properties)); - window_ = native_widget->GetNativeView(); - window_->SetProperty(kNonClientFrameControllerKey, this); - window_->AddObserver(this); - params.native_widget = native_widget; - aura::SetWindowType(window_, ws::mojom::WindowType::WINDOW); - for (auto& property_pair : *properties) { - property_converter->SetPropertyFromTransportValue( - window_, property_pair.first, &property_pair.second); - } - // Applying properties will have set the show state if specified. - // NativeWidgetAura resets the show state from |params|, so we need to update - // |params|. - params.show_state = window_->GetProperty(aura::client::kShowStateKey); - widget_->Init(params); - did_init_native_widget_ = true; -} - -// static -NonClientFrameController* NonClientFrameController::Get(aura::Window* window) { - return window->GetProperty(kNonClientFrameControllerKey); -} - -// static -gfx::Insets NonClientFrameController::GetPreferredClientAreaInsets() { - return gfx::Insets(views::GetCaptionButtonLayoutSize( - views::CaptionButtonLayoutSize::kNonBrowserCaption) - .height(), - 0, 0, 0); -} - -// static -int NonClientFrameController::GetMaxTitleBarButtonWidth() { - return views::GetCaptionButtonLayoutSize( - views::CaptionButtonLayoutSize::kNonBrowserCaption) - .width() * - 3; -} - -void NonClientFrameController::StoreCursor(const ui::Cursor& cursor) { - static_cast<WmNativeWidgetAura*>(widget_->native_widget()) - ->set_cursor(cursor); -} - -base::string16 NonClientFrameController::GetWindowTitle() const { - if (!window_) - return base::string16(); - - base::string16 title = window_->GetTitle(); - - if (window_->GetProperty(kWindowIsJanky)) - title += base::ASCIIToUTF16(" !! Not responding !!"); - - return title; -} - -bool NonClientFrameController::CanResize() const { - return window_ && (window_->GetProperty(aura::client::kResizeBehaviorKey) & - ws::mojom::kResizeBehaviorCanResize) != 0; -} - -bool NonClientFrameController::CanMaximize() const { - return window_ && (window_->GetProperty(aura::client::kResizeBehaviorKey) & - ws::mojom::kResizeBehaviorCanMaximize) != 0; -} - -bool NonClientFrameController::CanMinimize() const { - return window_ && (window_->GetProperty(aura::client::kResizeBehaviorKey) & - ws::mojom::kResizeBehaviorCanMinimize) != 0; -} - -bool NonClientFrameController::CanActivate() const { - // kCanFocus is used for both focus and activation. - return window_ && window_->GetProperty(ws::kCanFocus) && - views::WidgetDelegate::CanActivate(); -} - -bool NonClientFrameController::ShouldShowWindowTitle() const { - return window_ && window_->GetProperty(aura::client::kTitleShownKey); -} - -void NonClientFrameController::DeleteDelegate() { - delete this; -} - -views::Widget* NonClientFrameController::GetWidget() { - return widget_; -} - -const views::Widget* NonClientFrameController::GetWidget() const { - return widget_; -} - -views::View* NonClientFrameController::GetContentsView() { - return contents_view_; -} - -views::ClientView* NonClientFrameController::CreateClientView( - views::Widget* widget) { - DCHECK(!contents_view_); - contents_view_ = new ContentsViewMus(); // Owned by views hierarchy. - return new ClientViewMus(widget, contents_view_, top_level_proxy_window_); -} - -void NonClientFrameController::OnWindowBeginUserBoundsChange() { - top_level_proxy_window_->OnWindowResizeLoopStarted(); -} - -void NonClientFrameController::OnWindowEndUserBoundsChange() { - top_level_proxy_window_->OnWindowResizeLoopEnded(); -} - -void NonClientFrameController::OnWindowPropertyChanged(aura::Window* window, - const void* key, - intptr_t old) { - // Properties are applied before the call to InitNativeWidget(). Ignore - // processing changes in this case as the Widget is not in a state where we - // can use it yet. - if (!did_init_native_widget_) - return; - - if (key == kWindowIsJanky || key == aura::client::kTitleKey || - key == aura::client::kTitleShownKey) { - widget_->UpdateWindowTitle(); - widget_->non_client_view()->frame_view()->SchedulePaint(); - } else if (key == aura::client::kResizeBehaviorKey) { - widget_->OnSizeConstraintsChanged(); - } -} - -void NonClientFrameController::OnWindowDestroyed(aura::Window* window) { - window_->RemoveObserver(this); - window_ = nullptr; -} - -NonClientFrameController::~NonClientFrameController() { - if (window_) - window_->RemoveObserver(this); -} - -} // namespace ash
diff --git a/ash/wm/non_client_frame_controller.h b/ash/wm/non_client_frame_controller.h deleted file mode 100644 index df8e140..0000000 --- a/ash/wm/non_client_frame_controller.h +++ /dev/null
@@ -1,119 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef ASH_WM_NON_CLIENT_FRAME_CONTROLLER_H_ -#define ASH_WM_NON_CLIENT_FRAME_CONTROLLER_H_ - -#include <stdint.h> - -#include <map> -#include <string> -#include <vector> - -#include "ash/ash_export.h" -#include "base/macros.h" -#include "base/strings/string16.h" -#include "ui/aura/window_observer.h" -#include "ui/gfx/geometry/insets.h" -#include "ui/gfx/geometry/rect.h" -#include "ui/views/widget/widget_delegate.h" - -namespace aura { -class PropertyConverter; -class Window; -} // namespace aura - -namespace gfx { -class Insets; -} - -namespace ws { -class TopLevelProxyWindow; -} // namespace ws - -namespace ash { - -// Provides the non-client frame and contents view for windows created by remote -// app processes. -class ASH_EXPORT NonClientFrameController : public views::WidgetDelegate, - public aura::WindowObserver { - public: - // Creates a new NonClientFrameController and window to render the non-client - // frame decorations. This deletes itself when |window| is destroyed. |parent| - // is the parent to place the newly created window in, and may be null. If - // |parent| is null, |context| is used to determine the parent Window. One of - // |parent| or |context| must be non-null. |window_manager_client| may be - // null for now. |bounds| is screen coordinates when |parent| is null, - // otherwise local coordinates, see views::Widget::InitParams::bounds. - NonClientFrameController( - ws::TopLevelProxyWindow* top_level_proxy_window, - aura::Window* parent, - aura::Window* context, - const gfx::Rect& bounds, - aura::PropertyConverter* property_converter, - std::map<std::string, std::vector<uint8_t>>* properties); - - // Returns the NonClientFrameController for the specified window, null if - // one was not created. - static NonClientFrameController* Get(aura::Window* window); - - // Returns the preferred client area insets. - static gfx::Insets GetPreferredClientAreaInsets(); - - // Returns the width needed to display the standard set of buttons on the - // title bar. - static int GetMaxTitleBarButtonWidth(); - - aura::Window* window() { return window_; } - - // Stores |cursor| as this window's active cursor. It does not actually update - // the active cursor by calling into CursorManager, but will update the return - // value provided by the associated window's aura::WindowDelegate::GetCursor. - void StoreCursor(const ui::Cursor& cursor); - - ws::TopLevelProxyWindow* top_level_proxy_window() { - return top_level_proxy_window_; - } - - // views::WidgetDelegate: - base::string16 GetWindowTitle() const override; - bool CanResize() const override; - bool CanMaximize() const override; - bool CanMinimize() const override; - bool CanActivate() const override; - bool ShouldShowWindowTitle() const override; - void DeleteDelegate() override; - views::Widget* GetWidget() override; - const views::Widget* GetWidget() const override; - views::View* GetContentsView() override; - views::ClientView* CreateClientView(views::Widget* widget) override; - void OnWindowBeginUserBoundsChange() override; - void OnWindowEndUserBoundsChange() override; - - // aura::WindowObserver: - void OnWindowPropertyChanged(aura::Window* window, - const void* key, - intptr_t old) override; - void OnWindowDestroyed(aura::Window* window) override; - - private: - ~NonClientFrameController() override; - - views::Widget* widget_; - views::View* contents_view_ = nullptr; - // Owned by the window-service. - ws::TopLevelProxyWindow* top_level_proxy_window_; - - // WARNING: as widget delays destruction there is a portion of time when this - // is null. - aura::Window* window_ = nullptr; - - bool did_init_native_widget_ = false; - - DISALLOW_COPY_AND_ASSIGN(NonClientFrameController); -}; - -} // namespace ash - -#endif // ASH_WM_NON_CLIENT_FRAME_CONTROLLER_H_
diff --git a/ash/wm/overview/overview_grid.cc b/ash/wm/overview/overview_grid.cc index 0fd1915..69ea133 100644 --- a/ash/wm/overview/overview_grid.cc +++ b/ash/wm/overview/overview_grid.cc
@@ -932,9 +932,8 @@ } } -void OverviewGrid::OnPostWindowStateTypeChange( - wm::WindowState* window_state, - mojom::WindowStateType old_type) { +void OverviewGrid::OnPostWindowStateTypeChange(wm::WindowState* window_state, + WindowStateType old_type) { // During preparation, window state can change, e.g. updating shelf // visibility may show the temporarily hidden (minimized) panels. if (!prepared_for_overview_) @@ -947,7 +946,7 @@ return; } - mojom::WindowStateType new_type = window_state->GetStateType(); + WindowStateType new_type = window_state->GetStateType(); if (IsMinimizedWindowStateType(old_type) == IsMinimizedWindowStateType(new_type)) { return;
diff --git a/ash/wm/overview/overview_grid.h b/ash/wm/overview/overview_grid.h index 6d753378d..ef695a1 100644 --- a/ash/wm/overview/overview_grid.h +++ b/ash/wm/overview/overview_grid.h
@@ -184,7 +184,7 @@ // wm::WindowStateObserver: void OnPostWindowStateTypeChange(wm::WindowState* window_state, - mojom::WindowStateType old_type) override; + WindowStateType old_type) override; // ScreenRotationAnimatorObserver: void OnScreenCopiedBeforeRotation() override;
diff --git a/ash/wm/overview/overview_session_unittest.cc b/ash/wm/overview/overview_session_unittest.cc index 6046d366..bb329bc 100644 --- a/ash/wm/overview/overview_session_unittest.cc +++ b/ash/wm/overview/overview_session_unittest.cc
@@ -467,14 +467,14 @@ window_state->OnWMEvent(&minimize_event); EXPECT_FALSE(window->IsVisible()); EXPECT_EQ(0.f, window->layer()->GetTargetOpacity()); - EXPECT_EQ(mojom::WindowStateType::MINIMIZED, + EXPECT_EQ(WindowStateType::kMinimized, wm::GetWindowState(window.get())->GetStateType()); ToggleOverview(); EXPECT_FALSE(window->IsVisible()); EXPECT_EQ(0.f, window->layer()->GetTargetOpacity()); - EXPECT_EQ(mojom::WindowStateType::MINIMIZED, window_state->GetStateType()); + EXPECT_EQ(WindowStateType::kMinimized, window_state->GetStateType()); wm::WindowPreviewView* preview_view = GetPreviewView(GetWindowItemForWindow(0, window.get())); EXPECT_TRUE(preview_view); @@ -487,7 +487,7 @@ EXPECT_TRUE(window->IsVisible()); EXPECT_EQ(1.f, window->layer()->GetTargetOpacity()); - EXPECT_EQ(mojom::WindowStateType::NORMAL, window_state->GetStateType()); + EXPECT_EQ(WindowStateType::kNormal, window_state->GetStateType()); } // Tests that the ordering of windows is stable across different overview @@ -4287,8 +4287,7 @@ DragWindowTo(overview_item1, gfx::PointF(0, 0)); // Since the only window is snapped, overview and splitview should be both // ended. - EXPECT_EQ(window_state1->GetStateType(), - mojom::WindowStateType::LEFT_SNAPPED); + EXPECT_EQ(window_state1->GetStateType(), WindowStateType::kLeftSnapped); EXPECT_FALSE(overview_controller()->InOverviewSession()); EXPECT_FALSE(split_view_controller()->InSplitViewMode()); @@ -4307,8 +4306,7 @@ EXPECT_TRUE(split_view_controller()->IsWindowInSplitView(window1.get())); EXPECT_TRUE(overview_controller()->overview_session()->IsWindowInOverview( window2.get())); - EXPECT_EQ(window_state1->GetStateType(), - mojom::WindowStateType::RIGHT_SNAPPED); + EXPECT_EQ(window_state1->GetStateType(), WindowStateType::kRightSnapped); // Close |window2| will end overview and splitview. window2.reset(); EXPECT_FALSE(overview_controller()->InOverviewSession()); @@ -4322,10 +4320,9 @@ OverviewItem* overview_item3 = GetWindowItemForWindow(grid_index, window3.get()); DragWindowTo(overview_item3, gfx::PointF(600, 300)); - EXPECT_EQ(window_state1->GetStateType(), - mojom::WindowStateType::LEFT_SNAPPED); + EXPECT_EQ(window_state1->GetStateType(), WindowStateType::kLeftSnapped); EXPECT_EQ(wm::GetWindowState(window3.get())->GetStateType(), - mojom::WindowStateType::RIGHT_SNAPPED); + WindowStateType::kRightSnapped); EXPECT_FALSE(overview_controller()->InOverviewSession()); EXPECT_FALSE(split_view_controller()->InSplitViewMode()); @@ -4344,15 +4341,14 @@ window3.get())); EXPECT_FALSE(overview_controller()->overview_session()->IsWindowInOverview( window1.get())); - EXPECT_EQ(window_state1->GetStateType(), - mojom::WindowStateType::LEFT_SNAPPED); + EXPECT_EQ(window_state1->GetStateType(), WindowStateType::kLeftSnapped); EXPECT_EQ(wm::GetWindowState(window3.get())->GetStateType(), - mojom::WindowStateType::LEFT_SNAPPED); + WindowStateType::kLeftSnapped); EXPECT_TRUE(overview_controller()->InOverviewSession()); EXPECT_TRUE(split_view_controller()->InSplitViewMode()); ToggleOverview(); EXPECT_EQ(wm::GetWindowState(window4.get())->GetStateType(), - mojom::WindowStateType::RIGHT_SNAPPED); + WindowStateType::kRightSnapped); EXPECT_FALSE(overview_controller()->InOverviewSession()); EXPECT_FALSE(split_view_controller()->InSplitViewMode());
diff --git a/ash/wm/pip/pip_window_resizer_unittest.cc b/ash/wm/pip/pip_window_resizer_unittest.cc index 4d3b2b6..52232f6 100644 --- a/ash/wm/pip/pip_window_resizer_unittest.cc +++ b/ash/wm/pip/pip_window_resizer_unittest.cc
@@ -38,7 +38,7 @@ // WindowState based on a given initial state. Records the last resize bounds. class FakeWindowState : public wm::WindowState::State { public: - explicit FakeWindowState(mojom::WindowStateType initial_state_type) + explicit FakeWindowState(WindowStateType initial_state_type) : state_type_(initial_state_type) {} ~FakeWindowState() override = default; @@ -54,7 +54,7 @@ } } } - mojom::WindowStateType GetType() const override { return state_type_; } + WindowStateType GetType() const override { return state_type_; } void AttachState(wm::WindowState* window_state, wm::WindowState::State* previous_state) override {} void DetachState(wm::WindowState* window_state) override {} @@ -63,7 +63,7 @@ wm::WindowState* last_window_state() { return last_window_state_; } private: - mojom::WindowStateType state_type_; + WindowStateType state_type_; gfx::Rect last_bounds_; wm::WindowState* last_window_state_ = nullptr; @@ -169,7 +169,7 @@ void PreparePipWindow(const gfx::Rect& bounds) { widget_ = CreateWidgetForTest(bounds); window_ = widget_->GetNativeWindow(); - test_state_ = new FakeWindowState(mojom::WindowStateType::PIP); + test_state_ = new FakeWindowState(WindowStateType::kPip); wm::GetWindowState(window_)->SetStateObject( std::unique_ptr<wm::WindowState::State>(test_state_)); }
diff --git a/ash/wm/property_util.cc b/ash/wm/property_util.cc deleted file mode 100644 index 2f50cbc..0000000 --- a/ash/wm/property_util.cc +++ /dev/null
@@ -1,64 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "ash/wm/property_util.h" - -#include "services/ws/public/cpp/property_type_converters.h" -#include "services/ws/public/mojom/window_manager.mojom.h" -#include "ui/aura/mus/property_converter.h" -#include "ui/aura/window.h" -#include "ui/display/types/display_constants.h" -#include "ui/gfx/geometry/rect.h" -#include "ui/gfx/geometry/size.h" - -namespace ash { - -int64_t GetInitialDisplayId(const InitProperties& properties) { - auto iter = - properties.find(ws::mojom::WindowManager::kDisplayId_InitProperty); - return iter == properties.end() ? display::kInvalidDisplayId - : mojo::ConvertTo<int64_t>(iter->second); -} - -bool GetInitialContainerId(const InitProperties& properties, - int* container_id) { - auto iter = - properties.find(ws::mojom::WindowManager::kContainerId_InitProperty); - if (iter == properties.end()) - return false; - - *container_id = mojo::ConvertTo<int32_t>(iter->second); - return true; -} - -bool GetInitialBounds(const InitProperties& properties, gfx::Rect* bounds) { - auto iter = properties.find(ws::mojom::WindowManager::kBounds_InitProperty); - if (iter == properties.end()) - return false; - - *bounds = mojo::ConvertTo<gfx::Rect>(iter->second); - return true; -} - -bool GetWindowPreferredSize(const InitProperties& properties, gfx::Size* size) { - auto iter = - properties.find(ws::mojom::WindowManager::kPreferredSize_Property); - if (iter == properties.end()) - return false; - - *size = mojo::ConvertTo<gfx::Size>(iter->second); - return true; -} - -void ApplyProperties( - aura::Window* window, - aura::PropertyConverter* property_converter, - const std::map<std::string, std::vector<uint8_t>>& properties) { - for (auto& property_pair : properties) { - property_converter->SetPropertyFromTransportValue( - window, property_pair.first, &property_pair.second); - } -} - -} // namespace ash
diff --git a/ash/wm/property_util.h b/ash/wm/property_util.h deleted file mode 100644 index 3287b02..0000000 --- a/ash/wm/property_util.h +++ /dev/null
@@ -1,64 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef ASH_WM_PROPERTY_UTIL_H_ -#define ASH_WM_PROPERTY_UTIL_H_ - -#include <stdint.h> - -#include <map> -#include <string> -#include <vector> - -namespace aura { -class PropertyConverter; -class Window; -} // namespace aura - -namespace gfx { -class Rect; -class Size; -} // namespace gfx - -namespace ui { -namespace mojom { -enum class WindowType; -} -} // namespace ui - -namespace ash { - -// Functions for extracting properties that are used at a Window creation time. -// Clients pass an initial set of properties when requesting a new aura::Window. -// Not all of these properties need be persisted, some are used solely to -// configure the window. The functions below extract those properties. - -// Long lived properties are converted and stored as properties on the -// associated aura::Window. See aura::PropertyConverter for this set of -// properties. - -using InitProperties = std::map<std::string, std::vector<uint8_t>>; - -// Returns the kDisplayId_InitProperty if present, otherwise -// kInvalidDisplayID. -int64_t GetInitialDisplayId(const InitProperties& properties); - -// If |window| has the |kContainerId_InitProperty| set as a property, then -// the value of |kContainerId_InitProperty| is set in |container_id| and true -// is returned. Otherwise false is returned. -bool GetInitialContainerId(const InitProperties& properties, int* container_id); - -bool GetInitialBounds(const InitProperties& properties, gfx::Rect* bounds); - -bool GetWindowPreferredSize(const InitProperties& properties, gfx::Size* size); - -// Applies |properties| to |window| using |property_converter|. -void ApplyProperties( - aura::Window* window, - aura::PropertyConverter* property_converter, - const std::map<std::string, std::vector<uint8_t>>& properties); - -} // namespace ash - -#endif // ASH_WM_PROPERTY_UTIL_H_
diff --git a/ash/wm/splitview/split_view_controller.cc b/ash/wm/splitview/split_view_controller.cc index 956e538d..47658a42c 100644 --- a/ash/wm/splitview/split_view_controller.cc +++ b/ash/wm/splitview/split_view_controller.cc
@@ -107,15 +107,15 @@ bounds_in_screen.y())); } -mojom::WindowStateType GetStateTypeFromSnapPosition( +WindowStateType GetStateTypeFromSnapPosition( SplitViewController::SnapPosition snap_position) { DCHECK(snap_position != SplitViewController::NONE); if (snap_position == SplitViewController::LEFT) - return mojom::WindowStateType::LEFT_SNAPPED; + return WindowStateType::kLeftSnapped; if (snap_position == SplitViewController::RIGHT) - return mojom::WindowStateType::RIGHT_SNAPPED; + return WindowStateType::kRightSnapped; NOTREACHED(); - return mojom::WindowStateType::DEFAULT; + return WindowStateType::kDefault; } // Returns the minimum size of the window according to the screen orientation. @@ -835,7 +835,7 @@ void SplitViewController::OnPostWindowStateTypeChange( ash::wm::WindowState* window_state, - ash::mojom::WindowStateType old_type) { + ash::WindowStateType old_type) { if (window_state->IsSnapped()) { OnWindowSnapped(window_state->window()); } else if (window_state->IsFullscreen() || window_state->IsMaximized()) {
diff --git a/ash/wm/splitview/split_view_controller.h b/ash/wm/splitview/split_view_controller.h index 8ac554d..0f02817 100644 --- a/ash/wm/splitview/split_view_controller.h +++ b/ash/wm/splitview/split_view_controller.h
@@ -170,9 +170,8 @@ intptr_t old) override; // ash::wm::WindowStateObserver: - void OnPostWindowStateTypeChange( - ash::wm::WindowState* window_state, - ash::mojom::WindowStateType old_type) override; + void OnPostWindowStateTypeChange(ash::wm::WindowState* window_state, + ash::WindowStateType old_type) override; // wm::ActivationChangeObserver: void OnWindowActivated(ActivationReason reason,
diff --git a/ash/wm/tablet_mode/tablet_mode_window_manager.cc b/ash/wm/tablet_mode/tablet_mode_window_manager.cc index e96f941..5ebf496 100644 --- a/ash/wm/tablet_mode/tablet_mode_window_manager.cc +++ b/ash/wm/tablet_mode/tablet_mode_window_manager.cc
@@ -331,13 +331,13 @@ Shell::Get()->mru_window_tracker()->BuildWindowListIgnoreModal(); for (aura::Window* window : windows) { switch (wm::GetWindowState(window)->GetStateType()) { - case mojom::WindowStateType::LEFT_SNAPPED: + case WindowStateType::kLeftSnapped: if (split_view_controller->left_window() == nullptr) { split_view_controller->SnapWindow(window, SplitViewController::LEFT); } break; - case mojom::WindowStateType::RIGHT_SNAPPED: + case WindowStateType::kRightSnapped: if (split_view_controller->right_window() == nullptr) { split_view_controller->SnapWindow(window, SplitViewController::RIGHT); @@ -364,7 +364,7 @@ void TabletModeWindowManager::OnPostWindowStateTypeChange( wm::WindowState* window_state, - mojom::WindowStateType old_type) { + WindowStateType old_type) { Shell::Get()->tablet_mode_controller()->MaybeObserveBoundsAnimation( window_state->window()); } @@ -376,7 +376,7 @@ TabletModeWindowManager::TabletModeWindowManager() = default; -mojom::WindowStateType TabletModeWindowManager::GetDesktopWindowStateType( +WindowStateType TabletModeWindowManager::GetDesktopWindowStateType( aura::Window* window) const { auto iter = window_state_map_.find(window); return iter == window_state_map_.end() @@ -391,25 +391,25 @@ if (!IsCandidateForSplitView(windows, 0u)) return result; switch (GetDesktopWindowStateType(windows[0])) { - case mojom::WindowStateType::LEFT_SNAPPED: + case WindowStateType::kLeftSnapped: // windows[0] was snapped on the left in desktop mode. Snap windows[0] on // the left in split view. If windows[1] was snapped on the right in // desktop mode, then snap windows[1] on the right in split view. result.push_back(SplitViewController::LEFT); if (IsCandidateForSplitView(windows, 1u) && GetDesktopWindowStateType(windows[1]) == - mojom::WindowStateType::RIGHT_SNAPPED) { + WindowStateType::kRightSnapped) { result.push_back(SplitViewController::RIGHT); } return result; - case mojom::WindowStateType::RIGHT_SNAPPED: + case WindowStateType::kRightSnapped: // windows[0] was snapped on the right in desktop mode. Snap windows[0] on // the right in split view. If windows[1] was snapped on the left in // desktop mode, then snap windows[1] on the left in split view. result.push_back(SplitViewController::RIGHT); if (IsCandidateForSplitView(windows, 1u) && GetDesktopWindowStateType(windows[1]) == - mojom::WindowStateType::LEFT_SNAPPED) { + WindowStateType::kLeftSnapped) { result.push_back(SplitViewController::LEFT); } return result;
diff --git a/ash/wm/tablet_mode/tablet_mode_window_manager.h b/ash/wm/tablet_mode/tablet_mode_window_manager.h index 17341a06..8ebfa8be 100644 --- a/ash/wm/tablet_mode/tablet_mode_window_manager.h +++ b/ash/wm/tablet_mode/tablet_mode_window_manager.h
@@ -101,7 +101,7 @@ // wm::WindowStateObserver: void OnPostWindowStateTypeChange(wm::WindowState* window_state, - mojom::WindowStateType old_type) override; + WindowStateType old_type) override; // Tell all managing windows not to handle WM events. void SetIgnoreWmEventsForExit(); @@ -117,7 +117,7 @@ // Returns the state type that |window| had before tablet mode started. If // |window| is not yet tracked, returns the current state type of |window|. - mojom::WindowStateType GetDesktopWindowStateType(aura::Window* window) const; + WindowStateType GetDesktopWindowStateType(aura::Window* window) const; // Returns a std::vector of up to two split view snap positions, parallel to // |windows|, implementing the logic for carrying over snapped window states
diff --git a/ash/wm/tablet_mode/tablet_mode_window_manager_unittest.cc b/ash/wm/tablet_mode/tablet_mode_window_manager_unittest.cc index 5ced090..49eeeda5 100644 --- a/ash/wm/tablet_mode/tablet_mode_window_manager_unittest.cc +++ b/ash/wm/tablet_mode/tablet_mode_window_manager_unittest.cc
@@ -1642,13 +1642,13 @@ // wm::WindowStateObserver: void OnPreWindowStateTypeChange(wm::WindowState* window_state, - mojom::WindowStateType old_type) override { + WindowStateType old_type) override { pre_count_++; last_old_state_ = old_type; } void OnPostWindowStateTypeChange(wm::WindowState* window_state, - mojom::WindowStateType old_type) override { + WindowStateType old_type) override { post_count_++; post_layer_visibility_ = window_state->window()->layer()->visible(); EXPECT_EQ(last_old_state_, old_type); @@ -1672,9 +1672,9 @@ return r; } - mojom::WindowStateType GetLastOldStateAndReset() { - mojom::WindowStateType r = last_old_state_; - last_old_state_ = mojom::WindowStateType::DEFAULT; + WindowStateType GetLastOldStateAndReset() { + WindowStateType r = last_old_state_; + last_old_state_ = WindowStateType::kDefault; return r; } @@ -1682,7 +1682,7 @@ int pre_count_ = 0; int post_count_ = 0; bool post_layer_visibility_ = false; - mojom::WindowStateType last_old_state_ = mojom::WindowStateType::DEFAULT; + WindowStateType last_old_state_ = WindowStateType::kDefault; DISALLOW_COPY_AND_ASSIGN(TestObserver); }; @@ -1715,28 +1715,24 @@ window_state->OnWMEvent(&fullscreen_event); EXPECT_EQ(1, observer.GetPreCountAndReset()); EXPECT_EQ(1, observer.GetPostCountAndReset()); - EXPECT_EQ(mojom::WindowStateType::MAXIMIZED, - observer.GetLastOldStateAndReset()); + EXPECT_EQ(WindowStateType::kMaximized, observer.GetLastOldStateAndReset()); window_state->OnWMEvent(&maximize_event); EXPECT_EQ(1, observer.GetPreCountAndReset()); EXPECT_EQ(1, observer.GetPostCountAndReset()); - EXPECT_EQ(mojom::WindowStateType::FULLSCREEN, - observer.GetLastOldStateAndReset()); + EXPECT_EQ(WindowStateType::kFullscreen, observer.GetLastOldStateAndReset()); wm::WMEvent minimize_event(wm::WM_EVENT_MINIMIZE); window_state->OnWMEvent(&minimize_event); EXPECT_EQ(1, observer.GetPreCountAndReset()); EXPECT_EQ(1, observer.GetPostCountAndReset()); - EXPECT_EQ(mojom::WindowStateType::MAXIMIZED, - observer.GetLastOldStateAndReset()); + EXPECT_EQ(WindowStateType::kMaximized, observer.GetLastOldStateAndReset()); wm::WMEvent restore_event(wm::WM_EVENT_NORMAL); window_state->OnWMEvent(&restore_event); EXPECT_EQ(1, observer.GetPreCountAndReset()); EXPECT_EQ(1, observer.GetPostCountAndReset()); - EXPECT_EQ(mojom::WindowStateType::MINIMIZED, - observer.GetLastOldStateAndReset()); + EXPECT_EQ(WindowStateType::kMinimized, observer.GetLastOldStateAndReset()); EXPECT_EQ(true, observer.GetPostLayerVisibilityAndReset()); window_state->RemoveObserver(&observer);
diff --git a/ash/wm/tablet_mode/tablet_mode_window_state.cc b/ash/wm/tablet_mode/tablet_mode_window_state.cc index 23303a8..93dfb90 100644 --- a/ash/wm/tablet_mode/tablet_mode_window_state.cc +++ b/ash/wm/tablet_mode/tablet_mode_window_state.cc
@@ -83,14 +83,14 @@ state_object->window()); } - if (state_object->GetStateType() == mojom::WindowStateType::LEFT_SNAPPED) { + if (state_object->GetStateType() == WindowStateType::kLeftSnapped) { return Shell::Get() ->split_view_controller() ->GetSnappedWindowBoundsInParent(state_object->window(), SplitViewController::LEFT); } - if (state_object->GetStateType() == mojom::WindowStateType::RIGHT_SNAPPED) { + if (state_object->GetStateType() == WindowStateType::kRightSnapped) { return Shell::Get() ->split_view_controller() ->GetSnappedWindowBoundsInParent(state_object->window(), @@ -221,23 +221,22 @@ ToggleFullScreen(window_state, window_state->delegate()); break; case wm::WM_EVENT_FULLSCREEN: - UpdateWindow(window_state, mojom::WindowStateType::FULLSCREEN, + UpdateWindow(window_state, WindowStateType::kFullscreen, true /* animated */); break; case wm::WM_EVENT_PIN: if (!Shell::Get()->screen_pinning_controller()->IsPinned()) - UpdateWindow(window_state, mojom::WindowStateType::PINNED, + UpdateWindow(window_state, WindowStateType::kPinned, true /* animated */); break; case wm::WM_EVENT_PIP: if (!window_state->IsPip()) { - UpdateWindow(window_state, mojom::WindowStateType::PIP, - true /* animated */); + UpdateWindow(window_state, WindowStateType::kPip, true /* animated */); } break; case wm::WM_EVENT_TRUSTED_PIN: if (!Shell::Get()->screen_pinning_controller()->IsPinned()) - UpdateWindow(window_state, mojom::WindowStateType::TRUSTED_PINNED, + UpdateWindow(window_state, WindowStateType::kTrustedPinned, true /* animated */); break; case wm::WM_EVENT_TOGGLE_MAXIMIZE_CAPTION: @@ -257,8 +256,8 @@ // place the window. window_state->set_bounds_changed_by_user(true); UpdateWindow(window_state, - GetSnappedWindowStateType( - window_state, mojom::WindowStateType::LEFT_SNAPPED), + GetSnappedWindowStateType(window_state, + WindowStateType::kLeftSnapped), false /* animated */); return; case wm::WM_EVENT_SNAP_RIGHT: @@ -266,12 +265,12 @@ // place the window. window_state->set_bounds_changed_by_user(true); UpdateWindow(window_state, - GetSnappedWindowStateType( - window_state, mojom::WindowStateType::RIGHT_SNAPPED), + GetSnappedWindowStateType(window_state, + WindowStateType::kRightSnapped), false /* animated */); return; case wm::WM_EVENT_MINIMIZE: - UpdateWindow(window_state, mojom::WindowStateType::MINIMIZED, + UpdateWindow(window_state, WindowStateType::kMinimized, true /* animated */); return; case wm::WM_EVENT_SHOW_INACTIVE: @@ -289,18 +288,17 @@ // dragged window's source window, we may need to update its bounds // during dragging. window_state->SetBoundsDirect(bounds_in_parent); - } else if (current_state_type_ == mojom::WindowStateType::MAXIMIZED) { + } else if (current_state_type_ == WindowStateType::kMaximized) { // Having a maximized window, it could have been created with an empty // size and the caller should get his size upon leaving the maximized // mode. As such we set the restore bounds to the requested bounds. window_state->SetRestoreBoundsInParent(bounds_in_parent); - } else if (current_state_type_ != mojom::WindowStateType::MINIMIZED && - current_state_type_ != mojom::WindowStateType::FULLSCREEN && - current_state_type_ != mojom::WindowStateType::PINNED && - current_state_type_ != - mojom::WindowStateType::TRUSTED_PINNED && - current_state_type_ != mojom::WindowStateType::LEFT_SNAPPED && - current_state_type_ != mojom::WindowStateType::RIGHT_SNAPPED) { + } else if (current_state_type_ != WindowStateType::kMinimized && + current_state_type_ != WindowStateType::kFullscreen && + current_state_type_ != WindowStateType::kPinned && + current_state_type_ != WindowStateType::kTrustedPinned && + current_state_type_ != WindowStateType::kLeftSnapped && + current_state_type_ != WindowStateType::kRightSnapped) { // In all other cases (except for minimized windows) we respect the // requested bounds and center it to a fully visible area on the screen. bounds_in_parent = GetCenteredBounds(bounds_in_parent, window_state); @@ -316,27 +314,27 @@ break; } case wm::WM_EVENT_ADDED_TO_WORKSPACE: - if (current_state_type_ != mojom::WindowStateType::MAXIMIZED && - current_state_type_ != mojom::WindowStateType::FULLSCREEN && - current_state_type_ != mojom::WindowStateType::MINIMIZED) { - mojom::WindowStateType new_state = + if (current_state_type_ != WindowStateType::kMaximized && + current_state_type_ != WindowStateType::kFullscreen && + current_state_type_ != WindowStateType::kMinimized) { + WindowStateType new_state = GetMaximizedOrCenteredWindowType(window_state); UpdateWindow(window_state, new_state, true /* animated */); } break; case wm::WM_EVENT_WORKAREA_BOUNDS_CHANGED: - if (current_state_type_ != mojom::WindowStateType::MINIMIZED) + if (current_state_type_ != WindowStateType::kMinimized) UpdateBounds(window_state, true /* animated */); break; case wm::WM_EVENT_DISPLAY_BOUNDS_CHANGED: // Don't animate on a screen rotation - just snap to new size. - if (current_state_type_ != mojom::WindowStateType::MINIMIZED) + if (current_state_type_ != WindowStateType::kMinimized) UpdateBounds(window_state, false /* animated */); break; } } -mojom::WindowStateType TabletModeWindowState::GetType() const { +WindowStateType TabletModeWindowState::GetType() const { return current_state_type_; } @@ -353,11 +351,11 @@ window_state->GetShowState()); } - if (current_state_type_ != mojom::WindowStateType::MAXIMIZED && - current_state_type_ != mojom::WindowStateType::MINIMIZED && - current_state_type_ != mojom::WindowStateType::FULLSCREEN && - current_state_type_ != mojom::WindowStateType::PINNED && - current_state_type_ != mojom::WindowStateType::TRUSTED_PINNED) { + if (current_state_type_ != WindowStateType::kMaximized && + current_state_type_ != WindowStateType::kMinimized && + current_state_type_ != WindowStateType::kFullscreen && + current_state_type_ != WindowStateType::kPinned && + current_state_type_ != WindowStateType::kTrustedPinned) { UpdateWindow(window_state, state_type_on_attach_, animate_bounds_on_attach_); } @@ -370,33 +368,33 @@ } void TabletModeWindowState::UpdateWindow(wm::WindowState* window_state, - mojom::WindowStateType target_state, + WindowStateType target_state, bool animated) { - DCHECK(target_state == mojom::WindowStateType::MINIMIZED || - target_state == mojom::WindowStateType::MAXIMIZED || - target_state == mojom::WindowStateType::PINNED || - target_state == mojom::WindowStateType::TRUSTED_PINNED || - (target_state == mojom::WindowStateType::NORMAL && + DCHECK(target_state == WindowStateType::kMinimized || + target_state == WindowStateType::kMaximized || + target_state == WindowStateType::kPinned || + target_state == WindowStateType::kTrustedPinned || + (target_state == WindowStateType::kNormal && (!window_state->CanMaximize() || !!::wm::GetTransientParent(window_state->window()))) || - target_state == mojom::WindowStateType::FULLSCREEN || - target_state == mojom::WindowStateType::LEFT_SNAPPED || - target_state == mojom::WindowStateType::RIGHT_SNAPPED); + target_state == WindowStateType::kFullscreen || + target_state == WindowStateType::kLeftSnapped || + target_state == WindowStateType::kRightSnapped); if (current_state_type_ == target_state) { - if (target_state == mojom::WindowStateType::MINIMIZED) + if (target_state == WindowStateType::kMinimized) return; // If the state type did not change, update it accordingly. UpdateBounds(window_state, animated); return; } - const mojom::WindowStateType old_state_type = current_state_type_; + const WindowStateType old_state_type = current_state_type_; current_state_type_ = target_state; window_state->UpdateWindowPropertiesFromStateType(); window_state->NotifyPreStateTypeChange(old_state_type); - if (target_state == mojom::WindowStateType::MINIMIZED) { + if (target_state == WindowStateType::kMinimized) { ::wm::SetWindowVisibilityAnimationType( window_state->window(), wm::WINDOW_VISIBILITY_ANIMATION_TYPE_MINIMIZE); window_state->window()->Hide(); @@ -407,7 +405,7 @@ } if ((window_state->window()->layer()->GetTargetVisibility() || - old_state_type == mojom::WindowStateType::MINIMIZED) && + old_state_type == WindowStateType::kMinimized) && !window_state->window()->layer()->visible()) { // The layer may be hidden if the window was previously minimized. Make // sure it's visible. @@ -416,28 +414,28 @@ window_state->NotifyPostStateTypeChange(old_state_type); - if (old_state_type == mojom::WindowStateType::PINNED || - target_state == mojom::WindowStateType::PINNED || - old_state_type == mojom::WindowStateType::TRUSTED_PINNED || - target_state == mojom::WindowStateType::TRUSTED_PINNED) { + if (old_state_type == WindowStateType::kPinned || + target_state == WindowStateType::kPinned || + old_state_type == WindowStateType::kTrustedPinned || + target_state == WindowStateType::kTrustedPinned) { Shell::Get()->screen_pinning_controller()->SetPinnedWindow( window_state->window()); } } -mojom::WindowStateType TabletModeWindowState::GetMaximizedOrCenteredWindowType( +WindowStateType TabletModeWindowState::GetMaximizedOrCenteredWindowType( wm::WindowState* window_state) { return (window_state->CanMaximize() && ::wm::GetTransientParent(window_state->window()) == nullptr) - ? mojom::WindowStateType::MAXIMIZED - : mojom::WindowStateType::NORMAL; + ? WindowStateType::kMaximized + : WindowStateType::kNormal; } -mojom::WindowStateType TabletModeWindowState::GetSnappedWindowStateType( +WindowStateType TabletModeWindowState::GetSnappedWindowStateType( wm::WindowState* window_state, - mojom::WindowStateType target_state) { - DCHECK(target_state == mojom::WindowStateType::LEFT_SNAPPED || - target_state == mojom::WindowStateType::RIGHT_SNAPPED); + WindowStateType target_state) { + DCHECK(target_state == WindowStateType::kLeftSnapped || + target_state == WindowStateType::kRightSnapped); return CanSnapInSplitview(window_state->window()) ? target_state : GetMaximizedOrCenteredWindowType(window_state); @@ -451,7 +449,7 @@ return; // Do not update minimized windows bounds until it was unminimized. - if (current_state_type_ == mojom::WindowStateType::MINIMIZED) + if (current_state_type_ == WindowStateType::kMinimized) return; gfx::Rect bounds_in_parent = GetBoundsInTabletMode(window_state);
diff --git a/ash/wm/tablet_mode/tablet_mode_window_state.h b/ash/wm/tablet_mode/tablet_mode_window_state.h index 9d99267e..4c8e8e88 100644 --- a/ash/wm/tablet_mode/tablet_mode_window_state.h +++ b/ash/wm/tablet_mode/tablet_mode_window_state.h
@@ -47,7 +47,7 @@ void OnWMEvent(wm::WindowState* window_state, const wm::WMEvent* event) override; - mojom::WindowStateType GetType() const override; + WindowStateType GetType() const override; void AttachState(wm::WindowState* window_state, wm::WindowState::State* previous_state) override; void DetachState(wm::WindowState* window_state) override; @@ -60,21 +60,20 @@ // change, only the bounds will be changed. If |animate| is set, the bound // change get animated. void UpdateWindow(wm::WindowState* window_state, - mojom::WindowStateType new_state_type, + WindowStateType new_state_type, bool animate); // Depending on the capabilities of the window we either return - // |WindowStateType::MAXIMIZED| or |WindowStateType::NORMAL|. - mojom::WindowStateType GetMaximizedOrCenteredWindowType( + // |WindowStateType::kMaximized| or |WindowStateType::kNormal|. + WindowStateType GetMaximizedOrCenteredWindowType( wm::WindowState* window_state); // If |target_state| is LEFT/RIGHT_SNAPPED and the window can be snapped, // returns |target_state|. Otherwise depending on the capabilities of the - // window either returns |WindowStateType::MAXIMIZED| or - // |WindowStateType::NORMAL|. - mojom::WindowStateType GetSnappedWindowStateType( - wm::WindowState* window_state, - mojom::WindowStateType target_state); + // window either returns |WindowStateType::kMaximized| or + // |WindowStateType::kNormal|. + WindowStateType GetSnappedWindowStateType(wm::WindowState* window_state, + WindowStateType target_state); // Updates the bounds to the maximum possible bounds according to the current // window state. If |animated| is set we animate the change. @@ -95,7 +94,7 @@ // The state type to be established in AttachState(), unless // previous_state->GetType() is MAXIMIZED, MINIMIZED, FULLSCREEN, PINNED, or // TRUSTED_PINNED. - mojom::WindowStateType state_type_on_attach_; + WindowStateType state_type_on_attach_; // Whether to animate in case of a bounds update when switching to // |state_type_on_attach_|. @@ -103,7 +102,7 @@ // The current state type. Due to the nature of this state, this can only be // WM_STATE_TYPE{NORMAL, MINIMIZED, MAXIMIZED}. - mojom::WindowStateType current_state_type_; + WindowStateType current_state_type_; // If true, the state will not process events. bool ignore_wm_events_ = false;
diff --git a/ash/wm/top_level_window_factory.cc b/ash/wm/top_level_window_factory.cc deleted file mode 100644 index 0e12e2b..0000000 --- a/ash/wm/top_level_window_factory.cc +++ /dev/null
@@ -1,232 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "ash/wm/top_level_window_factory.h" - -#include "ash/disconnected_app_handler.h" -#include "ash/public/cpp/shell_window_ids.h" -#include "ash/public/cpp/window_properties.h" -#include "ash/public/interfaces/window_properties.mojom.h" -#include "ash/root_window_controller.h" -#include "ash/root_window_settings.h" -#include "ash/shell.h" -#include "ash/window_factory.h" -#include "ash/wm/container_finder.h" -#include "ash/wm/non_client_frame_controller.h" -#include "ash/wm/property_util.h" -#include "ash/wm/window_state.h" -#include "mojo/public/cpp/bindings/type_converter.h" -#include "services/ws/public/cpp/property_type_converters.h" -#include "services/ws/public/mojom/window_manager.mojom.h" -#include "services/ws/public/mojom/window_tree_constants.mojom.h" -#include "services/ws/top_level_proxy_window.h" -#include "services/ws/window_delegate_impl.h" -#include "services/ws/window_properties.h" -#include "ui/aura/client/aura_constants.h" -#include "ui/aura/mus/property_converter.h" -#include "ui/aura/mus/property_utils.h" -#include "ui/aura/window.h" -#include "ui/display/display.h" -#include "ui/display/screen.h" -#include "ui/views/widget/widget.h" -#include "ui/wm/core/coordinate_conversion.h" - -namespace ash { -namespace { - -// Returns true if a fullscreen window was requested. -bool IsFullscreen(aura::PropertyConverter* property_converter, - const std::vector<uint8_t>& transport_data) { - using ws::mojom::WindowManager; - aura::PropertyConverter::PrimitiveType show_state = 0; - return property_converter->GetPropertyValueFromTransportValue( - WindowManager::kShowState_Property, transport_data, &show_state) && - (static_cast<ui::WindowShowState>(show_state) == - ui::SHOW_STATE_FULLSCREEN); -} - -// Returns the RootWindowController where new top levels are created. -// |properties| is the properties supplied during window creation. -RootWindowController* GetRootWindowControllerForNewTopLevelWindow( - std::map<std::string, std::vector<uint8_t>>* properties) { - // If a specific display was requested, use it. If no display was requested, - // choose one based on the requested initial bounds. - int64_t display_id = GetInitialDisplayId(*properties); - gfx::Rect requested_bounds; - if (display_id == display::kInvalidDisplayId && - GetInitialBounds(*properties, &requested_bounds)) { - display_id = - display::Screen::GetScreen()->GetDisplayMatching(requested_bounds).id(); - } - - if (display_id != display::kInvalidDisplayId) { - for (RootWindowController* root_window_controller : - RootWindowController::root_window_controllers()) { - if (GetRootWindowSettings(root_window_controller->GetRootWindow()) - ->display_id == display_id) { - return root_window_controller; - } - } - } - - return RootWindowController::ForWindow(Shell::GetRootWindowForNewWindows()); -} - -// Returns the bounds for the new window. If |container_window| is provided the -// bounds are local to the container, otherwise they are in screen coordinates. -gfx::Rect CalculateDefaultBounds( - aura::Window* root_window, - aura::Window* container_window, - aura::PropertyConverter* property_converter, - const std::map<std::string, std::vector<uint8_t>>* properties) { - gfx::Rect requested_bounds; - if (GetInitialBounds(*properties, &requested_bounds)) - return requested_bounds; - - const gfx::Size root_size = root_window->bounds().size(); - auto show_state_iter = - properties->find(ws::mojom::WindowManager::kShowState_Property); - if (show_state_iter != properties->end()) { - if (IsFullscreen(property_converter, show_state_iter->second)) { - gfx::Rect bounds(root_size); - if (!container_window) { - // Ensure the window is placed on the correct display. - ::wm::ConvertRectToScreen(root_window, &bounds); - } - return bounds; - } - } - - gfx::Size window_size; - if (GetWindowPreferredSize(*properties, &window_size) && - !window_size.IsEmpty()) { - // TODO(sky): likely want to constrain more than root size. - window_size.SetToMin(root_size); - } else { - // Pick a fixed default size. Most applications will immediately set the - // bounds and/or center the window, so the user usually won't see this. - window_size.SetSize(300, 200); - } - // TODO(sky): this should use code in chrome/browser/ui/window_sizer. - static constexpr int kOriginOffset = 40; - gfx::Rect bounds(gfx::Point(kOriginOffset, kOriginOffset), window_size); - if (!container_window) { - // Ensure the window is placed on the correct display. - ::wm::ConvertRectToScreen(root_window, &bounds); - } - return bounds; -} - -// Does the real work of CreateAndParentTopLevelWindow() once the appropriate -// RootWindowController was found. -aura::Window* CreateAndParentTopLevelWindowInRoot( - ws::TopLevelProxyWindow* top_level_proxy_window, - RootWindowController* root_window_controller, - ws::mojom::WindowType window_type, - aura::PropertyConverter* property_converter, - std::map<std::string, std::vector<uint8_t>>* properties) { - // TODO(sky): constrain and validate properties. - aura::Window* root_window = root_window_controller->GetRootWindow(); - - int32_t container_id = kShellWindowId_Invalid; - aura::Window* context = nullptr; - aura::Window* container_window = nullptr; - if (GetInitialContainerId(*properties, &container_id)) { - container_window = root_window->GetChildById(container_id); - } else { - context = root_window; - } - - gfx::Rect bounds = CalculateDefaultBounds(root_window, container_window, - property_converter, properties); - - const bool provide_non_client_frame = - window_type == ws::mojom::WindowType::WINDOW; - if (provide_non_client_frame) { - // See NonClientFrameController for details on lifetime. - NonClientFrameController* non_client_frame_controller = - new NonClientFrameController(top_level_proxy_window, container_window, - context, bounds, property_converter, - properties); - return non_client_frame_controller->window(); - } - - // WindowDelegateImpl() deletes itself when the associated window is - // destroyed. - ws::WindowDelegateImpl* window_delegate = new ws::WindowDelegateImpl(); - aura::Window* window = window_factory::NewWindow(window_delegate).release(); - window_delegate->set_window(window); - aura::SetWindowType(window, window_type); - ApplyProperties(window, property_converter, *properties); - window->Init(ui::LAYER_NOT_DRAWN); - - if (container_window) { - // |bounds| are in local coordinates. - container_window->AddChild(window); - window->SetBounds(bounds); - } else { - // |bounds| are in screen coordinates. - aura::Window* parent = ash::wm::GetDefaultParent(window, bounds); - parent->AddChild(window); - gfx::Rect bounds_in_parent = bounds; - ::wm::ConvertRectFromScreen(parent, &bounds_in_parent); - window->SetBounds(bounds_in_parent); - } - return window; -} - -} // namespace - -aura::Window* CreateAndParentTopLevelWindow( - ws::TopLevelProxyWindow* top_level_proxy_window, - ws::mojom::WindowType window_type, - aura::PropertyConverter* property_converter, - std::map<std::string, std::vector<uint8_t>>* properties) { - if (window_type == ws::mojom::WindowType::UNKNOWN) - return nullptr; // Clients must supply a valid type. - - RootWindowController* root_window_controller = - GetRootWindowControllerForNewTopLevelWindow(properties); - aura::Window* window = CreateAndParentTopLevelWindowInRoot( - top_level_proxy_window, root_window_controller, window_type, - property_converter, properties); - DisconnectedAppHandler::Create(window); - - // TODO: kFocusable_InitProperty should be removed. http://crbug.com/837713. - auto focusable_iter = - properties->find(ws::mojom::WindowManager::kFocusable_InitProperty); - if (focusable_iter != properties->end()) { - bool can_focus = mojo::ConvertTo<bool>(focusable_iter->second); - NonClientFrameController* non_client_frame_controller = - NonClientFrameController::Get(window); - window->SetProperty(ws::kCanFocus, can_focus); - if (non_client_frame_controller) - non_client_frame_controller->SetCanActivate(can_focus); - // No need to persist this value. - properties->erase(focusable_iter); - } - - auto translucent_iter = - properties->find(ws::mojom::WindowManager::kTranslucent_InitProperty); - if (translucent_iter != properties->end()) { - bool translucent = mojo::ConvertTo<bool>(translucent_iter->second); - window->SetTransparent(translucent); - // No need to persist this value. - properties->erase(translucent_iter); - } - - auto hide_in_overview_iter = - properties->find(ash::mojom::kHideInOverview_Property); - if (hide_in_overview_iter != properties->end()) { - bool hide_in_overview = - mojo::ConvertTo<bool>(hide_in_overview_iter->second); - window->SetProperty(kHideInOverviewKey, hide_in_overview); - // No need to persist this value. - properties->erase(hide_in_overview_iter); - } - - return window; -} - -} // namespace ash
diff --git a/ash/wm/top_level_window_factory.h b/ash/wm/top_level_window_factory.h deleted file mode 100644 index 45b1482..0000000 --- a/ash/wm/top_level_window_factory.h +++ /dev/null
@@ -1,41 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef ASH_WM_TOP_LEVEL_WINDOW_FACTORY_H_ -#define ASH_WM_TOP_LEVEL_WINDOW_FACTORY_H_ - -#include <stdint.h> - -#include <map> -#include <string> -#include <vector> - -#include "ash/ash_export.h" - -namespace aura { -class PropertyConverter; -class Window; -} - -namespace ws { -namespace mojom { -enum class WindowType; -} -class TopLevelProxyWindow; -} // namespace ws - -namespace ash { - -// Creates and parents a new top-level window and returns it. The returned -// aura::Window is owned by its parent. A value of null is returned if invalid -// poarameters are supplied. -ASH_EXPORT aura::Window* CreateAndParentTopLevelWindow( - ws::TopLevelProxyWindow* top_level_proxy_window, - ws::mojom::WindowType window_type, - aura::PropertyConverter* property_converter, - std::map<std::string, std::vector<uint8_t>>* properties); - -} // namespace ash - -#endif // ASH_WM_TOP_LEVEL_WINDOW_FACTORY_H_
diff --git a/ash/wm/toplevel_window_event_handler.cc b/ash/wm/toplevel_window_event_handler.cc index 00e9bf8a..eaa24ef3 100644 --- a/ash/wm/toplevel_window_event_handler.cc +++ b/ash/wm/toplevel_window_event_handler.cc
@@ -183,7 +183,7 @@ // WindowStateObserver overrides: void OnPreWindowStateTypeChange(wm::WindowState* window_state, - mojom::WindowStateType type) override; + WindowStateType type) override; private: ToplevelWindowEventHandler* handler_; @@ -237,7 +237,7 @@ void ToplevelWindowEventHandler::ScopedWindowResizer:: OnPreWindowStateTypeChange(wm::WindowState* window_state, - mojom::WindowStateType old) { + WindowStateType old) { handler_->CompleteDrag(DragResult::SUCCESS); }
diff --git a/ash/wm/toplevel_window_event_handler_unittest.cc b/ash/wm/toplevel_window_event_handler_unittest.cc index 448b62f4..16862ff 100644 --- a/ash/wm/toplevel_window_event_handler_unittest.cc +++ b/ash/wm/toplevel_window_event_handler_unittest.cc
@@ -525,8 +525,7 @@ // Verify that the window has moved after the gesture. EXPECT_NE(old_bounds.ToString(), target->bounds().ToString()); - EXPECT_EQ(mojom::WindowStateType::RIGHT_SNAPPED, - window_state->GetStateType()); + EXPECT_EQ(WindowStateType::kRightSnapped, window_state->GetStateType()); old_bounds = target->bounds(); @@ -538,7 +537,7 @@ base::RunLoop().RunUntilIdle(); EXPECT_NE(old_bounds.ToString(), target->bounds().ToString()); - EXPECT_EQ(mojom::WindowStateType::LEFT_SNAPPED, window_state->GetStateType()); + EXPECT_EQ(WindowStateType::kLeftSnapped, window_state->GetStateType()); gfx::Rect bounds_before_maximization = target->bounds(); bounds_before_maximization.Offset(0, 100); @@ -596,8 +595,7 @@ // Verify that the window has moved after the gesture. EXPECT_NE(old_bounds.ToString(), target->bounds().ToString()); - EXPECT_EQ(mojom::WindowStateType::RIGHT_SNAPPED, - window_state->GetStateType()); + EXPECT_EQ(WindowStateType::kRightSnapped, window_state->GetStateType()); } // Tests that a gesture cannot minimize an unminimizeable window.
diff --git a/ash/wm/window_mirror_view.cc b/ash/wm/window_mirror_view.cc index 0323f81..d5c56b0e 100644 --- a/ash/wm/window_mirror_view.cc +++ b/ash/wm/window_mirror_view.cc
@@ -7,10 +7,8 @@ #include <algorithm> #include <memory> -#include "ash/wm/non_client_frame_controller.h" #include "ash/wm/widget_finder.h" #include "ash/wm/window_state.h" -#include "services/ws/top_level_proxy_window.h" #include "ui/aura/client/aura_constants.h" #include "ui/aura/env.h" #include "ui/aura/window.h" @@ -108,7 +106,6 @@ target_->TrackOcclusionState(); force_occlusion_tracker_visible_.reset(); - force_proxy_window_visible_.reset(); env_observer_.RemoveAll(); // Wait for window-occlusion tracker to be running before forcing visibility. @@ -173,16 +170,6 @@ force_occlusion_tracker_visible_ = std::make_unique<aura::WindowOcclusionTracker::ScopedForceVisible>( source_); - - NonClientFrameController* frame_controller = - NonClientFrameController::Get(source_); - if (frame_controller) { - // In order for the remote client to produce frames the client needs to - // think the window is visible. It may not actually be visible now, so force - // it. - force_proxy_window_visible_ = - frame_controller->top_level_proxy_window()->ForceVisible(); - } } void WindowMirrorView::OnWindowOcclusionTrackingResumed() {
diff --git a/ash/wm/window_mirror_view.h b/ash/wm/window_mirror_view.h index 9237b7b..d682a42 100644 --- a/ash/wm/window_mirror_view.h +++ b/ash/wm/window_mirror_view.h
@@ -24,10 +24,6 @@ class LayerTreeOwner; } -namespace ws { -class ScopedForceVisible; -} - namespace ash { namespace wm { @@ -88,7 +84,6 @@ std::unique_ptr<aura::WindowOcclusionTracker::ScopedForceVisible> force_occlusion_tracker_visible_; - std::unique_ptr<ws::ScopedForceVisible> force_proxy_window_visible_; ScopedObserver<aura::Env, aura::EnvObserver> env_observer_{this};
diff --git a/ash/wm/window_state.cc b/ash/wm/window_state.cc index e8da38a..54387f6 100644 --- a/ash/wm/window_state.cc +++ b/ash/wm/window_state.cc
@@ -15,7 +15,6 @@ #include "ash/public/cpp/window_properties.h" #include "ash/public/cpp/window_state_type.h" #include "ash/public/interfaces/window_pin_type.mojom.h" -#include "ash/public/interfaces/window_state_type.mojom.h" #include "ash/screen_util.h" #include "ash/shell.h" #include "ash/wm/collision_detection/collision_detection_utils.h" @@ -200,48 +199,48 @@ delegate_ = std::move(delegate); } -mojom::WindowStateType WindowState::GetStateType() const { +WindowStateType WindowState::GetStateType() const { return current_state_->GetType(); } bool WindowState::IsMinimized() const { - return GetStateType() == mojom::WindowStateType::MINIMIZED; + return GetStateType() == WindowStateType::kMinimized; } bool WindowState::IsMaximized() const { - return GetStateType() == mojom::WindowStateType::MAXIMIZED; + return GetStateType() == WindowStateType::kMaximized; } bool WindowState::IsFullscreen() const { - return GetStateType() == mojom::WindowStateType::FULLSCREEN; + return GetStateType() == WindowStateType::kFullscreen; } bool WindowState::IsMaximizedOrFullscreenOrPinned() const { - return GetStateType() == mojom::WindowStateType::MAXIMIZED || - GetStateType() == mojom::WindowStateType::FULLSCREEN || IsPinned(); + return GetStateType() == WindowStateType::kMaximized || + GetStateType() == WindowStateType::kFullscreen || IsPinned(); } bool WindowState::IsSnapped() const { - return GetStateType() == mojom::WindowStateType::LEFT_SNAPPED || - GetStateType() == mojom::WindowStateType::RIGHT_SNAPPED; + return GetStateType() == WindowStateType::kLeftSnapped || + GetStateType() == WindowStateType::kRightSnapped; } bool WindowState::IsPinned() const { - return GetStateType() == mojom::WindowStateType::PINNED || - GetStateType() == mojom::WindowStateType::TRUSTED_PINNED; + return GetStateType() == WindowStateType::kPinned || + GetStateType() == WindowStateType::kTrustedPinned; } bool WindowState::IsTrustedPinned() const { - return GetStateType() == mojom::WindowStateType::TRUSTED_PINNED; + return GetStateType() == WindowStateType::kTrustedPinned; } bool WindowState::IsPip() const { - return GetStateType() == mojom::WindowStateType::PIP; + return GetStateType() == WindowStateType::kPip; } bool WindowState::IsNormalStateType() const { - return GetStateType() == mojom::WindowStateType::NORMAL || - GetStateType() == mojom::WindowStateType::DEFAULT; + return GetStateType() == WindowStateType::kNormal || + GetStateType() == WindowStateType::kDefault; } bool WindowState::IsNormalOrSnapped() const { @@ -552,7 +551,7 @@ ignore_property_change_(false), current_state_(new DefaultState(ToWindowStateType(GetShowState()))) { window_->AddObserver(this); - OnPrePipStateChange(mojom::WindowStateType::DEFAULT); + OnPrePipStateChange(WindowStateType::kDefault); } bool WindowState::GetAlwaysOnTop() const { @@ -582,9 +581,9 @@ bounds->set_width( static_cast<int>(*snapped_width_ratio_ * maximized_bounds.width())); } - if (GetStateType() == mojom::WindowStateType::LEFT_SNAPPED) + if (GetStateType() == WindowStateType::kLeftSnapped) bounds->set_x(maximized_bounds.x()); - else if (GetStateType() == mojom::WindowStateType::RIGHT_SNAPPED) + else if (GetStateType() == WindowStateType::kRightSnapped) bounds->set_x(maximized_bounds.right() - bounds->width()); bounds->set_y(maximized_bounds.y()); bounds->set_height(maximized_bounds.height()); @@ -611,9 +610,9 @@ // sync up current window show state with PinType property. ash::mojom::WindowPinType pin_type = ash::mojom::WindowPinType::NONE; - if (GetStateType() == mojom::WindowStateType::PINNED) + if (GetStateType() == WindowStateType::kPinned) pin_type = ash::mojom::WindowPinType::PINNED; - else if (GetStateType() == mojom::WindowStateType::TRUSTED_PINNED) + else if (GetStateType() == WindowStateType::kTrustedPinned) pin_type = ash::mojom::WindowPinType::TRUSTED_PINNED; if (pin_type != GetPinType()) { base::AutoReset<bool> resetter(&ignore_property_change_, true); @@ -622,22 +621,21 @@ } void WindowState::NotifyPreStateTypeChange( - mojom::WindowStateType old_window_state_type) { + WindowStateType old_window_state_type) { for (auto& observer : observer_list_) observer.OnPreWindowStateTypeChange(this, old_window_state_type); OnPrePipStateChange(old_window_state_type); } void WindowState::NotifyPostStateTypeChange( - mojom::WindowStateType old_window_state_type) { + WindowStateType old_window_state_type) { for (auto& observer : observer_list_) observer.OnPostWindowStateTypeChange(this, old_window_state_type); OnPostPipStateChange(old_window_state_type); } -void WindowState::OnPostPipStateChange( - mojom::WindowStateType old_window_state_type) { - if (old_window_state_type == mojom::WindowStateType::PIP) { +void WindowState::OnPostPipStateChange(WindowStateType old_window_state_type) { + if (old_window_state_type == WindowStateType::kPip) { // The animation type may be FADE_OUT_SLIDE_IN at this point, which we don't // want it to be anymore if the window is not PIP anymore. ::wm::SetWindowVisibilityAnimationType( @@ -721,8 +719,7 @@ CrossFadeAnimation(window_, std::move(old_layer_owner), animation_type); } -void WindowState::OnPrePipStateChange( - mojom::WindowStateType old_window_state_type) { +void WindowState::OnPrePipStateChange(WindowStateType old_window_state_type) { auto* widget = views::Widget::GetWidgetForNativeWindow(window()); if (IsPip()) { CollisionDetectionUtils::MarkWindowPriorityForCollisionDetection( @@ -739,13 +736,13 @@ window(), WINDOW_VISIBILITY_ANIMATION_TYPE_FADE_IN_SLIDE_OUT); // There may already be a system ui window on the initial position. UpdatePipBounds(); - if (old_window_state_type != mojom::WindowStateType::PIP) { + if (old_window_state_type != WindowStateType::kPip) { window()->SetProperty(ash::kPrePipWindowStateTypeKey, old_window_state_type); } CollectPipEnterExitMetrics(window(), /*enter=*/true); - } else if (old_window_state_type == mojom::WindowStateType::PIP) { + } else if (old_window_state_type == WindowStateType::kPip) { if (widget) { widget->widget_delegate()->SetCanActivate(true); Shell::Get()->focus_cycler()->RemoveWidget(widget);
diff --git a/ash/wm/window_state.h b/ash/wm/window_state.h index 40e4aad4..6d166044 100644 --- a/ash/wm/window_state.h +++ b/ash/wm/window_state.h
@@ -9,7 +9,6 @@ #include "ash/ash_export.h" #include "ash/display/persistent_window_info.h" -#include "ash/public/interfaces/window_state_type.mojom.h" #include "ash/wm/drag_details.h" #include "base/gtest_prod_util.h" #include "base/macros.h" @@ -28,6 +27,7 @@ namespace ash { class LockWindowState; class TabletModeWindowState; +enum class WindowStateType; namespace mojom { enum class WindowPinType; @@ -84,7 +84,7 @@ // Update WindowState based on |event|. virtual void OnWMEvent(WindowState* window_state, const WMEvent* event) = 0; - virtual mojom::WindowStateType GetType() const = 0; + virtual WindowStateType GetType() const = 0; // Gets called when the state object became active and the managed window // needs to be adjusted to the State's requirement. @@ -127,7 +127,7 @@ // Returns the window's current ash state type. // Refer to WindowStateType definition in wm_types.h as for why Ash // has its own state type. - mojom::WindowStateType GetStateType() const; + WindowStateType GetStateType() const; // Predicates to check window state. bool IsMinimized() const; @@ -138,12 +138,12 @@ bool IsTrustedPinned() const; bool IsPip() const; - // True if the window's state type is WindowStateType::MAXIMIZED, - // WindowStateType::FULLSCREEN or WindowStateType::PINNED. + // True if the window's state type is WindowStateType::kMaximized, + // WindowStateType::kFullscreen or WindowStateType::kPinned. bool IsMaximizedOrFullscreenOrPinned() const; - // True if the window's state type is WindowStateType::NORMAL or - // WindowStateType::DEFAULT. + // True if the window's state type is WindowStateType::kNormal or + // WindowStateType::kDefault. bool IsNormalStateType() const; bool IsNormalOrSnapped() const; @@ -401,8 +401,8 @@ // Note that this does not update the window bounds. void UpdateWindowPropertiesFromStateType(); - void NotifyPreStateTypeChange(mojom::WindowStateType old_window_state_type); - void NotifyPostStateTypeChange(mojom::WindowStateType old_window_state_type); + void NotifyPreStateTypeChange(WindowStateType old_window_state_type); + void NotifyPostStateTypeChange(WindowStateType old_window_state_type); // Sets |bounds| as is and ensure the layer is aligned with pixel boundary. void SetBoundsDirect(const gfx::Rect& bounds); @@ -425,11 +425,11 @@ // Called before the state change and update PIP related state, such as next // window animation type, upon state change. - void OnPrePipStateChange(mojom::WindowStateType old_window_state_type); + void OnPrePipStateChange(WindowStateType old_window_state_type); // Called after the state change and update PIP related state, such as next // window animation type, upon state change. - void OnPostPipStateChange(mojom::WindowStateType old_window_state_type); + void OnPostPipStateChange(WindowStateType old_window_state_type); // Update the PIP bounds if necessary. This may need to happen when the // display work area changes, or if system ui regions like the virtual
diff --git a/ash/wm/window_state_observer.h b/ash/wm/window_state_observer.h index f0cd857..1eb02419 100644 --- a/ash/wm/window_state_observer.h +++ b/ash/wm/window_state_observer.h
@@ -9,9 +9,7 @@ namespace ash { -namespace mojom { enum class WindowStateType; -} namespace wm { class WindowState; @@ -30,13 +28,13 @@ // This is used to update the shell state such as work area so // that the window can use the correct environment to update its bounds. virtual void OnPreWindowStateTypeChange(WindowState* window_state, - mojom::WindowStateType old_type) {} + WindowStateType old_type) {} // Called after the window's state has been updated. // This is used to update the shell state that depends on the updated // window bounds, such as shelf visibility. virtual void OnPostWindowStateTypeChange(WindowState* window_state, - mojom::WindowStateType old_type) {} + WindowStateType old_type) {} }; } // namespace wm
diff --git a/ash/wm/window_state_unittest.cc b/ash/wm/window_state_unittest.cc index 3296d6f..38c7f42 100644 --- a/ash/wm/window_state_unittest.cc +++ b/ash/wm/window_state_unittest.cc
@@ -24,7 +24,7 @@ #include "ui/events/test/event_generator.h" #include "ui/wm/core/window_util.h" -using ash::mojom::WindowStateType; +using ash::WindowStateType; namespace ash { namespace wm { @@ -44,9 +44,9 @@ void AttachState(WindowState* window_state, WindowState::State* previous_state) override { // We always maximize. - if (state_type_ != mojom::WindowStateType::MAXIMIZED) { + if (state_type_ != WindowStateType::kMaximized) { window_state->Maximize(); - state_type_ = mojom::WindowStateType::MAXIMIZED; + state_type_ = WindowStateType::kMaximized; } } void DetachState(WindowState* window_state) override {} @@ -378,7 +378,7 @@ WindowState* window_state = GetWindowState(window.get()); const WMEvent cycle_snap_left(WM_EVENT_CYCLE_SNAP_LEFT); window_state->OnWMEvent(&cycle_snap_left); - EXPECT_EQ(mojom::WindowStateType::LEFT_SNAPPED, window_state->GetStateType()); + EXPECT_EQ(WindowStateType::kLeftSnapped, window_state->GetStateType()); gfx::Rect expected = gfx::Rect(kWorkAreaBounds.x(), kWorkAreaBounds.y(), kWorkAreaBounds.width() / 2, kWorkAreaBounds.height()); @@ -395,18 +395,18 @@ generator->ReleaseLeftButton(); expected.set_width(expected.width() + kIncreasedWidth); EXPECT_EQ(expected, window->GetBoundsInScreen()); - EXPECT_EQ(mojom::WindowStateType::LEFT_SNAPPED, window_state->GetStateType()); + EXPECT_EQ(WindowStateType::kLeftSnapped, window_state->GetStateType()); EXPECT_EQ(0.75f, *window_state->snapped_width_ratio()); // Another cycle snap left event will restore window state to normal. window_state->OnWMEvent(&cycle_snap_left); - EXPECT_EQ(mojom::WindowStateType::NORMAL, window_state->GetStateType()); + EXPECT_EQ(WindowStateType::kNormal, window_state->GetStateType()); EXPECT_FALSE(window_state->snapped_width_ratio()); // Another cycle snap left event will snap window and reset snapped width // ratio. window_state->OnWMEvent(&cycle_snap_left); - EXPECT_EQ(mojom::WindowStateType::LEFT_SNAPPED, window_state->GetStateType()); + EXPECT_EQ(WindowStateType::kLeftSnapped, window_state->GetStateType()); EXPECT_EQ(0.5f, *window_state->snapped_width_ratio()); } @@ -706,7 +706,7 @@ EXPECT_TRUE(window_state->IsMinimized()); window_state->Unminimize(); - EXPECT_TRUE(window_state->GetStateType() == mojom::WindowStateType::NORMAL); + EXPECT_TRUE(window_state->GetStateType() == WindowStateType::kNormal); } TEST_F(WindowStateTest, RestoreStateAfterEnterPipViaMinimizeAndDismissingPip) { @@ -747,7 +747,7 @@ EXPECT_TRUE(window_state->IsMinimized()); window_state->Unminimize(); - EXPECT_TRUE(window_state->GetStateType() == mojom::WindowStateType::NORMAL); + EXPECT_TRUE(window_state->GetStateType() == WindowStateType::kNormal); } TEST_F(WindowStateTest, SetBoundsUpdatesSizeOfPipRestoreBounds) {
diff --git a/ash/wm/window_util_unittest.cc b/ash/wm/window_util_unittest.cc index 2978e1f..892a349 100644 --- a/ash/wm/window_util_unittest.cc +++ b/ash/wm/window_util_unittest.cc
@@ -33,9 +33,7 @@ if (event->type() == WM_EVENT_MINIMIZE) was_visible_on_minimize_ = window_state->window()->IsVisible(); } - mojom::WindowStateType GetType() const override { - return mojom::WindowStateType::NORMAL; - } + WindowStateType GetType() const override { return WindowStateType::kNormal; } void AttachState(WindowState* window_state, WindowState::State* previous_state) override {} void DetachState(WindowState* window_state) override {}
diff --git a/ash/wm/workspace/backdrop_controller.cc b/ash/wm/workspace/backdrop_controller.cc index da90575d..24467bdb7 100644 --- a/ash/wm/workspace/backdrop_controller.cc +++ b/ash/wm/workspace/backdrop_controller.cc
@@ -89,20 +89,19 @@ Hide(); } -void BackdropController::OnWindowAddedToLayout(aura::Window* child) { +void BackdropController::OnWindowAddedToLayout() { UpdateBackdrop(); } -void BackdropController::OnWindowRemovedFromLayout(aura::Window* child) { +void BackdropController::OnWindowRemovedFromLayout() { UpdateBackdrop(); } -void BackdropController::OnChildWindowVisibilityChanged(aura::Window* child, - bool visible) { +void BackdropController::OnChildWindowVisibilityChanged() { UpdateBackdrop(); } -void BackdropController::OnWindowStackingChanged(aura::Window* window) { +void BackdropController::OnWindowStackingChanged() { UpdateBackdrop(); } @@ -110,9 +109,7 @@ UpdateBackdrop(); } -void BackdropController::OnPostWindowStateTypeChange( - wm::WindowState* window_state, - mojom::WindowStateType old_type) { +void BackdropController::OnPostWindowStateTypeChange() { UpdateBackdrop(); }
diff --git a/ash/wm/workspace/backdrop_controller.h b/ash/wm/workspace/backdrop_controller.h index adb59f62..421a0af 100644 --- a/ash/wm/workspace/backdrop_controller.h +++ b/ash/wm/workspace/backdrop_controller.h
@@ -28,13 +28,6 @@ } namespace ash { -namespace mojom { -enum class WindowStateType; -} - -namespace wm { -class WindowState; -} class BackdropDelegate; @@ -54,12 +47,11 @@ explicit BackdropController(aura::Window* container); ~BackdropController() override; - void OnWindowAddedToLayout(aura::Window* child); - void OnWindowRemovedFromLayout(aura::Window* child); - void OnChildWindowVisibilityChanged(aura::Window* child, bool visible); - void OnWindowStackingChanged(aura::Window* window); - void OnPostWindowStateTypeChange(wm::WindowState* window_state, - mojom::WindowStateType old_type); + void OnWindowAddedToLayout(); + void OnWindowRemovedFromLayout(); + void OnChildWindowVisibilityChanged(); + void OnWindowStackingChanged(); + void OnPostWindowStateTypeChange(); void OnDisplayMetricsChanged(); void SetBackdropDelegate(std::unique_ptr<BackdropDelegate> delegate);
diff --git a/ash/wm/workspace/multi_window_resize_controller.cc b/ash/wm/workspace/multi_window_resize_controller.cc index 700a817f..1ccc424 100644 --- a/ash/wm/workspace/multi_window_resize_controller.cc +++ b/ash/wm/workspace/multi_window_resize_controller.cc
@@ -281,7 +281,7 @@ void MultiWindowResizeController::OnPostWindowStateTypeChange( wm::WindowState* window_state, - mojom::WindowStateType old_type) { + WindowStateType old_type) { if (window_state->IsMaximized() || window_state->IsFullscreen() || window_state->IsMinimized()) { ResetResizer();
diff --git a/ash/wm/workspace/multi_window_resize_controller.h b/ash/wm/workspace/multi_window_resize_controller.h index 0d561429..1cf3667 100644 --- a/ash/wm/workspace/multi_window_resize_controller.h +++ b/ash/wm/workspace/multi_window_resize_controller.h
@@ -57,7 +57,7 @@ // wm::WindowStateObserver: void OnPostWindowStateTypeChange(wm::WindowState* window_state, - mojom::WindowStateType old_type) override; + WindowStateType old_type) override; private: friend class MultiWindowResizeControllerTest;
diff --git a/ash/wm/workspace/multi_window_resize_controller_unittest.cc b/ash/wm/workspace/multi_window_resize_controller_unittest.cc index bf8a03e..074d552d 100644 --- a/ash/wm/workspace/multi_window_resize_controller_unittest.cc +++ b/ash/wm/workspace/multi_window_resize_controller_unittest.cc
@@ -573,7 +573,7 @@ wm::WindowState* w1_state = wm::GetWindowState(w1.get()); const wm::WMEvent snap_left(wm::WM_EVENT_SNAP_LEFT); w1_state->OnWMEvent(&snap_left); - EXPECT_EQ(mojom::WindowStateType::LEFT_SNAPPED, w1_state->GetStateType()); + EXPECT_EQ(WindowStateType::kLeftSnapped, w1_state->GetStateType()); aura::test::TestWindowDelegate delegate2; std::unique_ptr<aura::Window> w2(CreateTestWindowInShellWithDelegate( &delegate2, -2, gfx::Rect(100, 100, 100, 100))); @@ -581,7 +581,7 @@ wm::WindowState* w2_state = wm::GetWindowState(w2.get()); const wm::WMEvent snap_right(wm::WM_EVENT_SNAP_RIGHT); w2_state->OnWMEvent(&snap_right); - EXPECT_EQ(mojom::WindowStateType::RIGHT_SNAPPED, w2_state->GetStateType()); + EXPECT_EQ(WindowStateType::kRightSnapped, w2_state->GetStateType()); EXPECT_EQ(0.5f, *w1_state->snapped_width_ratio()); EXPECT_EQ(0.5f, *w2_state->snapped_width_ratio()); @@ -613,9 +613,9 @@ generator->ReleaseLeftButton(); // Check snapped states and bounds. - EXPECT_EQ(mojom::WindowStateType::LEFT_SNAPPED, w1_state->GetStateType()); + EXPECT_EQ(WindowStateType::kLeftSnapped, w1_state->GetStateType()); EXPECT_EQ(gfx::Rect(0, 0, 300, bottom_inset), w1->bounds()); - EXPECT_EQ(mojom::WindowStateType::RIGHT_SNAPPED, w2_state->GetStateType()); + EXPECT_EQ(WindowStateType::kRightSnapped, w2_state->GetStateType()); EXPECT_EQ(gfx::Rect(300, 0, 100, bottom_inset), w2->bounds()); EXPECT_EQ(0.75f, *w1_state->snapped_width_ratio()); EXPECT_EQ(0.25f, *w2_state->snapped_width_ratio());
diff --git a/ash/wm/workspace/workspace_event_handler_unittest.cc b/ash/wm/workspace/workspace_event_handler_unittest.cc index 800e76e..6b5f3e4 100644 --- a/ash/wm/workspace/workspace_event_handler_unittest.cc +++ b/ash/wm/workspace/workspace_event_handler_unittest.cc
@@ -228,7 +228,7 @@ window.get()); delegate.set_window_component(HTTOP); generator.DoubleClickLeftButton(); - EXPECT_EQ(mojom::WindowStateType::LEFT_SNAPPED, window_state->GetStateType()); + EXPECT_EQ(WindowStateType::kLeftSnapped, window_state->GetStateType()); EXPECT_EQ(snapped_bounds_in_screen.ToString(), window->GetBoundsInScreen().ToString());
diff --git a/ash/wm/workspace/workspace_layout_manager.cc b/ash/wm/workspace/workspace_layout_manager.cc index 9885db5..b4c8580 100644 --- a/ash/wm/workspace/workspace_layout_manager.cc +++ b/ash/wm/workspace/workspace_layout_manager.cc
@@ -154,7 +154,7 @@ UpdateShelfVisibility(); UpdateFullscreenState(); - backdrop_controller_->OnWindowAddedToLayout(child); + backdrop_controller_->OnWindowAddedToLayout(); WindowPositioner::RearrangeVisibleWindowOnShow(child); if (Shell::Get()->screen_pinning_controller()->IsPinned()) wm::GetWindowState(child)->DisableAlwaysOnTop(nullptr); @@ -184,7 +184,7 @@ void WorkspaceLayoutManager::OnWindowRemovedFromLayout(aura::Window* child) { UpdateShelfVisibility(); UpdateFullscreenState(); - backdrop_controller_->OnWindowRemovedFromLayout(child); + backdrop_controller_->OnWindowRemovedFromLayout(); } void WorkspaceLayoutManager::OnChildWindowVisibilityChanged(aura::Window* child, @@ -200,7 +200,7 @@ WindowPositioner::RearrangeVisibleWindowOnHideOrRemove(child); UpdateFullscreenState(); UpdateShelfVisibility(); - backdrop_controller_->OnChildWindowVisibilityChanged(child, visible); + backdrop_controller_->OnChildWindowVisibilityChanged(); } void WorkspaceLayoutManager::SetChildBounds(aura::Window* child, @@ -323,7 +323,7 @@ void WorkspaceLayoutManager::OnWindowStackingChanged(aura::Window* window) { UpdateShelfVisibility(); UpdateFullscreenState(); - backdrop_controller_->OnWindowStackingChanged(window); + backdrop_controller_->OnWindowStackingChanged(); } void WorkspaceLayoutManager::OnWindowDestroying(aura::Window* window) { @@ -378,15 +378,15 @@ void WorkspaceLayoutManager::OnPostWindowStateTypeChange( wm::WindowState* window_state, - mojom::WindowStateType old_type) { + WindowStateType old_type) { // Notify observers that fullscreen state may be changing. if (window_state->IsFullscreen() || - old_type == mojom::WindowStateType::FULLSCREEN) { + old_type == WindowStateType::kFullscreen) { UpdateFullscreenState(); } UpdateShelfVisibility(); - backdrop_controller_->OnPostWindowStateTypeChange(window_state, old_type); + backdrop_controller_->OnPostWindowStateTypeChange(); } //////////////////////////////////////////////////////////////////////////////
diff --git a/ash/wm/workspace/workspace_layout_manager.h b/ash/wm/workspace/workspace_layout_manager.h index 79efeaa7..f0fb9b4 100644 --- a/ash/wm/workspace/workspace_layout_manager.h +++ b/ash/wm/workspace/workspace_layout_manager.h
@@ -94,7 +94,7 @@ // WindowStateObserver: void OnPostWindowStateTypeChange(wm::WindowState* window_state, - mojom::WindowStateType old_type) override; + WindowStateType old_type) override; // display::DisplayObserver: void OnDisplayMetricsChanged(const display::Display& display,
diff --git a/ash/wm/workspace/workspace_layout_manager_unittest.cc b/ash/wm/workspace/workspace_layout_manager_unittest.cc index c93bb92c..5d6c7c736 100644 --- a/ash/wm/workspace/workspace_layout_manager_unittest.cc +++ b/ash/wm/workspace/workspace_layout_manager_unittest.cc
@@ -594,7 +594,7 @@ Shell::Get()->SetDisplayWorkAreaInsets(window.get(), insets); const wm::WMEvent snap_left(wm::WM_EVENT_SNAP_LEFT); window_state->OnWMEvent(&snap_left); - EXPECT_EQ(mojom::WindowStateType::LEFT_SNAPPED, window_state->GetStateType()); + EXPECT_EQ(WindowStateType::kLeftSnapped, window_state->GetStateType()); const gfx::Rect kWorkAreaBounds = GetPrimaryDisplay().work_area(); gfx::Rect expected_bounds = gfx::Rect(kWorkAreaBounds.x(), kWorkAreaBounds.y(), @@ -1922,9 +1922,7 @@ if (event->type() == wm::WM_EVENT_SYSTEM_UI_AREA_CHANGED) num_system_ui_area_changes_++; } - mojom::WindowStateType GetType() const override { - return mojom::WindowStateType::NORMAL; - } + WindowStateType GetType() const override { return WindowStateType::kNormal; } void AttachState(wm::WindowState* window_state, wm::WindowState::State* previous_state) override {} void DetachState(wm::WindowState* window_state) override {}
diff --git a/ash/wm/workspace/workspace_window_resizer.cc b/ash/wm/workspace/workspace_window_resizer.cc index 9f1cf81..8d55bda 100644 --- a/ash/wm/workspace/workspace_window_resizer.cc +++ b/ash/wm/workspace/workspace_window_resizer.cc
@@ -530,7 +530,7 @@ if (details().window_component == HTCAPTION || !AreBoundsValidSnappedBounds(window_state()->GetStateType(), GetTarget()->bounds())) { - // Set the window to WindowStateType::NORMAL but keep the + // Set the window to WindowStateType::kNormal but keep the // window at the bounds that the user has moved/resized the // window to. window_state()->SaveCurrentBoundsForRestore(); @@ -596,20 +596,17 @@ } if (event->details().velocity_y() > kMinVertVelocityForWindowMinimize) { - SetWindowStateTypeFromGesture(GetTarget(), - mojom::WindowStateType::MINIMIZED); + SetWindowStateTypeFromGesture(GetTarget(), WindowStateType::kMinimized); } else if (event->details().velocity_y() < -kMinVertVelocityForWindowMinimize) { - SetWindowStateTypeFromGesture(GetTarget(), - mojom::WindowStateType::MAXIMIZED); + SetWindowStateTypeFromGesture(GetTarget(), WindowStateType::kMaximized); } else if (event->details().velocity_x() > kMinHorizVelocityForWindowSwipe) { SetWindowStateTypeFromGesture(GetTarget(), - mojom::WindowStateType::RIGHT_SNAPPED); + WindowStateType::kRightSnapped); } else if (event->details().velocity_x() < -kMinHorizVelocityForWindowSwipe) { - SetWindowStateTypeFromGesture(GetTarget(), - mojom::WindowStateType::LEFT_SNAPPED); + SetWindowStateTypeFromGesture(GetTarget(), WindowStateType::kLeftSnapped); } } else { DCHECK_EQ(event->type(), ui::ET_GESTURE_SWIPE); @@ -622,17 +619,14 @@ CompleteDrag(); if (event->details().swipe_down()) { - SetWindowStateTypeFromGesture(GetTarget(), - mojom::WindowStateType::MINIMIZED); + SetWindowStateTypeFromGesture(GetTarget(), WindowStateType::kMinimized); } else if (event->details().swipe_up()) { - SetWindowStateTypeFromGesture(GetTarget(), - mojom::WindowStateType::MAXIMIZED); + SetWindowStateTypeFromGesture(GetTarget(), WindowStateType::kMaximized); } else if (event->details().swipe_right()) { SetWindowStateTypeFromGesture(GetTarget(), - mojom::WindowStateType::RIGHT_SNAPPED); + WindowStateType::kRightSnapped); } else { - SetWindowStateTypeFromGesture(GetTarget(), - mojom::WindowStateType::LEFT_SNAPPED); + SetWindowStateTypeFromGesture(GetTarget(), WindowStateType::kLeftSnapped); } } event->StopPropagation(); @@ -1149,13 +1143,13 @@ } bool WorkspaceWindowResizer::AreBoundsValidSnappedBounds( - mojom::WindowStateType snapped_type, + WindowStateType snapped_type, const gfx::Rect& bounds_in_parent) const { - DCHECK(snapped_type == mojom::WindowStateType::LEFT_SNAPPED || - snapped_type == mojom::WindowStateType::RIGHT_SNAPPED); + DCHECK(snapped_type == WindowStateType::kLeftSnapped || + snapped_type == WindowStateType::kRightSnapped); gfx::Rect snapped_bounds = screen_util::GetDisplayWorkAreaBoundsInParent(GetTarget()); - if (snapped_type == mojom::WindowStateType::RIGHT_SNAPPED) + if (snapped_type == WindowStateType::kRightSnapped) snapped_bounds.set_x(snapped_bounds.right() - bounds_in_parent.width()); snapped_bounds.set_width(bounds_in_parent.width()); return bounds_in_parent == snapped_bounds; @@ -1163,33 +1157,33 @@ void WorkspaceWindowResizer::SetWindowStateTypeFromGesture( aura::Window* window, - mojom::WindowStateType new_state_type) { + WindowStateType new_state_type) { wm::WindowState* window_state = wm::GetWindowState(window); // TODO(oshima): Move extra logic (set_unminimize_to_restore_bounds, // SetRestoreBoundsInParent) that modifies the window state // into WindowState. switch (new_state_type) { - case mojom::WindowStateType::MINIMIZED: + case WindowStateType::kMinimized: if (window_state->CanMinimize()) { window_state->Minimize(); window_state->set_unminimize_to_restore_bounds(true); window_state->SetRestoreBoundsInParent(pre_drag_window_bounds_); } break; - case mojom::WindowStateType::MAXIMIZED: + case WindowStateType::kMaximized: if (window_state->CanMaximize()) { window_state->SetRestoreBoundsInParent(pre_drag_window_bounds_); window_state->Maximize(); } break; - case mojom::WindowStateType::LEFT_SNAPPED: + case WindowStateType::kLeftSnapped: if (window_state->CanSnap()) { window_state->SetRestoreBoundsInParent(pre_drag_window_bounds_); const wm::WMEvent event(wm::WM_EVENT_SNAP_LEFT); window_state->OnWMEvent(&event); } break; - case mojom::WindowStateType::RIGHT_SNAPPED: + case WindowStateType::kRightSnapped: if (window_state->CanSnap()) { window_state->SetRestoreBoundsInParent(pre_drag_window_bounds_); const wm::WMEvent event(wm::WM_EVENT_SNAP_RIGHT);
diff --git a/ash/wm/workspace/workspace_window_resizer.h b/ash/wm/workspace/workspace_window_resizer.h index 3712df0..15afd7d 100644 --- a/ash/wm/workspace/workspace_window_resizer.h +++ b/ash/wm/workspace/workspace_window_resizer.h
@@ -158,13 +158,13 @@ // Returns true if |bounds_in_parent| are valid bounds for snapped state type // |snapped_type|. - bool AreBoundsValidSnappedBounds(mojom::WindowStateType snapped_type, + bool AreBoundsValidSnappedBounds(WindowStateType snapped_type, const gfx::Rect& bounds_in_parent) const; // Sets |window|'s state type to |new_state_type|. Called after the drag has // been completed for fling/swipe gestures. void SetWindowStateTypeFromGesture(aura::Window* window, - mojom::WindowStateType new_state_type); + WindowStateType new_state_type); wm::WindowState* window_state() { return window_state_; }
diff --git a/ash/wm/workspace/workspace_window_resizer_unittest.cc b/ash/wm/workspace/workspace_window_resizer_unittest.cc index d2b3bc6..25aca010 100644 --- a/ash/wm/workspace/workspace_window_resizer_unittest.cc +++ b/ash/wm/workspace/workspace_window_resizer_unittest.cc
@@ -76,7 +76,7 @@ // WindowState based on a given initial state. Records the last resize bounds. class FakeWindowState : public wm::WindowState::State { public: - explicit FakeWindowState(mojom::WindowStateType initial_state_type) + explicit FakeWindowState(WindowStateType initial_state_type) : state_type_(initial_state_type) {} ~FakeWindowState() override = default; @@ -91,7 +91,7 @@ } } } - mojom::WindowStateType GetType() const override { return state_type_; } + WindowStateType GetType() const override { return state_type_; } void AttachState(wm::WindowState* window_state, wm::WindowState::State* previous_state) override {} void DetachState(wm::WindowState* window_state) override {} @@ -99,7 +99,7 @@ const gfx::Rect& last_bounds() { return last_bounds_; } private: - mojom::WindowStateType state_type_; + WindowStateType state_type_; gfx::Rect last_bounds_; DISALLOW_COPY_AND_ASSIGN(FakeWindowState); @@ -695,7 +695,7 @@ window_->Show(); const wm::WMEvent snap_event(wm::WM_EVENT_SNAP_LEFT); window_state->OnWMEvent(&snap_event); - EXPECT_EQ(mojom::WindowStateType::LEFT_SNAPPED, window_state->GetStateType()); + EXPECT_EQ(WindowStateType::kLeftSnapped, window_state->GetStateType()); gfx::Rect snapped_bounds = window_->bounds(); EXPECT_NE(snapped_bounds.ToString(), kInitialBounds.ToString()); EXPECT_EQ(window_state->GetRestoreBoundsInParent().ToString(), @@ -706,7 +706,7 @@ CreateResizerForTest(window_.get(), gfx::Point(), HTCAPTION)); resizer->Drag(CalculateDragPoint(*resizer, 10, 0), 0); resizer->CompleteDrag(); - EXPECT_EQ(mojom::WindowStateType::NORMAL, window_state->GetStateType()); + EXPECT_EQ(WindowStateType::kNormal, window_state->GetStateType()); EXPECT_EQ("10,0 100x100", window_->bounds().ToString()); EXPECT_FALSE(window_state->HasRestoreBounds()); } @@ -721,7 +721,7 @@ const wm::WMEvent snap_event(wm::WM_EVENT_SNAP_LEFT); window_state->OnWMEvent(&snap_event); - EXPECT_EQ(mojom::WindowStateType::LEFT_SNAPPED, window_state->GetStateType()); + EXPECT_EQ(WindowStateType::kLeftSnapped, window_state->GetStateType()); gfx::Rect snapped_bounds = window_->bounds(); EXPECT_NE(snapped_bounds.ToString(), kInitialBounds.ToString()); EXPECT_EQ(window_state->GetRestoreBoundsInParent().ToString(), @@ -734,8 +734,7 @@ CreateResizerForTest(window_.get(), gfx::Point(), HTRIGHT)); resizer->Drag(CalculateDragPoint(*resizer, 10, 0), 0); resizer->CompleteDrag(); - EXPECT_EQ(mojom::WindowStateType::LEFT_SNAPPED, - window_state->GetStateType()); + EXPECT_EQ(WindowStateType::kLeftSnapped, window_state->GetStateType()); snapped_bounds.Inset(0, 0, -10, 0); EXPECT_EQ(snapped_bounds.ToString(), window_->bounds().ToString()); EXPECT_EQ(window_state->GetRestoreBoundsInParent().ToString(), @@ -750,8 +749,7 @@ resizer->Drag(CalculateDragPoint(*resizer, 0, -30), 0); resizer->Drag(CalculateDragPoint(*resizer, 0, 0), 0); resizer->CompleteDrag(); - EXPECT_EQ(mojom::WindowStateType::LEFT_SNAPPED, - window_state->GetStateType()); + EXPECT_EQ(WindowStateType::kLeftSnapped, window_state->GetStateType()); EXPECT_EQ(snapped_bounds.ToString(), window_->bounds().ToString()); EXPECT_EQ(window_state->GetRestoreBoundsInParent().ToString(), kInitialBounds.ToString()); @@ -764,7 +762,7 @@ CreateResizerForTest(window_.get(), gfx::Point(), HTBOTTOM)); resizer->Drag(CalculateDragPoint(*resizer, 0, -10), 0); resizer->CompleteDrag(); - EXPECT_EQ(mojom::WindowStateType::NORMAL, window_state->GetStateType()); + EXPECT_EQ(WindowStateType::kNormal, window_state->GetStateType()); gfx::Rect expected_bounds(snapped_bounds); expected_bounds.Inset(0, 0, 0, 10); EXPECT_EQ(expected_bounds.ToString(), window_->bounds().ToString());
diff --git a/base/BUILD.gn b/base/BUILD.gn index 0b03c11..cebe549 100644 --- a/base/BUILD.gn +++ b/base/BUILD.gn
@@ -311,6 +311,7 @@ "hash/md5.h", "hash/sha1.cc", "hash/sha1.h", + "immediate_crash.h", "ios/block_types.h", "ios/crb_protocol_observers.h", "ios/crb_protocol_observers.mm", @@ -2467,6 +2468,7 @@ "i18n/string_search_unittest.cc", "i18n/time_formatting_unittest.cc", "i18n/timezone_unittest.cc", + "immediate_crash_unittest.cc", "ios/crb_protocol_observers_unittest.mm", "ios/device_util_unittest.mm", "ios/weak_nsobject_unittest.mm", @@ -2629,7 +2631,6 @@ "task/thread_pool/sequence_sort_key_unittest.cc", "task/thread_pool/sequence_unittest.cc", "task/thread_pool/service_thread_unittest.cc", - "task/thread_pool/task_source_unittest.cc", "task/thread_pool/task_tracker_unittest.cc", "task/thread_pool/test_task_factory.cc", "task/thread_pool/test_task_factory.h", @@ -2769,6 +2770,7 @@ ] data_deps = [ + "//base/test:immediate_crash_test_helper", "//base/test:test_child_process", "//base/test:test_shared_library", ]
diff --git a/base/android/child_process_service.cc b/base/android/child_process_service.cc index 8ec6e62..0418e60 100644 --- a/base/android/child_process_service.cc +++ b/base/android/child_process_service.cc
@@ -71,7 +71,11 @@ _exit(0); } -void JNI_ChildProcessService_DumpProcessStack(JNIEnv* env) { +// Make sure this isn't inlined so it shows up in stack traces. +// the function body unique by adding a log line, so it doesn't get merged +// with other functions by link time optimizations (ICF). +NOINLINE void JNI_ChildProcessService_DumpProcessStack(JNIEnv* env) { + LOG(ERROR) << "Dumping as requested."; base::debug::DumpWithoutCrashing(); }
diff --git a/base/debug/gdi_debug_util_win.cc b/base/debug/gdi_debug_util_win.cc index bf9827c..a2bb410 100644 --- a/base/debug/gdi_debug_util_win.cc +++ b/base/debug/gdi_debug_util_win.cc
@@ -17,9 +17,73 @@ namespace { -void CollectChildGDIUsageAndDie(DWORD parent_pid) { +constexpr size_t kLotsOfMemory = 1500 * 1024 * 1024; // 1.5GB + +HANDLE NOINLINE GetToolhelpSnapshot() { HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); CHECK_NE(INVALID_HANDLE_VALUE, snapshot); + return snapshot; +} + +void NOINLINE GetFirstProcess(HANDLE snapshot, PROCESSENTRY32* proc_entry) { + proc_entry->dwSize = sizeof(PROCESSENTRY32); + CHECK(Process32First(snapshot, proc_entry)); +} + +void NOINLINE CrashIfExcessiveHandles(DWORD num_gdi_handles) { + // By default, Windows 10 allows a max of 10,000 GDI handles per process. + // Number found by inspecting + // + // HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\ + // CurrentVersion\Windows\GDIProcessHandleQuota + // + // on a Windows 10 laptop. + static constexpr DWORD kLotsOfHandles = 9990; + CHECK_LE(num_gdi_handles, kLotsOfHandles); +} + +void NOINLINE +CrashIfPagefileUsageTooLarge(const PROCESS_MEMORY_COUNTERS_EX& pmc) { + CHECK_LE(pmc.PagefileUsage, kLotsOfMemory); +} + +void NOINLINE +CrashIfPrivateUsageTooLarge(const PROCESS_MEMORY_COUNTERS_EX& pmc) { + CHECK_LE(pmc.PrivateUsage, kLotsOfMemory); +} + +void NOINLINE CrashIfCannotAllocateSmallBitmap(BITMAPINFOHEADER* header, + HANDLE shared_section) { + void* small_data = nullptr; + base::debug::Alias(&small_data); + header->biWidth = 5; + header->biHeight = -5; + HBITMAP small_bitmap = + CreateDIBSection(nullptr, reinterpret_cast<BITMAPINFO*>(&header), 0, + &small_data, shared_section, 0); + CHECK(small_bitmap != nullptr); + DeleteObject(small_bitmap); +} + +void NOINLINE GetProcessMemoryInfo(PROCESS_MEMORY_COUNTERS_EX* pmc) { + pmc->cb = sizeof(*pmc); + CHECK(GetProcessMemoryInfo(GetCurrentProcess(), + reinterpret_cast<PROCESS_MEMORY_COUNTERS*>(pmc), + sizeof(*pmc))); +} + +DWORD NOINLINE GetNumGdiHandles() { + DWORD num_gdi_handles = GetGuiResources(GetCurrentProcess(), GR_GDIOBJECTS); + if (num_gdi_handles == 0) { + DWORD get_gui_resources_error = GetLastError(); + base::debug::Alias(&get_gui_resources_error); + CHECK(false); + } + return num_gdi_handles; +} + +void CollectChildGDIUsageAndDie(DWORD parent_pid) { + HANDLE snapshot = GetToolhelpSnapshot(); int total_process_count = 0; base::debug::Alias(&total_process_count); @@ -39,9 +103,8 @@ int sum_user_count = 0; base::debug::Alias(&sum_user_count); - PROCESSENTRY32 proc_entry = {0}; - proc_entry.dwSize = sizeof(PROCESSENTRY32); - CHECK(Process32First(snapshot, &proc_entry)); + PROCESSENTRY32 proc_entry = {}; + GetFirstProcess(snapshot, &proc_entry); do { base::win::ScopedHandle process( @@ -95,43 +158,23 @@ base::debug::Alias(&shared_section); DWORD num_user_handles = GetGuiResources(GetCurrentProcess(), GR_USEROBJECTS); - - DWORD num_gdi_handles = GetGuiResources(GetCurrentProcess(), GR_GDIOBJECTS); - if (num_gdi_handles == 0) { - DWORD get_gui_resources_error = GetLastError(); - base::debug::Alias(&get_gui_resources_error); - CHECK(false); - } + DWORD num_gdi_handles = GetNumGdiHandles(); base::debug::Alias(&num_gdi_handles); base::debug::Alias(&num_user_handles); - const DWORD kLotsOfHandles = 9990; - CHECK_LE(num_gdi_handles, kLotsOfHandles); + CrashIfExcessiveHandles(num_gdi_handles); PROCESS_MEMORY_COUNTERS_EX pmc; - pmc.cb = sizeof(pmc); - CHECK(GetProcessMemoryInfo(GetCurrentProcess(), - reinterpret_cast<PROCESS_MEMORY_COUNTERS*>(&pmc), - sizeof(pmc))); - const size_t kLotsOfMemory = 1500 * 1024 * 1024; // 1.5GB - CHECK_LE(pmc.PagefileUsage, kLotsOfMemory); - CHECK_LE(pmc.PrivateUsage, kLotsOfMemory); - - void* small_data = nullptr; - base::debug::Alias(&small_data); + GetProcessMemoryInfo(&pmc); + CrashIfPagefileUsageTooLarge(pmc); + CrashIfPrivateUsageTooLarge(pmc); if (std::abs(height) * width > 100) { // Huh, that's weird. We don't have crazy handle count, we don't have // ridiculous memory usage. Try to allocate a small bitmap and see if that // fails too. - header->biWidth = 5; - header->biHeight = -5; - HBITMAP small_bitmap = CreateDIBSection( - nullptr, reinterpret_cast<BITMAPINFO*>(&header), - 0, &small_data, shared_section, 0); - CHECK(small_bitmap != nullptr); - DeleteObject(small_bitmap); + CrashIfCannotAllocateSmallBitmap(header, shared_section); } // Maybe the child processes are the ones leaking GDI or USER resouces. CollectChildGDIUsageAndDie(GetCurrentProcessId());
diff --git a/base/debug/task_trace.cc b/base/debug/task_trace.cc index 24cd69f..ad5276a 100644 --- a/base/debug/task_trace.cc +++ b/base/debug/task_trace.cc
@@ -6,6 +6,7 @@ #include <algorithm> #include <iostream> +#include <sstream> #include "base/pending_task.h" #include "base/task/common/task_annotator.h" @@ -52,6 +53,12 @@ } } +std::string TaskTrace::ToString() const { + std::stringstream stream; + OutputToStream(&stream); + return stream.str(); +} + base::span<const void* const> TaskTrace::AddressesForTesting() const { if (empty()) return {};
diff --git a/base/debug/task_trace.h b/base/debug/task_trace.h index 4893b8d..9a11e4e 100644 --- a/base/debug/task_trace.h +++ b/base/debug/task_trace.h
@@ -6,6 +6,7 @@ #define BASE_DEBUG_TASK_TRACE_H_ #include <iosfwd> +#include <string> #include "base/base_export.h" #include "base/containers/span.h" @@ -45,6 +46,9 @@ // Outputs trace to |os|, may be called when empty() is true. void OutputToStream(std::ostream* os) const; + // Resolves trace to symbols and returns as string. + std::string ToString() const; + // Returns the list of addresses in the task trace for testing. base::span<const void* const> AddressesForTesting() const;
diff --git a/base/immediate_crash.h b/base/immediate_crash.h new file mode 100644 index 0000000..b948c7a --- /dev/null +++ b/base/immediate_crash.h
@@ -0,0 +1,114 @@ +// 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 BASE_IMMEDIATE_CRASH_H_ +#define BASE_IMMEDIATE_CRASH_H_ + +#include "build/build_config.h" + +// Crashes in the fastest possible way with no attempt at logging. +// There are different constraints to satisfy here, see http://crbug.com/664209 +// for more context: +// - The trap instructions, and hence the PC value at crash time, have to be +// distinct and not get folded into the same opcode by the compiler. +// On Linux/Android this is tricky because GCC still folds identical +// asm volatile blocks. The workaround is generating distinct opcodes for +// each CHECK using the __COUNTER__ macro. +// - The debug info for the trap instruction has to be attributed to the source +// line that has the CHECK(), to make crash reports actionable. This rules +// out the ability of using a inline function, at least as long as clang +// doesn't support attribute(artificial). +// - Failed CHECKs should produce a signal that is distinguishable from an +// invalid memory access, to improve the actionability of crash reports. +// - The compiler should treat the CHECK as no-return instructions, so that the +// trap code can be efficiently packed in the prologue of the function and +// doesn't interfere with the main execution flow. +// - When debugging, developers shouldn't be able to accidentally step over a +// CHECK. This is achieved by putting opcodes that will cause a non +// continuable exception after the actual trap instruction. +// - Don't cause too much binary bloat. +#if defined(COMPILER_GCC) + +#if defined(ARCH_CPU_X86_FAMILY) && !defined(OS_NACL) +// int 3 will generate a SIGTRAP. +#define TRAP_SEQUENCE() \ + asm volatile( \ + "int3; ud2; push %0;" ::"i"(static_cast<unsigned char>(__COUNTER__))) + +#elif defined(ARCH_CPU_ARMEL) && !defined(OS_NACL) +// bkpt will generate a SIGBUS when running on armv7 and a SIGTRAP when running +// as a 32 bit userspace app on arm64. There doesn't seem to be any way to +// cause a SIGTRAP from userspace without using a syscall (which would be a +// problem for sandboxing). +#define TRAP_SEQUENCE() \ + asm volatile("bkpt #0; udf %0;" ::"i"(__COUNTER__ % 256)) + +#elif defined(ARCH_CPU_ARM64) && !defined(OS_NACL) +// This will always generate a SIGTRAP on arm64. +#define TRAP_SEQUENCE() \ + asm volatile("brk #0; hlt %0;" ::"i"(__COUNTER__ % 65536)) + +#else +// Crash report accuracy will not be guaranteed on other architectures, but at +// least this will crash as expected. +#define TRAP_SEQUENCE() __builtin_trap() +#endif // ARCH_CPU_* + +#elif defined(COMPILER_MSVC) + +// Clang is cleverer about coalescing int3s, so we need to add a unique-ish +// instruction following the __debugbreak() to have it emit distinct locations +// for CHECKs rather than collapsing them all together. It would be nice to use +// a short intrinsic to do this (and perhaps have only one implementation for +// both clang and MSVC), however clang-cl currently does not support intrinsics. +// On the flip side, MSVC x64 doesn't support inline asm. So, we have to have +// two implementations. Normally clang-cl's version will be 5 bytes (1 for +// `int3`, 2 for `ud2`, 2 for `push byte imm`, however, TODO(scottmg): +// https://crbug.com/694670 clang-cl doesn't currently support %'ing +// __COUNTER__, so eventually it will emit the dword form of push. +// TODO(scottmg): Reinvestigate a short sequence that will work on both +// compilers once clang supports more intrinsics. See https://crbug.com/693713. +#if !defined(__clang__) +#define TRAP_SEQUENCE() __debugbreak() +#elif defined(ARCH_CPU_ARM64) +#define TRAP_SEQUENCE() \ + __asm volatile("brk #0\n hlt %0\n" ::"i"(__COUNTER__ % 65536)); +#else +#define TRAP_SEQUENCE() ({ {__asm int 3 __asm ud2 __asm push __COUNTER__}; }) +#endif // __clang__ + +#else +#error Port +#endif // COMPILER_GCC + +// CHECK() and the trap sequence can be invoked from a constexpr function. +// This could make compilation fail on GCC, as it forbids directly using inline +// asm inside a constexpr function. However, it allows calling a lambda +// expression including the same asm. +// The side effect is that the top of the stacktrace will not point to the +// calling function, but to this anonymous lambda. This is still useful as the +// full name of the lambda will typically include the name of the function that +// calls CHECK() and the debugger will still break at the right line of code. +#if !defined(COMPILER_GCC) +#define WRAPPED_TRAP_SEQUENCE() TRAP_SEQUENCE() +#else +#define WRAPPED_TRAP_SEQUENCE() \ + do { \ + [] { TRAP_SEQUENCE(); }(); \ + } while (false) +#endif + +#if defined(__clang__) || defined(COMPILER_GCC) +#define IMMEDIATE_CRASH() \ + ({ \ + WRAPPED_TRAP_SEQUENCE(); \ + __builtin_unreachable(); \ + }) +#else +// This is supporting non-chromium user of logging.h to build with MSVC, like +// pdfium. On MSVC there is no __builtin_unreachable(). +#define IMMEDIATE_CRASH() WRAPPED_TRAP_SEQUENCE() +#endif + +#endif // BASE_IMMEDIATE_CRASH_H_
diff --git a/base/immediate_crash_unittest.cc b/base/immediate_crash_unittest.cc new file mode 100644 index 0000000..aa14722 --- /dev/null +++ b/base/immediate_crash_unittest.cc
@@ -0,0 +1,172 @@ +// 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/immediate_crash.h" + +#include <stdint.h> + +#include <algorithm> + +#include "base/containers/span.h" +#include "base/files/file_path.h" +#include "base/native_library.h" +#include "base/optional.h" +#include "base/strings/string_number_conversions.h" +#include "build/build_config.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace base { + +// iOS is excluded, since it doesn't support loading shared libraries. +#if defined(OS_WIN) || (defined(OS_MACOSX) && !defined(OS_IOS)) || \ + defined(OS_LINUX) || defined(OS_ANDROID) || defined(OS_CHROMEOS) || \ + defined(OS_FUCHSIA) + +// Checks that the IMMEDIATE_CRASH() macro produces specific instructions; see +// comments in immediate_crash.h for the requirements. +TEST(ImmediateCrashTest, ExpectedOpcodeSequence) { + // TestFunction1() and TestFunction2() are defined in a shared library in an + // attempt to guarantee that they are located next to each other. + NativeLibraryLoadError load_error; + // TODO(dcheng): Shouldn't GetNativeLibraryName just return a FilePath? + NativeLibrary helper_library = LoadNativeLibrary( + FilePath::FromUTF8Unsafe( + GetNativeLibraryName("immediate_crash_test_helper")), + &load_error); + ASSERT_TRUE(helper_library) + << "shared library load failed: " << load_error.ToString(); + + // TestFunction1() and TestFunction2() each contain two IMMEDIATE_CRASH() + // invocations. IMMEDIATE_CRASH() should be treated as a noreturn sequence and + // optimized into the function epilogue. The general strategy is to find the + // return opcode, then scan the following bytes for the opcodes for two + // consecutive IMMEDIATE_CRASH() sequences. + void* a = + GetFunctionPointerFromNativeLibrary(helper_library, "TestFunction1"); + ASSERT_TRUE(a); + void* b = + GetFunctionPointerFromNativeLibrary(helper_library, "TestFunction2"); + ASSERT_TRUE(b); + +#if defined(ARCH_CPU_X86_FAMILY) + + // X86 opcode reference: + // https://software.intel.com/en-us/download/intel-64-and-ia-32-architectures-sdm-combined-volumes-1-2a-2b-2c-2d-3a-3b-3c-3d-and-4 + span<const uint8_t> function_body = + a < b ? make_span(static_cast<const uint8_t*>(a), + static_cast<const uint8_t*>(b)) + : make_span(static_cast<const uint8_t*>(b), + static_cast<const uint8_t*>(a)); + + // Look for RETN opcode (0xC3). Note that 0xC3 is a substring of several + // other opcodes (VMRESUME, MOVNTI), and can also be encoded as part of an + // argument to another opcode. None of these other cases are expected to be + // present, so a simple byte scan should be Good Enough™. + auto it = std::find(function_body.begin(), function_body.end(), 0xC3); + ASSERT_NE(function_body.end(), it) + << "Failed to find return! " + << HexEncode(function_body.data(), function_body.size_bytes()); + + // Look for two IMMEDIATE_CRASH() opcode sequences. + base::Optional<uint8_t> nonce; + for (int i = 0; i < 2; ++i) { + // INT 3 + EXPECT_EQ(0xCC, *++it); + // UD2 + EXPECT_EQ(0x0F, *++it); + EXPECT_EQ(0x0B, *++it); + // PUSH + EXPECT_EQ(0x6A, *++it); + // Immediate nonce argument to PUSH + if (!nonce) { + nonce = *++it; + } else { + EXPECT_EQ(++*nonce, *++it); + } +#if (defined(OS_WIN) && defined(ARCH_CPU_64_BITS)) || defined(OS_MACOSX) + // On Windows x64 and Mac, __builtin_unreachable() generates UD2. See + // https://crbug.com/958373. + EXPECT_EQ(0x0F, *++it); + EXPECT_EQ(0x0B, *++it); +#endif // defined(OS_WIN) || defined(OS_MACOSX) + } + +#elif defined(ARCH_CPU_ARMEL) + + // Routines loaded from a shared library will have the LSB in the pointer set + // if encoded as T32 instructions. The rest of this test assumes T32. + ASSERT_TRUE(reinterpret_cast<uintptr_t>(a) & 0x1) + << "Expected T32 opcodes but found A32 opcodes instead."; + ASSERT_TRUE(reinterpret_cast<uintptr_t>(b) & 0x1) + << "Expected T32 opcodes but found A32 opcodes instead."; + + // Mask off the lowest bit. + a = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(a) & ~uintptr_t{0x1}); + b = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(b) & ~uintptr_t{0x1}); + + // T32 opcode reference: https://developer.arm.com/docs/ddi0487/latest + span<const uint16_t> function_body = + a < b ? make_span(static_cast<const uint16_t*>(a), + static_cast<const uint16_t*>(b)) + : make_span(static_cast<const uint16_t*>(b), + static_cast<const uint16_t*>(a)); + + // Look for the standard return opcode sequence (BX LR). + auto it = std::find(function_body.begin(), function_body.end(), 0x4770); + ASSERT_NE(function_body.end(), it) + << "Failed to find return! " + << HexEncode(function_body.data(), function_body.size_bytes()); + + // Look for two IMMEDIATE_CRASH() opcode sequences. + base::Optional<uint8_t> nonce; + for (int i = 0; i < 2; ++i) { + // BKPT #0 + EXPECT_EQ(0xBE00, *++it); + // UDF #<nonce> + EXPECT_EQ(0xDE00, *++it & 0xFF00); + if (!nonce) { + nonce = *it & 0x00FF; + } else { + EXPECT_EQ(--*nonce, *it & 0x00FF); + } + } + +#elif defined(ARCH_CPU_ARM64) + + // A64 opcode reference: https://developer.arm.com/docs/ddi0487/latest + span<const uint32_t> function_body = + a < b ? make_span(static_cast<const uint32_t*>(a), + static_cast<const uint32_t*>(b)) + : make_span(static_cast<const uint32_t*>(b), + static_cast<const uint32_t*>(a)); + + // Look for RET. There appears to be multiple valid encodings, so this is + // hardcoded to whatever clang currently emits... + auto it = std::find(function_body.begin(), function_body.end(), 0XD65F03C0); + ASSERT_NE(function_body.end(), it) + << "Failed to find return! " + << HexEncode(function_body.data(), function_body.size_bytes()); + + // Look for two IMMEDIATE_CRASH() opcode sequences. + base::Optional<uint16_t> nonce; + for (int i = 0; i < 2; ++i) { + // BRK #0 + EXPECT_EQ(0XD4200000, *++it); + // HLT #<nonce> + EXPECT_EQ(0xD4400000, *++it & 0xFFE00000); + if (!nonce) { + nonce = (*it >> 5) & 0xFFFF; + } else { + EXPECT_EQ(++*nonce, (*it >> 5) & 0xFFFF); + } + } + +#endif // defined(ARCH_CPU_X86_FAMILY) + + UnloadNativeLibrary(helper_library); +} + +#endif + +} // namespace base
diff --git a/base/logging.h b/base/logging.h index a75230a..b700fdf 100644 --- a/base/logging.h +++ b/base/logging.h
@@ -18,6 +18,7 @@ #include "base/callback_forward.h" #include "base/compiler_specific.h" #include "base/debug/debugger.h" +#include "base/immediate_crash.h" #include "base/logging_buildflags.h" #include "base/macros.h" #include "base/scoped_clear_last_error.h" @@ -526,110 +527,6 @@ std::string* message_; }; -// Crashes in the fastest possible way with no attempt at logging. -// There are different constraints to satisfy here, see http://crbug.com/664209 -// for more context: -// - The trap instructions, and hence the PC value at crash time, have to be -// distinct and not get folded into the same opcode by the compiler. -// On Linux/Android this is tricky because GCC still folds identical -// asm volatile blocks. The workaround is generating distinct opcodes for -// each CHECK using the __COUNTER__ macro. -// - The debug info for the trap instruction has to be attributed to the source -// line that has the CHECK(), to make crash reports actionable. This rules -// out the ability of using a inline function, at least as long as clang -// doesn't support attribute(artificial). -// - Failed CHECKs should produce a signal that is distinguishable from an -// invalid memory access, to improve the actionability of crash reports. -// - The compiler should treat the CHECK as no-return instructions, so that the -// trap code can be efficiently packed in the prologue of the function and -// doesn't interfere with the main execution flow. -// - When debugging, developers shouldn't be able to accidentally step over a -// CHECK. This is achieved by putting opcodes that will cause a non -// continuable exception after the actual trap instruction. -// - Don't cause too much binary bloat. -#if defined(COMPILER_GCC) - -#if defined(ARCH_CPU_X86_FAMILY) && !defined(OS_NACL) -// int 3 will generate a SIGTRAP. -#define TRAP_SEQUENCE() \ - asm volatile( \ - "int3; ud2; push %0;" ::"i"(static_cast<unsigned char>(__COUNTER__))) - -#elif defined(ARCH_CPU_ARMEL) && !defined(OS_NACL) -// bkpt will generate a SIGBUS when running on armv7 and a SIGTRAP when running -// as a 32 bit userspace app on arm64. There doesn't seem to be any way to -// cause a SIGTRAP from userspace without using a syscall (which would be a -// problem for sandboxing). -#define TRAP_SEQUENCE() \ - asm volatile("bkpt #0; udf %0;" ::"i"(__COUNTER__ % 256)) - -#elif defined(ARCH_CPU_ARM64) && !defined(OS_NACL) -// This will always generate a SIGTRAP on arm64. -#define TRAP_SEQUENCE() \ - asm volatile("brk #0; hlt %0;" ::"i"(__COUNTER__ % 65536)) - -#else -// Crash report accuracy will not be guaranteed on other architectures, but at -// least this will crash as expected. -#define TRAP_SEQUENCE() __builtin_trap() -#endif // ARCH_CPU_* - -#elif defined(COMPILER_MSVC) - -// Clang is cleverer about coalescing int3s, so we need to add a unique-ish -// instruction following the __debugbreak() to have it emit distinct locations -// for CHECKs rather than collapsing them all together. It would be nice to use -// a short intrinsic to do this (and perhaps have only one implementation for -// both clang and MSVC), however clang-cl currently does not support intrinsics. -// On the flip side, MSVC x64 doesn't support inline asm. So, we have to have -// two implementations. Normally clang-cl's version will be 5 bytes (1 for -// `int3`, 2 for `ud2`, 2 for `push byte imm`, however, TODO(scottmg): -// https://crbug.com/694670 clang-cl doesn't currently support %'ing -// __COUNTER__, so eventually it will emit the dword form of push. -// TODO(scottmg): Reinvestigate a short sequence that will work on both -// compilers once clang supports more intrinsics. See https://crbug.com/693713. -#if !defined(__clang__) -#define TRAP_SEQUENCE() __debugbreak() -#elif defined(ARCH_CPU_ARM64) -#define TRAP_SEQUENCE() \ - __asm volatile("brk #0\n hlt %0\n" ::"i"(__COUNTER__ % 65536)); -#else -#define TRAP_SEQUENCE() ({ {__asm int 3 __asm ud2 __asm push __COUNTER__}; }) -#endif // __clang__ - -#else -#error Port -#endif // COMPILER_GCC - -// CHECK() and the trap sequence can be invoked from a constexpr function. -// This could make compilation fail on GCC, as it forbids directly using inline -// asm inside a constexpr function. However, it allows calling a lambda -// expression including the same asm. -// The side effect is that the top of the stacktrace will not point to the -// calling function, but to this anonymous lambda. This is still useful as the -// full name of the lambda will typically include the name of the function that -// calls CHECK() and the debugger will still break at the right line of code. -#if !defined(COMPILER_GCC) -#define WRAPPED_TRAP_SEQUENCE() TRAP_SEQUENCE() -#else -#define WRAPPED_TRAP_SEQUENCE() \ - do { \ - [] { TRAP_SEQUENCE(); }(); \ - } while (false) -#endif - -#if defined(__clang__) || defined(COMPILER_GCC) -#define IMMEDIATE_CRASH() \ - ({ \ - WRAPPED_TRAP_SEQUENCE(); \ - __builtin_unreachable(); \ - }) -#else -// This is supporting non-chromium user of logging.h to build with MSVC, like -// pdfium. On MSVC there is no __builtin_unreachable(). -#define IMMEDIATE_CRASH() WRAPPED_TRAP_SEQUENCE() -#endif - // CHECK dies with a fatal error if condition is not true. It is *not* // controlled by NDEBUG, so the check will be executed regardless of // compilation mode.
diff --git a/base/task/thread_pool/pooled_single_thread_task_runner_manager.cc b/base/task/thread_pool/pooled_single_thread_task_runner_manager.cc index 2fa3523..5d09efea 100644 --- a/base/task/thread_pool/pooled_single_thread_task_runner_manager.cc +++ b/base/task/thread_pool/pooled_single_thread_task_runner_manager.cc
@@ -82,9 +82,9 @@ WorkerThreadDelegate(const std::string& thread_name, WorkerThread::ThreadLabel thread_label, TrackedRef<TaskTracker> task_tracker) - : thread_name_(thread_name), - thread_label_(thread_label), - task_tracker_(std::move(task_tracker)) {} + : task_tracker_(std::move(task_tracker)), + thread_name_(thread_name), + thread_label_(thread_label) {} void set_worker(WorkerThread* worker) { DCHECK(!worker_); @@ -120,16 +120,21 @@ TimeDelta GetSleepTimeout() override { return TimeDelta::Max(); } - void PostTaskNow(scoped_refptr<Sequence> sequence, Task task) { + bool PostTaskNow(scoped_refptr<Sequence> sequence, Task task) { auto transaction = sequence->BeginTransaction(); - const bool sequence_should_be_queued = - transaction.PushTask(std::move(task)); + const bool sequence_should_be_queued = transaction.WillPushTask(); + if (sequence_should_be_queued && + !task_tracker_->WillQueueTaskSource(sequence.get())) { + return false; + } + transaction.PushTask(std::move(task)); if (sequence_should_be_queued) { bool should_wakeup = EnqueueTaskSource({std::move(sequence), std::move(transaction)}); if (should_wakeup) worker_->WakeUp(); } + return true; } bool RunsTasksInCurrentSequence() { @@ -172,6 +177,8 @@ CheckedLock lock_; bool worker_awake_ GUARDED_BY(lock_) = false; + const TrackedRef<TaskTracker> task_tracker_; + private: // Enqueues a task source in this single-threaded worker's priority queue. // Returns true iff the worker must wakeup, i.e. task source is allowed to run @@ -201,8 +208,6 @@ // OnMainEntry() and PostTaskNow(). WorkerThread* worker_ = nullptr; - const TrackedRef<TaskTracker> task_tracker_; - PriorityQueue priority_queue_ GUARDED_BY(lock_); AtomicThreadRefChecker thread_ref_checker_; @@ -317,10 +322,14 @@ TimeDelta()); if (task_tracker()->WillPostTask( &pump_message_task, TaskShutdownBehavior::SKIP_ON_SHUTDOWN)) { - bool was_empty = message_pump_sequence_->BeginTransaction().PushTask( - std::move(pump_message_task)); - DCHECK(was_empty) << "GetWorkFromWindowsMessageQueue() does not expect " - "queueing of pump tasks."; + auto transaction = message_pump_sequence_->BeginTransaction(); + const bool sequence_should_be_queued = transaction.WillPushTask(); + DCHECK(sequence_should_be_queued) + << "GetWorkFromWindowsMessageQueue() does not expect " + "queueing of pump tasks."; + if (!task_tracker_->WillQueueTaskSource(message_pump_sequence_.get())) + return nullptr; + transaction.PushTask(std::move(pump_message_task)); return message_pump_sequence_; } } @@ -375,17 +384,16 @@ return false; } - if (task.delayed_run_time.is_null()) { - GetDelegate()->PostTaskNow(sequence_, std::move(task)); - } else { - // Unretained(GetDelegate()) is safe because this TaskRunner and its - // worker are kept alive as long as there are pending Tasks. - outer_->delayed_task_manager_->AddDelayedTask( - std::move(task), - BindOnce(&WorkerThreadDelegate::PostTaskNow, - Unretained(GetDelegate()), sequence_), - this); - } + if (task.delayed_run_time.is_null()) + return GetDelegate()->PostTaskNow(sequence_, std::move(task)); + + // Unretained(GetDelegate()) is safe because this TaskRunner and its + // worker are kept alive as long as there are pending Tasks. + outer_->delayed_task_manager_->AddDelayedTask( + std::move(task), + BindOnce(IgnoreResult(&WorkerThreadDelegate::PostTaskNow), + Unretained(GetDelegate()), sequence_), + this); return true; }
diff --git a/base/task/thread_pool/sequence.cc b/base/task/thread_pool/sequence.cc index 761702a8..f07c515 100644 --- a/base/task/thread_pool/sequence.cc +++ b/base/task/thread_pool/sequence.cc
@@ -34,13 +34,23 @@ Sequence::Transaction::~Transaction() = default; -bool Sequence::Transaction::PushTask(Task task) { +bool Sequence::Transaction::WillPushTask() const { + // If the sequence is empty before a Task is inserted into it and the pool is + // not running any task from this sequence, it should be queued. + // Otherwise, one of these must be true: + // - The Sequence is already queued, or, + // - A thread is running a Task from the Sequence. It is expected to reenqueue + // the Sequence once it's done running the Task. + return sequence()->queue_.empty() && !sequence()->has_worker_; +} + +void Sequence::Transaction::PushTask(Task task) { // Use CHECK instead of DCHECK to crash earlier. See http://crbug.com/711167 // for details. CHECK(task.task); DCHECK(task.queue_time.is_null()); - bool queue_was_empty = sequence()->queue_.empty(); + bool should_be_queued = WillPushTask(); task.queue_time = base::TimeTicks::Now(); task.task = sequence()->traits_.shutdown_behavior() == @@ -50,32 +60,26 @@ sequence()->queue_.push(std::move(task)); - bool should_be_queued = queue_was_empty && NeedsWorker(); - // AddRef() matched by manual Release() when the sequence has no more tasks // to run (in DidRunTask() or Clear()). if (should_be_queued && sequence()->task_runner()) sequence()->task_runner()->AddRef(); - - // If the sequence was empty before |task| was inserted into it and the pool - // is not running any task from this sequence, it should be queued. - // Otherwise, one of these must be true: - // - The Sequence is already scheduled, or, - // - The pool is running a Task from the Sequence. The pool is expected to - // reschedule the Sequence once it's done running the Task. - return should_be_queued; } Optional<Task> Sequence::TakeTask() { - DCHECK(!IsEmpty()); + DCHECK(!has_worker_); + DCHECK(!queue_.empty()); DCHECK(queue_.front().task); + has_worker_ = true; auto next_task = std::move(queue_.front()); queue_.pop(); return std::move(next_task); } bool Sequence::DidRunTask() { + DCHECK(has_worker_); + has_worker_ = false; if (queue_.empty()) { ReleaseTaskRunner(); return false; @@ -84,18 +88,14 @@ } SequenceSortKey Sequence::GetSortKey() const { - DCHECK(!IsEmpty()); + DCHECK(!queue_.empty()); return SequenceSortKey(traits_.priority(), queue_.front().queue_time); } -bool Sequence::IsEmpty() const { - return queue_.empty(); -} - void Sequence::Clear() { bool queue_was_empty = queue_.empty(); while (!queue_.empty()) - TakeTask(); + queue_.pop(); if (!queue_was_empty) { // No member access after this point, ReleaseTaskRunner() might have deleted // |this|.
diff --git a/base/task/thread_pool/sequence.h b/base/task/thread_pool/sequence.h index 66863e48..256ed7f 100644 --- a/base/task/thread_pool/sequence.h +++ b/base/task/thread_pool/sequence.h
@@ -51,9 +51,11 @@ Transaction(Transaction&& other); ~Transaction(); - // Adds |task| in a new slot at the end of the Sequence. Returns true if the - // Sequence needs to be enqueued again. - bool PushTask(Task task); + // Returns true if the would need to be queued after receiving a new Task. + bool WillPushTask() const; + + // Adds |task| in a new slot at the end of the Sequence. + void PushTask(Task task); Sequence* sequence() const { return static_cast<Sequence*>(task_source()); } @@ -94,7 +96,6 @@ Optional<Task> TakeTask() override; bool DidRunTask() override; SequenceSortKey GetSortKey() const override; - bool IsEmpty() const override; void Clear() override; // Releases reference to TaskRunner. This might cause this object to be @@ -106,6 +107,8 @@ // Queue of tasks to execute. base::queue<Task> queue_; + bool has_worker_ = false; + // Holds data stored through the SequenceLocalStorageSlot API. SequenceLocalStorageMap sequence_local_storage_;
diff --git a/base/task/thread_pool/sequence_unittest.cc b/base/task/thread_pool/sequence_unittest.cc index 4f0890f..6de963f 100644 --- a/base/task/thread_pool/sequence_unittest.cc +++ b/base/task/thread_pool/sequence_unittest.cc
@@ -51,13 +51,17 @@ // Push task A in the sequence. PushTask() should return true since it's the // first task-> - EXPECT_TRUE(sequence_transaction.PushTask(CreateTask(&mock_task_a))); + EXPECT_TRUE(sequence_transaction.WillPushTask()); + sequence_transaction.PushTask(CreateTask(&mock_task_a)); // Push task B, C and D in the sequence. PushTask() should return false since // there is already a task in a sequence. - EXPECT_FALSE(sequence_transaction.PushTask(CreateTask(&mock_task_b))); - EXPECT_FALSE(sequence_transaction.PushTask(CreateTask(&mock_task_c))); - EXPECT_FALSE(sequence_transaction.PushTask(CreateTask(&mock_task_d))); + EXPECT_FALSE(sequence_transaction.WillPushTask()); + sequence_transaction.PushTask(CreateTask(&mock_task_b)); + EXPECT_FALSE(sequence_transaction.WillPushTask()); + sequence_transaction.PushTask(CreateTask(&mock_task_c)); + EXPECT_FALSE(sequence_transaction.WillPushTask()); + sequence_transaction.PushTask(CreateTask(&mock_task_d)); // Take the task in front of the sequence. It should be task A. Optional<Task> task = sequence_transaction.TakeTask(); @@ -66,12 +70,14 @@ // Remove the empty slot. Task B should now be in front. EXPECT_TRUE(sequence_transaction.DidRunTask()); + EXPECT_FALSE(sequence_transaction.WillPushTask()); task = sequence_transaction.TakeTask(); ExpectMockTask(&mock_task_b, &task.value()); EXPECT_FALSE(task->queue_time.is_null()); // Remove the empty slot. Task C should now be in front. EXPECT_TRUE(sequence_transaction.DidRunTask()); + EXPECT_FALSE(sequence_transaction.WillPushTask()); task = sequence_transaction.TakeTask(); ExpectMockTask(&mock_task_c, &task.value()); EXPECT_FALSE(task->queue_time.is_null()); @@ -80,7 +86,8 @@ EXPECT_TRUE(sequence_transaction.DidRunTask()); // Push task E in the sequence. - EXPECT_FALSE(sequence_transaction.PushTask(CreateTask(&mock_task_e))); + EXPECT_FALSE(sequence_transaction.WillPushTask()); + sequence_transaction.PushTask(CreateTask(&mock_task_e)); // Task D should be in front. task = sequence_transaction.TakeTask(); @@ -89,12 +96,14 @@ // Remove the empty slot. Task E should now be in front. EXPECT_TRUE(sequence_transaction.DidRunTask()); + EXPECT_FALSE(sequence_transaction.WillPushTask()); task = sequence_transaction.TakeTask(); ExpectMockTask(&mock_task_e, &task.value()); EXPECT_FALSE(task->queue_time.is_null()); // Remove the empty slot. The sequence should now be empty. EXPECT_FALSE(sequence_transaction.DidRunTask()); + EXPECT_TRUE(sequence_transaction.WillPushTask()); } // Verifies the sort key of a BEST_EFFORT sequence that contains one task.
diff --git a/base/task/thread_pool/task_source.cc b/base/task/thread_pool/task_source.cc index 52922a2..de39ebe8 100644 --- a/base/task/thread_pool/task_source.cc +++ b/base/task/thread_pool/task_source.cc
@@ -43,14 +43,10 @@ } Optional<Task> TaskSource::Transaction::TakeTask() { - DCHECK(!task_source_->has_worker_); - task_source_->has_worker_ = true; return task_source_->TakeTask(); } bool TaskSource::Transaction::DidRunTask() { - DCHECK(task_source_->has_worker_); - task_source_->has_worker_ = false; return task_source_->DidRunTask(); } @@ -58,10 +54,6 @@ return task_source_->GetSortKey(); } -bool TaskSource::Transaction::NeedsWorker() const { - return !task_source_->IsEmpty() && !task_source_->has_worker_; -} - void TaskSource::Transaction::Clear() { task_source_->Clear(); }
diff --git a/base/task/thread_pool/task_source.h b/base/task/thread_pool/task_source.h index 93ad825..bc30bc64 100644 --- a/base/task/thread_pool/task_source.h +++ b/base/task/thread_pool/task_source.h
@@ -37,26 +37,22 @@ // A TaskSource is a virtual class that provides a series of Tasks that must be // executed. // -// In order to execute a task from this TaskSource, a worker should first make -// sure that it can take up an additional worker with NeedsWorker(). TakeTask() -// can then be called to access the next Task, and Pop() must be called after -// the task executed and before accessing any subsequent Tasks. This ensure that -// the number of workers concurrently running tasks never go over the intended -// concurrency. +// In order to execute a task from this TaskSource, TakeTask() can be called to +// access the next Task, and DidRunTask() must be called after the task executed +// and before accessing any subsequent Tasks. This ensure that the number of +// workers concurrently running tasks never go over the intended concurrency. // // In comments below, an "empty TaskSource" is a TaskSource with no Task. // // Note: there is a known refcounted-ownership cycle in the Scheduler -// architecture: TaskSource -> Task -> TaskRunner -> TaskSource -> ... -// This is okay so long as the other owners of TaskSource (PriorityQueue and +// architecture: TaskSource -> TaskRunner -> TaskSource -> ... This is +// okay so long as the other owners of TaskSource (PriorityQueue and // WorkerThread in alternation and -// ThreadGroupImpl::WorkerThreadDelegateImpl::GetWork() -// temporarily) keep running it (and taking Tasks from it as a result). A -// dangling reference cycle would only occur should they release their reference -// to it while it's not empty. In other words, it is only correct for them to -// release it after IsEmpty() returns true. -// TODO(etiennep): Break ownership cycle by moving TaskRunner reference from -// Task to TaskSource. +// ThreadGroupImpl::WorkerThreadDelegateImpl::GetWork() temporarily) keep +// running it (and taking Tasks from it as a result). A dangling reference cycle +// would only occur should they release their reference to it while it's not +// empty. In other words, it is only correct for them to release it when +// DidRunTask() returns false. // // This class is thread-safe. class BASE_EXPORT TaskSource : public RefCountedThreadSafe<TaskSource> { @@ -89,9 +85,6 @@ // Cannot be called on an empty TaskSource. SequenceSortKey GetSortKey() const; - // Returns true if additional workers should run tasks from this TaskSource. - bool NeedsWorker() const; - // Sets TaskSource priority to |priority|. void UpdatePriority(TaskPriority priority); @@ -159,8 +152,6 @@ virtual SequenceSortKey GetSortKey() const = 0; - virtual bool IsEmpty() const = 0; - virtual void Clear() = 0; // Sets TaskSource priority to |priority|. @@ -180,15 +171,13 @@ HeapHandle heap_handle_; // A pointer to the TaskRunner that posts to this TaskSource, if any. The - // derived class is responsible for calling AddRef() when NeedWorkers() - // becomes true and Release() when DidRunTask() returns false. + // derived class is responsible for calling AddRef() when a TaskSource from + // which no Task is executing becomes non-empty and Release() when + // DidRunTask() returns false. TaskRunner* task_runner_; TaskSourceExecutionMode execution_mode_; - // TODO(etiennep): Add support for TaskSources with more than one worker. - bool has_worker_ = false; - DISALLOW_COPY_AND_ASSIGN(TaskSource); };
diff --git a/base/task/thread_pool/task_source_unittest.cc b/base/task/thread_pool/task_source_unittest.cc deleted file mode 100644 index 1b2d882..0000000 --- a/base/task/thread_pool/task_source_unittest.cc +++ /dev/null
@@ -1,82 +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/task/thread_pool/task_source.h" - -#include <utility> - -#include "base/bind.h" -#include "base/bind_helpers.h" -#include "base/memory/ptr_util.h" -#include "base/test/gtest_util.h" -#include "base/time/time.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace base { -namespace internal { - -namespace { - -class MockTaskSource : public TaskSource { - public: - MockTaskSource(TaskTraits traits) - : TaskSource(traits, nullptr, TaskSourceExecutionMode::kParallel) {} - - MOCK_METHOD0(GetExecutionEnvironment, ExecutionEnvironment()); - - protected: - MOCK_METHOD0(TakeTask, base::Optional<Task>()); - MOCK_CONST_METHOD0(GetSortKey, SequenceSortKey()); - MOCK_CONST_METHOD0(IsEmpty, bool()); - MOCK_METHOD0(Clear, void()); - - bool DidRunTask() override { return !IsEmpty(); } - - private: - ~MockTaskSource() override = default; -}; - -} // namespace - -TEST(ThreadPoolTaskSourceTest, TakeTaskDidRunTask) { - scoped_refptr<MockTaskSource> task_source = - MakeRefCounted<MockTaskSource>(TaskTraits(TaskPriority::BEST_EFFORT)); - TaskSource::Transaction task_source_transaction( - task_source->BeginTransaction()); - - EXPECT_TRUE(task_source_transaction.NeedsWorker()); - task_source_transaction.TakeTask(); - EXPECT_FALSE(task_source_transaction.NeedsWorker()); - - EXPECT_TRUE(task_source_transaction.DidRunTask()); - EXPECT_TRUE(task_source_transaction.NeedsWorker()); - - task_source_transaction.TakeTask(); - EXPECT_TRUE(task_source_transaction.DidRunTask()); -} - -TEST(ThreadPoolTaskSourceTest, InvalidTakeTask) { - scoped_refptr<MockTaskSource> task_source = - MakeRefCounted<MockTaskSource>(TaskTraits(TaskPriority::BEST_EFFORT)); - TaskSource::Transaction task_source_transaction( - task_source->BeginTransaction()); - - task_source_transaction.TakeTask(); - // Can not be called before DidRunTask(). - EXPECT_DCHECK_DEATH(task_source_transaction.TakeTask()); -} - -TEST(ThreadPoolTaskSourceTest, InvalidDidRunTask) { - scoped_refptr<MockTaskSource> task_source = - MakeRefCounted<MockTaskSource>(TaskTraits(TaskPriority::BEST_EFFORT)); - TaskSource::Transaction task_source_transaction( - task_source->BeginTransaction()); - - // Can not be called before TakeTask(). - EXPECT_DCHECK_DEATH(task_source_transaction.DidRunTask()); -} - -} // namespace internal -} // namespace base
diff --git a/base/task/thread_pool/task_tracker.cc b/base/task/thread_pool/task_tracker.cc index 31f5991..c219d7b4 100644 --- a/base/task/thread_pool/task_tracker.cc +++ b/base/task/thread_pool/task_tracker.cc
@@ -140,10 +140,13 @@ } // namespace -// Atomic internal state used by TaskTracker. Sequential consistency shouldn't -// be assumed from these calls (i.e. a thread reading -// |HasShutdownStarted() == true| isn't guaranteed to see all writes made before -// |StartShutdown()| on the thread that invoked it). +// Atomic internal state used by TaskTracker to track items that are blocking +// Shutdown. An "item" consist of either: +// - A running SKIP_ON_SHUTDOWN task +// - A queued/running BLOCK_SHUTDOWN TaskSource. +// Sequential consistency shouldn't be assumed from these calls (i.e. a thread +// reading |HasShutdownStarted() == true| isn't guaranteed to see all writes +// made before |StartShutdown()| on the thread that invoked it). class TaskTracker::State { public: State() = default; @@ -158,9 +161,9 @@ // if it was incremented twice. DCHECK(new_value & kShutdownHasStartedMask); - const auto num_tasks_blocking_shutdown = - new_value >> kNumTasksBlockingShutdownBitOffset; - return num_tasks_blocking_shutdown != 0; + const auto num_items_blocking_shutdown = + new_value >> kNumItemsBlockingShutdownBitOffset; + return num_items_blocking_shutdown != 0; } // Returns true if shutdown has started. @@ -170,58 +173,58 @@ // Returns true if there are tasks blocking shutdown. bool AreTasksBlockingShutdown() const { - const auto num_tasks_blocking_shutdown = - subtle::NoBarrier_Load(&bits_) >> kNumTasksBlockingShutdownBitOffset; - DCHECK_GE(num_tasks_blocking_shutdown, 0); - return num_tasks_blocking_shutdown != 0; + const auto num_items_blocking_shutdown = + subtle::NoBarrier_Load(&bits_) >> kNumItemsBlockingShutdownBitOffset; + DCHECK_GE(num_items_blocking_shutdown, 0); + return num_items_blocking_shutdown != 0; } - // Increments the number of tasks blocking shutdown. Returns true if shutdown - // has started. - bool IncrementNumTasksBlockingShutdown() { + // Increments the number of items blocking shutdown. Returns true if + // shutdown has started. + bool IncrementNumItemsBlockingShutdown() { #if DCHECK_IS_ON() // Verify that no overflow will occur. - const auto num_tasks_blocking_shutdown = - subtle::NoBarrier_Load(&bits_) >> kNumTasksBlockingShutdownBitOffset; - DCHECK_LT(num_tasks_blocking_shutdown, + const auto num_items_blocking_shutdown = + subtle::NoBarrier_Load(&bits_) >> kNumItemsBlockingShutdownBitOffset; + DCHECK_LT(num_items_blocking_shutdown, std::numeric_limits<subtle::Atomic32>::max() - - kNumTasksBlockingShutdownIncrement); + kNumItemsBlockingShutdownIncrement); #endif const auto new_bits = subtle::NoBarrier_AtomicIncrement( - &bits_, kNumTasksBlockingShutdownIncrement); + &bits_, kNumItemsBlockingShutdownIncrement); return new_bits & kShutdownHasStartedMask; } - // Decrements the number of tasks blocking shutdown. Returns true if shutdown + // Decrements the number of items blocking shutdown. Returns true if shutdown // has started and the number of tasks blocking shutdown becomes zero. - bool DecrementNumTasksBlockingShutdown() { + bool DecrementNumItemsBlockingShutdown() { const auto new_bits = subtle::NoBarrier_AtomicIncrement( - &bits_, -kNumTasksBlockingShutdownIncrement); + &bits_, -kNumItemsBlockingShutdownIncrement); const bool shutdown_has_started = new_bits & kShutdownHasStartedMask; - const auto num_tasks_blocking_shutdown = - new_bits >> kNumTasksBlockingShutdownBitOffset; - DCHECK_GE(num_tasks_blocking_shutdown, 0); - return shutdown_has_started && num_tasks_blocking_shutdown == 0; + const auto num_items_blocking_shutdown = + new_bits >> kNumItemsBlockingShutdownBitOffset; + DCHECK_GE(num_items_blocking_shutdown, 0); + return shutdown_has_started && num_items_blocking_shutdown == 0; } private: static constexpr subtle::Atomic32 kShutdownHasStartedMask = 1; - static constexpr subtle::Atomic32 kNumTasksBlockingShutdownBitOffset = 1; - static constexpr subtle::Atomic32 kNumTasksBlockingShutdownIncrement = - 1 << kNumTasksBlockingShutdownBitOffset; + static constexpr subtle::Atomic32 kNumItemsBlockingShutdownBitOffset = 1; + static constexpr subtle::Atomic32 kNumItemsBlockingShutdownIncrement = + 1 << kNumItemsBlockingShutdownBitOffset; // The LSB indicates whether shutdown has started. The other bits count the - // number of tasks blocking shutdown. + // number of items blocking shutdown. // No barriers are required to read/write |bits_| as this class is only used // as an atomic state checker, it doesn't provide sequential consistency // guarantees w.r.t. external state. Sequencing of the TaskTracker::State // operations themselves is guaranteed by the AtomicIncrement RMW (read- // modify-write) semantics however. For example, if two threads are racing to - // call IncrementNumTasksBlockingShutdown() and StartShutdown() respectively, + // call IncrementNumItemsBlockingShutdown() and StartShutdown() respectively, // either the first thread will win and the StartShutdown() call will see the // blocking task or the second thread will win and - // IncrementNumTasksBlockingShutdown() will know that shutdown has started. + // IncrementNumItemsBlockingShutdown() will know that shutdown has started. subtle::Atomic32 bits_ = 0; DISALLOW_COPY_AND_ASSIGN(State); @@ -345,7 +348,7 @@ void TaskTracker::FlushForTesting() { CheckedAutoLock auto_lock(flush_lock_); - while (subtle::Acquire_Load(&num_incomplete_undelayed_tasks_) != 0 && + while (num_incomplete_task_sources_.load(std::memory_order_acquire) != 0 && !IsShutdownComplete()) { flush_cv_->Wait(); } @@ -360,7 +363,7 @@ flush_callback_for_testing_ = std::move(flush_callback); } - if (subtle::Acquire_Load(&num_incomplete_undelayed_tasks_) == 0 || + if (num_incomplete_task_sources_.load(std::memory_order_acquire) == 0 || IsShutdownComplete()) { CallFlushCallbackForTesting(); } @@ -375,12 +378,26 @@ DCHECK(task); DCHECK(task->task); - if (!BeforePostTask(GetEffectiveShutdownBehavior( - shutdown_behavior, !task->delayed_run_time.is_null()))) - return false; + if (state_->HasShutdownStarted()) { + // A non BLOCK_SHUTDOWN task is allowed to be posted iff shutdown hasn't + // started. + if (GetEffectiveShutdownBehavior(shutdown_behavior, + !task->delayed_run_time.is_null()) != + TaskShutdownBehavior::BLOCK_SHUTDOWN) { + return false; + } - if (task->delayed_run_time.is_null()) - subtle::NoBarrier_AtomicIncrement(&num_incomplete_undelayed_tasks_, 1); + // A BLOCK_SHUTDOWN task posted after shutdown has completed is an + // ordering bug. This aims to catch those early. + DCHECK(shutdown_event_); + // TODO(http://crbug.com/698140): Atomically shutdown the service thread + // to prevent racily posting BLOCK_SHUTDOWN tasks in response to a + // FileDescriptorWatcher (and/or make such notifications never be + // BLOCK_SHUTDOWN). Then, enable this DCHECK, until then, skip the task. + // DCHECK(!shutdown_event_->IsSignaled()); + if (shutdown_event_->IsSignaled()) + return false; + } // TODO(scheduler-dev): Record the task traits here. task_annotator_.WillQueueTask("ThreadPool_PostTask", task, ""); @@ -388,6 +405,17 @@ return true; } +bool TaskTracker::WillQueueTaskSource(TaskSource* task_source) { + DCHECK(task_source); + + TaskShutdownBehavior shutdown_behavior = task_source->shutdown_behavior(); + if (!BeforeQueueTaskSource(shutdown_behavior)) + return false; + + num_incomplete_task_sources_.fetch_add(1, std::memory_order_relaxed); + return true; +} + bool TaskTracker::CanRunPriority(TaskPriority priority) const { auto can_run_policy = can_run_policy_.load(); @@ -413,35 +441,35 @@ TaskSource::Transaction task_source_transaction( task_source->BeginTransaction()); task = task_source_transaction.TakeTask(); - // TODO(fdoray): Support TakeTask() returning null. https://crbug.com/783309 - DCHECK(task); - traits = task_source_transaction.traits(); } - const TaskShutdownBehavior effective_shutdown_behavior = - GetEffectiveShutdownBehavior(task_source->shutdown_behavior(), - !task->delayed_run_time.is_null()); + if (task) { + const TaskShutdownBehavior effective_shutdown_behavior = + GetEffectiveShutdownBehavior(task_source->shutdown_behavior(), + !task->delayed_run_time.is_null()); - const bool can_run_task = BeforeRunTask(effective_shutdown_behavior); + const bool can_run_task = BeforeRunTask(effective_shutdown_behavior); - RunOrSkipTask(std::move(task.value()), task_source.get(), traits, - can_run_task); - if (can_run_task) { - IncrementNumTasksRun(); - AfterRunTask(effective_shutdown_behavior); + RunOrSkipTask(std::move(task.value()), task_source.get(), traits, + can_run_task); + + const bool task_source_must_be_queued = + task_source->BeginTransaction().DidRunTask(); + + if (can_run_task) { + IncrementNumTasksRun(); + AfterRunTask(effective_shutdown_behavior); + } + + // The task_source should be reenqueued iff requested by DidRunTask(). + if (task_source_must_be_queued) { + return task_source; + } } - if (task->delayed_run_time.is_null()) - DecrementNumIncompleteUndelayedTasks(); - - const bool task_source_must_be_queued = - task_source->BeginTransaction().DidRunTask(); - - // The task source should be reenqueued iff requested by DidRunTask(). - if (!task_source_must_be_queued) - return nullptr; - return task_source; + OnTaskSourceNotReEnqueued(task_source.get()); + return nullptr; } bool TaskTracker::HasShutdownStarted() const { @@ -575,16 +603,16 @@ ThreadRestrictions::SetSingletonAllowed(previous_singleton_allowed); } -bool TaskTracker::HasIncompleteUndelayedTasksForTesting() const { - return subtle::Acquire_Load(&num_incomplete_undelayed_tasks_) != 0; +bool TaskTracker::HasIncompleteTaskSourcesForTesting() const { + return num_incomplete_task_sources_.load(std::memory_order_acquire) != 0; } -bool TaskTracker::BeforePostTask( - TaskShutdownBehavior effective_shutdown_behavior) { - if (effective_shutdown_behavior == TaskShutdownBehavior::BLOCK_SHUTDOWN) { - // BLOCK_SHUTDOWN tasks block shutdown between the moment they are posted - // and the moment they complete their execution. - const bool shutdown_started = state_->IncrementNumTasksBlockingShutdown(); +bool TaskTracker::BeforeQueueTaskSource( + TaskShutdownBehavior shutdown_behavior) { + if (shutdown_behavior == TaskShutdownBehavior::BLOCK_SHUTDOWN) { + // BLOCK_SHUTDOWN task sources block shutdown between the moment they are + // queued and the moment their last task completes its execution. + const bool shutdown_started = state_->IncrementNumItemsBlockingShutdown(); if (shutdown_started) { CheckedAutoLock auto_lock(shutdown_lock_); @@ -598,7 +626,7 @@ // BLOCK_SHUTDOWN). Then, enable this DCHECK, until then, skip the task. // DCHECK(!shutdown_event_->IsSignaled()); if (shutdown_event_->IsSignaled()) { - state_->DecrementNumTasksBlockingShutdown(); + state_->DecrementNumItemsBlockingShutdown(); return false; } } @@ -630,17 +658,13 @@ case TaskShutdownBehavior::SKIP_ON_SHUTDOWN: { // SKIP_ON_SHUTDOWN tasks block shutdown while they are running. - const bool shutdown_started = state_->IncrementNumTasksBlockingShutdown(); + const bool shutdown_started = state_->IncrementNumItemsBlockingShutdown(); if (shutdown_started) { // The SKIP_ON_SHUTDOWN task isn't allowed to run during shutdown. // Decrement the number of tasks blocking shutdown that was wrongly // incremented. - const bool shutdown_started_and_no_tasks_block_shutdown = - state_->DecrementNumTasksBlockingShutdown(); - if (shutdown_started_and_no_tasks_block_shutdown) - OnBlockingShutdownTasksComplete(); - + DecrementNumItemsBlockingShutdown(); return false; } @@ -658,16 +682,25 @@ void TaskTracker::AfterRunTask( TaskShutdownBehavior effective_shutdown_behavior) { - if (effective_shutdown_behavior == TaskShutdownBehavior::BLOCK_SHUTDOWN || - effective_shutdown_behavior == TaskShutdownBehavior::SKIP_ON_SHUTDOWN) { - const bool shutdown_started_and_no_tasks_block_shutdown = - state_->DecrementNumTasksBlockingShutdown(); - if (shutdown_started_and_no_tasks_block_shutdown) - OnBlockingShutdownTasksComplete(); + if (effective_shutdown_behavior == TaskShutdownBehavior::SKIP_ON_SHUTDOWN) { + DecrementNumItemsBlockingShutdown(); } } -void TaskTracker::OnBlockingShutdownTasksComplete() { +void TaskTracker::OnTaskSourceNotReEnqueued(TaskSource* task_source) { + if (task_source->shutdown_behavior() == + TaskShutdownBehavior::BLOCK_SHUTDOWN) { + DecrementNumItemsBlockingShutdown(); + } + DecrementNumIncompleteTaskSources(); +} + +void TaskTracker::DecrementNumItemsBlockingShutdown() { + const bool shutdown_started_and_no_items_block_shutdown = + state_->DecrementNumItemsBlockingShutdown(); + if (!shutdown_started_and_no_items_block_shutdown) + return; + CheckedAutoLock auto_lock(shutdown_lock_); // This method can only be called after shutdown has started. @@ -677,11 +710,11 @@ shutdown_event_->Signal(); } -void TaskTracker::DecrementNumIncompleteUndelayedTasks() { - const auto new_num_incomplete_undelayed_tasks = - subtle::Barrier_AtomicIncrement(&num_incomplete_undelayed_tasks_, -1); - DCHECK_GE(new_num_incomplete_undelayed_tasks, 0); - if (new_num_incomplete_undelayed_tasks == 0) { +void TaskTracker::DecrementNumIncompleteTaskSources() { + const auto prev_num_incomplete_task_sources = + num_incomplete_task_sources_.fetch_sub(1); + DCHECK_GE(prev_num_incomplete_task_sources, 1); + if (prev_num_incomplete_task_sources == 1) { { CheckedAutoLock auto_lock(flush_lock_); flush_cv_->Signal();
diff --git a/base/task/thread_pool/task_tracker.h b/base/task/thread_pool/task_tracker.h index 357ff20..18054fb4 100644 --- a/base/task/thread_pool/task_tracker.h +++ b/base/task/thread_pool/task_tracker.h
@@ -26,6 +26,7 @@ #include "base/task/thread_pool/task.h" #include "base/task/thread_pool/task_source.h" #include "base/task/thread_pool/tracked_ref.h" +#include "base/thread_annotations.h" namespace base { @@ -46,8 +47,9 @@ // TaskTracker enforces policies that determines whether: // - A task can be added to a task source (WillPostTask). +// - A task source can be queued (WillQueueTaskSource). // - Tasks for a given priority can run (CanRunPriority). -// - The next task in a scheduled task source can run (RunAndPopNextTask). +// - The next task in a queued task source can run (RunAndPopNextTask). // TaskTracker also sets up the environment to run a task (RunAndPopNextTask) // and records metrics and trace events. This class is thread-safe. class BASE_EXPORT TaskTracker { @@ -71,10 +73,10 @@ // This can only be called once. void CompleteShutdown(); - // Waits until there are no incomplete undelayed tasks. May be called in tests - // to validate that a condition is met after all undelayed tasks have run. + // Waits until there are no incomplete task sources. May be called in tests + // to validate that a condition is met after all task sources have run. // - // Does not wait for delayed tasks. Waits for undelayed tasks posted from + // Does not wait for delayed tasks. Waits for task sources posted from // other threads during the call. Returns immediately when shutdown completes. void FlushForTesting(); @@ -96,6 +98,11 @@ // metadata on |task| if desired. bool WillPostTask(Task* task, TaskShutdownBehavior shutdown_behavior); + // Informs this TaskTracker that |task_source| is about to be queued. Returns + // true if this operation is allowed (|task_source| should be queued + // if-and-only-if it is). + bool WillQueueTaskSource(TaskSource* task_source); + // Returns true if a task with |priority| can run under to the current policy. bool CanRunPriority(TaskPriority priority) const; @@ -159,10 +166,10 @@ const TaskTraits& traits, bool can_run_task); - // Returns true if there are undelayed tasks that haven't completed their + // Returns true if there are task sources that haven't completed their // execution (still queued or in progress). If it returns false: the side- // effects of all completed tasks are guaranteed to be visible to the caller. - bool HasIncompleteUndelayedTasksForTesting() const; + bool HasIncompleteTaskSourcesForTesting() const; private: class State; @@ -170,27 +177,29 @@ void PerformShutdown(); // Called before WillPostTask() informs the tracing system that a task has - // been posted. Updates |num_tasks_blocking_shutdown_| if necessary and + // been posted. Updates |num_items_blocking_shutdown_| if necessary and // returns true if the current shutdown state allows the task to be posted. - bool BeforePostTask(TaskShutdownBehavior effective_shutdown_behavior); + bool BeforeQueueTaskSource(TaskShutdownBehavior effective_shutdown_behavior); // Called before a task with |effective_shutdown_behavior| is run by - // RunTask(). Updates |num_tasks_blocking_shutdown_| if necessary and returns + // RunTask(). Updates |num_items_blocking_shutdown_| if necessary and returns // true if the current shutdown state allows the task to be run. bool BeforeRunTask(TaskShutdownBehavior effective_shutdown_behavior); // Called after a task with |effective_shutdown_behavior| has been run by - // RunTask(). Updates |num_tasks_blocking_shutdown_| and signals - // |shutdown_cv_| if necessary. + // RunTask(). Updates |num_items_blocking_shutdown_| if necessary. void AfterRunTask(TaskShutdownBehavior effective_shutdown_behavior); - // Called when the number of tasks blocking shutdown becomes zero after - // shutdown has started. - void OnBlockingShutdownTasksComplete(); + // Called after the last task from |task_source| was run and it won't be + // reenqueued. Updates |num_items_blocking_shutdown_| if necessary. + void OnTaskSourceNotReEnqueued(TaskSource* task_source); - // Decrements the number of incomplete undelayed tasks and signals |flush_cv_| + // Called when an items blocking shutdown finishes after shutdown has started. + void DecrementNumItemsBlockingShutdown(); + + // Decrements the number of incomplete task sources and signals |flush_cv_| // if it reaches zero. - void DecrementNumIncompleteUndelayedTasks(); + void DecrementNumIncompleteTaskSources(); // Calls |flush_callback_for_testing_| if one is available in a lock-safe // manner. @@ -217,30 +226,30 @@ // has started. const std::unique_ptr<State> state_; - // Number of undelayed tasks that haven't completed their execution. Is - // decremented with a memory barrier after a task runs. Is accessed with an - // acquire memory barrier in FlushForTesting(). The memory barriers ensure - // that the memory written by flushed tasks is visible when FlushForTesting() - // returns. - subtle::Atomic32 num_incomplete_undelayed_tasks_ = 0; + // Number of task sources that haven't completed their execution. Is + // decremented with a memory barrier after the last task of a task source + // runs. Is accessed with an acquire memory barrier in FlushForTesting(). The + // memory barriers ensure that the memory written by flushed task sources is + // visible when FlushForTesting() returns. + std::atomic_int num_incomplete_task_sources_{0}; // Global policy the determines result of CanRunPriority(). std::atomic<CanRunPolicy> can_run_policy_; // Lock associated with |flush_cv_|. Partially synchronizes access to - // |num_incomplete_undelayed_tasks_|. Full synchronization isn't needed + // |num_incomplete_task_sources_|. Full synchronization isn't needed // because it's atomic, but synchronization is needed to coordinate waking and // sleeping at the right time. Fully synchronizes access to // |flush_callback_for_testing_|. mutable CheckedLock flush_lock_; - // Signaled when |num_incomplete_undelayed_tasks_| is or reaches zero or when + // Signaled when |num_incomplete_task_sources_| is or reaches zero or when // shutdown completes. const std::unique_ptr<ConditionVariable> flush_cv_; - // Invoked if non-null when |num_incomplete_undelayed_tasks_| is zero or when + // Invoked if non-null when |num_incomplete_task_sources_| is zero or when // shutdown completes. - OnceClosure flush_callback_for_testing_; + OnceClosure flush_callback_for_testing_ GUARDED_BY(flush_lock_); // Synchronizes access to shutdown related members below. mutable CheckedLock shutdown_lock_;
diff --git a/base/task/thread_pool/task_tracker_posix_unittest.cc b/base/task/thread_pool/task_tracker_posix_unittest.cc index 15021bf..058afd2 100644 --- a/base/task/thread_pool/task_tracker_posix_unittest.cc +++ b/base/task/thread_pool/task_tracker_posix_unittest.cc
@@ -61,6 +61,7 @@ EXPECT_TRUE(tracker_.WillPostTask(&task, default_traits.shutdown_behavior())); auto sequence = test::CreateSequenceWithTask(std::move(task), default_traits); + EXPECT_TRUE(tracker_.WillQueueTaskSource(sequence.get())); // Expect RunAndPopNextTask to return nullptr since |sequence| is empty after // popping a task from it. EXPECT_FALSE(tracker_.RunAndPopNextTask(sequence)); @@ -85,6 +86,7 @@ auto sequence = test::CreateSequenceWithTask( std::move(task), default_traits, MakeRefCounted<NullTaskRunner>(), TaskSourceExecutionMode::kSequenced); + EXPECT_TRUE(tracker_.WillQueueTaskSource(sequence.get())); // Expect RunAndPopNextTask to return nullptr since |sequence| is empty after // popping a task from it.
diff --git a/base/task/thread_pool/task_tracker_unittest.cc b/base/task/thread_pool/task_tracker_unittest.cc index cbd5adc..5e12523d 100644 --- a/base/task/thread_pool/task_tracker_unittest.cc +++ b/base/task/thread_pool/task_tracker_unittest.cc
@@ -78,62 +78,50 @@ }; ThreadPostingAndRunningTask(TaskTracker* tracker, - Task* task, - const TaskTraits& traits, + scoped_refptr<Sequence> sequence, Action action, - bool expect_post_succeeds) + bool expect_post_succeeds, + Task task = {}) : SimpleThread("ThreadPostingAndRunningTask"), tracker_(tracker), - owned_task_(FROM_HERE, OnceClosure(), TimeDelta()), - task_(task), - traits_(traits), + task_(std::move(task)), + sequence_(std::move(sequence)), action_(action), expect_post_succeeds_(expect_post_succeeds) { - EXPECT_TRUE(task_); - - // Ownership of the Task is required to run it. - EXPECT_NE(Action::RUN, action_); - EXPECT_NE(Action::WILL_POST_AND_RUN, action_); - } - - ThreadPostingAndRunningTask(TaskTracker* tracker, - Task task, - const TaskTraits& traits, - Action action, - bool expect_post_succeeds) - : SimpleThread("ThreadPostingAndRunningTask"), - tracker_(tracker), - owned_task_(std::move(task)), - task_(&owned_task_), - traits_(traits), - action_(action), - expect_post_succeeds_(expect_post_succeeds) { - EXPECT_TRUE(owned_task_.task); + if (!task_.task) { + EXPECT_NE(Action::WILL_POST, action_); + EXPECT_NE(Action::WILL_POST_AND_RUN, action_); + } } private: void Run() override { - bool post_succeeded = true; + bool post_and_queue_succeeded = true; if (action_ == Action::WILL_POST || action_ == Action::WILL_POST_AND_RUN) { - post_succeeded = - tracker_->WillPostTask(task_, traits_.shutdown_behavior()); - EXPECT_EQ(expect_post_succeeds_, post_succeeded); + EXPECT_TRUE(task_.task); + + post_and_queue_succeeded = + tracker_->WillPostTask(&task_, sequence_->shutdown_behavior()); + sequence_->BeginTransaction().PushTask(std::move(task_)); + + post_and_queue_succeeded &= + tracker_->WillQueueTaskSource(sequence_.get()); + + EXPECT_EQ(expect_post_succeeds_, post_and_queue_succeeded); } - if (post_succeeded && + if (post_and_queue_succeeded && (action_ == Action::RUN || action_ == Action::WILL_POST_AND_RUN)) { - EXPECT_TRUE(owned_task_.task); + EXPECT_TRUE(sequence_); // Expect RunAndPopNextTask to return nullptr since |sequence| is empty // after popping a task from it. - EXPECT_FALSE(tracker_->RunAndPopNextTask( - test::CreateSequenceWithTask(std::move(owned_task_), traits_))); + EXPECT_FALSE(tracker_->RunAndPopNextTask(std::move(sequence_))); } } TaskTracker* const tracker_; - Task owned_task_; - Task* task_; - const TaskTraits traits_; + Task task_; + scoped_refptr<Sequence> sequence_; const Action action_; const bool expect_post_succeeds_; @@ -166,9 +154,15 @@ TimeDelta()); } - void DispatchAndRunTaskWithTracker(Task task, const TaskTraits& traits) { - tracker_.RunAndPopNextTask( - test::CreateSequenceWithTask(std::move(task), traits)); + scoped_refptr<Sequence> WillPostTaskAndQueueTaskSource( + Task task, + const TaskTraits& traits) { + if (!tracker_.WillPostTask(&task, traits.shutdown_behavior())) + return nullptr; + auto sequence = test::CreateSequenceWithTask(std::move(task), traits); + if (!tracker_.WillQueueTaskSource(sequence.get())) + return nullptr; + return sequence; } // Calls tracker_->CompleteShutdown() on a new thread and expects it to block. @@ -274,7 +268,8 @@ // Run the task. EXPECT_EQ(0U, NumTasksExecuted()); - DispatchAndRunTaskWithTracker(std::move(task), GetParam()); + test::QueueAndRunTaskSource( + &tracker_, test::CreateSequenceWithTask(std::move(task), GetParam())); EXPECT_EQ(1U, NumTasksExecuted()); // Shutdown() shouldn't block. @@ -293,19 +288,20 @@ Bind( [](WaitableEvent* task_running, WaitableEvent* task_barrier) { task_running->Signal(); - task_barrier->Wait(); + test::WaitWithoutBlockingObserver(task_barrier); }, Unretained(&task_running), Unretained(&task_barrier)), TimeDelta()); // Inform |task_tracker_| that |blocked_task| will be posted. - EXPECT_TRUE(tracker_.WillPostTask(&blocked_task, GetParam())); + auto sequence = + WillPostTaskAndQueueTaskSource(std::move(blocked_task), {GetParam()}); + EXPECT_TRUE(sequence); // Create a thread to run the task. Wait until the task starts running. ThreadPostingAndRunningTask thread_running_task( - &tracker_, std::move(blocked_task), - TaskTraits(WithBaseSyncPrimitives(), GetParam()), - ThreadPostingAndRunningTask::Action::RUN, false); + &tracker_, std::move(sequence), ThreadPostingAndRunningTask::Action::RUN, + false); thread_running_task.Start(); task_running.Wait(); @@ -329,16 +325,50 @@ WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED(); } -TEST_P(ThreadPoolTaskTrackerTest, WillPostBeforeShutdownRunDuringShutdown) { - // Inform |task_tracker_| that a task will be posted. - Task task(CreateTask()); +// Verify that a undelayed task whose sequence wasn't queued does not block +// shutdown, regardless of its shutdown behavior. +TEST_P(ThreadPoolTaskTrackerTest, WillPostBeforeShutdownQueueDuringShutdown) { + // Simulate posting a delayed task. + Task task{CreateTask()}; EXPECT_TRUE(tracker_.WillPostTask(&task, GetParam())); + auto sequence = test::CreateSequenceWithTask(std::move(task), GetParam()); // Inform |task_tracker_| that a BLOCK_SHUTDOWN task will be posted just to // block shutdown. - Task block_shutdown_task(CreateTask()); - EXPECT_TRUE(tracker_.WillPostTask(&block_shutdown_task, - TaskShutdownBehavior::BLOCK_SHUTDOWN)); + auto block_shutdown_sequence = WillPostTaskAndQueueTaskSource( + CreateTask(), TaskShutdownBehavior::BLOCK_SHUTDOWN); + EXPECT_TRUE(block_shutdown_sequence); + + // Start shutdown and try to complete it asynchronously. + tracker_.StartShutdown(); + ExpectAsyncCompleteShutdownBlocks(); + + const bool should_run = GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN; + if (should_run) { + EXPECT_TRUE(tracker_.WillQueueTaskSource(sequence.get())); + tracker_.RunAndPopNextTask(std::move(sequence)); + EXPECT_EQ(1U, NumTasksExecuted()); + VERIFY_ASYNC_SHUTDOWN_IN_PROGRESS(); + } else { + EXPECT_FALSE(tracker_.WillQueueTaskSource(sequence.get())); + } + + // Unblock shutdown by running the remaining BLOCK_SHUTDOWN task. + tracker_.RunAndPopNextTask(std::move(block_shutdown_sequence)); + EXPECT_EQ(should_run ? 2U : 1U, NumTasksExecuted()); + WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED(); +} + +TEST_P(ThreadPoolTaskTrackerTest, WillPostBeforeShutdownRunDuringShutdown) { + // Inform |task_tracker_| that a task will be posted. + auto sequence = WillPostTaskAndQueueTaskSource(CreateTask(), GetParam()); + EXPECT_TRUE(sequence); + + // Inform |task_tracker_| that a BLOCK_SHUTDOWN task will be posted just to + // block shutdown. + auto block_shutdown_sequence = WillPostTaskAndQueueTaskSource( + CreateTask(), TaskShutdownBehavior::BLOCK_SHUTDOWN); + EXPECT_TRUE(block_shutdown_sequence); // Start shutdown and try to complete it asynchronously. tracker_.StartShutdown(); @@ -349,21 +379,20 @@ EXPECT_EQ(0U, NumTasksExecuted()); const bool should_run = GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN; - DispatchAndRunTaskWithTracker(std::move(task), GetParam()); + tracker_.RunAndPopNextTask(std::move(sequence)); EXPECT_EQ(should_run ? 1U : 0U, NumTasksExecuted()); VERIFY_ASYNC_SHUTDOWN_IN_PROGRESS(); // Unblock shutdown by running the remaining BLOCK_SHUTDOWN task. - DispatchAndRunTaskWithTracker(std::move(block_shutdown_task), - TaskShutdownBehavior::BLOCK_SHUTDOWN); + tracker_.RunAndPopNextTask(std::move(block_shutdown_sequence)); EXPECT_EQ(should_run ? 2U : 1U, NumTasksExecuted()); WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED(); } TEST_P(ThreadPoolTaskTrackerTest, WillPostBeforeShutdownRunAfterShutdown) { // Inform |task_tracker_| that a task will be posted. - Task task(CreateTask()); - EXPECT_TRUE(tracker_.WillPostTask(&task, GetParam())); + auto sequence = WillPostTaskAndQueueTaskSource(CreateTask(), GetParam()); + EXPECT_TRUE(sequence); // Start shutdown. tracker_.StartShutdown(); @@ -374,7 +403,7 @@ ExpectAsyncCompleteShutdownBlocks(); // Run the task to unblock shutdown. - DispatchAndRunTaskWithTracker(std::move(task), GetParam()); + tracker_.RunAndPopNextTask(std::move(sequence)); EXPECT_EQ(1U, NumTasksExecuted()); WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED(); @@ -385,7 +414,7 @@ tracker_.CompleteShutdown(); // The task shouldn't be allowed to run after shutdown. - DispatchAndRunTaskWithTracker(std::move(task), GetParam()); + tracker_.RunAndPopNextTask(std::move(sequence)); EXPECT_EQ(0U, NumTasksExecuted()); } } @@ -393,26 +422,26 @@ TEST_P(ThreadPoolTaskTrackerTest, WillPostAndRunDuringShutdown) { // Inform |task_tracker_| that a BLOCK_SHUTDOWN task will be posted just to // block shutdown. - Task block_shutdown_task(CreateTask()); - EXPECT_TRUE(tracker_.WillPostTask(&block_shutdown_task, - TaskShutdownBehavior::BLOCK_SHUTDOWN)); + auto block_shutdown_sequence = WillPostTaskAndQueueTaskSource( + CreateTask(), TaskShutdownBehavior::BLOCK_SHUTDOWN); + EXPECT_TRUE(block_shutdown_sequence); // Start shutdown. tracker_.StartShutdown(); if (GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN) { // Inform |task_tracker_| that a BLOCK_SHUTDOWN task will be posted. - Task task(CreateTask()); - EXPECT_TRUE(tracker_.WillPostTask(&task, GetParam())); + auto sequence = WillPostTaskAndQueueTaskSource(CreateTask(), GetParam()); + EXPECT_TRUE(sequence); // Run the BLOCK_SHUTDOWN task. EXPECT_EQ(0U, NumTasksExecuted()); - DispatchAndRunTaskWithTracker(std::move(task), GetParam()); + tracker_.RunAndPopNextTask(std::move(sequence)); EXPECT_EQ(1U, NumTasksExecuted()); } else { // It shouldn't be allowed to post a non BLOCK_SHUTDOWN task. - Task task(CreateTask()); - EXPECT_FALSE(tracker_.WillPostTask(&task, GetParam())); + auto sequence = WillPostTaskAndQueueTaskSource(CreateTask(), GetParam()); + EXPECT_FALSE(sequence); // Don't try to run the task, because it wasn't allowed to be posted. } @@ -421,8 +450,7 @@ ExpectAsyncCompleteShutdownBlocks(); // Unblock shutdown by running |block_shutdown_task|. - DispatchAndRunTaskWithTracker(std::move(block_shutdown_task), - TaskShutdownBehavior::BLOCK_SHUTDOWN); + tracker_.RunAndPopNextTask(std::move(block_shutdown_sequence)); EXPECT_EQ(GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN ? 2U : 1U, NumTasksExecuted()); WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED(); @@ -445,7 +473,8 @@ Task task(FROM_HERE, BindOnce(&ThreadRestrictions::AssertSingletonAllowed), TimeDelta()); - EXPECT_TRUE(tracker_.WillPostTask(&task, GetParam())); + auto sequence = WillPostTaskAndQueueTaskSource(std::move(task), GetParam()); + EXPECT_TRUE(sequence); // Set the singleton allowed bit to the opposite of what it is expected to be // when |tracker| runs |task| to verify that |tracker| actually sets the @@ -454,10 +483,9 @@ // Running the task should fail iff the task isn't allowed to use singletons. if (can_use_singletons) { - DispatchAndRunTaskWithTracker(std::move(task), GetParam()); + tracker_.RunAndPopNextTask(std::move(sequence)); } else { - EXPECT_DCHECK_DEATH( - { DispatchAndRunTaskWithTracker(std::move(task), GetParam()); }); + EXPECT_DCHECK_DEATH({ tracker_.RunAndPopNextTask(std::move(sequence)); }); } } @@ -473,10 +501,10 @@ }), TimeDelta()); TaskTraits traits_with_may_block = TaskTraits(MayBlock(), GetParam()); - EXPECT_TRUE(tracker_.WillPostTask(&task_with_may_block, - traits_with_may_block.shutdown_behavior())); - DispatchAndRunTaskWithTracker(std::move(task_with_may_block), - traits_with_may_block); + auto sequence_with_may_block = WillPostTaskAndQueueTaskSource( + std::move(task_with_may_block), traits_with_may_block); + EXPECT_TRUE(sequence_with_may_block); + tracker_.RunAndPopNextTask(std::move(sequence_with_may_block)); // Set the IO allowed bit. Expect TaskTracker to unset it before running a // task without the MayBlock() trait. @@ -489,10 +517,10 @@ }), TimeDelta()); TaskTraits traits_without_may_block = TaskTraits(GetParam()); - EXPECT_TRUE(tracker_.WillPostTask( - &task_without_may_block, traits_without_may_block.shutdown_behavior())); - DispatchAndRunTaskWithTracker(std::move(task_without_may_block), - traits_without_may_block); + auto sequence_without_may_block = WillPostTaskAndQueueTaskSource( + std::move(task_without_may_block), traits_without_may_block); + EXPECT_TRUE(sequence_without_may_block); + tracker_.RunAndPopNextTask(std::move(sequence_without_may_block)); } static void RunTaskRunnerHandleVerificationTask( @@ -509,10 +537,10 @@ EXPECT_FALSE(ThreadTaskRunnerHandle::IsSet()); EXPECT_FALSE(SequencedTaskRunnerHandle::IsSet()); - auto sequence = test::CreateSequenceWithTask( - std::move(verify_task), traits, std::move(task_runner), execution_mode); - - tracker->RunAndPopNextTask(std::move(sequence)); + test::QueueAndRunTaskSource( + tracker, + test::CreateSequenceWithTask(std::move(verify_task), traits, + std::move(task_runner), execution_mode)); // TaskRunnerHandle state is reset outside of task's scope. EXPECT_FALSE(ThreadTaskRunnerHandle::IsSet()); @@ -602,7 +630,8 @@ TEST_P(ThreadPoolTaskTrackerTest, FlushPendingUndelayedTask) { Task undelayed_task(FROM_HERE, DoNothing(), TimeDelta()); - tracker_.WillPostTask(&undelayed_task, GetParam()); + auto undelayed_sequence = + WillPostTaskAndQueueTaskSource(std::move(undelayed_task), GetParam()); // FlushForTesting() shouldn't return before the undelayed task runs. CallFlushFromAnotherThread(); @@ -610,13 +639,14 @@ VERIFY_ASYNC_FLUSH_IN_PROGRESS(); // FlushForTesting() should return after the undelayed task runs. - DispatchAndRunTaskWithTracker(std::move(undelayed_task), GetParam()); + tracker_.RunAndPopNextTask(std::move(undelayed_sequence)); WAIT_FOR_ASYNC_FLUSH_RETURNED(); } TEST_P(ThreadPoolTaskTrackerTest, FlushAsyncForTestingPendingUndelayedTask) { Task undelayed_task(FROM_HERE, DoNothing(), TimeDelta()); - tracker_.WillPostTask(&undelayed_task, GetParam()); + auto undelayed_sequence = + WillPostTaskAndQueueTaskSource(std::move(undelayed_task), GetParam()); // FlushAsyncForTesting() shouldn't callback before the undelayed task runs. WaitableEvent event; @@ -626,13 +656,14 @@ EXPECT_FALSE(event.IsSignaled()); // FlushAsyncForTesting() should callback after the undelayed task runs. - DispatchAndRunTaskWithTracker(std::move(undelayed_task), GetParam()); + tracker_.RunAndPopNextTask(std::move(undelayed_sequence)); event.Wait(); } TEST_P(ThreadPoolTaskTrackerTest, PostTaskDuringFlush) { Task undelayed_task(FROM_HERE, DoNothing(), TimeDelta()); - tracker_.WillPostTask(&undelayed_task, GetParam()); + auto undelayed_sequence = + WillPostTaskAndQueueTaskSource(std::move(undelayed_task), GetParam()); // FlushForTesting() shouldn't return before the undelayed task runs. CallFlushFromAnotherThread(); @@ -641,23 +672,25 @@ // Simulate posting another undelayed task. Task other_undelayed_task(FROM_HERE, DoNothing(), TimeDelta()); - tracker_.WillPostTask(&other_undelayed_task, GetParam()); + auto other_undelayed_sequence = WillPostTaskAndQueueTaskSource( + std::move(other_undelayed_task), GetParam()); // Run the first undelayed task. - DispatchAndRunTaskWithTracker(std::move(undelayed_task), GetParam()); + tracker_.RunAndPopNextTask(std::move(undelayed_sequence)); // FlushForTesting() shouldn't return before the second undelayed task runs. PlatformThread::Sleep(TestTimeouts::tiny_timeout()); VERIFY_ASYNC_FLUSH_IN_PROGRESS(); // FlushForTesting() should return after the second undelayed task runs. - DispatchAndRunTaskWithTracker(std::move(other_undelayed_task), GetParam()); + tracker_.RunAndPopNextTask(std::move(other_undelayed_sequence)); WAIT_FOR_ASYNC_FLUSH_RETURNED(); } TEST_P(ThreadPoolTaskTrackerTest, PostTaskDuringFlushAsyncForTesting) { Task undelayed_task(FROM_HERE, DoNothing(), TimeDelta()); - tracker_.WillPostTask(&undelayed_task, GetParam()); + auto undelayed_sequence = + WillPostTaskAndQueueTaskSource(std::move(undelayed_task), GetParam()); // FlushAsyncForTesting() shouldn't callback before the undelayed task runs. WaitableEvent event; @@ -668,10 +701,11 @@ // Simulate posting another undelayed task. Task other_undelayed_task(FROM_HERE, DoNothing(), TimeDelta()); - tracker_.WillPostTask(&other_undelayed_task, GetParam()); + auto other_undelayed_sequence = WillPostTaskAndQueueTaskSource( + std::move(other_undelayed_task), GetParam()); // Run the first undelayed task. - DispatchAndRunTaskWithTracker(std::move(undelayed_task), GetParam()); + tracker_.RunAndPopNextTask(std::move(undelayed_sequence)); // FlushAsyncForTesting() shouldn't callback before the second undelayed task // runs. @@ -680,16 +714,18 @@ // FlushAsyncForTesting() should callback after the second undelayed task // runs. - DispatchAndRunTaskWithTracker(std::move(other_undelayed_task), GetParam()); + tracker_.RunAndPopNextTask(std::move(other_undelayed_sequence)); event.Wait(); } TEST_P(ThreadPoolTaskTrackerTest, RunDelayedTaskDuringFlush) { // Simulate posting a delayed and an undelayed task. Task delayed_task(FROM_HERE, DoNothing(), TimeDelta::FromDays(1)); - tracker_.WillPostTask(&delayed_task, GetParam()); + auto delayed_sequence = + WillPostTaskAndQueueTaskSource(std::move(delayed_task), GetParam()); Task undelayed_task(FROM_HERE, DoNothing(), TimeDelta()); - tracker_.WillPostTask(&undelayed_task, GetParam()); + auto undelayed_sequence = + WillPostTaskAndQueueTaskSource(std::move(undelayed_task), GetParam()); // FlushForTesting() shouldn't return before the undelayed task runs. CallFlushFromAnotherThread(); @@ -697,7 +733,7 @@ VERIFY_ASYNC_FLUSH_IN_PROGRESS(); // Run the delayed task. - DispatchAndRunTaskWithTracker(std::move(delayed_task), GetParam()); + tracker_.RunAndPopNextTask(std::move(delayed_sequence)); // FlushForTesting() shouldn't return since there is still a pending undelayed // task. @@ -705,7 +741,7 @@ VERIFY_ASYNC_FLUSH_IN_PROGRESS(); // Run the undelayed task. - DispatchAndRunTaskWithTracker(std::move(undelayed_task), GetParam()); + tracker_.RunAndPopNextTask(std::move(undelayed_sequence)); // FlushForTesting() should now return. WAIT_FOR_ASYNC_FLUSH_RETURNED(); @@ -714,9 +750,11 @@ TEST_P(ThreadPoolTaskTrackerTest, RunDelayedTaskDuringFlushAsyncForTesting) { // Simulate posting a delayed and an undelayed task. Task delayed_task(FROM_HERE, DoNothing(), TimeDelta::FromDays(1)); - tracker_.WillPostTask(&delayed_task, GetParam()); + auto delayed_sequence = + WillPostTaskAndQueueTaskSource(std::move(delayed_task), GetParam()); Task undelayed_task(FROM_HERE, DoNothing(), TimeDelta()); - tracker_.WillPostTask(&undelayed_task, GetParam()); + auto undelayed_sequence = + WillPostTaskAndQueueTaskSource(std::move(undelayed_task), GetParam()); // FlushAsyncForTesting() shouldn't callback before the undelayed task runs. WaitableEvent event; @@ -726,7 +764,7 @@ EXPECT_FALSE(event.IsSignaled()); // Run the delayed task. - DispatchAndRunTaskWithTracker(std::move(delayed_task), GetParam()); + tracker_.RunAndPopNextTask(std::move(delayed_sequence)); // FlushAsyncForTesting() shouldn't callback since there is still a pending // undelayed task. @@ -734,7 +772,7 @@ EXPECT_FALSE(event.IsSignaled()); // Run the undelayed task. - DispatchAndRunTaskWithTracker(std::move(undelayed_task), GetParam()); + tracker_.RunAndPopNextTask(std::move(undelayed_sequence)); // FlushAsyncForTesting() should now callback. event.Wait(); @@ -784,7 +822,8 @@ // Simulate posting a task. Task undelayed_task(FROM_HERE, DoNothing(), TimeDelta()); - tracker_.WillPostTask(&undelayed_task, GetParam()); + auto undelayed_sequence = + WillPostTaskAndQueueTaskSource(std::move(undelayed_task), GetParam()); // FlushForTesting() shouldn't return before the undelayed task runs or // shutdown completes. @@ -806,7 +845,8 @@ // Simulate posting a task. Task undelayed_task(FROM_HERE, DoNothing(), TimeDelta()); - tracker_.WillPostTask(&undelayed_task, GetParam()); + auto undelayed_sequence = + WillPostTaskAndQueueTaskSource(std::move(undelayed_task), GetParam()); // FlushAsyncForTesting() shouldn't callback before the undelayed task runs or // shutdown completes. @@ -827,7 +867,8 @@ TEST_P(ThreadPoolTaskTrackerTest, DoublePendingFlushAsyncForTestingFails) { Task undelayed_task(FROM_HERE, DoNothing(), TimeDelta()); - tracker_.WillPostTask(&undelayed_task, GetParam()); + auto undelayed_sequence = + WillPostTaskAndQueueTaskSource(std::move(undelayed_task), GetParam()); // FlushAsyncForTesting() shouldn't callback before the undelayed task runs. bool called_back = false; @@ -838,12 +879,25 @@ EXPECT_DCHECK_DEATH({ tracker_.FlushAsyncForTesting(BindOnce([]() {})); }); } -// Verify that a delayed task does not block shutdown, regardless of its +TEST_P(ThreadPoolTaskTrackerTest, PostTasksDoNotBlockShutdown) { + // Simulate posting an undelayed task. + Task undelayed_task(FROM_HERE, DoNothing(), TimeDelta()); + EXPECT_TRUE(tracker_.WillPostTask(&undelayed_task, GetParam())); + + // Since no sequence was queued, a call to Shutdown() should not hang. + test::ShutdownTaskTracker(&tracker_); +} + +// Verify that running a delayed task does not block shutdown, regardless of its // shutdown behavior. -TEST_P(ThreadPoolTaskTrackerTest, DelayedTasksDoNotBlockShutdown) { +TEST_P(ThreadPoolTaskTrackerTest, DelayedPostTasksDoNotBlockShutdown) { // Simulate posting a delayed task. Task delayed_task(FROM_HERE, DoNothing(), TimeDelta::FromDays(1)); - EXPECT_TRUE(tracker_.WillPostTask(&delayed_task, GetParam())); + auto sequence = + WillPostTaskAndQueueTaskSource(std::move(delayed_task), GetParam()); + EXPECT_TRUE(sequence); + + tracker_.RunAndPopNextTask(std::move(sequence)); // Since the delayed task doesn't block shutdown, a call to Shutdown() should // not hang. @@ -888,7 +942,7 @@ EXPECT_FALSE(SequenceToken::GetForCurrentThread().IsValid()); } - tracker_.RunAndPopNextTask(std::move(sequence)); + test::QueueAndRunTaskSource(&tracker_, std::move(sequence)); EXPECT_FALSE(SequenceToken::GetForCurrentThread().IsValid()); } @@ -898,21 +952,27 @@ for (size_t i = 0; i < kLoadTestNumIterations; ++i) { threads.push_back(std::make_unique<ThreadPostingAndRunningTask>( - &tracker_, CreateTask(), - TaskTraits(TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN), - ThreadPostingAndRunningTask::Action::WILL_POST_AND_RUN, true)); + &tracker_, + MakeRefCounted<Sequence>(TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN, + nullptr, TaskSourceExecutionMode::kParallel), + ThreadPostingAndRunningTask::Action::WILL_POST_AND_RUN, true, + CreateTask())); threads.back()->Start(); threads.push_back(std::make_unique<ThreadPostingAndRunningTask>( - &tracker_, CreateTask(), - TaskTraits(TaskShutdownBehavior::SKIP_ON_SHUTDOWN), - ThreadPostingAndRunningTask::Action::WILL_POST_AND_RUN, true)); + &tracker_, + MakeRefCounted<Sequence>(TaskShutdownBehavior::SKIP_ON_SHUTDOWN, + nullptr, TaskSourceExecutionMode::kParallel), + ThreadPostingAndRunningTask::Action::WILL_POST_AND_RUN, true, + CreateTask())); threads.back()->Start(); threads.push_back(std::make_unique<ThreadPostingAndRunningTask>( - &tracker_, CreateTask(), - TaskTraits(TaskShutdownBehavior::BLOCK_SHUTDOWN), - ThreadPostingAndRunningTask::Action::WILL_POST_AND_RUN, true)); + &tracker_, + MakeRefCounted<Sequence>(TaskShutdownBehavior::BLOCK_SHUTDOWN, nullptr, + TaskSourceExecutionMode::kParallel), + ThreadPostingAndRunningTask::Action::WILL_POST_AND_RUN, true, + CreateTask())); threads.back()->Start(); } @@ -928,16 +988,6 @@ TEST_F(ThreadPoolTaskTrackerTest, LoadWillPostBeforeShutdownAndRunDuringShutdown) { - // Post tasks asynchronously. - std::vector<Task> tasks_continue_on_shutdown; - std::vector<Task> tasks_skip_on_shutdown; - std::vector<Task> tasks_block_shutdown; - for (size_t i = 0; i < kLoadTestNumIterations; ++i) { - tasks_continue_on_shutdown.push_back(CreateTask()); - tasks_skip_on_shutdown.push_back(CreateTask()); - tasks_block_shutdown.push_back(CreateTask()); - } - TaskTraits traits_continue_on_shutdown = TaskTraits(TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN); TaskTraits traits_skip_on_shutdown = @@ -945,21 +995,35 @@ TaskTraits traits_block_shutdown = TaskTraits(TaskShutdownBehavior::BLOCK_SHUTDOWN); + // Post tasks asynchronously. + std::vector<scoped_refptr<Sequence>> sequences_continue_on_shutdown; + std::vector<scoped_refptr<Sequence>> sequences_skip_on_shutdown; + std::vector<scoped_refptr<Sequence>> sequences_block_shutdown; + for (size_t i = 0; i < kLoadTestNumIterations; ++i) { + sequences_continue_on_shutdown.push_back( + MakeRefCounted<Sequence>(traits_continue_on_shutdown, nullptr, + TaskSourceExecutionMode::kParallel)); + sequences_skip_on_shutdown.push_back(MakeRefCounted<Sequence>( + traits_skip_on_shutdown, nullptr, TaskSourceExecutionMode::kParallel)); + sequences_block_shutdown.push_back(MakeRefCounted<Sequence>( + traits_block_shutdown, nullptr, TaskSourceExecutionMode::kParallel)); + } + std::vector<std::unique_ptr<ThreadPostingAndRunningTask>> post_threads; for (size_t i = 0; i < kLoadTestNumIterations; ++i) { post_threads.push_back(std::make_unique<ThreadPostingAndRunningTask>( - &tracker_, &tasks_continue_on_shutdown[i], traits_continue_on_shutdown, - ThreadPostingAndRunningTask::Action::WILL_POST, true)); + &tracker_, sequences_continue_on_shutdown[i], + ThreadPostingAndRunningTask::Action::WILL_POST, true, CreateTask())); post_threads.back()->Start(); post_threads.push_back(std::make_unique<ThreadPostingAndRunningTask>( - &tracker_, &tasks_skip_on_shutdown[i], traits_skip_on_shutdown, - ThreadPostingAndRunningTask::Action::WILL_POST, true)); + &tracker_, sequences_skip_on_shutdown[i], + ThreadPostingAndRunningTask::Action::WILL_POST, true, CreateTask())); post_threads.back()->Start(); post_threads.push_back(std::make_unique<ThreadPostingAndRunningTask>( - &tracker_, &tasks_block_shutdown[i], traits_block_shutdown, - ThreadPostingAndRunningTask::Action::WILL_POST, true)); + &tracker_, sequences_block_shutdown[i], + ThreadPostingAndRunningTask::Action::WILL_POST, true, CreateTask())); post_threads.back()->Start(); } @@ -974,19 +1038,17 @@ std::vector<std::unique_ptr<ThreadPostingAndRunningTask>> run_threads; for (size_t i = 0; i < kLoadTestNumIterations; ++i) { run_threads.push_back(std::make_unique<ThreadPostingAndRunningTask>( - &tracker_, std::move(tasks_continue_on_shutdown[i]), - traits_continue_on_shutdown, ThreadPostingAndRunningTask::Action::RUN, - false)); + &tracker_, std::move(sequences_continue_on_shutdown[i]), + ThreadPostingAndRunningTask::Action::RUN, false)); run_threads.back()->Start(); run_threads.push_back(std::make_unique<ThreadPostingAndRunningTask>( - &tracker_, std::move(tasks_skip_on_shutdown[i]), - traits_skip_on_shutdown, ThreadPostingAndRunningTask::Action::RUN, - false)); + &tracker_, std::move(sequences_skip_on_shutdown[i]), + ThreadPostingAndRunningTask::Action::RUN, false)); run_threads.back()->Start(); run_threads.push_back(std::make_unique<ThreadPostingAndRunningTask>( - &tracker_, std::move(tasks_block_shutdown[i]), traits_block_shutdown, + &tracker_, std::move(sequences_block_shutdown[i]), ThreadPostingAndRunningTask::Action::RUN, false)); run_threads.back()->Start(); } @@ -1003,9 +1065,9 @@ TEST_F(ThreadPoolTaskTrackerTest, LoadWillPostAndRunDuringShutdown) { // Inform |task_tracker_| that a BLOCK_SHUTDOWN task will be posted just to // block shutdown. - Task block_shutdown_task(CreateTask()); - EXPECT_TRUE(tracker_.WillPostTask(&block_shutdown_task, - TaskShutdownBehavior::BLOCK_SHUTDOWN)); + auto block_shutdown_sequence = WillPostTaskAndQueueTaskSource( + CreateTask(), TaskShutdownBehavior::BLOCK_SHUTDOWN); + EXPECT_TRUE(block_shutdown_sequence); // Start shutdown and try to complete it asynchronously. tracker_.StartShutdown(); @@ -1016,21 +1078,27 @@ for (size_t i = 0; i < kLoadTestNumIterations; ++i) { threads.push_back(std::make_unique<ThreadPostingAndRunningTask>( - &tracker_, CreateTask(), - TaskTraits(TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN), - ThreadPostingAndRunningTask::Action::WILL_POST_AND_RUN, false)); + &tracker_, + MakeRefCounted<Sequence>(TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN, + nullptr, TaskSourceExecutionMode::kParallel), + ThreadPostingAndRunningTask::Action::WILL_POST_AND_RUN, false, + CreateTask())); threads.back()->Start(); threads.push_back(std::make_unique<ThreadPostingAndRunningTask>( - &tracker_, CreateTask(), - TaskTraits(TaskShutdownBehavior::SKIP_ON_SHUTDOWN), - ThreadPostingAndRunningTask::Action::WILL_POST_AND_RUN, false)); + &tracker_, + MakeRefCounted<Sequence>(TaskShutdownBehavior::SKIP_ON_SHUTDOWN, + nullptr, TaskSourceExecutionMode::kParallel), + ThreadPostingAndRunningTask::Action::WILL_POST_AND_RUN, false, + CreateTask())); threads.back()->Start(); threads.push_back(std::make_unique<ThreadPostingAndRunningTask>( - &tracker_, CreateTask(), - TaskTraits(TaskShutdownBehavior::BLOCK_SHUTDOWN), - ThreadPostingAndRunningTask::Action::WILL_POST_AND_RUN, true)); + &tracker_, + MakeRefCounted<Sequence>(TaskShutdownBehavior::BLOCK_SHUTDOWN, nullptr, + TaskSourceExecutionMode::kParallel), + ThreadPostingAndRunningTask::Action::WILL_POST_AND_RUN, true, + CreateTask())); threads.back()->Start(); } @@ -1044,9 +1112,7 @@ VERIFY_ASYNC_SHUTDOWN_IN_PROGRESS(); // Unblock shutdown by running |block_shutdown_task|. - DispatchAndRunTaskWithTracker( - std::move(block_shutdown_task), - TaskTraits(TaskShutdownBehavior::BLOCK_SHUTDOWN)); + tracker_.RunAndPopNextTask(std::move(block_shutdown_sequence)); EXPECT_EQ(kLoadTestNumIterations + 1, NumTasksExecuted()); WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED(); } @@ -1066,7 +1132,7 @@ scoped_refptr<Sequence> sequence = test::CreateSequenceWithTask(std::move(task_1), default_traits); sequence->BeginTransaction().PushTask(std::move(task_2)); - EXPECT_EQ(sequence, tracker_.RunAndPopNextTask(sequence)); + EXPECT_EQ(sequence, test::QueueAndRunTaskSource(&tracker_, sequence)); } namespace { @@ -1092,8 +1158,8 @@ default_traits.shutdown_behavior())); auto sequence_without_sync_primitives = test::CreateSequenceWithTask( std::move(task_without_sync_primitives), default_traits); - task_tracker->RunAndPopNextTask( - std::move(sequence_without_sync_primitives)); + test::QueueAndRunTaskSource(task_tracker.get(), + std::move(sequence_without_sync_primitives)); // Disallow waiting. Expect TaskTracker to allow it before running a task // with the WithBaseSyncPrimitives() trait. @@ -1111,7 +1177,8 @@ traits_with_sync_primitives.shutdown_behavior())); auto sequence_with_sync_primitives = test::CreateSequenceWithTask( std::move(task_with_sync_primitives), traits_with_sync_primitives); - task_tracker->RunAndPopNextTask(std::move(sequence_with_sync_primitives)); + test::QueueAndRunTaskSource(task_tracker.get(), + std::move(sequence_with_sync_primitives)); ScopedAllowBaseSyncPrimitivesForTesting allow_wait_in_task_tracker_destructor; @@ -1180,8 +1247,8 @@ HistogramTester tester; - tracker.RunAndPopNextTask( - test::CreateSequenceWithTask(std::move(task), test.traits)); + test::QueueAndRunTaskSource( + &tracker, test::CreateSequenceWithTask(std::move(task), test.traits)); tester.ExpectTotalCount(test.expected_histogram, 1); } }
diff --git a/base/task/thread_pool/test_utils.cc b/base/task/thread_pool/test_utils.cc index 671d871..341c979 100644 --- a/base/task/thread_pool/test_utils.cc +++ b/base/task/thread_pool/test_utils.cc
@@ -118,9 +118,7 @@ return false; if (task.delayed_run_time.is_null()) { - thread_group_->PostTaskWithSequenceNow( - std::move(task), - SequenceAndTransaction::FromSequence(std::move(sequence))); + PostTaskWithSequenceNow(std::move(task), std::move(sequence)); } else { // It's safe to take a ref on this pointer since the caller must have a ref // to the TaskRunner in order to post. @@ -128,19 +126,33 @@ delayed_task_manager_->AddDelayedTask( std::move(task), BindOnce( - [](scoped_refptr<Sequence> sequence, ThreadGroup* thread_group, - Task task) { - thread_group->PostTaskWithSequenceNow( - std::move(task), - SequenceAndTransaction::FromSequence(std::move(sequence))); + [](scoped_refptr<Sequence> sequence, + MockPooledTaskRunnerDelegate* self, Task task) { + self->PostTaskWithSequenceNow(std::move(task), + std::move(sequence)); }, - std::move(sequence), thread_group_), + std::move(sequence), Unretained(this)), std::move(task_runner)); } return true; } +void MockPooledTaskRunnerDelegate::PostTaskWithSequenceNow( + Task task, + scoped_refptr<Sequence> sequence) { + auto transaction = sequence->BeginTransaction(); + const bool sequence_should_be_queued = transaction.WillPushTask(); + if (sequence_should_be_queued && + !task_tracker_->WillQueueTaskSource(sequence.get())) + return; + transaction.PushTask(std::move(task)); + if (sequence_should_be_queued) { + thread_group_->PushTaskSourceAndWakeUpWorkers( + {std::move(sequence), std::move(transaction)}); + } +} + bool MockPooledTaskRunnerDelegate::IsRunningPoolWithTraits( const TaskTraits& traits) const { // |thread_group_| must be initialized with SetThreadGroup() before @@ -163,6 +175,14 @@ thread_group_ = thread_group; } +scoped_refptr<TaskSource> QueueAndRunTaskSource( + TaskTracker* task_tracker, + scoped_refptr<TaskSource> task_source) { + if (!task_tracker->WillQueueTaskSource(task_source.get())) + return nullptr; + return task_tracker->RunAndPopNextTask(std::move(task_source)); +} + void ShutdownTaskTracker(TaskTracker* task_tracker) { task_tracker->StartShutdown(); task_tracker->CompleteShutdown();
diff --git a/base/task/thread_pool/test_utils.h b/base/task/thread_pool/test_utils.h index 3c8d52de..d4f33c0 100644 --- a/base/task/thread_pool/test_utils.h +++ b/base/task/thread_pool/test_utils.h
@@ -62,6 +62,8 @@ void SetThreadGroup(ThreadGroup* thread_group); + void PostTaskWithSequenceNow(Task task, scoped_refptr<Sequence> sequence); + private: const TrackedRef<TaskTracker> task_tracker_; DelayedTaskManager* const delayed_task_manager_; @@ -105,6 +107,10 @@ void WaitWithoutBlockingObserver(WaitableEvent* event); +scoped_refptr<TaskSource> QueueAndRunTaskSource( + TaskTracker* task_tracker, + scoped_refptr<TaskSource> task_source); + // Calls StartShutdown() and CompleteShutdown() on |task_tracker|. void ShutdownTaskTracker(TaskTracker* task_tracker);
diff --git a/base/task/thread_pool/thread_group.cc b/base/task/thread_pool/thread_group.cc index 4ae9473e..b3b5177 100644 --- a/base/task/thread_pool/thread_group.cc +++ b/base/task/thread_pool/thread_group.cc
@@ -73,24 +73,6 @@ return GetCurrentThreadGroup() == this; } -void ThreadGroup::PostTaskWithSequenceNow( - Task task, - SequenceAndTransaction sequence_and_transaction) { - DCHECK(task.task); - - // Confirm that |task| is ready to run (its delayed run time is either null or - // in the past). - DCHECK_LE(task.delayed_run_time, TimeTicks::Now()); - - const bool sequence_should_be_queued = - sequence_and_transaction.transaction.PushTask(std::move(task)); - if (sequence_should_be_queued) { - PushTaskSourceAndWakeUpWorkers( - {std::move(sequence_and_transaction.sequence), - std::move(sequence_and_transaction.transaction)}); - } -} - size_t ThreadGroup::GetNumQueuedCanRunBestEffortTaskSources() const { const size_t num_queued = priority_queue_.GetNumTaskSourcesWithPriority(TaskPriority::BEST_EFFORT);
diff --git a/base/task/thread_pool/thread_group.h b/base/task/thread_pool/thread_group.h index f0d0508..3550b190 100644 --- a/base/task/thread_pool/thread_group.h +++ b/base/task/thread_pool/thread_group.h
@@ -9,7 +9,6 @@ #include "base/memory/ref_counted.h" #include "base/task/common/checked_lock.h" #include "base/task/thread_pool/priority_queue.h" -#include "base/task/thread_pool/sequence.h" #include "base/task/thread_pool/task.h" #include "base/task/thread_pool/task_source.h" #include "base/task/thread_pool/tracked_ref.h" @@ -47,13 +46,6 @@ virtual ~ThreadGroup(); - // Posts |task| to be executed by this ThreadGroup as part of - // the Sequence in |sequence_and_transaction|. This must only be called after - // |task| has gone through TaskTracker::WillPostTask() and after |task|'s - // delayed run time. - void PostTaskWithSequenceNow(Task task, - SequenceAndTransaction sequence_and_transaction); - // Registers the thread group in TLS. void BindToCurrentThread();
diff --git a/base/task/thread_pool/thread_pool_impl.cc b/base/task/thread_pool/thread_pool_impl.cc index 09955498..3bf56c9 100644 --- a/base/task/thread_pool/thread_pool_impl.cc +++ b/base/task/thread_pool/thread_pool_impl.cc
@@ -312,6 +312,22 @@ UpdateCanRunPolicy(); } +bool ThreadPoolImpl::PostTaskWithSequenceNow(Task task, + scoped_refptr<Sequence> sequence) { + auto transaction = sequence->BeginTransaction(); + const bool sequence_should_be_queued = transaction.WillPushTask(); + if (sequence_should_be_queued && + !task_tracker_->WillQueueTaskSource(sequence.get())) + return false; + transaction.PushTask(std::move(task)); + if (sequence_should_be_queued) { + const TaskTraits traits = transaction.traits(); + GetThreadGroupForTraits(traits)->PushTaskSourceAndWakeUpWorkers( + {std::move(sequence), std::move(transaction)}); + } + return true; +} + bool ThreadPoolImpl::PostTaskWithSequence(Task task, scoped_refptr<Sequence> sequence) { // Use CHECK instead of DCHECK to crash earlier. See http://crbug.com/711167 @@ -323,11 +339,7 @@ return false; if (task.delayed_run_time.is_null()) { - auto sequence_and_transaction = - SequenceAndTransaction::FromSequence(std::move(sequence)); - const TaskTraits traits = sequence_and_transaction.transaction.traits(); - GetThreadGroupForTraits(traits)->PostTaskWithSequenceNow( - std::move(task), std::move(sequence_and_transaction)); + return PostTaskWithSequenceNow(std::move(task), std::move(sequence)); } else { // It's safe to take a ref on this pointer since the caller must have a ref // to the TaskRunner in order to post. @@ -337,13 +349,8 @@ BindOnce( [](scoped_refptr<Sequence> sequence, ThreadPoolImpl* thread_pool_impl, Task task) { - auto sequence_and_transaction = - SequenceAndTransaction::FromSequence(std::move(sequence)); - const TaskTraits traits = - sequence_and_transaction.transaction.traits(); - thread_pool_impl->GetThreadGroupForTraits(traits) - ->PostTaskWithSequenceNow( - std::move(task), std::move(sequence_and_transaction)); + thread_pool_impl->PostTaskWithSequenceNow(std::move(task), + std::move(sequence)); }, std::move(sequence), Unretained(this)), std::move(task_runner));
diff --git a/base/task/thread_pool/thread_pool_impl.h b/base/task/thread_pool/thread_pool_impl.h index 00b7d0a..d8ef7255 100644 --- a/base/task/thread_pool/thread_pool_impl.h +++ b/base/task/thread_pool/thread_pool_impl.h
@@ -23,6 +23,7 @@ #include "base/task/thread_pool/environment_config.h" #include "base/task/thread_pool/pooled_single_thread_task_runner_manager.h" #include "base/task/thread_pool/pooled_task_runner_delegate.h" +#include "base/task/thread_pool/task_source.h" #include "base/task/thread_pool/task_tracker.h" #include "base/task/thread_pool/thread_group.h" #include "base/task/thread_pool/thread_group_impl.h" @@ -115,6 +116,11 @@ // ThreadGroup::Delegate: ThreadGroup* GetThreadGroupForTraits(const TaskTraits& traits) override; + // Posts |task| to be executed by the appropriate thread group as part of + // |sequence|. This must only be called after |task| has gone through + // TaskTracker::WillPostTask() and after |task|'s delayed run time. + bool PostTaskWithSequenceNow(Task task, scoped_refptr<Sequence> sequence); + // PooledTaskRunnerDelegate: bool PostTaskWithSequence(Task task, scoped_refptr<Sequence> sequence) override;
diff --git a/base/task/thread_pool/worker_thread_unittest.cc b/base/task/thread_pool/worker_thread_unittest.cc index 0611af5..08b98cd 100644 --- a/base/task/thread_pool/worker_thread_unittest.cc +++ b/base/task/thread_pool/worker_thread_unittest.cc
@@ -60,7 +60,7 @@ scoped_refptr<TaskSource> GetWork(WorkerThread* worker) override { return nullptr; } - void DidRunTask(scoped_refptr<TaskSource> sequence) override { + void DidRunTask(scoped_refptr<TaskSource> task_source) override { ADD_FAILURE() << "Unexpected call to DidRunTask()"; } TimeDelta GetSleepTimeout() override { return TimeDelta::Max(); } @@ -184,6 +184,7 @@ &task, sequence->shutdown_behavior())); sequence_transaction.PushTask(std::move(task)); } + EXPECT_TRUE(outer_->task_tracker_.WillQueueTaskSource(sequence.get())); ExpectCallToDidRunTask(); @@ -192,39 +193,38 @@ CheckedAutoLock auto_lock(outer_->lock_); outer_->created_sequences_.push_back(sequence); } - return sequence; } - // This override verifies that |sequence| has the expected number of Tasks - // and adds it to |did_run_task_sequences_|. Unlike a normal DidRunTask() - // implementation, it doesn't add |sequence| to a queue for further - // execution. - void DidRunTask(scoped_refptr<TaskSource> sequence) override { + // This override verifies that |task_source| has the expected number of + // Tasks and adds it to |did_run_task_sequences_|. Unlike a normal + // DidRunTask() implementation, it doesn't add |task_source| to a queue for + // further execution. + void DidRunTask(scoped_refptr<TaskSource> task_source) override { { CheckedAutoLock auto_lock(expect_did_run_task_lock_); EXPECT_TRUE(expect_did_run_task_); expect_did_run_task_ = false; } - // If TasksPerSequence() is 1, |sequence| should be nullptr. Otherwise, - // |sequence| should contain TasksPerSequence() - 1 Tasks. + // If TasksPerSequence() is 1, |task_source| should be nullptr. Otherwise, + // |task_source| should contain TasksPerSequence() - 1 Tasks. if (outer_->TasksPerSequence() == 1) { - EXPECT_FALSE(sequence); + EXPECT_FALSE(task_source); } else { - EXPECT_TRUE(sequence); + EXPECT_TRUE(task_source); - // Verify the number of Tasks in |sequence|. - auto sequence_transaction(sequence->BeginTransaction()); + // Verify the number of Tasks in |task_source|. + auto transaction(task_source->BeginTransaction()); for (int i = 0; i < outer_->TasksPerSequence() - 1; ++i) { - EXPECT_TRUE(sequence_transaction.TakeTask()); + EXPECT_TRUE(transaction.TakeTask()); EXPECT_EQ(i == outer_->TasksPerSequence() - 2, - !sequence_transaction.DidRunTask()); + !transaction.DidRunTask()); } - // Add |sequence| to |did_run_task_sequences_|. + // Add |task_source| to |did_run_task_sequences_|. CheckedAutoLock auto_lock(outer_->lock_); - outer_->did_run_task_sequences_.push_back(std::move(sequence)); + outer_->did_run_task_sequences_.push_back(std::move(task_source)); EXPECT_LE(outer_->did_run_task_sequences_.size(), outer_->created_sequences_.size()); } @@ -456,6 +456,7 @@ EXPECT_TRUE( task_tracker_->WillPostTask(&task, sequence->shutdown_behavior())); sequence->BeginTransaction().PushTask(std::move(task)); + EXPECT_TRUE(task_tracker_->WillQueueTaskSource(sequence.get())); return sequence; } @@ -737,8 +738,10 @@ // Block shutdown to ensure that the worker doesn't exit when StartShutdown() // is called. - Task task(FROM_HERE, DoNothing(), TimeDelta()); - task_tracker.WillPostTask(&task, TaskShutdownBehavior::BLOCK_SHUTDOWN); + scoped_refptr<Sequence> sequence = + MakeRefCounted<Sequence>(TaskTraits(TaskShutdownBehavior::BLOCK_SHUTDOWN), + nullptr, TaskSourceExecutionMode::kParallel); + task_tracker.WillQueueTaskSource(sequence.get()); std::unique_ptr<ExpectThreadPriorityDelegate> delegate( new ExpectThreadPriorityDelegate);
diff --git a/base/test/BUILD.gn b/base/test/BUILD.gn index 1d20e94e..518f959 100644 --- a/base/test/BUILD.gn +++ b/base/test/BUILD.gn
@@ -347,6 +347,27 @@ ] } +# This shared library is dynamically loaded by ImmediateCrash unittests. +shared_library("immediate_crash_test_helper") { + sources = [ + "immediate_crash_test_helper.cc", + ] + + # Note: the helper has a header-only dependency on //base/immediate_helper.h. + # However, the build rule intentionally omits an explicit //base dependency + # to avoid potential ODR violations and minimize the amount of code linked in. + + # Try to minimize the risk of non-official builds generating different code. + if (!is_official_build) { + configs -= [ "//build/config/compiler:default_optimization" ] + configs += [ "//build/config/compiler:optimize_max" ] + } + + if (is_android) { + configs -= [ "//build/config/android:hide_all_but_jni_onload" ] + } +} + # This shared library is dynamically loaded by NativeLibrary unittests. shared_library("test_shared_library") { testonly = true
diff --git a/base/test/immediate_crash_test_helper.cc b/base/test/immediate_crash_test_helper.cc new file mode 100644 index 0000000..676a2ba6 --- /dev/null +++ b/base/test/immediate_crash_test_helper.cc
@@ -0,0 +1,32 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/immediate_crash.h" // nogncheck + +#if defined(WIN32) +#define IMMEDIATE_CRASH_TEST_HELPER_EXPORT __declspec(dllexport) +#else // defined(WIN32) +#define IMMEDIATE_CRASH_TEST_HELPER_EXPORT \ + __attribute__((visibility("default"))) +#endif // defined(WIN32) + +extern "C" { + +IMMEDIATE_CRASH_TEST_HELPER_EXPORT int TestFunction1(int x, int y) { + if (x < 1) + IMMEDIATE_CRASH(); + if (y < 1) + IMMEDIATE_CRASH(); + return x + y; +} + +IMMEDIATE_CRASH_TEST_HELPER_EXPORT int TestFunction2(int x, int y) { + if (x < 2) + IMMEDIATE_CRASH(); + if (y < 2) + IMMEDIATE_CRASH(); + return x * y; +} + +} // extern "C"
diff --git a/base/test/scoped_task_environment.cc b/base/test/scoped_task_environment.cc index 7e51e08..562d49c 100644 --- a/base/test/scoped_task_environment.cc +++ b/base/test/scoped_task_environment.cc
@@ -581,7 +581,7 @@ // verified which could result in HasIncompleteUndelayedTasksForTesting() // returning false and the loop erroneously exiting with a pending task on // the main thread. - if (!task_tracker_->HasIncompleteUndelayedTasksForTesting()) + if (!task_tracker_->HasIncompleteTaskSourcesForTesting()) break; }
diff --git a/build/android/arbitrary_main_dex.flags b/build/android/arbitrary_main_dex.flags new file mode 100644 index 0000000..55bfb92 --- /dev/null +++ b/build/android/arbitrary_main_dex.flags
@@ -0,0 +1,15 @@ +# Copyright 2019 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# Proguard flags to pass to R8 which do nothing, and thus allows R8 to +# arbitrarily assign code to different dex files. If we pass a flags file with +# no rules, R8 applies default main dex rules which usually include too much +# and pushes us over the main dex limit. We can't pass higher --min-api since we +# also want to allow multidex in libraries, which are compiled with a low +# min-api. Thus, we have rules which won't do anything to pass as a +# main-dex-rule. + +-keep class this.should.not.match.anything { + *; +}
diff --git a/build/android/gyp/compile_resources.py b/build/android/gyp/compile_resources.py index 350c215..721e1a81 100755 --- a/build/android/gyp/compile_resources.py +++ b/build/android/gyp/compile_resources.py
@@ -535,11 +535,14 @@ partial_path = os.path.join(partials_dir, dirname + '.zip') compile_command = (partial_compile_command + ['--dir', directory, '-o', partial_path]) + # There are resources targeting API-versions lower than our minapi. For + # various reasons it's easier to let aapt2 ignore these than for us to + # remove them from our build (e.g. it's from a 3rd party library). build_utils.CheckOutput( compile_command, stderr_filter=lambda output: build_utils.FilterLines( - output, r'ignoring configuration .* for styleable')) + output, r'ignoring configuration .* for (styleable|attribute)')) # Sorting the files in the partial ensures deterministic output from the # aapt2 link step which uses order of files in the partial.
diff --git a/build/config/BUILDCONFIG.gn b/build/config/BUILDCONFIG.gn index 37bfe8b9..d8c49c5 100644 --- a/build/config/BUILDCONFIG.gn +++ b/build/config/BUILDCONFIG.gn
@@ -422,7 +422,6 @@ "//build/config:feature_flags", "//build/config/compiler:afdo", "//build/config/compiler:afdo_optimize_size", - "//build/config/compiler:assembler_debug_dir", "//build/config/compiler:compiler", "//build/config/compiler:compiler_arm_fpu", "//build/config/compiler:compiler_arm_thumb",
diff --git a/build/config/android/internal_rules.gni b/build/config/android/internal_rules.gni index b01289a..dc4893f 100644 --- a/build/config/android/internal_rules.gni +++ b/build/config/android/internal_rules.gni
@@ -1300,9 +1300,11 @@ ] inputs += [ _main_dex_rules ] } else { - if (defined(invoker.extra_main_dex_proguard_config)) { - not_needed(invoker, [ "extra_main_dex_proguard_config" ]) - } + args += [ + "--main-dex-rules-path", + rebase_path("//build/android/arbitrary_main_dex.flags", + root_build_dir), + ] } }
diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn index b4b0522..f10fd1e 100644 --- a/build/config/compiler/BUILD.gn +++ b/build/config/compiler/BUILD.gn
@@ -1098,6 +1098,10 @@ "-Xclang", ".", ] + if (!is_win) { + # We don't use clang -cc1as on Windows (yet? https://crbug.com/762167) + asmflags = [ "-Wa,-fdebug-compilation-dir,." ] + } if (is_win && use_lld) { if (symbol_level == 2 || (is_clang && using_sanitizer)) { @@ -1171,18 +1175,6 @@ } } -config("assembler_debug_dir") { - # TODO(thakis): Once openmax_dl no longer uses -fno-integrated-as, move - # this behind the -fdebug-compilation-dir cflags in the "compiler" config. - if (symbol_level != 0 && is_clang && - strip_absolute_paths_from_debug_symbols) { - if (!is_win) { - # We don't use clang -cc1as on Windows (yet? https://crbug.com/762167) - asmflags = [ "-Wa,-fdebug-compilation-dir,." ] - } - } -} - # runtime_library ------------------------------------------------------------- # # Sets the runtime library and associated options.
diff --git a/build/fuchsia/linux.sdk.sha1 b/build/fuchsia/linux.sdk.sha1 index f2d5f730..30b5e46 100644 --- a/build/fuchsia/linux.sdk.sha1 +++ b/build/fuchsia/linux.sdk.sha1
@@ -1 +1 @@ -8913928381394866528 \ No newline at end of file +8913901306260496704 \ No newline at end of file
diff --git a/build/fuchsia/mac.sdk.sha1 b/build/fuchsia/mac.sdk.sha1 index 2632e4e..74d0a87 100644 --- a/build/fuchsia/mac.sdk.sha1 +++ b/build/fuchsia/mac.sdk.sha1
@@ -1 +1 @@ -8913934899603518544 \ No newline at end of file +8913908069615752272 \ No newline at end of file
diff --git a/cc/animation/keyframed_animation_curve_unittest.cc b/cc/animation/keyframed_animation_curve_unittest.cc index 05ab214..4b678bdf 100644 --- a/cc/animation/keyframed_animation_curve_unittest.cc +++ b/cc/animation/keyframed_animation_curve_unittest.cc
@@ -602,30 +602,6 @@ } } -// Tests a frames timing function. -TEST(KeyframedAnimationCurveTest, FramesTimingFunction) { - std::unique_ptr<KeyframedFloatAnimationCurve> curve( - KeyframedFloatAnimationCurve::Create()); - curve->AddKeyframe(FloatKeyframe::Create(base::TimeDelta(), 0.f, - FramesTimingFunction::Create(5))); - curve->AddKeyframe( - FloatKeyframe::Create(base::TimeDelta::FromSecondsD(1.0), 1.f, nullptr)); - - struct Expected { - double time; - float value; - } expectations[] = { - {0.0, 0.f}, {0.1999, 0.f}, {0.2001, 0.25f}, {0.3999, 0.25f}, - {0.4001, 0.5f}, {0.5999, 0.5f}, {0.6001, 0.75f}, {0.7999, 0.75f}, - {0.8001, 1.f}, {1.0, 1.f}, - }; - for (const auto& expectation : expectations) { - EXPECT_FLOAT_EQ( - expectation.value, - curve->GetValue(base::TimeDelta::FromSecondsD(expectation.time))); - } -} - // Tests that animations that are translations are correctly identified. TEST(KeyframedAnimationCurveTest, IsTranslation) { std::unique_ptr<KeyframedTransformAnimationCurve> curve( @@ -916,23 +892,6 @@ EXPECT_FLOAT_EQ(2.f, curve->GetValue(base::TimeDelta::FromSecondsD(0.75f))); } -// Tests that a frames timing function works as expected for inputs outside of -// range [0,1] -TEST(KeyframedAnimationCurveTest, FramesTimingInputsOutsideZeroOneRange) { - std::unique_ptr<KeyframedFloatAnimationCurve> curve( - KeyframedFloatAnimationCurve::Create()); - curve->AddKeyframe(FloatKeyframe::Create(base::TimeDelta(), 0.f, - FramesTimingFunction::Create(5))); - curve->AddKeyframe( - FloatKeyframe::Create(base::TimeDelta::FromSecondsD(1.0), 2.f, nullptr)); - // Curve timing function producing timing outputs outside of range [0,1]. - curve->SetTimingFunction( - CubicBezierTimingFunction::Create(0.5f, -0.5f, 0.5f, 1.5f)); - - EXPECT_FLOAT_EQ(-0.5f, curve->GetValue(base::TimeDelta::FromSecondsD(0.25f))); - EXPECT_FLOAT_EQ(2.5f, curve->GetValue(base::TimeDelta::FromSecondsD(0.75f))); -} - // Tests that an animation with a curve timing function and multiple keyframes // works as expected. TEST(KeyframedAnimationCurveTest, CurveTimingMultipleKeyframes) {
diff --git a/cc/animation/timing_function.cc b/cc/animation/timing_function.cc index 6b6110d..f7f8c6e 100644 --- a/cc/animation/timing_function.cc +++ b/cc/animation/timing_function.cc
@@ -118,36 +118,4 @@ } } -std::unique_ptr<FramesTimingFunction> FramesTimingFunction::Create(int frames) { - return base::WrapUnique(new FramesTimingFunction(frames)); -} - -FramesTimingFunction::FramesTimingFunction(int frames) : frames_(frames) {} - -FramesTimingFunction::~FramesTimingFunction() = default; - -TimingFunction::Type FramesTimingFunction::GetType() const { - return Type::FRAMES; -} - -double FramesTimingFunction::GetValue(double t) const { - return GetPreciseValue(t); -} - -std::unique_ptr<TimingFunction> FramesTimingFunction::Clone() const { - return base::WrapUnique(new FramesTimingFunction(*this)); -} - -double FramesTimingFunction::Velocity(double x) const { - return 0; -} - -double FramesTimingFunction::GetPreciseValue(double t) const { - const double frames = static_cast<double>(frames_); - double output_progress = std::floor(frames * t) / (frames - 1); - if (t <= 1 && output_progress > 1) - output_progress = 1; - return output_progress; -} - } // namespace cc
diff --git a/cc/animation/timing_function.h b/cc/animation/timing_function.h index 77969ac4..a215a0fb 100644 --- a/cc/animation/timing_function.h +++ b/cc/animation/timing_function.h
@@ -20,7 +20,7 @@ TimingFunction& operator=(const TimingFunction&) = delete; // Note that LINEAR is a nullptr TimingFunction (for now). - enum class Type { LINEAR, CUBIC_BEZIER, STEPS, FRAMES }; + enum class Type { LINEAR, CUBIC_BEZIER, STEPS }; virtual Type GetType() const = 0; virtual double GetValue(double t) const = 0; @@ -98,28 +98,6 @@ StepPosition step_position_; }; -class CC_ANIMATION_EXPORT FramesTimingFunction : public TimingFunction { - public: - static std::unique_ptr<FramesTimingFunction> Create(int frames); - ~FramesTimingFunction() override; - - FramesTimingFunction& operator=(const FramesTimingFunction&) = delete; - - // TimingFunction implementation. - Type GetType() const override; - double GetValue(double t) const override; - std::unique_ptr<TimingFunction> Clone() const override; - double Velocity(double time) const override; - - int frames() const { return frames_; } - double GetPreciseValue(double t) const; - - private: - explicit FramesTimingFunction(int frames); - - int frames_; -}; - } // namespace cc #endif // CC_ANIMATION_TIMING_FUNCTION_H_
diff --git a/cc/layers/heads_up_display_layer_impl.cc b/cc/layers/heads_up_display_layer_impl.cc index 114ee63..a98a6de1 100644 --- a/cc/layers/heads_up_display_layer_impl.cc +++ b/cc/layers/heads_up_display_layer_impl.cc
@@ -594,11 +594,11 @@ if (align == TextAlign::kCenter) { auto width = - font.measureText(text.c_str(), text.length(), kUTF8_SkTextEncoding); + font.measureText(text.c_str(), text.length(), SkTextEncoding::kUTF8); x -= width * 0.5f; } else if (align == TextAlign::kRight) { auto width = - font.measureText(text.c_str(), text.length(), kUTF8_SkTextEncoding); + font.measureText(text.c_str(), text.length(), SkTextEncoding::kUTF8); x -= width; } @@ -953,7 +953,7 @@ SkFont label_font(typeface_, kFontHeight); const SkScalar label_text_width = label_font.measureText( - label_text.c_str(), label_text.length(), kUTF8_SkTextEncoding); + label_text.c_str(), label_text.length(), SkTextEncoding::kUTF8); canvas->drawRect(SkRect::MakeWH(label_text_width + 2 * kPadding, kFontHeight + 2 * kPadding), label_flags);
diff --git a/chrome/BUILD.gn b/chrome/BUILD.gn index 358d9e1..b8c06ea4 100644 --- a/chrome/BUILD.gn +++ b/chrome/BUILD.gn
@@ -1646,6 +1646,7 @@ if (!is_android) { public_deps += [ "//chrome/browser/resources:component_extension_resources", + "//chrome/browser/resources:downloads_resources", "//chrome/browser/resources:local_ntp_resources", "//chrome/browser/resources:settings_resources", ]
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn index dacca1a5..633a8f4c 100644 --- a/chrome/android/BUILD.gn +++ b/chrome/android/BUILD.gn
@@ -2232,6 +2232,7 @@ module_name = "Vr" + _bundle_name base_module_target = ":$_base_module_target_name" native_switches = _native_switches + is_monochrome_or_trichrome = true uncompress_shared_libraries = true version_code = _version_code version_name = _version_name
diff --git a/chrome/android/chrome_java_sources.gni b/chrome/android/chrome_java_sources.gni index f2e43f9..415a1605 100644 --- a/chrome/android/chrome_java_sources.gni +++ b/chrome/android/chrome_java_sources.gni
@@ -418,7 +418,6 @@ "java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/ModuleMetrics.java", "java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/ObjectWrapper.java", "java/src/org/chromium/chrome/browser/database/SQLiteCursor.java", - "java/src/org/chromium/chrome/browser/datareduction/DataReductionBrandingResourceProvider.java", "java/src/org/chromium/chrome/browser/datareduction/DataReductionMainMenuItem.java", "java/src/org/chromium/chrome/browser/datareduction/DataReductionPromoScreen.java", "java/src/org/chromium/chrome/browser/datareduction/DataReductionPromoUtils.java", @@ -1144,6 +1143,7 @@ "java/src/org/chromium/chrome/browser/payments/PaymentPreferencesUtil.java", "java/src/org/chromium/chrome/browser/payments/PaymentRequestFactory.java", "java/src/org/chromium/chrome/browser/payments/PaymentRequestImpl.java", + "java/src/org/chromium/chrome/browser/payments/PaymentsExperimentalFeatures.java", "java/src/org/chromium/chrome/browser/payments/PaymentResponseHelper.java", "java/src/org/chromium/chrome/browser/payments/ServiceWorkerPaymentApp.java", "java/src/org/chromium/chrome/browser/payments/ServiceWorkerPaymentAppBridge.java", @@ -1238,7 +1238,6 @@ "java/src/org/chromium/chrome/browser/preferences/autofill/CreditCardNumberFormattingTextWatcher.java", "java/src/org/chromium/chrome/browser/preferences/autofill_assistant/AutofillAssistantPreferences.java", "java/src/org/chromium/chrome/browser/preferences/datareduction/DataReductionDataUseItem.java", - "java/src/org/chromium/chrome/browser/preferences/datareduction/DataReductionPreference.java", "java/src/org/chromium/chrome/browser/preferences/datareduction/DataReductionPreferenceFragment.java", "java/src/org/chromium/chrome/browser/preferences/datareduction/DataReductionSiteBreakdownView.java", "java/src/org/chromium/chrome/browser/preferences/datareduction/DataReductionStatsPreference.java",
diff --git a/chrome/android/features/ar/ar_module_tmpl.gni b/chrome/android/features/ar/ar_module_tmpl.gni index 4f232922..8c4570d 100644 --- a/chrome/android/features/ar/ar_module_tmpl.gni +++ b/chrome/android/features/ar/ar_module_tmpl.gni
@@ -4,7 +4,7 @@ import("//build/config/android/rules.gni") import("//build/config/locales.gni") -import("//chrome/android/features/module_names_to_package_ids.gni") +import("//chrome/android/features/dynamic_feature_modules.gni") import("//device/vr/buildflags/buildflags.gni") assert(enable_arcore)
diff --git a/chrome/android/features/autofill_assistant/autofill_assistant_module_tmpl.gni b/chrome/android/features/autofill_assistant/autofill_assistant_module_tmpl.gni index 4c1733cf..52964d52 100644 --- a/chrome/android/features/autofill_assistant/autofill_assistant_module_tmpl.gni +++ b/chrome/android/features/autofill_assistant/autofill_assistant_module_tmpl.gni
@@ -1,6 +1,6 @@ import("//build/config/android/rules.gni") import("//build/config/locales.gni") -import("//chrome/android/features/module_names_to_package_ids.gni") +import("//chrome/android/features/dynamic_feature_modules.gni") template("autofill_assistant_module_tmpl") { _manifest = "$target_gen_dir/$target_name/AndroidManifest.xml"
diff --git a/chrome/android/features/dynamic_feature_modules.gni b/chrome/android/features/dynamic_feature_modules.gni new file mode 100644 index 0000000..32808a5 --- /dev/null +++ b/chrome/android/features/dynamic_feature_modules.gni
@@ -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. + +import("//build/config/compiler/compiler.gni") +import("//device/vr/buildflags/buildflags.gni") + +# This file aggregates data used when pulling DFM-related dependencies into +# bundle builds. As DFMs move to describe their parameters in a standard way, +# this file may evolve to an aggregation of individual DFM configurations. + +# Mapping that controls package IDs assigned to modules. +resource_packages_id_mapping = [ + "ar=0x7e", + "vr=0x7d", + "tab_ui=0x7c", + "autofill_assistant=0x7b", +] + +# This variable indicates whether the native feature module system is engaged. +# Currently, this implies a build configuration that supports native modules, +# and that at least one feature is using a native module. +if (is_clang && use_lld && !is_component_build) { + use_native_modules = enable_vr && modularize_vr_native +} else { + use_native_modules = false +}
diff --git a/chrome/android/features/module_names_to_package_ids.gni b/chrome/android/features/module_names_to_package_ids.gni deleted file mode 100644 index 24c43a5..0000000 --- a/chrome/android/features/module_names_to_package_ids.gni +++ /dev/null
@@ -1,7 +0,0 @@ -# Mapping that controls package IDs assigned to modules. -resource_packages_id_mapping = [ - "ar=0x7e", - "vr=0x7d", - "tab_ui=0x7c", - "autofill_assistant=0x7b", -]
diff --git a/chrome/android/features/tab_ui/tab_ui_module_tmpl.gni b/chrome/android/features/tab_ui/tab_ui_module_tmpl.gni index b85d55f..4e10712 100644 --- a/chrome/android/features/tab_ui/tab_ui_module_tmpl.gni +++ b/chrome/android/features/tab_ui/tab_ui_module_tmpl.gni
@@ -4,7 +4,7 @@ import("//build/config/android/rules.gni") import("//build/config/locales.gni") -import("//chrome/android/features/module_names_to_package_ids.gni") +import("//chrome/android/features/dynamic_feature_modules.gni") template("tab_ui_module_tmpl") { assert(defined(invoker.version_code))
diff --git a/chrome/android/features/vr/vr_module_tmpl.gni b/chrome/android/features/vr/vr_module_tmpl.gni index bea275c8..6f55d90b1 100644 --- a/chrome/android/features/vr/vr_module_tmpl.gni +++ b/chrome/android/features/vr/vr_module_tmpl.gni
@@ -5,7 +5,7 @@ import("//base/android/linker/config.gni") import("//build/config/android/rules.gni") import("//build/config/locales.gni") -import("//chrome/android/features/module_names_to_package_ids.gni") +import("//chrome/android/features/dynamic_feature_modules.gni") import("//device/vr/buildflags/buildflags.gni") assert(enable_vr) @@ -45,9 +45,49 @@ "//chrome/browser/android/vr:vr_ui_dummy_lib", ] - # TODO(crbug.com/943210): Remove this condition once downstream passes in - # native_switches. - if (defined(invoker.native_switches)) { + if (defined(invoker.is_monochrome_or_trichrome)) { + not_needed(invoker, [ "is_monochrome_or_trichrome" ]) + } + if (use_native_modules && modularize_vr_native) { + # Include the VR native library. In relation to http://crbug.com/950056, + # this logic could be moved into a location common to all feature modules. + # This could be android_app_bundle_module(), or a Chrome-specific + # extension of it. In that case, this scope would potentially pass "vr" + # as a required native library, and the lower-level template would derive + # and include the correct library. + _is_monochrome_or_trichrome = + defined(invoker.is_monochrome_or_trichrome) && + invoker.is_monochrome_or_trichrome + _arch = "" + _toolchain = "" + _root_out_dir = root_out_dir + if (android_64bit_target_cpu) { + if (defined(invoker.is_64_bit_browser) && invoker.is_64_bit_browser) { + _arch = "_64" + } else { + _toolchain = "($android_secondary_abi_toolchain)" + _root_out_dir = + get_label_info(":foo($android_secondary_abi_toolchain)", + "root_out_dir") + } + } + if (_is_monochrome_or_trichrome) { + _base_target_name = "monochrome${_arch}_base" + } else { + _base_target_name = "libchrome${_arch}_base" + } + _module = "vr" + deps += + [ "//chrome/android:${_base_target_name}_${_module}${_toolchain}" ] + _module_file = + "${_root_out_dir}/${_base_target_name}_partitions/lib${_module}.so" + + # Pass the correct library as both the 32 and 64-bit options. Underlying + # logic will choose from the correct variable, and supply a dummy library + # for the other architecture if required. + loadable_modules_if_32_bit = [ _module_file ] + loadable_modules_if_64_bit = [ _module_file ] + } else { if (android_64bit_target_cpu) { _32_bit_toolchain_root_dir = get_label_info(":foo($android_secondary_abi_toolchain)",
diff --git a/chrome/android/java/res/layout/fre_data_reduction_proxy.xml b/chrome/android/java/res/layout/fre_data_reduction_proxy.xml deleted file mode 100644 index 7629239..0000000 --- a/chrome/android/java/res/layout/fre_data_reduction_proxy.xml +++ /dev/null
@@ -1,93 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright 2015 The Chromium Authors. All rights reserved. - - Use of this source code is governed by a BSD-style license that can be - found in the LICENSE file. ---> -<org.chromium.chrome.browser.firstrun.FirstRunView - xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:app="http://schemas.android.com/apk/res-auto" - xmlns:tools="http://schemas.android.com/tools" - android:layout_width="match_parent" - android:layout_height="match_parent"> - - <ScrollView - android:layout_width="match_parent" - android:layout_height="match_parent" - android:layout_marginBottom="@dimen/fre_button_bar_height" - android:fillViewport="true"> - - <LinearLayout - android:id="@+id/fre_main_layout" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:orientation="vertical" - android:gravity="center_horizontal"> - - <TextView - android:id="@+id/title" - android:text="@string/data_reduction_promo_title" - style="@style/FreTitle"/> - - <!-- The orientation of this view is changed dynamically to give a nicer layout when in - landscape mode on devices with small screens. --> - <LinearLayout - android:id="@+id/fre_image_and_content" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:orientation="vertical" - android:gravity="center_horizontal" - android:layout_marginTop="@dimen/fre_vertical_spacing"> - - <ImageView - android:id="@+id/image" - android:layout_width="wrap_content" - android:layout_height="@dimen/fre_image_height" - tools:ignore="ContentDescription" - app:srcCompat="@drawable/data_reduction_illustration" /> - - <LinearLayout - android:id="@+id/fre_content_wrapper" - android:layout_width="0dp" - android:layout_height="0dp" - android:layout_weight="1" - android:layout_marginTop="@dimen/fre_vertical_spacing" - android:layout_marginEnd="@dimen/fre_content_margin" - android:layout_marginStart="@dimen/fre_content_margin" - android:orientation="vertical" > - - <TextView - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_marginBottom="@dimen/fre_vertical_spacing" - android:gravity="start" - android:lineSpacingMultiplier="1.4" - android:text="@string/data_reduction_promo_summary" - android:textAppearance="@style/TextAppearance.BlackBodyDefault" /> - - <android.support.v7.widget.SwitchCompat - android:id="@+id/enable_data_saver_switch" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:lineSpacingMultiplier="1.4" - android:showText="false" - android:text="@string/data_reduction_enabled_switch" - style="@style/TextAppearance.BlackTitle2" /> - - </LinearLayout> - </LinearLayout> - </LinearLayout> - </ScrollView> - - <!-- fre_button_bar_height = 52dp = layout_height + layout_marginBottom --> - <org.chromium.ui.widget.ButtonCompat - android:id="@+id/next_button" - android:layout_width="wrap_content" - android:layout_height="36dp" - android:layout_marginBottom="16dp" - android:layout_gravity="bottom|center_horizontal" - android:paddingStart="@dimen/fre_button_padding" - android:paddingEnd="@dimen/fre_button_padding" - android:text="@string/next" - style="@style/FilledButton.Flat" /> -</org.chromium.chrome.browser.firstrun.FirstRunView>
diff --git a/chrome/android/java/res/layout/translate_menu_item_checked.xml b/chrome/android/java/res/layout/translate_menu_item_checked.xml index 93d6b47..c37e037 100644 --- a/chrome/android/java/res/layout/translate_menu_item_checked.xml +++ b/chrome/android/java/res/layout/translate_menu_item_checked.xml
@@ -41,7 +41,7 @@ android:id="@+id/menu_item_divider" android:layout_width="match_parent" android:layout_height="1dp" - android:background="@color/translate_overflow_menu_divider_color" + android:background="@color/divider_bg_color" android:visibility="gone" /> </LinearLayout>
diff --git a/chrome/android/java/res/values/colors.xml b/chrome/android/java/res/values/colors.xml index 8c2ff85..bee945a 100644 --- a/chrome/android/java/res/values/colors.xml +++ b/chrome/android/java/res/values/colors.xml
@@ -181,9 +181,6 @@ <color name="payments_section_edit_background">@color/modern_secondary_color</color> <color name="payments_section_chevron">#B2B2B2</color> - <!-- Translate Infobar colors --> - <color name="translate_overflow_menu_divider_color">@color/modern_grey_300</color> - <!-- Other colors --> <color name="media_viewer_bg">#000000</color> <color name="image_viewer_bg">#0E0E0E</color>
diff --git a/chrome/android/java/res/xml/data_reduction_preferences_off.xml b/chrome/android/java/res/xml/data_reduction_preferences_off.xml deleted file mode 100644 index 1c8bcb4..0000000 --- a/chrome/android/java/res/xml/data_reduction_preferences_off.xml +++ /dev/null
@@ -1,16 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright 2015 The Chromium Authors. All rights reserved. - Use of this source code is governed by a BSD-style license that can be - found in the LICENSE file. --> - -<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:app="http://schemas.android.com/apk/res-auto" > - - <org.chromium.chrome.browser.preferences.TextMessagePreference - android:title="@string/data_reduction_benefits_description" /> - <org.chromium.chrome.browser.preferences.TextMessagePreference - android:title="@string/data_reduction_description" /> - <org.chromium.chrome.browser.preferences.LearnMorePreference - android:key="data_reduction_learn_more" - app:helpContext="@string/help_context_data_reduction" /> -</PreferenceScreen>
diff --git a/chrome/android/java/res/xml/main_preferences.xml b/chrome/android/java/res/xml/main_preferences.xml index cd253fa..8be6e7d 100644 --- a/chrome/android/java/res/xml/main_preferences.xml +++ b/chrome/android/java/res/xml/main_preferences.xml
@@ -90,11 +90,11 @@ android:key="languages" android:order="16" android:title="@string/prefs_languages"/> - <org.chromium.chrome.browser.preferences.datareduction.DataReductionPreference + <org.chromium.chrome.browser.preferences.ChromeBasePreference android:fragment="org.chromium.chrome.browser.preferences.datareduction.DataReductionPreferenceFragment" android:key="data_reduction" android:order="17" - android:title="@string/data_reduction_title"/> + android:title="@string/data_reduction_title_lite_mode"/> <org.chromium.chrome.browser.preferences.ChromeBasePreference android:fragment="org.chromium.chrome.browser.preferences.download.DownloadPreferences" android:key="downloads"
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java index 944d3ca9..02cdbf9 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java
@@ -213,7 +213,6 @@ public static final String CONTEXTUAL_SEARCH_UNITY_INTEGRATION = "ContextualSearchUnityIntegration"; public static final String CUSTOM_CONTEXT_MENU = "CustomContextMenu"; - public static final String DATA_SAVER_LITE_MODE_REBRANDING = "DataSaverLiteModeRebranding"; public static final String DELEGATE_OVERSCROLL_SWIPES = "DelegateOverscrollSwipes"; public static final String DOWNLOAD_LOCATION_SHOW_IMAGE_IN_GALLERY = "DownloadLocationShowImageInGallery"; @@ -287,6 +286,8 @@ public static final String PERMISSION_DELEGATION = "PermissionDelegation"; public static final String PER_METHOD_CAN_MAKE_PAYMENT_QUOTA = "WebPaymentsPerMethodCanMakePaymentQuota"; + public static final String WEB_PAYMENTS_REDACT_SHIPPING_ADDRESS = + "WebPaymentsRedactShippingAddress"; public static final String PREDICTIVE_PREFETCHING_ALLOWED_ON_ALL_CONNECTION_TYPES = "PredictivePrefetchingAllowedOnAllConnectionTypes"; public static final String PRIORITIZE_BOOTSTRAP_TASKS = "PrioritizeBootstrapTasks"; @@ -327,6 +328,8 @@ public static final String USER_ACTIVATION_V2 = "UserActivationV2"; public static final String WEB_AUTH = "WebAuthentication"; public static final String WEB_PAYMENTS = "WebPayments"; + public static final String WEB_PAYMENTS_EXPERIMENTAL_FEATURES = + "WebPaymentsExperimentalFeatures"; public static final String WEB_PAYMENTS_METHOD_SECTION_ORDER_V2 = "WebPaymentsMethodSectionOrderV2"; public static final String WEB_PAYMENTS_MODIFIERS = "WebPaymentsModifiers";
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java index 91e5457..b4fdba6 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
@@ -615,21 +615,29 @@ private void closeIfNoTabsAndHomepageEnabled(boolean isPendingClosure) { if (getTabModelSelector().getTotalTabCount() == 0) { - // If the last tab is closed, and one of the following is true, then exit - // Chrome: - // 1. If homepage is enabled. - // 2. If TabGroupsAndroid is enabled, and isPendingClosure is true. - // isPendingClosure is used to avoid calling finish() when closing all - // tabs in tab switcher. - if (HomepageManager.shouldCloseAppWithZeroTabs() - || (FeatureUtilities.isTabGroupsAndroidEnabled() - && isPendingClosure)) { + // If the last tab is closed, and homepage is enabled, then exit Chrome. + if (HomepageManager.shouldCloseAppWithZeroTabs()) { finish(); } else if (isPendingClosure) { NewTabPageUma.recordNTPImpression( NewTabPageUma.NTP_IMPESSION_POTENTIAL_NOTAB); } } + + // TODO(960196) : remove this when the associated bug fix. This is a band-aid + // fix for Tabgroups and closing tabs with TabGroupUi. + // If one of the following is true, then exit Chrome when TabGroupsAndroid is + // enabled, and tab switcher is not shown: + // 1. If the very last tab is closed. + // 2. If normal tab model is selected and no normal tabs. + if (FeatureUtilities.isTabGroupsAndroidEnabled() + && !mOverviewModeController.overviewVisible()) { + if (getTabModelSelector().getTotalTabCount() == 0 + || (!getTabModelSelector().isIncognitoSelected() + && getTabModelSelector().getModel(false).getCount() == 0)) { + finish(); + } + } } @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/ephemeraltab/EphemeralTabPanel.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/ephemeraltab/EphemeralTabPanel.java index 2999241..005136cd 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/ephemeraltab/EphemeralTabPanel.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/ephemeraltab/EphemeralTabPanel.java
@@ -11,6 +11,7 @@ import org.chromium.base.SysUtils; import org.chromium.base.TimeUtils; import org.chromium.base.metrics.RecordHistogram; +import org.chromium.chrome.R; import org.chromium.chrome.browser.ChromeFeatureList; import org.chromium.chrome.browser.compositor.LayerTitleCache; import org.chromium.chrome.browser.compositor.bottombar.OverlayContentDelegate; @@ -83,7 +84,9 @@ Context context, LayoutUpdateHost updateHost, OverlayPanelManager panelManager) { super(context, updateHost, panelManager); mSceneLayer = - new EphemeralTabSceneLayer(mContext.getResources().getDisplayMetrics().density); + new EphemeralTabSceneLayer(mContext.getResources().getDisplayMetrics().density, + mContext.getResources().getDimensionPixelSize( + R.dimen.compositor_tab_title_favicon_size)); mEventFilter = new OverlayPanelEventFilter(mContext, this) { @Override public boolean onInterceptTouchEventInternal(MotionEvent e, boolean isKeyboardShowing) { @@ -232,6 +235,13 @@ return !mActivity.isCustomTab(); } + /** + * @return URL of the page to open in the panel. + */ + public String getUrl() { + return mUrl; + } + // Panel base methods @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/scene_layer/ContextualSearchSceneLayer.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/scene_layer/ContextualSearchSceneLayer.java index 91f6fcd..f0a19fb3 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/scene_layer/ContextualSearchSceneLayer.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/scene_layer/ContextualSearchSceneLayer.java
@@ -61,7 +61,8 @@ int searchContextViewId = searchBarControl.getSearchContextViewId(); int searchTermViewId = searchBarControl.getSearchTermViewId(); int searchCaptionViewId = searchBarControl.getCaptionViewId(); - int openNewTabIconId = panel.canPromoteToNewTab() ? R.drawable.open_in_new_tab : -1; + int openNewTabIconId = + panel.canPromoteToNewTab() ? R.drawable.open_in_new_tab : INVALID_RESOURCE_ID; int searchPromoViewId = promoControl.getViewId(); boolean searchPromoVisible = promoControl.isVisible();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/scene_layer/EphemeralTabSceneLayer.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/scene_layer/EphemeralTabSceneLayer.java index 2806fcf..f896582 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/scene_layer/EphemeralTabSceneLayer.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/scene_layer/EphemeralTabSceneLayer.java
@@ -4,11 +4,14 @@ package org.chromium.chrome.browser.compositor.scene_layer; +import android.text.TextUtils; + import org.chromium.base.annotations.JNINamespace; import org.chromium.chrome.R; import org.chromium.chrome.browser.compositor.bottombar.ephemeraltab.EphemeralTabBarControl; import org.chromium.chrome.browser.compositor.bottombar.ephemeraltab.EphemeralTabPanel; import org.chromium.chrome.browser.compositor.bottombar.ephemeraltab.EphemeralTabTitleControl; +import org.chromium.chrome.browser.profiles.Profile; import org.chromium.content_public.browser.WebContents; import org.chromium.ui.resources.ResourceManager; @@ -26,11 +29,17 @@ /** The conversion multiple from dp to px. */ private final float mDpToPx; + private final int mFaviconSizePx; + + private String mCachedUrl; + /** * @param dpToPx The conversion multiple from dp to px for the device. + * @param faviconSizeDp Preferred size of the favicon to fetch. */ - public EphemeralTabSceneLayer(float dpToPx) { + public EphemeralTabSceneLayer(float dpToPx, int faviconSizeDp) { mDpToPx = dpToPx; + mFaviconSizePx = (int) (faviconSizeDp * dpToPx); } /** @@ -46,12 +55,10 @@ if (resourceManager == null || !panel.isShowing()) return; if (!mIsInitialized) { nativeCreateEphemeralTabLayer(mNativePtr, resourceManager); - - // TODO(jinsukkim): Find the right icon/background resource for the tab bar. nativeSetResourceIds(mNativePtr, title.getViewId(), R.drawable.contextual_search_bar_background, R.drawable.modern_toolbar_shadow, R.drawable.infobar_chrome, R.drawable.drag_handlebar, - panel.canPromoteToNewTab() ? R.drawable.open_in_new_tab : -1, + panel.canPromoteToNewTab() ? R.drawable.open_in_new_tab : INVALID_RESOURCE_ID, R.drawable.btn_close); mIsInitialized = true; } @@ -74,6 +81,12 @@ panel.getBarShadowVisible(), panel.getBarShadowOpacity(), panel.getIconColor(), panel.getDragHandlebarColor(), isProgressBarVisible, progressBarHeight * mDpToPx, progressBarOpacity, progressBarCompletion); + + String url = panel.getUrl(); + if (!TextUtils.equals(mCachedUrl, url)) { + nativeGetFavicon(mNativePtr, Profile.getLastUsedProfile(), url, mFaviconSizePx); + mCachedUrl = url; + } } @Override @@ -87,6 +100,7 @@ public void hideTree() { if (!mIsInitialized) return; nativeHideTree(mNativePtr); + mCachedUrl = null; } @Override @@ -117,6 +131,8 @@ int barTextResourceId, int barBackgroundResourceId, int barShadowResourceId, int panelIconResourceId, int dragHandlebarResourceId, int openTabIconResourceId, int closeIconResourceId); + private native void nativeGetFavicon( + long nativeEphemeralTabSceneLayer, Profile profile, String url, int size); private native void nativeUpdate(long nativeEphemeralTabSceneLayer, int titleViewId, float textLayerMinHeight, int progressBarBackgroundResourceId, int progressBarResourceId, float dpToPx, float basePageBrightness,
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/scene_layer/SceneOverlayLayer.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/scene_layer/SceneOverlayLayer.java index 9cf31cd..57c79a9 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/scene_layer/SceneOverlayLayer.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/scene_layer/SceneOverlayLayer.java
@@ -8,10 +8,12 @@ * An extension of SceneLayer for SceneOverlay. */ public abstract class SceneOverlayLayer extends SceneLayer { + protected static final int INVALID_RESOURCE_ID = -1; + /** * Sets a content tree inside this scene overlay tree. * TODO(jaekyun): We need to rename this method later because the meaning of "content" isn't * clear. */ public abstract void setContentTree(SceneLayer contentTree); -} \ No newline at end of file +}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/datareduction/DataReductionBrandingResourceProvider.java b/chrome/android/java/src/org/chromium/chrome/browser/datareduction/DataReductionBrandingResourceProvider.java deleted file mode 100644 index 66c85a0..0000000 --- a/chrome/android/java/src/org/chromium/chrome/browser/datareduction/DataReductionBrandingResourceProvider.java +++ /dev/null
@@ -1,113 +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. - -package org.chromium.chrome.browser.datareduction; - -import android.support.annotation.LayoutRes; -import android.support.annotation.StringRes; -import android.support.annotation.XmlRes; - -import org.chromium.chrome.R; -import org.chromium.chrome.browser.ChromeFeatureList; - -/** - * This class provides Android resource IDs for the Data Saver/Lite Mode feature. This feature is - * being rebranded, but the rebrand is controlled by a feature flag. - * - * TODO(crbug.com/909915): Remove this class and callsites when fully rolled out. - */ -public final class DataReductionBrandingResourceProvider { - /** - * Given a DataSaver string resource, maybe return the string resource for Lite Mode rebranding - * if it is enabled. If not, the same string resource is returned. - * - * @param resource The string resource to check. - * @return The string resource to use with respect to the Lite Mode rebranding. - */ - public static @StringRes int getDataSaverBrandedString(@StringRes int resource) { - if (shouldUseLiteMode()) { - return mapToLiteModeString(resource); - } - return resource; - } - - /** - * Given a DataSaver first run layout resource, maybe return the first run layout - * resource for Lite Mode rebranding if it is enabled. If not, the same resource is returned. - * - * @param resource The layout resource to check. - * @return The resource to use with respect to the Lite Mode rebranding. - */ - public static @LayoutRes int getFirstRunLayout(@LayoutRes int resource) { - if (shouldUseLiteMode()) { - return mapToLiteModeLayout(resource); - } - return resource; - } - - /** - * Given a DataSaver preferences XML resource, maybe return the preferences XML - * resource for Lite Mode rebranding if it is enabled. If not, the same resource is returned - * - * @param resource The XML resource to check. - * @return The resource to use with respect to the Lite Mode rebranding. - */ - public static @XmlRes int getPreferencesOffXml(@XmlRes int resource) { - if (shouldUseLiteMode()) { - return mapToLiteModeXml(resource); - } - return resource; - } - - private static boolean shouldUseLiteMode() { - return ChromeFeatureList.isEnabled(ChromeFeatureList.DATA_SAVER_LITE_MODE_REBRANDING); - } - - private static @StringRes int mapToLiteModeString(@StringRes int resource) { - // Enumerates all strings used by Data Saver or Lite Mode. Not all strings are changed in - // the Lite Mode rebrand, so some strings are returned as is. - if (resource == R.string.data_reduction_title) { - return R.string.data_reduction_title_lite_mode; - } - if (resource == R.string.data_reduction_usage_reset_statistics_confirmation_title) { - return R.string.data_reduction_usage_reset_statistics_confirmation_title_lite_mode; - } - if (resource == R.string.data_reduction_usage_reset_statistics_confirmation_dialog) { - return R.string.data_reduction_usage_reset_statistics_confirmation_dialog_lite_mode; - } - if (resource == R.string.data_reduction_promo_title) { - return R.string.data_reduction_promo_title_lite_mode; - } - if (resource == R.string.data_reduction_promo_summary) { - return R.string.data_reduction_promo_summary_lite_mode; - } - if (resource == R.string.data_reduction_enable_button) { - return R.string.data_reduction_enable_button_lite_mode; - } - if (resource == R.string.data_reduction_enabled_switch) { - return R.string.data_reduction_enabled_switch_lite_mode; - } - if (resource == R.string.data_reduction_disabled_switch) { - return R.string.data_reduction_disabled_switch_lite_mode; - } - if (resource == R.string.data_reduction_enabled_toast) { - return R.string.data_reduction_enabled_toast_lite_mode; - } - return resource; - } - - private static @LayoutRes int mapToLiteModeLayout(@LayoutRes int resource) { - if (resource == R.layout.fre_data_reduction_proxy) { - return R.layout.fre_data_reduction_proxy_lite_mode; - } - return resource; - } - - private static @XmlRes int mapToLiteModeXml(@XmlRes int resource) { - if (resource == R.xml.data_reduction_preferences_off) { - return R.xml.data_reduction_preferences_off_lite_mode; - } - return resource; - } -}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/datareduction/DataReductionMainMenuItem.java b/chrome/android/java/src/org/chromium/chrome/browser/datareduction/DataReductionMainMenuItem.java index 5267ebaf..7ef84cf2 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/datareduction/DataReductionMainMenuItem.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/datareduction/DataReductionMainMenuItem.java
@@ -43,9 +43,7 @@ TextView itemText = (TextView) findViewById(R.id.menu_item_text); TextView itemSummary = (TextView) findViewById(R.id.menu_item_summary); ImageView icon = (ImageView) findViewById(R.id.icon); - icon.setContentDescription(getContext().getString( - DataReductionBrandingResourceProvider.getDataSaverBrandedString( - R.string.data_reduction_title))); + icon.setContentDescription(getContext().getString(R.string.data_reduction_title_lite_mode)); if (DataReductionProxySettings.getInstance().isDataReductionProxyEnabled()) { DataReductionProxyUma.dataReductionProxyUIAction( @@ -74,8 +72,7 @@ DataReductionProxyUma.dataReductionProxyUIAction( DataReductionProxyUma.ACTION_MAIN_MENU_DISPLAYED_OFF); - itemText.setText(DataReductionBrandingResourceProvider.getDataSaverBrandedString( - R.string.data_reduction_title)); + itemText.setText(R.string.data_reduction_title_lite_mode); itemSummary.setText(R.string.text_off); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/datareduction/DataReductionPromoScreen.java b/chrome/android/java/src/org/chromium/chrome/browser/datareduction/DataReductionPromoScreen.java index 5fc81d9..5e09764 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/datareduction/DataReductionPromoScreen.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/datareduction/DataReductionPromoScreen.java
@@ -65,15 +65,9 @@ protected DialogParams getDialogParams() { PromoDialog.DialogParams params = new PromoDialog.DialogParams(); params.vectorDrawableResource = R.drawable.data_reduction_illustration; - params.headerStringResource = - DataReductionBrandingResourceProvider.getDataSaverBrandedString( - R.string.data_reduction_promo_title); - params.subheaderStringResource = - DataReductionBrandingResourceProvider.getDataSaverBrandedString( - R.string.data_reduction_promo_summary); - params.primaryButtonStringResource = - DataReductionBrandingResourceProvider.getDataSaverBrandedString( - R.string.data_reduction_enable_button); + params.headerStringResource = R.string.data_reduction_promo_title_lite_mode; + params.subheaderStringResource = R.string.data_reduction_promo_summary_lite_mode; + params.primaryButtonStringResource = R.string.data_reduction_enable_button_lite_mode; params.secondaryButtonStringResource = R.string.no_thanks; return params; } @@ -101,9 +95,7 @@ DataReductionProxySettings.getInstance().setDataReductionProxyEnabled(getContext(), true); dismiss(); Toast.makeText(getContext(), - getContext().getString( - DataReductionBrandingResourceProvider.getDataSaverBrandedString( - R.string.data_reduction_enabled_toast)), + getContext().getString(R.string.data_reduction_enabled_toast_lite_mode), Toast.LENGTH_LONG) .show(); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/DataReductionProxyFirstRunFragment.java b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/DataReductionProxyFirstRunFragment.java index 29348e7..ea9e140df 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/DataReductionProxyFirstRunFragment.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/DataReductionProxyFirstRunFragment.java
@@ -14,7 +14,6 @@ import android.widget.Button; import org.chromium.chrome.R; -import org.chromium.chrome.browser.datareduction.DataReductionBrandingResourceProvider; import org.chromium.chrome.browser.datareduction.DataReductionPromoUtils; import org.chromium.chrome.browser.net.spdyproxy.DataReductionProxySettings; @@ -33,9 +32,7 @@ @Override public View onCreateView( LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - return inflater.inflate(DataReductionBrandingResourceProvider.getFirstRunLayout( - R.layout.fre_data_reduction_proxy), - container, false); + return inflater.inflate(R.layout.fre_data_reduction_proxy_lite_mode, container, false); } @Override @@ -52,13 +49,10 @@ DataReductionProxySettings.getInstance().setDataReductionProxyEnabled( v.getContext(), enableDataSaverSwitch.isChecked()); if (enableDataSaverSwitch.isChecked()) { - enableDataSaverSwitch.setText( - DataReductionBrandingResourceProvider.getDataSaverBrandedString( - R.string.data_reduction_enabled_switch)); + enableDataSaverSwitch.setText(R.string.data_reduction_enabled_switch_lite_mode); } else { enableDataSaverSwitch.setText( - DataReductionBrandingResourceProvider.getDataSaverBrandedString( - R.string.data_reduction_disabled_switch)); + R.string.data_reduction_disabled_switch_lite_mode); } } });
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/infobar/DataReductionPromoInfoBar.java b/chrome/android/java/src/org/chromium/chrome/browser/infobar/DataReductionPromoInfoBar.java index 3521f51..0ec878e 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/infobar/DataReductionPromoInfoBar.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/infobar/DataReductionPromoInfoBar.java
@@ -14,7 +14,6 @@ import org.chromium.base.ThreadUtils; import org.chromium.chrome.R; import org.chromium.chrome.browser.UrlConstants; -import org.chromium.chrome.browser.datareduction.DataReductionBrandingResourceProvider; import org.chromium.chrome.browser.datareduction.DataReductionPromoUtils; import org.chromium.chrome.browser.omaha.VersionNumberGetter; import org.chromium.chrome.browser.preferences.PrefServiceBridge; @@ -129,8 +128,7 @@ DataReductionPromoInfoBar.launch(webContents, R.drawable.infobar_chrome, context.getString(R.string.data_reduction_promo_infobar_title), context.getString(R.string.data_reduction_promo_infobar_text), - context.getString(DataReductionBrandingResourceProvider.getDataSaverBrandedString( - R.string.data_reduction_enable_button)), + context.getString(R.string.data_reduction_enable_button_lite_mode), context.getString(R.string.no_thanks)); return true;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/infobar/DataReductionPromoInfoBarDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/infobar/DataReductionPromoInfoBarDelegate.java index db45819..f8fe3de3 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/infobar/DataReductionPromoInfoBarDelegate.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/infobar/DataReductionPromoInfoBarDelegate.java
@@ -9,7 +9,6 @@ import org.chromium.base.ContextUtils; import org.chromium.base.annotations.CalledByNative; import org.chromium.chrome.R; -import org.chromium.chrome.browser.datareduction.DataReductionBrandingResourceProvider; import org.chromium.chrome.browser.datareduction.DataReductionProxyUma; import org.chromium.chrome.browser.net.spdyproxy.DataReductionProxySettings; import org.chromium.content_public.browser.WebContents; @@ -52,10 +51,7 @@ .dataReductionProxyUIAction(DataReductionProxyUma.ACTION_INFOBAR_ENABLED); DataReductionProxySettings.getInstance().setDataReductionProxyEnabled( context, true); - Toast.makeText(context, - context.getString( - DataReductionBrandingResourceProvider.getDataSaverBrandedString( - R.string.data_reduction_enabled_toast)), + Toast.makeText(context, context.getString(R.string.data_reduction_enabled_toast_lite_mode), Toast.LENGTH_LONG) .show(); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/infobar/InfoBar.java b/chrome/android/java/src/org/chromium/chrome/browser/infobar/InfoBar.java index a346fb1..2ddd5dfd 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/infobar/InfoBar.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/infobar/InfoBar.java
@@ -295,6 +295,13 @@ mContainer = container; } + /** + * @return Whether or not this InfoBar is already dismissed (i.e. closed). + */ + boolean isDismissed() { + return mIsDismissed; + } + @Override public boolean areControlsEnabled() { return mControlsEnabled;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/infobar/TranslateCompactInfoBar.java b/chrome/android/java/src/org/chromium/chrome/browser/infobar/TranslateCompactInfoBar.java index 97765f01..a4ba362 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/infobar/TranslateCompactInfoBar.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/infobar/TranslateCompactInfoBar.java
@@ -327,6 +327,8 @@ } private void closeInfobar(boolean explicitly) { + if (isDismissed()) return; + if (!mUserInteracted) { recordInfobarAction(INFOBAR_DECLINE); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentRequestImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentRequestImpl.java index a8055c8..98b45ff4 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentRequestImpl.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentRequestImpl.java
@@ -64,6 +64,7 @@ import org.chromium.payments.mojom.HasEnrolledInstrumentQueryResult; import org.chromium.payments.mojom.PayerDetail; import org.chromium.payments.mojom.PayerErrors; +import org.chromium.payments.mojom.PaymentAddress; import org.chromium.payments.mojom.PaymentComplete; import org.chromium.payments.mojom.PaymentCurrencyAmount; import org.chromium.payments.mojom.PaymentDetails; @@ -2108,8 +2109,19 @@ // Don't reuse the selected address because it is formatted for display. AutofillAddress shippingAddress = new AutofillAddress(chromeActivity, profile); + // Redact shipping address before exposing it in ShippingAddressChangeEvent. + // https://w3c.github.io/payment-request/#shipping-address-changed-algorithm + PaymentAddress redactedAddress = shippingAddress.toPaymentAddress(); + if (PaymentsExperimentalFeatures.isEnabled( + ChromeFeatureList.WEB_PAYMENTS_REDACT_SHIPPING_ADDRESS)) { + redactedAddress.organization = ""; + redactedAddress.phone = ""; + redactedAddress.recipient = ""; + redactedAddress.addressLine = new String[0]; + } + // This updates the line items and the shipping options asynchronously. - mClient.onShippingAddressChange(shippingAddress.toPaymentAddress()); + mClient.onShippingAddressChange(redactedAddress); } @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentsExperimentalFeatures.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentsExperimentalFeatures.java new file mode 100644 index 0000000..f311f5c8 --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentsExperimentalFeatures.java
@@ -0,0 +1,26 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.payments; + +import org.chromium.chrome.browser.ChromeFeatureList; + +/** + * Utility wrapper around |ChromeFeatureList| to enable kWebPaymentsExperimentalFeature to be used + * as an override to all payments features. + */ +public final class PaymentsExperimentalFeatures { + /** + * Returns whether the specified feature is enabled or not. + * + * This API differs from |ChromeFeatureList| in that it also returns true if the + * |kWebPaymentsExperimentalFeatures| feature is enabled. + */ + public static boolean isEnabled(String featureName) { + return ChromeFeatureList.isEnabled(ChromeFeatureList.WEB_PAYMENTS_EXPERIMENTAL_FEATURES) + || ChromeFeatureList.isEnabled(featureName); + } + + private PaymentsExperimentalFeatures() {} +}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/datareduction/DataReductionPreference.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/datareduction/DataReductionPreference.java deleted file mode 100644 index 6b7ab8a..0000000 --- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/datareduction/DataReductionPreference.java +++ /dev/null
@@ -1,27 +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. - -package org.chromium.chrome.browser.preferences.datareduction; - -import android.content.Context; -import android.util.AttributeSet; - -import org.chromium.chrome.R; -import org.chromium.chrome.browser.datareduction.DataReductionBrandingResourceProvider; -import org.chromium.chrome.browser.preferences.ChromeBasePreference; - -/** - * Custom preference to enable programmatically overriding the Preference's title string. - */ -public class DataReductionPreference extends ChromeBasePreference { - /** - * Constructor for inflating from XML. - */ - public DataReductionPreference(Context context, AttributeSet attrs) { - super(context, attrs); - - setTitle(DataReductionBrandingResourceProvider.getDataSaverBrandedString( - R.string.data_reduction_title)); - } -}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/datareduction/DataReductionPreferenceFragment.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/datareduction/DataReductionPreferenceFragment.java index 7969e23..608e649 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/datareduction/DataReductionPreferenceFragment.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/datareduction/DataReductionPreferenceFragment.java
@@ -16,7 +16,6 @@ import org.chromium.base.CommandLine; import org.chromium.chrome.R; -import org.chromium.chrome.browser.datareduction.DataReductionBrandingResourceProvider; import org.chromium.chrome.browser.datareduction.DataReductionPromoUtils; import org.chromium.chrome.browser.datareduction.DataReductionProxyUma; import org.chromium.chrome.browser.help.HelpAndFeedback; @@ -48,8 +47,7 @@ super.onCreate(savedInstanceState); PreferenceUtils.addPreferencesFromResource(this, R.xml.data_reduction_preferences); - getActivity().setTitle(DataReductionBrandingResourceProvider.getDataSaverBrandedString( - R.string.data_reduction_title)); + getActivity().setTitle(R.string.data_reduction_title_lite_mode); boolean isEnabled = DataReductionProxySettings.getInstance().isDataReductionProxyEnabled(); mIsEnabled = !isEnabled; mWasEnabledAtCreation = isEnabled; @@ -129,9 +127,8 @@ if (isEnabled) { PreferenceUtils.addPreferencesFromResource(this, R.xml.data_reduction_preferences); } else { - PreferenceUtils.addPreferencesFromResource(this, - DataReductionBrandingResourceProvider.getPreferencesOffXml( - R.xml.data_reduction_preferences_off)); + PreferenceUtils.addPreferencesFromResource( + this, R.xml.data_reduction_preferences_off_lite_mode); } mIsEnabled = isEnabled; } @@ -144,9 +141,7 @@ String percent = DataReductionProxySettings.getInstance().getContentLengthPercentSavings(); return resources.getString( - DataReductionBrandingResourceProvider.getDataSaverBrandedString( - R.string.data_reduction_menu_item_summary), - percent); + R.string.data_reduction_menu_item_summary_lite_mode, percent); } else { return (String) resources.getText(R.string.text_off); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/datareduction/DataReductionStatsPreference.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/datareduction/DataReductionStatsPreference.java index 696ffcb..eeb81b9b0 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/datareduction/DataReductionStatsPreference.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/datareduction/DataReductionStatsPreference.java
@@ -32,7 +32,6 @@ import org.chromium.base.Log; import org.chromium.base.VisibleForTesting; import org.chromium.chrome.R; -import org.chromium.chrome.browser.datareduction.DataReductionBrandingResourceProvider; import org.chromium.chrome.browser.datareduction.DataReductionProxyUma; import org.chromium.chrome.browser.net.spdyproxy.DataReductionProxySettings; import org.chromium.chrome.browser.util.ConversionUtils; @@ -377,11 +376,13 @@ } }; + final int title = + R.string.data_reduction_usage_reset_statistics_confirmation_title_lite_mode; + final int message = + R.string.data_reduction_usage_reset_statistics_confirmation_dialog_lite_mode; new AlertDialog.Builder(getContext(), R.style.Theme_Chromium_AlertDialog) - .setTitle(DataReductionBrandingResourceProvider.getDataSaverBrandedString( - R.string.data_reduction_usage_reset_statistics_confirmation_title)) - .setMessage(DataReductionBrandingResourceProvider.getDataSaverBrandedString( - R.string.data_reduction_usage_reset_statistics_confirmation_dialog)) + .setTitle(title) + .setMessage(message) .setPositiveButton( R.string.data_reduction_usage_reset_statistics_confirmation_button, dialogListener)
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsBinder.java b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsBinder.java index b4649e7b..2b11674a 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsBinder.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsBinder.java
@@ -111,19 +111,21 @@ mTextLayout.setMinimumHeight(showThumbnail ? mThumbnailSize : 0); - ViewGroup.MarginLayoutParams publisherBarParams = - (ViewGroup.MarginLayoutParams) mPublisherBar.getLayoutParams(); - if (showHeadline) { - // When we show a headline and not a description, we reduce the top margin of the - // publisher bar. - publisherBarParams.topMargin = mPublisherBar.getResources().getDimensionPixelSize( - R.dimen.snippets_publisher_margin_top); - } else { - // When there is no headline and no description, we remove the top margin of the - // publisher bar. - publisherBarParams.topMargin = 0; + if (mPublisherBar != null) { + ViewGroup.MarginLayoutParams publisherBarParams = + (ViewGroup.MarginLayoutParams) mPublisherBar.getLayoutParams(); + if (showHeadline) { + // When we show a headline and not a description, we reduce the top margin of the + // publisher bar. + publisherBarParams.topMargin = mPublisherBar.getResources().getDimensionPixelSize( + R.dimen.snippets_publisher_margin_top); + } else { + // When there is no headline and no description, we remove the top margin of the + // publisher bar. + publisherBarParams.topMargin = 0; + } + mPublisherBar.setLayoutParams(publisherBarParams); } - mPublisherBar.setLayoutParams(publisherBarParams); } public void updateOfflineBadgeVisibility(boolean visible) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/SplashController.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/SplashController.java index 407bdf6..2c4985d 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/SplashController.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/SplashController.java
@@ -7,8 +7,10 @@ import android.app.Activity; import android.os.SystemClock; import android.support.annotation.IntDef; +import android.support.annotation.Nullable; import android.view.View; import android.view.ViewGroup; +import android.view.ViewPropertyAnimator; import android.view.ViewTreeObserver; import org.chromium.base.ObserverList; @@ -17,6 +19,7 @@ import org.chromium.chrome.browser.WarmupManager; import org.chromium.chrome.browser.compositor.CompositorView; import org.chromium.chrome.browser.lifecycle.ActivityLifecycleDispatcher; +import org.chromium.chrome.browser.lifecycle.Destroyable; import org.chromium.chrome.browser.lifecycle.InflationObserver; import org.chromium.chrome.browser.tab.EmptyTabObserver; import org.chromium.chrome.browser.tab.Tab; @@ -26,7 +29,7 @@ import java.lang.annotation.RetentionPolicy; /** Shows and hides splash screen. */ -public class SplashController extends EmptyTabObserver implements InflationObserver { +public class SplashController extends EmptyTabObserver implements InflationObserver, Destroyable { private static class SingleShotOnDrawListener implements ViewTreeObserver.OnDrawListener { private final View mView; private final Runnable mAction; @@ -76,6 +79,9 @@ private View mSplashView; + @Nullable + private ViewPropertyAnimator mFadeOutAnimator; + private boolean mDidPreInflationStartup; /** Whether the splash hide animation was started. */ @@ -132,6 +138,13 @@ public void onPostInflationStartup() {} @Override + public void destroy() { + if (mFadeOutAnimator != null) { + mFadeOutAnimator.cancel(); + } + } + + @Override public void didFirstVisuallyNonEmptyPaint(Tab tab) { if (canHideSplashScreen()) { hideSplash(tab, SplashHidesReason.PAINT); @@ -198,9 +211,10 @@ hideSplashNow(tab, reason); return; } - mSplashView.animate().alpha(0f).setDuration(animationDurationMs).withEndAction(() -> { - hideSplashNow(tab, reason); - }); + mFadeOutAnimator = mSplashView.animate() + .alpha(0f) + .setDuration(animationDurationMs) + .withEndAction(() -> { hideSplashNow(tab, reason); }); } private void hideSplashNow(Tab tab, @SplashHidesReason int reason) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webshare/ShareServiceImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/webshare/ShareServiceImpl.java index f3b389e..0cdc27c 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/webshare/ShareServiceImpl.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/webshare/ShareServiceImpl.java
@@ -138,10 +138,6 @@ private static final TaskRunner TASK_RUNNER = PostTask.createSequencedTaskRunner(TaskTraits.USER_BLOCKING); - static { - TASK_RUNNER.disableLifetimeCheck(); - } - public ShareServiceImpl(@Nullable WebContents webContents) { mActivity = activityFromWebContents(webContents); }
diff --git a/chrome/android/java/strings/android_chrome_strings.grd b/chrome/android/java/strings/android_chrome_strings.grd index 1024fa9d..59fde07 100644 --- a/chrome/android/java/strings/android_chrome_strings.grd +++ b/chrome/android/java/strings/android_chrome_strings.grd
@@ -158,7 +158,7 @@ <message name="IDS_SAVE" desc="Label for a button to save a change. Used in multiple contexts. [CHAR-LIMIT=20]"> Save </message> - <message name="IDS_DETAILS_LINK" desc="In 1) Settings > Clean up computer (desktop), a link to open details of incompatible applications. In 2) Settings > Data Saver (mobile), static title for data usage breakdown." meaning="Short for 'view details'. Link; static title."> + <message name="IDS_DETAILS_LINK" desc="In 1) Settings > Clean up computer (desktop), a link to open details of incompatible applications. In 2) Settings > Lite mode (mobile), static title for data usage breakdown." meaning="Short for 'view details'. Link; static title."> Details </message> <message name="IDS_DONE" desc="Label for a button to save a change or finish editing data. Used in multiple contexts. [CHAR-LIMIT=20]"> @@ -1287,47 +1287,35 @@ Revoke all permissions for device </message> - <!-- Data Saver and Lite Mode--> + <!-- Lite Mode--> <message name="IDS_DATA_SAVER_IPH_REBRAND_LITE_MODE" desc="An onscreen notification to the user that the Chrome feature previously named 'Data Saver' is now named 'Lite mode'."> Data Saver is now Lite mode </message> - <message name="IDS_DATA_REDUCTION_TITLE" desc="Menu item for Data Saver, which allows users to save mobile data by compressing network traffic."> - Data Saver - </message> <message name="IDS_DATA_REDUCTION_TITLE_LITE_MODE" desc="Menu item for Lite mode, which allows users to save mobile data by compressing network traffic."> Lite mode </message> <message name="IDS_DATA_REDUCTION_INITIAL_TITLE" desc="This title states that the below chart will contain the user's data savings after they have started browsing."> Your data savings will appear here </message> - <message name="IDS_DATA_REDUCTION_SAVED_LABEL" desc="Summary text for the menu item that states the amount of mobile data that was saved by Data Saver (i.e. XX MB saved). Data Saver allows users to to reduce their mobile data usage by compressing network traffic."> + <message name="IDS_DATA_REDUCTION_SAVED_LABEL" desc="Summary text for the menu item that states the amount of mobile data that was saved by Lite mode (i.e. XX MB saved). Lite mode allows users to to reduce their mobile data usage by compressing network traffic."> <ph name="data">%1$s<ex>1.0 GB</ex></ph> saved </message> <message name="IDS_DATA_REDUCTION_DATE_LABEL" desc="Summary text for the menu item that states the beginning date when the displayed mobile data was saved (i.e. XX MB saved 'since Feb 28')"> since <ph name="date">%1$s<ex>Feb 28</ex></ph> </message> - <message name="IDS_DATA_REDUCTION_BENEFITS_DESCRIPTION" desc="Description text about the benefits of the Data Saver feature. Seen only before the user has enabled the feature."> - Use up to 60 percent less data and speed up the web. - </message> - <message name="IDS_DATA_REDUCTION_BENEFITS_DESCRIPTION_LITE_MODE" desc="Description text about the benefits of the Data Saver feature. Seen only before the user has enabled the feature."> + <message name="IDS_DATA_REDUCTION_BENEFITS_DESCRIPTION_LITE_MODE" desc="Description text about the benefits of the Lite mode feature. Seen only before the user has enabled the feature."> In Lite mode, Chrome loads pages faster and uses up to 60 percent less data. </message> - <message name="IDS_DATA_REDUCTION_DESCRIPTION" desc="Text descripting how the Data Saver feature works. Seen only before the user has enabled the feature."> - When Data Saver is turned on, Chrome uses Google servers to speed up and compress page loads. On especially slow pages, Data Saver rewrites the page to load only the essential content. Data Saver does not optimize pages loaded in Incognito mode. - </message> <message name="IDS_DATA_REDUCTION_DESCRIPTION_LITE_MODE" desc="Text describing how the Lite mode feature works. Seen only before the user has enabled the feature."> When Lite mode is on, Chrome uses Google servers to make pages load faster. Lite mode rewrites very slow pages to load only essential content. Lite mode does not apply to Incognito tabs. </message> - <message name="IDS_DATA_REDUCTION_MENU_ITEM_SUMMARY" desc="Summary text for data reduction menu item."> - <ph name="PERCENT">%1$s<ex>49%</ex></ph> data savings - </message> <message name="IDS_DATA_REDUCTION_MENU_ITEM_SUMMARY_LITE_MODE" desc="Label that states the percent of mobile data that was saved by Lite mode. Lite mode allows users to to reduce their mobile data usage by compressing network traffic."> <ph name="PERCENT">%1$s<ex>49%</ex></ph> data savings </message> - <message name="IDS_DATA_REDUCTION_SAVINGS_LABEL" desc="Data Reduction statistics label that states the amount of mobile data that was saved by Data Saver. Data Saver allows users to to reduce their mobile data usage by compressing network traffic."> + <message name="IDS_DATA_REDUCTION_SAVINGS_LABEL" desc="Data Reduction statistics label that states the amount of mobile data that was saved by Lite mode. Lite mode allows users to to reduce their mobile data usage by compressing network traffic."> data saved </message> - <message name="IDS_DATA_REDUCTION_USAGE_LABEL" desc="Data Reduction statistics label that states the amount of data that was used by Chrome when Data Saver is enabled."> + <message name="IDS_DATA_REDUCTION_USAGE_LABEL" desc="Data Reduction statistics label that states the amount of data that was used by Chrome when Lite mode is enabled."> data used </message> <message name="IDS_DATA_REDUCTION_START_DATE_CONTENT_DESCRIPTION" desc="This label is used in the device screen reader to describe the starting date that data savings are computed from. This will always be used in the form 'Start date: February 28'."> @@ -1354,10 +1342,10 @@ <message name="IDS_DATA_REDUCTION_BREAKDOWN_DATA_USED_SORTED" desc="This title states that the following table contains the details of how much data was saved for each site and that the table rows are sorted by the how much data was used for each site. This is used in the device's screen reader and is not displayed visually to the user."> Details: Sorted by amount of data used </message> - <message name="IDS_DATA_REDUCTION_BREAKDOWN_SAVED_TITLE" desc="Title for the data saved column on the Data Reduction statistics page. The breakdown lists for the top ten sites with the greatest amount of data usage or mobile data that was saved. Data Saver allows users to to reduce their mobile data usage by compressing network traffic."> + <message name="IDS_DATA_REDUCTION_BREAKDOWN_SAVED_TITLE" desc="Title for the data saved column on the Data Reduction statistics page. The breakdown lists for the top ten sites with the greatest amount of data usage or mobile data that was saved. Lite mode allows users to to reduce their mobile data usage by compressing network traffic."> Saved </message> - <message name="IDS_DATA_REDUCTION_BREAKDOWN_SAVED_HEADER_CONTENT_DESCRIPTION" desc="This label is used to state that by clicking the associated button, the displayed table will be sorted descending by the amount of mobile data that was saved when viewing a webpage by using Chrome's Data Saver feature. This is used in the device's screen reader and is not displayed visually to the user."> + <message name="IDS_DATA_REDUCTION_BREAKDOWN_SAVED_HEADER_CONTENT_DESCRIPTION" desc="This label is used to state that by clicking the associated button, the displayed table will be sorted descending by the amount of mobile data that was saved when viewing a webpage by using Chrome's Lite mode feature. This is used in the device's screen reader and is not displayed visually to the user."> Sort by amount of data saved </message> <message name="IDS_DATA_REDUCTION_BREAKDOWN_DATA_SAVED_SORTED" desc="This title states that the following table contains the details of how much data was saved for each site and that the table rows are sorted by how much data was saved for each site. This is used in the device's screen reader and is not displayed visually to the user."> @@ -1366,7 +1354,7 @@ <message name="IDS_DATA_REDUCTION_BREAKDOWN_USED_CONTENT_DESCRIPTION" desc="This label is used as a suffix to describe the amount of mobile data that was used to view a webpage. It is used in the form '0 bytes used'."> <ph name="amount">%1$s<ex>0 bytes</ex></ph> used </message> - <message name="IDS_DATA_REDUCTION_BREAKDOWN_SAVED_CONTENT_DESCRIPTION" desc="This label is used as a suffix to describe the amount of mobile data that was saved when viewing a webpage by using Chrome's Data Saver feature. It is used in the form '0 bytes used'."> + <message name="IDS_DATA_REDUCTION_BREAKDOWN_SAVED_CONTENT_DESCRIPTION" desc="This label is used as a suffix to describe the amount of mobile data that was saved when viewing a webpage by using Chrome's Lite mode feature. It is used in the form '0 bytes used'."> <ph name="amount">%1$s<ex>0 bytes</ex></ph> saved </message> <message name="IDS_DATA_REDUCTION_BREAKDOWN_REMAINING_SITES_LABEL" desc="Title for the the remaining sites on the Data Reduction statistics page. The breakdown lists the top ten sites with the greatest amount of data usage or mobile data that was saved and then groups the remaining sites together."> @@ -1378,15 +1366,9 @@ <message name="IDS_DATA_REDUCTION_USAGE_RESET_STATISTICS_BUTTON" desc="Text to be displayed on the button to reset the Data Reduction statistics."> Reset statistics </message> - <message name="IDS_DATA_REDUCTION_USAGE_RESET_STATISTICS_CONFIRMATION_TITLE" desc="Text to be displayed on the confirmation dialog to reset the Data Reduction statistics."> - Reset Data Saver? - </message> <message name="IDS_DATA_REDUCTION_USAGE_RESET_STATISTICS_CONFIRMATION_TITLE_LITE_MODE" desc="Text to be displayed on the confirmation dialog to reset the user's history of data savings."> Reset Lite mode? </message> - <message name="IDS_DATA_REDUCTION_USAGE_RESET_STATISTICS_CONFIRMATION_DIALOG" desc="Text to be displayed on the confirmation dialog to reset the Data Reduction statistics."> - Resetting erases Data Saver history, including the list of visited sites. - </message> <message name="IDS_DATA_REDUCTION_USAGE_RESET_STATISTICS_CONFIRMATION_DIALOG_LITE_MODE" desc="Text to be displayed on the confirmation dialog to reset the user's history of data savings."> Resetting erases your history of data savings, including the list of visited sites. </message> @@ -1394,40 +1376,22 @@ Reset </message> - <!-- Data Saver or Lite Mode Promo and FRE card --> - <message name="IDS_DATA_REDUCTION_PROMO_TITLE" desc="The title for the promo inviting users to enable Data Saver" > - Save data and browse faster - </message> + <!-- Lite Mode Promo and FRE card --> <message name="IDS_DATA_REDUCTION_PROMO_TITLE_LITE_MODE" desc="The title for the promo inviting users to enable Lite mode" > Browse faster. Use less data. </message> - <message name="IDS_DATA_REDUCTION_PROMO_SUMMARY" desc="Description for the promo inviting users to enable Data Saver" > - Use up to 60 percent less data and speed up the web. Google servers will optimize the pages you visit. - </message> <message name="IDS_DATA_REDUCTION_PROMO_SUMMARY_LITE_MODE" desc="Description for the promo inviting users to enable Lite mode. This informs users that their web traffic will be seen and optimized for speed and data usage, by Google servers (AKA 'Cloud technology')." meaning="The translation of percent should be spelled out instead of using the percent symbol."> In Lite mode, Chrome loads pages faster and uses up to 60 percent less data. Google's Cloud technology optimizes the pages you visit. </message> - <message name="IDS_DATA_REDUCTION_ENABLE_BUTTON" desc="Button the user presses if they want to enable Data Saver" > - Turn on Data Saver - </message> <message name="IDS_DATA_REDUCTION_ENABLE_BUTTON_LITE_MODE" desc="Button the user presses if they want to enable Lite mode" > Turn on Lite mode </message> - <message name="IDS_DATA_REDUCTION_ENABLED_SWITCH" desc="Message to show when the Data Saver feature is enabled via the switch on the First Run Experience card" > - Data Saver is on - </message> <message name="IDS_DATA_REDUCTION_ENABLED_SWITCH_LITE_MODE" desc="Message to show when the Lite mode feature is enabled via the switch on the First Run Experience card" > Lite mode is on </message> - <message name="IDS_DATA_REDUCTION_DISABLED_SWITCH" desc="Message to show when the Data Saver feature is disabled via the switch on the First Run Experience card" > - Data Saver is off - </message> <message name="IDS_DATA_REDUCTION_DISABLED_SWITCH_LITE_MODE" desc="Message to show when the Lite mode feature is disabled via the switch on the First Run Experience card" > Lite mode is off </message> - <message name="IDS_DATA_REDUCTION_ENABLED_TOAST" desc="Toast message displayed after the user enables Data Saver from the promo" > - Data Saver is on. Manage it in Settings. - </message> <message name="IDS_DATA_REDUCTION_ENABLED_TOAST_LITE_MODE" desc="Toast message displayed after the user enables Lite mode from the promo" > Lite mode is on. Manage it in Settings. </message> @@ -2193,7 +2157,7 @@ <message name="IDS_CONTEXTMENU_OPEN_IMAGE_IN_EPHEMERAL_TAB" desc="Context-sensitive menu item to open a quick preview of the selected image. Note that 'preview' is a verb, not a noun. We're also labeling it *New* to draw attention to it when first released. The selected image link will open in an overlay panel on top of the current tab which will go away easily too. [CHAR-LIMIT=30]"> Preview image <ph name="BEGIN_NEW"><new></ph>New<ph name="END_NEW"></new></ph> </message> - <message name="IDS_CONTEXTMENU_LOAD_ORIGINAL_IMAGE" desc="Context sensitive menu item for Data Saver low fidelity placeholder images that loads the original version in place. [CHAR-LIMIT=30]"> + <message name="IDS_CONTEXTMENU_LOAD_ORIGINAL_IMAGE" desc="Context sensitive menu item for Lite mode low fidelity placeholder images that loads the original version in place. [CHAR-LIMIT=30]"> Load image </message> <message name="IDS_CONTEXTMENU_SEARCH_WEB_FOR_IMAGE" desc="Context sensitive menu item for search-for-Image command in a new tab. [CHAR-LIMIT=30]"> @@ -3890,13 +3854,13 @@ <message name="IDS_IPH_DOWNLOAD_HOME_ACCESSIBILITY_TEXT" desc="The in-product-help accessibility text to open download home after a restart."> Find your files and pages in Downloads from the More Options button </message> - <message name="IDS_IPH_DATA_SAVER_PREVIEW_TEXT" desc="In-product help for when a data saver preview page and infobar are shown."> + <message name="IDS_IPH_DATA_SAVER_PREVIEW_TEXT" desc="In-product help for when a lite mode preview page and infobar are shown."> Chrome is using less data to show you this page </message> - <message name="IDS_IPH_DATA_SAVER_DETAIL_TEXT" desc="The in-product-help message to open data saver."> + <message name="IDS_IPH_DATA_SAVER_DETAIL_TEXT" desc="The in-product-help message to open lite mode."> See how much data you've saved </message> - <message name="IDS_IPH_DATA_SAVER_DETAIL_ACCESSIBILITY_TEXT" desc="The in-product-help accessibility text to open data saver."> + <message name="IDS_IPH_DATA_SAVER_DETAIL_ACCESSIBILITY_TEXT" desc="The in-product-help accessibility text to open lite mode."> See how much data you've saved from the More Options button </message> <message name="IDS_IPH_PREVIEWS_OMNIBOX_UI_TEXT" desc="The in-product-help text informing the user that the displayed page was modified to make it load faster or use less data. Prompts the user to tap the message and load the original, unaltered, page if they would like. The 'Lite page provided by Google.' sentence should match TC ID 373879247902731825">
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestShippingAddressChangeTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestShippingAddressChangeTest.java index f9d8a04..ef57d730 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestShippingAddressChangeTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestShippingAddressChangeTest.java
@@ -15,6 +15,7 @@ import org.chromium.base.test.util.DisabledTest; import org.chromium.base.test.util.Feature; import org.chromium.chrome.R; +import org.chromium.chrome.browser.ChromeFeatureList; import org.chromium.chrome.browser.ChromeSwitches; import org.chromium.chrome.browser.autofill.AutofillTestHelper; import org.chromium.chrome.browser.autofill.CardType; @@ -62,6 +63,8 @@ @MediumTest @Feature({"Payments"}) @DisabledTest(message = "https://crbug.com/894011") + @CommandLineFlags. + Add({"disable-features=" + ChromeFeatureList.WEB_PAYMENTS_REDACT_SHIPPING_ADDRESS}) public void testShippingAddressChangeFormat() throws InterruptedException, ExecutionException, TimeoutException { // Select a shipping address and cancel out. @@ -77,4 +80,29 @@ mPaymentRequestTestRule.expectResultContains(new String[] {"Jon Doe", "Google", "340 Main St", "CA", "Los Angeles", "90291", "+16502530000", "US"}); } + + /** + * Tests that only redacted shipping address is sent to the merchant when the user changes the + * shipping address selection. + */ + @Test + @MediumTest + @Feature({"Payments"}) + @CommandLineFlags. + Add({"enable-features=" + ChromeFeatureList.WEB_PAYMENTS_REDACT_SHIPPING_ADDRESS}) + public void testAddressRedactionInShippingAddressChange() + throws InterruptedException, ExecutionException, TimeoutException { + // Select a shipping address and cancel out. + mPaymentRequestTestRule.triggerUIAndWait(mPaymentRequestTestRule.getReadyForInput()); + mPaymentRequestTestRule.clickInShippingAddressAndWait( + R.id.payments_section, mPaymentRequestTestRule.getReadyForInput()); + mPaymentRequestTestRule.clickOnShippingAddressSuggestionOptionAndWait( + 0, mPaymentRequestTestRule.getReadyForInput()); + mPaymentRequestTestRule.clickAndWait( + R.id.close_button, mPaymentRequestTestRule.getDismissed()); + + // The phone number should be formatted to the internation format. + mPaymentRequestTestRule.expectResultContains( + new String[] {"", "", "", "CA", "Los Angeles", "90291", "", "US"}); + } }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/widget/PromoDialogTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/widget/PromoDialogTest.java index a639379c..c0a61e5 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/widget/PromoDialogTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/widget/PromoDialogTest.java
@@ -103,8 +103,8 @@ // Create a full dialog. DialogParams dialogParams = new DialogParams(); dialogParams.vectorDrawableResource = R.drawable.data_reduction_illustration; - dialogParams.headerStringResource = R.string.data_reduction_promo_title; - dialogParams.subheaderStringResource = R.string.data_reduction_promo_summary; + dialogParams.headerStringResource = R.string.data_reduction_promo_title_lite_mode; + dialogParams.subheaderStringResource = R.string.data_reduction_promo_summary_lite_mode; dialogParams.primaryButtonStringResource = R.string.ok; dialogParams.secondaryButtonStringResource = R.string.cancel; dialogParams.footerStringResource = R.string.learn_more; @@ -112,7 +112,7 @@ // Create a minimal dialog. dialogParams = new DialogParams(); - dialogParams.headerStringResource = R.string.data_reduction_promo_title; + dialogParams.headerStringResource = R.string.data_reduction_promo_title_lite_mode; dialogParams.primaryButtonStringResource = R.string.ok; checkDialogControlVisibility(dialogParams); } @@ -152,8 +152,8 @@ public void testBasic_Orientation() throws Exception { DialogParams dialogParams = new DialogParams(); dialogParams.vectorDrawableResource = R.drawable.data_reduction_illustration; - dialogParams.headerStringResource = R.string.data_reduction_promo_title; - dialogParams.subheaderStringResource = R.string.data_reduction_promo_summary; + dialogParams.headerStringResource = R.string.data_reduction_promo_title_lite_mode; + dialogParams.subheaderStringResource = R.string.data_reduction_promo_summary_lite_mode; dialogParams.primaryButtonStringResource = R.string.ok; dialogParams.secondaryButtonStringResource = R.string.cancel; dialogParams.footerStringResource = R.string.learn_more; @@ -214,8 +214,8 @@ // With an illustration, the header View is part of the scrollable content. DialogParams dialogParams = new DialogParams(); dialogParams.drawableResource = R.drawable.preview_pin_round; - dialogParams.headerStringResource = R.string.data_reduction_promo_title; - dialogParams.primaryButtonStringResource = R.string.data_reduction_enable_button; + dialogParams.headerStringResource = R.string.data_reduction_promo_title_lite_mode; + dialogParams.primaryButtonStringResource = R.string.data_reduction_enable_button_lite_mode; PromoDialogWrapper wrapper = new PromoDialogWrapper(getActivity(), dialogParams); PromoDialogLayout promoDialogLayout = wrapper.dialogLayout;
diff --git a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessSuggestionsBinder.java b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessSuggestionsBinder.java index 8a030a7..15c00a34 100644 --- a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessSuggestionsBinder.java +++ b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessSuggestionsBinder.java
@@ -4,11 +4,14 @@ package org.chromium.chrome.browser.touchless; +import android.graphics.Bitmap; +import android.graphics.drawable.Drawable; import android.view.View; import android.widget.TextView; import org.chromium.chrome.browser.suggestions.SuggestionsBinder; import org.chromium.chrome.browser.suggestions.SuggestionsUiDelegate; +import org.chromium.chrome.browser.util.ViewUtils; import org.chromium.chrome.touchless.R; /** Overrides SuggestionsBinder methods to provide touchless specific values and functionality. */
diff --git a/chrome/app/BUILD.gn b/chrome/app/BUILD.gn index b0fb860..565cbcf 100644 --- a/chrome/app/BUILD.gn +++ b/chrome/app/BUILD.gn
@@ -457,6 +457,7 @@ if (is_chromeos) { deps += [ "//chrome/browser/chromeos/kiosk_next_home/mojom", + "//chrome/browser/chromeos/supervision/mojom", "//chromeos/assistant:buildflags", "//chromeos/services/cellular_setup/public/mojom", "//chromeos/services/device_sync/public/cpp:manifest",
diff --git a/chrome/app/chrome_content_browser_overlay_manifest.cc b/chrome/app/chrome_content_browser_overlay_manifest.cc index 7d510ea..39bab7e9 100644 --- a/chrome/app/chrome_content_browser_overlay_manifest.cc +++ b/chrome/app/chrome_content_browser_overlay_manifest.cc
@@ -49,6 +49,7 @@ #if defined(OS_CHROMEOS) #include "chrome/browser/chromeos/kiosk_next_home/mojom/kiosk_next_home_interface_broker.mojom.h" // nogncheck +#include "chrome/browser/chromeos/supervision/mojom/onboarding_controller.mojom.h" #include "chromeos/assistant/buildflags.h" // nogncheck #include "chromeos/services/cellular_setup/public/mojom/cellular_setup.mojom.h" #include "chromeos/services/device_sync/public/cpp/manifest.h" @@ -225,6 +226,7 @@ chromeos::kiosk_next_home::mojom:: KioskNextHomeInterfaceBroker, chromeos::media_perception::mojom::MediaPerception, + chromeos::supervision::mojom::OnboardingController, cros::mojom::CrosImageCapture, #endif contextual_search::mojom::ContextualSearchJsApiService,
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index 29675304..7ceb00e 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd
@@ -9093,9 +9093,6 @@ <message name="IDS_BLUETOOTH_DEVICE_CHOOSER_PAIR_BUTTON_TEXT" desc="Label on the button that closes the Bluetooth chooser popup and pairs the selected device."> Pair </message> - <message name="IDS_DEVICE_CHOOSER_CANCEL_BUTTON_TEXT" desc="Label on the button that closes the chooser popup without selecting an option."> - Cancel - </message> <message name="IDS_DEVICE_CHOOSER_GET_HELP_LINK_WITH_SCANNING_STATUS" desc="This text is shown at the bottom of the chooser popup with a link to 'Get help'."> Get help<ph name="SCANNING_STATUS">$1<ex> while scanning for devices...</ex></ph> </message> @@ -9124,6 +9121,9 @@ <message name="IDS_USB_DEVICE_CHOOSER_CONNECT_BUTTON_TEXT" desc="Label on the button that closes the USB chooser popup and connects the selected device."> Connect </message> + <message name="IDS_DEVICE_CHOOSER_CANCEL_BUTTON_TEXT" desc="Label on the button that closes the chooser popup without selecting an option."> + Cancel + </message> <!-- Device Chooser Device Name Unknown --> <message name="IDS_DEVICE_CHOOSER_DEVICE_NAME_UNKNOWN_DEVICE_WITH_VENDOR_NAME" desc="String describing an unknown device by its vendor name."> @@ -9133,6 +9133,23 @@ Unknown device [<ph name="VENDOR_ID">$1<ex>123</ex></ph>:<ph name="PRODUCT_ID">$2<ex>123</ex></ph>] </message> + <!-- Bluetooth Scanning Prompt --> + <message name="IDS_BLUETOOTH_SCANNING_PROMPT_NO_DEVICES_FOUND_PROMPT" desc="The label shown to the user to inform them that no nearby Bluetooth devices were found using the requirements that the application provided."> + No nearby devices found. + </message> + <message name="IDS_BLUETOOTH_SCANNING_PROMPT_ORIGIN" desc="The label that is used to introduce Bluetooth scanning prompt details to the user when it is from a website."> + <ph name="Origin">$1<ex>www.google.com</ex></ph> wants to scan for nearby Bluetooth devices, the following devices have been found: + </message> + <message name="IDS_BLUETOOTH_SCANNING_PROMPT_ALLOW_BUTTON_TEXT" desc="Label on the button that allows Bluetooth scanning."> + Allow + </message> + <message name="IDS_BLUETOOTH_SCANNING_PROMPT_BLOCK_BUTTON_TEXT" desc="Label on the button that blocks Bluetooth scanning."> + Block + </message> + <message name="IDS_BLUETOOTH_SCANNING_DEVICE_UNKNOWN" desc="Text to identify Bluetooth devices of unknown or unsupported class."> + Unknown or unsupported device (<ph name="DEVICE_ID">$1<ex>A1:B2:C3:D4:E5:F6</ex></ph>) + </message> + <!-- Device descriptions for devices defined by policy with wildcards. --> <message name="IDS_DEVICE_DESCRIPTION_FOR_PRODUCT_ID_AND_VENDOR_NAME" desc="String describing a device by its vendor name when only the numeric product ID is available."> Unknown product <ph name="PRODUCT_ID">$1<ex>123</ex></ph> from <ph name="VENDOR_NAME">$2<ex>Google</ex></ph>
diff --git a/chrome/app/settings_strings.grdp b/chrome/app/settings_strings.grdp index 1e51a63..05dcae26 100644 --- a/chrome/app/settings_strings.grdp +++ b/chrome/app/settings_strings.grdp
@@ -2775,9 +2775,6 @@ <message name="IDS_SETTINGS_SEARCH_GOOGLE_ASSISTANT_DISABLED" desc="Sub label for the Google Assistant button when Assistant is disabled."> Disabled </message> - <message name="IDS_SETTINGS_SEARCH_GOOGLE_ASSISTANT_TURN_ON" desc="Label for the Google Assistant button when ARC is disabled or value prop is not accepted."> - Enable - </message> </if> <!-- Search Engines Page -->
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index b894bd6..c3508d2c 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -167,6 +167,8 @@ "banners/app_banner_metrics.h", "banners/app_banner_settings_helper.cc", "banners/app_banner_settings_helper.h", + "battery/battery_metrics.cc", + "battery/battery_metrics.h", "bitmap_fetcher/bitmap_fetcher.cc", "bitmap_fetcher/bitmap_fetcher.h", "bitmap_fetcher/bitmap_fetcher_delegate.h", @@ -2862,6 +2864,10 @@ "download/download_shelf_context_menu.h", "download/download_shelf_controller.cc", "download/download_shelf_controller.h", + "enterprise_reporting/prefs.cc", + "enterprise_reporting/prefs.h", + "enterprise_reporting/request_timer.cc", + "enterprise_reporting/request_timer.h", "feedback/feedback_dialog_utils.cc", "feedback/feedback_dialog_utils.h", "feedback/feedback_profile_observer.cc", @@ -5074,7 +5080,6 @@ "//chrome/browser/performance_manager:mojo_bindings_js", "//chrome/browser/resources/ssl/ssl_error_assistant:make_ssl_error_assistant_protobuf", "//chrome/browser/ui/webui/bluetooth_internals:mojo_bindings_js", - "//chrome/browser/ui/webui/downloads:mojo_bindings_js", "//chrome/browser/ui/webui/interventions_internals:mojo_bindings_js", "//chrome/browser/ui/webui/omnibox:mojo_bindings_js", "//chrome/browser/ui/webui/usb_internals:mojo_bindings_js", @@ -5117,6 +5122,10 @@ ] } + if (is_chromeos) { + deps += [ "//chrome/browser/chromeos/supervision/mojom:mojom_js" ] + } + if (is_android) { deps += [ "//chrome/browser/ui/webui/explore_sites_internals:mojo_bindings_js", @@ -5130,7 +5139,6 @@ if (!is_android && optimize_webui) { deps += [ "//chrome/browser/resources/bookmarks:build", - "//chrome/browser/resources/downloads:build", "//chrome/browser/resources/history:build", ] if (is_chromeos) {
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index 68964c9..0725d8c 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -1469,9 +1469,6 @@ ENABLE_DISABLE_VALUE_TYPE( chromeos::switches::kEnablePhysicalKeyboardAutocorrect, chromeos::switches::kDisablePhysicalKeyboardAutocorrect)}, - {"gesture-typing", flag_descriptions::kGestureTypingName, - flag_descriptions::kGestureTypingDescription, kOsCrOS, - SINGLE_DISABLE_VALUE_TYPE(keyboard::switches::kDisableGestureTyping)}, #endif // OS_CHROMEOS #if BUILDFLAG(ENABLE_SERVICE_DISCOVERY) {"device-discovery-notifications", @@ -1578,12 +1575,6 @@ flag_descriptions::kExtensionContentVerificationName, flag_descriptions::kExtensionContentVerificationDescription, kOsDesktop, MULTI_VALUE_TYPE(kExtensionContentVerificationChoices)}, -#if BUILDFLAG(ENABLE_EXTENSIONS) - {"enable-embedded-extension-options", - flag_descriptions::kEmbeddedExtensionOptionsName, - flag_descriptions::kEmbeddedExtensionOptionsDescription, kOsDesktop, - SINGLE_VALUE_TYPE(extensions::switches::kEnableEmbeddedExtensionOptions)}, -#endif // ENABLE_EXTENSIONS #if !defined(OS_ANDROID) #if defined(OS_CHROMEOS) {"enable-lock-screen-notification", @@ -2145,6 +2136,10 @@ flag_descriptions::kPerMethodCanMakePaymentQuotaDescription, kOsAll, FEATURE_VALUE_TYPE( payments::features::kWebPaymentsPerMethodCanMakePaymentQuota)}, + {"enable-web-payments-experimental-features", + flag_descriptions::kWebPaymentsExperimentalFeaturesName, + flag_descriptions::kWebPaymentsExperimentalFeaturesDescription, kOsAll, + FEATURE_VALUE_TYPE(payments::features::kWebPaymentsExperimentalFeatures)}, {"fill-on-account-select", flag_descriptions::kFillOnAccountSelectName, flag_descriptions::kFillOnAccountSelectDescription, kOsAll, FEATURE_VALUE_TYPE(password_manager::features::kFillOnAccountSelect)}, @@ -3202,6 +3197,9 @@ {"enable-arc-cups-api", flag_descriptions::kArcCupsApiName, flag_descriptions::kArcCupsApiDescription, kOsCrOS, FEATURE_VALUE_TYPE(features::kArcCupsApi)}, + {"enable-cros-vm-cups-proxy", flag_descriptions::kCrosVmCupsProxyName, + flag_descriptions::kCrosVmCupsProxyDescription, kOsCrOS, + FEATURE_VALUE_TYPE(features::kCrosVmCupsProxy)}, #endif // OS_CHROMEOS #if defined(OS_CHROMEOS)
diff --git a/chrome/browser/android/chrome_feature_list.cc b/chrome/browser/android/chrome_feature_list.cc index d283da55..47aa4b3 100644 --- a/chrome/browser/android/chrome_feature_list.cc +++ b/chrome/browser/android/chrome_feature_list.cc
@@ -181,9 +181,11 @@ &kVrBrowsingFeedback, &network::features::kNetworkService, &payments::features::kReturnGooglePayInBasicCard, + &payments::features::kWebPaymentsExperimentalFeatures, &payments::features::kWebPaymentsMethodSectionOrderV2, &payments::features::kWebPaymentsModifiers, &payments::features::kWebPaymentsSingleAppUiSkip, + &payments::features::kWebPaymentsRedactShippingAddress, &language::kExplicitLanguageAsk, &ntp_snippets::kArticleSuggestionsFeature, &offline_pages::kOfflineIndicatorFeature, @@ -202,7 +204,6 @@ &omnibox::kUIExperimentShowSuggestionFavicons, &password_manager::features::kGooglePasswordManager, &password_manager::features::kPasswordsKeyboardAccessory, - &previews::features::kDataSaverLiteModeRebranding, &safe_browsing::kCaptureSafetyNetId, &signin::kMiceFeature, &switches::kSyncSendTabToSelf,
diff --git a/chrome/browser/android/compositor/layer/ephemeral_tab_layer.cc b/chrome/browser/android/compositor/layer/ephemeral_tab_layer.cc index 3e2745c..3ceab504 100644 --- a/chrome/browser/android/compositor/layer/ephemeral_tab_layer.cc +++ b/chrome/browser/android/compositor/layer/ephemeral_tab_layer.cc
@@ -4,12 +4,50 @@ #include "chrome/browser/android/compositor/layer/ephemeral_tab_layer.h" +#include "base/task/cancelable_task_tracker.h" #include "cc/layers/layer.h" -#include "cc/layers/nine_patch_layer.h" -#include "cc/resources/scoped_ui_resource.h" -#include "content/public/browser/android/compositor.h" -#include "ui/android/resources/nine_patch_resource.h" +#include "cc/layers/ui_resource_layer.h" +#include "chrome/browser/favicon/favicon_service_factory.h" +#include "chrome/browser/profiles/profile.h" +#include "components/favicon/core/favicon_service.h" +#include "third_party/skia/include/core/SkBitmap.h" #include "ui/android/resources/resource_manager.h" +#include "ui/base/l10n/l10n_util_android.h" +#include "ui/gfx/codec/png_codec.h" +#include "url/gurl.h" + +namespace { + +void OnLocalFaviconAvailable( + scoped_refptr<cc::UIResourceLayer> layer, + scoped_refptr<cc::UIResourceLayer> icon_layer, + const float dp_to_px, + const float panel_width, + const float bar_height, + const float padding, + const favicon_base::FaviconRawBitmapResult& result) { + if (!result.is_valid()) + return; + SkBitmap favicon_bitmap; + gfx::PNGCodec::Decode(result.bitmap_data->front(), result.bitmap_data->size(), + &favicon_bitmap); + if (favicon_bitmap.isNull()) + return; + const float icon_width = + android::OverlayPanelLayer::kDefaultIconWidthDp * dp_to_px; + favicon_bitmap.setImmutable(); + layer->SetBitmap(favicon_bitmap); + layer->SetBounds(gfx::Size(icon_width, icon_width)); + + bool is_rtl = l10n_util::IsLayoutRtl(); + float icon_x = is_rtl ? panel_width - icon_width - padding : padding; + float icon_y = (bar_height - layer->bounds().height()) / 2; + icon_layer->SetIsDrawable(false); + layer->SetIsDrawable(true); + layer->SetPosition(gfx::PointF(icon_x, icon_y)); +} + +} // namespace namespace android { // static @@ -63,6 +101,10 @@ progress_bar_background_resource_id, progress_bar_resource_id, progress_bar_visible, bar_bottom, progress_bar_height, progress_bar_opacity, progress_bar_completion, panel_width); + dp_to_px_ = dp_to_px; + panel_width_ = panel_width; + bar_height_ = bar_height; + bar_margin_side_ = bar_margin_side; } void EphemeralTabLayer::SetupTextLayer(float bar_top, @@ -113,17 +155,48 @@ title_->SetPosition(gfx::PointF(0.f, title_top)); } +void EphemeralTabLayer::GetLocalFaviconImageForURL(Profile* profile, + const std::string& url, + int size) { + panel_icon_->SetIsDrawable(true); + favicon_layer_->SetIsDrawable(false); + favicon::FaviconService* favicon_service = + FaviconServiceFactory::GetForProfile(profile, + ServiceAccessType::EXPLICIT_ACCESS); + DCHECK(favicon_service); + if (!favicon_service) + return; + + favicon_base::FaviconRawBitmapCallback callback_runner = base::BindRepeating( + &OnLocalFaviconAvailable, favicon_layer_, panel_icon_, dp_to_px_, + panel_width_, bar_height_, bar_margin_side_); + + // Set |fallback_to_host|=true so the favicon database will fall back to + // matching only the hostname to have the best chance of finding a favicon. + const bool fallback_to_host = true; + favicon_service->GetRawFaviconForPageURL( + GURL(url), + {favicon_base::IconType::kFavicon, favicon_base::IconType::kTouchIcon, + favicon_base::IconType::kTouchPrecomposedIcon, + favicon_base::IconType::kWebManifestIcon}, + size, fallback_to_host, callback_runner, cancelable_task_tracker_.get()); +} + EphemeralTabLayer::EphemeralTabLayer(ui::ResourceManager* resource_manager) : OverlayPanelLayer(resource_manager), title_(cc::UIResourceLayer::Create()), + favicon_layer_(cc::UIResourceLayer::Create()), text_layer_(cc::UIResourceLayer::Create()) { // Content layer text_layer_->SetIsDrawable(true); - title_->SetIsDrawable(true); AddBarTextLayer(text_layer_); text_layer_->AddChild(title_); + + favicon_layer_->SetIsDrawable(true); + layer_->AddChild(favicon_layer_); + cancelable_task_tracker_.reset(new base::CancelableTaskTracker()); } EphemeralTabLayer::~EphemeralTabLayer() {}
diff --git a/chrome/browser/android/compositor/layer/ephemeral_tab_layer.h b/chrome/browser/android/compositor/layer/ephemeral_tab_layer.h index 3b6c64ee..e475fd7 100644 --- a/chrome/browser/android/compositor/layer/ephemeral_tab_layer.h +++ b/chrome/browser/android/compositor/layer/ephemeral_tab_layer.h
@@ -5,13 +5,17 @@ #ifndef CHROME_BROWSER_ANDROID_COMPOSITOR_LAYER_EPHEMERAL_TAB_LAYER_H_ #define CHROME_BROWSER_ANDROID_COMPOSITOR_LAYER_EPHEMERAL_TAB_LAYER_H_ -#include <memory> - #include "chrome/browser/android/compositor/layer/overlay_panel_layer.h" +class Profile; + +namespace base { +class CancelableTaskTracker; +} + namespace cc { class Layer; -} // namespace cc +} namespace ui { class ResourceManager; @@ -51,13 +55,23 @@ float text_layer_min_height, int context_resource_id); + void GetLocalFaviconImageForURL(Profile* profile, + const std::string& url, + int size); + protected: explicit EphemeralTabLayer(ui::ResourceManager* resource_manager); ~EphemeralTabLayer() override; private: + float dp_to_px_; + float panel_width_; + float bar_height_; + float bar_margin_side_; scoped_refptr<cc::UIResourceLayer> title_; + scoped_refptr<cc::UIResourceLayer> favicon_layer_; scoped_refptr<cc::UIResourceLayer> text_layer_; + std::unique_ptr<base::CancelableTaskTracker> cancelable_task_tracker_; }; } // namespace android
diff --git a/chrome/browser/android/compositor/layer/overlay_panel_layer.cc b/chrome/browser/android/compositor/layer/overlay_panel_layer.cc index 9905c7b5..e6afccb 100644 --- a/chrome/browser/android/compositor/layer/overlay_panel_layer.cc +++ b/chrome/browser/android/compositor/layer/overlay_panel_layer.cc
@@ -16,16 +16,14 @@ #include "ui/base/l10n/l10n_util_android.h" #include "ui/gfx/color_utils.h" -namespace { - -// This is the default width for any icon displayed on an OverlayPanel. -const float kDefaultIconWidthDp = 36.0f; - -} // namespace - namespace android { +const float OverlayPanelLayer::kDefaultIconWidthDp = 36.0f; +const int OverlayPanelLayer::kInvalidResourceID = -1; + scoped_refptr<cc::Layer> OverlayPanelLayer::GetIconLayer() { + if (panel_icon_resource_id_ == -1) + return nullptr; ui::Resource* panel_icon_resource = resource_manager_->GetResource( ui::ANDROID_RESOURCE_TYPE_STATIC, panel_icon_resource_id_); DCHECK(panel_icon_resource); @@ -209,7 +207,7 @@ // --------------------------------------------------------------------------- // Open Tab icon // --------------------------------------------------------------------------- - if (open_tab_icon_resource_id_ != -1) { + if (open_tab_icon_resource_id_ != kInvalidResourceID) { ui::Resource* open_tab_icon_resource = resource_manager_->GetStaticResourceWithTint(open_tab_icon_resource_id_, icon_tint);
diff --git a/chrome/browser/android/compositor/layer/overlay_panel_layer.h b/chrome/browser/android/compositor/layer/overlay_panel_layer.h index 14c84b9..1f61b0d 100644 --- a/chrome/browser/android/compositor/layer/overlay_panel_layer.h +++ b/chrome/browser/android/compositor/layer/overlay_panel_layer.h
@@ -24,6 +24,12 @@ class OverlayPanelLayer : public Layer { public: + // Default width for any icon displayed on an OverlayPanel. + static const float kDefaultIconWidthDp; + + // ID for Invalid resource. + static const int kInvalidResourceID; + void SetResourceIds(int bar_text_resource_id, int panel_shadow_resource_id, int bar_shadow_resource_id,
diff --git a/chrome/browser/android/compositor/scene_layer/ephemeral_tab_scene_layer.cc b/chrome/browser/android/compositor/scene_layer/ephemeral_tab_scene_layer.cc index 990a017d..82d7f1b 100644 --- a/chrome/browser/android/compositor/scene_layer/ephemeral_tab_scene_layer.cc +++ b/chrome/browser/android/compositor/scene_layer/ephemeral_tab_scene_layer.cc
@@ -3,17 +3,16 @@ // found in the LICENSE file. #include "chrome/browser/android/compositor/scene_layer/ephemeral_tab_scene_layer.h" -#include "base/android/jni_android.h" -#include "base/android/jni_array.h" +#include "base/android/jni_string.h" #include "cc/layers/solid_color_layer.h" #include "chrome/browser/android/compositor/layer/ephemeral_tab_layer.h" -#include "content/public/browser/android/compositor.h" +#include "chrome/browser/profiles/profile_android.h" #include "content/public/browser/web_contents.h" #include "jni/EphemeralTabSceneLayer_jni.h" #include "ui/android/resources/resource_manager_impl.h" #include "ui/android/view_android.h" -#include "ui/gfx/android/java_bitmap.h" +using base::android::ConvertJavaStringToUTF8; using base::android::JavaParamRef; using base::android::JavaRef; @@ -60,6 +59,19 @@ open_tab_icon_resource_id, close_icon_resource_id); } +void EphemeralTabSceneLayer::GetFavicon(JNIEnv* env, + const JavaParamRef<jobject>& object, + const JavaParamRef<jobject>& jprofile, + const JavaParamRef<jstring>& jurl, + jint size) { + Profile* profile = ProfileAndroid::FromProfileAndroid(jprofile); + DCHECK(profile); + if (!profile) + return; + ephemeral_tab_layer_->GetLocalFaviconImageForURL( + profile, ConvertJavaStringToUTF8(env, jurl), size); +} + void EphemeralTabSceneLayer::Update(JNIEnv* env, const JavaParamRef<jobject>& object, jint title_view_resource_id,
diff --git a/chrome/browser/android/compositor/scene_layer/ephemeral_tab_scene_layer.h b/chrome/browser/android/compositor/scene_layer/ephemeral_tab_scene_layer.h index 0113e57..a78e6b01 100644 --- a/chrome/browser/android/compositor/scene_layer/ephemeral_tab_scene_layer.h +++ b/chrome/browser/android/compositor/scene_layer/ephemeral_tab_scene_layer.h
@@ -5,15 +5,10 @@ #ifndef CHROME_BROWSER_ANDROID_COMPOSITOR_SCENE_LAYER_EPHEMERAL_TAB_SCENE_LAYER_H_ #define CHROME_BROWSER_ANDROID_COMPOSITOR_SCENE_LAYER_EPHEMERAL_TAB_SCENE_LAYER_H_ -#include <memory> -#include <vector> - #include "base/android/jni_android.h" #include "base/android/jni_weak_ref.h" #include "base/android/scoped_java_ref.h" -#include "base/macros.h" #include "chrome/browser/android/compositor/scene_layer/scene_layer.h" -#include "ui/android/resources/resource_manager_impl.h" namespace cc { class Layer; @@ -45,6 +40,12 @@ jint open_tab_icon_resource_id, jint close_icon_resource_id); + void GetFavicon(JNIEnv* env, + const base::android::JavaParamRef<jobject>& object, + const base::android::JavaParamRef<jobject>& jprofile, + const base::android::JavaParamRef<jstring>& jurl, + jint size); + void Update(JNIEnv* env, const base::android::JavaParamRef<jobject>& object, jint title_view_resource_id,
diff --git a/chrome/browser/battery/OWNERS b/chrome/browser/battery/OWNERS new file mode 100644 index 0000000..70a9cca0 --- /dev/null +++ b/chrome/browser/battery/OWNERS
@@ -0,0 +1,4 @@ +ryansturm@chromium.org +tbansal@chromium.org + +# COMPONENT: Internals>Preload \ No newline at end of file
diff --git a/chrome/browser/battery/battery_metrics.cc b/chrome/browser/battery/battery_metrics.cc new file mode 100644 index 0000000..08c61a2 --- /dev/null +++ b/chrome/browser/battery/battery_metrics.cc
@@ -0,0 +1,84 @@ +// 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/battery/battery_metrics.h" + +#include <cmath> +#include <utility> + +#include "base/bind.h" +#include "base/metrics/histogram_macros.h" +#include "build/build_config.h" +#include "content/public/common/service_manager_connection.h" +#include "mojo/public/cpp/bindings/strong_binding.h" +#include "services/device/public/mojom/constants.mojom.h" +#include "services/service_manager/public/cpp/connector.h" +#include "services/service_manager/public/cpp/service_filter.h" + +BatteryMetrics::BatteryMetrics() : weak_factory_(this) { + StartRecording(); +} + +BatteryMetrics::~BatteryMetrics() = default; + +void BatteryMetrics::QueryNextStatus() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK(battery_monitor_.is_bound()); + + battery_monitor_->QueryNextStatus( + base::BindOnce(&BatteryMetrics::DidChange, weak_factory_.GetWeakPtr())); +} + +void BatteryMetrics::StartRecording() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK(!battery_monitor_.is_bound()); + + // Don't create a long lived BatteryMonitor on windows. crbug.com/794105. +#if !defined(OS_WIN) + content::ServiceManagerConnection* connection = + content::ServiceManagerConnection::GetForProcess(); + connection->GetConnector()->BindInterface( + service_manager::ServiceFilter::ByName(device::mojom::kServiceName), + mojo::MakeRequest(&battery_monitor_)); + QueryNextStatus(); +#endif // !defined(OS_WIN) +} + +void BatteryMetrics::DidChange(device::mojom::BatteryStatusPtr battery_status) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + QueryNextStatus(); + RecordBatteryDropUMA(*battery_status); +} + +void BatteryMetrics::RecordBatteryDropUMA( + const device::mojom::BatteryStatus& battery_status) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + if (battery_status.charging) { + // If the battery charges, drop the stored battery level. + last_recorded_battery_level_ = base::nullopt; + return; + } + + if (!last_recorded_battery_level_) { + // If the battery is not charging, and we don't have a stored battery level, + // record the current battery level. + last_recorded_battery_level_ = battery_status.level; + return; + } + + // Record the percentage drop event every time the battery drops by 1 percent + // or more. + if (last_recorded_battery_level_) { + float battery_drop_percent_floored = + std::floor(last_recorded_battery_level_.value() * 100.f - + battery_status.level * 100.f); + if (battery_drop_percent_floored > 0) { + UMA_HISTOGRAM_PERCENTAGE("Power.BatteryPercentDrop", + static_cast<int>(battery_drop_percent_floored)); + // Record the old level minus the recorded drop. + last_recorded_battery_level_ = last_recorded_battery_level_.value() - + (battery_drop_percent_floored / 100.f); + } + } +}
diff --git a/chrome/browser/battery/battery_metrics.h b/chrome/browser/battery/battery_metrics.h new file mode 100644 index 0000000..892f831 --- /dev/null +++ b/chrome/browser/battery/battery_metrics.h
@@ -0,0 +1,50 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_BATTERY_BATTERY_METRICS_H_ +#define CHROME_BROWSER_BATTERY_BATTERY_METRICS_H_ + +#include "base/macros.h" +#include "base/memory/weak_ptr.h" +#include "base/optional.h" +#include "base/sequence_checker.h" +#include "services/device/public/mojom/battery_monitor.mojom.h" +#include "services/device/public/mojom/battery_status.mojom.h" + +// Records metrics around battery usage on all platforms. Connects to +// Battery monitor via mojo. +class BatteryMetrics { + public: + BatteryMetrics(); + ~BatteryMetrics(); + + private: + // Start recording UMA for the session/profile. + void StartRecording(); + + // Calls |QueryNextStatus()| on |battery_monitor_|. + void QueryNextStatus(); + + // Called when a new BatteryStatus update occurs. + void DidChange(device::mojom::BatteryStatusPtr battery_status); + + // Records the drop in battery by percents of total battery. + void RecordBatteryDropUMA(const device::mojom::BatteryStatus& battery_status); + + // The battery level at the last time the battery level was recorded. This + // value is updated by the amount of battery drop reported, so may be + // different from the last update by .01. + base::Optional<float> last_recorded_battery_level_; + + // The battery monitor backend for the device Chrome is running on. + device::mojom::BatteryMonitorPtr battery_monitor_; + + SEQUENCE_CHECKER(sequence_checker_); + + base::WeakPtrFactory<BatteryMetrics> weak_factory_; + + DISALLOW_COPY_AND_ASSIGN(BatteryMetrics); +}; + +#endif // CHROME_BROWSER_BATTERY_BATTERY_METRICS_H_
diff --git a/chrome/browser/battery/battery_metrics_browsertest.cc b/chrome/browser/battery/battery_metrics_browsertest.cc new file mode 100644 index 0000000..deea6f5 --- /dev/null +++ b/chrome/browser/battery/battery_metrics_browsertest.cc
@@ -0,0 +1,162 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <utility> + +#include "base/bind.h" +#include "base/macros.h" +#include "base/run_loop.h" +#include "base/test/metrics/histogram_tester.h" +#include "base/threading/thread_task_runner_handle.h" +#include "build/build_config.h" +#include "chrome/browser/browser_process.h" +#include "chrome/browser/metrics/subprocess_metrics_provider.h" +#include "chrome/test/base/in_process_browser_test.h" +#include "content/public/common/service_manager_connection.h" +#include "content/public/test/browser_test_utils.h" +#include "mojo/public/cpp/bindings/strong_binding.h" +#include "services/device/public/mojom/battery_monitor.mojom.h" +#include "services/device/public/mojom/battery_status.mojom.h" +#include "services/device/public/mojom/constants.mojom.h" +#include "services/service_manager/public/cpp/service_binding.h" + +namespace { + +// Retries fetching |histogram_name| until it contains at least |count| samples. +void RetryForHistogramBucketUntilCountReached( + base::HistogramTester* histogram_tester, + const std::string& histogram_name, + base::HistogramBase::Sample target_bucket, + size_t count) { + base::RunLoop().RunUntilIdle(); + for (size_t attempt = 0; attempt < 50; ++attempt) { + const std::vector<base::Bucket> buckets = + histogram_tester->GetAllSamples(histogram_name); + size_t total_count = 0; + for (const auto& bucket : buckets) { + if (bucket.min == target_bucket) + total_count += bucket.count; + } + if (total_count >= count) + return; + content::FetchHistogramsFromChildProcesses(); + SubprocessMetricsProvider::MergeHistogramDeltasForTesting(); + base::RunLoop().RunUntilIdle(); + } +} + +// Replaces the platform specific implementation of BatteryMonitor. +class MockBatteryMonitor : public device::mojom::BatteryMonitor { + public: + MockBatteryMonitor() : binding_(this) {} + ~MockBatteryMonitor() override = default; + + void Bind(device::mojom::BatteryMonitorRequest request) { + DCHECK(!binding_.is_bound()); + binding_.Bind(std::move(request)); + } + + void DidChange(const device::mojom::BatteryStatus& battery_status) { + status_ = battery_status; + status_to_report_ = true; + + if (!callback_.is_null()) + ReportStatus(); + } + + void CloseBinding() { binding_.Close(); } + + private: + // mojom::BatteryMonitor methods: + void QueryNextStatus(QueryNextStatusCallback callback) override { + if (!callback_.is_null()) { + binding_.Close(); + return; + } + callback_ = std::move(callback); + + if (status_to_report_) + ReportStatus(); + } + + void ReportStatus() { + std::move(callback_).Run(status_.Clone()); + status_to_report_ = false; + } + + QueryNextStatusCallback callback_; + device::mojom::BatteryStatus status_; + bool status_to_report_ = false; + mojo::Binding<device::mojom::BatteryMonitor> binding_; + + DISALLOW_COPY_AND_ASSIGN(MockBatteryMonitor); +}; + +// Test that the metricss around battery usage are recorded correctly. +class BatteryMetricsBrowserTest : public InProcessBrowserTest { + public: + BatteryMetricsBrowserTest() = default; + ~BatteryMetricsBrowserTest() override = default; + + protected: + MockBatteryMonitor* mock_battery_monitor() { + return mock_battery_monitor_.get(); + } + + private: + void SetUpOnMainThread() override { + mock_battery_monitor_ = std::make_unique<MockBatteryMonitor>(); + service_manager::ServiceBinding::OverrideInterfaceBinderForTesting( + device::mojom::kServiceName, + base::BindRepeating(&MockBatteryMonitor::Bind, + base::Unretained(mock_battery_monitor_.get()))); + } + + void TearDownOnMainThread() override { + service_manager::ServiceBinding::ClearInterfaceBinderOverrideForTesting< + device::mojom::BatteryMonitor>(device::mojom::kServiceName); + + InProcessBrowserTest::TearDownOnMainThread(); + } + + std::unique_ptr<MockBatteryMonitor> mock_battery_monitor_; + + DISALLOW_COPY_AND_ASSIGN(BatteryMetricsBrowserTest); +}; + +#if defined(OS_WIN) +#define DISABLED_ON_WIN(name) DISABLED##name +#else +#define DISABLED_ON_WIN(name) name +#endif + +IN_PROC_BROWSER_TEST_F(BatteryMetricsBrowserTest, + DISABLED_ON_WIN(BatteryDropUMA)) { + // Verify that drops in battery level are recorded, and drops by less than 1% + // are aggregated together until there is a full percentage drop. + device::mojom::BatteryStatus status; + status.charging = false; + status.charging_time = std::numeric_limits<double>::infinity(); + status.discharging_time = 100; + status.level = 0.6; + + mock_battery_monitor()->DidChange(status); + + base::HistogramTester histogram_tester; + // A drop of 10.9% should record in the 10 bucket. + status.level = 0.491; + mock_battery_monitor()->DidChange(status); + RetryForHistogramBucketUntilCountReached(&histogram_tester, + "Power.BatteryPercentDrop", 10, 1); + + // .9% should be stored from the previous drop, so an additional drop to 1% + // should be recorded in the 1% bucket. + status.level = 0.49; + mock_battery_monitor()->DidChange(status); + + RetryForHistogramBucketUntilCountReached(&histogram_tester, + "Power.BatteryPercentDrop", 1, 1); +} + +} // namespace
diff --git a/chrome/browser/browser_process_impl.cc b/chrome/browser/browser_process_impl.cc index fcda1981..d5712a0d 100644 --- a/chrome/browser/browser_process_impl.cc +++ b/chrome/browser/browser_process_impl.cc
@@ -34,6 +34,7 @@ #include "base/time/default_tick_clock.h" #include "base/trace_event/trace_event.h" #include "build/build_config.h" +#include "chrome/browser/battery/battery_metrics.h" #include "chrome/browser/chrome_browser_main.h" #include "chrome/browser/chrome_child_process_watcher.h" #include "chrome/browser/chrome_content_browser_client.h" @@ -267,6 +268,8 @@ net_log_ = std::make_unique<net_log::ChromeNetLog>(); + battery_metrics_ = std::make_unique<BatteryMetrics>(); + ChildProcessSecurityPolicy::GetInstance()->RegisterWebSafeScheme( chrome::kChromeSearchScheme); @@ -410,6 +413,8 @@ remote_debugging_server_.reset(); devtools_auto_opener_.reset(); + battery_metrics_.reset(); + // Need to clear profiles (download managers) before the io_thread_. { TRACE_EVENT0("shutdown",
diff --git a/chrome/browser/browser_process_impl.h b/chrome/browser/browser_process_impl.h index f91fd655..95a7bd8e 100644 --- a/chrome/browser/browser_process_impl.h +++ b/chrome/browser/browser_process_impl.h
@@ -35,6 +35,7 @@ #include "services/network/public/cpp/network_quality_tracker.h" #include "services/network/public/mojom/network_service.mojom-forward.h" +class BatteryMetrics; class ChromeChildProcessWatcher; class ChromeFeatureListCreator; class ChromeMetricsServicesManagerClient; @@ -362,6 +363,8 @@ // Lives here so can safely log events on shutdown. std::unique_ptr<net_log::ChromeNetLog> net_log_; + std::unique_ptr<BatteryMetrics> battery_metrics_; + std::unique_ptr<ChromeResourceDispatcherHostDelegate> resource_dispatcher_host_delegate_;
diff --git a/chrome/browser/browser_resources.grd b/chrome/browser/browser_resources.grd index 8ca0591..cb0dc12 100644 --- a/chrome/browser/browser_resources.grd +++ b/chrome/browser/browser_resources.grd
@@ -158,37 +158,6 @@ <include name="IDR_UKM_INTERNALS_CSS" file="../../components/ukm/debug/ukm_internals.css" flattenhtml="true" compress="gzip" type="BINDATA" /> <include name="IDR_TRANSLATE_INTERNALS_HTML" file="../../components/translate/translate_internals/translate_internals.html" flattenhtml="true" allowexternalscript="true" compress="gzip" type="BINDATA" /> <include name="IDR_TRANSLATE_INTERNALS_JS" file="../../components/translate/translate_internals/translate_internals.js" flattenhtml="true" compress="gzip" type="BINDATA" /> - <if expr="not is_android"> - <include name="IDR_DOWNLOADS_IMAGES_INCOGNITO_MARKER_SVG" file="resources\downloads\images\incognito_marker.svg" type="BINDATA" /> - <include name="IDR_DOWNLOADS_IMAGES_NO_DOWNLOADS_SVG" file="resources\downloads\images\no_downloads.svg" type="BINDATA" /> - <include name="IDR_DOWNLOADS_MOJO_LITE_JS" file="${root_gen_dir}\chrome\browser\ui\webui\downloads\downloads.mojom-lite.js" use_base_dir="false" type="BINDATA" /> - <if expr="optimize_webui"> - <then> - <include name="IDR_DOWNLOADS_VULCANIZED_HTML" file="${root_gen_dir}\chrome\browser\resources\downloads\vulcanized.html" use_base_dir="false" flattenhtml="true" allowexternalscript="true" type="BINDATA" compress="gzip" /> - <include name="IDR_DOWNLOADS_CRISPER_JS" file="${root_gen_dir}\chrome\browser\resources\downloads\crisper.js" use_base_dir="false" flattenhtml="true" type="BINDATA" compress="gzip" /> - </then> - <else> - <include name="IDR_DOWNLOADS_DOWNLOADS_HTML" file="resources\downloads\downloads.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" /> - <include name="IDR_DOWNLOADS_BROWSER_PROXY_HTML" file="resources\downloads\browser_proxy.html" type="BINDATA" /> - <include name="IDR_DOWNLOADS_BROWSER_PROXY_JS" file="resources\downloads\browser_proxy.js" type="BINDATA" /> - <include name="IDR_DOWNLOADS_CONSTANTS_HTML" file="resources\downloads\constants.html" type="BINDATA" /> - <include name="IDR_DOWNLOADS_CONSTANTS_JS" file="resources\downloads\constants.js" type="BINDATA" /> - <include name="IDR_DOWNLOADS_DOWNLOADS_JS" file="resources\downloads\downloads.js" type="BINDATA" /> - <include name="IDR_DOWNLOADS_I18N_SETUP_HTML" file="resources\downloads\i18n_setup.html" type="BINDATA" /> - <include name="IDR_DOWNLOADS_ICON_LOADER_HTML" file="resources\downloads\icon_loader.html" type="BINDATA" /> - <include name="IDR_DOWNLOADS_ICON_LOADER_JS" file="resources\downloads\icon_loader.js" type="BINDATA" /> - <include name="IDR_DOWNLOADS_ICONS_HTML" file="resources\downloads\icons.html" type="BINDATA" /> - <include name="IDR_DOWNLOADS_ITEM_HTML" file="resources\downloads\item.html" type="BINDATA" /> - <include name="IDR_DOWNLOADS_ITEM_JS" file="resources\downloads\item.js" type="BINDATA" /> - <include name="IDR_DOWNLOADS_MANAGER_HTML" file="resources\downloads\manager.html" type="BINDATA" /> - <include name="IDR_DOWNLOADS_MANAGER_JS" file="resources\downloads\manager.js" type="BINDATA" /> - <include name="IDR_DOWNLOADS_SEARCH_SERVICE_HTML" file="resources\downloads\search_service.html" type="BINDATA" /> - <include name="IDR_DOWNLOADS_SEARCH_SERVICE_JS" file="resources\downloads\search_service.js" type="BINDATA" /> - <include name="IDR_DOWNLOADS_TOOLBAR_HTML" file="resources\downloads\toolbar.html" type="BINDATA" /> - <include name="IDR_DOWNLOADS_TOOLBAR_JS" file="resources\downloads\toolbar.js" type="BINDATA" /> - </else> - </if> - </if> <include name="IDR_FEEDBACK_MANIFEST" file="resources\feedback\manifest.json" type="BINDATA" /> <if expr="is_android"> <include name="IDR_EXPLORE_SITES_INTERNALS_HTML" file="resources\explore_sites_internals\explore_sites_internals.html" allowexternalscript="true" compress="gzip" type="BINDATA" /> @@ -216,6 +185,20 @@ <include name="IDR_HANGOUT_SERVICES_MANIFEST" file="resources\hangout_services\manifest.json" type="BINDATA" /> </if> + <!-- Chrome OS Supervised users. --> + <if expr="chromeos"> + <include name="IDR_SUPERVISION_ONBOARDING_CONTROLLER_MOJOM_HTML" + file="${root_gen_dir}/chrome/browser/chromeos/supervision/mojom/onboarding_controller.mojom.html" + use_base_dir="false" + type="BINDATA" + compress="gzip" /> + <include name="IDR_SUPERVISION_ONBOARDING_CONTROLLER_MOJOM_LITE_JS" + file="${root_gen_dir}/chrome/browser/chromeos/supervision/mojom/onboarding_controller.mojom-lite.js" + use_base_dir="false" + type="BINDATA" + compress="gzip" /> + </if> + <!-- App Management. --> <if expr="not is_android"> <include name="IDR_APP_MANAGEMENT_BITMAP_MOJO_LITE_JS" file="${root_gen_dir}\skia\public\interfaces\bitmap.mojom-lite.js" use_base_dir="false" type="BINDATA" />
diff --git a/chrome/browser/browsing_data/mock_browsing_data_local_storage_helper.cc b/chrome/browser/browsing_data/mock_browsing_data_local_storage_helper.cc index 5c0ce5ae..fa4558b9a 100644 --- a/chrome/browser/browsing_data/mock_browsing_data_local_storage_helper.cc +++ b/chrome/browser/browsing_data/mock_browsing_data_local_storage_helper.cc
@@ -44,7 +44,7 @@ void MockBrowsingDataLocalStorageHelper::AddLocalStorageForOrigin( const url::Origin& origin, - size_t size) { + int64_t size) { response_.emplace_back(origin, size, base::Time()); origins_[origin] = true; }
diff --git a/chrome/browser/browsing_data/mock_browsing_data_local_storage_helper.h b/chrome/browser/browsing_data/mock_browsing_data_local_storage_helper.h index f0b1e73..c01d22b 100644 --- a/chrome/browser/browsing_data/mock_browsing_data_local_storage_helper.h +++ b/chrome/browser/browsing_data/mock_browsing_data_local_storage_helper.h
@@ -29,7 +29,7 @@ void AddLocalStorageSamples(); // Add a LocalStorageInfo entry for a single origin. - void AddLocalStorageForOrigin(const url::Origin& origin, size_t size); + void AddLocalStorageForOrigin(const url::Origin& origin, int64_t size); // Notifies the callback. void Notify();
diff --git a/chrome/browser/chooser_controller/chooser_controller.cc b/chrome/browser/chooser_controller/chooser_controller.cc index 2694473..5641093 100644 --- a/chrome/browser/chooser_controller/chooser_controller.cc +++ b/chrome/browser/chooser_controller/chooser_controller.cc
@@ -6,6 +6,7 @@ #include "base/logging.h" #include "base/strings/utf_string_conversions.h" +#include "chrome/grit/generated_resources.h" #include "components/url_formatter/elide_url.h" #include "content/public/browser/render_frame_host.h" #include "content/public/browser/web_contents.h" @@ -83,6 +84,18 @@ return false; } +base::string16 ChooserController::GetCancelButtonLabel() const { + return l10n_util::GetStringUTF16(IDS_DEVICE_CHOOSER_CANCEL_BUTTON_TEXT); +} + +bool ChooserController::BothButtonsAlwaysEnabled() const { + return false; +} + +bool ChooserController::TableViewAlwaysDisabled() const { + return false; +} + int ChooserController::GetSignalStrengthLevel(size_t index) const { return -1; }
diff --git a/chrome/browser/chooser_controller/chooser_controller.h b/chrome/browser/chooser_controller/chooser_controller.h index 72530af..896b9d9 100644 --- a/chrome/browser/chooser_controller/chooser_controller.h +++ b/chrome/browser/chooser_controller/chooser_controller.h
@@ -83,6 +83,28 @@ // Returns the label for OK button. virtual base::string16 GetOkButtonLabel() const = 0; + // Returns the label for Cancel button. + virtual base::string16 GetCancelButtonLabel() const; + + // Returns whether both OK and Cancel buttons are enabled. + // + // For chooser used in Web APIs such as WebBluetooth, WebUSB, + // WebSerial, etc., the OK button is only enabled when there is at least + // one device listed in the chooser, because user needs to be able to select + // a device to grant access permission in these APIs. + // + // For permission prompt used in Bluetooth scanning Web API, the two buttons + // represent Allow and Block, and should always be enabled so that user can + // make their permission decision. + virtual bool BothButtonsAlwaysEnabled() const; + + // Returns whether table view should always be disabled. + // + // For permission prompt used in Bluetooth scanning Web API, the table is + // used for displaying device names, and user doesn't need to select a device + // from the table, so it should always be disabled. + virtual bool TableViewAlwaysDisabled() const; + // The number of options users can pick from. For example, it can be // the number of USB/Bluetooth device names which are listed in the // chooser so that users can grant permission.
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc index 804e81f..c507af9 100644 --- a/chrome/browser/chrome_content_browser_client.cc +++ b/chrome/browser/chrome_content_browser_client.cc
@@ -2229,7 +2229,6 @@ extensions::switches::kAllowHTTPBackgroundPage, extensions::switches::kAllowLegacyExtensionManifests, extensions::switches::kDisableExtensionsHttpThrottling, - extensions::switches::kEnableEmbeddedExtensionOptions, extensions::switches::kEnableExperimentalExtensionApis, extensions::switches::kExtensionsOnChromeURLs, extensions::switches::kSetExtensionThrottleTestParams, // For tests only.
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn index 9b46a352..7aa9155 100644 --- a/chrome/browser/chromeos/BUILD.gn +++ b/chrome/browser/chromeos/BUILD.gn
@@ -61,6 +61,7 @@ "//chrome/browser/apps/platform_apps/api", "//chrome/browser/chromeos/kiosk_next_home/mojom", "//chrome/browser/chromeos/power/ml/smart_dim", + "//chrome/browser/chromeos/supervision/mojom", "//chrome/browser/devtools", "//chrome/browser/extensions", "//chrome/browser/resource_coordinator:tab_metrics_event_proto", @@ -1792,6 +1793,8 @@ "preferences.h", "prefs/pref_connector_service.cc", "prefs/pref_connector_service.h", + "printing/automatic_usb_printer_configurer.cc", + "printing/automatic_usb_printer_configurer.h", "printing/bulk_printers_calculator.cc", "printing/bulk_printers_calculator.h", "printing/bulk_printers_calculator_factory.cc", @@ -1930,6 +1933,8 @@ "smb_client/temp_file_manager.h", "startup_settings_cache.cc", "startup_settings_cache.h", + "supervision/onboarding_controller_impl.cc", + "supervision/onboarding_controller_impl.h", "system/automatic_reboot_manager.cc", "system/automatic_reboot_manager.h", "system/automatic_reboot_manager_observer.h", @@ -2549,6 +2554,7 @@ "power/process_data_collector_unittest.cc", "power/renderer_freezer_unittest.cc", "preferences_unittest.cc", + "printing/automatic_usb_printer_configurer_unittest.cc", "printing/bulk_printers_calculator_unittest.cc", "printing/cups_printers_manager_unittest.cc", "printing/ppd_resolution_state_unittest.cc",
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 index 128264e..ed866ed8 100644 --- 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
@@ -13,6 +13,7 @@ #include "base/feature_list.h" #include "base/metrics/histogram_macros.h" #include "base/optional.h" +#include "base/threading/thread_task_runner_handle.h" #include "chrome/browser/extensions/extension_service.h" #include "chrome/browser/extensions/extension_util.h" #include "chrome/browser/profiles/profile.h" @@ -42,6 +43,11 @@ } // namespace +// static +const base::TimeDelta AndroidSmsAppSetupControllerImpl::kInstallRetryDelay = + base::TimeDelta::FromSeconds(5); +const size_t AndroidSmsAppSetupControllerImpl::kMaxInstallRetryCount = 7u; + AndroidSmsAppSetupControllerImpl::PwaDelegate::PwaDelegate() = default; AndroidSmsAppSetupControllerImpl::PwaDelegate::~PwaDelegate() = default; @@ -218,6 +224,17 @@ return; } + TryInstallApp(install_url, app_url, 0 /* num_attempts_so_far */, + std::move(callback)); +} + +void AndroidSmsAppSetupControllerImpl::TryInstallApp(const GURL& install_url, + const GURL& app_url, + size_t num_attempts_so_far, + SuccessCallback callback) { + PA_LOG(VERBOSE) << "AndroidSmsAppSetupControllerImpl::TryInstallApp(): " + << "Trying to install PWA for " << install_url + << ". Num attempts so far # " << num_attempts_so_far; web_app::InstallOptions options(install_url, web_app::LaunchContainer::kWindow, web_app::InstallSource::kInternal); @@ -226,24 +243,44 @@ // bypass it as a workaround. options.bypass_service_worker_check = true; options.require_manifest = true; - - PA_LOG(VERBOSE) << "AndroidSmsAppSetupControllerImpl::OnSetCookieResult(): " - << "Installing PWA for " << install_url << "."; pending_app_manager_->Install( std::move(options), base::BindOnce(&AndroidSmsAppSetupControllerImpl::OnAppInstallResult, weak_ptr_factory_.GetWeakPtr(), std::move(callback), - app_url)); + num_attempts_so_far, app_url)); } void AndroidSmsAppSetupControllerImpl::OnAppInstallResult( SuccessCallback callback, + size_t num_attempts_so_far, const GURL& app_url, const GURL& install_url, web_app::InstallResultCode code) { UMA_HISTOGRAM_ENUMERATION("AndroidSms.PWAInstallationResult", code); + bool install_succeeded = + code == web_app::InstallResultCode::kSuccess || + code == web_app::InstallResultCode::kAlreadyInstalled; - if (code != web_app::InstallResultCode::kSuccess) { + if (!install_succeeded && num_attempts_so_far < kMaxInstallRetryCount) { + base::TimeDelta retry_delay = + kInstallRetryDelay * (1 << num_attempts_so_far); + PA_LOG(VERBOSE) + << "AndroidSmsAppSetupControllerImpl::OnAppInstallResult(): " + << "PWA for " << install_url << " failed to install." + << "InstallResultCode: " << static_cast<int>(code) + << " Retrying again in " << retry_delay; + base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( + FROM_HERE, + base::BindOnce(&AndroidSmsAppSetupControllerImpl::TryInstallApp, + weak_ptr_factory_.GetWeakPtr(), install_url, app_url, + num_attempts_so_far + 1, std::move(callback)), + retry_delay); + return; + } + UMA_HISTOGRAM_BOOLEAN("AndroidSms.EffectivePWAInstallationSuccess", + install_succeeded); + + if (!install_succeeded) { PA_LOG(WARNING) << "AndroidSmsAppSetupControllerImpl::OnAppInstallResult(): " << "PWA for " << install_url << " failed to install. " @@ -251,10 +288,12 @@ std::move(callback).Run(false /* success */); return; } - PA_LOG(INFO) << "AndroidSmsAppSetupControllerImpl::OnAppInstallResult(): " << "PWA for " << install_url << " was installed successfully."; + UMA_HISTOGRAM_EXACT_LINEAR("AndroidSms.NumAttemptsForSuccessfulInstallation", + num_attempts_so_far + 1, kMaxInstallRetryCount); + // Grant notification permission for the PWA. host_content_settings_map_->SetWebsiteSettingDefaultScope( app_url, GURL() /* top_level_url */,
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 index 10308d048..e532bc8 100644 --- 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
@@ -42,6 +42,11 @@ private: friend class AndroidSmsAppSetupControllerImplTest; + FRIEND_TEST_ALL_PREFIXES(AndroidSmsAppSetupControllerImplTest, + SetUpApp_Retry); + + static const base::TimeDelta kInstallRetryDelay; + static const size_t kMaxInstallRetryCount; // Thin wrapper around static PWA functions which is stubbed out for tests. class PwaDelegate { @@ -81,7 +86,13 @@ SuccessCallback callback, net::CanonicalCookie::CookieInclusionStatus status); + void TryInstallApp(const GURL& install_url, + const GURL& app_url, + size_t num_attempts_so_far, + SuccessCallback callback); + void OnAppInstallResult(SuccessCallback callback, + size_t num_attempts_so_far, const GURL& app_url, const GURL& install_url, web_app::InstallResultCode code);
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 index 329eb2f..b0df60e 100644 --- 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
@@ -182,7 +182,9 @@ }; AndroidSmsAppSetupControllerImplTest() - : host_content_settings_map_( + : thread_bundle_( + content::TestBrowserThreadBundle::MainThreadType::UI_MOCK_TIME), + host_content_settings_map_( HostContentSettingsMapFactory::GetForProfile(&profile_)) {} ~AndroidSmsAppSetupControllerImplTest() override = default; @@ -208,6 +210,72 @@ ->SetPwaDelegateForTesting(std::move(base_delegate)); } + void CallSetUpAppWithRetries(const GURL& app_url, + const GURL& install_url, + size_t num_failure_tries, + bool expected_setup_result) { + 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; + + test_pending_app_manager_->SetInstallResultCode( + web_app::InstallResultCode::kFailedUnknownReason); + + setup_controller_->SetUpApp( + app_url, install_url, + base::BindOnce(&AndroidSmsAppSetupControllerImplTest::OnSetUpAppResult, + base::Unretained(this), run_loop.QuitClosure())); + + fake_cookie_manager_->InvokePendingSetCanonicalCookieCallback( + "default_to_persist" /* expected_cookie_name */, + "true" /* expected_cookie_value */, + "https" /* expected_source_scheme */, + false /* expected_modify_http_only */, + net::CookieOptions::SameSiteCookieContext::SAME_SITE_STRICT, + true /* success */); + + fake_cookie_manager_->InvokePendingDeleteCookiesCallback( + app_url, "cros_migrated_to" /* expected_cookie_name */, + true /* success */); + + base::RunLoop().RunUntilIdle(); + + // Fast forward through remaining attempts. + for (size_t retry_count = 0; retry_count < num_failure_tries - 1; + retry_count++) { + EXPECT_NE(ContentSetting::CONTENT_SETTING_ALLOW, + GetNotificationSetting(app_url)); + EXPECT_EQ(num_install_requests_before_call + retry_count + 1u, + install_requests.size()); + EXPECT_EQ(GetInstallOptionsForUrl(install_url), install_requests.back()); + + thread_bundle_.FastForwardBy( + AndroidSmsAppSetupControllerImpl::kInstallRetryDelay * + (1 << retry_count)); + } + + // Send success code for last attempt. + test_pending_app_manager_->SetInstallResultCode( + web_app::InstallResultCode::kSuccess); + thread_bundle_.FastForwardBy( + AndroidSmsAppSetupControllerImpl::kInstallRetryDelay * + (1 << (num_failure_tries - 1))); + + if (last_set_up_app_result_ && *last_set_up_app_result_) { + histogram_tester.ExpectBucketCount( + "AndroidSms.NumAttemptsForSuccessfulInstallation", + num_failure_tries + 1, 1); + } + histogram_tester.ExpectBucketCount( + "AndroidSms.EffectivePWAInstallationSuccess", expected_setup_result, 1); + + EXPECT_EQ(last_set_up_app_result_, expected_setup_result); + last_set_up_app_result_.reset(); + } + void CallSetUpApp(const GURL& app_url, const GURL& install_url, size_t num_expected_app_installs) { @@ -250,6 +318,8 @@ histogram_tester.ExpectBucketCount("AndroidSms.PWAInstallationResult", web_app::InstallResultCode::kSuccess, num_expected_app_installs); + histogram_tester.ExpectBucketCount( + "AndroidSms.EffectivePWAInstallationSuccess", true, 1); } run_loop.Run(); @@ -392,6 +462,26 @@ CallDeleteRememberDeviceByDefaultCookie(GURL(kTestUrl1)); } +TEST_F(AndroidSmsAppSetupControllerImplTest, SetUpApp_Retry) { + // Setup should fail when all attempts fail. + CallSetUpAppWithRetries( + GURL(kTestUrl1), GURL(kTestInstallUrl1), + AndroidSmsAppSetupControllerImpl::kMaxInstallRetryCount + + 1 /* num_failure_tries*/, + false /* expected_setup_result */); + + // Setup should succeed when the last attempt succeeds. + CallSetUpAppWithRetries(GURL(kTestUrl1), GURL(kTestInstallUrl1), + AndroidSmsAppSetupControllerImpl:: + kMaxInstallRetryCount /* num_failure_tries*/, + true /* expected_setup_result */); + + // Setup should succeed when only fewer than max attempts fail. + CallSetUpAppWithRetries(GURL(kTestUrl1), GURL(kTestInstallUrl1), + 1 /* num_failure_tries*/, + true /* expected_setup_result */); +} + TEST_F(AndroidSmsAppSetupControllerImplTest, SetUpAppThenRemove) { // Install and remove. CallSetUpApp(GURL(kTestUrl1), GURL(kTestInstallUrl1),
diff --git a/chrome/browser/chromeos/login/screens/supervision_onboarding_screen_browsertest.cc b/chrome/browser/chromeos/login/screens/supervision_onboarding_screen_browsertest.cc index e9cb3b1..d58f85f 100644 --- a/chrome/browser/chromeos/login/screens/supervision_onboarding_screen_browsertest.cc +++ b/chrome/browser/chromeos/login/screens/supervision_onboarding_screen_browsertest.cc
@@ -8,6 +8,7 @@ #include <memory> #include "base/bind.h" +#include "base/command_line.h" #include "base/run_loop.h" #include "base/strings/string_piece.h" #include "base/test/scoped_feature_list.h" @@ -23,12 +24,15 @@ #include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/ui/webui/chromeos/login/supervision_onboarding_screen_handler.h" #include "chromeos/constants/chromeos_features.h" +#include "chromeos/constants/chromeos_switches.h" namespace chromeos { namespace { constexpr char kTestUser[] = "test-user1@gmail.com"; +constexpr char kTestOnboardingPageUrl[] = + "https://families.google.com/families"; chromeos::OobeUI* GetOobeUI() { auto* host = chromeos::LoginDisplayHost::default_host(); @@ -43,6 +47,10 @@ ~SupervisionOnboardingTest() override = default; void SetUpOnMainThread() override { + base::CommandLine::ForCurrentProcess()->AppendSwitchASCII( + chromeos::switches::kSupervisionOnboardingStartPageUrl, + kTestOnboardingPageUrl); + login_manager_.LoginAndWaitForActiveSession( LoginManagerMixin::CreateDefaultUserContext(test_user_));
diff --git a/chrome/browser/chromeos/printing/automatic_usb_printer_configurer.cc b/chrome/browser/chromeos/printing/automatic_usb_printer_configurer.cc new file mode 100644 index 0000000..502d2ac --- /dev/null +++ b/chrome/browser/chromeos/printing/automatic_usb_printer_configurer.cc
@@ -0,0 +1,102 @@ +// 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/printing/automatic_usb_printer_configurer.h" + +#include "base/bind.h" +#include "base/feature_list.h" +#include "base/stl_util.h" +#include "chrome/common/chrome_features.h" + +namespace chromeos { +namespace { + +bool IsInAutomaticList(const std::string& printer_id, + const std::vector<Printer>& automatic_printers) { + for (const auto& automatic_printer : automatic_printers) { + if (automatic_printer.id() == printer_id) { + return true; + } + } + return false; +} + +} // namespace + +AutomaticUsbPrinterConfigurer::AutomaticUsbPrinterConfigurer( + std::unique_ptr<PrinterConfigurer> printer_configurer, + PrinterInstallationManager* installation_manager) + : printer_configurer_(std::move(printer_configurer)), + installation_manager_(installation_manager), + weak_factory_(this) { + DCHECK(installation_manager); +} + +AutomaticUsbPrinterConfigurer::~AutomaticUsbPrinterConfigurer() = default; + +void AutomaticUsbPrinterConfigurer::OnPrintersChanged( + PrinterClass printer_class, + const std::vector<Printer>& printers) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_); + + if (!base::FeatureList::IsEnabled(features::kStreamlinedUsbPrinterSetup)) { + return; + } + + if (printer_class != PrinterClass::kAutomatic) { + return; + } + + PruneRemovedPrinters(printers); + + for (const Printer& printer : printers) { + if (!printers_.contains(printer.id()) && printer.IsUsbProtocol()) { + SetupPrinter(printer); + } + } +} + +void AutomaticUsbPrinterConfigurer::SetupPrinter(const Printer& printer) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_); + if (installation_manager_->IsPrinterInstalled(printer)) { + // Skip setup if the printer is already installed. + CompleteConfiguration(printer); + } + + printer_configurer_->SetUpPrinter( + printer, base::BindOnce(&AutomaticUsbPrinterConfigurer::OnSetupComplete, + weak_factory_.GetWeakPtr(), printer)); +} + +void AutomaticUsbPrinterConfigurer::OnSetupComplete(const Printer& printer, + PrinterSetupResult result) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_); + if (result != PrinterSetupResult::kSuccess) { + LOG(ERROR) << "Unable to autoconfigure usb printer " << printer.id(); + return; + } + installation_manager_->PrinterInstalled(printer, true /* is_automatic */); + CompleteConfiguration(printer); +} + +void AutomaticUsbPrinterConfigurer::CompleteConfiguration( + const Printer& printer) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_); + VLOG(1) << "Auto USB Printer setup successful for " << printer.id(); + + printers_.insert(printer.id()); +} + +void AutomaticUsbPrinterConfigurer::PruneRemovedPrinters( + const std::vector<Printer>& automatic_printers) { + for (auto it = printers_.begin(); it != printers_.end();) { + if (!IsInAutomaticList(*it, automatic_printers)) { + it = printers_.erase(it); + } else { + ++it; + } + } +} + +} // namespace chromeos
diff --git a/chrome/browser/chromeos/printing/automatic_usb_printer_configurer.h b/chrome/browser/chromeos/printing/automatic_usb_printer_configurer.h new file mode 100644 index 0000000..4cba590 --- /dev/null +++ b/chrome/browser/chromeos/printing/automatic_usb_printer_configurer.h
@@ -0,0 +1,66 @@ +// 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_PRINTING_AUTOMATIC_USB_PRINTER_CONFIGURER_H_ +#define CHROME_BROWSER_CHROMEOS_PRINTING_AUTOMATIC_USB_PRINTER_CONFIGURER_H_ + +#include <memory> +#include <vector> + +#include "base/containers/flat_set.h" +#include "base/macros.h" +#include "base/memory/weak_ptr.h" +#include "base/sequence_checker.h" +#include "chrome/browser/chromeos/printing/cups_printers_manager.h" +#include "chrome/browser/chromeos/printing/printer_configurer.h" +#include "chrome/browser/chromeos/printing/printer_installation_manager.h" +#include "chromeos/printing/printer_configuration.h" + +namespace chromeos { + +class AutomaticUsbPrinterConfigurer : public CupsPrintersManager::Observer { + public: + AutomaticUsbPrinterConfigurer( + std::unique_ptr<PrinterConfigurer> printer_configurer_, + PrinterInstallationManager* installation_manager); + + ~AutomaticUsbPrinterConfigurer() override; + + // CupsPrintersManager::Observer override. + void OnPrintersChanged(PrinterClass printer_class, + const std::vector<Printer>& printers) override; + + private: + FRIEND_TEST_ALL_PREFIXES(AutomaticUsbPrinterConfigurerTest, + UsbPrinterAddedToSet); + FRIEND_TEST_ALL_PREFIXES(AutomaticUsbPrinterConfigurerTest, + UsbPrinterRemovedFromSet); + + // Uses |printer_configurer_| to setup |printer| if it is not yet setup. + void SetupPrinter(const Printer& printer); + + // Callback for PrinterConfiguer::SetUpPrinter(). + void OnSetupComplete(const Printer& printer, PrinterSetupResult result); + + // Completes the configuration for |printer|. Saves printer in |printers_|. + void CompleteConfiguration(const Printer& printer); + + // Removes any printers from |printers_| that are no longer in + // |automatic_printers|. + void PruneRemovedPrinters(const std::vector<Printer>& automatic_printers); + + SEQUENCE_CHECKER(sequence_); + + std::unique_ptr<PrinterConfigurer> printer_configurer_; + PrinterInstallationManager* installation_manager_; // Not owned. + base::flat_set<std::string> printers_; + + base::WeakPtrFactory<AutomaticUsbPrinterConfigurer> weak_factory_; + + DISALLOW_COPY_AND_ASSIGN(AutomaticUsbPrinterConfigurer); +}; + +} // namespace chromeos + +#endif // CHROME_BROWSER_CHROMEOS_PRINTING_AUTOMATIC_USB_PRINTER_CONFIGURER_H_
diff --git a/chrome/browser/chromeos/printing/automatic_usb_printer_configurer_unittest.cc b/chrome/browser/chromeos/printing/automatic_usb_printer_configurer_unittest.cc new file mode 100644 index 0000000..5b02ab8e --- /dev/null +++ b/chrome/browser/chromeos/printing/automatic_usb_printer_configurer_unittest.cc
@@ -0,0 +1,253 @@ +// 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/printing/automatic_usb_printer_configurer.h" + +#include <string> +#include <vector> + +#include "base/containers/flat_set.h" +#include "base/optional.h" +#include "base/test/scoped_feature_list.h" +#include "chrome/browser/chromeos/printing/cups_printers_manager.h" +#include "chrome/browser/chromeos/printing/printers_map.h" +#include "chrome/common/chrome_features.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace chromeos { +namespace { + +Printer CreateUsbPrinter(const std::string& id) { + Printer printer; + printer.set_id(id); + printer.set_uri("usb:printer"); + return printer; +} + +Printer CreateIppUsbPrinter(const std::string& id) { + Printer printer; + printer.set_id(id); + printer.set_uri("ippusb:printer"); + return printer; +} + +Printer CreateIppPrinter(const std::string& id) { + Printer printer; + printer.set_id(id); + printer.set_uri("ipp:printer"); + return printer; +} + +} // namespace + +// Provides a mechanism to interact with AutomaticPrinterConfigurer. +// Adding a printer causes the observer's OnPrintersChanged() method to run. +class FakeObservablePrintersManager { + public: + void SetObserver(CupsPrintersManager::Observer* observer) { + DCHECK(observer); + observer_ = observer; + } + + // Simulates a nearby kAutomatic printer. + void AddNearbyAutomaticPrinter(const Printer& printer) { + AddPrinter(PrinterClass::kAutomatic, printer); + } + + // Simulates a nearby kDiscovered printer. + void AddNearbyDiscoveredPrinter(const Printer& printer) { + AddPrinter(PrinterClass::kDiscovered, printer); + } + + void RemoveAutomaticPrinter(const std::string& printer_id) { + RemovePrinter(PrinterClass::kAutomatic, printer_id); + } + + private: + // Add |printer| to the corresponding list in |printers_| bases on the given + // |printer_class|. + void AddPrinter(PrinterClass printer_class, const Printer& printer) { + printers_.Insert(printer_class, printer); + observer_->OnPrintersChanged(printer_class, printers_.Get(printer_class)); + } + + // Remove |printer_id| from |printer_class|. + void RemovePrinter(PrinterClass printer_class, + const std::string& printer_id) { + printers_.Remove(PrinterClass::kAutomatic, printer_id); + observer_->OnPrintersChanged(printer_class, printers_.Get(printer_class)); + } + + CupsPrintersManager::Observer* observer_; + PrintersMap printers_; +}; + +class FakePrinterInstallationManager : public PrinterInstallationManager { + public: + FakePrinterInstallationManager() = default; + ~FakePrinterInstallationManager() override = default; + + // CupsPrintersManager overrides + void PrinterInstalled(const Printer& printer, bool is_automatic) override { + DCHECK(is_automatic); + + installed_printers_.insert(printer.id()); + } + + bool IsPrinterInstalled(const Printer& printer) const override { + return installed_printers_.contains(printer.id()); + } + + private: + base::flat_set<std::string> installed_printers_; +}; + +class FakePrinterConfigurer : public PrinterConfigurer { + public: + FakePrinterConfigurer() = default; + + // PrinterConfigurer overrides + void SetUpPrinter(const Printer& printer, + PrinterSetupCallback callback) override { + MarkConfigured(printer.id()); + std::move(callback).Run(PrinterSetupResult::kSuccess); + } + + // Manipulation functions + bool IsConfigured(const std::string& printer_id) const { + return configured_.contains(printer_id); + } + + void MarkConfigured(const std::string& printer_id) { + configured_.insert(printer_id); + } + + private: + base::flat_set<std::string> configured_; +}; + +class AutomaticUsbPrinterConfigurerTest : public testing::Test { + public: + AutomaticUsbPrinterConfigurerTest() { + scoped_feature_list_.InitAndEnableFeature( + features::kStreamlinedUsbPrinterSetup); + fake_installation_manager_ = + std::make_unique<FakePrinterInstallationManager>(); + auto printer_configurer = std::make_unique<FakePrinterConfigurer>(); + fake_printer_configurer_ = printer_configurer.get(); + + auto_usb_printer_configurer_ = + std::make_unique<AutomaticUsbPrinterConfigurer>( + std::move(printer_configurer), fake_installation_manager_.get()); + + fake_observable_printers_manager_.SetObserver( + auto_usb_printer_configurer_.get()); + } + + ~AutomaticUsbPrinterConfigurerTest() override = default; + + protected: + FakeObservablePrintersManager fake_observable_printers_manager_; + FakePrinterConfigurer* fake_printer_configurer_; // not owned. + std::unique_ptr<FakePrinterInstallationManager> fake_installation_manager_; + std::unique_ptr<AutomaticUsbPrinterConfigurer> auto_usb_printer_configurer_; + + private: + base::test::ScopedFeatureList scoped_feature_list_; + + DISALLOW_COPY_AND_ASSIGN(AutomaticUsbPrinterConfigurerTest); +}; + +TEST_F(AutomaticUsbPrinterConfigurerTest, + AutoUsbPrinterInstalledAutomatically) { + const std::string printer_id = "id"; + const Printer printer = CreateUsbPrinter(printer_id); + + // Adding an automatic USB printer should result in the printer becoming + // configured and getting marked as installed. + fake_observable_printers_manager_.AddNearbyAutomaticPrinter(printer); + + EXPECT_TRUE(fake_installation_manager_->IsPrinterInstalled(printer)); + EXPECT_TRUE(fake_printer_configurer_->IsConfigured(printer_id)); +} + +TEST_F(AutomaticUsbPrinterConfigurerTest, + AutoIppUsbPrinterInstalledAutomatically) { + const std::string printer_id = "id"; + const Printer printer = CreateIppUsbPrinter(printer_id); + + // Adding an automatic IPPUSB printer should result in the printer becoming + // configured and getting marked as installed. + fake_observable_printers_manager_.AddNearbyAutomaticPrinter(printer); + + EXPECT_TRUE(fake_installation_manager_->IsPrinterInstalled(printer)); + EXPECT_TRUE(fake_printer_configurer_->IsConfigured(printer_id)); +} + +TEST_F(AutomaticUsbPrinterConfigurerTest, AutoIppPrinterNotInstalled) { + const std::string printer_id = "id"; + const Printer printer = CreateIppPrinter(printer_id); + + // Adding an automatic Ipp printer should *not* result in the printer becoming + // configured and getting marked as installed. + fake_observable_printers_manager_.AddNearbyAutomaticPrinter(printer); + + EXPECT_FALSE(fake_installation_manager_->IsPrinterInstalled(printer)); + EXPECT_FALSE(fake_printer_configurer_->IsConfigured(printer_id)); +} + +TEST_F(AutomaticUsbPrinterConfigurerTest, DiscoveredUsbPrinterNotInstalled) { + const std::string printer_id = "id"; + const Printer printer = CreateUsbPrinter(printer_id); + + // Adding an automatic USB printer should result in the printer becoming + // configured and getting marked as installed. + fake_observable_printers_manager_.AddNearbyDiscoveredPrinter(printer); + + EXPECT_FALSE(fake_installation_manager_->IsPrinterInstalled(printer)); + EXPECT_FALSE(fake_printer_configurer_->IsConfigured(printer_id)); +} + +TEST_F(AutomaticUsbPrinterConfigurerTest, + ConfiguredAutoUsbPrinterGetsInstalled) { + const std::string printer_id = "id"; + const Printer printer = CreateUsbPrinter(printer_id); + + fake_printer_configurer_->MarkConfigured(printer_id); + + // Adding an automatic USB printer that's already configured should still + // result in the printer getting marked as installed. + fake_observable_printers_manager_.AddNearbyAutomaticPrinter(printer); + + EXPECT_TRUE(fake_installation_manager_->IsPrinterInstalled(printer)); +} + +TEST_F(AutomaticUsbPrinterConfigurerTest, UsbPrinterAddedToSet) { + const std::string printer_id = "id"; + const Printer printer = CreateUsbPrinter(printer_id); + + // Adding an automatic USB printer should result in the printer getting added + // to |auto_usb_printer_configurer_::printers_|. + fake_observable_printers_manager_.AddNearbyAutomaticPrinter(printer); + + EXPECT_EQ(1u, auto_usb_printer_configurer_->printers_.size()); + EXPECT_TRUE(auto_usb_printer_configurer_->printers_.contains(printer_id)); +} + +TEST_F(AutomaticUsbPrinterConfigurerTest, UsbPrinterRemovedFromSet) { + const std::string printer_id = "id"; + const Printer printer = CreateUsbPrinter(printer_id); + + fake_observable_printers_manager_.AddNearbyAutomaticPrinter(printer); + + EXPECT_EQ(1u, auto_usb_printer_configurer_->printers_.size()); + + // Removing the automatic printer should result in the printer getting + // removed from |auto_usb_printer_configurer_::printers_|. + fake_observable_printers_manager_.RemoveAutomaticPrinter(printer_id); + + EXPECT_EQ(0u, auto_usb_printer_configurer_->printers_.size()); +} + +} // namespace chromeos
diff --git a/chrome/browser/chromeos/printing/cups_printers_manager.cc b/chrome/browser/chromeos/printing/cups_printers_manager.cc index 58755e46..ded2bcae 100644 --- a/chrome/browser/chromeos/printing/cups_printers_manager.cc +++ b/chrome/browser/chromeos/printing/cups_printers_manager.cc
@@ -18,6 +18,7 @@ #include "base/scoped_observer.h" #include "base/sequence_checker.h" #include "base/strings/stringprintf.h" +#include "chrome/browser/chromeos/printing/automatic_usb_printer_configurer.h" #include "chrome/browser/chromeos/printing/ppd_provider_factory.h" #include "chrome/browser/chromeos/printing/ppd_resolution_tracker.h" #include "chrome/browser/chromeos/printing/printer_configurer.h" @@ -51,6 +52,7 @@ std::unique_ptr<PrinterDetector> usb_detector, std::unique_ptr<PrinterDetector> zeroconf_detector, scoped_refptr<PpdProvider> ppd_provider, + std::unique_ptr<PrinterConfigurer> printer_configurer, PrinterEventTracker* event_tracker, PrefService* pref_service) : synced_printers_manager_(synced_printers_manager), @@ -58,8 +60,12 @@ usb_detector_(std::move(usb_detector)), zeroconf_detector_(std::move(zeroconf_detector)), ppd_provider_(std::move(ppd_provider)), + auto_usb_printer_configurer_(std::move(printer_configurer), this), event_tracker_(event_tracker), weak_ptr_factory_(this) { + // Add the |auto_usb_printer_configurer_| as an observer. + AddObserver(&auto_usb_printer_configurer_); + // Prime the printer cache with the saved and enterprise printers. printers_.ReplacePrintersInClass( PrinterClass::kSaved, synced_printers_manager_->GetSavedPrinters()); @@ -448,6 +454,8 @@ scoped_refptr<PpdProvider> ppd_provider_; + AutomaticUsbPrinterConfigurer auto_usb_printer_configurer_; + // Not owned PrinterEventTracker* const event_tracker_; @@ -487,7 +495,7 @@ SyncedPrintersManagerFactory::GetInstance()->GetForBrowserContext( profile), UsbPrinterDetector::Create(), ZeroconfPrinterDetector::Create(), - CreatePpdProvider(profile), + CreatePpdProvider(profile), PrinterConfigurer::Create(profile), PrinterEventTrackerFactory::GetInstance()->GetForBrowserContext(profile), profile->GetPrefs()); } @@ -498,12 +506,13 @@ std::unique_ptr<PrinterDetector> usb_detector, std::unique_ptr<PrinterDetector> zeroconf_detector, scoped_refptr<PpdProvider> ppd_provider, + std::unique_ptr<PrinterConfigurer> printer_configurer, PrinterEventTracker* event_tracker, PrefService* pref_service) { return std::make_unique<CupsPrintersManagerImpl>( synced_printers_manager, std::move(usb_detector), - std::move(zeroconf_detector), std::move(ppd_provider), event_tracker, - pref_service); + std::move(zeroconf_detector), std::move(ppd_provider), + std::move(printer_configurer), event_tracker, pref_service); } // static
diff --git a/chrome/browser/chromeos/printing/cups_printers_manager.h b/chrome/browser/chromeos/printing/cups_printers_manager.h index c549f55..7d4228a 100644 --- a/chrome/browser/chromeos/printing/cups_printers_manager.h +++ b/chrome/browser/chromeos/printing/cups_printers_manager.h
@@ -24,6 +24,7 @@ namespace chromeos { class PpdProvider; +class PrinterConfigurer; class PrinterDetector; class PrinterEventTracker; class SyncedPrintersManager; @@ -57,6 +58,7 @@ std::unique_ptr<PrinterDetector> usb_printer_detector, std::unique_ptr<PrinterDetector> zeroconf_printer_detector, scoped_refptr<PpdProvider> ppd_provider, + std::unique_ptr<PrinterConfigurer> printer_configurer, PrinterEventTracker* event_tracker, PrefService* pref_service);
diff --git a/chrome/browser/chromeos/printing/cups_printers_manager_unittest.cc b/chrome/browser/chromeos/printing/cups_printers_manager_unittest.cc index 844b5272..943d171 100644 --- a/chrome/browser/chromeos/printing/cups_printers_manager_unittest.cc +++ b/chrome/browser/chromeos/printing/cups_printers_manager_unittest.cc
@@ -13,12 +13,16 @@ #include "base/bind.h" #include "base/bind_helpers.h" #include "base/containers/flat_map.h" +#include "base/containers/flat_set.h" #include "base/sequenced_task_runner.h" +#include "base/test/scoped_feature_list.h" #include "base/test/scoped_task_environment.h" #include "base/threading/sequenced_task_runner_handle.h" +#include "chrome/browser/chromeos/printing/printer_configurer.h" #include "chrome/browser/chromeos/printing/printers_map.h" #include "chrome/browser/chromeos/printing/synced_printers_manager.h" #include "chrome/browser/chromeos/printing/usb_printer_detector.h" +#include "chrome/common/chrome_features.h" #include "chrome/common/pref_names.h" #include "components/sync_preferences/testing_pref_service_syncable.h" #include "testing/gtest/include/gtest/gtest.h" @@ -266,24 +270,52 @@ EXPECT_EQ(sorted_ids, found_ids); } +class FakePrinterConfigurer : public PrinterConfigurer { + public: + FakePrinterConfigurer() = default; + + // PrinterConfigurer overrides + void SetUpPrinter(const Printer& printer, + PrinterSetupCallback callback) override { + MarkConfigured(printer.id()); + std::move(callback).Run(PrinterSetupResult::kSuccess); + } + + // Manipulation functions + bool IsConfigured(const std::string& printer_id) const { + return configured_.contains(printer_id); + } + + void MarkConfigured(const std::string& printer_id) { + configured_.insert(printer_id); + } + + private: + base::flat_set<std::string> configured_; +}; + class CupsPrintersManagerTest : public testing::Test, public CupsPrintersManager::Observer { public: CupsPrintersManagerTest() : ppd_provider_(new FakePpdProvider) { + scoped_feature_list_.InitAndEnableFeature( + features::kStreamlinedUsbPrinterSetup); // Zeroconf and usb detector ownerships are taken by the manager, so we have // to keep raw pointers to them. auto zeroconf_detector = std::make_unique<FakePrinterDetector>(); zeroconf_detector_ = zeroconf_detector.get(); auto usb_detector = std::make_unique<FakePrinterDetector>(); usb_detector_ = usb_detector.get(); + auto printer_configurer = std::make_unique<FakePrinterConfigurer>(); + printer_configurer_ = printer_configurer.get(); // Register the pref |UserNativePrintersAllowed| CupsPrintersManager::RegisterProfilePrefs(pref_service_.registry()); manager_ = CupsPrintersManager::CreateForTesting( &synced_printers_manager_, std::move(usb_detector), - std::move(zeroconf_detector), ppd_provider_, &event_tracker_, - &pref_service_); + std::move(zeroconf_detector), ppd_provider_, + std::move(printer_configurer), &event_tracker_, &pref_service_); manager_->AddObserver(this); } @@ -312,14 +344,16 @@ protected: base::test::ScopedTaskEnvironment scoped_task_environment_; + base::test::ScopedFeatureList scoped_feature_list_; // Captured printer lists from observer callbacks. base::flat_map<PrinterClass, std::vector<Printer>> observed_printers_; // Backend fakes driving the CupsPrintersManager. FakeSyncedPrintersManager synced_printers_manager_; - FakePrinterDetector* usb_detector_; - FakePrinterDetector* zeroconf_detector_; + FakePrinterDetector* usb_detector_; // Not owned. + FakePrinterDetector* zeroconf_detector_; // Not owned. + FakePrinterConfigurer* printer_configurer_; // Not owned. scoped_refptr<FakePpdProvider> ppd_provider_; // This is unused, it's just here for memory ownership. @@ -721,5 +755,51 @@ EXPECT_FALSE(manager_->IsPrinterInstalled(updated)); } +// Automatic USB Printer is configured automatically. +TEST_F(CupsPrintersManagerTest, AutomaticUsbPrinterIsInstalledAutomatically) { + auto automatic_printer = MakeAutomaticPrinter(kPrinterId); + automatic_printer.printer.set_uri("usb:"); + + usb_detector_->AddDetections({automatic_printer}); + + scoped_task_environment_.RunUntilIdle(); + + EXPECT_TRUE(printer_configurer_->IsConfigured(kPrinterId)); +} + +// Automatic USB Printer is *not* configured if |UserNativePrintersAllowed| +// pref is set to false. +TEST_F(CupsPrintersManagerTest, AutomaticUsbPrinterNotInstalledAutomatically) { + // Disable the use of non-enterprise printers. + UpdatePolicyValue(prefs::kUserNativePrintersAllowed, false); + + auto automatic_printer = MakeAutomaticPrinter(kPrinterId); + automatic_printer.printer.set_uri("usb:"); + + zeroconf_detector_->AddDetections({automatic_printer}); + + scoped_task_environment_.RunUntilIdle(); + + EXPECT_FALSE(manager_->IsPrinterInstalled(automatic_printer.printer)); +} + +// Nearby printers that are not automatic & USB are not automatically +// installed. +TEST_F(CupsPrintersManagerTest, OtherNearbyPrintersNotInstalledAutomatically) { + auto discovered_printer = MakeDiscoveredPrinter("Discovered"); + discovered_printer.printer.set_uri("usb:"); + auto automatic_printer = MakeAutomaticPrinter("Automatic"); + + usb_detector_->AddDetections({discovered_printer}); + zeroconf_detector_->AddDetections({automatic_printer}); + + scoped_task_environment_.RunUntilIdle(); + + ExpectPrintersInClassAre(PrinterClass::kDiscovered, {"Discovered"}); + ExpectPrintersInClassAre(PrinterClass::kAutomatic, {"Automatic"}); + EXPECT_FALSE(printer_configurer_->IsConfigured("Discovered")); + EXPECT_FALSE(printer_configurer_->IsConfigured("Automatic")); +} + } // namespace } // namespace chromeos
diff --git a/chrome/browser/chromeos/supervision/OWNERS b/chrome/browser/chromeos/supervision/OWNERS new file mode 100644 index 0000000..235390c5 --- /dev/null +++ b/chrome/browser/chromeos/supervision/OWNERS
@@ -0,0 +1,5 @@ +agawronska@chromium.org +brunoad@chromium.org +hgrandinetti@chromium.org +ltenorio@chromium.org +michaelpg@chromium.org
diff --git a/chrome/browser/chromeos/supervision/mojom/BUILD.gn b/chrome/browser/chromeos/supervision/mojom/BUILD.gn new file mode 100644 index 0000000..59ed51f5 --- /dev/null +++ b/chrome/browser/chromeos/supervision/mojom/BUILD.gn
@@ -0,0 +1,11 @@ +# Copyright 2019 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//mojo/public/tools/bindings/mojom.gni") + +mojom("mojom") { + sources = [ + "onboarding_controller.mojom", + ] +}
diff --git a/chrome/browser/chromeos/supervision/mojom/OWNERS b/chrome/browser/chromeos/supervision/mojom/OWNERS new file mode 100644 index 0000000..08850f4 --- /dev/null +++ b/chrome/browser/chromeos/supervision/mojom/OWNERS
@@ -0,0 +1,2 @@ +per-file *.mojom=set noparent +per-file *.mojom=file://ipc/SECURITY_OWNERS
diff --git a/chrome/browser/chromeos/supervision/mojom/onboarding_controller.mojom b/chrome/browser/chromeos/supervision/mojom/onboarding_controller.mojom new file mode 100644 index 0000000..6b3317e --- /dev/null +++ b/chrome/browser/chromeos/supervision/mojom/onboarding_controller.mojom
@@ -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. + +module chromeos.supervision.mojom; + +// Represents user actions that the OnboardingController can handle. +enum OnboardingFlowAction { + // The user has expressed intent to skip the remaining screens of the flow. + // When receiving this we will most likely perform cleanup functions and + // order the WebviewHost to exit the flow. + kSkipFlow, + + // The user wants to go back/forward in the flow. + kShowNextPage, + kShowPreviousPage, +}; + + +// Represents a webview host, responsible for displaying supervision +// onboarding pages. This will usually be a WebUI page that contains a +// webview tag and manages its properties. +// TODO(958995): Complete this interface. +interface OnboardingWebviewHost { + // Requests that the webview load the page with the given url. + LoadPage(string url); + + // Requests that the host exit the flow immediately. This might mean + // different things depending on the type of host. If we are running in the + // OOBE we will exit the supervision screen and move the the next OOBE step, + // if we are running in a custom WebUI, we should close it. + ExitFlow(); +}; + +// Interface responsible for managing the whole onboarding flow. +// TODO(958995): Complete this interface. +interface OnboardingController { + // Binds the given webview host to this controller. The host will start + // receiving commands as soon as this is called. + BindWebviewHost(OnboardingWebviewHost webview_host); + + // Requests the controller to handle the given action. + // The controller will decide the next step to continue/end the flow. + HandleAction(OnboardingFlowAction action); +};
diff --git a/chrome/browser/chromeos/supervision/onboarding_controller_impl.cc b/chrome/browser/chromeos/supervision/onboarding_controller_impl.cc new file mode 100644 index 0000000..f3c70a53 --- /dev/null +++ b/chrome/browser/chromeos/supervision/onboarding_controller_impl.cc
@@ -0,0 +1,51 @@ +// 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/supervision/onboarding_controller_impl.h" + +#include "base/command_line.h" +#include "base/logging.h" +#include "chromeos/constants/chromeos_switches.h" + +namespace chromeos { +namespace supervision { + +OnboardingControllerImpl::OnboardingControllerImpl() = default; +OnboardingControllerImpl::~OnboardingControllerImpl() = default; + +void OnboardingControllerImpl::BindRequest( + mojom::OnboardingControllerRequest request) { + bindings_.AddBinding(this, std::move(request)); +} + +void OnboardingControllerImpl::BindWebviewHost( + mojom::OnboardingWebviewHostPtr webview_host) { + webview_host_ = std::move(webview_host); + + std::string start_page_url = + base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( + chromeos::switches::kSupervisionOnboardingStartPageUrl); + if (start_page_url.empty()) { + webview_host_->ExitFlow(); + return; + } + + webview_host_->LoadPage(start_page_url); +} + +void OnboardingControllerImpl::HandleAction( + mojom::OnboardingFlowAction action) { + DCHECK(webview_host_); + switch (action) { + // TODO(958985): Implement the full flow state machine. + case mojom::OnboardingFlowAction::kSkipFlow: + case mojom::OnboardingFlowAction::kShowNextPage: + case mojom::OnboardingFlowAction::kShowPreviousPage: + webview_host_->ExitFlow(); + return; + } +} + +} // namespace supervision +} // namespace chromeos
diff --git a/chrome/browser/chromeos/supervision/onboarding_controller_impl.h b/chrome/browser/chromeos/supervision/onboarding_controller_impl.h new file mode 100644 index 0000000..c8c3418 --- /dev/null +++ b/chrome/browser/chromeos/supervision/onboarding_controller_impl.h
@@ -0,0 +1,39 @@ +// 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_SUPERVISION_ONBOARDING_CONTROLLER_IMPL_H_ +#define CHROME_BROWSER_CHROMEOS_SUPERVISION_ONBOARDING_CONTROLLER_IMPL_H_ + +#include <string> +#include <vector> + +#include "base/macros.h" +#include "chrome/browser/chromeos/supervision/mojom/onboarding_controller.mojom.h" +#include "mojo/public/cpp/bindings/binding_set.h" + +namespace chromeos { +namespace supervision { + +class OnboardingControllerImpl : public mojom::OnboardingController { + public: + OnboardingControllerImpl(); + ~OnboardingControllerImpl() override; + + void BindRequest(mojom::OnboardingControllerRequest request); + + private: + // mojom::OnboardingController: + void BindWebviewHost(mojom::OnboardingWebviewHostPtr webview_host) override; + void HandleAction(mojom::OnboardingFlowAction action) override; + + mojom::OnboardingWebviewHostPtr webview_host_; + mojo::BindingSet<mojom::OnboardingController> bindings_; + + DISALLOW_COPY_AND_ASSIGN(OnboardingControllerImpl); +}; + +} // namespace supervision +} // namespace chromeos + +#endif // CHROME_BROWSER_CHROMEOS_SUPERVISION_ONBOARDING_CONTROLLER_IMPL_H_
diff --git a/chrome/browser/download/chrome_download_manager_delegate.cc b/chrome/browser/download/chrome_download_manager_delegate.cc index b128f79..ecd78503 100644 --- a/chrome/browser/download/chrome_download_manager_delegate.cc +++ b/chrome/browser/download/chrome_download_manager_delegate.cc
@@ -791,6 +791,15 @@ return nullptr; } +void ChromeDownloadManagerDelegate::ShouldBlockDownload( + download::DownloadItem* download, + const base::FilePath& virtual_path, + const ShouldBlockDownloadCallback& callback) { + // TODO(https://crbug.com/960819): Block insecure downloads in secure contexts + // as mixed content. + callback.Run(false); +} + void ChromeDownloadManagerDelegate::NotifyExtensions( DownloadItem* download, const base::FilePath& virtual_path,
diff --git a/chrome/browser/download/chrome_download_manager_delegate.h b/chrome/browser/download/chrome_download_manager_delegate.h index 25ccaf6..e34a0af2 100644 --- a/chrome/browser/download/chrome_download_manager_delegate.h +++ b/chrome/browser/download/chrome_download_manager_delegate.h
@@ -144,6 +144,10 @@ const DownloadTargetDeterminerDelegate::ConfirmationCallback& callback); // DownloadTargetDeterminerDelegate. Protected for testing. + void ShouldBlockDownload( + download::DownloadItem* download, + const base::FilePath& virtual_path, + const ShouldBlockDownloadCallback& callback) override; void NotifyExtensions(download::DownloadItem* download, const base::FilePath& suggested_virtual_path, const NotifyExtensionsCallback& callback) override;
diff --git a/chrome/browser/download/download_target_determiner.cc b/chrome/browser/download/download_target_determiner.cc index 010f951..1f85663 100644 --- a/chrome/browser/download/download_target_determiner.cc +++ b/chrome/browser/download/download_target_determiner.cc
@@ -142,6 +142,9 @@ case STATE_GENERATE_TARGET_PATH: result = DoGenerateTargetPath(); break; + case STATE_CHECK_IF_DOWNLOAD_BLOCKED: + result = DoCheckIfDownloadBlocked(); + break; case STATE_NOTIFY_EXTENSIONS: result = DoNotifyExtensions(); break; @@ -193,7 +196,7 @@ DCHECK(!should_notify_extensions_); bool is_forced_path = !download_->GetForcedFilePath().empty(); - next_state_ = STATE_NOTIFY_EXTENSIONS; + next_state_ = STATE_CHECK_IF_DOWNLOAD_BLOCKED; // Transient download should use the existing path. if (download_->IsTransient()) { @@ -308,6 +311,35 @@ } DownloadTargetDeterminer::Result +DownloadTargetDeterminer::DoCheckIfDownloadBlocked() { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + DCHECK(!virtual_path_.empty()); + + next_state_ = STATE_NOTIFY_EXTENSIONS; + + delegate_->ShouldBlockDownload( + download_, virtual_path_, + base::Bind(&DownloadTargetDeterminer::CheckIfDownloadBlockedDone, + weak_ptr_factory_.GetWeakPtr())); + return QUIT_DOLOOP; +} + +void DownloadTargetDeterminer::CheckIfDownloadBlockedDone(bool should_block) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + + // Delegate should not call back here more than once. + DCHECK_EQ(STATE_NOTIFY_EXTENSIONS, next_state_); + + if (should_block) { + ScheduleCallbackAndDeleteSelf( + download::DOWNLOAD_INTERRUPT_REASON_USER_CANCELED); + return; + } + + DoLoop(); +} + +DownloadTargetDeterminer::Result DownloadTargetDeterminer::DoNotifyExtensions() { DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK(!virtual_path_.empty());
diff --git a/chrome/browser/download/download_target_determiner.h b/chrome/browser/download/download_target_determiner.h index 7ede9b1d..ba41b15f 100644 --- a/chrome/browser/download/download_target_determiner.h +++ b/chrome/browser/download/download_target_determiner.h
@@ -97,6 +97,7 @@ // handler returns COMPLETE. enum State { STATE_GENERATE_TARGET_PATH, + STATE_CHECK_IF_DOWNLOAD_BLOCKED, STATE_NOTIFY_EXTENSIONS, STATE_RESERVE_VIRTUAL_PATH, STATE_PROMPT_USER_FOR_DOWNLOAD_PATH, @@ -158,9 +159,21 @@ // the download item. // Next state: // - STATE_NONE : If the download is not in progress, returns COMPLETE. - // - STATE_NOTIFY_EXTENSIONS : All other downloads. + // - STATE_CHECK_IF_DOWNLOAD_BLOCKED : All other downloads. Result DoGenerateTargetPath(); + // Determines whether the download ought to be blocked before a user is + // prompted for file path. Used for active mixed content blocking. This + // function relies on the delegate for the actual determination. + // + // Next state: + // - STATE_NOTIFY_EXTENSIONS + Result DoCheckIfDownloadBlocked(); + + // Callback invoked by delegate after blocking is determined. Does the actual + // cancellation of the download if necessary. + void CheckIfDownloadBlockedDone(bool should_block); + // Notifies downloads extensions. If any extension wishes to override the // download filename, it will respond to the OnDeterminingFilename() // notification.
diff --git a/chrome/browser/download/download_target_determiner_delegate.h b/chrome/browser/download/download_target_determiner_delegate.h index 77ddced..64b7ae24 100644 --- a/chrome/browser/download/download_target_determiner_delegate.h +++ b/chrome/browser/download/download_target_determiner_delegate.h
@@ -25,6 +25,10 @@ // DownloadTargetDeterminer and is expected to outlive it. class DownloadTargetDeterminerDelegate { public: + // Callback to be invoked after ShouldBlockDownload() completes. The + // |should_block| bool represents whether the download should be aborted. + typedef base::Callback<void(bool should_block)> ShouldBlockDownloadCallback; + // Callback to be invoked after NotifyExtensions() completes. The // |new_virtual_path| should be set to a new path if an extension wishes to // override the download path. |conflict_action| should be set to the action @@ -67,6 +71,14 @@ // determined, it should be set to the empty string. typedef base::Callback<void(const std::string&)> GetFileMimeTypeCallback; + // Checks whether the download should be blocked based on data available + // such as filename. Functionality used for active content blocking, not Safe + // Browsing. + virtual void ShouldBlockDownload( + download::DownloadItem* download, + const base::FilePath& virtual_path, + const ShouldBlockDownloadCallback& callback) = 0; + // Notifies extensions of the impending filename determination. |virtual_path| // is the current suggested virtual path. The |callback| should be invoked to // indicate whether any extensions wish to override the path.
diff --git a/chrome/browser/download/download_target_determiner_unittest.cc b/chrome/browser/download/download_target_determiner_unittest.cc index b09367b..01ce4d5f 100644 --- a/chrome/browser/download/download_target_determiner_unittest.cc +++ b/chrome/browser/download/download_target_determiner_unittest.cc
@@ -177,6 +177,10 @@ class MockDownloadTargetDeterminerDelegate : public DownloadTargetDeterminerDelegate { public: + MOCK_METHOD3(ShouldBlockDownload, + void(download::DownloadItem*, + const base::FilePath&, + const ShouldBlockDownloadCallback&)); MOCK_METHOD3(CheckDownloadUrl, void(download::DownloadItem*, const base::FilePath&, @@ -202,6 +206,8 @@ const GetFileMimeTypeCallback&)); void SetupDefaults() { + ON_CALL(*this, ShouldBlockDownload(_, _, _)) + .WillByDefault(WithArg<2>(ScheduleCallback(false))); ON_CALL(*this, CheckDownloadUrl(_, _, _)) .WillByDefault(WithArg<2>( ScheduleCallback(download::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS))); @@ -1487,6 +1493,21 @@ base::size(kManagedPathTestCases)); } +// Test basic blocking functionality via ShouldBlockDownloads. +TEST_F(DownloadTargetDeterminerTest, BlockDownloads) { + const DownloadTestCase kBlockDownloadsTestCases[] = { + {AUTOMATIC, download::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, + DownloadFileType::NOT_DANGEROUS, "http://example.com/foo.txt", "", + FILE_PATH_LITERAL(""), FILE_PATH_LITERAL(""), + DownloadItem::TARGET_DISPOSITION_OVERWRITE, EXPECT_EMPTY}, + }; + + ON_CALL(*delegate(), ShouldBlockDownload(_, _, _)) + .WillByDefault(WithArg<2>(ScheduleCallback(true))); + RunTestCasesWithActiveItem(kBlockDownloadsTestCases, + base::size(kBlockDownloadsTestCases)); +} + // Test basic functionality supporting extensions that want to override download // filenames. TEST_F(DownloadTargetDeterminerTest, NotifyExtensionsSafe) {
diff --git a/chrome/browser/enterprise_reporting/prefs.cc b/chrome/browser/enterprise_reporting/prefs.cc new file mode 100644 index 0000000..abe7abc --- /dev/null +++ b/chrome/browser/enterprise_reporting/prefs.cc
@@ -0,0 +1,26 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/enterprise_reporting/prefs.h" + +#include "base/feature_list.h" +#include "chrome/common/chrome_features.h" +#include "chrome/common/pref_names.h" + +namespace enterprise_reporting { + +const char kLastUploadTimestamp[] = + "enterprise_reporting.last_upload_timestamp"; + +void RegisterPrefs(PrefRegistrySimple* registry) { + if (!base::FeatureList::IsEnabled(features::kEnterpriseReportingInBrowser)) + return; + + // This is also registered as a Profile pref which will be removed after + // the migration. + registry->RegisterBooleanPref(prefs::kCloudReportingEnabled, false); + registry->RegisterTimePref(kLastUploadTimestamp, base::Time()); +} + +} // namespace enterprise_reporting
diff --git a/chrome/browser/enterprise_reporting/prefs.h b/chrome/browser/enterprise_reporting/prefs.h new file mode 100644 index 0000000..89011c81 --- /dev/null +++ b/chrome/browser/enterprise_reporting/prefs.h
@@ -0,0 +1,18 @@ +// 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_ENTERPRISE_REPORTING_PREFS_H_ +#define CHROME_BROWSER_ENTERPRISE_REPORTING_PREFS_H_ + +#include "components/prefs/pref_registry_simple.h" + +namespace enterprise_reporting { + +extern const char kLastUploadTimestamp[]; + +void RegisterPrefs(PrefRegistrySimple* registry); + +} // namespace enterprise_reporting + +#endif // CHROME_BROWSER_ENTERPRISE_REPORTING_PREFS_H_
diff --git a/chrome/browser/enterprise_reporting/request_timer.cc b/chrome/browser/enterprise_reporting/request_timer.cc new file mode 100644 index 0000000..eb79028 --- /dev/null +++ b/chrome/browser/enterprise_reporting/request_timer.cc
@@ -0,0 +1,49 @@ +// 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/enterprise_reporting/request_timer.h" + +#include "base/time/time.h" + +namespace enterprise_reporting { + +RequestTimer::RequestTimer() = default; +RequestTimer::~RequestTimer() = default; + +void RequestTimer::Start(const base::Location& posted_from, + base::TimeDelta first_delay, + base::TimeDelta repeat_delay, + base::RepeatingClosure user_task) { + // Create |repeat_request_timer| but not start it because the first request is + // sent after |first_delay|. + repeat_request_timer_ = std::make_unique<base::RetainingOneShotTimer>( + FROM_HERE, repeat_delay, user_task); + + if (first_delay >= repeat_delay) { + repeat_request_timer_->Reset(); + } else { + first_request_timer_.Start(FROM_HERE, first_delay, + base::BindOnce(user_task)); + } +} + +void RequestTimer::Stop() { + repeat_request_timer_->Stop(); + first_request_timer_.Stop(); +} + +void RequestTimer::Reset() { + DCHECK(!first_request_timer_.IsRunning()); + repeat_request_timer_->Reset(); +} + +bool RequestTimer::IsRepeatTimerRunning() const { + return repeat_request_timer_ && repeat_request_timer_->IsRunning(); +} + +bool RequestTimer::IsFirstTimerRunning() const { + return first_request_timer_.IsRunning(); +} + +} // namespace enterprise_reporting
diff --git a/chrome/browser/enterprise_reporting/request_timer.h b/chrome/browser/enterprise_reporting/request_timer.h new file mode 100644 index 0000000..48f2a2e --- /dev/null +++ b/chrome/browser/enterprise_reporting/request_timer.h
@@ -0,0 +1,49 @@ +// 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_ENTERPRISE_REPORTING_REQUEST_TIMER_H_ +#define CHROME_BROWSER_ENTERPRISE_REPORTING_REQUEST_TIMER_H_ + +#include <memory> + +#include "base/timer/timer.h" + +namespace enterprise_reporting { + +// A Retaining timer which runs the same task with same delay after every reset +// except the first one which has a special delay. This is used by +// ReportScheduler to schedule the next report. +class RequestTimer { + public: + RequestTimer(); + ~RequestTimer(); + + // Starts the timer. The first task will be ran after |first_delay|. The + // following task will be ran with |repeat_delay|. If |first_delay| is larger + // than the |repeat_delay|, the first request will be fired after + // |repeat_delay| instead. Also, please note that the repeating task is ran + // once per Reset call. + void Start(const base::Location& posted_from, + base::TimeDelta first_delay, + base::TimeDelta repeat_delay, + base::RepeatingClosure user_task); + // Stops the timer. The running task will not be abandon. + void Stop(); + // Resets the timer, ran the task again after |repat_delay| that is set in + // Start(); This is only available after the first task is ran. + void Reset(); + + bool IsRepeatTimerRunning() const; + bool IsFirstTimerRunning() const; + + private: + base::OneShotTimer first_request_timer_; + std::unique_ptr<base::RetainingOneShotTimer> repeat_request_timer_; + + DISALLOW_COPY_AND_ASSIGN(RequestTimer); +}; + +} // namespace enterprise_reporting + +#endif // CHROME_BROWSER_ENTERPRISE_REPORTING_REQUEST_TIMER_H_
diff --git a/chrome/browser/enterprise_reporting/request_timer_unittest.cc b/chrome/browser/enterprise_reporting/request_timer_unittest.cc new file mode 100644 index 0000000..2362a66 --- /dev/null +++ b/chrome/browser/enterprise_reporting/request_timer_unittest.cc
@@ -0,0 +1,156 @@ +// 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/enterprise_reporting/request_timer.h" + +#include "base/test/scoped_task_environment.h" +#include "base/time/time.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace enterprise_reporting { +class RequestTimerTest : public ::testing::Test { + public: + RequestTimerTest() + : scoped_task_environment_( + base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME) {} + + void RunTask() { task_count_ += 1; } + + protected: + void StartTask(int first_delay, int repeat_delay) { + timer_.Start(FROM_HERE, base::TimeDelta::FromSeconds(first_delay), + base::TimeDelta::FromSeconds(repeat_delay), + base::BindRepeating(&RequestTimerTest::RunTask, + base::Unretained(this))); + } + + base::test::ScopedTaskEnvironment scoped_task_environment_; + int task_count_ = 0; + RequestTimer timer_; +}; + +TEST_F(RequestTimerTest, StartTimer) { + StartTask(5, 10); + ASSERT_TRUE(timer_.IsFirstTimerRunning()); + ASSERT_FALSE(timer_.IsRepeatTimerRunning()); +} + +TEST_F(RequestTimerTest, StartTimerWithLargerFirstDelay) { + StartTask(20, 10); + ASSERT_FALSE(timer_.IsFirstTimerRunning()); + ASSERT_TRUE(timer_.IsRepeatTimerRunning()); +} + +TEST_F(RequestTimerTest, RunFirstTask) { + StartTask(5, 10); + + // The first task hasn't been ran yet. + scoped_task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(4)); + ASSERT_TRUE(timer_.IsFirstTimerRunning()); + ASSERT_EQ(0, task_count_); + + // The first task is due. + scoped_task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(1)); + ASSERT_FALSE(timer_.IsFirstTimerRunning()); + ASSERT_FALSE(timer_.IsRepeatTimerRunning()); + ASSERT_EQ(1, task_count_); +} + +TEST_F(RequestTimerTest, RunFirstTaskWithoutDelay) { + StartTask(0, 10); + + // First task is posted and ran immediately. + scoped_task_environment_.RunUntilIdle(); + ASSERT_FALSE(timer_.IsFirstTimerRunning()); + ASSERT_FALSE(timer_.IsRepeatTimerRunning()); + ASSERT_EQ(1, task_count_); +} + +TEST_F(RequestTimerTest, RunFirstTaskWithNegativeDelay) { + StartTask(-1, 10); + + // First task is posted and ran immediately. + scoped_task_environment_.RunUntilIdle(); + ASSERT_FALSE(timer_.IsFirstTimerRunning()); + ASSERT_FALSE(timer_.IsRepeatTimerRunning()); + ASSERT_EQ(1, task_count_); +} + +TEST_F(RequestTimerTest, RunRepeatingTaskTest) { + StartTask(1, 10); + + // Run the first task. + scoped_task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(1)); + + // Reset and wait for the second task. + timer_.Reset(); + ASSERT_FALSE(timer_.IsFirstTimerRunning()); + ASSERT_TRUE(timer_.IsRepeatTimerRunning()); + + scoped_task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(10)); + ASSERT_FALSE(timer_.IsFirstTimerRunning()); + ASSERT_FALSE(timer_.IsRepeatTimerRunning()); + ASSERT_EQ(2, task_count_); + + // Reset and wait for the third task. + timer_.Reset(); + ASSERT_TRUE(timer_.IsRepeatTimerRunning()); + + scoped_task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(10)); + ASSERT_FALSE(timer_.IsFirstTimerRunning()); + ASSERT_FALSE(timer_.IsRepeatTimerRunning()); + ASSERT_EQ(3, task_count_); +} + +TEST_F(RequestTimerTest, NotRuningRepeatingTaskWithoutResetTest) { + StartTask(1, 10); + + // Run the first task. + scoped_task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(1)); + ASSERT_EQ(1, task_count_); + + // The repeat task is not ran without reset. + scoped_task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(15)); + ASSERT_FALSE(timer_.IsRepeatTimerRunning()); + ASSERT_EQ(1, task_count_); + + // Reset the task, the repeat task is ran only once. + timer_.Reset(); + scoped_task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(60)); + ASSERT_FALSE(timer_.IsRepeatTimerRunning()); + ASSERT_EQ(2, task_count_); +} + +TEST_F(RequestTimerTest, StopFirstTask) { + StartTask(1, 10); + + timer_.Stop(); + + // The task is stopped. + ASSERT_FALSE(timer_.IsFirstTimerRunning()); + ASSERT_FALSE(timer_.IsRepeatTimerRunning()); + scoped_task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(10)); + ASSERT_EQ(0, task_count_); +} + +TEST_F(RequestTimerTest, StopRepeatTask) { + StartTask(1, 10); + + // Run the first task. + scoped_task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(1)); + ASSERT_EQ(1, task_count_); + + // Start the repeat task, stop after a while. + timer_.Reset(); + scoped_task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(3)); + timer_.Stop(); + + // The task is stopped. + ASSERT_FALSE(timer_.IsFirstTimerRunning()); + ASSERT_FALSE(timer_.IsRepeatTimerRunning()); + scoped_task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(60)); + ASSERT_EQ(1, task_count_); +} + +} // namespace enterprise_reporting
diff --git a/chrome/browser/extensions/api/signed_in_devices/id_mapping_helper_unittest.cc b/chrome/browser/extensions/api/signed_in_devices/id_mapping_helper_unittest.cc index cd6db0d..cdc749a 100644 --- a/chrome/browser/extensions/api/signed_in_devices/id_mapping_helper_unittest.cc +++ b/chrome/browser/extensions/api/signed_in_devices/id_mapping_helper_unittest.cc
@@ -8,6 +8,7 @@ #include <string> #include "base/guid.h" +#include "base/time/time.h" #include "base/values.h" #include "components/sync_device_info/device_info.h" #include "testing/gmock/include/gmock/gmock.h" @@ -32,12 +33,12 @@ devices.push_back(std::make_unique<DeviceInfo>( base::GenerateGUID(), "abc Device", "XYZ v1", "XYZ SyncAgent v1", - sync_pb::SyncEnums_DeviceType_TYPE_LINUX, "device_id1", + sync_pb::SyncEnums_DeviceType_TYPE_LINUX, "device_id1", base::Time(), /*send_tab_to_self_receiving_enabled=*/true)); devices.push_back(std::make_unique<DeviceInfo>( base::GenerateGUID(), "def Device", "XYZ v1", "XYZ SyncAgent v1", - sync_pb::SyncEnums_DeviceType_TYPE_LINUX, "device_id2", + sync_pb::SyncEnums_DeviceType_TYPE_LINUX, "device_id2", base::Time(), /*send_tab_to_self_receiving_enabled=*/true)); base::DictionaryValue dictionary; @@ -55,7 +56,7 @@ // Now add a third device. devices.push_back(std::make_unique<DeviceInfo>( base::GenerateGUID(), "ghi Device", "XYZ v1", "XYZ SyncAgent v1", - sync_pb::SyncEnums_DeviceType_TYPE_LINUX, "device_id3", + sync_pb::SyncEnums_DeviceType_TYPE_LINUX, "device_id3", base::Time(), /*send_tab_to_self_receiving_enabled=*/true)); CreateMappingForUnmappedDevices(devices, &dictionary);
diff --git a/chrome/browser/extensions/api/signed_in_devices/signed_in_devices_api_unittest.cc b/chrome/browser/extensions/api/signed_in_devices/signed_in_devices_api_unittest.cc index 3422a4c7..f4f9013 100644 --- a/chrome/browser/extensions/api/signed_in_devices/signed_in_devices_api_unittest.cc +++ b/chrome/browser/extensions/api/signed_in_devices/signed_in_devices_api_unittest.cc
@@ -11,6 +11,7 @@ #include "base/bind.h" #include "base/guid.h" #include "base/threading/thread_task_runner_handle.h" +#include "base/time/time.h" #include "base/values.h" #include "chrome/browser/extensions/extension_api_unittest.h" #include "chrome/browser/extensions/test_extension_prefs.h" @@ -48,6 +49,7 @@ device_info.guid(), device_info.client_name(), device_info.chrome_version(), device_info.sync_user_agent(), device_info.device_type(), device_info.signin_scoped_device_id(), + device_info.last_updated_timestamp(), device_info.send_tab_to_self_receiving_enabled()); } @@ -89,13 +91,15 @@ scoped_refptr<Extension> extension_test = extension_prefs.AddExtension(extension_name); - DeviceInfo device_info1( - base::GenerateGUID(), "abc Device", "XYZ v1", "XYZ SyncAgent v1", - sync_pb::SyncEnums_DeviceType_TYPE_LINUX, "device_id", true); + DeviceInfo device_info1(base::GenerateGUID(), "abc Device", "XYZ v1", + "XYZ SyncAgent v1", + sync_pb::SyncEnums_DeviceType_TYPE_LINUX, "device_id", + base::Time(), true); - DeviceInfo device_info2( - base::GenerateGUID(), "def Device", "XYZ v2", "XYZ SyncAgent v2", - sync_pb::SyncEnums_DeviceType_TYPE_LINUX, "device_id", true); + DeviceInfo device_info2(base::GenerateGUID(), "def Device", "XYZ v2", + "XYZ SyncAgent v2", + sync_pb::SyncEnums_DeviceType_TYPE_LINUX, "device_id", + base::Time(), true); device_tracker.Add(&device_info1); device_tracker.Add(&device_info2); @@ -112,9 +116,10 @@ // Add a third device and make sure the first 2 ids are retained and a new // id is generated for the third device. - DeviceInfo device_info3( - base::GenerateGUID(), "def Device", "jkl v2", "XYZ SyncAgent v2", - sync_pb::SyncEnums_DeviceType_TYPE_LINUX, "device_id", true); + DeviceInfo device_info3(base::GenerateGUID(), "def Device", "jkl v2", + "XYZ SyncAgent v2", + sync_pb::SyncEnums_DeviceType_TYPE_LINUX, "device_id", + base::Time(), true); device_tracker.Add(&device_info3); @@ -200,13 +205,15 @@ DeviceInfoSyncServiceFactory::GetForProfile(profile())) ->mock_tracker(); - DeviceInfo device_info1( - base::GenerateGUID(), "abc Device", "XYZ v1", "XYZ SyncAgent v1", - sync_pb::SyncEnums_DeviceType_TYPE_LINUX, "device_id", true); + DeviceInfo device_info1(base::GenerateGUID(), "abc Device", "XYZ v1", + "XYZ SyncAgent v1", + sync_pb::SyncEnums_DeviceType_TYPE_LINUX, "device_id", + base::Time(), true); - DeviceInfo device_info2( - base::GenerateGUID(), "def Device", "XYZ v2", "XYZ SyncAgent v2", - sync_pb::SyncEnums_DeviceType_TYPE_LINUX, "device_id", true); + DeviceInfo device_info2(base::GenerateGUID(), "def Device", "XYZ v2", + "XYZ SyncAgent v2", + sync_pb::SyncEnums_DeviceType_TYPE_LINUX, "device_id", + base::Time(), true); device_tracker->Add(&device_info1); device_tracker->Add(&device_info2);
diff --git a/chrome/browser/extensions/api/virtual_keyboard_private/chrome_virtual_keyboard_delegate.cc b/chrome/browser/extensions/api/virtual_keyboard_private/chrome_virtual_keyboard_delegate.cc index 1aa88fcd..56c227c 100644 --- a/chrome/browser/extensions/api/virtual_keyboard_private/chrome_virtual_keyboard_delegate.cc +++ b/chrome/browser/extensions/api/virtual_keyboard_private/chrome_virtual_keyboard_delegate.cc
@@ -357,9 +357,7 @@ std::unique_ptr<base::ListValue> features(new base::ListValue()); features->AppendString(GenerateFeatureFlag("floatingkeyboard", true)); - features->AppendString(GenerateFeatureFlag( - "gesturetyping", !base::CommandLine::ForCurrentProcess()->HasSwitch( - keyboard::switches::kDisableGestureTyping))); + features->AppendString(GenerateFeatureFlag("gesturetyping", true)); // TODO(https://crbug.com/890134): Implement gesture editing. features->AppendString(GenerateFeatureFlag("gestureediting", false)); features->AppendString(GenerateFeatureFlag("fullscreenhandwriting", false));
diff --git a/chrome/browser/extensions/api/web_request/web_request_apitest.cc b/chrome/browser/extensions/api/web_request/web_request_apitest.cc index f9c5ce7..305134e 100644 --- a/chrome/browser/extensions/api/web_request/web_request_apitest.cc +++ b/chrome/browser/extensions/api/web_request/web_request_apitest.cc
@@ -2435,6 +2435,8 @@ IN_PROC_BROWSER_TEST_F(ExtensionWebRequestApiTest, ChangeHeaderUMAs) { using RequestHeaderType = extension_web_request_api_helpers::RequestHeaderType; + using ResponseHeaderType = + extension_web_request_api_helpers::ResponseHeaderType; ASSERT_TRUE(embedded_test_server()->Start()); @@ -2465,11 +2467,16 @@ chrome.webRequest.onHeadersReceived.addListener(function(details) { var headers = details.responseHeaders; for (var i = 0; i < headers.length; i++) { - if (headers[i].name.toLowerCase() == 'set-cookie') { - headers[i].value = 'Blah=Blah'; - break; + if (headers[i].name.toLowerCase() == 'set-cookie' && + headers[i].value == 'key1=val1') { + headers.splice(i, 1); + i--; + } else if (headers[i].name == 'Content-Length') { + headers[i].value = '0'; } } + headers.push({name: 'Foo3', value: 'Bar3'}); + headers.push({name: 'Foo4', value: 'Bar4'}); return {responseHeaders: headers}; }, {urls: ['*://*/set-cookie*']}, ['blocking', 'responseHeaders', 'extraHeaders']); @@ -2483,15 +2490,24 @@ base::HistogramTester tester; ui_test_utils::NavigateToURL( - browser(), embedded_test_server()->GetURL("/set-cookie?Foo=Bar")); + browser(), + embedded_test_server()->GetURL("/set-cookie?key1=val1&key2=val2")); - // Changed histograms should record kUserAgent and true. + // Changed histograms should record kUserAgent request header along with + // kSetCookie and kContentLength response headers. tester.ExpectUniqueSample("Extensions.WebRequest.RequestHeaderChanged", RequestHeaderType::kUserAgent, 1); - tester.ExpectUniqueSample( - "Extensions.WebRequest.SetCookieResponseHeaderChanged", true, 1); + EXPECT_THAT( + tester.GetAllSamples("Extensions.WebRequest.ResponseHeaderChanged"), + ::testing::UnorderedElementsAre( + base::Bucket(static_cast<base::HistogramBase::Sample>( + ResponseHeaderType::kSetCookie), + 1), + base::Bucket(static_cast<base::HistogramBase::Sample>( + ResponseHeaderType::kContentLength), + 1))); - // Added histogram should record kOther and kDNT. + // Added request header histogram should record kOther and kDNT. EXPECT_THAT(tester.GetAllSamples("Extensions.WebRequest.RequestHeaderAdded"), ::testing::UnorderedElementsAre( base::Bucket(static_cast<base::HistogramBase::Sample>( @@ -2501,16 +2517,22 @@ RequestHeaderType::kOther), 2))); - // Removed histograms should record kNone and false. + // Added response header histogram should record kOther. + tester.ExpectUniqueSample("Extensions.WebRequest.ResponseHeaderAdded", + ResponseHeaderType::kOther, 2); + + // Histograms for removed headers should record kNone. tester.ExpectUniqueSample("Extensions.WebRequest.RequestHeaderRemoved", RequestHeaderType::kNone, 1); - tester.ExpectUniqueSample( - "Extensions.WebRequest.SetCookieResponseHeaderRemoved", false, 1); + tester.ExpectUniqueSample("Extensions.WebRequest.ResponseHeaderRemoved", + ResponseHeaderType::kNone, 1); } IN_PROC_BROWSER_TEST_F(ExtensionWebRequestApiTest, RemoveHeaderUMAs) { using RequestHeaderType = extension_web_request_api_helpers::RequestHeaderType; + using ResponseHeaderType = + extension_web_request_api_helpers::ResponseHeaderType; ASSERT_TRUE(embedded_test_server()->Start()); @@ -2558,21 +2580,23 @@ ui_test_utils::NavigateToURL( browser(), embedded_test_server()->GetURL("/set-cookie?Foo=Bar")); - // Removed histograms should record kUserAgent and true. + // Histograms for removed headers should record kUserAgent and kSetCookie. tester.ExpectUniqueSample("Extensions.WebRequest.RequestHeaderRemoved", RequestHeaderType::kUserAgent, 1); - tester.ExpectUniqueSample( - "Extensions.WebRequest.SetCookieResponseHeaderRemoved", true, 1); + tester.ExpectUniqueSample("Extensions.WebRequest.ResponseHeaderRemoved", + ResponseHeaderType::kSetCookie, 1); - // Changed histograms should record kNone and false. + // Histograms for changed headers should record kNone. tester.ExpectUniqueSample("Extensions.WebRequest.RequestHeaderChanged", RequestHeaderType::kNone, 1); - tester.ExpectUniqueSample( - "Extensions.WebRequest.SetCookieResponseHeaderChanged", false, 1); + tester.ExpectUniqueSample("Extensions.WebRequest.ResponseHeaderChanged", + ResponseHeaderType::kNone, 1); - // Added histograms should record kNone. + // Histograms for added headers should record kNone. tester.ExpectUniqueSample("Extensions.WebRequest.RequestHeaderAdded", RequestHeaderType::kNone, 1); + tester.ExpectUniqueSample("Extensions.WebRequest.ResponseHeaderAdded", + ResponseHeaderType::kNone, 1); } IN_PROC_BROWSER_TEST_F(ExtensionWebRequestApiTest, ServiceWorkerFetch) {
diff --git a/chrome/browser/extensions/user_script_listener.cc b/chrome/browser/extensions/user_script_listener.cc index 1c924136..30fe8a2 100644 --- a/chrome/browser/extensions/user_script_listener.cc +++ b/chrome/browser/extensions/user_script_listener.cc
@@ -142,8 +142,6 @@ } void UserScriptListener::StartDelayedRequests() { - UMA_HISTOGRAM_COUNTS_100("Extensions.ThrottledNetworkRequests", - throttles_.size()); WeakThrottleList::const_iterator it; for (it = throttles_.begin(); it != throttles_.end(); ++it) { if (it->get())
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json index e47eea5..2e94723 100644 --- a/chrome/browser/flag-metadata.json +++ b/chrome/browser/flag-metadata.json
@@ -564,11 +564,6 @@ "expiry_milestone": 76 }, { - "name": "disable-tablet-splitview", - // "owners": [ "your-team" ], - "expiry_milestone": 76 - }, - { "name": "disable-threaded-scrolling", "owners": [ "bokan", "input-dev" ], // This flag is a useful debugging control when investigating scrolling @@ -943,6 +938,11 @@ "expiry_milestone": 76 }, { + "name": "enable-cros-vm-cups-proxy", + "owners": [ "//chrome/services/cups_proxy/OWNERS" ], + "expiry_milestone": 78 + }, + { "name": "enable-custom-context-menu", "owners": [ "chrome-android-app" ], "expiry_milestone": 77 @@ -1010,11 +1010,6 @@ "expiry_milestone": 76 }, { - "name": "enable-embedded-extension-options", - // "owners": [ "your-team" ], - "expiry_milestone": 76 - }, - { "name": "enable-encryption-migration", "owners": [ "fukino" ], "expiry_milestone": 76 @@ -1591,11 +1586,6 @@ "expiry_milestone": 80 }, { - "name": "enable-sole-integration", - // "owners": [ "your-team" ], - "expiry_milestone": 76 - }, - { "name": "enable-speculative-service-worker-start-on-query-input", // "owners": [ "your-team" ], "expiry_milestone": 76 @@ -1812,6 +1802,13 @@ "expiry_milestone": 77 }, { + "name": "enable-web-payments-experimental-features", + "owners": [ "danyao", "rouslan", "paymentrequest@google.com" ], + // This flag is used by early adoption partners to test new Web Payments + // features in each release. + "expiry_milestone": -1 + }, + { "name": "enable-webassembly", "owners": [ "titzer", "wasm-team@google.com" ], "expiry_milestone": 72 @@ -2098,11 +2095,6 @@ "expiry_milestone": 76 }, { - "name": "gesture-typing", - // "owners": [ "your-team" ], - "expiry_milestone": 76 - }, - { "name": "google-password-manager", "owners": [ "ioanap", "jdoerrie" ], "expiry_milestone": 76
diff --git a/chrome/browser/flag-never-expire-list.json b/chrome/browser/flag-never-expire-list.json index e0b487f..59d55e9 100644 --- a/chrome/browser/flag-never-expire-list.json +++ b/chrome/browser/flag-never-expire-list.json
@@ -50,6 +50,7 @@ "enable-ui-devtools", "enable-virtual-keyboard", "enable-web-authentication-testing-api", + "enable-web-payments-experimental-features", "enable-webgl-draft-extensions", "enable-zero-copy", "extensions-on-chrome-urls",
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc index 662fedc..e80ed5d3 100644 --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc
@@ -346,11 +346,6 @@ "code), where the final download origin or any origin in the redirect " "chain is insecure."; -const char kEmbeddedExtensionOptionsName[] = "Embedded extension options"; -const char kEmbeddedExtensionOptionsDescription[] = - "Display extension options as an embedded element in chrome://extensions " - "rather than opening a new tab."; - const char kEnableAccessibilityImageDescriptionsName[] = "Accessibility Image Descriptions"; const char kEnableAccessibilityImageDescriptionsDescription[] = @@ -1984,6 +1979,11 @@ const char kWebMidiName[] = "Web MIDI API"; const char kWebMidiDescription[] = "Enable Web MIDI API experimental support."; +const char kWebPaymentsExperimentalFeaturesName[] = + "Experimental Web Payments API features"; +const char kWebPaymentsExperimentalFeaturesDescription[] = + "Enable experimental Web Payments API features"; + const char kWebrtcHideLocalIpsWithMdnsName[] = "Anonymize local IPs exposed by WebRTC."; const char kWebrtcHideLocalIpsWithMdnsDecription[] = @@ -2969,6 +2969,10 @@ const char kCrostiniUsbSupportDescription[] = "Enable mounting Usb devices in Crostini."; +const char kCrosVmCupsProxyName[] = "Chrome OS CUPS Proxy"; +const char kCrosVmCupsProxyDescription[] = + "Supports printing from VMs on Chrome OS."; + const char kCryptAuthV2EnrollmentName[] = "CryptAuth v2 Enrollment"; const char kCryptAuthV2EnrollmentDescription[] = "Use the CryptAuth v2 Enrollment protocol."; @@ -3142,11 +3146,6 @@ " option, so the chromuimos LSM denies symlink traversal on the" " filesystem."; -const char kGestureTypingName[] = "Gesture typing for the virtual keyboard."; -const char kGestureTypingDescription[] = - "Enable/Disable gesture typing option in the settings page for the virtual " - "keyboard."; - const char kHideArcMediaNotificationsName[] = "Hide ARC media notifications"; const char kHideArcMediaNotificationsDescription[] = "Hides media notifications for ARC apps. Requires "
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h index f21cf57..9bee64df 100644 --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h
@@ -239,9 +239,6 @@ extern const char kDisplayList2dCanvasName[]; extern const char kDisplayList2dCanvasDescription[]; -extern const char kEmbeddedExtensionOptionsName[]; -extern const char kEmbeddedExtensionOptionsDescription[]; - extern const char kEnableAccessibilityImageDescriptionsName[]; extern const char kEnableAccessibilityImageDescriptionsDescription[]; @@ -1188,6 +1185,9 @@ extern const char kWebMidiName[]; extern const char kWebMidiDescription[]; +extern const char kWebPaymentsExperimentalFeaturesName[]; +extern const char kWebPaymentsExperimentalFeaturesDescription[]; + extern const char kWebrtcHideLocalIpsWithMdnsName[]; extern const char kWebrtcHideLocalIpsWithMdnsDecription[]; @@ -1789,6 +1789,9 @@ extern const char kCrostiniUsbSupportName[]; extern const char kCrostiniUsbSupportDescription[]; +extern const char kCrosVmCupsProxyName[]; +extern const char kCrosVmCupsProxyDescription[]; + extern const char kCryptAuthV2EnrollmentName[]; extern const char kCryptAuthV2EnrollmentDescription[]; @@ -1893,9 +1896,6 @@ extern const char kFsNosymfollowName[]; extern const char kFsNosymfollowDescription[]; -extern const char kGestureTypingName[]; -extern const char kGestureTypingDescription[]; - extern const char kHideArcMediaNotificationsName[]; extern const char kHideArcMediaNotificationsDescription[];
diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc index 83f3d59..242dfac8 100644 --- a/chrome/browser/prefs/browser_prefs.cc +++ b/chrome/browser/prefs/browser_prefs.cc
@@ -214,6 +214,7 @@ #include "components/feed/core/user_classifier.h" #endif // BUILDFLAG(ENABLE_FEED_IN_CHROME) #else // defined(OS_ANDROID) +#include "chrome/browser/enterprise_reporting/prefs.h" #include "chrome/browser/gcm/gcm_product_util.h" #include "chrome/browser/metrics/tab_stats_tracker.h" #include "chrome/browser/search/instant_service.h" @@ -565,6 +566,7 @@ StartupBrowserCreator::RegisterLocalStatePrefs(registry); task_manager::TaskManagerInterface::RegisterPrefs(registry); UpgradeDetector::RegisterPrefs(registry); + enterprise_reporting::RegisterPrefs(registry); // Obsolete. See MigrateObsoleteBrowserPrefs(). registry->RegisterIntegerPref(kShowFirstRunBubbleOption, 0); #if !defined(OS_CHROMEOS)
diff --git a/chrome/browser/previews/hints_fetcher_browsertest.cc b/chrome/browser/previews/hints_fetcher_browsertest.cc index 11eeda4..1f8edd3c 100644 --- a/chrome/browser/previews/hints_fetcher_browsertest.cc +++ b/chrome/browser/previews/hints_fetcher_browsertest.cc
@@ -88,21 +88,35 @@ HintsFetcherDisabledBrowserTest() = default; ~HintsFetcherDisabledBrowserTest() override = default; + void SetUpOnMainThread() override { + g_browser_process->network_quality_tracker() + ->ReportEffectiveConnectionTypeForTesting( + net::EFFECTIVE_CONNECTION_TYPE_2G); + + InProcessBrowserTest::SetUpOnMainThread(); + } + void SetUp() override { - https_server_.reset( + origin_server_.reset( new net::EmbeddedTestServer(net::EmbeddedTestServer::TYPE_HTTPS)); - https_server_->ServeFilesFromSourceDirectory("chrome/test/data/previews"); - https_server_->RegisterRequestMonitor(base::BindRepeating( - &HintsFetcherDisabledBrowserTest::MonitorResourceRequest, + origin_server_->ServeFilesFromSourceDirectory("chrome/test/data/previews"); + origin_server_->RegisterRequestHandler(base::BindRepeating( + &HintsFetcherDisabledBrowserTest::HandleOriginRequest, base::Unretained(this))); - https_server_->RegisterRequestHandler(base::BindRepeating( + + ASSERT_TRUE(origin_server_->Start()); + + https_url_ = origin_server_->GetURL("/hint_setup.html"); + ASSERT_TRUE(https_url().SchemeIs(url::kHttpsScheme)); + + hints_server_.reset( + new net::EmbeddedTestServer(net::EmbeddedTestServer::TYPE_HTTPS)); + hints_server_->ServeFilesFromSourceDirectory("chrome/test/data/previews"); + hints_server_->RegisterRequestHandler(base::BindRepeating( &HintsFetcherDisabledBrowserTest::HandleGetHintsRequest, base::Unretained(this))); - ASSERT_TRUE(https_server_->Start()); - - https_url_ = https_server_->GetURL("/hint_setup.html"); - ASSERT_TRUE(https_url().SchemeIs(url::kHttpsScheme)); + ASSERT_TRUE(hints_server_->Start()); InProcessBrowserTest::SetUp(); } @@ -119,7 +133,7 @@ // Set up OptimizationGuideServiceURL, this does not enable HintsFetching, // only provides the URL. cmd->AppendSwitchASCII(previews::switches::kOptimizationGuideServiceURL, - https_server_->base_url().spec()); + hints_server_->base_url().spec()); cmd->AppendSwitchASCII(previews::switches::kFetchHintsOverride, "example1.com, example2.com"); } @@ -170,6 +184,20 @@ service->AddPointsForTesting(http_url2, 2); } + void LoadHintsForUrl(const GURL& url) { + base::HistogramTester histogram_tester; + + // Navigate to |url| to prime the OptimizationGuide hints for the + // url's host and ensure that they have been loaded from the store (via + // histogram) prior to the navigation that tests functionality. + ui_test_utils::NavigateToURL(browser(), url); + + RetryForHistogramUntilCountReached( + &histogram_tester, + previews::kPreviewsOptimizationGuideOnLoadedHintResultHistogramString, + 1); + } + const GURL& https_url() const { return https_url_; } const base::HistogramTester* GetHistogramTester() { return &histogram_tester_; @@ -177,30 +205,38 @@ protected: base::test::ScopedFeatureList scoped_feature_list_; - std::unique_ptr<net::EmbeddedTestServer> https_server_; + std::unique_ptr<net::EmbeddedTestServer> origin_server_; + std::unique_ptr<net::EmbeddedTestServer> hints_server_; HintsFetcherRemoteResponseType response_type_ = HintsFetcherRemoteResponseType::kSuccessful; private: - // Called by |https_server_|. - void MonitorResourceRequest(const net::test_server::HttpRequest& request) { - // The request by HintsFetcher request should happen and be a POST request. - EXPECT_EQ(request.method, net::test_server::METHOD_POST); + std::unique_ptr<net::test_server::HttpResponse> HandleOriginRequest( + const net::test_server::HttpRequest& request) { + EXPECT_EQ(request.method, net::test_server::METHOD_GET); + std::unique_ptr<net::test_server::BasicHttpResponse> response; + response.reset(new net::test_server::BasicHttpResponse); + response->set_code(net::HTTP_OK); + + return std::move(response); } std::unique_ptr<net::test_server::HttpResponse> HandleGetHintsRequest( const net::test_server::HttpRequest& request) { std::unique_ptr<net::test_server::BasicHttpResponse> response; + response.reset(new net::test_server::BasicHttpResponse); + // If the request is a GET, it corresponds to a navigation so return a + // normal response. + EXPECT_EQ(request.method, net::test_server::METHOD_POST); if (response_type_ == HintsFetcherRemoteResponseType::kSuccessful) { - response.reset(new net::test_server::BasicHttpResponse); response->set_code(net::HTTP_OK); optimization_guide::proto::GetHintsResponse get_hints_response; optimization_guide::proto::Hint* hint = get_hints_response.add_hints(); hint->set_key_representation(optimization_guide::proto::HOST_SUFFIX); - hint->set_key("host.domain.org"); + hint->set_key(https_url_.host()); optimization_guide::proto::PageHint* page_hint = hint->add_page_hints(); page_hint->set_page_pattern("page pattern"); @@ -209,15 +245,14 @@ response->set_content(serialized_request); } else if (response_type_ == HintsFetcherRemoteResponseType::kUnsuccessful) { - response.reset(new net::test_server::BasicHttpResponse); response->set_code(net::HTTP_NOT_FOUND); } else if (response_type_ == HintsFetcherRemoteResponseType::kMalformed) { - response.reset(new net::test_server::BasicHttpResponse); response->set_code(net::HTTP_OK); std::string serialized_request = "Not a proto"; response->set_content(serialized_request); + } else { NOTREACHED(); } @@ -226,7 +261,8 @@ } void TearDownOnMainThread() override { - EXPECT_TRUE(https_server_->ShutdownAndWaitUntilComplete()); + EXPECT_TRUE(origin_server_->ShutdownAndWaitUntilComplete()); + EXPECT_TRUE(hints_server_->ShutdownAndWaitUntilComplete()); InProcessBrowserTest::TearDownOnMainThread(); } @@ -251,10 +287,13 @@ void SetUp() override { // Enable OptimizationHintsFetching with |kOptimizationHintsFetching|. scoped_feature_list_.InitWithFeatures( - {previews::features::kPreviews, previews::features::kOptimizationHints, - previews::features::kOptimizationHintsFetching}, + {previews::features::kPreviews, previews::features::kNoScriptPreviews, + previews::features::kOptimizationHints, + previews::features::kResourceLoadingHints, + previews::features::kOptimizationHintsFetching, + data_reduction_proxy::features:: + kDataReductionProxyEnabledWithNetworkService}, {}); - // Call to inherited class to match same set up with feature flags added. HintsFetcherDisabledBrowserTest::SetUp(); } @@ -364,6 +403,46 @@ "Previews.HintsFetcher.GetHintsRequest.HostCount", 2, 1); } +IN_PROC_BROWSER_TEST_F( + HintsFetcherBrowserTest, + DISABLE_ON_WIN_MAC_CHROMESOS(HintsFetcherFetchedHintsLoaded)) { + const base::HistogramTester* histogram_tester = GetHistogramTester(); + GURL url = https_url(); + + // Whitelist NoScript for https_url()'s' host. + SetUpComponentUpdateHints(https_url()); + + // Expect that the browser initialization will record at least one sample + // in each of the follow histograms as One Platform Hints are enabled. + EXPECT_GE(RetryForHistogramUntilCountReached( + histogram_tester, + "Previews.HintsFetcher.GetHintsRequest.HostCount", 1), + 1); + + EXPECT_GE( + RetryForHistogramUntilCountReached( + histogram_tester, "Previews.HintsFetcher.GetHintsRequest.Status", 1), + 1); + + LoadHintsForUrl(https_url()); + + ui_test_utils::NavigateToURL(browser(), https_url()); + + // Verifies that the fetched hint is loaded and not the component hint as + // fetched hints are prioritized. + + histogram_tester->ExpectBucketCount( + "Previews.OptimizationGuide.HintCache.HintType.Loaded", + static_cast<int>(previews::HintCacheStore::StoreEntryType::kFetchedHint), + 1); + + histogram_tester->ExpectBucketCount( + "Previews.OptimizationGuide.HintCache.HintType.Loaded", + static_cast<int>( + previews::HintCacheStore::StoreEntryType::kComponentHint), + 0); +} + IN_PROC_BROWSER_TEST_P( HintsFetcherWithResponseBrowserTest, DISABLE_ON_WIN_MAC_CHROMESOS(HintsFetcherWithResponses)) { @@ -402,10 +481,23 @@ histogram_tester->ExpectBucketCount( "Previews.HintsFetcher.GetHintsRequest.NetErrorCode", net::OK, 1); - // TODO(mcrouse): Once hints are stored, validiation - // will be done to show that nothing has been added to the store and hints - // can still be used. Current unittests cover this behavior but needed here - // for fault tests. + LoadHintsForUrl(https_url()); + + ui_test_utils::NavigateToURL(browser(), https_url()); + + // Verifies that no Fetched Hint was added to the store, only the + // Component hint is loaded. + histogram_tester->ExpectBucketCount( + "Previews.OptimizationGuide.HintCache.HintType.Loaded", + static_cast<int>( + previews::HintCacheStore::StoreEntryType::kComponentHint), + 1); + histogram_tester->ExpectBucketCount( + "Previews.OptimizationGuide.HintCache.HintType.Loaded", + static_cast<int>( + previews::HintCacheStore::StoreEntryType::kFetchedHint), + 0); + } else { NOTREACHED(); }
diff --git a/chrome/browser/previews/previews_offline_helper_unittest.cc b/chrome/browser/previews/previews_offline_helper_unittest.cc index 9ea8654..7723493 100644 --- a/chrome/browser/previews/previews_offline_helper_unittest.cc +++ b/chrome/browser/previews/previews_offline_helper_unittest.cc
@@ -25,8 +25,8 @@ ChromeRenderViewHostTestHarness::TearDown(); } - PreviewsOfflineHelper* NewHelper() { - helper_.reset(new PreviewsOfflineHelper(browser_context())); + PreviewsOfflineHelper* NewHelper(content::BrowserContext* browser_context) { + helper_.reset(new PreviewsOfflineHelper(browser_context)); return helper_.get(); } @@ -188,7 +188,7 @@ TestingPrefServiceSimple test_prefs; PreviewsOfflineHelper::RegisterProfilePrefs(test_prefs.registry()); - PreviewsOfflineHelper* helper = NewHelper(); + PreviewsOfflineHelper* helper = NewHelper(nullptr); helper->SetPrefServiceForTesting(&test_prefs); // The tests above rely on this ordering. @@ -242,7 +242,7 @@ previews::features::kOfflinePreviewsFalsePositivePrevention, {{"max_pref_entries", "1"}}); - PreviewsOfflineHelper* helper = NewHelper(); + PreviewsOfflineHelper* helper = NewHelper(nullptr); base::Time first = base::Time::Now(); base::Time second = first + base::TimeDelta::FromMinutes(1); @@ -267,7 +267,7 @@ base::HistogramTester histogram_tester; - PreviewsOfflineHelper* helper = NewHelper(); + PreviewsOfflineHelper* helper = NewHelper(nullptr); base::Time now = base::Time::Now(); base::Time expired = now - previews::params::OfflinePreviewFreshnessDuration() -
diff --git a/chrome/browser/resources/BUILD.gn b/chrome/browser/resources/BUILD.gn index ccfd3ee..c576553 100644 --- a/chrome/browser/resources/BUILD.gn +++ b/chrome/browser/resources/BUILD.gn
@@ -175,6 +175,39 @@ ] output_dir = "$root_gen_dir/chrome" } + + grit("downloads_resources") { + if (optimize_webui) { + source = "downloads/downloads_resources_vulcanized.grd" + + deps = [ + "//chrome/browser/resources/downloads:build", + ] + } else { + source = "downloads/downloads_resources.grd" + + deps = [ + "//chrome/browser/ui/webui/downloads:mojo_bindings", + ] + } + + # The .grd contains references to generated files. + source_is_generated = true + + grit_flags = [ + "-E", + "root_gen_dir=" + rebase_path(root_gen_dir, root_build_dir), + ] + + defines = chrome_grit_defines + outputs = [ + "grit/downloads_resources.h", + "grit/downloads_resources_map.cc", + "grit/downloads_resources_map.h", + "downloads_resources.pak", + ] + output_dir = "$root_gen_dir/chrome" + } } if (is_chromeos) {
diff --git a/chrome/browser/resources/chromeos/login/BUILD.gn b/chrome/browser/resources/chromeos/login/BUILD.gn index afe04dda..20bd59fd 100644 --- a/chrome/browser/resources/chromeos/login/BUILD.gn +++ b/chrome/browser/resources/chromeos/login/BUILD.gn
@@ -47,6 +47,7 @@ ":recommend_apps", ":saml_confirm_password", ":saml_interstitial", + ":supervision_onboarding", ":sync_consent", ":throbber_notice", ":update_required_card", @@ -145,6 +146,13 @@ ] } +js_library("supervision_onboarding") { + deps = [ + "//chrome/browser/chromeos/supervision/mojom:mojom_js_library_for_compile", + "//ui/webui/resources/js:cr", + ] +} + js_library("active_directory_password_change") { }
diff --git a/chrome/browser/resources/chromeos/login/supervision_onboarding.html b/chrome/browser/resources/chromeos/login/supervision_onboarding.html index 71b426a..dd1cb377 100644 --- a/chrome/browser/resources/chromeos/login/supervision_onboarding.html +++ b/chrome/browser/resources/chromeos/login/supervision_onboarding.html
@@ -5,6 +5,8 @@ <link rel="import" href="chrome://resources/html/polymer.html"> <link rel="import" href="chrome://oobe/custom_elements.html"> +<link rel="import" href="chrome://resources/mojo/mojo/public/js/mojo_bindings_lite.html"> +<link rel="import" href="chrome://oobe/supervision_onboarding_controller.mojom.html"> <!-- UI for the Supervision Onboarding flow that's displayed for the first login @@ -13,10 +15,7 @@ <template> <link rel="stylesheet" href="oobe_flex_layout.css"> <oobe-dialog id="supervision-onboarding-dialog" has-buttons> - <iron-icon src="chrome://oobe/supervision_icon.png" slot="oobe-icon" - aria-hidden="true"> - </iron-icon> - <h1 slot="title">Placeholder Supervision Onboarding flow</h1> + <webview id="contentWebview" slot="footer"></webview> <div slot="bottom-buttons" class="flex layout horizontal"> <oobe-back-button id="back-button" on-tap="onBack_">
diff --git a/chrome/browser/resources/chromeos/login/supervision_onboarding.js b/chrome/browser/resources/chromeos/login/supervision_onboarding.js index 79a48026..519e80b2 100644 --- a/chrome/browser/resources/chromeos/login/supervision_onboarding.js +++ b/chrome/browser/resources/chromeos/login/supervision_onboarding.js
@@ -11,6 +11,37 @@ behaviors: [LoginScreenBehavior], + /** Overridden from LoginScreenBehavior. */ + EXTERNAL_API: [ + 'setupMojo', + ], + + /** @private {?chromeos.supervision.mojom.OnboardingControllerProxy} */ + controller_: null, + + /** + * @private {?chromeos.supervision.mojom. + * OnboardingWebviewHostCallbackRouter} + */ + hostCallbackRouter_: null, + + setupMojo: function() { + this.controller_ = + chromeos.supervision.mojom.OnboardingController.getProxy(); + + this.hostCallbackRouter_ = + new chromeos.supervision.mojom.OnboardingWebviewHostCallbackRouter(); + + this.hostCallbackRouter_.loadPage.addListener(pageUrl => { + this.$.contentWebview.src = pageUrl; + }); + this.hostCallbackRouter_.exitFlow.addListener(() => { + this.exitFlow_(); + }); + + this.controller_.bindWebviewHost(this.hostCallbackRouter_.createProxy()); + }, + /** @override */ ready: function() { this.initializeLoginScreen('SupervisionOnboardingScreen', { @@ -21,21 +52,24 @@ /** @private */ onBack_: function() { - this.exitSetupFlow_(); + this.controller_.handleAction( + chromeos.supervision.mojom.OnboardingFlowAction.kShowPreviousPage); }, /** @private */ onSkip_: function() { - this.exitSetupFlow_(); + this.controller_.handleAction( + chromeos.supervision.mojom.OnboardingFlowAction.kSkipFlow); }, /** @private */ onNext_: function() { - this.exitSetupFlow_(); + this.controller_.handleAction( + chromeos.supervision.mojom.OnboardingFlowAction.kShowNextPage); }, /** @private */ - exitSetupFlow_: function() { + exitFlow_: function() { chrome.send('login.SupervisionOnboardingScreen.userActed', ['setup-finished']); }
diff --git a/chrome/browser/resources/downloads/BUILD.gn b/chrome/browser/resources/downloads/BUILD.gn index f111ccb..d24bdfb 100644 --- a/chrome/browser/resources/downloads/BUILD.gn +++ b/chrome/browser/resources/downloads/BUILD.gn
@@ -2,21 +2,63 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import("//chrome/common/features.gni") import("//third_party/closure_compiler/compile_js.gni") +import("//tools/grit/grit_rule.gni") import("../optimize_webui.gni") -optimize_webui("build") { - deps = [] - host = "downloads" - html_in_files = [ "downloads.html" ] - html_out_files = [ "vulcanized.html" ] - input = rebase_path(".", root_build_dir) - insert_in_head = "<base href=chrome://downloads>" - js_out_files = [ "crisper.js" ] - excludes = [ - "chrome://resources/js/mojo_bindings_lite.js", - "chrome://downloads/downloads.mojom-lite.js", - ] +if (optimize_webui) { + downloads_pak_file = "downloads_resources.pak" + unpak_folder = "downloads_resources.unpak" + + optimize_webui("build") { + host = "downloads" + html_in_files = [ "downloads.html" ] + html_out_files = [ "vulcanized.html" ] + insert_in_head = "<base href=chrome://downloads>" + input = rebase_path("$target_gen_dir/$unpak_folder", root_build_dir) + js_out_files = [ "crisper.js" ] + excludes = [ + "chrome://resources/js/mojo_bindings_lite.js", + "chrome://downloads/downloads.mojom-lite.js", + ] + + deps = [ + ":unpak", + ] + } + + unpak("unpak") { + pak_file = downloads_pak_file + out_folder = unpak_folder + + deps = [ + ":flattened_resources", + ] + } + + grit("flattened_resources") { + source = "downloads_resources.grd" + + # The .grd contains references to generated files. + source_is_generated = true + + defines = chrome_grit_defines + outputs = [ + "grit/downloads_resources.h", + "grit/downloads_resources_map.cc", + "grit/downloads_resources_map.h", + downloads_pak_file, + ] + deps = [ + "//chrome/browser/ui/webui/downloads:mojo_bindings", + ] + grit_flags = [ + "-E", + "root_gen_dir=" + rebase_path(root_gen_dir, root_build_dir), + ] + output_dir = "$root_gen_dir/chrome/browser/resources/downloads" + } } js_type_check("closure_compile") { @@ -66,6 +108,7 @@ ":constants", ":icon_loader", "//third_party/polymer/v1_0/components-chromium/paper-behaviors:paper-inky-focus-behavior-extracted", + "//ui/webui/resources/cr_elements/cr_toast:cr_toast_manager", "//ui/webui/resources/js:cr", "//ui/webui/resources/js:load_time_data", "//ui/webui/resources/js:util",
diff --git a/chrome/browser/resources/downloads/downloads_resources.grd b/chrome/browser/resources/downloads/downloads_resources.grd new file mode 100644 index 0000000..ba9c485 --- /dev/null +++ b/chrome/browser/resources/downloads/downloads_resources.grd
@@ -0,0 +1,83 @@ +<?xml version="1.0" encoding="UTF-8"?> +<grit latest_public_release="0" current_release="1" output_all_resource_defines="false"> + <outputs> + <output filename="grit/downloads_resources.h" type="rc_header"> + <emit emit_type='prepend'></emit> + </output> + <output filename="grit/downloads_resources_map.cc" + type="resource_file_map_source" /> + <output filename="grit/downloads_resources_map.h" + type="resource_map_header" /> + <output filename="downloads_resources.pak" type="data_package" /> + </outputs> + <release seq="1"> + <includes> + <include name="IDR_DOWNLOADS_IMAGES_INCOGNITO_MARKER_SVG" + file="images\incognito_marker.svg" + type="BINDATA" /> + <include name="IDR_DOWNLOADS_IMAGES_NO_DOWNLOADS_SVG" + file="images\no_downloads.svg" + type="BINDATA" /> + <include name="IDR_DOWNLOADS_MOJO_LITE_JS" + file="${root_gen_dir}\chrome\browser\ui\webui\downloads\downloads.mojom-lite.js" + use_base_dir="false" + type="BINDATA" /> + </includes> + <structures> + <structure name="IDR_DOWNLOADS_DOWNLOADS_HTML" + file="downloads.html" + preprocess="true" + type="chrome_html" /> + <structure name="IDR_DOWNLOADS_BROWSER_PROXY_HTML" + file="browser_proxy.html" + type="chrome_html" /> + <structure name="IDR_DOWNLOADS_BROWSER_PROXY_JS" + file="browser_proxy.js" + type="chrome_html" /> + <structure name="IDR_DOWNLOADS_CONSTANTS_HTML" + file="constants.html" + type="chrome_html" /> + <structure name="IDR_DOWNLOADS_CONSTANTS_JS" + file="constants.js" + type="chrome_html" /> + <structure name="IDR_DOWNLOADS_DOWNLOADS_JS" + file="downloads.js" + type="chrome_html" /> + <structure name="IDR_DOWNLOADS_I18N_SETUP_HTML" + file="i18n_setup.html" + type="chrome_html" /> + <structure name="IDR_DOWNLOADS_ICON_LOADER_HTML" + file="icon_loader.html" + type="chrome_html" /> + <structure name="IDR_DOWNLOADS_ICON_LOADER_JS" + file="icon_loader.js" type="chrome_html" /> + <structure name="IDR_DOWNLOADS_ICONS_HTML" + file="icons.html" + type="chrome_html" /> + <structure name="IDR_DOWNLOADS_ITEM_HTML" + file="item.html" + type="chrome_html" /> + <structure name="IDR_DOWNLOADS_ITEM_JS" + file="item.js" + type="chrome_html" /> + <structure name="IDR_DOWNLOADS_MANAGER_HTML" + file="manager.html" + type="chrome_html" /> + <structure name="IDR_DOWNLOADS_MANAGER_JS" + file="manager.js" + type="chrome_html" /> + <structure name="IDR_DOWNLOADS_SEARCH_SERVICE_HTML" + file="search_service.html" + type="chrome_html" /> + <structure name="IDR_DOWNLOADS_SEARCH_SERVICE_JS" + file="search_service.js" + type="chrome_html" /> + <structure name="IDR_DOWNLOADS_TOOLBAR_HTML" + file="toolbar.html" + type="chrome_html" /> + <structure name="IDR_DOWNLOADS_TOOLBAR_JS" + file="toolbar.js" + type="chrome_html" /> + </structures> + </release> +</grit>
diff --git a/chrome/browser/resources/downloads/downloads_resources_vulcanized.grd b/chrome/browser/resources/downloads/downloads_resources_vulcanized.grd new file mode 100644 index 0000000..71179dc --- /dev/null +++ b/chrome/browser/resources/downloads/downloads_resources_vulcanized.grd
@@ -0,0 +1,40 @@ +<?xml version="1.0" encoding="UTF-8"?> +<grit latest_public_release="0" current_release="1" output_all_resource_defines="false"> + <outputs> + <output filename="grit/downloads_resources.h" type="rc_header"> + <emit emit_type='prepend'></emit> + </output> + <output filename="grit/downloads_resources_map.cc" + type="resource_map_source" /> + <output filename="grit/downloads_resources_map.h" + type="resource_map_header" /> + <output filename="downloads_resources.pak" type="data_package" /> + </outputs> + <release seq="1"> + <includes> + <include name="IDR_DOWNLOADS_IMAGES_INCOGNITO_MARKER_SVG" + file="images\incognito_marker.svg" + type="BINDATA" /> + <include name="IDR_DOWNLOADS_IMAGES_NO_DOWNLOADS_SVG" + file="images\no_downloads.svg" + type="BINDATA" /> + <include name="IDR_DOWNLOADS_MOJO_LITE_JS" + file="${root_gen_dir}\chrome\browser\ui\webui\downloads\downloads.mojom-lite.js" + use_base_dir="false" + compress="gzip" + type="BINDATA" /> + <include name="IDR_DOWNLOADS_VULCANIZED_HTML" + file="${root_gen_dir}\chrome\browser\resources\downloads\vulcanized.html" + use_base_dir="false" + preprocess="true" + compress="gzip" + type="BINDATA" /> + <include name="IDR_DOWNLOADS_CRISPER_JS" + file="${root_gen_dir}\chrome\browser\resources\downloads\crisper.js" + use_base_dir="false" + preprocess="true" + compress="gzip" + type="BINDATA" /> + </includes> + </release> +</grit>
diff --git a/chrome/browser/resources/downloads/item.html b/chrome/browser/resources/downloads/item.html index d75108d..31f4800 100644 --- a/chrome/browser/resources/downloads/item.html +++ b/chrome/browser/resources/downloads/item.html
@@ -7,6 +7,7 @@ <link rel="import" href="chrome://downloads/icons.html"> <link rel="import" href="chrome://resources/cr_elements/cr_icon_button/cr_icon_button.html"> <link rel="import" href="chrome://resources/cr_elements/cr_icons_css.html"> +<link rel="import" href="chrome://resources/cr_elements/cr_toast/cr_toast_manager.html"> <link rel="import" href="chrome://resources/cr_elements/hidden_style_css.html"> <link rel="import" href="chrome://resources/cr_elements/icons.html"> <link rel="import" href="chrome://resources/cr_elements/paper_button_style_css.html">
diff --git a/chrome/browser/resources/downloads/item.js b/chrome/browser/resources/downloads/item.js index 921f573..b96fff2 100644 --- a/chrome/browser/resources/downloads/item.js +++ b/chrome/browser/resources/downloads/item.js
@@ -452,6 +452,13 @@ /** @private */ onRemoveTap_: function() { + const pieces = loadTimeData.getSubstitutedStringPieces( + loadTimeData.getString('toastRemovedFromList'), this.data.fileName); + pieces.forEach(p => { + // Make the file name collapsible. + p.collapsible = !!p.arg; + }); + cr.toastManager.getInstance().showForStringPieces(pieces, true); this.mojoHandler_.remove(this.data.id); this.fire('restore-focus-after-remove'); },
diff --git a/chrome/browser/resources/downloads/manager.js b/chrome/browser/resources/downloads/manager.js index 046603a7..a8d6788 100644 --- a/chrome/browser/resources/downloads/manager.js +++ b/chrome/browser/resources/downloads/manager.js
@@ -249,7 +249,6 @@ */ removeItem_: function(index) { const removed = this.items_.splice(index, 1); - const removedFileName = removed[0].fileName; this.updateHideDates_(index, index); this.notifySplices('items_', [{ index: index, @@ -258,13 +257,6 @@ type: 'splice', removed: removed, }]); - const pieces = loadTimeData.getSubstitutedStringPieces( - loadTimeData.getString('toastRemovedFromList'), removedFileName); - pieces.forEach(p => { - // Make the file name collapsible. - p.collapsible = !!p.arg; - }); - cr.toastManager.getInstance().showForStringPieces(pieces, true); if (this.restoreFocusAfterRemove_) { this.restoreFocusAfterRemove_ = false; if (this.items_.length > 0) {
diff --git a/chrome/browser/resources/downloads/toolbar.html b/chrome/browser/resources/downloads/toolbar.html index 42d38f18..acbdae2 100644 --- a/chrome/browser/resources/downloads/toolbar.html +++ b/chrome/browser/resources/downloads/toolbar.html
@@ -4,6 +4,7 @@ <link rel="import" href="chrome://downloads/browser_proxy.html"> <link rel="import" href="chrome://resources/cr_elements/cr_action_menu/cr_action_menu.html"> <link rel="import" href="chrome://resources/cr_elements/cr_icon_button/cr_icon_button.html"> +<link rel="import" href="chrome://resources/cr_elements/cr_toast/cr_toast_manager.html"> <link rel="import" href="chrome://resources/cr_elements/cr_toolbar/cr_toolbar.html"> <link rel="import" href="chrome://resources/cr_elements/hidden_style_css.html"> <link rel="import" href="chrome://resources/cr_elements/icons.html">
diff --git a/chrome/browser/resources/local_ntp/custom_backgrounds.js b/chrome/browser/resources/local_ntp/custom_backgrounds.js index 0a06fa4b..196d9a4 100644 --- a/chrome/browser/resources/local_ntp/custom_backgrounds.js +++ b/chrome/browser/resources/local_ntp/custom_backgrounds.js
@@ -76,6 +76,7 @@ ATTRIBUTIONS: 'custom-bg-attr', BACK_CIRCLE: 'bg-sel-back-circle', BACKGROUNDS_BUTTON: 'backgrounds-button', + BACKGROUNDS_IMAGE_MENU: 'backgrounds-image-menu', BACKGROUNDS_MENU: 'backgrounds-menu', CANCEL: 'bg-sel-footer-cancel', COLORS_BUTTON: 'colors-button', @@ -91,7 +92,9 @@ EDIT_BG_ICON: 'edit-bg-icon', EDIT_BG_MENU: 'edit-bg-menu', EDIT_BG_TEXT: 'edit-bg-text', + MENU_BACK: 'menu-back', MENU_CANCEL: 'menu-cancel', + MENU_TITLE: 'menu-title', LINK_ICON: 'link-icon', MENU: 'bg-sel-menu', OPTIONS_TITLE: 'edit-bg-title', @@ -121,6 +124,7 @@ // Extended and elevated style for entry point. ENTRY_POINT_ENHANCED: 'ep-enhanced', IMAGE_DIALOG: 'is-img-sel', + ON_IMAGE_MENU: 'on-img-menu', OPTION: 'bg-option', OPTION_DISABLED: 'bg-option-disabled', // The menu option is disabled. MENU_SHOWN: 'menu-shown', @@ -290,6 +294,24 @@ customBackgrounds.unselectTile(); }; +/** + * Remove image tiles and maybe swap back to main background menu. + * @param {boolean} showMenu Whether the main background menu should be shown. + */ +customBackgrounds.resetImageMenu = function(showMenu) { + const backgroundMenu = $(customBackgrounds.IDS.BACKGROUNDS_MENU); + const imageMenu = $(customBackgrounds.IDS.BACKGROUNDS_IMAGE_MENU); + const menu = $(customBackgrounds.IDS.CUSTOMIZATION_MENU); + const menuTitle = $(customBackgrounds.IDS.MENU_TITLE); + + imageMenu.innerHTML = ''; + imageMenu.classList.toggle(customBackgrounds.CLASSES.MENU_SHOWN, false); + menuTitle.textContent = menuTitle.dataset.mainTitle; + menu.classList.toggle(customBackgrounds.CLASSES.ON_IMAGE_MENU, false); + backgroundMenu.classList.toggle( + customBackgrounds.CLASSES.MENU_SHOWN, showMenu); +}; + /* Close the collection selection dialog and cleanup the state * @param {dialog} menu The dialog to be closed */ @@ -402,8 +424,10 @@ // Create dialog header. $(customBackgrounds.IDS.TITLE).textContent = configData.translatedStrings.selectChromeWallpaper; - menu.classList.add(customBackgrounds.CLASSES.COLLECTION_DIALOG); - menu.classList.remove(customBackgrounds.CLASSES.IMAGE_DIALOG); + if (!configData.richerPicker) { + menu.classList.toggle(customBackgrounds.CLASSES.COLLECTION_DIALOG); + menu.classList.remove(customBackgrounds.CLASSES.IMAGE_DIALOG); + } // Create dialog tiles. for (let i = 0; i < coll.length; ++i) { @@ -451,6 +475,11 @@ // Dependent upon the success of the load, populate the image selection // dialog or close the current dialog. if (imageDataLoaded) { + $(customBackgrounds.IDS.BACKGROUNDS_MENU) + .classList.toggle(customBackgrounds.CLASSES.MENU_SHOWN, false); + $(customBackgrounds.IDS.BACKGROUNDS_IMAGE_MENU) + .classList.toggle(customBackgrounds.CLASSES.MENU_SHOWN, true); + customBackgrounds.resetSelectionDialog(); customBackgrounds.showImageSelectionDialog(tile.dataset.name); } else { @@ -547,12 +576,20 @@ customBackgrounds.showImageSelectionDialog = function(dialogTitle) { const firstNTile = customBackgrounds.ROWS_TO_PRELOAD * customBackgrounds.getTilesWide(); - const menu = $(customBackgrounds.IDS.MENU); - const tileContainer = $(customBackgrounds.IDS.TILES); + const tileContainer = configData.richerPicker ? + $(customBackgrounds.IDS.BACKGROUNDS_IMAGE_MENU) : + $(customBackgrounds.IDS.TILES); + const menu = configData.richerPicker ? + $(customBackgrounds.IDS.CUSTOMIZATION_MENU) : + $(customBackgrounds.IDS.MENU); - $(customBackgrounds.IDS.TITLE).textContent = dialogTitle; - menu.classList.remove(customBackgrounds.CLASSES.COLLECTION_DIALOG); - menu.classList.add(customBackgrounds.CLASSES.IMAGE_DIALOG); + $(customBackgrounds.IDS.MENU_TITLE).textContent = dialogTitle; + if (configData.richerPicker) { + menu.classList.toggle(customBackgrounds.CLASSES.ON_IMAGE_MENU, true); + } else { + menu.classList.remove(customBackgrounds.CLASSES.COLLECTION_DIALOG); + menu.classList.add(customBackgrounds.CLASSES.IMAGE_DIALOG); + } const preLoadTiles = []; const postLoadTiles = []; @@ -811,6 +848,10 @@ $(customBackgrounds.IDS.OPTIONS_TITLE).textContent = configData.translatedStrings.customizeBackground; + // Store the main menu title so it can be restored if needed. + $(customBackgrounds.IDS.MENU_TITLE).dataset.mainTitle = + $(customBackgrounds.IDS.MENU_TITLE).textContent; + $(customBackgrounds.IDS.EDIT_BG_ICON) .setAttribute( 'aria-label', configData.translatedStrings.customizeThisPage); @@ -1142,11 +1183,15 @@ // Interactions with the back arrow on the image selection dialog. const backInteraction = function(event) { + if (configData.richerPicker) { + customBackgrounds.resetImageMenu(true); + } customBackgrounds.resetSelectionDialog(); customBackgrounds.showCollectionSelectionDialog( customBackgrounds.dialogCollectionsSource); }; $(customBackgrounds.IDS.BACK_CIRCLE).onclick = backInteraction; + $(customBackgrounds.IDS.MENU_BACK).onclick = backInteraction; $(customBackgrounds.IDS.BACK_CIRCLE).onkeyup = function(event) { if (event.keyCode === customBackgrounds.KEYCODES.ENTER || event.keyCode === customBackgrounds.KEYCODES.SPACE) { @@ -1216,13 +1261,11 @@ }; $(customBackgrounds.IDS.SHORTCUTS_BUTTON).onclick = function() { - $(customBackgrounds.IDS.BACKGROUNDS_MENU) - .classList.toggle(customBackgrounds.CLASSES.MENU_SHOWN, false); + customBackgrounds.resetImageMenu(false); }; $(customBackgrounds.IDS.COLORS_BUTTON).onclick = function() { - $(customBackgrounds.IDS.BACKGROUNDS_MENU) - .classList.toggle(customBackgrounds.CLASSES.MENU_SHOWN, false); + customBackgrounds.resetImageMenu(false); }; };
diff --git a/chrome/browser/resources/local_ntp/local_ntp.css b/chrome/browser/resources/local_ntp/local_ntp.css index b4444029..221d0a9aa 100644 --- a/chrome/browser/resources/local_ntp/local_ntp.css +++ b/chrome/browser/resources/local_ntp/local_ntp.css
@@ -922,14 +922,28 @@ user-select: none; } +#menu-header { + height: 80px; + +} + +#menu-title-wrapper { + display: inline-block; + height: 80px; + position: absolute; +} + #menu-title { font-size: 16px; - height: 48px; - line-height: 48px; - margin-bottom: 8px; - margin-inline-start: 235px; - margin-top: 24px; + height: 20px; + line-height: 20px; + margin-top: 38px; user-select: none; + width: fit-content; +} + +.on-img-menu #menu-title { + margin-inline-start: 16px; } #menu-footer { @@ -975,16 +989,27 @@ width: 100%; } -#backgrounds-menu .bg-sel-tile-bg { +.menu-panel.menu-shown { + visibility: visible; +} + +#backgrounds-menu .bg-sel-tile-bg, +#backgrounds-image-menu .bg-sel-tile-bg { border-radius: 4px; height: 176px; margin-bottom: 45px; margin-inline-end: 8px; margin-inline-start: 0; + margin-top: 0; width: 176px; } -#backgrounds-menu .bg-sel-tile { +#backgrounds-image-menu .bg-sel-tile-bg { + margin-bottom: 8px; +} + +#backgrounds-menu .bg-sel-tile, +#backgrounds-image-menu .bg-sel-tile { background-position: center; border-radius: 4px; } @@ -1002,7 +1027,7 @@ background-color: white; border: 1px solid black; height: 174px; - margin-inline-end: 6px + margin-inline-end: 6px; width: 174px; } @@ -1015,6 +1040,27 @@ width: 174px; } -.menu-shown { +#menu-back-wrapper { + display: inline-block; + height: 80px; +} + +#menu-back { + background: url(../../../../ui/webui/resources/images/icon_arrow_back.svg) no-repeat center; + background-size: 20px 20px; + height: 20px; + margin-inline-start: 192px; + margin-top: 39px; + outline: none; + visibility: hidden; + width: 20px; +} + +html[dir=rtl] #menu-back { + transform: scaleX(-1); +} + +.on-img-menu #menu-back { + margin-inline-start: 212px; visibility: visible; }
diff --git a/chrome/browser/resources/local_ntp/local_ntp.html b/chrome/browser/resources/local_ntp/local_ntp.html index 000706a1..02b33e5 100644 --- a/chrome/browser/resources/local_ntp/local_ntp.html +++ b/chrome/browser/resources/local_ntp/local_ntp.html
@@ -170,7 +170,14 @@ </dialog> <dialog id="customization-menu" class="customize-dialog"> - <div id="menu-title">$i18n{customizeMenuTitle}</div> + <div id="menu-header"> + <div id="menu-back-wrapper"> + <div id="menu-back"></div> + </div> + <div id="menu-title-wrapper"> + <div id="menu-title">$i18n{customizeMenuTitle}</div> + </div> + </div> <div id="menu-nav-panel"> <div id="backgrounds-button" class="menu-option" tabindex="0"> <div class="menu-option-icon-wrapper"> @@ -198,6 +205,7 @@ <div class="bg-sel-tile-title">Default</div> </div> </div> + <div id="backgrounds-image-menu" class="menu-panel"></div> </div> <div id="menu-footer"> <button id="menu-cancel" class="bg-sel-footer-button paper secondary
diff --git a/chrome/browser/resources/local_ntp/most_visited_single.js b/chrome/browser/resources/local_ntp/most_visited_single.js index 1d08965..a763387 100644 --- a/chrome/browser/resources/local_ntp/most_visited_single.js +++ b/chrome/browser/resources/local_ntp/most_visited_single.js
@@ -237,14 +237,20 @@ this.tileWidth_ = 0; /** @private {number} */ this.tilesAlwaysVisible_ = 0; - /** @private {number} */ + /** + * The maximum number of tiles per row allowed by the grid parameters. + * @private {number} + */ this.maxTilesPerRow_ = 0; /** @private {number} */ this.maxTiles_ = 0; /** @private {number} */ this.gridWidth_ = 0; - /** @private {number} */ + /** + * The maximum number of tiles per row allowed by the window width. + * @private {number} + */ this.maxTilesPerRowWindow_ = 0; /** @private {?Element} */ @@ -393,17 +399,24 @@ /** - * Returns the number of tiles per row. This may be balanced if there are more - * than |this.maxTilesPerRow_| in order to make even rows. + * Returns the number of tiles per row. This may be balanced in order to make + * even rows. * @return {number} The number of tiles per row. * @private */ getTilesPerRow_() { - const tilesPerRow = (this.tiles_.length > this.maxTilesPerRow_) ? - Math.ceil(this.tiles_.length / 2) : - this.tiles_.length; - // The number of tiles cannot exceed the max allowed by the window size. - return Math.min(tilesPerRow, this.maxTilesPerRowWindow_); + const maxTilesPerRow = + Math.min(this.maxTilesPerRow_, this.maxTilesPerRowWindow_); + if (this.tiles_.length >= maxTilesPerRow * 2) { + // We have enough for two full rows, so just return the max. + return maxTilesPerRow; + } else if (this.tiles_.length > maxTilesPerRow) { + // We have have a little more than one full row, so we need to rebalance. + return Math.ceil(this.tiles_.length / 2); + } else { + // We have (less than) a full row, so just return the tiles we have. + return this.tiles_.length; + } } @@ -555,8 +568,9 @@ // Shift tiles according to the new order. for (let i = 0; i < this.tiles_.length; i++) { const tileIndex = this.order_[i]; - // Don't move the tile we're holding. - if (tileIndex === this.itemToReorder_) { + // Don't move the tile we're holding nor the add shortcut button. + if (tileIndex === this.itemToReorder_ || + this.tiles_[i].getAttribute('add') === 'true') { continue; } this.applyReorder_(this.tiles_[tileIndex], i); @@ -573,6 +587,9 @@ * @private */ applyReorder_(tile, newIndex) { + if (tile.getAttribute('index') === null) { + throw new Error('Tile does not have an index.'); + } const index = Number(tile.getAttribute('index')); const x = this.position_[newIndex].x - this.position_[index].x; const y = this.position_[newIndex].y - this.position_[index].y;
diff --git a/chrome/browser/resources/safe_browsing/download_file_types.asciipb b/chrome/browser/resources/safe_browsing/download_file_types.asciipb index 3bc8ad0..b0532e9 100644 --- a/chrome/browser/resources/safe_browsing/download_file_types.asciipb +++ b/chrome/browser/resources/safe_browsing/download_file_types.asciipb
@@ -706,7 +706,7 @@ ping_setting: FULL_PING inspection_type: ZIP platform_settings { - max_file_size_to_analyze: 52428800 # 50MB + max_file_size_to_analyze: 15728640 # 15MB } } file_types {
diff --git a/chrome/browser/resources/settings/basic_page/basic_page.html b/chrome/browser/resources/settings/basic_page/basic_page.html index c9e4d46..23abb7b5 100644 --- a/chrome/browser/resources/settings/basic_page/basic_page.html +++ b/chrome/browser/resources/settings/basic_page/basic_page.html
@@ -174,16 +174,7 @@ <template is="dom-if" if="[[showPage_(pageVisibility.search)]]" restamp> <settings-section page-title="$i18n{searchPageTitle}" section="search"> -<if expr="chromeos"> - <settings-search-page prefs="{{prefs}}" - arc-enabled="[[prefs.arc.enabled.value]]" - voice-interaction-value-prop-accepted="[[ - prefs.arc.voice_interaction_value_prop.accepted.value]]"> - </settings-search-page> -</if> -<if expr="not chromeos"> <settings-search-page prefs="{{prefs}}"></settings-search-page> -</if> </settings-section> </template> <if expr="chromeos">
diff --git a/chrome/browser/resources/settings/chromeos/os_settings_page/os_settings_page.html b/chrome/browser/resources/settings/chromeos/os_settings_page/os_settings_page.html index 099dd4ac..a26c929 100644 --- a/chrome/browser/resources/settings/chromeos/os_settings_page/os_settings_page.html +++ b/chrome/browser/resources/settings/chromeos/os_settings_page/os_settings_page.html
@@ -150,11 +150,7 @@ <template is="dom-if" if="[[showPage_(pageVisibility.search)]]" restamp> <settings-section page-title="$i18n{searchPageTitle}" section="search"> - <settings-search-page prefs="{{prefs}}" - arc-enabled="[[prefs.arc.enabled.value]]" - voice-interaction-value-prop-accepted="[[ - prefs.arc.voice_interaction_value_prop.accepted.value]]"> - </settings-search-page> + <settings-search-page prefs="{{prefs}}"></settings-search-page> </settings-section> </template> <template is="dom-if" if="[[shouldCreateAndroidAppsSection_(
diff --git a/chrome/browser/resources/settings/google_assistant_page/google_assistant_page.html b/chrome/browser/resources/settings/google_assistant_page/google_assistant_page.html index 61c613ff..344d9ab 100644 --- a/chrome/browser/resources/settings/google_assistant_page/google_assistant_page.html +++ b/chrome/browser/resources/settings/google_assistant_page/google_assistant_page.html
@@ -52,7 +52,7 @@ label="$i18n{googleAssistantEnableContext}" sub-label="$i18n{googleAssistantEnableContextDescription}"> </settings-toggle-button> - <template is="dom-if" if="[[assistantFeatureEnabled_]]"> + <template is="dom-if" if="[[isAssistantAllowed_]]"> <settings-toggle-button id="google-assistant-hotword-enable" pref="{{prefs.settings.voice_interaction.hotword.enabled}}" label="$i18n{googleAssistantEnableHotword}"
diff --git a/chrome/browser/resources/settings/google_assistant_page/google_assistant_page.js b/chrome/browser/resources/settings/google_assistant_page/google_assistant_page.js index ca0bb30d..b68ac142 100644 --- a/chrome/browser/resources/settings/google_assistant_page/google_assistant_page.js +++ b/chrome/browser/resources/settings/google_assistant_page/google_assistant_page.js
@@ -45,10 +45,10 @@ properties: { /** @private */ - assistantFeatureEnabled_: { + isAssistantAllowed_: { type: Boolean, value: function() { - return loadTimeData.getBoolean('enableAssistant'); + return loadTimeData.getBoolean('isAssistantAllowed'); }, },
diff --git a/chrome/browser/resources/settings/search_engines_page/search_engines_browser_proxy.js b/chrome/browser/resources/settings/search_engines_page/search_engines_browser_proxy.js index ab81a32..d8a275e 100644 --- a/chrome/browser/resources/settings/search_engines_page/search_engines_browser_proxy.js +++ b/chrome/browser/resources/settings/search_engines_page/search_engines_browser_proxy.js
@@ -68,8 +68,6 @@ * @return {!Promise<boolean>} */ validateSearchEngineInput(fieldName, fieldValue) {} - - turnOnGoogleAssistant() {} } /** @@ -115,11 +113,6 @@ return cr.sendWithPromise( 'validateSearchEngineInput', fieldName, fieldValue); } - - /** @override */ - turnOnGoogleAssistant() { - chrome.send('turnOnGoogleAssistant'); - } } // The singleton instance_ is replaced with a test version of this wrapper
diff --git a/chrome/browser/resources/settings/search_page/search_page.html b/chrome/browser/resources/settings/search_page/search_page.html index d2797c0..aabee77 100644 --- a/chrome/browser/resources/settings/search_page/search_page.html +++ b/chrome/browser/resources/settings/search_page/search_page.html
@@ -6,7 +6,6 @@ <link rel="import" href="chrome://resources/html/assert.html"> <link rel="import" href="chrome://resources/html/i18n_behavior.html"> <link rel="import" href="chrome://resources/html/md_select_css.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html"> <link rel="import" href="../controls/extension_controlled_indicator.html"> <link rel="import" href="../controls/settings_toggle_button.html"> <link rel="import" href="../icons.html"> @@ -86,7 +85,7 @@ <if expr="chromeos"> <!-- Google Assistant --> - <template is="dom-if" if="[[voiceInteractionFeatureEnabled_]]"> + <template is="dom-if" if="[[isAssistantAllowed_]]"> <div id="assistant-subpage-trigger" class="settings-box two-line" on-click="onGoogleAssistantTap_" actionable> <div class="start"> @@ -96,19 +95,8 @@ prefs.settings.voice_interaction.enabled.value)]] </div> </div> - <template is="dom-if" if="[[assistantOn_]]"> - <cr-icon-button class="subpage-arrow" - aria-label="$i18n{searchGoogleAssistant}"></cr-icon-button> - </template> - <template is="dom-if" if="[[!assistantOn_]]"> - <div class="separator"></div> - <paper-button id="enable" class="secondary-button" - on-click="onAssistantTurnOnTap_" - aria-label="$i18n{searchPageTitle}" - aria-describedby="secondaryText"> - $i18n{assistantTurnOn} - </paper-button> - </template> + <cr-icon-button class="subpage-arrow" + aria-label="$i18n{searchGoogleAssistant}"></cr-icon-button> </div> </template> </if> @@ -123,7 +111,7 @@ </settings-subpage> </template> <if expr="chromeos"> - <template is="dom-if" if="[[voiceInteractionFeatureEnabled_]]"> + <template is="dom-if" if="[[isAssistantAllowed_]]"> <template is="dom-if" route-path="/googleAssistant"> <settings-subpage associated-control="[[$$('#assistant-subpage-trigger')]]"
diff --git a/chrome/browser/resources/settings/search_page/search_page.js b/chrome/browser/resources/settings/search_page/search_page.js index 114c3f15..2ac4cc4 100644 --- a/chrome/browser/resources/settings/search_page/search_page.js +++ b/chrome/browser/resources/settings/search_page/search_page.js
@@ -14,12 +14,6 @@ properties: { prefs: Object, - // <if expr="chromeos"> - arcEnabled: Boolean, - - voiceInteractionValuePropAccepted: Boolean, - // </if> - /** * List of default search engines available. * @private {!Array<!SearchEngine>} @@ -38,28 +32,13 @@ focusConfig_: Object, // <if expr="chromeos"> - /** @private */ - voiceInteractionFeatureEnabled_: { + /** @private Can be disallowed due to flag, policy, locale, etc. */ + isAssistantAllowed_: { type: Boolean, value: function() { - return loadTimeData.getBoolean('enableVoiceInteraction'); + return loadTimeData.getBoolean('isAssistantAllowed'); }, }, - - /** @private */ - assistantFeatureEnabled_: { - type: Boolean, - value: function() { - return loadTimeData.getBoolean('enableAssistant'); - }, - }, - - /** @private */ - assistantOn_: { - type: Boolean, - computed: 'isAssistantTurnedOn_(arcEnabled, ' + - 'voiceInteractionValuePropAccepted, assistantFeatureEnabled_)', - } // </if> }, @@ -115,19 +94,9 @@ // <if expr="chromeos"> /** @private */ onGoogleAssistantTap_: function() { - assert(this.voiceInteractionFeatureEnabled_); - - if (!this.assistantOn_) { - return; - } - + assert(this.isAssistantAllowed_); settings.navigateTo(settings.routes.GOOGLE_ASSISTANT); }, - - /** @private */ - onAssistantTurnOnTap_: function(event) { - this.browserProxy_.turnOnGoogleAssistant(); - }, // </if> // <if expr="chromeos"> @@ -141,17 +110,6 @@ toggleValue ? 'searchGoogleAssistantEnabled' : 'searchGoogleAssistantDisabled'); }, - - /** @private - * @param {boolean} arcEnabled - * @param {boolean} valuePropAccepted - * @param {boolean} assistantFeatureEnabled - * @return {boolean} - */ - isAssistantTurnedOn_: function( - arcEnabled, valuePropAccepted, assistantFeatureEnabled) { - return (arcEnabled && valuePropAccepted) || assistantFeatureEnabled; - }, // </if> /**
diff --git a/chrome/browser/sync/test/integration/two_client_send_tab_to_self_sync_test.cc b/chrome/browser/sync/test/integration/two_client_send_tab_to_self_sync_test.cc index ffcd7df6..d72bcf5 100644 --- a/chrome/browser/sync/test/integration/two_client_send_tab_to_self_sync_test.cc +++ b/chrome/browser/sync/test/integration/two_client_send_tab_to_self_sync_test.cc
@@ -14,6 +14,7 @@ #include "components/send_tab_to_self/features.h" #include "components/send_tab_to_self/send_tab_to_self_model.h" #include "components/send_tab_to_self/send_tab_to_self_sync_service.h" +#include "components/send_tab_to_self/target_device_info.h" #include "components/sync/driver/sync_driver_switches.h" #include "components/sync_device_info/device_info.h" #include "components/sync_device_info/device_info_sync_service.h" @@ -188,3 +189,34 @@ EXPECT_NE(device_infos[0]->send_tab_to_self_receiving_enabled(), device_infos[1]->send_tab_to_self_receiving_enabled()); } + +IN_PROC_BROWSER_TEST_F(TwoClientSendTabToSelfSyncTest, + SendTabToSelfTargetDeviceMap) { + ASSERT_TRUE(SetupSync()); + + DeviceInfoSyncServiceFactory::GetForProfile(GetProfile(0)) + ->GetDeviceInfoTracker() + ->ForcePulseForTest(); + DeviceInfoSyncServiceFactory::GetForProfile(GetProfile(1)) + ->GetDeviceInfoTracker() + ->ForcePulseForTest(); + + ASSERT_TRUE(send_tab_to_self_helper::SendTabToSelfMultiDeviceActiveChecker( + DeviceInfoSyncServiceFactory::GetForProfile(GetProfile(1)) + ->GetDeviceInfoTracker()) + .Wait()); + + std::map<std::string, send_tab_to_self::TargetDeviceInfo> + profile1_target_device_map = + SendTabToSelfSyncServiceFactory::GetForProfile(GetProfile(0)) + ->GetSendTabToSelfModel() + ->GetTargetDeviceNameToCacheInfoMap(); + std::map<std::string, send_tab_to_self::TargetDeviceInfo> + profile2_target_device_map = + SendTabToSelfSyncServiceFactory::GetForProfile(GetProfile(1)) + ->GetSendTabToSelfModel() + ->GetTargetDeviceNameToCacheInfoMap(); + + EXPECT_EQ(1u, profile1_target_device_map.size()); + EXPECT_EQ(1u, profile2_target_device_map.size()); +}
diff --git a/chrome/browser/taskbar/taskbar_decorator_win.cc b/chrome/browser/taskbar/taskbar_decorator_win.cc index 72adc4e0..c35a72c 100644 --- a/chrome/browser/taskbar/taskbar_decorator_win.cc +++ b/chrome/browser/taskbar/taskbar_decorator_win.cc
@@ -149,12 +149,12 @@ // |content| fits into our 16x16px icon, with margins. do { font.setSize(text_size--); - font.measureText(content.c_str(), content.size(), kUTF8_SkTextEncoding, + font.measureText(content.c_str(), content.size(), SkTextEncoding::kUTF8, &bounds); } while (text_size >= kMinTextSize && (bounds.width() > kMaxBounds || bounds.height() > kMaxBounds)); - canvas.drawSimpleText(content.c_str(), content.size(), kUTF8_SkTextEncoding, + canvas.drawSimpleText(content.c_str(), content.size(), SkTextEncoding::kUTF8, kRadius - bounds.width() / 2 - bounds.x(), kRadius - bounds.height() / 2 - bounds.y(), font, paint);
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index a878ef7..b329c243 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn
@@ -784,6 +784,10 @@ "bluetooth/bluetooth_chooser_controller.h", "bluetooth/bluetooth_chooser_desktop.cc", "bluetooth/bluetooth_chooser_desktop.h", + "bluetooth/bluetooth_scanning_prompt_controller.cc", + "bluetooth/bluetooth_scanning_prompt_controller.h", + "bluetooth/bluetooth_scanning_prompt_desktop.cc", + "bluetooth/bluetooth_scanning_prompt_desktop.h", "bluetooth/chrome_extension_bluetooth_chooser.cc", "bluetooth/chrome_extension_bluetooth_chooser.h", "bookmarks/bookmark_context_menu_controller.cc", @@ -1794,6 +1798,7 @@ "//ash/public/cpp/resources:ash_public_unscaled_resources", "//ash/public/cpp/vector_icons", "//chrome/browser/chromeos", + "//chrome/browser/chromeos/supervision/mojom", "//chrome/browser/ui/webui/chromeos/add_supervision:mojo_bindings", "//chromeos", "//chromeos/assistant:buildflags",
diff --git a/chrome/browser/ui/app_list/app_list_syncable_service_unittest.cc b/chrome/browser/ui/app_list/app_list_syncable_service_unittest.cc index 24ea3d0..0dd2b41 100644 --- a/chrome/browser/ui/app_list/app_list_syncable_service_unittest.cc +++ b/chrome/browser/ui/app_list/app_list_syncable_service_unittest.cc
@@ -263,6 +263,15 @@ content::RunAllTasksUntilIdle(); } + void InstallExtension(extensions::Extension* extension) { + const syncer::StringOrdinal& page_ordinal = + syncer::StringOrdinal::CreateInitialOrdinal(); + service()->OnExtensionInstalled(extension, page_ordinal, + extensions::kInstallFlagNone); + // Allow async callbacks to run. + base::RunLoop().RunUntilIdle(); + } + private: base::ScopedTempDir temp_dir_; std::unique_ptr<AppListModelUpdater::TestApi> model_updater_test_api_; @@ -280,7 +289,7 @@ scoped_refptr<extensions::Extension> store = MakeApp("webstore", web_store_app_id, extensions::Extension::WAS_INSTALLED_BY_DEFAULT); - service_->AddExtension(store.get()); + InstallExtension(store.get()); // Create some app. Note its id should be greater than web store app id in // order to move app in case of conflicting pos after web store app. @@ -288,7 +297,7 @@ scoped_refptr<extensions::Extension> some_app = MakeApp(kSomeAppName, some_app_id, extensions ::Extension::WAS_INSTALLED_BY_DEFAULT); - service_->AddExtension(some_app.get()); + InstallExtension(some_app.get()); ChromeAppListItem* web_store_item = model_updater()->FindItem(web_store_app_id); @@ -305,7 +314,7 @@ const std::string oem_app_id = CreateNextAppId(some_app_id); scoped_refptr<extensions::Extension> oem_app = MakeApp( kOemAppName, oem_app_id, extensions::Extension::WAS_INSTALLED_BY_OEM); - service_->AddExtension(oem_app.get()); + InstallExtension(oem_app.get()); size_t web_store_app_index; size_t some_app_index; @@ -329,7 +338,7 @@ const std::string oem_app_id = CreateNextAppId(extensions::kWebStoreAppId); scoped_refptr<extensions::Extension> oem_app = MakeApp( kOemAppName, oem_app_id, extensions::Extension::WAS_INSTALLED_BY_OEM); - service_->AddExtension(oem_app.get()); + InstallExtension(oem_app.get()); // OEM item is not top level element. ChromeAppListItem* oem_app_item = model_updater()->FindItem(oem_app_id); @@ -357,7 +366,7 @@ const std::string app_id = CreateNextAppId(extensions::kWebStoreAppId); scoped_refptr<extensions::Extension> app = MakeApp( kSomeAppName, app_id, extensions::Extension::WAS_INSTALLED_BY_DEFAULT); - service_->AddExtension(app.get()); + InstallExtension(app.get()); ChromeAppListItem* app_item = model_updater()->FindItem(app_id); ASSERT_TRUE(app_item); @@ -853,13 +862,13 @@ scoped_refptr<extensions::Extension> webstore = MakeApp(kSomeAppName, extensions::kWebStoreAppId, extensions::Extension::WAS_INSTALLED_BY_DEFAULT); - service_->AddExtension(webstore.get()); + InstallExtension(webstore.get()); // Chrome is an existing app to transfer attributes to. scoped_refptr<extensions::Extension> chrome = MakeApp(kSomeAppName, extension_misc::kChromeAppId, extensions::Extension::WAS_INSTALLED_BY_DEFAULT); - service_->AddExtension(chrome.get()); + InstallExtension(chrome.get()); // Youtube is a future app to be installed. scoped_refptr<extensions::Extension> youtube = @@ -915,7 +924,7 @@ AreAllAppAtributesEqualInSync(webstore_sync_item, chrome_sync_item)); // Install Youtube now. - service_->AddExtension(youtube.get()); + InstallExtension(youtube.get()); const app_list::AppListSyncableService::SyncItem* youtube_sync_item = GetSyncItem(extension_misc::kYoutubeAppId); @@ -924,13 +933,6 @@ ASSERT_TRUE(youtube_item); ASSERT_TRUE(youtube_sync_item); - // Note, attributes are not transferred inline for pending app. - EXPECT_TRUE(AreAllAppAtributesNotEqualInAppList(webstore_item, youtube_item)); - EXPECT_TRUE( - AreAllAppAtributesNotEqualInSync(webstore_sync_item, youtube_sync_item)); - - content::RunAllTasksUntilIdle(); - EXPECT_TRUE(AreAllAppAtributesEqualInAppList(webstore_item, youtube_item)); EXPECT_TRUE( AreAllAppAtributesEqualInSync(webstore_sync_item, youtube_sync_item));
diff --git a/chrome/browser/ui/app_list/test/chrome_app_list_test_support.cc b/chrome/browser/ui/app_list/test/chrome_app_list_test_support.cc index f6f65df..4dfcc4c2 100644 --- a/chrome/browser/ui/app_list/test/chrome_app_list_test_support.cc +++ b/chrome/browser/ui/app_list/test/chrome_app_list_test_support.cc
@@ -6,14 +6,20 @@ #include <string> +#include "ash/public/cpp/app_list/app_list_config.h" +#include "ash/public/interfaces/app_list_view.mojom.h" #include "base/bind.h" #include "base/macros.h" #include "base/run_loop.h" +#include "base/strings/stringprintf.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/ui/app_list/app_list_client_impl.h" +#include "chrome/browser/ui/app_list/app_list_model_updater.h" #include "chrome/browser/ui/app_list/app_list_syncable_service.h" #include "chrome/browser/ui/app_list/app_list_syncable_service_factory.h" +#include "chrome/browser/ui/app_list/chrome_app_list_item.h" +#include "components/crx_file/id_util.h" namespace test { @@ -51,6 +57,18 @@ DISALLOW_COPY_AND_ASSIGN(CreateProfileHelper); }; +// Create the icon image for the app-item with |id|. +// TODO(mukai): consolidate the implementation with +// ash/app_list/test/app_list_test_model.cc. +gfx::ImageSkia CreateImageSkia(int id) { + const int size = app_list::AppListConfig::instance().grid_icon_dimension(); + SkBitmap bitmap; + bitmap.allocN32Pixels(size, size); + bitmap.eraseARGB(255, 255 * ((id >> 2) % 2), 255 * ((id >> 1) % 2), + 255 * (id % 2)); + return gfx::ImageSkia::CreateFrom1xBitmap(bitmap); +} + } // namespace AppListModelUpdater* GetModelUpdater(AppListClientImpl* client) { @@ -70,4 +88,26 @@ return helper.CreateAsync(); } +void PopulateDummyAppListItems(int n) { + AppListClientImpl* client = GetAppListClient(); + Profile* profile = client->GetCurrentAppListProfile(); + AppListModelUpdater* model_updater = GetModelUpdater(client); + for (int i = 0; i < n; ++i) { + const std::string app_name = base::StringPrintf("app %d", i); + const std::string app_id = crx_file::id_util::GenerateId(app_name); + auto item = + std::make_unique<ChromeAppListItem>(profile, app_id, model_updater); + gfx::ImageSkia icon = CreateImageSkia(i); + item->SetMetadata(ash::mojom::AppListItemMetadata::New( + app_id, app_name, /*short_name=*/app_name, /*folder_id=*/"", + syncer::StringOrdinal(app_id), /*is_folder=*/false, + /*is_persistent=*/false, icon, /*is_page_break=*/false)); + model_updater->AddItem(std::move(item)); + } + // Wait for the AddItem mojo calls to be handled by Ash. Note that + // FlushMojoForTesting() isn't working well here. + // TODO(mukai): remove this once we eliminate the mojo for app-list. + base::RunLoop().RunUntilIdle(); +} + } // namespace test
diff --git a/chrome/browser/ui/app_list/test/chrome_app_list_test_support.h b/chrome/browser/ui/app_list/test/chrome_app_list_test_support.h index 00c5c4e..4956765 100644 --- a/chrome/browser/ui/app_list/test/chrome_app_list_test_support.h +++ b/chrome/browser/ui/app_list/test/chrome_app_list_test_support.h
@@ -21,6 +21,10 @@ // Creates a second profile in a nested run loop for testing the app list. Profile* CreateSecondProfileAsync(); +// Creates |n| app items with dummy data and adds to the current app-list +// client. +void PopulateDummyAppListItems(int n); + } // namespace test #endif // CHROME_BROWSER_UI_APP_LIST_TEST_CHROME_APP_LIST_TEST_SUPPORT_H_
diff --git a/chrome/browser/ui/ash/chrome_browser_main_extra_parts_ash.cc b/chrome/browser/ui/ash/chrome_browser_main_extra_parts_ash.cc index 1e36234e..7cbc1b9 100644 --- a/chrome/browser/ui/ash/chrome_browser_main_extra_parts_ash.cc +++ b/chrome/browser/ui/ash/chrome_browser_main_extra_parts_ash.cc
@@ -11,7 +11,6 @@ #include "ash/public/cpp/shelf_model.h" #include "ash/public/cpp/window_properties.h" #include "ash/public/interfaces/constants.mojom.h" -#include "ash/public/interfaces/process_creation_time_recorder.mojom.h" #include "ash/shell.h" #include "base/command_line.h" #include "base/task/post_task.h" @@ -74,20 +73,6 @@ #include "chrome/browser/exo_parts.h" #endif -namespace { - -void PushProcessCreationTimeToAsh() { - ash::mojom::ProcessCreationTimeRecorderPtr recorder; - content::ServiceManagerConnection::GetForProcess() - ->GetConnector() - ->BindInterface(ash::mojom::kServiceName, &recorder); - DCHECK(!startup_metric_utils::MainEntryPointTicks().is_null()); - recorder->SetMainProcessCreationTime( - startup_metric_utils::MainEntryPointTicks()); -} - -} // namespace - namespace internal { // Creates a ChromeLauncherController on the first active session notification. @@ -204,8 +189,6 @@ #if BUILDFLAG(ENABLE_WAYLAND_SERVER) exo_parts_ = ExoParts::CreateIfNecessary(); #endif - - PushProcessCreationTimeToAsh(); } void ChromeBrowserMainExtraPartsAsh::PostProfileInit() {
diff --git a/chrome/browser/ui/ash/chrome_launcher_prefs.cc b/chrome/browser/ui/ash/chrome_launcher_prefs.cc index aac5e1bd..888a1ac9 100644 --- a/chrome/browser/ui/ash/chrome_launcher_prefs.cc +++ b/chrome/browser/ui/ash/chrome_launcher_prefs.cc
@@ -150,9 +150,9 @@ syncer::StringOrdinal GetFirstPinnedAppPosition(Profile* profile, bool exclude_chrome) { syncer::StringOrdinal position; - app_list::AppListSyncableService* app_service = + app_list::AppListSyncableService* syncable_service = app_list::AppListSyncableServiceFactory::GetForProfile(profile); - for (const auto& sync_peer : app_service->sync_items()) { + for (const auto& sync_peer : syncable_service->sync_items()) { if (!sync_peer.second->item_pin_ordinal.IsValid()) continue; if (exclude_chrome && sync_peer.first == extension_misc::kChromeAppId) @@ -178,9 +178,9 @@ // app is not currently visible on a device. syncer::StringOrdinal CreateLastPinPosition(Profile* profile) { syncer::StringOrdinal position; - app_list::AppListSyncableService* app_service = + app_list::AppListSyncableService* syncable_service = app_list::AppListSyncableServiceFactory::GetForProfile(profile); - for (const auto& sync_peer : app_service->sync_items()) { + for (const auto& sync_peer : syncable_service->sync_items()) { if (!sync_peer.second->item_pin_ordinal.IsValid()) continue; if (!position.IsValid() || @@ -199,7 +199,7 @@ // app. void InsertPinsAfterChromeAndBeforeFirstPinnedApp( LauncherControllerHelper* helper, - app_list::AppListSyncableService* app_service, + app_list::AppListSyncableService* syncable_service, const std::vector<std::string>& app_ids, std::vector<PinInfo>* pin_infos) { if (app_ids.empty()) @@ -207,7 +207,7 @@ // Chrome must be pinned at this point. const syncer::StringOrdinal chrome_position = - app_service->GetPinPosition(extension_misc::kChromeAppId); + syncable_service->GetPinPosition(extension_misc::kChromeAppId); DCHECK(chrome_position.IsValid()); // New pins are inserted after this position. @@ -233,11 +233,11 @@ for (const auto& app_id : app_ids) { // Check if we already processed the current app. - if (app_service->GetPinPosition(app_id).IsValid()) + if (syncable_service->GetPinPosition(app_id).IsValid()) continue; const syncer::StringOrdinal position = after.CreateBetween(before); - app_service->SetPinPosition(app_id, position); + syncable_service->SetPinPosition(app_id, position); // Even if app is not currently visible, its pin is pre-created. if (helper->IsValidIDForCurrentUser(app_id)) @@ -252,10 +252,10 @@ std::vector<ash::ShelfID> GetPinnedAppsFromSync( LauncherControllerHelper* helper) { const PrefService* prefs = helper->profile()->GetPrefs(); - app_list::AppListSyncableService* const app_service = + app_list::AppListSyncableService* const syncable_service = app_list::AppListSyncableServiceFactory::GetForProfile(helper->profile()); // Some unit tests may not have it or service may not be initialized. - if (!app_service || !app_service->IsInitialized()) + if (!syncable_service || !syncable_service->IsInitialized()) return std::vector<ash::ShelfID>(); std::vector<PinInfo> pin_infos; @@ -264,7 +264,7 @@ // time. In the normal workflow we have at least Chrome browser pin info. bool first_run = true; - for (const auto& sync_peer : app_service->sync_items()) { + for (const auto& sync_peer : syncable_service->sync_items()) { if (!sync_peer.second->item_pin_ordinal.IsValid()) continue; @@ -285,10 +285,11 @@ // Make sure Chrome is always pinned. syncer::StringOrdinal chrome_position = - app_service->GetPinPosition(extension_misc::kChromeAppId); + syncable_service->GetPinPosition(extension_misc::kChromeAppId); if (!chrome_position.IsValid()) { chrome_position = CreateFirstPinPosition(helper->profile()); - app_service->SetPinPosition(extension_misc::kChromeAppId, chrome_position); + syncable_service->SetPinPosition(extension_misc::kChromeAppId, + chrome_position); pin_infos.emplace_back( PinInfo(extension_misc::kChromeAppId, chrome_position)); } @@ -298,7 +299,7 @@ std::vector<std::string> default_app_ids; for (const char* default_app_id : kDefaultPinnedApps) default_app_ids.push_back(default_app_id); - InsertPinsAfterChromeAndBeforeFirstPinnedApp(helper, app_service, + InsertPinsAfterChromeAndBeforeFirstPinnedApp(helper, syncable_service, default_app_ids, &pin_infos); } @@ -308,16 +309,16 @@ // preallocated and apps will appear on shelf in deterministic order, even if // their install order differ. InsertPinsAfterChromeAndBeforeFirstPinnedApp( - helper, app_service, GetAppsPinnedByPolicy(helper), &pin_infos); + helper, syncable_service, GetAppsPinnedByPolicy(helper), &pin_infos); // In case Play Store appears first time on the device, pin it to the last // position. if (helper->IsValidIDForCurrentUser(arc::kPlayStoreAppId) && - !app_service->GetSyncItem(arc::kPlayStoreAppId)) { + !syncable_service->GetSyncItem(arc::kPlayStoreAppId)) { const syncer::StringOrdinal play_store_position = CreateLastPinPosition(helper->profile()); pin_infos.emplace_back(PinInfo(arc::kPlayStoreAppId, play_store_position)); - app_service->SetPinPosition(arc::kPlayStoreAppId, play_store_position); + syncable_service->SetPinPosition(arc::kPlayStoreAppId, play_store_position); } // Sort pins according their ordinals. @@ -343,9 +344,9 @@ } DCHECK(!app_id.empty()); - app_list::AppListSyncableService* app_service = + app_list::AppListSyncableService* syncable_service = app_list::AppListSyncableServiceFactory::GetForProfile(profile); - app_service->SetPinPosition(app_id, syncer::StringOrdinal()); + syncable_service->SetPinPosition(app_id, syncer::StringOrdinal()); } void SetPinPosition(Profile* profile, @@ -369,21 +370,22 @@ DCHECK(!app_id.empty()); DCHECK_NE(app_id, app_id_before); - app_list::AppListSyncableService* app_service = + app_list::AppListSyncableService* syncable_service = app_list::AppListSyncableServiceFactory::GetForProfile(profile); // Some unit tests may not have this service. - if (!app_service) + if (!syncable_service) return; syncer::StringOrdinal position_before = app_id_before.empty() ? syncer::StringOrdinal() - : app_service->GetPinPosition(app_id_before); + : syncable_service->GetPinPosition(app_id_before); syncer::StringOrdinal position_after; for (const auto& shelf_id_after : shelf_ids_after) { const std::string& app_id_after = shelf_id_after.app_id; DCHECK_NE(app_id_after, app_id); DCHECK_NE(app_id_after, app_id_before); - syncer::StringOrdinal position = app_service->GetPinPosition(app_id_after); + syncer::StringOrdinal position = + syncable_service->GetPinPosition(app_id_after); DCHECK(position.IsValid()); if (!position.IsValid()) { LOG(ERROR) << "Sync pin position was not found for " << app_id_after; @@ -404,5 +406,5 @@ pin_position = position_after.CreateBefore(); else pin_position = syncer::StringOrdinal::CreateInitialOrdinal(); - app_service->SetPinPosition(app_id, pin_position); + syncable_service->SetPinPosition(app_id, pin_position); }
diff --git a/chrome/browser/ui/ash/launcher/arc_app_window.h b/chrome/browser/ui/ash/launcher/arc_app_window.h index 38c1a6d..de25192 100644 --- a/chrome/browser/ui/ash/launcher/arc_app_window.h +++ b/chrome/browser/ui/ash/launcher/arc_app_window.h
@@ -34,7 +34,7 @@ public AppIconLoaderDelegate { public: // TODO(khmel): use a bool set to false by default, or use an existing enum, - // like ash::mojom::WindowStateType. + // like ash::WindowStateType. enum class FullScreenMode { NOT_DEFINED, // Fullscreen mode was not defined. ACTIVE, // Fullscreen is activated for an app.
diff --git a/chrome/browser/ui/ash/launcher/arc_app_window_launcher_item_controller.cc b/chrome/browser/ui/ash/launcher/arc_app_window_launcher_item_controller.cc index 1e72f40..0605457 100644 --- a/chrome/browser/ui/ash/launcher/arc_app_window_launcher_item_controller.cc +++ b/chrome/browser/ui/ash/launcher/arc_app_window_launcher_item_controller.cc
@@ -7,7 +7,7 @@ #include <utility> #include "ash/public/cpp/window_properties.h" -#include "ash/public/interfaces/window_state_type.mojom.h" +#include "ash/public/cpp/window_state_type.h" #include "chrome/browser/chromeos/arc/pip/arc_pip_bridge.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/app_list/arc/arc_app_utils.h" @@ -45,7 +45,7 @@ ui::BaseWindow* window = GetLastActiveWindow(); aura::Window* native_window = window->GetNativeWindow(); if (native_window->GetProperty(ash::kWindowStateTypeKey) == - ash::mojom::WindowStateType::PIP) { + ash::WindowStateType::kPip) { Profile* profile = ChromeLauncherController::instance()->profile(); arc::ArcPipBridge* pip_bridge = arc::ArcPipBridge::GetForBrowserContext(profile);
diff --git a/chrome/browser/ui/ash/launcher_animations_interactive_uitest.cc b/chrome/browser/ui/ash/launcher_animations_interactive_uitest.cc index 26ef0abf..f171b2c 100644 --- a/chrome/browser/ui/ash/launcher_animations_interactive_uitest.cc +++ b/chrome/browser/ui/ash/launcher_animations_interactive_uitest.cc
@@ -7,6 +7,7 @@ #include "base/macros.h" #include "base/run_loop.h" #include "base/task/post_task.h" +#include "chrome/browser/ui/app_list/test/chrome_app_list_test_support.h" #include "chrome/browser/ui/ash/ash_test_util.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_list.h" @@ -25,6 +26,7 @@ void SetUpOnMainThread() override { UIPerformanceTest::SetUpOnMainThread(); + test::PopulateDummyAppListItems(100); if (base::SysInfo::IsRunningOnChromeOS()) { base::RunLoop run_loop; base::PostDelayedTask(FROM_HERE, run_loop.QuitClosure(),
diff --git a/chrome/browser/ui/ash/launcher_drag_interactive_uitest.cc b/chrome/browser/ui/ash/launcher_drag_interactive_uitest.cc index bd0b91d..e2fec830 100644 --- a/chrome/browser/ui/ash/launcher_drag_interactive_uitest.cc +++ b/chrome/browser/ui/ash/launcher_drag_interactive_uitest.cc
@@ -9,6 +9,7 @@ #include "base/run_loop.h" #include "base/strings/stringprintf.h" #include "base/task/post_task.h" +#include "chrome/browser/ui/app_list/test/chrome_app_list_test_support.h" #include "chrome/browser/ui/ash/ash_test_util.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/views/frame/browser_view.h" @@ -29,6 +30,7 @@ void SetUpOnMainThread() override { UIPerformanceTest::SetUpOnMainThread(); + test::PopulateDummyAppListItems(100); // Ash may not be ready to receive events right away. int warmup_seconds = base::SysInfo::IsRunningOnChromeOS() ? 5 : 1; base::RunLoop run_loop;
diff --git a/chrome/browser/ui/ash/overview_window_drag_interactive_uitest.cc b/chrome/browser/ui/ash/overview_window_drag_interactive_uitest.cc index 04efba9e..4f56217 100644 --- a/chrome/browser/ui/ash/overview_window_drag_interactive_uitest.cc +++ b/chrome/browser/ui/ash/overview_window_drag_interactive_uitest.cc
@@ -3,7 +3,7 @@ // found in the LICENSE file. #include "ash/public/cpp/window_properties.h" -#include "ash/public/interfaces/window_state_type.mojom.h" +#include "ash/public/cpp/window_state_type.h" #include "base/macros.h" #include "base/run_loop.h" #include "base/task/post_task.h" @@ -51,7 +51,7 @@ bool IsLeftSnapped() { return window_->GetProperty(ash::kWindowStateTypeKey) == - ash::mojom::WindowStateType::LEFT_SNAPPED; + ash::WindowStateType::kLeftSnapped; } private:
diff --git a/chrome/browser/ui/ash/tablet_mode_transition_interactive_uitest.cc b/chrome/browser/ui/ash/tablet_mode_transition_interactive_uitest.cc new file mode 100644 index 0000000..2588ef43 --- /dev/null +++ b/chrome/browser/ui/ash/tablet_mode_transition_interactive_uitest.cc
@@ -0,0 +1,111 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/command_line.h" +#include "base/macros.h" +#include "base/run_loop.h" +#include "base/task/post_task.h" +#include "chrome/browser/ui/ash/ash_test_util.h" +#include "chrome/browser/ui/ash/tablet_mode_client_test_util.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/browser_list.h" +#include "chrome/browser/ui/browser_window.h" +#include "chrome/test/base/perf/performance_test.h" +#include "ui/aura/window.h" +#include "ui/compositor/layer.h" +#include "ui/compositor/layer_animation_observer.h" +#include "ui/compositor/layer_animator.h" +#include "ui/wm/core/window_util.h" +#include "ui/wm/core/wm_core_switches.h" + +namespace { + +class TestLayerAnimationObserver : public ui::LayerAnimationObserver { + public: + TestLayerAnimationObserver(ui::LayerAnimator* animator, + base::OnceClosure callback) + : animator_(animator), callback_(std::move(callback)) {} + ~TestLayerAnimationObserver() override = default; + + void OnLayerAnimationEnded(ui::LayerAnimationSequence* sequence) override { + if (!animator_->is_animating()) + std::move(callback_).Run(); + } + void OnLayerAnimationAborted(ui::LayerAnimationSequence* sequence) override {} + void OnLayerAnimationScheduled( + ui::LayerAnimationSequence* sequence) override {} + + private: + ui::LayerAnimator* animator_; + base::OnceClosure callback_; + DISALLOW_COPY_AND_ASSIGN(TestLayerAnimationObserver); +}; + +} // namespace + +class TabletModeTransitionTest : public UIPerformanceTest { + public: + TabletModeTransitionTest() = default; + ~TabletModeTransitionTest() override = default; + + // UIPerformanceTest: + void SetUpOnMainThread() override { + UIPerformanceTest::SetUpOnMainThread(); + + constexpr int additional_browsers = 5; + constexpr int cost_per_browser = 100; + for (int i = 0; i < additional_browsers; ++i) + CreateBrowser(browser()->profile()); + + int wait_ms = (base::SysInfo::IsRunningOnChromeOS() ? 5000 : 0) + + (additional_browsers + 1) * cost_per_browser; + base::RunLoop run_loop; + base::PostDelayedTask(FROM_HERE, run_loop.QuitClosure(), + base::TimeDelta::FromMilliseconds(wait_ms)); + run_loop.Run(); + + // The uma stats we are interested in measure the animations directly so we + // need to ensure they are turned on. + auto* cmd = base::CommandLine::ForCurrentProcess(); + if (cmd->HasSwitch(wm::switches::kWindowAnimationsDisabled)) + cmd->RemoveSwitch(wm::switches::kWindowAnimationsDisabled); + } + + std::vector<std::string> GetUMAHistogramNames() const override { + return { + "Ash.TabletMode.AnimationSmoothness.Enter", + "Ash.TabletMode.AnimationSmoothness.Exit", + }; + } + + private: + DISALLOW_COPY_AND_ASSIGN(TabletModeTransitionTest); +}; + +IN_PROC_BROWSER_TEST_F(TabletModeTransitionTest, EnterExit) { + // Activate the first window. The top window is the only window which animates + // and is the one we should check to see if the tablet animation has finished. + Browser* browser = BrowserList::GetInstance()->GetLastActive(); + aura::Window* browser_window = browser->window()->GetNativeWindow(); + + { + base::RunLoop run_loop; + ui::LayerAnimator* animator = browser_window->layer()->GetAnimator(); + TestLayerAnimationObserver waiter(animator, run_loop.QuitClosure()); + animator->AddObserver(&waiter); + test::SetAndWaitForTabletMode(true); + run_loop.Run(); + animator->RemoveObserver(&waiter); + } + + { + base::RunLoop run_loop; + ui::LayerAnimator* animator = browser_window->layer()->GetAnimator(); + TestLayerAnimationObserver waiter(animator, run_loop.QuitClosure()); + animator->AddObserver(&waiter); + test::SetAndWaitForTabletMode(false); + run_loop.Run(); + animator->RemoveObserver(&waiter); + } +}
diff --git a/chrome/browser/ui/ash/time_to_first_present_recorder_browsertest.cc b/chrome/browser/ui/ash/time_to_first_present_recorder_browsertest.cc index 25870311..75111f8 100644 --- a/chrome/browser/ui/ash/time_to_first_present_recorder_browsertest.cc +++ b/chrome/browser/ui/ash/time_to_first_present_recorder_browsertest.cc
@@ -2,24 +2,30 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ash/public/interfaces/constants.mojom.h" -#include "ash/public/interfaces/time_to_first_present_recorder_test_api.test-mojom-test-utils.h" -#include "ash/public/interfaces/time_to_first_present_recorder_test_api.test-mojom.h" +#include "ash/metrics/time_to_first_present_recorder.h" + +#include "ash/metrics/time_to_first_present_recorder_test_api.h" #include "base/command_line.h" +#include "base/run_loop.h" +#include "base/test/metrics/histogram_tester.h" #include "chrome/test/base/in_process_browser_test.h" -#include "content/public/common/service_manager_connection.h" -#include "services/service_manager/public/cpp/connector.h" using TimeToFirstPresentRecorderTest = InProcessBrowserTest; IN_PROC_BROWSER_TEST_F(TimeToFirstPresentRecorderTest, VerifyTimeCalculated) { - ash::mojom::TimeToFirstPresentRecorderTestApiPtr recorder_test_api; - content::ServiceManagerConnection::GetForProcess() - ->GetConnector() - ->BindInterface(ash::mojom::kServiceName, &recorder_test_api); - ash::mojom::TimeToFirstPresentRecorderTestApiAsyncWaiter recorder( - recorder_test_api.get()); - base::TimeDelta time_delta; - recorder.GetProcessCreationToFirstPresentTime(&time_delta); - EXPECT_FALSE(time_delta.is_zero()); + // It's possible that the metric was already recorded. + base::HistogramTester tester; + auto counts = tester.GetTotalCountsForPrefix( + ash::TimeToFirstPresentRecorder::kMetricName); + if (counts[ash::TimeToFirstPresentRecorder::kMetricName] == 1) + return; + + // The metric wasn't recorded. Wait for it to be recorded. + base::RunLoop run_loop; + ash::TimeToFirstPresentRecorderTestApi::SetTimeToFirstPresentCallback( + run_loop.QuitClosure()); + run_loop.Run(); + counts = tester.GetTotalCountsForPrefix( + ash::TimeToFirstPresentRecorder::kMetricName); + EXPECT_EQ(1, counts[ash::TimeToFirstPresentRecorder::kMetricName]); }
diff --git a/chrome/browser/ui/bluetooth/bluetooth_scanning_prompt_controller.cc b/chrome/browser/ui/bluetooth/bluetooth_scanning_prompt_controller.cc new file mode 100644 index 0000000..8f43308 --- /dev/null +++ b/chrome/browser/ui/bluetooth/bluetooth_scanning_prompt_controller.cc
@@ -0,0 +1,140 @@ +// 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/bluetooth/bluetooth_scanning_prompt_controller.h" + +#include <algorithm> + +#include "base/strings/utf_string_conversions.h" +#include "chrome/browser/ui/bluetooth/bluetooth_chooser_desktop.h" +#include "chrome/grit/generated_resources.h" +#include "ui/base/l10n/l10n_util.h" + +BluetoothScanningPromptController::BluetoothScanningPromptController( + content::RenderFrameHost* owner, + const content::BluetoothScanningPrompt::EventHandler& event_handler) + : ChooserController(owner, + IDS_BLUETOOTH_SCANNING_PROMPT_ORIGIN, + IDS_BLUETOOTH_SCANNING_PROMPT_ORIGIN), + event_handler_(event_handler) {} + +BluetoothScanningPromptController::~BluetoothScanningPromptController() {} + +bool BluetoothScanningPromptController::ShouldShowHelpButton() const { + return false; +} + +base::string16 BluetoothScanningPromptController::GetNoOptionsText() const { + return l10n_util::GetStringUTF16( + IDS_BLUETOOTH_SCANNING_PROMPT_NO_DEVICES_FOUND_PROMPT); +} + +base::string16 BluetoothScanningPromptController::GetOkButtonLabel() const { + return l10n_util::GetStringUTF16( + IDS_BLUETOOTH_SCANNING_PROMPT_ALLOW_BUTTON_TEXT); +} + +base::string16 BluetoothScanningPromptController::GetCancelButtonLabel() const { + return l10n_util::GetStringUTF16( + IDS_BLUETOOTH_SCANNING_PROMPT_BLOCK_BUTTON_TEXT); +} + +bool BluetoothScanningPromptController::BothButtonsAlwaysEnabled() const { + return true; +} + +bool BluetoothScanningPromptController::TableViewAlwaysDisabled() const { + return true; +} + +size_t BluetoothScanningPromptController::NumOptions() const { + return device_ids_.size(); +} + +base::string16 BluetoothScanningPromptController::GetOption( + size_t index) const { + DCHECK_LT(index, device_ids_.size()); + const std::string& device_id = device_ids_[index]; + const auto& device_name_it = device_id_to_name_map_.find(device_id); + DCHECK(device_name_it != device_id_to_name_map_.end()); + const auto& it = device_name_counts_.find(device_name_it->second); + DCHECK(it != device_name_counts_.end()); + return it->second == 1 + ? device_name_it->second + : l10n_util::GetStringFUTF16( + IDS_DEVICE_CHOOSER_DEVICE_NAME_WITH_ID, + device_name_it->second, base::UTF8ToUTF16(device_id)); +} + +void BluetoothScanningPromptController::Select( + const std::vector<size_t>& indices) { + DCHECK(indices.empty()); + + if (event_handler_.is_null()) + return; + + event_handler_.Run(content::BluetoothScanningPrompt::Event::kAllow); +} + +void BluetoothScanningPromptController::Cancel() { + if (event_handler_.is_null()) + return; + + event_handler_.Run(content::BluetoothScanningPrompt::Event::kBlock); +} + +void BluetoothScanningPromptController::Close() { + if (event_handler_.is_null()) + return; + + event_handler_.Run(content::BluetoothScanningPrompt::Event::kCanceled); +} + +void BluetoothScanningPromptController::OpenHelpCenterUrl() const {} + +void BluetoothScanningPromptController::AddOrUpdateDevice( + const std::string& device_id, + bool should_update_name, + const base::string16& device_name) { + base::string16 device_name_for_display = device_name; + if (device_name_for_display.empty()) { + device_name_for_display = l10n_util::GetStringFUTF16( + IDS_BLUETOOTH_SCANNING_DEVICE_UNKNOWN, base::UTF8ToUTF16(device_id)); + } + + auto name_it = device_id_to_name_map_.find(device_id); + if (name_it != device_id_to_name_map_.end()) { + if (should_update_name) { + base::string16 previous_device_name = name_it->second; + name_it->second = device_name_for_display; + + const auto& it = device_name_counts_.find(previous_device_name); + DCHECK(it != device_name_counts_.end()); + DCHECK_GT(it->second, 0); + + if (--(it->second) == 0) + device_name_counts_.erase(it); + + ++device_name_counts_[device_name_for_display]; + } + + auto device_id_it = + std::find(device_ids_.begin(), device_ids_.end(), device_id); + + DCHECK(device_id_it != device_ids_.end()); + if (view()) + view()->OnOptionUpdated(device_id_it - device_ids_.begin()); + return; + } + + device_ids_.push_back(device_id); + device_id_to_name_map_.insert({device_id, device_name_for_display}); + ++device_name_counts_[device_name_for_display]; + if (view()) + view()->OnOptionAdded(device_ids_.size() - 1); +} + +void BluetoothScanningPromptController::ResetEventHandler() { + event_handler_.Reset(); +}
diff --git a/chrome/browser/ui/bluetooth/bluetooth_scanning_prompt_controller.h b/chrome/browser/ui/bluetooth/bluetooth_scanning_prompt_controller.h new file mode 100644 index 0000000..9e7a2e5 --- /dev/null +++ b/chrome/browser/ui/bluetooth/bluetooth_scanning_prompt_controller.h
@@ -0,0 +1,65 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_BLUETOOTH_BLUETOOTH_SCANNING_PROMPT_CONTROLLER_H_ +#define CHROME_BROWSER_UI_BLUETOOTH_BLUETOOTH_SCANNING_PROMPT_CONTROLLER_H_ + +#include <stddef.h> + +#include <string> +#include <unordered_map> +#include <utility> +#include <vector> + +#include "base/callback.h" +#include "base/macros.h" +#include "chrome/browser/chooser_controller/chooser_controller.h" +#include "content/public/browser/bluetooth_scanning_prompt.h" + +// BluetoothScanningPromptController is a prompt that presents a list of +// Bluetooth device names. It can be used by Bluetooth Scanning API to +// show example nearby Bluetooth devices to user. It is owned by +// ChooserBubbleDelegate. +class BluetoothScanningPromptController : public ChooserController { + public: + BluetoothScanningPromptController( + content::RenderFrameHost* owner, + const content::BluetoothScanningPrompt::EventHandler& event_handler); + ~BluetoothScanningPromptController() override; + + // ChooserController: + bool ShouldShowHelpButton() const override; + base::string16 GetNoOptionsText() const override; + base::string16 GetOkButtonLabel() const override; + base::string16 GetCancelButtonLabel() const override; + bool BothButtonsAlwaysEnabled() const override; + bool TableViewAlwaysDisabled() const override; + size_t NumOptions() const override; + base::string16 GetOption(size_t index) const override; + void Select(const std::vector<size_t>& indices) override; + void Cancel() override; + void Close() override; + void OpenHelpCenterUrl() const override; + + // Shows a new device in the permission prompt or updates its information. + void AddOrUpdateDevice(const std::string& device_id, + bool should_update_name, + const base::string16& device_name); + + // Called when |event_handler_| is no longer valid and should not be used + // any more. + void ResetEventHandler(); + + private: + std::vector<std::string> device_ids_; + std::unordered_map<std::string, base::string16> device_id_to_name_map_; + // Maps from device name to number of devices with that name. + std::unordered_map<base::string16, int> device_name_counts_; + + content::BluetoothScanningPrompt::EventHandler event_handler_; + + DISALLOW_COPY_AND_ASSIGN(BluetoothScanningPromptController); +}; + +#endif // CHROME_BROWSER_UI_BLUETOOTH_BLUETOOTH_SCANNING_PROMPT_CONTROLLER_H_
diff --git a/chrome/browser/ui/bluetooth/bluetooth_scanning_prompt_controller_unittest.cc b/chrome/browser/ui/bluetooth/bluetooth_scanning_prompt_controller_unittest.cc new file mode 100644 index 0000000..54aeae5 --- /dev/null +++ b/chrome/browser/ui/bluetooth/bluetooth_scanning_prompt_controller_unittest.cc
@@ -0,0 +1,169 @@ +// 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 <string> + +#include "base/bind.h" +#include "base/macros.h" +#include "base/strings/utf_string_conversions.h" +#include "chrome/browser/ui/bluetooth/bluetooth_scanning_prompt_controller.h" +#include "chrome/grit/generated_resources.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "ui/base/l10n/l10n_util.h" + +namespace { + +class MockBluetoothScanningPromptView : public ChooserController::View { + public: + MockBluetoothScanningPromptView() {} + + // ChooserController::View: + MOCK_METHOD0(OnOptionsInitialized, void()); + MOCK_METHOD1(OnOptionAdded, void(size_t index)); + MOCK_METHOD1(OnOptionRemoved, void(size_t index)); + MOCK_METHOD1(OnOptionUpdated, void(size_t index)); + MOCK_METHOD1(OnAdapterEnabledChanged, void(bool enabled)); + MOCK_METHOD1(OnRefreshStateChanged, void(bool enabled)); + + private: + DISALLOW_COPY_AND_ASSIGN(MockBluetoothScanningPromptView); +}; + +} // namespace + +class BluetoothScanningPromptControllerTest : public testing::Test { + public: + BluetoothScanningPromptControllerTest() + : bluetooth_scanning_prompt_controller_( + nullptr, + base::BindRepeating(&BluetoothScanningPromptControllerTest:: + OnBluetoothScanningPromptEvent, + base::Unretained(this))) { + bluetooth_scanning_prompt_controller_.set_view( + &mock_bluetooth_scanning_prompt_view_); + } + + protected: + void OnBluetoothScanningPromptEvent( + content::BluetoothScanningPrompt::Event event) { + last_event_ = event; + } + + BluetoothScanningPromptController bluetooth_scanning_prompt_controller_; + MockBluetoothScanningPromptView mock_bluetooth_scanning_prompt_view_; + content::BluetoothScanningPrompt::Event last_event_; + + private: + DISALLOW_COPY_AND_ASSIGN(BluetoothScanningPromptControllerTest); +}; + +class BluetoothScanningPromptControllerWithDevicesAddedTest + : public BluetoothScanningPromptControllerTest { + public: + BluetoothScanningPromptControllerWithDevicesAddedTest() { + bluetooth_scanning_prompt_controller_.AddOrUpdateDevice( + "id_a", /*should_update_name=*/false, base::ASCIIToUTF16("a")); + bluetooth_scanning_prompt_controller_.AddOrUpdateDevice( + "id_b", /*should_update_name=*/false, base::ASCIIToUTF16("b")); + bluetooth_scanning_prompt_controller_.AddOrUpdateDevice( + "id_c", /*should_update_name=*/false, base::ASCIIToUTF16("c")); + } +}; + +TEST_F(BluetoothScanningPromptControllerTest, AddDevice) { + EXPECT_CALL(mock_bluetooth_scanning_prompt_view_, OnOptionAdded(0)).Times(1); + bluetooth_scanning_prompt_controller_.AddOrUpdateDevice( + "id_a", /*should_update_name=*/false, base::ASCIIToUTF16("a")); + EXPECT_EQ(1u, bluetooth_scanning_prompt_controller_.NumOptions()); + EXPECT_EQ(base::ASCIIToUTF16("a"), + bluetooth_scanning_prompt_controller_.GetOption(0)); + testing::Mock::VerifyAndClearExpectations( + &mock_bluetooth_scanning_prompt_view_); + + EXPECT_CALL(mock_bluetooth_scanning_prompt_view_, OnOptionAdded(1)).Times(1); + bluetooth_scanning_prompt_controller_.AddOrUpdateDevice( + "id_b", /*should_update_name=*/false, base::ASCIIToUTF16("b")); + EXPECT_EQ(2u, bluetooth_scanning_prompt_controller_.NumOptions()); + EXPECT_EQ(base::ASCIIToUTF16("b"), + bluetooth_scanning_prompt_controller_.GetOption(1)); + testing::Mock::VerifyAndClearExpectations( + &mock_bluetooth_scanning_prompt_view_); + + EXPECT_CALL(mock_bluetooth_scanning_prompt_view_, OnOptionAdded(2)).Times(1); + bluetooth_scanning_prompt_controller_.AddOrUpdateDevice( + "id_c", /*should_update_name=*/false, base::ASCIIToUTF16("c")); + EXPECT_EQ(3u, bluetooth_scanning_prompt_controller_.NumOptions()); + EXPECT_EQ(base::ASCIIToUTF16("c"), + bluetooth_scanning_prompt_controller_.GetOption(2)); +} + +TEST_F(BluetoothScanningPromptControllerTest, + MultipleDevicesWithSameNameShowIds) { + bluetooth_scanning_prompt_controller_.AddOrUpdateDevice( + "id_a_1", /*should_update_name=*/false, base::ASCIIToUTF16("a")); + EXPECT_EQ(base::ASCIIToUTF16("a"), + bluetooth_scanning_prompt_controller_.GetOption(0)); + + bluetooth_scanning_prompt_controller_.AddOrUpdateDevice( + "id_b", /*should_update_name=*/false, base::ASCIIToUTF16("b")); + bluetooth_scanning_prompt_controller_.AddOrUpdateDevice( + "id_a_2", /*should_update_name=*/false, base::ASCIIToUTF16("a")); + EXPECT_EQ(base::ASCIIToUTF16("a (id_a_1)"), + bluetooth_scanning_prompt_controller_.GetOption(0)); + EXPECT_EQ(base::ASCIIToUTF16("b"), + bluetooth_scanning_prompt_controller_.GetOption(1)); + EXPECT_EQ(base::ASCIIToUTF16("a (id_a_2)"), + bluetooth_scanning_prompt_controller_.GetOption(2)); +} + +TEST_F(BluetoothScanningPromptControllerTest, UpdateDeviceName) { + bluetooth_scanning_prompt_controller_.AddOrUpdateDevice( + "id_a", /*should_update_name=*/false, base::ASCIIToUTF16("a")); + EXPECT_EQ(base::ASCIIToUTF16("a"), + bluetooth_scanning_prompt_controller_.GetOption(0)); + + EXPECT_CALL(mock_bluetooth_scanning_prompt_view_, OnOptionUpdated(0)) + .Times(1); + bluetooth_scanning_prompt_controller_.AddOrUpdateDevice( + "id_a", /*should_update_name=*/false, base::ASCIIToUTF16("aa")); + // The name is still "a" since |should_update_name| is false. + EXPECT_EQ(base::ASCIIToUTF16("a"), + bluetooth_scanning_prompt_controller_.GetOption(0)); + testing::Mock::VerifyAndClearExpectations( + &mock_bluetooth_scanning_prompt_view_); + + EXPECT_CALL(mock_bluetooth_scanning_prompt_view_, OnOptionUpdated(0)) + .Times(1); + bluetooth_scanning_prompt_controller_.AddOrUpdateDevice( + "id_a", true /* should_update_name */, base::ASCIIToUTF16("aa")); + EXPECT_EQ(1u, bluetooth_scanning_prompt_controller_.NumOptions()); + EXPECT_EQ(base::ASCIIToUTF16("aa"), + bluetooth_scanning_prompt_controller_.GetOption(0)); +} + +TEST_F(BluetoothScanningPromptControllerWithDevicesAddedTest, + InitialNoOptionsText) { + EXPECT_EQ(base::ASCIIToUTF16("No nearby devices found."), + bluetooth_scanning_prompt_controller_.GetNoOptionsText()); +} + +TEST_F(BluetoothScanningPromptControllerWithDevicesAddedTest, + AllowShouldCallEventHandler) { + std::vector<size_t> indices; + bluetooth_scanning_prompt_controller_.Select(indices); + EXPECT_EQ(content::BluetoothScanningPrompt::Event::kAllow, last_event_); +} + +TEST_F(BluetoothScanningPromptControllerWithDevicesAddedTest, + BlockShouldCallEventHandler) { + bluetooth_scanning_prompt_controller_.Cancel(); + EXPECT_EQ(content::BluetoothScanningPrompt::Event::kBlock, last_event_); +} + +TEST_F(BluetoothScanningPromptControllerWithDevicesAddedTest, + CloseShouldCallEventHandler) { + bluetooth_scanning_prompt_controller_.Close(); + EXPECT_EQ(content::BluetoothScanningPrompt::Event::kCanceled, last_event_); +}
diff --git a/chrome/browser/ui/bluetooth/bluetooth_scanning_prompt_desktop.cc b/chrome/browser/ui/bluetooth/bluetooth_scanning_prompt_desktop.cc new file mode 100644 index 0000000..bee595b --- /dev/null +++ b/chrome/browser/ui/bluetooth/bluetooth_scanning_prompt_desktop.cc
@@ -0,0 +1,33 @@ +// 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/bluetooth/bluetooth_scanning_prompt_desktop.h" + +#include "base/logging.h" +#include "chrome/browser/ui/bluetooth/bluetooth_scanning_prompt_controller.h" +#include "components/bubble/bubble_controller.h" + +BluetoothScanningPromptDesktop::BluetoothScanningPromptDesktop( + BluetoothScanningPromptController* bluetooth_scanning_prompt_controller) + : bluetooth_scanning_prompt_controller_( + bluetooth_scanning_prompt_controller) { + DCHECK(bluetooth_scanning_prompt_controller_); +} + +BluetoothScanningPromptDesktop::~BluetoothScanningPromptDesktop() { + // This satisfies the WebContentsDelegate::ShowBluetoothScanningPrompt() + // requirement that the EventHandler can be destroyed any time after the + // BluetoothScanningPrompt instance. + bluetooth_scanning_prompt_controller_->ResetEventHandler(); + if (bubble_) + bubble_->CloseBubble(BUBBLE_CLOSE_FORCED); +} + +void BluetoothScanningPromptDesktop::AddOrUpdateDevice( + const std::string& device_id, + bool should_update_name, + const base::string16& device_name) { + bluetooth_scanning_prompt_controller_->AddOrUpdateDevice( + device_id, should_update_name, device_name); +}
diff --git a/chrome/browser/ui/bluetooth/bluetooth_scanning_prompt_desktop.h b/chrome/browser/ui/bluetooth/bluetooth_scanning_prompt_desktop.h new file mode 100644 index 0000000..1661bfc --- /dev/null +++ b/chrome/browser/ui/bluetooth/bluetooth_scanning_prompt_desktop.h
@@ -0,0 +1,43 @@ +// 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_BLUETOOTH_BLUETOOTH_SCANNING_PROMPT_DESKTOP_H_ +#define CHROME_BROWSER_UI_BLUETOOTH_BLUETOOTH_SCANNING_PROMPT_DESKTOP_H_ + +#include "base/macros.h" +#include "components/bubble/bubble_reference.h" +#include "content/public/browser/bluetooth_scanning_prompt.h" + +class BluetoothScanningPromptController; + +// Represents a Bluetooth scanning prompt to ask the user permission to +// allow a site to receive Bluetooth advertisement packets from Bluetooth +// devices. This implementation is for desktop. +class BluetoothScanningPromptDesktop : public content::BluetoothScanningPrompt { + public: + explicit BluetoothScanningPromptDesktop( + BluetoothScanningPromptController* bluetooth_scanning_prompt_controller); + ~BluetoothScanningPromptDesktop() override; + + // content::BluetoothScanningPrompt: + void AddOrUpdateDevice(const std::string& device_id, + bool should_update_name, + const base::string16& device_name) override; + + // Sets a reference to the bubble being displayed so that it can be closed if + // this object is destroyed. + void set_bubble(base::WeakPtr<BubbleController> bubble) { + bubble_ = std::move(bubble); + } + + private: + // Weak. DeviceChooserContentView owns it. + BluetoothScanningPromptController* bluetooth_scanning_prompt_controller_; + + base::WeakPtr<BubbleController> bubble_; + + DISALLOW_COPY_AND_ASSIGN(BluetoothScanningPromptDesktop); +}; + +#endif // CHROME_BROWSER_UI_BLUETOOTH_BLUETOOTH_SCANNING_PROMPT_DESKTOP_H_
diff --git a/chrome/browser/ui/browser.cc b/chrome/browser/ui/browser.cc index cf89e93..5230064 100644 --- a/chrome/browser/ui/browser.cc +++ b/chrome/browser/ui/browser.cc
@@ -101,6 +101,8 @@ #include "chrome/browser/ui/blocked_content/popup_tracker.h" #include "chrome/browser/ui/bluetooth/bluetooth_chooser_controller.h" #include "chrome/browser/ui/bluetooth/bluetooth_chooser_desktop.h" +#include "chrome/browser/ui/bluetooth/bluetooth_scanning_prompt_controller.h" +#include "chrome/browser/ui/bluetooth/bluetooth_scanning_prompt_desktop.h" #include "chrome/browser/ui/bookmarks/bookmark_tab_helper.h" #include "chrome/browser/ui/bookmarks/bookmark_utils.h" #include "chrome/browser/ui/browser_command_controller.h" @@ -1206,6 +1208,27 @@ return std::move(bluetooth_chooser_desktop); } +std::unique_ptr<content::BluetoothScanningPrompt> +Browser::ShowBluetoothScanningPrompt( + content::RenderFrameHost* frame, + const content::BluetoothScanningPrompt::EventHandler& event_handler) { + auto bluetooth_scanning_prompt_controller = + std::make_unique<BluetoothScanningPromptController>(frame, event_handler); + + auto bluetooth_scanning_prompt_desktop = + std::make_unique<BluetoothScanningPromptDesktop>( + bluetooth_scanning_prompt_controller.get()); + + auto chooser_bubble_delegate = std::make_unique<ChooserBubbleDelegate>( + frame, std::move(bluetooth_scanning_prompt_controller)); + + BubbleReference bubble_reference = + GetBubbleManager()->ShowBubble(std::move(chooser_bubble_delegate)); + bluetooth_scanning_prompt_desktop->set_bubble(std::move(bubble_reference)); + + return std::move(bluetooth_scanning_prompt_desktop); +} + void Browser::PassiveInsecureContentFound(const GURL& resource_url) { // Note: this implementation is a mirror of // ContentSettingsObserver::passiveInsecureContentFound
diff --git a/chrome/browser/ui/browser.h b/chrome/browser/ui/browser.h index a2364d0..bce833a9 100644 --- a/chrome/browser/ui/browser.h +++ b/chrome/browser/ui/browser.h
@@ -541,6 +541,10 @@ std::unique_ptr<content::BluetoothChooser> RunBluetoothChooser( content::RenderFrameHost* frame, const content::BluetoothChooser::EventHandler& event_handler) override; + std::unique_ptr<content::BluetoothScanningPrompt> ShowBluetoothScanningPrompt( + content::RenderFrameHost* frame, + const content::BluetoothScanningPrompt::EventHandler& event_handler) + override; void PassiveInsecureContentFound(const GURL& resource_url) override; bool ShouldAllowRunningInsecureContent(content::WebContents* web_contents, bool allowed_per_prefs,
diff --git a/chrome/browser/ui/browser_navigator_params.h b/chrome/browser/ui/browser_navigator_params.h index 7e46721..91cefc1 100644 --- a/chrome/browser/ui/browser_navigator_params.h +++ b/chrome/browser/ui/browser_navigator_params.h
@@ -9,6 +9,7 @@ #include <vector> #include "base/memory/ref_counted.h" +#include "base/optional.h" #include "build/build_config.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" #include "content/public/browser/global_request_id.h" @@ -172,7 +173,7 @@ int tabstrip_index = -1; // The group the caller would like the tab to be added to. - const TabGroupData* group = nullptr; + base::Optional<int> group; // A bitmask of values defined in TabStripModel::AddTabTypes. Helps // determine where to insert a new tab and whether or not it should be
diff --git a/chrome/browser/ui/browser_tab_strip_model_delegate.cc b/chrome/browser/ui/browser_tab_strip_model_delegate.cc index fa4dccfa..fb3300a 100644 --- a/chrome/browser/ui/browser_tab_strip_model_delegate.cc +++ b/chrome/browser/ui/browser_tab_strip_model_delegate.cc
@@ -44,7 +44,7 @@ void BrowserTabStripModelDelegate::AddTabAt(const GURL& url, int index, bool foreground, - const TabGroupData* group) { + base::Optional<int> group) { chrome::AddTabAt(browser_, url, index, foreground, group); }
diff --git a/chrome/browser/ui/browser_tab_strip_model_delegate.h b/chrome/browser/ui/browser_tab_strip_model_delegate.h index a7d1ba9..2b85d065a 100644 --- a/chrome/browser/ui/browser_tab_strip_model_delegate.h +++ b/chrome/browser/ui/browser_tab_strip_model_delegate.h
@@ -24,7 +24,7 @@ void AddTabAt(const GURL& url, int index, bool foreground, - const TabGroupData* group) override; + base::Optional<int> group) override; Browser* CreateNewStripWithContents(std::vector<NewStripContents> contentses, const gfx::Rect& window_bounds, bool maximize) override;
diff --git a/chrome/browser/ui/browser_tabstrip.cc b/chrome/browser/ui/browser_tabstrip.cc index 43ffee3..3721294 100644 --- a/chrome/browser/ui/browser_tabstrip.cc +++ b/chrome/browser/ui/browser_tabstrip.cc
@@ -23,7 +23,7 @@ const GURL& url, int idx, bool foreground, - const TabGroupData* group) { + base::Optional<int> group) { // Time new tab page creation time. We keep track of the timing data in // WebContents, but we want to include the time it takes to create the // WebContents object too.
diff --git a/chrome/browser/ui/browser_tabstrip.h b/chrome/browser/ui/browser_tabstrip.h index 01b7bd7..d644d8f2 100644 --- a/chrome/browser/ui/browser_tabstrip.h +++ b/chrome/browser/ui/browser_tabstrip.h
@@ -5,6 +5,7 @@ #ifndef CHROME_BROWSER_UI_BROWSER_TABSTRIP_H_ #define CHROME_BROWSER_UI_BROWSER_TABSTRIP_H_ +#include "base/optional.h" #include "content/public/browser/navigation_controller.h" #include "content/public/browser/web_contents.h" #include "ui/base/page_transition_types.h" @@ -12,7 +13,6 @@ class Browser; class GURL; -class TabGroupData; namespace gfx { class Rect; @@ -27,7 +27,7 @@ const GURL& url, int index, bool foreground, - const TabGroupData* group = nullptr); + base::Optional<int> group = base::nullopt); // Adds a selected tab with the specified URL and transition, returns the // created WebContents.
diff --git a/chrome/browser/ui/tabs/existing_tab_group_sub_menu_model.cc b/chrome/browser/ui/tabs/existing_tab_group_sub_menu_model.cc index 7cec602..094afeb 100644 --- a/chrome/browser/ui/tabs/existing_tab_group_sub_menu_model.cc +++ b/chrome/browser/ui/tabs/existing_tab_group_sub_menu_model.cc
@@ -21,9 +21,9 @@ void ExistingTabGroupSubMenuModel::Build() { // Start command ids after the parent menu's ids to avoid collisions. int group_index = kFirstCommandIndex; - for (TabGroupData* group : model_->ListTabGroups()) { + for (int group : model_->ListTabGroups()) { if (ShouldShowGroup(model_, context_index_, group)) { - AddItem(group_index, group->title()); + AddItem(group_index, model_->GetDataForGroup(group)->title()); } group_index++; } @@ -39,18 +39,18 @@ void ExistingTabGroupSubMenuModel::ExecuteCommand(int command_id, int event_flags) { - const int groupId = command_id - kFirstCommandIndex; - // TODO(https://crbug.com/922736): If a group has been deleted, groupId may - // refer to a different group than it did when the menu was created. - DCHECK((size_t)groupId < model_->ListTabGroups().size()); - model_->ExecuteAddToExistingGroupCommand(context_index_, - model_->ListTabGroups()[groupId]); + const int group_index = command_id - kFirstCommandIndex; + // TODO(https://crbug.com/922736): If a group has been deleted, |group_index| + // may refer to a different group than it did when the menu was created. + DCHECK_LT(size_t{group_index}, model_->ListTabGroups().size()); + model_->ExecuteAddToExistingGroupCommand( + context_index_, model_->ListTabGroups()[group_index]); } // static bool ExistingTabGroupSubMenuModel::ShouldShowSubmenu(TabStripModel* model, int context_index) { - for (TabGroupData* group : model->ListTabGroups()) { + for (int group : model->ListTabGroups()) { if (ShouldShowGroup(model, context_index, group)) { return true; } @@ -61,14 +61,13 @@ // static bool ExistingTabGroupSubMenuModel::ShouldShowGroup(TabStripModel* model, int context_index, - TabGroupData* group) { + int group) { if (!model->IsTabSelected(context_index)) { - if (group != nullptr && group != model->GetTabGroupForTab(context_index)) { + if (group != model->GetTabGroupForTab(context_index)) return true; - } } else { for (int index : model->selection_model().selected_indices()) { - if (group != nullptr && group != model->GetTabGroupForTab(index)) { + if (group != model->GetTabGroupForTab(index)) { return true; } }
diff --git a/chrome/browser/ui/tabs/existing_tab_group_sub_menu_model.h b/chrome/browser/ui/tabs/existing_tab_group_sub_menu_model.h index 7901738e..9fbfe434 100644 --- a/chrome/browser/ui/tabs/existing_tab_group_sub_menu_model.h +++ b/chrome/browser/ui/tabs/existing_tab_group_sub_menu_model.h
@@ -8,7 +8,6 @@ #include <stddef.h> #include "base/macros.h" -#include "chrome/browser/ui/tabs/tab_group_data.h" #include "ui/base/models/simple_menu_model.h" class TabStripModel; @@ -42,7 +41,7 @@ // one tab that would be affected by the command is not in |group|. static bool ShouldShowGroup(TabStripModel* model, int context_index, - TabGroupData* group); + int group); DISALLOW_COPY_AND_ASSIGN(ExistingTabGroupSubMenuModel); };
diff --git a/chrome/browser/ui/tabs/tab_group_data.cc b/chrome/browser/ui/tabs/tab_group_data.cc index aced56e..f32c3f9 100644 --- a/chrome/browser/ui/tabs/tab_group_data.cc +++ b/chrome/browser/ui/tabs/tab_group_data.cc
@@ -3,13 +3,17 @@ // found in the LICENSE file. #include "chrome/browser/ui/tabs/tab_group_data.h" + +#include "base/strings/string_number_conversions.h" #include "base/strings/utf_string_conversions.h" #include "third_party/skia/include/utils/SkRandom.h" TabGroupData::TabGroupData() { - static int groupCount = 0; - title_ = base::ASCIIToUTF16("Group " + std::to_string(groupCount)); - groupCount++; + static int next_placeholder_title_number = 1; + title_ = base::ASCIIToUTF16( + "Group " + base::NumberToString(next_placeholder_title_number)); + ++next_placeholder_title_number; + static SkRandom rand; stroke_color_ = rand.nextU() | 0xff000000; }
diff --git a/chrome/browser/ui/tabs/tab_menu_model.cc b/chrome/browser/ui/tabs/tab_menu_model.cc index c647cde..9b3d51e 100644 --- a/chrome/browser/ui/tabs/tab_menu_model.cc +++ b/chrome/browser/ui/tabs/tab_menu_model.cc
@@ -51,7 +51,7 @@ } for (size_t index = 0; index < affected_indices.size(); index++) { - if (tab_strip->GetTabGroupForTab(affected_indices[index]) != nullptr) { + if (tab_strip->GetTabGroupForTab(affected_indices[index]).has_value()) { AddItemWithStringId(TabStripModel::CommandRemoveFromGroup, IDS_TAB_CXMENU_REMOVE_TAB_FROM_GROUP); break;
diff --git a/chrome/browser/ui/tabs/tab_strip_model.cc b/chrome/browser/ui/tabs/tab_strip_model.cc index 5aea4fc..a9605f92 100644 --- a/chrome/browser/ui/tabs/tab_strip_model.cc +++ b/chrome/browser/ui/tabs/tab_strip_model.cc
@@ -159,8 +159,8 @@ void set_pinned(bool value) { pinned_ = value; } bool blocked() const { return blocked_; } void set_blocked(bool value) { blocked_ = value; } - const TabGroupData* group() const { return group_; } - void set_group(const TabGroupData* value) { group_ = value; } + base::Optional<int> group() const { return group_; } + void set_group(base::Optional<int> value) { group_ = value; } private: // Make sure that if someone deletes this WebContents out from under us, it @@ -195,7 +195,7 @@ // break that guarantee, with undefined results. // - The exact shape of the group-related changes to the TabStripModel API // (and the relevant bits of the extension API) are TBD. - const TabGroupData* group_ = nullptr; + base::Optional<int> group_ = base::nullopt; DISALLOW_COPY_AND_ASSIGN(WebContentsData); }; @@ -332,7 +332,7 @@ void TabStripModel::InsertWebContentsAt(int index, std::unique_ptr<WebContents> contents, int add_types, - const TabGroupData* group) { + base::Optional<int> group) { DCHECK(!reentrancy_guard_); base::AutoReset<bool> resetter(&reentrancy_guard_, true); @@ -406,7 +406,7 @@ return nullptr; DCHECK(ContainsIndex(index)); - NotifyGroupChange(index, UngroupTab(index), nullptr); + NotifyGroupChange(index, UngroupTab(index), base::nullopt); FixOpeners(index); // Ask the delegate to save an entry for this tab in the historical tab @@ -740,21 +740,23 @@ return contents_data_[index]->blocked(); } -const TabGroupData* TabStripModel::GetTabGroupForTab(int index) const { - return (index == kNoTab) ? nullptr : contents_data_[index]->group(); +const TabGroupData* TabStripModel::GetDataForGroup(int group) const { + DCHECK(base::ContainsKey(group_data_, group)); + return group_data_.at(group).get(); } -std::vector<TabGroupData*> TabStripModel::ListTabGroups() const { - std::vector<TabGroupData*> groups; - for (std::unique_ptr<TabGroupData> const& group : group_data_) - groups.push_back(group.get()); +base::Optional<int> TabStripModel::GetTabGroupForTab(int index) const { + return (index == kNoTab) ? base::nullopt : contents_data_[index]->group(); +} +std::vector<int> TabStripModel::ListTabGroups() const { + std::vector<int> groups(group_data_.size()); + std::transform(group_data_.cbegin(), group_data_.cend(), groups.begin(), + [](const auto& id_group_pair) { return id_group_pair.first; }); return groups; } -std::vector<int> TabStripModel::ListTabsInGroup( - const TabGroupData* group) const { - DCHECK(group); +std::vector<int> TabStripModel::ListTabsInGroup(int group) const { std::vector<int> result; for (size_t i = 0; i < contents_data_.size(); ++i) { if (contents_data_[i]->group() == group) @@ -763,13 +765,11 @@ return result; } -bool TabStripModel::IsGroupPinned(const TabGroupData* group) const { - DCHECK_NE(nullptr, group); - for (auto& contents_datum : contents_data_) { +bool TabStripModel::IsGroupPinned(int group) const { + for (const auto& contents_datum : contents_data_) { if (contents_datum->group() == group) return contents_datum->pinned(); } - NOTREACHED(); return false; } @@ -840,7 +840,7 @@ int index, ui::PageTransition transition, int add_types, - const TabGroupData* group) { + base::Optional<int> group) { DCHECK(!reentrancy_guard_); base::AutoReset<bool> resetter(&reentrancy_guard_, true); @@ -947,8 +947,10 @@ DCHECK(!reentrancy_guard_); base::AutoReset<bool> resetter(&reentrancy_guard_, true); - group_data_.push_back(std::make_unique<TabGroupData>()); - TabGroupData* new_group = group_data_.back().get(); + static int next_group_id = 0; + const int new_group = next_group_id; + next_group_id++; + group_data_[new_group] = std::make_unique<TabGroupData>(); // Find a destination for the first tab that's not inside another group. We // will stack the rest of the tabs up to its right. @@ -956,7 +958,7 @@ for (int i = indices[0]; i < count(); i++) { const int destination_candidate = i + 1; const bool end_of_strip = !ContainsIndex(destination_candidate); - if (end_of_strip || GetTabGroupForTab(destination_candidate) == nullptr || + if (end_of_strip || !GetTabGroupForTab(destination_candidate).has_value() || GetTabGroupForTab(destination_candidate) != GetTabGroupForTab(indices[0])) { destination_index = destination_candidate; @@ -972,7 +974,7 @@ } void TabStripModel::AddToExistingGroup(const std::vector<int>& indices, - const TabGroupData* group) { + int group) { DCHECK(!reentrancy_guard_); base::AutoReset<bool> resetter(&reentrancy_guard_, true); @@ -1005,8 +1007,8 @@ // since tabs may move to the right. for (int i = indices.size() - 1; i >= 0; i--) { const int index = indices[i]; - const TabGroupData* old_group = GetTabGroupForTab(index); - if (old_group == nullptr) + base::Optional<int> old_group = GetTabGroupForTab(index); + if (!old_group.has_value()) continue; // Move the tab until it's the rightmost tab in its group @@ -1014,7 +1016,7 @@ while (ContainsIndex(new_index + 1) && GetTabGroupForTab(new_index + 1) == old_group) new_index++; - MoveAndSetGroup(index, new_index, nullptr); + MoveAndSetGroup(index, new_index, base::nullopt); } } @@ -1263,9 +1265,8 @@ } } -void TabStripModel::ExecuteAddToExistingGroupCommand( - int context_index, - const TabGroupData* group) { +void TabStripModel::ExecuteAddToExistingGroupCommand(int context_index, + int group) { base::RecordAction(UserMetricsAction("TabContextMenu_AddToExistingGroup")); AddToExistingGroup(GetIndicesForCommand(context_index), group); @@ -1427,13 +1428,13 @@ int index, std::unique_ptr<content::WebContents> contents, int add_types, - const TabGroupData* group) { + base::Optional<int> group) { delegate()->WillAddWebContents(contents.get()); bool active = (add_types & ADD_ACTIVE) != 0; bool pin = (add_types & ADD_PINNED) != 0; - if (group) - pin = IsGroupPinned(group); + if (group.has_value()) + pin = IsGroupPinned(group.value()); index = ConstrainInsertionIndex(index, pin); // Have to get the active contents before we monkey with the contents @@ -1475,7 +1476,7 @@ /*triggered_by_other_operation=*/true); } - if (group) + if (group.has_value()) contents_data_[index]->set_group(group); TabStripModelChange::Insert insert; @@ -1713,7 +1714,7 @@ void TabStripModel::MoveTabsIntoGroup(const std::vector<int>& indices, int destination_index, - const TabGroupData* group) { + int group) { // Some tabs will need to be moved to the right, some to the left. We need to // handle those separately. First, move tabs to the right, starting with the // rightmost tab so we don't cause other tabs we are about to move to shift. @@ -1739,8 +1740,8 @@ void TabStripModel::MoveAndSetGroup(int index, int new_index, - const TabGroupData* new_group) { - const TabGroupData* old_group = UngroupTab(index); + base::Optional<int> new_group) { + base::Optional<int> old_group = UngroupTab(index); // TODO(crbug.com/940677): Ideally the delta of type kGroupChanged below would // be batched with the move deltas resulting from MoveWebContentsAt, but that @@ -1754,38 +1755,34 @@ } void TabStripModel::NotifyGroupChange(int index, - const TabGroupData* old_group, - const TabGroupData* new_group) { + base::Optional<int> old_group, + base::Optional<int> new_group) { if (old_group == new_group) return; TabStripModelChange::GroupChange group_change; group_change.contents = GetWebContentsAt(index); group_change.index = index; - group_change.old_group_data = old_group; - group_change.new_group_data = new_group; + group_change.old_group = old_group; + group_change.new_group = new_group; TabStripModelChange change(group_change); TabStripSelectionChange selection(GetActiveWebContents(), selection_model_); for (auto& observer : observers_) observer.OnTabStripModelChanged(this, change, selection); } -const TabGroupData* TabStripModel::UngroupTab(int index) { - const TabGroupData* group = GetTabGroupForTab(index); - if (group == nullptr) - return nullptr; +base::Optional<int> TabStripModel::UngroupTab(int index) { + base::Optional<int> group = GetTabGroupForTab(index); + if (!group.has_value()) + return base::nullopt; - contents_data_[index]->set_group(nullptr); + contents_data_[index]->set_group(base::nullopt); // Delete the group if we just ungrouped the last tab in that group. if ((!ContainsIndex(index + 1) || GetTabGroupForTab(index + 1) != group) && (!ContainsIndex(index - 1) || GetTabGroupForTab(index - 1) != group)) { - for (size_t i = 0; i < contents_data_.size(); i++) - DCHECK_NE(GetTabGroupForTab(i), group); - for (auto it = group_data_.begin(); it != group_data_.end(); it++) { - if (it->get() == group) { - group_data_.erase(it); - break; - } - } + DCHECK(!std::any_of( + contents_data_.cbegin(), contents_data_.cend(), + [group](const auto& datum) { return datum->group() == group; })); + group_data_.erase(group.value()); } return group; }
diff --git a/chrome/browser/ui/tabs/tab_strip_model.h b/chrome/browser/ui/tabs/tab_strip_model.h index a7205f7..b3799df 100644 --- a/chrome/browser/ui/tabs/tab_strip_model.h +++ b/chrome/browser/ui/tabs/tab_strip_model.h
@@ -8,6 +8,7 @@ #include <stddef.h> #include <stdint.h> +#include <map> #include <memory> #include <vector> @@ -16,6 +17,7 @@ #include "base/macros.h" #include "base/memory/weak_ptr.h" #include "base/observer_list.h" +#include "base/optional.h" #include "base/time/time.h" #include "chrome/browser/ui/tabs/tab_group_data.h" #include "chrome/browser/ui/tabs/tab_strip_model_observer.h" @@ -172,7 +174,7 @@ void InsertWebContentsAt(int index, std::unique_ptr<content::WebContents> contents, int add_types, - const TabGroupData* group = nullptr); + base::Optional<int> group = base::nullopt); // Closes the WebContents at the specified index. This causes the // WebContents to be destroyed, but it may not happen immediately. @@ -304,19 +306,22 @@ // Returns true if the tab at |index| is blocked by a tab modal dialog. bool IsTabBlocked(int index) const; - // Returns the group that contains the tab at |index|, or nullptr if it is not - // grouped. This feature is in development and gated behind a feature flag. - // https://crbug.com/915956. - const TabGroupData* GetTabGroupForTab(int index) const; + // Returns the group that contains the tab at |index|, or nullopt if it is not + // grouped. This feature is in development and gated behind a feature flag + // (see https://crbug.com/915956). + base::Optional<int> GetTabGroupForTab(int index) const; - // Returns the list of tab groups that contain at least one tab in this strip. - std::vector<TabGroupData*> ListTabGroups() const; + // Returns the TabGroupData instance for the given |group|. + const TabGroupData* GetDataForGroup(int group) const; - // Returns the list of tabs affiliated with |group|. - std::vector<int> ListTabsInGroup(const TabGroupData* group) const; + // Returns a list of tab groups that contain at least one tab in this strip. + std::vector<int> ListTabGroups() const; - // Returns true if the tabs in |group| are pinned. - bool IsGroupPinned(const TabGroupData* group) const; + // Returns the list of tabs in the given |group|. + std::vector<int> ListTabsInGroup(int group) const; + + // Returns true if the tabs in the given |group| are pinned. + bool IsGroupPinned(int group) const; // Returns the index of the first tab that is not a pinned tab. This returns // |count()| if all of the tabs are pinned tabs, and 0 if none of the tabs are @@ -353,7 +358,7 @@ int index, ui::PageTransition transition, int add_types, - const TabGroupData* group = nullptr); + base::Optional<int> group = base::nullopt); // Closes the selected tabs. void CloseSelectedTabs(); @@ -379,13 +384,12 @@ // 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. |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); + // Add the set of tabs pointed to by |indices| to the given 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. |indices| must + // be sorted in ascending order. This feature is in development and gated + // behind a feature flag (see https://crbug.com/915956). + void AddToExistingGroup(const std::vector<int>& indices, int 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| @@ -430,8 +434,7 @@ // Adds the tab at |context_index| to the given tab group |group|. If // |context_index| is selected the command applies to all selected tabs. - void ExecuteAddToExistingGroupCommand(int context_index, - const TabGroupData* group); + void ExecuteAddToExistingGroupCommand(int context_index, int group); // Returns true if 'CommandToggleSiteMuted' will mute. |index| is the // index supplied to |ExecuteContextMenuCommand|. @@ -533,7 +536,7 @@ void InsertWebContentsAtImpl(int index, std::unique_ptr<content::WebContents> contents, int add_types, - const TabGroupData* group); + base::Optional<int> group); // Closes the WebContentses at the specified indices. This causes the // WebContentses to be destroyed, but it may not happen immediately. If @@ -596,22 +599,22 @@ // being moved, and adds them to the tab group |group|. void MoveTabsIntoGroup(const std::vector<int>& indices, int destination_index, - const TabGroupData* group); + int group); // Moves the tab at |index| to |new_index| and sets its group to |new_group|. // Notifies any observers that group affiliation has changed for the tab. - void MoveAndSetGroup(int index, int new_index, const TabGroupData* new_group); + void MoveAndSetGroup(int index, int new_index, base::Optional<int> new_group); // Notifies observers that the tab at |index| was moved from |old_group| to // |new_group|. void NotifyGroupChange(int index, - const TabGroupData* old_group, - const TabGroupData* new_group); + base::Optional<int> old_group, + base::Optional<int> new_group); // Helper function for MoveAndSetGroup. Removes the tab at |index| from the // group that contains it, if any. Also deletes that group, if it now contains // no tabs. Returns that group. - const TabGroupData* UngroupTab(int index); + base::Optional<int> UngroupTab(int index); // Changes the pinned state of the tab at |index|. void SetTabPinnedImpl(int index, bool pinned); @@ -631,8 +634,9 @@ // be kept in sync with |selection_model_|. std::vector<std::unique_ptr<WebContentsData>> contents_data_; - // The tab groups hosted within this TabStripModel. - std::vector<std::unique_ptr<TabGroupData>> group_data_; + // The data for tab groups hosted within this TabStripModel, indexed by the + // group ID. + std::map<int, std::unique_ptr<TabGroupData>> group_data_; TabStripModelDelegate* delegate_;
diff --git a/chrome/browser/ui/tabs/tab_strip_model_delegate.h b/chrome/browser/ui/tabs/tab_strip_model_delegate.h index 703e088..f542eb4b 100644 --- a/chrome/browser/ui/tabs/tab_strip_model_delegate.h +++ b/chrome/browser/ui/tabs/tab_strip_model_delegate.h
@@ -9,10 +9,10 @@ #include <vector> #include "base/macros.h" +#include "base/optional.h" class Browser; class GURL; -class TabGroupData; namespace content { class WebContents; @@ -55,7 +55,7 @@ virtual void AddTabAt(const GURL& url, int index, bool foreground, - const TabGroupData* group = nullptr) = 0; + base::Optional<int> group = base::nullopt) = 0; // Asks for a new TabStripModel to be created and the given web contentses to // be added to it. Its size and position are reflected in |window_bounds|.
diff --git a/chrome/browser/ui/tabs/tab_strip_model_observer.cc b/chrome/browser/ui/tabs/tab_strip_model_observer.cc index 82649bd8..555b5eb 100644 --- a/chrome/browser/ui/tabs/tab_strip_model_observer.cc +++ b/chrome/browser/ui/tabs/tab_strip_model_observer.cc
@@ -25,6 +25,16 @@ // TabStripModelChange::TabStripModelChange() = default; +TabStripModelChange::GroupChange::GroupChange() = default; + +TabStripModelChange::GroupChange::GroupChange(const GroupChange& other) = + default; + +TabStripModelChange::GroupChange& TabStripModelChange::GroupChange::operator=( + const GroupChange& other) = default; + +TabStripModelChange::GroupChange::~GroupChange() = default; + TabStripModelChange::TabStripModelChange(Insert delta) : TabStripModelChange(Type::kInserted, std::make_unique<Insert>(std::move(delta))) {}
diff --git a/chrome/browser/ui/tabs/tab_strip_model_observer.h b/chrome/browser/ui/tabs/tab_strip_model_observer.h index 8b7f264..31709007 100644 --- a/chrome/browser/ui/tabs/tab_strip_model_observer.h +++ b/chrome/browser/ui/tabs/tab_strip_model_observer.h
@@ -9,10 +9,10 @@ #include <vector> #include "base/macros.h" +#include "base/optional.h" #include "chrome/browser/ui/tabs/tab_change_type.h" #include "ui/base/models/list_selection_model.h" -class TabGroupData; class TabStripModel; namespace content { @@ -142,13 +142,18 @@ int index; }; - // A WebContents' group affiliation changed from |old_group_data| to - // |new_group_data|. + // A WebContents' group affiliation changed from |old_group| to |new_group|. struct GroupChange : public Delta { + // Constructors and destructor required due to Optional. + GroupChange(); + GroupChange(const GroupChange& other); + GroupChange& operator=(const GroupChange& other); + ~GroupChange() override; + content::WebContents* contents; int index; - const TabGroupData* old_group_data; - const TabGroupData* new_group_data; + base::Optional<int> old_group; + base::Optional<int> new_group; }; TabStripModelChange();
diff --git a/chrome/browser/ui/tabs/tab_strip_model_unittest.cc b/chrome/browser/ui/tabs/tab_strip_model_unittest.cc index fdd0589..32755fbbe2db 100644 --- a/chrome/browser/ui/tabs/tab_strip_model_unittest.cc +++ b/chrome/browser/ui/tabs/tab_strip_model_unittest.cc
@@ -12,6 +12,7 @@ #include <utility> #include <vector> +#include "base/optional.h" #include "base/stl_util.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_split.h" @@ -85,8 +86,6 @@ dst_index(a_dst_index), change_reason(CHANGE_REASON_NONE), foreground(false), - old_group(nullptr), - new_group(nullptr), action(a_action) {} WebContents* src_contents; @@ -95,8 +94,8 @@ int dst_index; int change_reason; bool foreground; - const TabGroupData* old_group; - const TabGroupData* new_group; + base::Optional<int> old_group; + base::Optional<int> new_group; TabStripModelObserverAction action; }; @@ -192,10 +191,11 @@ s.src_contents = old_contents; states_.push_back(s); } + void PushGroupChangeState(WebContents* contents, int index, - const TabGroupData* old_group, - const TabGroupData* new_group) { + base::Optional<int> old_group, + base::Optional<int> new_group) { State s(contents, index, GROUP_CHANGED); s.old_group = old_group; s.new_group = new_group; @@ -239,8 +239,7 @@ case TabStripModelChange::kGroupChanged: { auto* group_change = change.GetGroupChange(); PushGroupChangeState(group_change->contents, group_change->index, - group_change->old_group_data, - group_change->new_group_data); + group_change->old_group, group_change->new_group); break; } case TabStripModelChange::kSelectionOnly: @@ -360,12 +359,16 @@ return actual; } + void PrepareTabs(TabStripModel* model, int tab_count) { + for (int i = 0; i < tab_count; ++i) + model->AppendWebContents(CreateWebContentsWithID(i), true); + } + void PrepareTabstripForSelectionTest(TabStripModel* model, int tab_count, int pinned_count, const std::string& selected_tabs) { - for (int i = 0; i < tab_count; ++i) - model->AppendWebContents(CreateWebContentsWithID(i), true); + PrepareTabs(model, tab_count); for (int i = 0; i < pinned_count; ++i) model->SetTabPinned(i, true); @@ -2729,7 +2732,7 @@ TabStripModel strip(&delegate, profile()); strip.AppendWebContents(CreateWebContents(), false); - EXPECT_EQ(strip.GetTabGroupForTab(0), nullptr); + EXPECT_FALSE(strip.GetTabGroupForTab(0).has_value()); strip.ActivateTabAt(0, {TabStripModel::GestureType::kOther}); strip.CloseAllTabs(); @@ -2742,7 +2745,7 @@ strip.AddToNewGroup({0}); - EXPECT_NE(strip.GetTabGroupForTab(0), nullptr); + EXPECT_TRUE(strip.GetTabGroupForTab(0).has_value()); strip.ActivateTabAt(0, {TabStripModel::GestureType::kOther}); strip.CloseAllTabs(); @@ -2753,8 +2756,8 @@ MockTabStripModelObserver::State ExpectedGroupChangeState( const TabStripModel& strip, int tab_index, - const TabGroupData* old_group, - const TabGroupData* new_group) { + base::Optional<int> old_group, + base::Optional<int> new_group) { MockTabStripModelObserver::State state( strip.GetWebContentsAt(tab_index), tab_index, MockTabStripModelObserver::GROUP_CHANGED); @@ -2775,7 +2778,7 @@ observer.ClearStates(); strip.AddToNewGroup({0}); EXPECT_EQ(1, observer.GetStateCount()); - observer.StateEquals(0, ExpectedGroupChangeState(strip, 0, nullptr, + observer.StateEquals(0, ExpectedGroupChangeState(strip, 0, base::nullopt, strip.GetTabGroupForTab(0))); strip.CloseAllTabs(); @@ -2790,11 +2793,11 @@ observer.ClearStates(); strip.AddToNewGroup({0}); - const TabGroupData* first_group = strip.GetTabGroupForTab(0); + base::Optional<int> first_group = strip.GetTabGroupForTab(0); strip.AddToNewGroup({0}); EXPECT_EQ(2, observer.GetStateCount()); observer.StateEquals( - 0, ExpectedGroupChangeState(strip, 0, nullptr, first_group)); + 0, ExpectedGroupChangeState(strip, 0, base::nullopt, first_group)); observer.StateEquals(1, ExpectedGroupChangeState(strip, 0, first_group, strip.GetTabGroupForTab(0))); @@ -2804,12 +2807,9 @@ TEST_F(TabStripModelTest, AddTabToNewGroupMiddleOfExistingGroup) { TestTabStripModelDelegate delegate; TabStripModel strip(&delegate, profile()); - strip.AppendWebContents(CreateWebContentsWithID(0), false); - strip.AppendWebContents(CreateWebContentsWithID(1), false); - strip.AppendWebContents(CreateWebContentsWithID(2), false); - strip.AppendWebContents(CreateWebContentsWithID(3), false); + PrepareTabs(&strip, 4); strip.AddToNewGroup({0, 1, 2, 3}); - const TabGroupData* first_group = strip.GetTabGroupForTab(0); + base::Optional<int> first_group = strip.GetTabGroupForTab(0); strip.AddToNewGroup({1, 2}); @@ -2819,17 +2819,13 @@ EXPECT_EQ(strip.GetTabGroupForTab(2), strip.GetTabGroupForTab(3)); EXPECT_EQ("0 3 1 2", GetTabStripStateString(strip)); - strip.ActivateTabAt(0, {TabStripModel::GestureType::kOther}); strip.CloseAllTabs(); } TEST_F(TabStripModelTest, AddTabToNewGroupMiddleOfExistingGroupTwoGroups) { TestTabStripModelDelegate delegate; TabStripModel strip(&delegate, profile()); - strip.AppendWebContents(CreateWebContentsWithID(0), false); - strip.AppendWebContents(CreateWebContentsWithID(1), false); - strip.AppendWebContents(CreateWebContentsWithID(2), false); - strip.AppendWebContents(CreateWebContentsWithID(3), false); + PrepareTabs(&strip, 4); strip.AddToNewGroup({0, 1, 2}); strip.AddToNewGroup({3}); @@ -2837,110 +2833,69 @@ EXPECT_NE(strip.GetTabGroupForTab(2), strip.GetTabGroupForTab(0)); EXPECT_EQ("0 2 1 3", GetTabStripStateString(strip)); - strip.ActivateTabAt(0, {TabStripModel::GestureType::kOther}); strip.CloseAllTabs(); } TEST_F(TabStripModelTest, AddTabToNewGroupReorders) { TestTabStripModelDelegate delegate; TabStripModel strip(&delegate, profile()); - 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)}; + PrepareTabs(&strip, 3); strip.AddToNewGroup({0, 2}); - EXPECT_EQ(strip.GetWebContentsAt(0), orig[0]); - EXPECT_EQ(strip.GetWebContentsAt(1), orig[2]); - EXPECT_EQ(strip.GetWebContentsAt(2), orig[1]); + EXPECT_EQ("0 2 1", GetTabStripStateString(strip)); EXPECT_EQ(strip.GetTabGroupForTab(0), strip.GetTabGroupForTab(1)); - EXPECT_NE(strip.GetTabGroupForTab(0), nullptr); - EXPECT_EQ(strip.GetTabGroupForTab(2), nullptr); + EXPECT_TRUE(strip.GetTabGroupForTab(0).has_value()); + EXPECT_FALSE(strip.GetTabGroupForTab(2).has_value()); - strip.ActivateTabAt(0, {TabStripModel::GestureType::kOther}); strip.CloseAllTabs(); } TEST_F(TabStripModelTest, AddTabToNewGroupPins) { TestTabStripModelDelegate delegate; TabStripModel strip(&delegate, profile()); - strip.AppendWebContents(CreateWebContents(), false); - strip.AppendWebContents(CreateWebContents(), false); - std::vector<WebContents*> orig{strip.GetWebContentsAt(0), - strip.GetWebContentsAt(1)}; + PrepareTabs(&strip, 2); + strip.SetTabPinned(0, true); strip.AddToNewGroup({0, 1}); + EXPECT_EQ("0p 1p", GetTabStripStateString(strip)); - EXPECT_TRUE(strip.IsTabPinned(1)); - EXPECT_EQ(strip.GetWebContentsAt(0), orig[0]); - EXPECT_EQ(strip.GetWebContentsAt(1), orig[1]); - - strip.ActivateTabAt(0, {TabStripModel::GestureType::kOther}); strip.CloseAllTabs(); } TEST_F(TabStripModelTest, AddTabToNewGroupPinsAndReorders) { TestTabStripModelDelegate delegate; TabStripModel strip(&delegate, profile()); - 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)}; + PrepareTabs(&strip, 3); + strip.SetTabPinned(0, true); - strip.AddToNewGroup({0, 2}); + EXPECT_EQ("0p 2p 1", GetTabStripStateString(strip)); - EXPECT_EQ(strip.GetWebContentsAt(0), orig[0]); - EXPECT_EQ(strip.GetWebContentsAt(1), orig[2]); - EXPECT_EQ(strip.GetWebContentsAt(2), orig[1]); - - strip.ActivateTabAt(0, {TabStripModel::GestureType::kOther}); strip.CloseAllTabs(); } TEST_F(TabStripModelTest, AddTabToNewGroupMovePinnedTabRight) { TestTabStripModelDelegate 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)}; + PrepareTabs(&strip, 4); + strip.SetTabPinned(0, true); strip.SetTabPinned(1, true); strip.SetTabPinned(2, true); strip.AddToNewGroup({0, 1, 2}); strip.AddToNewGroup({1, 3}); + EXPECT_EQ("0p 2p 1p 3p", GetTabStripStateString(strip)); - EXPECT_EQ(strip.GetWebContentsAt(0), orig[0]); - EXPECT_EQ(strip.GetWebContentsAt(1), orig[2]); - EXPECT_EQ(strip.GetWebContentsAt(2), orig[1]); - EXPECT_EQ(strip.GetWebContentsAt(3), orig[3]); - - strip.ActivateTabAt(0, {TabStripModel::GestureType::kOther}); strip.CloseAllTabs(); } TEST_F(TabStripModelTest, AddTabToNewGroupMovePinnedTabLeft) { TestTabStripModelDelegate 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)}; + PrepareTabs(&strip, 5); + strip.SetTabPinned(0, true); strip.SetTabPinned(1, true); strip.SetTabPinned(2, true); @@ -2948,49 +2903,42 @@ strip.AddToNewGroup({0, 1, 2}); strip.AddToNewGroup({1, 3, 4}); + EXPECT_EQ("0p 2p 1p 3p 4p", GetTabStripStateString(strip)); - EXPECT_EQ(strip.GetWebContentsAt(0), orig[0]); - EXPECT_EQ(strip.GetWebContentsAt(1), orig[2]); - EXPECT_EQ(strip.GetWebContentsAt(2), orig[1]); - EXPECT_EQ(strip.GetWebContentsAt(3), orig[3]); - EXPECT_EQ(strip.GetWebContentsAt(4), orig[4]); - - strip.ActivateTabAt(0, {TabStripModel::GestureType::kOther}); strip.CloseAllTabs(); } TEST_F(TabStripModelTest, AddTabToExistingGroupIdempotent) { TestTabStripModelDelegate delegate; TabStripModel strip(&delegate, profile()); - strip.AppendWebContents(CreateWebContents(), false); + MockTabStripModelObserver observer; + strip.AddObserver(&observer); + strip.AppendWebContents(CreateWebContents(), true); + strip.AddToNewGroup({0}); - const TabGroupData* group = strip.GetTabGroupForTab(0); + base::Optional<int> group = strip.GetTabGroupForTab(0); + strip.AddToExistingGroup({0}, group.value()); - strip.AddToExistingGroup({0}, group); - + observer.ClearStates(); EXPECT_EQ(strip.GetTabGroupForTab(0), group); + EXPECT_EQ(0, observer.GetStateCount()); - strip.ActivateTabAt(0, {TabStripModel::GestureType::kOther}); strip.CloseAllTabs(); } TEST_F(TabStripModelTest, AddTabToExistingGroup) { TestTabStripModelDelegate delegate; TabStripModel strip(&delegate, profile()); - strip.AppendWebContents(CreateWebContents(), false); - strip.AppendWebContents(CreateWebContents(), false); - std::vector<WebContents*> in{strip.GetWebContentsAt(0), - strip.GetWebContentsAt(1)}; - strip.AddToNewGroup({0}); - const TabGroupData* group = strip.GetTabGroupForTab(0); + PrepareTabs(&strip, 2); - strip.AddToExistingGroup({1}, group); + strip.AddToNewGroup({0}); + base::Optional<int> group = strip.GetTabGroupForTab(0); + + strip.AddToExistingGroup({1}, group.value()); EXPECT_EQ(strip.GetTabGroupForTab(1), group); - EXPECT_EQ(strip.GetWebContentsAt(0), in[0]); - EXPECT_EQ(strip.GetWebContentsAt(1), in[1]); + EXPECT_EQ("0 1", GetTabStripStateString(strip)); - strip.ActivateTabAt(0, {TabStripModel::GestureType::kOther}); strip.CloseAllTabs(); } @@ -2999,16 +2947,16 @@ TabStripModel strip(&delegate, profile()); MockTabStripModelObserver observer; strip.AddObserver(&observer); - strip.AppendWebContents(CreateWebContents(), true); - strip.AppendWebContents(CreateWebContents(), false); + PrepareTabs(&strip, 2); strip.AddToNewGroup({0}); observer.ClearStates(); - const TabGroupData* group = strip.GetTabGroupForTab(0); + base::Optional<int> group = strip.GetTabGroupForTab(0); - strip.AddToExistingGroup({1}, group); + strip.AddToExistingGroup({1}, group.value()); EXPECT_EQ(1, observer.GetStateCount()); - observer.StateEquals(0, ExpectedGroupChangeState(strip, 1, nullptr, group)); + observer.StateEquals( + 0, ExpectedGroupChangeState(strip, 1, base::nullopt, group)); strip.CloseAllTabs(); } @@ -3016,118 +2964,84 @@ TEST_F(TabStripModelTest, AddTabToExistingGroupReordersToTheRight) { TestTabStripModelDelegate delegate; TabStripModel strip(&delegate, profile()); - strip.AppendWebContents(CreateWebContents(), false); - strip.AppendWebContents(CreateWebContents(), false); - std::vector<WebContents*> orig{strip.GetWebContentsAt(0), - strip.GetWebContentsAt(1)}; + PrepareTabs(&strip, 2); + strip.AddToNewGroup({1}); - const TabGroupData* group = strip.GetTabGroupForTab(1); + base::Optional<int> group = strip.GetTabGroupForTab(1); - strip.AddToExistingGroup({0}, group); - + strip.AddToExistingGroup({0}, group.value()); EXPECT_EQ(strip.GetTabGroupForTab(0), group); EXPECT_EQ(strip.GetTabGroupForTab(1), group); - EXPECT_EQ(strip.GetWebContentsAt(0), orig[1]); - EXPECT_EQ(strip.GetWebContentsAt(1), orig[0]); + EXPECT_EQ("1 0", GetTabStripStateString(strip)); - strip.ActivateTabAt(0, {TabStripModel::GestureType::kOther}); strip.CloseAllTabs(); } TEST_F(TabStripModelTest, AddTabToExistingGroupReordersToTheLeft) { TestTabStripModelDelegate delegate; TabStripModel strip(&delegate, profile()); - 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)}; + PrepareTabs(&strip, 3); + strip.AddToNewGroup({0}); - const TabGroupData* group = strip.GetTabGroupForTab(0); + base::Optional<int> group = strip.GetTabGroupForTab(0); - strip.AddToExistingGroup({2}, group); - + strip.AddToExistingGroup({2}, group.value()); EXPECT_EQ(strip.GetTabGroupForTab(0), group); EXPECT_EQ(strip.GetTabGroupForTab(1), group); - EXPECT_EQ(strip.GetTabGroupForTab(2), nullptr); - EXPECT_EQ(strip.GetWebContentsAt(0), orig[0]); - EXPECT_EQ(strip.GetWebContentsAt(1), orig[2]); - EXPECT_EQ(strip.GetWebContentsAt(2), orig[1]); + EXPECT_FALSE(strip.GetTabGroupForTab(2).has_value()); + EXPECT_EQ("0 2 1", GetTabStripStateString(strip)); - strip.ActivateTabAt(0, {TabStripModel::GestureType::kOther}); strip.CloseAllTabs(); } TEST_F(TabStripModelTest, AddTabToExistingGroupReorders) { TestTabStripModelDelegate 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)}; + PrepareTabs(&strip, 4); + strip.AddToNewGroup({1}); - const TabGroupData* group = strip.GetTabGroupForTab(1); + base::Optional<int> group = strip.GetTabGroupForTab(1); - strip.AddToExistingGroup({0, 3}, group); - + strip.AddToExistingGroup({0, 3}, group.value()); EXPECT_EQ(strip.GetTabGroupForTab(0), group); EXPECT_EQ(strip.GetTabGroupForTab(1), group); EXPECT_EQ(strip.GetTabGroupForTab(2), group); - EXPECT_EQ(strip.GetTabGroupForTab(3), nullptr); - EXPECT_EQ(strip.GetWebContentsAt(0), orig[1]); - EXPECT_EQ(strip.GetWebContentsAt(1), orig[0]); - EXPECT_EQ(strip.GetWebContentsAt(2), orig[3]); - EXPECT_EQ(strip.GetWebContentsAt(3), orig[2]); + EXPECT_FALSE(strip.GetTabGroupForTab(3).has_value()); + EXPECT_EQ("1 0 3 2", GetTabStripStateString(strip)); - strip.ActivateTabAt(0, {TabStripModel::GestureType::kOther}); strip.CloseAllTabs(); } TEST_F(TabStripModelTest, AddTabToExistingGroupPins) { TestTabStripModelDelegate delegate; TabStripModel strip(&delegate, profile()); - strip.AppendWebContents(CreateWebContents(), false); - strip.AppendWebContents(CreateWebContents(), false); - std::vector<WebContents*> orig{strip.GetWebContentsAt(0), - strip.GetWebContentsAt(1)}; + PrepareTabs(&strip, 2); + strip.SetTabPinned(0, true); strip.AddToNewGroup({0}); - const TabGroupData* group = strip.GetTabGroupForTab(0); + base::Optional<int> group = strip.GetTabGroupForTab(0); - strip.AddToExistingGroup({1}, group); - - EXPECT_TRUE(strip.IsTabPinned(1)); + strip.AddToExistingGroup({1}, group.value()); + EXPECT_EQ("0p 1p", GetTabStripStateString(strip)); EXPECT_EQ(strip.GetTabGroupForTab(1), group); - EXPECT_EQ(strip.GetWebContentsAt(0), orig[0]); - EXPECT_EQ(strip.GetWebContentsAt(1), orig[1]); - strip.ActivateTabAt(0, {TabStripModel::GestureType::kOther}); strip.CloseAllTabs(); } TEST_F(TabStripModelTest, AddTabToExistingGroupUnpins) { TestTabStripModelDelegate delegate; TabStripModel strip(&delegate, profile()); - strip.AppendWebContents(CreateWebContents(), false); - strip.AppendWebContents(CreateWebContents(), false); - std::vector<WebContents*> orig{strip.GetWebContentsAt(0), - strip.GetWebContentsAt(1)}; + PrepareTabs(&strip, 2); + strip.SetTabPinned(0, true); strip.AddToNewGroup({1}); - const TabGroupData* group = strip.GetTabGroupForTab(1); + base::Optional<int> group = strip.GetTabGroupForTab(1); - strip.AddToExistingGroup({0}, group); - + strip.AddToExistingGroup({0}, group.value()); EXPECT_FALSE(strip.IsTabPinned(0)); EXPECT_EQ(strip.GetTabGroupForTab(0), group); - EXPECT_EQ(strip.GetWebContentsAt(0), orig[1]); - EXPECT_EQ(strip.GetWebContentsAt(1), orig[0]); + EXPECT_EQ("1 0", GetTabStripStateString(strip)); - strip.ActivateTabAt(0, {TabStripModel::GestureType::kOther}); strip.CloseAllTabs(); } @@ -3148,14 +3062,13 @@ TEST_F(TabStripModelTest, RemoveTabFromGroup) { TestTabStripModelDelegate delegate; TabStripModel strip(&delegate, profile()); - strip.AppendWebContents(CreateWebContents(), false); + strip.AppendWebContents(CreateWebContents(), true); strip.AddToNewGroup({0}); strip.RemoveFromGroup({0}); - EXPECT_EQ(strip.GetTabGroupForTab(0), nullptr); + EXPECT_FALSE(strip.GetTabGroupForTab(0).has_value()); - strip.ActivateTabAt(0, {TabStripModel::GestureType::kOther}); strip.CloseAllTabs(); } @@ -3169,11 +3082,12 @@ strip.AddToNewGroup({0}); observer.ClearStates(); - const TabGroupData* group = strip.GetTabGroupForTab(0); + base::Optional<int> group = strip.GetTabGroupForTab(0); strip.RemoveFromGroup({0}); EXPECT_EQ(1, observer.GetStateCount()); - observer.StateEquals(0, ExpectedGroupChangeState(strip, 0, group, nullptr)); + observer.StateEquals( + 0, ExpectedGroupChangeState(strip, 0, group, base::nullopt)); strip.CloseAllTabs(); } @@ -3181,29 +3095,22 @@ TEST_F(TabStripModelTest, RemoveTabFromGroupReorders) { TestTabStripModelDelegate delegate; TabStripModel strip(&delegate, profile()); - strip.AppendWebContents(CreateWebContents(), false); - strip.AppendWebContents(CreateWebContents(), false); - std::vector<WebContents*> orig{strip.GetWebContentsAt(0), - strip.GetWebContentsAt(1)}; + PrepareTabs(&strip, 2); 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]); + EXPECT_FALSE(strip.GetTabGroupForTab(1).has_value()); + EXPECT_TRUE(strip.GetTabGroupForTab(0).has_value()); + EXPECT_EQ("1 0", GetTabStripStateString(strip)); - strip.ActivateTabAt(0, {TabStripModel::GestureType::kOther}); strip.CloseAllTabs(); } TEST_F(TabStripModelTest, RemoveTabFromGroupDoesntReorderIfNoGroup) { TestTabStripModelDelegate delegate; TabStripModel strip(&delegate, profile()); - strip.AppendWebContents(CreateWebContentsWithID(0), true); - strip.AppendWebContents(CreateWebContentsWithID(1), false); - strip.AppendWebContents(CreateWebContentsWithID(2), false); + PrepareTabs(&strip, 3); strip.AddToNewGroup({0}); strip.RemoveFromGroup({0, 1}); @@ -3215,66 +3122,43 @@ TEST_F(TabStripModelTest, RemoveTabFromGroupMaintainsOrderOfSelectedTabs) { TestTabStripModelDelegate 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)}; + PrepareTabs(&strip, 4); 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]); + EXPECT_TRUE(strip.GetTabGroupForTab(0).has_value()); + EXPECT_TRUE(strip.GetTabGroupForTab(1).has_value()); + EXPECT_FALSE(strip.GetTabGroupForTab(2).has_value()); + EXPECT_FALSE(strip.GetTabGroupForTab(3).has_value()); + EXPECT_EQ("1 3 0 2", GetTabStripStateString(strip)); - strip.ActivateTabAt(0, {TabStripModel::GestureType::kOther}); strip.CloseAllTabs(); } TEST_F(TabStripModelTest, RemoveTabFromGroupMixtureOfGroups) { TestTabStripModelDelegate 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)}; + PrepareTabs(&strip, 5); 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]); + EXPECT_TRUE(strip.GetTabGroupForTab(0).has_value()); + EXPECT_FALSE(strip.GetTabGroupForTab(1).has_value()); + EXPECT_TRUE(strip.GetTabGroupForTab(2).has_value()); + EXPECT_FALSE(strip.GetTabGroupForTab(3).has_value()); + EXPECT_FALSE(strip.GetTabGroupForTab(4).has_value()); + EXPECT_EQ("1 0 2 3 4", GetTabStripStateString(strip)); - strip.ActivateTabAt(0, {TabStripModel::GestureType::kOther}); strip.CloseAllTabs(); } TEST_F(TabStripModelTest, RemoveTabFromGroupDeletesGroup) { TestTabStripModelDelegate delegate; TabStripModel strip(&delegate, profile()); - strip.AppendWebContents(CreateWebContents(), false); + strip.AppendWebContents(CreateWebContents(), true); strip.AddToNewGroup({0}); EXPECT_EQ(strip.ListTabGroups().size(), 1U); @@ -3282,43 +3166,40 @@ EXPECT_EQ(strip.ListTabGroups().size(), 0U); - strip.ActivateTabAt(0, {TabStripModel::GestureType::kOther}); strip.CloseAllTabs(); } TEST_F(TabStripModelTest, AddToNewGroupDeletesGroup) { TestTabStripModelDelegate delegate; TabStripModel strip(&delegate, profile()); - strip.AppendWebContents(CreateWebContents(), false); + strip.AppendWebContents(CreateWebContents(), true); strip.AddToNewGroup({0}); EXPECT_EQ(strip.ListTabGroups().size(), 1U); - const TabGroupData* group = strip.GetTabGroupForTab(0); + base::Optional<int> group = strip.GetTabGroupForTab(0); strip.AddToNewGroup({0}); EXPECT_EQ(strip.ListTabGroups().size(), 1U); EXPECT_NE(strip.GetTabGroupForTab(0), group); - strip.ActivateTabAt(0, {TabStripModel::GestureType::kOther}); strip.CloseAllTabs(); } TEST_F(TabStripModelTest, AddToExistingGroupDeletesGroup) { TestTabStripModelDelegate delegate; TabStripModel strip(&delegate, profile()); - strip.AppendWebContents(CreateWebContents(), false); + strip.AppendWebContents(CreateWebContents(), true); strip.AppendWebContents(CreateWebContents(), false); strip.AddToNewGroup({0}); strip.AddToNewGroup({1}); EXPECT_EQ(strip.ListTabGroups().size(), 2U); - const TabGroupData* group = strip.GetTabGroupForTab(1); + base::Optional<int> group = strip.GetTabGroupForTab(1); - strip.AddToExistingGroup({1}, strip.GetTabGroupForTab(0)); + strip.AddToExistingGroup({1}, strip.GetTabGroupForTab(0).value()); EXPECT_EQ(strip.ListTabGroups().size(), 1U); EXPECT_NE(strip.ListTabGroups()[0], group); - strip.ActivateTabAt(0, {TabStripModel::GestureType::kOther}); strip.CloseAllTabs(); } @@ -3341,7 +3222,7 @@ strip.AddObserver(&observer); strip.AppendWebContents(CreateWebContents(), true); strip.AddToNewGroup({0}); - const TabGroupData* old_group = strip.GetTabGroupForTab(0); + base::Optional<int> old_group = strip.GetTabGroupForTab(0); observer.ClearStates(); strip.CloseWebContentsAt(0, TabStripModel::CLOSE_USER_GESTURE); @@ -3352,7 +3233,7 @@ if (observer.GetStateAt(i).action == MockTabStripModelObserver::GROUP_CHANGED) { observer.StateEquals( - i, ExpectedGroupChangeState(strip, 0, old_group, nullptr)); + i, ExpectedGroupChangeState(strip, 0, old_group, base::nullopt)); num_group_changed_notifications++; } } @@ -3364,20 +3245,17 @@ TEST_F(TabStripModelTest, InsertWebContentsAtDoesNotGroupByDefault) { TestTabStripModelDelegate delegate; TabStripModel strip(&delegate, profile()); + strip.AppendWebContents(CreateWebContents(), true); strip.AppendWebContents(CreateWebContents(), false); - strip.AppendWebContents(CreateWebContents(), false); - std::vector<WebContents*> orig = {strip.GetWebContentsAt(0), - strip.GetWebContentsAt(1)}; strip.AddToNewGroup({0, 1}); strip.InsertWebContentsAt(2, CreateWebContents(), TabStripModel::ADD_NONE); // The newly added tab should not be in the group. - EXPECT_NE(strip.GetTabGroupForTab(0), nullptr); - EXPECT_NE(strip.GetTabGroupForTab(1), nullptr); - EXPECT_EQ(strip.GetTabGroupForTab(2), nullptr); + EXPECT_TRUE(strip.GetTabGroupForTab(0).has_value()); + EXPECT_TRUE(strip.GetTabGroupForTab(1).has_value()); + EXPECT_FALSE(strip.GetTabGroupForTab(2).has_value()); - strip.ActivateTabAt(0, {TabStripModel::GestureType::kOther}); strip.CloseAllTabs(); } @@ -3386,23 +3264,19 @@ TEST_F(TabStripModelTest, InsertWebContentsAtWithGroupGroups) { TestTabStripModelDelegate delegate; TabStripModel strip(&delegate, profile()); - strip.AppendWebContents(CreateWebContents(), false); - strip.AppendWebContents(CreateWebContents(), false); - std::vector<WebContents*> orig = {strip.GetWebContentsAt(0), - strip.GetWebContentsAt(1)}; + strip.AppendWebContents(CreateWebContentsWithID(0), true); + strip.AppendWebContents(CreateWebContentsWithID(1), false); strip.AddToNewGroup({0, 1}); - const TabGroupData* group = strip.GetTabGroupForTab(0); + base::Optional<int> group = strip.GetTabGroupForTab(0); - strip.InsertWebContentsAt(1, CreateWebContents(), TabStripModel::ADD_NONE, - group); + strip.InsertWebContentsAt(1, CreateWebContentsWithID(2), + TabStripModel::ADD_NONE, group); EXPECT_EQ(strip.GetTabGroupForTab(0), group); EXPECT_EQ(strip.GetTabGroupForTab(1), group); EXPECT_EQ(strip.GetTabGroupForTab(2), group); - EXPECT_EQ(strip.GetWebContentsAt(0), orig[0]); - EXPECT_EQ(strip.GetWebContentsAt(2), orig[1]); + EXPECT_EQ("0 2 1", GetTabStripStateString(strip)); - strip.ActivateTabAt(0, {TabStripModel::GestureType::kOther}); strip.CloseAllTabs(); } @@ -3411,22 +3285,16 @@ TEST_F(TabStripModelTest, InsertWebContentsAtWithPinnedGroupPins) { TestTabStripModelDelegate delegate; TabStripModel strip(&delegate, profile()); - strip.AppendWebContents(CreateWebContents(), false); - strip.AppendWebContents(CreateWebContents(), false); + strip.AppendWebContents(CreateWebContentsWithID(0), true); + strip.AppendWebContents(CreateWebContentsWithID(1), false); strip.SetTabPinned(0, true); strip.SetTabPinned(1, true); - std::vector<WebContents*> orig = {strip.GetWebContentsAt(0), - strip.GetWebContentsAt(1)}; strip.AddToNewGroup({0, 1}); - const TabGroupData* group = strip.GetTabGroupForTab(0); + base::Optional<int> group = strip.GetTabGroupForTab(0); - strip.InsertWebContentsAt(1, CreateWebContents(), TabStripModel::ADD_NONE, - group); + strip.InsertWebContentsAt(1, CreateWebContentsWithID(2), + TabStripModel::ADD_NONE, group); + EXPECT_EQ("0p 2p 1p", GetTabStripStateString(strip)); - EXPECT_TRUE(strip.IsTabPinned(1)); - EXPECT_EQ(strip.GetWebContentsAt(0), orig[0]); - EXPECT_EQ(strip.GetWebContentsAt(2), orig[1]); - - strip.ActivateTabAt(0, {TabStripModel::GestureType::kOther}); strip.CloseAllTabs(); }
diff --git a/chrome/browser/ui/tabs/test_tab_strip_model_delegate.cc b/chrome/browser/ui/tabs/test_tab_strip_model_delegate.cc index 9bb6c86..c2dedae 100644 --- a/chrome/browser/ui/tabs/test_tab_strip_model_delegate.cc +++ b/chrome/browser/ui/tabs/test_tab_strip_model_delegate.cc
@@ -18,7 +18,7 @@ void TestTabStripModelDelegate::AddTabAt(const GURL& url, int index, bool foreground, - const TabGroupData* group) {} + base::Optional<int> group) {} Browser* TestTabStripModelDelegate::CreateNewStripWithContents( std::vector<NewStripContents> contentses,
diff --git a/chrome/browser/ui/tabs/test_tab_strip_model_delegate.h b/chrome/browser/ui/tabs/test_tab_strip_model_delegate.h index 4855f61..d08beaa 100644 --- a/chrome/browser/ui/tabs/test_tab_strip_model_delegate.h +++ b/chrome/browser/ui/tabs/test_tab_strip_model_delegate.h
@@ -7,10 +7,9 @@ #include "base/compiler_specific.h" #include "base/macros.h" +#include "base/optional.h" #include "chrome/browser/ui/tabs/tab_strip_model_delegate.h" -class TabGroupData; - // Mock TabStripModelDelegate. class TestTabStripModelDelegate : public TabStripModelDelegate { public: @@ -21,7 +20,7 @@ void AddTabAt(const GURL& url, int index, bool foregroud, - const TabGroupData* group) override; + base::Optional<int> group) override; Browser* CreateNewStripWithContents(std::vector<NewStripContents> contentses, const gfx::Rect& window_bounds, bool maximize) override;
diff --git a/chrome/browser/ui/views/apps/app_info_dialog/app_info_summary_panel.cc b/chrome/browser/ui/views/apps/app_info_dialog/app_info_summary_panel.cc index 25136a3..f730093a 100644 --- a/chrome/browser/ui/views/apps/app_info_dialog/app_info_summary_panel.cc +++ b/chrome/browser/ui/views/apps/app_info_dialog/app_info_summary_panel.cc
@@ -253,9 +253,14 @@ } void AppInfoSummaryPanel::StartCalculatingAppSize() { - extensions::path_util::CalculateAndFormatExtensionDirectorySize( - app_->path(), IDS_APPLICATION_INFO_SIZE_SMALL_LABEL, - base::Bind(&AppInfoSummaryPanel::OnAppSizeCalculated, AsWeakPtr())); + // In tests the app may be a dummy app without a path. In this case, avoid + // calculating the directory size as it would calculate the size of the + // current directory, which is both potentially slow and meaningless. + if (!app_->path().empty()) { + extensions::path_util::CalculateAndFormatExtensionDirectorySize( + app_->path(), IDS_APPLICATION_INFO_SIZE_SMALL_LABEL, + base::BindOnce(&AppInfoSummaryPanel::OnAppSizeCalculated, AsWeakPtr())); + } } void AppInfoSummaryPanel::OnAppSizeCalculated(const base::string16& size) {
diff --git a/chrome/browser/ui/views/apps/chrome_native_app_window_views_aura_ash.cc b/chrome/browser/ui/views/apps/chrome_native_app_window_views_aura_ash.cc index 95197ac..62b8ab5 100644 --- a/chrome/browser/ui/views/apps/chrome_native_app_window_views_aura_ash.cc +++ b/chrome/browser/ui/views/apps/chrome_native_app_window_views_aura_ash.cc
@@ -457,7 +457,7 @@ void ChromeNativeAppWindowViewsAuraAsh::OnPostWindowStateTypeChange( ash::wm::WindowState* window_state, - ash::mojom::WindowStateType old_type) { + ash::WindowStateType old_type) { DCHECK(!IsFrameless()); DCHECK_EQ(GetNativeWindow(), window_state->window()); if (window_state->IsFullscreen() != app_window()->IsFullscreen()) {
diff --git a/chrome/browser/ui/views/apps/chrome_native_app_window_views_aura_ash.h b/chrome/browser/ui/views/apps/chrome_native_app_window_views_aura_ash.h index dbf7ba0..d729967c 100644 --- a/chrome/browser/ui/views/apps/chrome_native_app_window_views_aura_ash.h +++ b/chrome/browser/ui/views/apps/chrome_native_app_window_views_aura_ash.h
@@ -118,9 +118,8 @@ void OnWidgetActivationChanged(views::Widget* widget, bool active) override; // ash::wm::WindowStateObserver - void OnPostWindowStateTypeChange( - ash::wm::WindowState* window_state, - ash::mojom::WindowStateType old_type) override; + void OnPostWindowStateTypeChange(ash::wm::WindowState* window_state, + ash::WindowStateType old_type) override; // aura::WindowObserver: void OnWindowPropertyChanged(aura::Window* window,
diff --git a/chrome/browser/ui/views/device_chooser_content_view.cc b/chrome/browser/ui/views/device_chooser_content_view.cc index 8f681ec5..1ee6af2 100644 --- a/chrome/browser/ui/views/device_chooser_content_view.cc +++ b/chrome/browser/ui/views/device_chooser_content_view.cc
@@ -355,11 +355,14 @@ ui::DialogButton button) const { return button == ui::DIALOG_BUTTON_OK ? chooser_controller_->GetOkButtonLabel() - : l10n_util::GetStringUTF16(IDS_DEVICE_CHOOSER_CANCEL_BUTTON_TEXT); + : chooser_controller_->GetCancelButtonLabel(); } bool DeviceChooserContentView::IsDialogButtonEnabled( ui::DialogButton button) const { + if (chooser_controller_->BothButtonsAlwaysEnabled()) + return true; + return button != ui::DIALOG_BUTTON_OK || !table_view_->selection_model().empty(); } @@ -382,7 +385,10 @@ void DeviceChooserContentView::UpdateTableView() { bool has_options = adapter_enabled_ && chooser_controller_->NumOptions() > 0; table_parent_->SetVisible(has_options); - table_view_->SetEnabled(has_options); + if (chooser_controller_->TableViewAlwaysDisabled()) + table_view_->SetEnabled(false); + else + table_view_->SetEnabled(has_options); no_options_help_->SetVisible(!has_options && adapter_enabled_); adapter_off_help_->SetVisible(!adapter_enabled_); }
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.cc b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.cc index 962e7936..ed3de7728 100644 --- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.cc +++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.cc
@@ -15,8 +15,8 @@ #include "ash/public/cpp/frame_utils.h" #include "ash/public/cpp/touch_uma.h" #include "ash/public/cpp/window_properties.h" +#include "ash/public/cpp/window_state_type.h" #include "ash/public/interfaces/constants.mojom.h" -#include "ash/public/interfaces/window_state_type.mojom.h" #include "ash/wm/window_util.h" #include "base/command_line.h" #include "base/metrics/user_metrics.h" @@ -86,18 +86,17 @@ // Returns true if |window| is currently snapped in split view mode. bool IsSnappedInSplitView(const aura::Window* window) { ash::SplitViewState state = ash::SplitViewNotifier::Get()->GetCurrentState(); - ash::mojom::WindowStateType type = - window->GetProperty(ash::kWindowStateTypeKey); + ash::WindowStateType type = window->GetProperty(ash::kWindowStateTypeKey); switch (state) { case ash::SplitViewState::kNoSnap: return false; case ash::SplitViewState::kLeftSnapped: - return type == ash::mojom::WindowStateType::LEFT_SNAPPED; + return type == ash::WindowStateType::kLeftSnapped; case ash::SplitViewState::kRightSnapped: - return type == ash::mojom::WindowStateType::RIGHT_SNAPPED; + return type == ash::WindowStateType::kRightSnapped; case ash::SplitViewState::kBothSnapped: - return type == ash::mojom::WindowStateType::LEFT_SNAPPED || - type == ash::mojom::WindowStateType::RIGHT_SNAPPED; + return type == ash::WindowStateType::kLeftSnapped || + type == ash::WindowStateType::kRightSnapped; } NOTREACHED();
diff --git a/chrome/browser/ui/views/frame/immersive_mode_controller_ash.cc b/chrome/browser/ui/views/frame/immersive_mode_controller_ash.cc index 6e668279..defdd55 100644 --- a/chrome/browser/ui/views/frame/immersive_mode_controller_ash.cc +++ b/chrome/browser/ui/views/frame/immersive_mode_controller_ash.cc
@@ -6,7 +6,6 @@ #include "ash/public/cpp/immersive/immersive_revealed_lock.h" #include "ash/public/cpp/window_properties.h" -#include "ash/public/interfaces/window_state_type.mojom.h" #include "base/macros.h" #include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/platform_util.h"
diff --git a/chrome/browser/ui/views/media_router/presentation_receiver_window_view.cc b/chrome/browser/ui/views/media_router/presentation_receiver_window_view.cc index 7722009d..3732ffd 100644 --- a/chrome/browser/ui/views/media_router/presentation_receiver_window_view.cc +++ b/chrome/browser/ui/views/media_router/presentation_receiver_window_view.cc
@@ -43,7 +43,6 @@ #if defined(OS_CHROMEOS) #include "ash/public/cpp/window_properties.h" -#include "ash/public/interfaces/window_state_type.mojom.h" #include "base/callback.h" #include "base/scoped_observer.h" #include "ui/aura/client/aura_constants.h"
diff --git a/chrome/browser/ui/views/media_router/presentation_receiver_window_view_browsertest.cc b/chrome/browser/ui/views/media_router/presentation_receiver_window_view_browsertest.cc index 35d934d..d637f4c 100644 --- a/chrome/browser/ui/views/media_router/presentation_receiver_window_view_browsertest.cc +++ b/chrome/browser/ui/views/media_router/presentation_receiver_window_view_browsertest.cc
@@ -27,7 +27,6 @@ #if defined(CHROMEOS) #include "ash/public/cpp/window_properties.h" -#include "ash/public/interfaces/window_state_type.mojom.h" #include "ui/aura/client/aura_constants.h" #include "ui/aura/window.h" #include "ui/gfx/native_widget_types.h"
diff --git a/chrome/browser/ui/views/payments/payment_method_view_controller.cc b/chrome/browser/ui/views/payments/payment_method_view_controller.cc index cccd43c..f806bf38 100644 --- a/chrome/browser/ui/views/payments/payment_method_view_controller.cc +++ b/chrome/browser/ui/views/payments/payment_method_view_controller.cc
@@ -82,8 +82,10 @@ BackNavigationType::kPaymentSheet, static_cast<int>(PaymentMethodViewControllerTags::MAX_TAG), /*on_edited=*/ - base::BindOnce(&PaymentRequestState::SetSelectedInstrument, - base::Unretained(state()), instrument_), + base::BindOnce( + &PaymentRequestState::SetSelectedInstrument, + base::Unretained(state()), instrument_, + PaymentRequestState::SectionSelectionStatus::kEditedSelected), /*on_added=*/ base::OnceCallback<void(const autofill::CreditCard&)>(), static_cast<AutofillPaymentInstrument*>(instrument_) @@ -145,7 +147,8 @@ void SelectedStateChanged() override { if (selected()) { - state()->SetSelectedInstrument(instrument_); + state()->SetSelectedInstrument( + instrument_, PaymentRequestState::SectionSelectionStatus::kSelected); dialog_->GoBack(); } }
diff --git a/chrome/browser/ui/views/payments/payment_request_dialog_view.cc b/chrome/browser/ui/views/payments/payment_request_dialog_view.cc index d88d6b8..1994fc9 100644 --- a/chrome/browser/ui/views/payments/payment_request_dialog_view.cc +++ b/chrome/browser/ui/views/payments/payment_request_dialog_view.cc
@@ -207,8 +207,10 @@ ShowShippingAddressEditor( BackNavigationType::kOneStep, /*on_edited=*/ - base::BindOnce(&PaymentRequestState::SetSelectedShippingProfile, - base::Unretained(request_->state()), profile), + base::BindOnce( + &PaymentRequestState::SetSelectedShippingProfile, + base::Unretained(request_->state()), profile, + PaymentRequestState::SectionSelectionStatus::kEditedSelected), /*on_added=*/ base::OnceCallback<void(const autofill::AutofillProfile&)>(), profile); } @@ -219,8 +221,10 @@ ShowContactInfoEditor( BackNavigationType::kOneStep, /*on_edited=*/ - base::BindOnce(&PaymentRequestState::SetSelectedContactProfile, - base::Unretained(request_->state()), profile), + base::BindOnce( + &PaymentRequestState::SetSelectedContactProfile, + base::Unretained(request_->state()), profile, + PaymentRequestState::SectionSelectionStatus::kEditedSelected), /*on_added=*/ base::OnceCallback<void(const autofill::AutofillProfile&)>(), profile); }
diff --git a/chrome/browser/ui/views/payments/profile_list_view_controller.cc b/chrome/browser/ui/views/payments/profile_list_view_controller.cc index 43cff32..fa56e7d 100644 --- a/chrome/browser/ui/views/payments/profile_list_view_controller.cc +++ b/chrome/browser/ui/views/payments/profile_list_view_controller.cc
@@ -140,15 +140,18 @@ // of the profile list. When the spec comes back updated (in OnSpecUpdated), // the decision will be made to either stay on this screen or go back to the // payment sheet. - state()->SetSelectedShippingProfile(profile); + state()->SetSelectedShippingProfile( + profile, PaymentRequestState::SectionSelectionStatus::kSelected); } void ShowEditor(autofill::AutofillProfile* profile) override { dialog()->ShowShippingAddressEditor( BackNavigationType::kPaymentSheet, /*on_edited=*/ - base::BindOnce(&PaymentRequestState::SetSelectedShippingProfile, - base::Unretained(state()), profile), + base::BindOnce( + &PaymentRequestState::SetSelectedShippingProfile, + base::Unretained(state()), profile, + PaymentRequestState::SectionSelectionStatus::kEditedSelected), /*on_added=*/ base::BindOnce(&PaymentRequestState::AddAutofillShippingProfile, base::Unretained(state()), /*selected=*/true), @@ -251,7 +254,8 @@ } void SelectProfile(autofill::AutofillProfile* profile) override { - state()->SetSelectedContactProfile(profile); + state()->SetSelectedContactProfile( + profile, PaymentRequestState::SectionSelectionStatus::kSelected); dialog()->GoBack(); } @@ -259,8 +263,10 @@ dialog()->ShowContactInfoEditor( BackNavigationType::kPaymentSheet, /*on_edited=*/ - base::BindOnce(&PaymentRequestState::SetSelectedContactProfile, - base::Unretained(state()), profile), + base::BindOnce( + &PaymentRequestState::SetSelectedContactProfile, + base::Unretained(state()), profile, + PaymentRequestState::SectionSelectionStatus::kEditedSelected), /*on_added=*/ base::BindOnce(&PaymentRequestState::AddAutofillContactProfile, base::Unretained(state()), /*selected=*/true),
diff --git a/chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc b/chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc index 6dbebe9..69daf1e5 100644 --- a/chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc +++ b/chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc
@@ -392,8 +392,12 @@ source_browser_view->TabDraggingStatusChanged(/*is_dragging=*/false); } -std::vector<int> BrowserTabStripController::ListTabsInGroup( - const TabGroupData* group) const { +const TabGroupData* BrowserTabStripController::GetDataForGroup( + int group) const { + return model_->GetDataForGroup(group); +} + +std::vector<int> BrowserTabStripController::ListTabsInGroup(int group) const { return model_->ListTabsInGroup(group); } @@ -487,9 +491,8 @@ } case TabStripModelChange::kGroupChanged: { auto* group_change = change.GetGroupChange(); - tabstrip_->ChangeTabGroup(group_change->index, - group_change->old_group_data, - group_change->new_group_data); + tabstrip_->ChangeTabGroup(group_change->index, group_change->old_group, + group_change->new_group); break; } case TabStripModelChange::kSelectionOnly:
diff --git a/chrome/browser/ui/views/tabs/browser_tab_strip_controller.h b/chrome/browser/ui/views/tabs/browser_tab_strip_controller.h index 44c8f72..f47aadea 100644 --- a/chrome/browser/ui/views/tabs/browser_tab_strip_controller.h +++ b/chrome/browser/ui/views/tabs/browser_tab_strip_controller.h
@@ -72,7 +72,8 @@ void StackedLayoutMaybeChanged() override; void OnStartedDraggingTabs() override; void OnStoppedDraggingTabs() override; - std::vector<int> ListTabsInGroup(const TabGroupData* group) const override; + const TabGroupData* GetDataForGroup(int group_id) const override; + std::vector<int> ListTabsInGroup(int group_id) const override; bool IsFrameCondensed() const override; bool HasVisibleBackgroundTabShapes() const override; bool EverHasVisibleBackgroundTabShapes() const override;
diff --git a/chrome/browser/ui/views/tabs/fake_base_tab_strip_controller.cc b/chrome/browser/ui/views/tabs/fake_base_tab_strip_controller.cc index 3ed389d2..6365385 100644 --- a/chrome/browser/ui/views/tabs/fake_base_tab_strip_controller.cc +++ b/chrome/browser/ui/views/tabs/fake_base_tab_strip_controller.cc
@@ -47,25 +47,36 @@ tab_strip_->RemoveTabAt(nullptr, index, was_active); } -TabGroupData* FakeBaseTabStripController::CreateTabGroup() { - groups_.push_back(std::make_unique<TabGroupData>()); - return groups_.back().get(); +int FakeBaseTabStripController::CreateTabGroup() { + ++num_groups_; + return num_groups_ - 1; } -void FakeBaseTabStripController::MoveTabIntoGroup(int index, - TabGroupData* new_group) { - TabGroupData* old_group = tab_to_group_[index]; - tab_to_group_[index] = new_group; +void FakeBaseTabStripController::MoveTabIntoGroup( + int index, + base::Optional<int> new_group) { + auto tab_group_pair = tab_to_group_.find(index); + base::Optional<int> old_group = + tab_group_pair != tab_to_group_.end() + ? base::make_optional(tab_group_pair->second) + : base::nullopt; + if (new_group.has_value()) + tab_to_group_[index] = new_group.value(); + else + tab_to_group_.erase(index); tab_strip_->ChangeTabGroup(index, old_group, new_group); } -std::vector<int> FakeBaseTabStripController::ListTabsInGroup( - const TabGroupData* group) const { - DCHECK(group); +const TabGroupData* FakeBaseTabStripController::GetDataForGroup( + int group) const { + return &fake_group_data_; +} + +std::vector<int> FakeBaseTabStripController::ListTabsInGroup(int group) const { std::vector<int> result; - for (auto const& tab_header_pair : tab_to_group_) { - if (tab_header_pair.second == group) - result.push_back(tab_header_pair.first); + for (auto const& tab_group_pair : tab_to_group_) { + if (tab_group_pair.second == group) + result.push_back(tab_group_pair.first); } return result; }
diff --git a/chrome/browser/ui/views/tabs/fake_base_tab_strip_controller.h b/chrome/browser/ui/views/tabs/fake_base_tab_strip_controller.h index ef1ac2d..0b08f7a 100644 --- a/chrome/browser/ui/views/tabs/fake_base_tab_strip_controller.h +++ b/chrome/browser/ui/views/tabs/fake_base_tab_strip_controller.h
@@ -11,6 +11,8 @@ #include "base/compiler_specific.h" #include "base/macros.h" +#include "base/optional.h" +#include "chrome/browser/ui/tabs/tab_group_data.h" #include "chrome/browser/ui/views/tabs/tab_strip_controller.h" #include "ui/base/models/list_selection_model.h" @@ -23,8 +25,8 @@ void AddPinnedTab(int index, bool is_active); void RemoveTab(int index); - TabGroupData* CreateTabGroup(); - void MoveTabIntoGroup(int index, TabGroupData* new_group); + int CreateTabGroup(); + void MoveTabIntoGroup(int index, base::Optional<int> new_group); ui::ListSelectionModel* selection_model() { return &selection_model_; } @@ -54,7 +56,8 @@ void StackedLayoutMaybeChanged() override; void OnStartedDraggingTabs() override; void OnStoppedDraggingTabs() override; - std::vector<int> ListTabsInGroup(const TabGroupData* group) const override; + const TabGroupData* GetDataForGroup(int group_id) const override; + std::vector<int> ListTabsInGroup(int group_id) const override; bool IsFrameCondensed() const override; bool HasVisibleBackgroundTabShapes() const override; bool EverHasVisibleBackgroundTabShapes() const override; @@ -78,8 +81,9 @@ int num_tabs_ = 0; int active_index_ = -1; - std::vector<std::unique_ptr<TabGroupData>> groups_; - std::map<int, TabGroupData*> tab_to_group_; + TabGroupData fake_group_data_; + int num_groups_ = 0; + std::map<int, int> tab_to_group_; ui::ListSelectionModel selection_model_;
diff --git a/chrome/browser/ui/views/tabs/tab_drag_controller.cc b/chrome/browser/ui/views/tabs/tab_drag_controller.cc index 6a14057..3963d95 100644 --- a/chrome/browser/ui/views/tabs/tab_drag_controller.cc +++ b/chrome/browser/ui/views/tabs/tab_drag_controller.cc
@@ -49,7 +49,7 @@ #if defined(OS_CHROMEOS) #include "ash/public/cpp/ash_features.h" #include "ash/public/cpp/window_properties.h" // nogncheck -#include "ash/public/interfaces/window_state_type.mojom.h" // nogncheck +#include "ash/public/cpp/window_state_type.h" // nogncheck #include "chrome/browser/ui/ash/tablet_mode_client.h" #include "ui/base/ui_base_features.h" #include "ui/wm/core/coordinate_conversion.h" @@ -102,11 +102,11 @@ // Returns true if |context| browser window is snapped. bool IsSnapped(const TabDragContext* context) { DCHECK(context); - ash::mojom::WindowStateType type = + ash::WindowStateType type = GetWindowForTabDraggingProperties(context)->GetProperty( ash::kWindowStateTypeKey); - return type == ash::mojom::WindowStateType::LEFT_SNAPPED || - type == ash::mojom::WindowStateType::RIGHT_SNAPPED; + return type == ash::WindowStateType::kLeftSnapped || + type == ash::WindowStateType::kRightSnapped; } // In Chrome OS tablet mode, when dragging a tab/tabs around, the desired
diff --git a/chrome/browser/ui/views/tabs/tab_strip.cc b/chrome/browser/ui/views/tabs/tab_strip.cc index 613fb55..531ae1e 100644 --- a/chrome/browser/ui/views/tabs/tab_strip.cc +++ b/chrome/browser/ui/views/tabs/tab_strip.cc
@@ -1184,17 +1184,19 @@ } void TabStrip::ChangeTabGroup(int model_index, - const TabGroupData* old_group_data, - const TabGroupData* new_group_data) { - if (new_group_data && !group_headers_[new_group_data]) { - auto header = std::make_unique<TabGroupHeader>(new_group_data->title()); - group_headers_[new_group_data] = header.get(); - AddChildView(header.release()); + base::Optional<int> old_group, + base::Optional<int> new_group) { + if (new_group.has_value() && !group_headers_[new_group.value()]) { + const TabGroupData* group_data = + controller_->GetDataForGroup(new_group.value()); + auto header = std::make_unique<TabGroupHeader>(group_data->title()); + header->set_owned_by_client(); + AddChildView(header.get()); + group_headers_[new_group.value()] = std::move(header); } - if (old_group_data != nullptr && - controller_->ListTabsInGroup(old_group_data).size() == 0) { - delete group_headers_[old_group_data]; - group_headers_.erase(old_group_data); + if (old_group.has_value() && + controller_->ListTabsInGroup(old_group.value()).size() == 0) { + group_headers_.erase(old_group.value()); } }
diff --git a/chrome/browser/ui/views/tabs/tab_strip.h b/chrome/browser/ui/views/tabs/tab_strip.h index 3cfd34f..9b27520 100644 --- a/chrome/browser/ui/views/tabs/tab_strip.h +++ b/chrome/browser/ui/views/tabs/tab_strip.h
@@ -40,7 +40,6 @@ class NewTabButton; class StackedTabStripLayout; class Tab; -class TabGroupData; class TabGroupHeader; class TabHoverCardBubbleView; class TabStripController; @@ -156,11 +155,11 @@ // Sets the tab data at the specified model index. void SetTabData(int model_index, TabRendererData data); - // Changes the group affiliation of the tab at |model_index| from - // |old_group_data| to |new_group_data|. + // Changes the group of the tab at |model_index| from |old_group| to + // |new_group|. void ChangeTabGroup(int model_index, - const TabGroupData* old_group_data, - const TabGroupData* new_group_data); + base::Optional<int> old_group, + base::Optional<int> new_group); // Returns true if the tab is not partly or fully clipped (due to overflow), // and the tab couldn't become partly clipped due to changing the selected tab @@ -549,7 +548,8 @@ views::ViewModelT<Tab> tabs_; TabsClosingMap tabs_closing_map_; - std::map<const TabGroupData*, TabGroupHeader*> group_headers_; + // Map associating each group to its TabGroupHeader instance. + std::map<int, std::unique_ptr<TabGroupHeader>> group_headers_; // The view tracker is used to keep track of if the hover card has been // destroyed by its widget.
diff --git a/chrome/browser/ui/views/tabs/tab_strip_controller.h b/chrome/browser/ui/views/tabs/tab_strip_controller.h index c7535014..6b4a45b 100644 --- a/chrome/browser/ui/views/tabs/tab_strip_controller.h +++ b/chrome/browser/ui/views/tabs/tab_strip_controller.h
@@ -110,8 +110,11 @@ // from this tabstrip but the user is still dragging the tabs. virtual void OnStoppedDraggingTabs() = 0; - // Returns the list of tabs affiliated with |group|. - virtual std::vector<int> ListTabsInGroup(const TabGroupData* group) const = 0; + // Returns the TabGroupData instance for the given |group|. + virtual const TabGroupData* GetDataForGroup(int group) const = 0; + + // Returns the list of tabs in the given |group|. + virtual std::vector<int> ListTabsInGroup(int group) const = 0; // Determines whether the top frame is condensed vertically, as when the // window is maximized. If true, the top frame is just the height of a tab,
diff --git a/chrome/browser/ui/views/tabs/tab_strip_unittest.cc b/chrome/browser/ui/views/tabs/tab_strip_unittest.cc index 80c08ff6..4a5aeefe 100644 --- a/chrome/browser/ui/views/tabs/tab_strip_unittest.cc +++ b/chrome/browser/ui/views/tabs/tab_strip_unittest.cc
@@ -10,7 +10,6 @@ #include "base/macros.h" #include "base/timer/timer.h" #include "chrome/browser/ui/layout_constants.h" -#include "chrome/browser/ui/tabs/tab_group_data.h" #include "chrome/browser/ui/views/tabs/fake_base_tab_strip_controller.h" #include "chrome/browser/ui/views/tabs/new_tab_button.h" #include "chrome/browser/ui/views/tabs/tab.h" @@ -208,7 +207,7 @@ std::vector<TabGroupHeader*> ListGroupHeaders() const { std::vector<TabGroupHeader*> result; for (auto const& header_pair : tab_strip_->group_headers_) - result.push_back(header_pair.second); + result.push_back(header_pair.second.get()); return result; } @@ -970,7 +969,7 @@ TEST_P(TabStripTest, CreateTabGroup) { tab_strip_->AddTabAt(0, TabRendererData(), false); - TabGroupData* group = controller_->CreateTabGroup(); + base::Optional<int> group = controller_->CreateTabGroup(); controller_->MoveTabIntoGroup(0, group); EXPECT_EQ(1u, ListGroupHeaders().size()); } @@ -978,13 +977,13 @@ TEST_P(TabStripTest, DeleteTabGroupHeaderWhenEmpty) { tab_strip_->AddTabAt(0, TabRendererData(), false); tab_strip_->AddTabAt(1, TabRendererData(), false); - TabGroupData* group = controller_->CreateTabGroup(); + base::Optional<int> group = controller_->CreateTabGroup(); controller_->MoveTabIntoGroup(0, group); controller_->MoveTabIntoGroup(1, group); - controller_->MoveTabIntoGroup(0, nullptr); + controller_->MoveTabIntoGroup(0, base::nullopt); EXPECT_EQ(1u, ListGroupHeaders().size()); - controller_->MoveTabIntoGroup(1, nullptr); + controller_->MoveTabIntoGroup(1, base::nullopt); EXPECT_EQ(0u, ListGroupHeaders().size()); }
diff --git a/chrome/browser/ui/webui/chromeos/assistant_optin/assistant_optin_ui.cc b/chrome/browser/ui/webui/chromeos/assistant_optin/assistant_optin_ui.cc index f42815b..c975428a 100644 --- a/chrome/browser/ui/webui/chromeos/assistant_optin/assistant_optin_ui.cc +++ b/chrome/browser/ui/webui/chromeos/assistant_optin/assistant_optin_ui.cc
@@ -8,6 +8,7 @@ #include <string> #include <utility> +#include "ash/public/cpp/window_properties.h" #include "base/bind.h" #include "base/macros.h" #include "chrome/browser/profiles/profile.h" @@ -26,6 +27,7 @@ #include "content/public/browser/web_ui_data_source.h" #include "content/public/common/content_features.h" #include "net/base/url_util.h" +#include "ui/aura/window.h" #include "ui/views/widget/widget.h" namespace chromeos { @@ -121,6 +123,7 @@ g_dialog = new AssistantOptInDialog(type, std::move(callback)); g_dialog->ShowSystemDialog(); + g_dialog->dialog_window()->SetProperty(ash::kHideInOverviewKey, true); } AssistantOptInDialog::AssistantOptInDialog(
diff --git a/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc b/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc index af629ff..c0f2e46 100644 --- a/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc +++ b/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc
@@ -165,6 +165,13 @@ #endif } +void AddSupervisionOnboardingScreenResources(content::WebUIDataSource* source) { + source->AddResourcePath("supervision_onboarding_controller.mojom.html", + IDR_SUPERVISION_ONBOARDING_CONTROLLER_MOJOM_HTML); + source->AddResourcePath("onboarding_controller.mojom-lite.js", + IDR_SUPERVISION_ONBOARDING_CONTROLLER_MOJOM_LITE_JS); +} + // Adds resources for ARC-dependent screens (PlayStore ToS, Assistant, etc...) void AddArcScreensResources(content::WebUIDataSource* source) { // Required for postprocessing of Goolge PlayStore Terms and Overlay help. @@ -248,6 +255,7 @@ AddFingerprintResources(source); AddSyncConsentResources(source); AddArcScreensResources(source); + AddSupervisionOnboardingScreenResources(source); source->AddResourcePath(kKeyboardUtilsJSPath, IDR_KEYBOARD_UTILS_JS); source->OverrideContentSecurityPolicyChildSrc(base::StringPrintf(
diff --git a/chrome/browser/ui/webui/chromeos/login/supervision_onboarding_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/supervision_onboarding_screen_handler.cc index 13a8c15..7eac378 100644 --- a/chrome/browser/ui/webui/chromeos/login/supervision_onboarding_screen_handler.cc +++ b/chrome/browser/ui/webui/chromeos/login/supervision_onboarding_screen_handler.cc
@@ -10,6 +10,7 @@ #include "chrome/browser/chromeos/login/screens/supervision_onboarding_screen.h" #include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/ui/ash/login_screen_client.h" +#include "chrome/browser/ui/webui/chromeos/login/oobe_ui.h" #include "components/login/localized_values_builder.h" namespace chromeos { @@ -20,6 +21,8 @@ JSCallsContainer* js_calls_container) : BaseScreenHandler(kScreenId, js_calls_container) { set_user_acted_method_path("login.SupervisionOnboardingScreen.userActed"); + supervision_onboarding_controller_ = + std::make_unique<supervision::OnboardingControllerImpl>(); } SupervisionOnboardingScreenHandler::~SupervisionOnboardingScreenHandler() { @@ -45,10 +48,21 @@ void SupervisionOnboardingScreenHandler::Show() { ShowScreen(kScreenId); + + GetOobeUI()->AddHandlerToRegistry(base::BindRepeating( + &SupervisionOnboardingScreenHandler::BindSupervisionOnboardingController, + base::Unretained(this))); + + CallJS("login.SupervisionOnboardingScreen.setupMojo"); } void SupervisionOnboardingScreenHandler::Hide() {} void SupervisionOnboardingScreenHandler::Initialize() {} +void SupervisionOnboardingScreenHandler::BindSupervisionOnboardingController( + supervision::mojom::OnboardingControllerRequest request) { + supervision_onboarding_controller_->BindRequest(std::move(request)); +} + } // namespace chromeos
diff --git a/chrome/browser/ui/webui/chromeos/login/supervision_onboarding_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/supervision_onboarding_screen_handler.h index 1464d653..ba8035c 100644 --- a/chrome/browser/ui/webui/chromeos/login/supervision_onboarding_screen_handler.h +++ b/chrome/browser/ui/webui/chromeos/login/supervision_onboarding_screen_handler.h
@@ -11,6 +11,8 @@ #include "base/macros.h" #include "base/time/time.h" #include "base/timer/timer.h" +#include "chrome/browser/chromeos/supervision/mojom/onboarding_controller.mojom.h" +#include "chrome/browser/chromeos/supervision/onboarding_controller_impl.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/webui/chromeos/login/base_screen_handler.h" #include "components/prefs/pref_change_registrar.h" @@ -63,8 +65,15 @@ // BaseScreenHandler: void Initialize() override; + // Callback used to bing the mojo onboarding controller. + void BindSupervisionOnboardingController( + supervision::mojom::OnboardingControllerRequest request); + SupervisionOnboardingScreen* screen_ = nullptr; + std::unique_ptr<supervision::OnboardingControllerImpl> + supervision_onboarding_controller_; + DISALLOW_COPY_AND_ASSIGN(SupervisionOnboardingScreenHandler); };
diff --git a/chrome/browser/ui/webui/downloads/downloads_ui.cc b/chrome/browser/ui/webui/downloads/downloads_ui.cc index 0b8d0d0..d0518761 100644 --- a/chrome/browser/ui/webui/downloads/downloads_ui.cc +++ b/chrome/browser/ui/webui/downloads/downloads_ui.cc
@@ -25,8 +25,9 @@ #include "chrome/common/chrome_switches.h" #include "chrome/common/pref_names.h" #include "chrome/common/url_constants.h" -#include "chrome/grit/browser_resources.h" #include "chrome/grit/chromium_strings.h" +#include "chrome/grit/downloads_resources.h" +#include "chrome/grit/downloads_resources_map.h" #include "chrome/grit/generated_resources.h" #include "chrome/grit/theme_resources.h" #include "components/prefs/pref_service.h" @@ -142,25 +143,10 @@ source->AddResourcePath("crisper.js", IDR_DOWNLOADS_CRISPER_JS); source->SetDefaultResource(IDR_DOWNLOADS_VULCANIZED_HTML); #else - source->AddResourcePath("browser_proxy.html", - IDR_DOWNLOADS_BROWSER_PROXY_HTML); - source->AddResourcePath("browser_proxy.js", IDR_DOWNLOADS_BROWSER_PROXY_JS); - source->AddResourcePath("constants.html", IDR_DOWNLOADS_CONSTANTS_HTML); - source->AddResourcePath("constants.js", IDR_DOWNLOADS_CONSTANTS_JS); - source->AddResourcePath("downloads.js", IDR_DOWNLOADS_DOWNLOADS_JS); - source->AddResourcePath("i18n_setup.html", IDR_DOWNLOADS_I18N_SETUP_HTML); - source->AddResourcePath("icon_loader.html", IDR_DOWNLOADS_ICON_LOADER_HTML); - source->AddResourcePath("icon_loader.js", IDR_DOWNLOADS_ICON_LOADER_JS); - source->AddResourcePath("icons.html", IDR_DOWNLOADS_ICONS_HTML); - source->AddResourcePath("item.html", IDR_DOWNLOADS_ITEM_HTML); - source->AddResourcePath("item.js", IDR_DOWNLOADS_ITEM_JS); - source->AddResourcePath("manager.html", IDR_DOWNLOADS_MANAGER_HTML); - source->AddResourcePath("manager.js", IDR_DOWNLOADS_MANAGER_JS); - source->AddResourcePath("search_service.html", - IDR_DOWNLOADS_SEARCH_SERVICE_HTML); - source->AddResourcePath("search_service.js", IDR_DOWNLOADS_SEARCH_SERVICE_JS); - source->AddResourcePath("toolbar.html", IDR_DOWNLOADS_TOOLBAR_HTML); - source->AddResourcePath("toolbar.js", IDR_DOWNLOADS_TOOLBAR_JS); + for (size_t i = 0; i < kDownloadsResourcesSize; ++i) { + source->AddResourcePath(kDownloadsResources[i].name, + kDownloadsResources[i].value); + } source->SetDefaultResource(IDR_DOWNLOADS_DOWNLOADS_HTML); #endif
diff --git a/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc b/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc index 8b18a03..cf35ede1 100644 --- a/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc +++ b/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc
@@ -2200,6 +2200,7 @@ void AddSearchStrings(content::WebUIDataSource* html_source, Profile* profile) { #if defined(OS_CHROMEOS) + // NOTE: This will be false when the flag is disabled. const bool is_assistant_allowed = assistant::IsAssistantAllowedForProfile(profile) == ash::mojom::AssistantAllowedState::ALLOWED; @@ -2219,7 +2220,6 @@ IDS_SETTINGS_SEARCH_GOOGLE_ASSISTANT_ENABLED}, {"searchGoogleAssistantDisabled", IDS_SETTINGS_SEARCH_GOOGLE_ASSISTANT_DISABLED}, - {"assistantTurnOn", IDS_SETTINGS_SEARCH_GOOGLE_ASSISTANT_TURN_ON}, #endif }; AddLocalizedStringsBulk(html_source, localized_strings, @@ -2229,9 +2229,7 @@ base::ASCIIToUTF16(chrome::kOmniboxLearnMoreURL)); html_source->AddString("searchExplanation", search_explanation_text); #if defined(OS_CHROMEOS) - html_source->AddBoolean("enableVoiceInteraction", is_assistant_allowed); - html_source->AddBoolean("enableAssistant", - chromeos::switches::IsAssistantEnabled()); + html_source->AddBoolean("isAssistantAllowed", is_assistant_allowed); #endif }
diff --git a/chrome/browser/ui/webui/settings/site_settings_handler.cc b/chrome/browser/ui/webui/settings/site_settings_handler.cc index bc14b95..b2bca94 100644 --- a/chrome/browser/ui/webui/settings/site_settings_handler.cc +++ b/chrome/browser/ui/webui/settings/site_settings_handler.cc
@@ -210,8 +210,8 @@ // Update the storage data in |origin_size_map|. void UpdateDataForOrigin(const GURL& url, - const int size, - std::map<std::string, int>* origin_size_map) { + const int64_t size, + std::map<std::string, int64_t>* origin_size_map) { if (size > 0) (*origin_size_map)[url.spec()] += size; } @@ -296,7 +296,7 @@ void UpdateDataFromCookiesTree( std::map<std::string, std::set<std::string>>* all_sites_map, - std::map<std::string, int>* origin_size_map, + std::map<std::string, int64_t>* origin_size_map, const GURL& origin, int64_t size) { UpdateDataForOrigin(origin, size, origin_size_map); @@ -759,7 +759,7 @@ } base::Value SiteSettingsHandler::PopulateCookiesAndUsageData(Profile* profile) { - std::map<std::string, int> origin_size_map; + std::map<std::string, int64_t> origin_size_map; std::map<std::string, int> origin_cookie_map; base::Value list_value(base::Value::Type::LIST); @@ -784,7 +784,7 @@ const std::string& origin = origin_info.FindKey("origin")->GetString(); const auto& size_info_it = origin_size_map.find(origin); if (size_info_it != origin_size_map.end()) - origin_info.SetKey("usage", base::Value(size_info_it->second)); + origin_info.SetKey("usage", base::Value(double(size_info_it->second))); const auto& origin_cookie_num_it = origin_cookie_map.find(GURL(origin).host()); if (origin_cookie_num_it != origin_cookie_map.end()) { @@ -812,10 +812,10 @@ CHECK_EQ(2U, args->GetSize()); const base::Value* callback_id; CHECK(args->Get(0, &callback_id)); - int num_bytes; - CHECK(args->GetInteger(1, &num_bytes)); + double num_bytes; + CHECK(args->GetDouble(1, &num_bytes)); - const base::string16 string = ui::FormatBytes(num_bytes); + const base::string16 string = ui::FormatBytes(int64_t(num_bytes)); ResolveJavascriptCallback(*callback_id, base::Value(string)); } @@ -1410,7 +1410,7 @@ void SiteSettingsHandler::GetOriginStorage( std::map<std::string, std::set<std::string>>* all_sites_map, - std::map<std::string, int>* origin_size_map) { + std::map<std::string, int64_t>* origin_size_map) { CHECK(cookies_tree_model_.get()); const CookieTreeNode* root = cookies_tree_model_->GetRoot();
diff --git a/chrome/browser/ui/webui/settings/site_settings_handler.h b/chrome/browser/ui/webui/settings/site_settings_handler.h index 3bcce17e..862145c4 100644 --- a/chrome/browser/ui/webui/settings/site_settings_handler.h +++ b/chrome/browser/ui/webui/settings/site_settings_handler.h
@@ -121,6 +121,7 @@ FRIEND_TEST_ALL_PREFIXES(SiteSettingsHandlerTest, ZoomLevels); FRIEND_TEST_ALL_PREFIXES(SiteSettingsHandlerTest, HandleClearEtldPlus1DataAndCookies); + FRIEND_TEST_ALL_PREFIXES(SiteSettingsHandlerTest, HandleGetFormattedBytes); // Creates the CookiesTreeModel if necessary. void EnsureCookiesTreeModelCreated(); @@ -134,7 +135,7 @@ // stores the information in the |all_sites_map| and |origin_size_map|. void GetOriginStorage( std::map<std::string, std::set<std::string>>* all_sites_map, - std::map<std::string, int>* origin_size_map); + std::map<std::string, int64_t>* origin_size_map); // Calculates the number of cookies for each etld+1 and each origin, and // stores the information in the |all_sites_map| and |origin_cookie_map|.
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 667a45fb..169e56c 100644 --- a/chrome/browser/ui/webui/settings/site_settings_handler_unittest.cc +++ b/chrome/browser/ui/webui/settings/site_settings_handler_unittest.cc
@@ -11,6 +11,7 @@ #include "base/bind_helpers.h" #include "base/json/json_reader.h" +#include "base/strings/utf_string_conversions.h" #include "base/test/metrics/histogram_tester.h" #include "base/test/simple_test_clock.h" #include "base/values.h" @@ -50,6 +51,7 @@ #include "extensions/common/extension_builder.h" #include "ppapi/buildflags/buildflags.h" #include "testing/gtest/include/gtest/gtest.h" +#include "ui/base/text/bytes_formatting.h" #if defined(OS_CHROMEOS) #include "chrome/browser/chromeos/login/users/mock_user_manager.h" @@ -424,7 +426,7 @@ url::Origin::Create(GURL("https://www.example.com/")), 2); mock_browsing_data_local_storage_helper->AddLocalStorageForOrigin( - url::Origin::Create(GURL("https://www.google.com/")), 5); + url::Origin::Create(GURL("https://www.google.com/")), 50000000000); mock_browsing_data_local_storage_helper->Notify(); mock_browsing_data_cookie_helper->AddCookieSamples( @@ -761,7 +763,7 @@ EXPECT_EQ("https://www.google.com/", origin_info->FindKey("origin")->GetString()); EXPECT_EQ(0, origin_info->FindKey("engagement")->GetDouble()); - EXPECT_EQ(5, origin_info->FindKey("usage")->GetDouble()); + EXPECT_EQ(50000000000, origin_info->FindKey("usage")->GetDouble()); EXPECT_EQ(0, origin_info->FindKey("numCookies")->GetDouble()); ASSERT_TRUE(storage_and_cookie_list->GetDictionary(2, &site_group)); @@ -1890,4 +1892,20 @@ storage_and_cookie_list = GetOnStorageFetchedSentListValue(); EXPECT_EQ(0U, storage_and_cookie_list->GetSize()); } + +TEST_F(SiteSettingsHandlerTest, HandleGetFormattedBytes) { + const double size = 120000000000; + base::ListValue get_args; + get_args.AppendString(kCallbackId); + get_args.AppendDouble(size); + handler()->HandleGetFormattedBytes(&get_args); + + // Validate that this method can handle large data. + const content::TestWebUI::CallData& data = *web_ui()->call_data().back(); + EXPECT_EQ("cr.webUIResponse", data.function_name()); + EXPECT_EQ(kCallbackId, data.arg1()->GetString()); + ASSERT_TRUE(data.arg2()->GetBool()); + EXPECT_EQ(base::UTF16ToUTF8(ui::FormatBytes(int64_t(size))), + data.arg3()->GetString()); +} } // namespace settings
diff --git a/chrome/browser/vr/webxr_vr_input_browser_test.cc b/chrome/browser/vr/webxr_vr_input_browser_test.cc index ea8f48cd6..583ccd7 100644 --- a/chrome/browser/vr/webxr_vr_input_browser_test.cc +++ b/chrome/browser/vr/webxr_vr_input_browser_test.cc
@@ -192,7 +192,7 @@ this->LoadUrlAndAwaitInitialization( this->GetFileUrlForHtmlTestFile("test_webxr_gamepad_support")); this->EnterSessionWithUserGestureOrFail(); - this->ExecuteStepAndWait("validateInsufficientGamepadData()"); + this->ExecuteStepAndWait("validateInputSourceHasNoGamepad()"); this->RunJavaScriptOrFail("done()"); this->EndTest(); }
diff --git a/chrome/browser/web_applications/components/test_pending_app_manager.cc b/chrome/browser/web_applications/components/test_pending_app_manager.cc index 6de7e989..8dc651d 100644 --- a/chrome/browser/web_applications/components/test_pending_app_manager.cc +++ b/chrome/browser/web_applications/components/test_pending_app_manager.cc
@@ -28,6 +28,11 @@ installed_apps_[url] = install_source; } +void TestPendingAppManager::SetInstallResultCode( + InstallResultCode result_code) { + install_result_code_ = result_code; +} + void TestPendingAppManager::Install(InstallOptions install_options, OnceInstallCallback callback) { // TODO(nigeltao): Add error simulation when error codes are added to the API. @@ -39,8 +44,8 @@ deduped_install_count_++; } install_requests_.push_back(install_options); - std::move(callback).Run(install_options.url, - InstallResultCode::kSuccess); + + std::move(callback).Run(install_options.url, install_result_code_); }); base::SequencedTaskRunnerHandle::Get()->PostTask( FROM_HERE, base::BindOnce(do_install, std::move(callback)));
diff --git a/chrome/browser/web_applications/components/test_pending_app_manager.h b/chrome/browser/web_applications/components/test_pending_app_manager.h index 04e59da..f9dc6b1 100644 --- a/chrome/browser/web_applications/components/test_pending_app_manager.h +++ b/chrome/browser/web_applications/components/test_pending_app_manager.h
@@ -46,6 +46,8 @@ void SimulatePreviouslyInstalledApp(const GURL& url, InstallSource install_source); + void SetInstallResultCode(InstallResultCode result_code); + // PendingAppManager: void Install(InstallOptions install_options, OnceInstallCallback callback) override; @@ -69,6 +71,7 @@ int deduped_uninstall_count_; std::map<GURL, InstallSource> installed_apps_; + InstallResultCode install_result_code_ = InstallResultCode::kSuccess; DISALLOW_COPY_AND_ASSIGN(TestPendingAppManager); };
diff --git a/chrome/chrome_paks.gni b/chrome/chrome_paks.gni index aba6aad8..8ff44c72 100644 --- a/chrome/chrome_paks.gni +++ b/chrome/chrome_paks.gni
@@ -138,6 +138,7 @@ # New paks should be added here by default. sources += [ "$root_gen_dir/chrome/component_extension_resources.pak", + "$root_gen_dir/chrome/downloads_resources.pak", "$root_gen_dir/chrome/local_ntp_resources.pak", "$root_gen_dir/chrome/settings_resources.pak", "$root_gen_dir/content/browser/devtools/devtools_resources.pak", @@ -145,6 +146,7 @@ ] deps += [ "//chrome/browser/resources:component_extension_resources", + "//chrome/browser/resources:downloads_resources", "//chrome/browser/resources:local_ntp_resources", "//chrome/browser/resources:settings_resources", "//content/browser/devtools:devtools_resources",
diff --git a/chrome/common/chrome_features.cc b/chrome/common/chrome_features.cc index 6ba7733..5f19a82 100644 --- a/chrome/common/chrome_features.cc +++ b/chrome/common/chrome_features.cc
@@ -707,6 +707,10 @@ const base::Feature kArcCupsApi{"ArcCupsApi", base::FEATURE_DISABLED_BY_DEFAULT}; +// Enables or disables serving printing requests from VMs on ChromeOS. +const base::Feature kCrosVmCupsProxy{"CrosVmCupsProxy", + base::FEATURE_DISABLED_BY_DEFAULT}; + // Enables or disables pin quick unlock. // TODO(https://crbug.com/935613): Remove this & the backing code. const base::Feature kQuickUnlockPin{"QuickUnlockPin",
diff --git a/chrome/common/chrome_features.h b/chrome/common/chrome_features.h index 1352752..dbc1c93 100644 --- a/chrome/common/chrome_features.h +++ b/chrome/common/chrome_features.h
@@ -444,6 +444,8 @@ #if defined(OS_CHROMEOS) COMPONENT_EXPORT(CHROME_FEATURES) extern const base::Feature kArcCupsApi; +COMPONENT_EXPORT(CHROME_FEATURES) extern const base::Feature kCrosVmCupsProxy; + COMPONENT_EXPORT(CHROME_FEATURES) extern const base::Feature kQuickUnlockPin; COMPONENT_EXPORT(CHROME_FEATURES)
diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc index 1314a3a9..42aa855a 100644 --- a/chrome/common/pref_names.cc +++ b/chrome/common/pref_names.cc
@@ -2333,7 +2333,7 @@ const char kRegisteredSupervisedUserWhitelists[] = "supervised_users.whitelists"; -#if !defined(OS_ANDROID) && !defined(OS_CHROMEOS) +#if !defined(OS_ANDROID) // Boolean that indicates whether Chrome enterprise cloud reporting is enabled // or not. const char kCloudReportingEnabled[] =
diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h index 70feb8a..da8e742 100644 --- a/chrome/common/pref_names.h +++ b/chrome/common/pref_names.h
@@ -808,7 +808,7 @@ extern const char kRegisteredSupervisedUserWhitelists[]; -#if !defined(OS_ANDROID) && !defined(OS_CHROMEOS) +#if !defined(OS_ANDROID) extern const char kCloudReportingEnabled[]; #endif
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index 565b002..dc6685e 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -616,6 +616,7 @@ "../browser/banners/app_banner_manager_desktop_browsertest.cc", "../browser/banners/test_app_banner_manager_desktop.cc", "../browser/banners/test_app_banner_manager_desktop.h", + "../browser/battery/battery_metrics_browsertest.cc", "../browser/bitmap_fetcher/bitmap_fetcher_browsertest.cc", "../browser/browser_encoding_browsertest.cc", "../browser/browsing_data/browsing_data_cache_storage_helper_browsertest.cc", @@ -3324,6 +3325,7 @@ "../browser/diagnostics/diagnostics_model_unittest.cc", "../browser/download/download_commands_unittest.cc", "../browser/download/download_shelf_unittest.cc", + "../browser/enterprise_reporting/request_timer_unittest.cc", "../browser/first_run/first_run_unittest.cc", "../browser/font_family_cache_unittest.cc", @@ -3651,6 +3653,7 @@ "../browser/ui/autofill/payments/local_card_migration_bubble_controller_impl_unittest.cc", "../browser/ui/autofill/payments/save_card_bubble_controller_impl_unittest.cc", "../browser/ui/bluetooth/bluetooth_chooser_controller_unittest.cc", + "../browser/ui/bluetooth/bluetooth_scanning_prompt_controller_unittest.cc", "../browser/ui/media_router/cast_modes_with_media_sources_unittest.cc", "../browser/ui/media_router/media_cast_mode_unittest.cc", "../browser/ui/media_router/media_router_file_dialog_unittest.cc", @@ -5295,6 +5298,7 @@ "../browser/ui/ash/overview_window_drag_interactive_uitest.cc", "../browser/ui/ash/screen_rotation_interactive_uitest.cc", "../browser/ui/ash/split_view_interactive_uitest.cc", + "../browser/ui/ash/tablet_mode_transition_interactive_uitest.cc", "base/perf/drag_event_generator.cc", "base/perf/drag_event_generator.h", ]
diff --git a/chrome/test/data/extensions/platform_apps/music_manager_private/device_id_value_returned/chrometest.js b/chrome/test/data/extensions/platform_apps/music_manager_private/device_id_value_returned/chrometest.js index 93be223..693da0a 100644 --- a/chrome/test/data/extensions/platform_apps/music_manager_private/device_id_value_returned/chrometest.js +++ b/chrome/test/data/extensions/platform_apps/music_manager_private/device_id_value_returned/chrometest.js
@@ -2,26 +2,20 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -function runTests() { - chrome.test.runTests([ - function test() { - chrome.musicManagerPrivate.getDeviceId(function(id) { - console.log('Device ID=' + id); - if (id) { - // This block is not entered in VMs (e.g. the bots) which return - // dummy MACs. - chrome.test.assertEq('string', typeof id); - chrome.test.assertTrue(id.length >= 8); - } - chrome.test.succeed(); - }); - } - ]); -} - -window.onload = function() { - chrome.test.getConfig(function(config) { - console.log('customArg=' + config.customArg); - runTests(); - }); -} +chrome.test.runTests([ + function getDeviceIdTest() { + chrome.musicManagerPrivate.getDeviceId(function(id) { + if (id !== undefined) { + chrome.test.assertNoLastError(); + chrome.test.assertEq('string', typeof id); + chrome.test.assertTrue(id.length >= 8); + } else { + // Bots may not support device ID. In this case, we still check that the + // error message is what we expect. + chrome.test.assertLastError( + 'Device ID API is not supported on this platform.'); + } + chrome.test.succeed(); + }); + } +]);
diff --git a/chrome/test/data/local_ntp/local_ntp_browsertest.html b/chrome/test/data/local_ntp/local_ntp_browsertest.html index 94d85f24..2ac65be 100644 --- a/chrome/test/data/local_ntp/local_ntp_browsertest.html +++ b/chrome/test/data/local_ntp/local_ntp_browsertest.html
@@ -156,7 +156,14 @@ </dialog> <dialog id="customization-menu" class="customize-dialog"> - <div id="menu-title">$i18n{customizeMenuTitle}</div> + <div id="menu-header"> + <div id="menu-back-wrapper"> + <div id="menu-back"></div> + </div> + <div id="menu-title-wrapper"> + <div id="menu-title">$i18n{customizeMenuTitle}</div> + </div> + </div> <div id="menu-nav-panel"> <div id="backgrounds-button" class="menu-option" tabindex="0"> <div class="menu-option-icon-wrapper"> @@ -184,6 +191,7 @@ <div class="bg-sel-tile-title">Default</div> </div> </div> + <div id="backgrounds-image-menu" class="menu-panel"></div> </div> <div id="menu-footer"> <button id="menu-cancel" class="bg-sel-footer-button paper secondary
diff --git a/chrome/test/data/local_ntp/most_visited_browsertest.js b/chrome/test/data/local_ntp/most_visited_browsertest.js index d713e31..a615d3e 100644 --- a/chrome/test/data/local_ntp/most_visited_browsertest.js +++ b/chrome/test/data/local_ntp/most_visited_browsertest.js
@@ -322,6 +322,44 @@ /** + * Tests if the grid rebalances correctly when the window is resized. + */ +test.mostVisited.testGridResizeRebalance = function() { + const params = { // Used to override the default grid parameters. + tileHeight: 10, + tileWidth: 10, + tilesAlwaysVisible: 6, + maxTilesPerRow: 5, + maxTiles: 10 + }; + + window.innerWidth = 50; + // Create a grid a full row. + let container = document.createElement('div'); + let expectedLayout = [ + 'translate(0px, 0px)', 'translate(10px, 0px)', 'translate(20px, 0px)', + 'translate(30px, 0px)', 'translate(40px, 0px)' + ]; + test.mostVisited.initGridWithAdd(container, params, 5); + assertEquals('50px', container.style.width); + test.mostVisited.assertLayout(container, expectedLayout); + test.mostVisited.assertVisibility(container, 0); + + // Shrink the window so that only 4 tiles can fit in a row. + window.innerWidth = 40; + // The tiles should rebalance. + let expectedLayoutRebalance = [ + 'translate(0px, 0px)', 'translate(10px, 0px)', 'translate(20px, 0px)', + 'translate(5px, 10px)', 'translate(15px, 10px)' + ]; + test.mostVisited.grid.onResize(); + assertEquals('30px', container.style.width); + test.mostVisited.assertLayout(container, expectedLayoutRebalance); + test.mostVisited.assertVisibility(container, 0); +}; + + +/** * Tests if all tiles except the add button can be reordered. */ test.mostVisited.testReorderStart = function() { @@ -779,6 +817,72 @@ }; +/** + * Tests if the tiles are translated properly when reordering with an add + * shortcut button present. + */ +test.mostVisited.testReorderInsertWithAddButton = function() { + // Set the window so that there's 10px padding around the grid. + window.innerHeight = 40; + window.innerWidth = 50; + const params = { // Used to override the default grid parameters. + tileHeight: 10, + tileWidth: 10, + maxTilesPerRow: 3, + maxTiles: 6, + enableReorder: true + }; + + // Create a grid with uneven rows. + let container = document.createElement('div'); + $(test.mostVisited.MOST_VISITED).appendChild(container); + test.mostVisited.initGridWithAdd(container, params, 5); + + const dragStart = new Event('dragstart'); + const mouseOver = new Event('mouseover'); + const mouseUp = new Event('mouseup'); + + const tiles = document.getElementsByClassName( + test.mostVisited.CLASSES.GRID_TILE_CONTAINER); + + // Start the reorder flow on the second tile. + + let tile = tiles[1]; + tile.firstChild.dispatchEvent(dragStart); + + // Mouseover the first tile. This should shift tiles as if the held tile was + // inserted before. + let expectedLayout = [ + 'translate(10px, 0px)', '', 'translate(0px, 0px)', 'translate(0px, 0px)', '' + ]; + tiles[0].dispatchEvent(mouseOver); + + test.mostVisited.assertReorderInsert(container, expectedLayout, 3); + + // Mouseover the last tile (the add shortcut button). This should not shift + // the tiles. + tiles[4].dispatchEvent(mouseOver); + + test.mostVisited.assertReorderInsert(container, expectedLayout, 0); + + // Mouseover the second to last tile. This should shift tiles as if the held + // tile was inserted after. + expectedLayout = [ + 'translate(0px, 0px)', '', 'translate(-10px, 0px)', + 'translate(15px, -10px)', '' + ]; + tiles[3].dispatchEvent(mouseOver); + + test.mostVisited.assertReorderInsert(container, expectedLayout, 3); + + // Stop the reorder flow. + document.dispatchEvent(mouseUp); + // Check that the correct values were sent to the EmbeddedSearchAPI. + assertEquals(1, test.mostVisited.reorderRid); + assertEquals(3, test.mostVisited.reorderNewIndex); +}; + + // ***************************** HELPER FUNCTIONS ***************************** // These are used by the tests above.
diff --git a/chrome/test/data/webui/settings/google_assistant_page_test.js b/chrome/test/data/webui/settings/google_assistant_page_test.js index 91a54a6e..a10fe15 100644 --- a/chrome/test/data/webui/settings/google_assistant_page_test.js +++ b/chrome/test/data/webui/settings/google_assistant_page_test.js
@@ -40,7 +40,7 @@ suiteSetup(function() { loadTimeData.overrideValues({ - enableAssistant: true, + isAssistantAllowed: true, voiceMatchEnabled: true, hotwordDspAvailable: true, }); @@ -326,7 +326,7 @@ suiteSetup(function() { loadTimeData.overrideValues({ - enableAssistant: true, + isAssistantAllowed: true, voiceMatchEnabled: true, hotwordDspAvailable: false, });
diff --git a/chrome/test/data/webui/settings/site_entry_tests.js b/chrome/test/data/webui/settings/site_entry_tests.js index 80c033d4..4b30b29d 100644 --- a/chrome/test/data/webui/settings/site_entry_tests.js +++ b/chrome/test/data/webui/settings/site_entry_tests.js
@@ -241,6 +241,29 @@ }); }); + test( + 'large number data usage shown correctly for grouped entries', + function() { + // Clone this object to avoid propagating changes made in this test. + const testSiteGroup = + JSON.parse(JSON.stringify(TEST_MULTIPLE_SITE_GROUP)); + const numBytes1 = 2000000000; + const numBytes2 = 10000000000; + const numBytes3 = 7856; + testSiteGroup.origins[0].usage = numBytes1; + testSiteGroup.origins[1].usage = numBytes2; + testSiteGroup.origins[2].usage = numBytes3; + testElement.siteGroup = testSiteGroup; + Polymer.dom.flush(); + return browserProxy.whenCalled('getFormattedBytes').then((args) => { + const sumBytes = numBytes1 + numBytes2 + numBytes3; + assertEquals( + `${sumBytes} B`, + testElement.root.querySelector('#displayName .data-unit') + .textContent.trim()); + }); + }); + test('favicon with www.etld+1 chosen for site group', function() { // Clone this object to avoid propagating changes made in this test. const testSiteGroup = JSON.parse(JSON.stringify(TEST_MULTIPLE_SITE_GROUP));
diff --git a/chrome/test/data/xr/e2e_test_files/html/test_webxr_gamepad_support.html b/chrome/test/data/xr/e2e_test_files/html/test_webxr_gamepad_support.html index 2109812..10bf14b 100644 --- a/chrome/test/data/xr/e2e_test_files/html/test_webxr_gamepad_support.html +++ b/chrome/test/data/xr/e2e_test_files/html/test_webxr_gamepad_support.html
@@ -28,9 +28,16 @@ "Number of returned gamepads matches expectation"); } - let validateFirstGamepadStateCallback = null; - function validateInsufficientGamepadData() { + function validateInputSourceHasNoGamepad() { + assert_equals(onImmersiveXRFrameCallback, null); onImmersiveXRFrameCallback = function(session) { + // Clear the callback first in case any of the following asserts fail. + // If any asserts trigger, we don't run any code that follows, so if + // we did this as the last step of the callback and any of the asserts + // failed, we would be continually called, which just makes it harder + // to debug. + onImmersiveXRFrameCallback = null; + // We don't expect to have attached any non-vr gamepads, and vr // gamepads shouldn't show up in navigator.getGamepads() assertNumNavigatorGamepadsMatchesExpectation(0); @@ -38,14 +45,21 @@ assert_equals(input_sources.length, 1, "There should only be one input source"); assert_equals(input_sources[0].gamepad, null, "There should not be enough data to make a gamepad"); - onImmersiveXRFrameCallback = null; finishJavaScriptStep(); } } - function validateGamepad() { + function validateFirstGamepad(validationFunction) { + assert_equals(onImmersiveXRFrameCallback, null); onImmersiveXRFrameCallback = function(session) { + // Clear the callback first in case any of the following asserts fail. + // If any asserts trigger, we don't run any code that follows, so if + // we did this as the last step of the callback and any of the asserts + // failed, we would be continually called, which just makes it harder + // to debug. + onImmersiveXRFrameCallback = null; + // We don't expect to have attached any non-vr gamepads, and vr // gamepads shouldn't show up in navigator.getGamepads() assertNumNavigatorGamepadsMatchesExpectation(0); @@ -54,53 +68,46 @@ assert_not_equals(input_sources[0].gamepad, null, "There should be enough data to make a gamepad"); assert_equals(input_sources[0].gamepad.mapping, "xr-standard"); - if (validateFirstGamepadStateCallback) { - validateFirstGamepadStateCallback(input_sources[0].gamepad); + if (validationFunction) { + validationFunction(input_sources[0].gamepad); } - onImmersiveXRFrameCallback = null; finishJavaScriptStep(); } } function validateButtonNotPressed(button_index) { - validateFirstGamepadStateCallback = function(gamepad) { + let validationFunction = function(gamepad) { assert_less_than(button_index, gamepad.buttons.length, "Verify that we have at least as many buttons as requested"); assert_false(gamepad.buttons[button_index].pressed); - - validateFirstGamepadStateCallback = null; } - validateGamepad(); + validateFirstGamepad(validationFunction); } function validateButtonPressed(button_index) { - validateFirstGamepadStateCallback = function(gamepad) { + let validationFunction = function(gamepad) { assert_less_than(button_index, gamepad.buttons.length, "Verify that we have at least as many buttons as requested"); assert_true(gamepad.buttons[button_index].pressed); - - validateFirstGamepadStateCallback = null; } - validateGamepad(); + validateFirstGamepad(validationFunction); } function validateButtonTouched(button_index) { - validateFirstGamepadStateCallback = function(gamepad) { + let validationFunction = function(gamepad) { assert_less_than(button_index, gamepad.buttons.length, "Verify that we have at least as many buttons as requested"); assert_true(gamepad.buttons[button_index].touched); - - validateFirstGamepadStateCallback = null; } - validateGamepad(); + validateFirstGamepad(validationFunction); } function validateAxesValues(axes_pair_index, x_axis_value, y_axis_value) { - validateFirstGamepadStateCallback = function(gamepad) { + let validationFunction = function(gamepad) { let epsilon = 0.001; let x_index = (2 * axes_pair_index); let y_index = (2 * axes_pair_index) + 1; @@ -111,11 +118,9 @@ "X approximately equals expected"); assert_true(Math.abs(gamepad.axes[y_index] - y_axis_value) < epsilon, "Y approximately equals expected"); - - validateFirstGamepadStateCallback = null; } - validateGamepad(); + validateFirstGamepad(validationFunction); } </script> </body>
diff --git a/chromecast/browser/cast_media_blocker.cc b/chromecast/browser/cast_media_blocker.cc index 29277ce..96d8f92 100644 --- a/chromecast/browser/cast_media_blocker.cc +++ b/chromecast/browser/cast_media_blocker.cc
@@ -7,17 +7,24 @@ #include <utility> #include "base/threading/thread_checker.h" +#include "chromecast/common/mojom/media_playback_options.mojom.h" #include "content/public/browser/media_session.h" #include "content/public/browser/web_contents.h" +#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h" namespace chromecast { -namespace shell { + +CastMediaBlocker::CastMediaBlocker(content::WebContents* web_contents) + : CastMediaBlocker(content::MediaSession::Get(web_contents)) { + content::WebContentsObserver::Observe(web_contents); +} CastMediaBlocker::CastMediaBlocker(content::MediaSession* media_session) : blocked_(false), paused_by_user_(true), suspended_(true), controllable_(false), + background_video_playback_enabled_(false), media_session_(media_session) { media_session::mojom::MediaSessionObserverPtr observer; observer_binding_.Bind(mojo::MakeRequest(&observer)); @@ -52,6 +59,14 @@ } } +void CastMediaBlocker::EnableBackgroundVideoPlayback(bool enabled) { + if (!web_contents()) + return; + + background_video_playback_enabled_ = enabled; + UpdateBackgroundVideoPlaybackState(); +} + void CastMediaBlocker::MediaSessionInfoChanged( media_session::mojom::MediaSessionInfoPtr session_info) { bool is_suspended = session_info->playback_state == @@ -115,5 +130,54 @@ media_session_->Resume(content::MediaSession::SuspendType::kSystem); } -} // namespace shell +void CastMediaBlocker::RenderFrameCreated( + content::RenderFrameHost* render_frame_host) { + UpdateRenderFrameMediaBlockedState(render_frame_host); + UpdateRenderFrameBackgroundVideoPlaybackState(render_frame_host); +} + +void CastMediaBlocker::RenderViewReady() { + UpdateMediaBlockedState(); +} + +void CastMediaBlocker::UpdateMediaBlockedState() { + if (!web_contents()) + return; + + const std::vector<content::RenderFrameHost*> frames = + web_contents()->GetAllFrames(); + for (content::RenderFrameHost* frame : frames) { + UpdateRenderFrameMediaBlockedState(frame); + } +} + +void CastMediaBlocker::UpdateBackgroundVideoPlaybackState() { + if (!web_contents()) + return; + const std::vector<content::RenderFrameHost*> frames = + web_contents()->GetAllFrames(); + for (content::RenderFrameHost* frame : frames) { + UpdateRenderFrameBackgroundVideoPlaybackState(frame); + } +} + +void CastMediaBlocker::UpdateRenderFrameMediaBlockedState( + content::RenderFrameHost* render_frame_host) { + DCHECK(render_frame_host); + chromecast::shell::mojom::MediaPlaybackOptionsAssociatedPtr + media_playback_options; + render_frame_host->GetRemoteAssociatedInterfaces()->GetInterface( + &media_playback_options); + media_playback_options->SetMediaLoadingBlocked(media_loading_blocked()); +} + +void CastMediaBlocker::UpdateRenderFrameBackgroundVideoPlaybackState( + content::RenderFrameHost* frame) { + chromecast::shell::mojom::MediaPlaybackOptionsAssociatedPtr + media_playback_options; + frame->GetRemoteAssociatedInterfaces()->GetInterface(&media_playback_options); + media_playback_options->SetBackgroundVideoPlaybackEnabled( + background_video_playback_enabled_); +} + } // namespace chromecast
diff --git a/chromecast/browser/cast_media_blocker.h b/chromecast/browser/cast_media_blocker.h index 784878b..a9687233 100644 --- a/chromecast/browser/cast_media_blocker.h +++ b/chromecast/browser/cast_media_blocker.h
@@ -17,18 +17,24 @@ } // namespace content namespace chromecast { -namespace shell { // This class implements a blocking mode for web applications and is used in // Chromecast internal code. Media is unblocked by default. -class CastMediaBlocker : public media_session::mojom::MediaSessionObserver { +class CastMediaBlocker : public content::WebContentsObserver, + public media_session::mojom::MediaSessionObserver { public: + // Observes WebContents and MediaSession. + explicit CastMediaBlocker(content::WebContents* web_contents); + + // Observes only the MediaSession. explicit CastMediaBlocker(content::MediaSession* media_session); + ~CastMediaBlocker() override; // Sets if the web contents is allowed to play media or not. If media is // unblocked, previously suspended elements should begin playing again. void BlockMediaLoading(bool blocked); + void EnableBackgroundVideoPlayback(bool enabled); // media_session::mojom::MediaSessionObserver implementation: void MediaSessionInfoChanged( @@ -43,18 +49,27 @@ std::vector<media_session::MediaImage>>& images) override {} - protected: + private: bool media_loading_blocked() const { return blocked_; } - // Blocks or unblocks the render process from loading new media - // according to |media_loading_blocked_|. - virtual void UpdateMediaBlockedState() {} + // content::WebContentsObserver implementation: + void RenderFrameCreated(content::RenderFrameHost* render_frame_host) override; + void RenderViewReady() override; - private: // Suspends or resumes the media session for the web contents. void Suspend(); void Resume(); + // Blocks or unblocks the render process from loading new media + // according to |blocked_|. + void UpdateMediaBlockedState(); + void UpdateRenderFrameMediaBlockedState( + content::RenderFrameHost* render_frame_host); + + void UpdateBackgroundVideoPlaybackState(); + void UpdateRenderFrameBackgroundVideoPlaybackState( + content::RenderFrameHost* frame); + // Whether or not media should be blocked. This value cache's the last call to // BlockMediaLoading. Is false by default. bool blocked_; @@ -67,6 +82,11 @@ bool suspended_; bool controllable_; + // Setting for whether or not the WebContents should suspend video when the + // content is put into the background. For most content, this setting should + // be disabled. + bool background_video_playback_enabled_; + content::MediaSession* const media_session_; mojo::Binding<media_session::mojom::MediaSessionObserver> observer_binding_{ @@ -75,7 +95,6 @@ DISALLOW_COPY_AND_ASSIGN(CastMediaBlocker); }; -} // namespace shell } // namespace chromecast #endif // CHROMECAST_BROWSER_CAST_MEDIA_BLOCKER_H_
diff --git a/chromecast/browser/cast_media_blocker_browsertest.cc b/chromecast/browser/cast_media_blocker_browsertest.cc index f37cc6b..a2b476d 100644 --- a/chromecast/browser/cast_media_blocker_browsertest.cc +++ b/chromecast/browser/cast_media_blocker_browsertest.cc
@@ -45,8 +45,7 @@ web_contents_ = NavigateToURL(gurl); WaitForLoadStop(web_contents_); - blocker_ = std::make_unique<CastMediaBlocker>( - content::MediaSession::Get(web_contents_)); + blocker_ = std::make_unique<CastMediaBlocker>(web_contents_); } void BlockAndTestPlayerState(const std::string& media_type, bool blocked) {
diff --git a/chromecast/browser/cast_web_contents.h b/chromecast/browser/cast_web_contents.h index 4c64868..a51b49f 100644 --- a/chromecast/browser/cast_web_contents.h +++ b/chromecast/browser/cast_web_contents.h
@@ -154,14 +154,23 @@ // Initialization parameters for CastWebContents. struct InitParams { - Delegate* delegate; - // Whether the underlying WebContents is exposed to the remote debugger. - bool enabled_for_dev; + // Delegate for CastWebContents. This can be null for an inner WebContents. + Delegate* delegate = nullptr; + // Enable development mode for this CastWebCastWebContents. Whitelists + // certain functionality for the WebContents, like remote debugging and + // debugging interfaces. + bool enabled_for_dev = false; // Chooses a media renderer for the WebContents. - bool use_cma_renderer; + bool use_cma_renderer = false; // Whether the WebContents is a root native window, or if it is embedded in // another WebContents (see Delegate::InnerContentsCreated()). bool is_root_window = false; + // Whether inner WebContents events should be handled. If this is set to + // true, then inner WebContents will automatically have a CastWebContents + // created and notify the delegate. + bool handle_inner_contents = false; + // Construct internal media blocker and enable BlockMediaLoading(). + bool use_media_blocker = false; }; // Page state for the main frame. @@ -220,6 +229,18 @@ // page. virtual void Stop(int error_code) = 0; + // =========================================================================== + // Media Management + // =========================================================================== + + // Block/unblock media from loading in all RenderFrames for the WebContents. + virtual void BlockMediaLoading(bool blocked) = 0; + virtual void EnableBackgroundVideoPlayback(bool enabled) = 0; + + // =========================================================================== + // Utility Methods + // =========================================================================== + // Used to add or remove |observer| to the ObserverList in the implementation. // These functions should only be invoked by CastWebContents::Observer in a // valid sequence, enforced via SequenceChecker.
diff --git a/chromecast/browser/cast_web_contents_impl.cc b/chromecast/browser/cast_web_contents_impl.cc index f50ac23..92b156d 100644 --- a/chromecast/browser/cast_web_contents_impl.cc +++ b/chromecast/browser/cast_web_contents_impl.cc
@@ -62,8 +62,12 @@ last_state_(PageState::IDLE), enabled_for_dev_(init_params.enabled_for_dev), use_cma_renderer_(init_params.use_cma_renderer), + handle_inner_contents_(init_params.handle_inner_contents), remote_debugging_server_( shell::CastBrowserProcess::GetInstance()->remote_debugging_server()), + media_blocker_(init_params.use_media_blocker + ? std::make_unique<CastMediaBlocker>(web_contents_) + : nullptr), tab_id_(init_params.is_root_window ? 0 : next_tab_id++), main_frame_loaded_(false), closing_(false), @@ -175,6 +179,16 @@ NotifyObservers(); } +void CastWebContentsImpl::BlockMediaLoading(bool blocked) { + if (media_blocker_) + media_blocker_->BlockMediaLoading(blocked); +} + +void CastWebContentsImpl::EnableBackgroundVideoPlayback(bool enabled) { + if (media_blocker_) + media_blocker_->EnableBackgroundVideoPlayback(enabled); +} + void CastWebContentsImpl::SetDelegate(CastWebContents::Delegate* delegate) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); delegate_ = delegate; @@ -511,16 +525,21 @@ void CastWebContentsImpl::InnerWebContentsCreated( content::WebContents* inner_web_contents) { + if (!handle_inner_contents_ || !delegate_) + return; auto result = inner_contents_.insert(std::make_unique<CastWebContentsImpl>( - inner_web_contents, InitParams{nullptr, enabled_for_dev_})); - if (delegate_) - delegate_->InnerContentsCreated(result.first->get(), this); + inner_web_contents, + InitParams{nullptr, enabled_for_dev_, false /* use_cma_renderer */, + false /* is_root_window */, false /* handle_inner_contents */, + false /* use_media_blocker */})); + delegate_->InnerContentsCreated(result.first->get(), this); } void CastWebContentsImpl::WebContentsDestroyed() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); closing_ = false; DisableDebugging(); + media_blocker_.reset(); content::WebContentsObserver::Observe(nullptr); web_contents_ = nullptr; Stop(net::OK);
diff --git a/chromecast/browser/cast_web_contents_impl.h b/chromecast/browser/cast_web_contents_impl.h index 07f8008..3553575 100644 --- a/chromecast/browser/cast_web_contents_impl.h +++ b/chromecast/browser/cast_web_contents_impl.h
@@ -17,6 +17,7 @@ #include "base/memory/weak_ptr.h" #include "base/sequence_checker.h" #include "base/time/time.h" +#include "chromecast/browser/cast_media_blocker.h" #include "chromecast/browser/cast_web_contents.h" #include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents_observer.h" @@ -52,6 +53,8 @@ const InterfaceSet& interface_set, service_manager::InterfaceProvider* interface_provider) override; service_manager::BinderRegistry* binder_registry() override; + void BlockMediaLoading(bool blocked) override; + void EnableBackgroundVideoPlayback(bool enabled) override; // Observer interface: void AddObserver(Observer* observer) override; @@ -99,7 +102,9 @@ PageState last_state_; const bool enabled_for_dev_; bool use_cma_renderer_; + const bool handle_inner_contents_; shell::RemoteDebuggingServer* const remote_debugging_server_; + std::unique_ptr<CastMediaBlocker> media_blocker_; base::flat_set<std::unique_ptr<CastWebContents>> inner_contents_; std::vector<RendererFeature> renderer_features_;
diff --git a/chromecast/browser/cast_web_view.h b/chromecast/browser/cast_web_view.h index ee36352a..14949aa 100644 --- a/chromecast/browser/cast_web_view.h +++ b/chromecast/browser/cast_web_view.h
@@ -68,6 +68,11 @@ // The delegate for the CastWebView. Must be non-null. Delegate* delegate = nullptr; + // Parameters for initializing CastWebContents. These will be passed as-is + // to a CastWebContents instance, which should be used by all CastWebView + // implementations. + CastWebContents::InitParams web_contents_params; + // Parameters for creating the content window for this CastWebView. shell::CastContentWindow::CreateParams window_params; @@ -80,14 +85,6 @@ // Whether this CastWebView is granted media access. bool allow_media_access = false; - // Whether this CastWebView will use CMA for media playback. - bool use_cma_renderer = true; - - // Enable development mode for this CastWebView. Whitelists certain - // functionality for the WebContents, like remote debugging and debugging - // interfaces. - bool enabled_for_dev = false; - // Enable/Force 720p resolution for this CastWebView instance. bool force_720p_resolution = false;
diff --git a/chromecast/browser/cast_web_view_default.cc b/chromecast/browser/cast_web_view_default.cc index c00971f..2d45095 100644 --- a/chromecast/browser/cast_web_view_default.cc +++ b/chromecast/browser/cast_web_view_default.cc
@@ -64,9 +64,7 @@ transparent_(params.transparent), allow_media_access_(params.allow_media_access), web_contents_(CreateWebContents(browser_context_, site_instance_)), - cast_web_contents_( - web_contents_.get(), - {delegate_, params.enabled_for_dev, params.use_cma_renderer}), + cast_web_contents_(web_contents_.get(), params.web_contents_params), window_(shell::CastContentWindow::Create(params.window_params)), resize_window_when_navigation_starts_(true) { DCHECK(delegate_);
diff --git a/chromecast/browser/service/cast_service_simple.cc b/chromecast/browser/service/cast_service_simple.cc index ea6b25e..6c486bc 100644 --- a/chromecast/browser/service/cast_service_simple.cc +++ b/chromecast/browser/service/cast_service_simple.cc
@@ -70,7 +70,8 @@ CastWebView::CreateParams params; params.delegate = this; - params.enabled_for_dev = true; + params.web_contents_params.delegate = this; + params.web_contents_params.enabled_for_dev = true; params.window_params.delegate = this; cast_web_view_ = web_contents_manager_->CreateWebView(params, nullptr, /* site_instance */
diff --git a/chromecast/browser/test/cast_browser_test.cc b/chromecast/browser/test/cast_browser_test.cc index 9c7184e..8c0c128 100644 --- a/chromecast/browser/test/cast_browser_test.cc +++ b/chromecast/browser/test/cast_browser_test.cc
@@ -59,7 +59,9 @@ content::WebContents* CastBrowserTest::CreateWebView() { CastWebView::CreateParams params; params.delegate = this; - params.enabled_for_dev = true; + params.web_contents_params.delegate = this; + params.web_contents_params.use_cma_renderer = true; + params.web_contents_params.enabled_for_dev = true; params.window_params.delegate = this; cast_web_view_ = web_contents_manager_->CreateWebView(params, nullptr, /* site_instance */
diff --git a/chromecast/media/audio/cast_audio_output_stream.cc b/chromecast/media/audio/cast_audio_output_stream.cc index e984788..6e3fd2bb 100644 --- a/chromecast/media/audio/cast_audio_output_stream.cc +++ b/chromecast/media/audio/cast_audio_output_stream.cc
@@ -131,7 +131,6 @@ std::unique_ptr<TaskRunnerImpl> cma_backend_task_runner_; std::unique_ptr<CmaBackend> cma_backend_; std::unique_ptr<::media::AudioBus> audio_bus_; - scoped_refptr<media::DecoderBufferBase> decoder_buffer_; base::OneShotTimer push_timer_; bool push_in_progress_; bool encountered_error_; @@ -225,9 +224,6 @@ } audio_bus_ = ::media::AudioBus::Create(audio_params_); - decoder_buffer_ = - base::MakeRefCounted<DecoderBufferAdapter>(new ::media::DecoderBuffer( - audio_params_.GetBytesPerBuffer(::media::kSampleFormatS16))); timestamp_helper_.SetBaseTimestamp(base::TimeDelta()); } @@ -330,15 +326,15 @@ DVLOG(3) << "frames_filled=" << frame_count << " with latency=" << delay; DCHECK_EQ(frame_count, audio_bus_->frames()); - DCHECK_EQ(static_cast<int>(decoder_buffer_->data_size()), - audio_params_.GetBytesPerBuffer(::media::kSampleFormatS16)); + auto decoder_buffer = + base::MakeRefCounted<DecoderBufferAdapter>(new ::media::DecoderBuffer( + audio_params_.GetBytesPerBuffer(::media::kSampleFormatS16))); audio_bus_->ToInterleaved<::media::SignedInt16SampleTypeTraits>( - frame_count, - reinterpret_cast<int16_t*>(decoder_buffer_->writable_data())); - decoder_buffer_->set_timestamp(timestamp_helper_.GetTimestamp()); + frame_count, reinterpret_cast<int16_t*>(decoder_buffer->writable_data())); + decoder_buffer->set_timestamp(timestamp_helper_.GetTimestamp()); timestamp_helper_.AddFrames(frame_count); - BufferStatus status = audio_decoder_->PushBuffer(decoder_buffer_.get()); + BufferStatus status = audio_decoder_->PushBuffer(std::move(decoder_buffer)); if (status != CmaBackend::BufferStatus::kBufferPending) OnPushBufferComplete(status); }
diff --git a/chromecast/media/cma/backend/cma_backend.h b/chromecast/media/cma/backend/cma_backend.h index 28de8a9a..8c8e4c1 100644 --- a/chromecast/media/cma/backend/cma_backend.h +++ b/chromecast/media/cma/backend/cma_backend.h
@@ -33,6 +33,9 @@ // MediaPipelineBackend::Decoder. // See chromecast/public/media/media_pipeline_backend.h for documentation. virtual void SetDelegate(Delegate* delegate) = 0; + + // Pushes buffer to decoder. A new |buffer| should be used for each call + // and should not be mutated by the caller. virtual BufferStatus PushBuffer( scoped_refptr<DecoderBufferBase> buffer) = 0;
diff --git a/chromeos/components/tether/network_host_scan_cache_unittest.cc b/chromeos/components/tether/network_host_scan_cache_unittest.cc index de58d5fc..fb275f5 100644 --- a/chromeos/components/tether/network_host_scan_cache_unittest.cc +++ b/chromeos/components/tether/network_host_scan_cache_unittest.cc
@@ -105,7 +105,7 @@ tether_network_guid); ASSERT_TRUE(tether_network_state); EXPECT_EQ(entry.device_name, tether_network_state->name()); - EXPECT_EQ(entry.carrier, tether_network_state->carrier()); + EXPECT_EQ(entry.carrier, tether_network_state->tether_carrier()); EXPECT_EQ(entry.battery_percentage, tether_network_state->battery_percentage()); EXPECT_EQ(entry.signal_strength, tether_network_state->signal_strength());
diff --git a/chromeos/components/tether/network_list_sorter.cc b/chromeos/components/tether/network_list_sorter.cc index 5c8cdb1e..8e12e14e 100644 --- a/chromeos/components/tether/network_list_sorter.cc +++ b/chromeos/components/tether/network_list_sorter.cc
@@ -50,8 +50,8 @@ return first->name() < second->name(); // Priority 7: Alphabetize by cellular carrier name. - if (first->carrier() != second->carrier()) - return first->carrier() < second->carrier(); + if (first->tether_carrier() != second->tether_carrier()) + return first->tether_carrier() < second->tether_carrier(); // Priority 8: Alphabetize by GUID. GUID is not shown in the UI, // so this is just a tie-breaker. All networks have unique GUIDs.
diff --git a/chromeos/components/tether/network_list_sorter_unittest.cc b/chromeos/components/tether/network_list_sorter_unittest.cc index edc4645..958a388 100644 --- a/chromeos/components/tether/network_list_sorter_unittest.cc +++ b/chromeos/components/tether/network_list_sorter_unittest.cc
@@ -117,9 +117,9 @@ TEST_F(NetworkListSorterTest, Carrier) { GenerateTestList(); - NetworkAtIndex(0)->set_carrier("c"); - NetworkAtIndex(1)->set_carrier("b"); - NetworkAtIndex(2)->set_carrier("a"); + NetworkAtIndex(0)->set_tether_carrier("c"); + NetworkAtIndex(1)->set_tether_carrier("b"); + NetworkAtIndex(2)->set_tether_carrier("a"); SortAndVerifySortOrder(2, 1, 0); }
diff --git a/chromeos/constants/chromeos_switches.cc b/chromeos/constants/chromeos_switches.cc index 6990455..ea869d5 100644 --- a/chromeos/constants/chromeos_switches.cc +++ b/chromeos/constants/chromeos_switches.cc
@@ -493,6 +493,10 @@ // This makes it easier to test layout logic. const char kShowLoginDevOverlay[] = "show-login-dev-overlay"; +// Url for the Supervision Onboarding starting page. +const char kSupervisionOnboardingStartPageUrl[] = + "supervision-onboarding-start-page-url"; + // Enables testing for encryption migration UI. const char kTestEncryptionMigrationUI[] = "test-encryption-migration-ui";
diff --git a/chromeos/constants/chromeos_switches.h b/chromeos/constants/chromeos_switches.h index 639dc0d..894253b 100644 --- a/chromeos/constants/chromeos_switches.h +++ b/chromeos/constants/chromeos_switches.h
@@ -187,6 +187,8 @@ COMPONENT_EXPORT(CHROMEOS_CONSTANTS) extern const char kShelfHoverPreviews[]; COMPONENT_EXPORT(CHROMEOS_CONSTANTS) extern const char kShowAndroidFilesInFilesApp[]; +COMPONENT_EXPORT(CHROMEOS_CONSTANTS) +extern const char kSupervisionOnboardingStartPageUrl[]; COMPONENT_EXPORT(CHROMEOS_CONSTANTS) extern const char kShowLoginDevOverlay[]; COMPONENT_EXPORT(CHROMEOS_CONSTANTS) extern const char kTestEncryptionMigrationUI[];
diff --git a/chromeos/network/BUILD.gn b/chromeos/network/BUILD.gn index 433859c..4ca2ad8 100644 --- a/chromeos/network/BUILD.gn +++ b/chromeos/network/BUILD.gn
@@ -184,6 +184,8 @@ sources = [ "fake_network_activation_handler.cc", "fake_network_activation_handler.h", + "fake_network_connection_handler.cc", + "fake_network_connection_handler.h", "fake_network_device_handler.cc", "fake_network_device_handler.h", "mock_managed_network_configuration_handler.cc",
diff --git a/chromeos/network/fake_network_activation_handler.cc b/chromeos/network/fake_network_activation_handler.cc index adb75e5..10b1bc4 100644 --- a/chromeos/network/fake_network_activation_handler.cc +++ b/chromeos/network/fake_network_activation_handler.cc
@@ -32,13 +32,14 @@ FakeNetworkActivationHandler::ActivationParams::~ActivationParams() = default; -void FakeNetworkActivationHandler::ActivationParams::InvokeSuccessCallback() { +void FakeNetworkActivationHandler::ActivationParams::InvokeSuccessCallback() + const { success_callback_.Run(); } void FakeNetworkActivationHandler::ActivationParams::InvokeErrorCallback( const std::string& error_name, - std::unique_ptr<base::DictionaryValue> error_data) { + std::unique_ptr<base::DictionaryValue> error_data) const { error_callback_.Run(error_name, std::move(error_data)); }
diff --git a/chromeos/network/fake_network_activation_handler.h b/chromeos/network/fake_network_activation_handler.h index 2bc77ab49..746e666 100644 --- a/chromeos/network/fake_network_activation_handler.h +++ b/chromeos/network/fake_network_activation_handler.h
@@ -21,6 +21,8 @@ FakeNetworkActivationHandler(); ~FakeNetworkActivationHandler() override; + // Parameters captured by calls to Activate() and CompleteActivation(). + // Accessible to clients via activate_calls() and complete_activation_calls(). class ActivationParams { public: // For Activate() calls. @@ -38,11 +40,15 @@ ~ActivationParams(); const std::string& service_path() const { return service_path_; } + + // Should only be called on ActivationParams objects corresponding to + // Activate() calls. const std::string& carrier() const { return *carrier_; } - void InvokeSuccessCallback(); - void InvokeErrorCallback(const std::string& error_name, - std::unique_ptr<base::DictionaryValue> error_data); + void InvokeSuccessCallback() const; + void InvokeErrorCallback( + const std::string& error_name, + std::unique_ptr<base::DictionaryValue> error_data) const; private: std::string service_path_; @@ -51,8 +57,10 @@ network_handler::ErrorCallback error_callback_; }; - std::vector<ActivationParams>& activate_calls() { return activate_calls_; } - std::vector<ActivationParams>& complete_activation_calls() { + const std::vector<ActivationParams>& activate_calls() const { + return activate_calls_; + } + const std::vector<ActivationParams>& complete_activation_calls() const { return complete_activation_calls_; }
diff --git a/chromeos/network/fake_network_connection_handler.cc b/chromeos/network/fake_network_connection_handler.cc new file mode 100644 index 0000000..2768248 --- /dev/null +++ b/chromeos/network/fake_network_connection_handler.cc
@@ -0,0 +1,74 @@ +// 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/network/fake_network_connection_handler.h" + +namespace chromeos { + +FakeNetworkConnectionHandler::ConnectionParams::ConnectionParams( + const std::string& service_path, + const base::Closure& success_callback, + const network_handler::ErrorCallback& error_callback, + bool check_error_state, + ConnectCallbackMode connect_callback_mode) + : service_path_(service_path), + success_callback_(success_callback), + error_callback_(error_callback), + check_error_state_(check_error_state), + connect_callback_mode_(connect_callback_mode) {} + +FakeNetworkConnectionHandler::ConnectionParams::ConnectionParams( + const std::string& service_path, + const base::Closure& success_callback, + const network_handler::ErrorCallback& error_callback) + : service_path_(service_path), + success_callback_(success_callback), + error_callback_(error_callback) {} + +FakeNetworkConnectionHandler::ConnectionParams::ConnectionParams( + const ConnectionParams& other) = default; + +FakeNetworkConnectionHandler::ConnectionParams::~ConnectionParams() = default; + +void FakeNetworkConnectionHandler::ConnectionParams::InvokeSuccessCallback() + const { + success_callback_.Run(); +} + +void FakeNetworkConnectionHandler::ConnectionParams::InvokeErrorCallback( + const std::string& error_name, + std::unique_ptr<base::DictionaryValue> error_data) const { + error_callback_.Run(error_name, std::move(error_data)); +} + +FakeNetworkConnectionHandler::FakeNetworkConnectionHandler() = default; + +FakeNetworkConnectionHandler::~FakeNetworkConnectionHandler() = default; + +void FakeNetworkConnectionHandler::ConnectToNetwork( + const std::string& service_path, + const base::Closure& success_callback, + const network_handler::ErrorCallback& error_callback, + bool check_error_state, + ConnectCallbackMode connect_callback_mode) { + connect_calls_.emplace_back(service_path, success_callback, error_callback, + check_error_state, connect_callback_mode); +} + +void FakeNetworkConnectionHandler::DisconnectNetwork( + const std::string& service_path, + const base::Closure& success_callback, + const network_handler::ErrorCallback& error_callback) { + disconnect_calls_.emplace_back(service_path, success_callback, + error_callback); +} + +void FakeNetworkConnectionHandler::Init( + NetworkStateHandler* network_state_handler, + NetworkConfigurationHandler* network_configuration_handler, + ManagedNetworkConfigurationHandler* managed_network_configuration_handler) { + // No initialization necessary for a test double. +} + +} // namespace chromeos
diff --git a/chromeos/network/fake_network_connection_handler.h b/chromeos/network/fake_network_connection_handler.h new file mode 100644 index 0000000..d7443ae --- /dev/null +++ b/chromeos/network/fake_network_connection_handler.h
@@ -0,0 +1,98 @@ +// 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_NETWORK_FAKE_NETWORK_CONNECTION_HANDLER_H_ +#define CHROMEOS_NETWORK_FAKE_NETWORK_CONNECTION_HANDLER_H_ + +#include <string> +#include <vector> + +#include "base/callback_forward.h" +#include "base/component_export.h" +#include "base/macros.h" +#include "chromeos/network/network_connection_handler.h" +#include "chromeos/network/network_handler_callbacks.h" + +namespace chromeos { + +// Fake NetworkConnectionHandler implementation for tests. +class COMPONENT_EXPORT(CHROMEOS_NETWORK) FakeNetworkConnectionHandler + : public NetworkConnectionHandler { + public: + FakeNetworkConnectionHandler(); + ~FakeNetworkConnectionHandler() override; + + // Parameters captured by calls to ConnectToNetwork() and DisconnectNetwork(). + // Accessible to clients via connect_calls() and disconnect_calls(). + class ConnectionParams { + public: + // For ConnectToNetwork() calls. + ConnectionParams(const std::string& service_path, + const base::Closure& success_callback, + const network_handler::ErrorCallback& error_callback, + bool check_error_state, + ConnectCallbackMode connect_callback_mode); + + // For DisconnectNetwork() calls. + ConnectionParams(const std::string& service_path, + const base::Closure& success_callback, + const network_handler::ErrorCallback& error_callback); + + ConnectionParams(const ConnectionParams& other); + ~ConnectionParams(); + + const std::string& service_path() const { return service_path_; } + + // check_error_state() and connect_callback_mode() should only be called for + // ConnectionParams objects corresponding to ConnectToNetwork() calls. + bool check_error_state() const { return *check_error_state_; } + ConnectCallbackMode connect_callback_mode() const { + return *connect_callback_mode_; + } + + void InvokeSuccessCallback() const; + void InvokeErrorCallback( + const std::string& error_name, + std::unique_ptr<base::DictionaryValue> error_data) const; + + private: + std::string service_path_; + base::Closure success_callback_; + network_handler::ErrorCallback error_callback_; + base::Optional<bool> check_error_state_; + base::Optional<ConnectCallbackMode> connect_callback_mode_; + }; + + const std::vector<ConnectionParams>& connect_calls() const { + return connect_calls_; + } + const std::vector<ConnectionParams>& disconnect_calls() const { + return disconnect_calls_; + } + + private: + // NetworkConnectionHandler: + void ConnectToNetwork(const std::string& service_path, + const base::Closure& success_callback, + const network_handler::ErrorCallback& error_callback, + bool check_error_state, + ConnectCallbackMode connect_callback_mode) override; + void DisconnectNetwork( + const std::string& service_path, + const base::Closure& success_callback, + const network_handler::ErrorCallback& error_callback) override; + void Init(NetworkStateHandler* network_state_handler, + NetworkConfigurationHandler* network_configuration_handler, + ManagedNetworkConfigurationHandler* + managed_network_configuration_handler) override; + + std::vector<ConnectionParams> connect_calls_; + std::vector<ConnectionParams> disconnect_calls_; + + DISALLOW_COPY_AND_ASSIGN(FakeNetworkConnectionHandler); +}; + +} // namespace chromeos + +#endif // CHROMEOS_NETWORK_FAKE_NETWORK_CONNECTION_HANDLER_H_
diff --git a/chromeos/network/network_state.cc b/chromeos/network/network_state.cc index 3bdd774..729ec49 100644 --- a/chromeos/network/network_state.cc +++ b/chromeos/network/network_state.cc
@@ -281,7 +281,7 @@ if (NetworkTypePattern::Tether().MatchesType(type())) { dictionary->SetKey(kTetherBatteryPercentage, base::Value(battery_percentage())); - dictionary->SetKey(kTetherCarrier, base::Value(carrier())); + dictionary->SetKey(kTetherCarrier, base::Value(tether_carrier())); dictionary->SetKey(kTetherHasConnectedToHost, base::Value(tether_has_connected_to_host())); dictionary->SetKey(kTetherSignalStrength, base::Value(signal_strength()));
diff --git a/chromeos/network/network_state.h b/chromeos/network/network_state.h index 96ff747..de06b717 100644 --- a/chromeos/network/network_state.h +++ b/chromeos/network/network_state.h
@@ -137,8 +137,10 @@ void set_battery_percentage(int battery_percentage) { battery_percentage_ = battery_percentage; } - const std::string& carrier() const { return carrier_; } - void set_carrier(const std::string& carrier) { carrier_ = carrier; } + const std::string& tether_carrier() const { return tether_carrier_; } + void set_tether_carrier(const std::string& tether_carrier) { + tether_carrier_ = tether_carrier; + } bool tether_has_connected_to_host() const { return tether_has_connected_to_host_; } @@ -307,7 +309,7 @@ std::unique_ptr<VpnProviderInfo> vpn_provider_; // Tether properties. - std::string carrier_; + std::string tether_carrier_; int battery_percentage_ = 0; // Whether the current device has already connected to the tether host device
diff --git a/chromeos/network/network_state_handler.cc b/chromeos/network/network_state_handler.cc index 5253727..932bbcf 100644 --- a/chromeos/network/network_state_handler.cc +++ b/chromeos/network/network_state_handler.cc
@@ -689,7 +689,7 @@ tether_network_state->set_update_received(); tether_network_state->set_update_requested(false); tether_network_state->set_connectable(true); - tether_network_state->set_carrier(carrier); + tether_network_state->set_tether_carrier(carrier); tether_network_state->set_battery_percentage(battery_percentage); tether_network_state->set_tether_has_connected_to_host(has_connected_to_host); tether_network_state->set_signal_strength(signal_strength); @@ -718,7 +718,7 @@ return false; } - tether_network_state->set_carrier(carrier); + tether_network_state->set_tether_carrier(carrier); tether_network_state->set_battery_percentage(battery_percentage); tether_network_state->set_signal_strength(signal_strength); network_list_sorted_ = false;
diff --git a/chromeos/network/network_state_handler_unittest.cc b/chromeos/network/network_state_handler_unittest.cc index 3989cc5e..18fb9f76 100644 --- a/chromeos/network/network_state_handler_unittest.cc +++ b/chromeos/network/network_state_handler_unittest.cc
@@ -988,7 +988,7 @@ ASSERT_TRUE(tether_network); EXPECT_EQ(kTetherName1, tether_network->name()); EXPECT_EQ(kTetherGuid1, tether_network->path()); - EXPECT_EQ(kTetherCarrier1, tether_network->carrier()); + EXPECT_EQ(kTetherCarrier1, tether_network->tether_carrier()); EXPECT_EQ(kTetherBatteryPercentage1, tether_network->battery_percentage()); EXPECT_EQ(kTetherSignalStrength1, tether_network->signal_strength()); EXPECT_FALSE(tether_network->tether_has_connected_to_host()); @@ -1006,7 +1006,7 @@ ASSERT_TRUE(tether_network); EXPECT_EQ(kTetherName1, tether_network->name()); EXPECT_EQ(kTetherGuid1, tether_network->path()); - EXPECT_EQ("NewCarrier", tether_network->carrier()); + EXPECT_EQ("NewCarrier", tether_network->tether_carrier()); EXPECT_EQ(5, tether_network->battery_percentage()); EXPECT_EQ(10, tether_network->signal_strength()); EXPECT_FALSE(tether_network->tether_has_connected_to_host());
diff --git a/chromeos/network/network_state_unittest.cc b/chromeos/network/network_state_unittest.cc index 2b17d6c4..73adbb19 100644 --- a/chromeos/network/network_state_unittest.cc +++ b/chromeos/network/network_state_unittest.cc
@@ -322,7 +322,7 @@ TEST_F(NetworkStateTest, TetherProperties) { network_state_.set_type_for_testing(kTypeTether); - network_state_.set_carrier("Project Fi"); + network_state_.set_tether_carrier("Project Fi"); network_state_.set_battery_percentage(85); network_state_.set_tether_has_connected_to_host(true); network_state_.set_signal_strength(75);
diff --git a/chromeos/services/network_config/cros_network_config.cc b/chromeos/services/network_config/cros_network_config.cc index e399dd1..0d908c5 100644 --- a/chromeos/services/network_config/cros_network_config.cc +++ b/chromeos/services/network_config/cros_network_config.cc
@@ -165,7 +165,7 @@ case mojom::NetworkType::kTether: { auto tether = mojom::TetherStateProperties::New(); tether->battery_percentage = network->battery_percentage(); - tether->carrier = network->carrier(); + tether->carrier = network->tether_carrier(); tether->has_connected_to_host = network->tether_has_connected_to_host(); tether->signal_strength = network->signal_strength(); result->tether = std::move(tether);
diff --git a/components/exo/client_controlled_shell_surface.cc b/components/exo/client_controlled_shell_surface.cc index 2f11aace..4cebdea 100644 --- a/components/exo/client_controlled_shell_surface.cc +++ b/components/exo/client_controlled_shell_surface.cc
@@ -83,14 +83,13 @@ ~ClientControlledStateDelegate() override {} // Overridden from ash::wm::ClientControlledState::Delegate: - void HandleWindowStateRequest( - ash::wm::WindowState* window_state, - ash::mojom::WindowStateType next_state) override { + void HandleWindowStateRequest(ash::wm::WindowState* window_state, + ash::WindowStateType next_state) override { shell_surface_->OnWindowStateChangeEvent(window_state->GetStateType(), next_state); } void HandleBoundsRequest(ash::wm::WindowState* window_state, - ash::mojom::WindowStateType requested_state, + ash::WindowStateType requested_state, const gfx::Rect& bounds) override { gfx::Rect bounds_in_screen(bounds); ::wm::ConvertRectToScreen(window_state->window()->GetRootWindow(), @@ -125,31 +124,31 @@ // Overridden from ash::wm::WindowStateDelegate: bool ToggleFullscreen(ash::wm::WindowState* window_state) override { - ash::mojom::WindowStateType next_state; + ash::WindowStateType next_state; aura::Window* window = window_state->window(); switch (window_state->GetStateType()) { - case ash::mojom::WindowStateType::DEFAULT: - case ash::mojom::WindowStateType::NORMAL: + case ash::WindowStateType::kDefault: + case ash::WindowStateType::kNormal: window->SetProperty(aura::client::kPreFullscreenShowStateKey, ui::SHOW_STATE_NORMAL); - next_state = ash::mojom::WindowStateType::FULLSCREEN; + next_state = ash::WindowStateType::kFullscreen; break; - case ash::mojom::WindowStateType::MAXIMIZED: + case ash::WindowStateType::kMaximized: window->SetProperty(aura::client::kPreFullscreenShowStateKey, ui::SHOW_STATE_MAXIMIZED); - next_state = ash::mojom::WindowStateType::FULLSCREEN; + next_state = ash::WindowStateType::kFullscreen; break; - case ash::mojom::WindowStateType::FULLSCREEN: + case ash::WindowStateType::kFullscreen: switch (window->GetProperty(aura::client::kPreFullscreenShowStateKey)) { case ui::SHOW_STATE_DEFAULT: case ui::SHOW_STATE_NORMAL: - next_state = ash::mojom::WindowStateType::NORMAL; + next_state = ash::WindowStateType::kNormal; break; case ui::SHOW_STATE_MAXIMIZED: - next_state = ash::mojom::WindowStateType::MAXIMIZED; + next_state = ash::WindowStateType::kMaximized; break; case ui::SHOW_STATE_MINIMIZED: - next_state = ash::mojom::WindowStateType::MINIMIZED; + next_state = ash::WindowStateType::kMinimized; break; case ui::SHOW_STATE_FULLSCREEN: case ui::SHOW_STATE_INACTIVE: @@ -160,14 +159,14 @@ return false; } break; - case ash::mojom::WindowStateType::MINIMIZED: { + case ash::WindowStateType::kMinimized: { ui::WindowShowState pre_full_state = window->GetProperty(aura::client::kPreMinimizedShowStateKey); if (pre_full_state != ui::SHOW_STATE_FULLSCREEN) { window->SetProperty(aura::client::kPreFullscreenShowStateKey, pre_full_state); } - next_state = ash::mojom::WindowStateType::FULLSCREEN; + next_state = ash::WindowStateType::kFullscreen; break; } default: @@ -333,39 +332,39 @@ void ClientControlledShellSurface::SetMaximized() { TRACE_EVENT0("exo", "ClientControlledShellSurface::SetMaximized"); - pending_window_state_ = ash::mojom::WindowStateType::MAXIMIZED; + pending_window_state_ = ash::WindowStateType::kMaximized; } void ClientControlledShellSurface::SetMinimized() { TRACE_EVENT0("exo", "ClientControlledShellSurface::SetMinimized"); - pending_window_state_ = ash::mojom::WindowStateType::MINIMIZED; + pending_window_state_ = ash::WindowStateType::kMinimized; } void ClientControlledShellSurface::SetRestored() { TRACE_EVENT0("exo", "ClientControlledShellSurface::SetRestored"); - pending_window_state_ = ash::mojom::WindowStateType::NORMAL; + pending_window_state_ = ash::WindowStateType::kNormal; } void ClientControlledShellSurface::SetFullscreen(bool fullscreen) { TRACE_EVENT1("exo", "ClientControlledShellSurface::SetFullscreen", "fullscreen", fullscreen); - pending_window_state_ = fullscreen ? ash::mojom::WindowStateType::FULLSCREEN - : ash::mojom::WindowStateType::NORMAL; + pending_window_state_ = fullscreen ? ash::WindowStateType::kFullscreen + : ash::WindowStateType::kNormal; } void ClientControlledShellSurface::SetSnappedToLeft() { TRACE_EVENT0("exo", "ClientControlledShellSurface::SetSnappedToLeft"); - pending_window_state_ = ash::mojom::WindowStateType::LEFT_SNAPPED; + pending_window_state_ = ash::WindowStateType::kLeftSnapped; } void ClientControlledShellSurface::SetSnappedToRight() { TRACE_EVENT0("exo", "ClientControlledShellSurface::SetSnappedToRight"); - pending_window_state_ = ash::mojom::WindowStateType::RIGHT_SNAPPED; + pending_window_state_ = ash::WindowStateType::kRightSnapped; } void ClientControlledShellSurface::SetPip() { TRACE_EVENT0("exo", "ClientControlledShellSurface::SetPip"); - pending_window_state_ = ash::mojom::WindowStateType::PIP; + pending_window_state_ = ash::WindowStateType::kPip; } void ClientControlledShellSurface::SetPinned(ash::mojom::WindowPinType type) { @@ -445,8 +444,8 @@ } void ClientControlledShellSurface::OnWindowStateChangeEvent( - ash::mojom::WindowStateType current_state, - ash::mojom::WindowStateType next_state) { + ash::WindowStateType current_state, + ash::WindowStateType next_state) { // Android already knows this state change. Don't send state change to Android // that it is about to do anyway. if (state_changed_callback_ && pending_window_state_ != next_state) @@ -547,8 +546,8 @@ } void ClientControlledShellSurface::OnBoundsChangeEvent( - ash::mojom::WindowStateType current_state, - ash::mojom::WindowStateType requested_state, + ash::WindowStateType current_state, + ash::WindowStateType requested_state, int64_t display_id, const gfx::Rect& window_bounds, int bounds_change) { @@ -558,7 +557,7 @@ // The bounds will be provided by client when unminimized. if (!geometry().IsEmpty() && !window_bounds.IsEmpty() && (!widget_->IsMinimized() || - requested_state != ash::mojom::WindowStateType::MINIMIZED) && + requested_state != ash::WindowStateType::kMinimized) && bounds_changed_callback_) { // Sends the client bounds, which matches the geometry // when frame is enabled. @@ -570,8 +569,8 @@ // Snapped window states in tablet mode also do not include the caption // height. const bool becoming_snapped = - requested_state == ash::mojom::WindowStateType::LEFT_SNAPPED || - requested_state == ash::mojom::WindowStateType::RIGHT_SNAPPED; + requested_state == ash::WindowStateType::kLeftSnapped || + requested_state == ash::WindowStateType::kRightSnapped; const bool is_tablet_mode = WMHelper::GetInstance()->IsTabletModeWindowManagerEnabled(); gfx::Rect client_bounds = @@ -916,14 +915,14 @@ auto animation_type = ash::wm::ClientControlledState::kAnimationNone; switch (pending_window_state_) { - case ash::mojom::WindowStateType::NORMAL: + case ash::WindowStateType::kNormal: if (widget_->IsMaximized() || widget_->IsFullscreen()) { animation_type = ash::wm::ClientControlledState::kAnimationCrossFade; } break; - case ash::mojom::WindowStateType::MAXIMIZED: - case ash::mojom::WindowStateType::FULLSCREEN: + case ash::WindowStateType::kMaximized: + case ash::WindowStateType::kFullscreen: if (!window_state->IsPip()) animation_type = ash::wm::ClientControlledState::kAnimationCrossFade; break; @@ -932,7 +931,7 @@ break; } - if (pending_window_state_ == ash::mojom::WindowStateType::PIP) { + if (pending_window_state_ == ash::WindowStateType::kPip) { if (ash::features::IsPipRoundedCornersEnabled()) { decorator_ = std::make_unique<ash::RoundedCornerDecorator>( window_state->window(), host_window(), host_window()->layer(),
diff --git a/components/exo/client_controlled_shell_surface.h b/components/exo/client_controlled_shell_surface.h index 8608a9e2..122856a 100644 --- a/components/exo/client_controlled_shell_surface.h +++ b/components/exo/client_controlled_shell_surface.h
@@ -83,21 +83,21 @@ // Set the callback to run when the surface state changed. using StateChangedCallback = - base::RepeatingCallback<void(ash::mojom::WindowStateType old_state_type, - ash::mojom::WindowStateType new_state_type)>; + base::RepeatingCallback<void(ash::WindowStateType old_state_type, + ash::WindowStateType new_state_type)>; void set_state_changed_callback( const StateChangedCallback& state_changed_callback) { state_changed_callback_ = state_changed_callback; } // Set the callback to run when the surface bounds changed. - using BoundsChangedCallback = base::RepeatingCallback<void( - ash::mojom::WindowStateType current_state, - ash::mojom::WindowStateType requested_state, - int64_t display_id, - const gfx::Rect& bounds, - bool is_resize, - int bounds_change)>; + using BoundsChangedCallback = + base::RepeatingCallback<void(ash::WindowStateType current_state, + ash::WindowStateType requested_state, + int64_t display_id, + const gfx::Rect& bounds, + bool is_resize, + int bounds_change)>; void set_bounds_changed_callback( const BoundsChangedCallback& bounds_changed_callback) { bounds_changed_callback_ = bounds_changed_callback; @@ -144,16 +144,16 @@ void SetResizeOutset(int outset); // Sends the window state change event to client. - void OnWindowStateChangeEvent(ash::mojom::WindowStateType old_state, - ash::mojom::WindowStateType next_state); + void OnWindowStateChangeEvent(ash::WindowStateType old_state, + ash::WindowStateType next_state); // Sends the window bounds change event to client. |display_id| specifies in // which display the surface should live in. |drag_bounds_change| is // a masked value of ash::WindowResizer::kBoundsChange_Xxx, and specifies // how the bounds was changed. The bounds change event may also come from a // snapped window state change |requested_state|. - void OnBoundsChangeEvent(ash::mojom::WindowStateType current_state, - ash::mojom::WindowStateType requested_state, + void OnBoundsChangeEvent(ash::WindowStateType current_state, + ash::WindowStateType requested_state, int64_t display_id, const gfx::Rect& bounds, int drag_bounds_change); @@ -285,8 +285,7 @@ ash::wm::ClientControlledState* client_controlled_state_ = nullptr; - ash::mojom::WindowStateType pending_window_state_ = - ash::mojom::WindowStateType::NORMAL; + ash::WindowStateType pending_window_state_ = ash::WindowStateType::kNormal; bool can_maximize_ = true;
diff --git a/components/exo/client_controlled_shell_surface_unittest.cc b/components/exo/client_controlled_shell_surface_unittest.cc index da9e0c57..2f338db 100644 --- a/components/exo/client_controlled_shell_surface_unittest.cc +++ b/components/exo/client_controlled_shell_surface_unittest.cc
@@ -1015,8 +1015,7 @@ ash::wm::ClientControlledState* state1 = static_cast<ash::wm::ClientControlledState*>( ash::wm::WindowState::TestApi::GetStateImpl(window_state1)); - EXPECT_EQ(window_state1->GetStateType(), - ash::mojom::WindowStateType::MAXIMIZED); + EXPECT_EQ(window_state1->GetStateType(), ash::WindowStateType::kMaximized); // Snap window to left. ash::SplitViewController* split_view_controller = @@ -1026,8 +1025,7 @@ window1->SetBounds(split_view_controller->GetSnappedWindowBoundsInScreen( window1, ash::SplitViewController::LEFT)); state1->set_bounds_locally(false); - EXPECT_EQ(window_state1->GetStateType(), - ash::mojom::WindowStateType::LEFT_SNAPPED); + EXPECT_EQ(window_state1->GetStateType(), ash::WindowStateType::kLeftSnapped); EXPECT_EQ(shell_surface1->GetWidget()->GetWindowBoundsInScreen(), split_view_controller->GetSnappedWindowBoundsInScreen( window1, ash::SplitViewController::LEFT)); @@ -1040,8 +1038,7 @@ window1->SetBounds(split_view_controller->GetSnappedWindowBoundsInScreen( window1, ash::SplitViewController::RIGHT)); state1->set_bounds_locally(false); - EXPECT_EQ(window_state1->GetStateType(), - ash::mojom::WindowStateType::RIGHT_SNAPPED); + EXPECT_EQ(window_state1->GetStateType(), ash::WindowStateType::kRightSnapped); EXPECT_EQ(shell_surface1->GetWidget()->GetWindowBoundsInScreen(), split_view_controller->GetSnappedWindowBoundsInScreen( window1, ash::SplitViewController::RIGHT)); @@ -1246,7 +1243,7 @@ shell->overview_controller()->ToggleOverview(); SendGestureEvents(window, gfx::Point(0, 210)); EXPECT_EQ(ash::wm::GetWindowState(window)->GetStateType(), - ash::mojom::WindowStateType::LEFT_SNAPPED); + ash::WindowStateType::kLeftSnapped); } namespace { @@ -1275,8 +1272,8 @@ return requested_display_ids_; } - void OnBoundsChangeEvent(ash::mojom::WindowStateType current_state, - ash::mojom::WindowStateType requested_state, + void OnBoundsChangeEvent(ash::WindowStateType current_state, + ash::WindowStateType requested_state, int64_t display_id, const gfx::Rect& bounds, bool is_resize, @@ -1810,8 +1807,8 @@ exo_test_helper()->CreateClientControlledShellSurface(surface.get()); gfx::Rect requested_bounds; shell_surface->set_bounds_changed_callback(base::BindRepeating( - [](gfx::Rect* dst, ash::mojom::WindowStateType current_state, - ash::mojom::WindowStateType requested_state, int64_t display_id, + [](gfx::Rect* dst, ash::WindowStateType current_state, + ash::WindowStateType requested_state, int64_t display_id, const gfx::Rect& bounds, bool is_resize, int bounds_change) { *dst = bounds; }, base::Unretained(&requested_bounds))); @@ -1851,8 +1848,7 @@ ash::wm::WMEvent event(ash::wm::WM_EVENT_SNAP_LEFT); window_state->OnWMEvent(&event); - EXPECT_EQ(window_state->GetStateType(), - ash::mojom::WindowStateType::LEFT_SNAPPED); + EXPECT_EQ(window_state->GetStateType(), ash::WindowStateType::kLeftSnapped); ash::NonClientFrameViewAsh* frame_view = static_cast<ash::NonClientFrameViewAsh*>( @@ -1909,8 +1905,8 @@ base::Unretained(this))); ASSERT_EQ(0, bounds_change_count()); - shell_surface->OnBoundsChangeEvent(ash::mojom::WindowStateType::NORMAL, - ash::mojom::WindowStateType::NORMAL, 0, + shell_surface->OnBoundsChangeEvent(ash::WindowStateType::kNormal, + ash::WindowStateType::kNormal, 0, gfx::Rect(10, 10, 100, 100), 0); ASSERT_EQ(1, bounds_change_count()); @@ -1920,14 +1916,14 @@ surface->Commit(); EXPECT_TRUE(shell_surface->GetWidget()->IsMinimized()); - shell_surface->OnBoundsChangeEvent(ash::mojom::WindowStateType::MINIMIZED, - ash::mojom::WindowStateType::MINIMIZED, 0, + shell_surface->OnBoundsChangeEvent(ash::WindowStateType::kMinimized, + ash::WindowStateType::kMinimized, 0, gfx::Rect(0, 0, 100, 100), 0); ASSERT_EQ(1, bounds_change_count()); // Send bounds change when exiting minmized. - shell_surface->OnBoundsChangeEvent(ash::mojom::WindowStateType::MINIMIZED, - ash::mojom::WindowStateType::NORMAL, 0, + shell_surface->OnBoundsChangeEvent(ash::WindowStateType::kMinimized, + ash::WindowStateType::kNormal, 0, gfx::Rect(0, 0, 100, 100), 0); ASSERT_EQ(2, bounds_change_count()); @@ -1937,9 +1933,9 @@ shell_surface->GetWidget()->non_client_view()->frame_view()); surface->SetFrame(SurfaceFrameType::NORMAL); surface->Commit(); - shell_surface->OnBoundsChangeEvent(ash::mojom::WindowStateType::MINIMIZED, - ash::mojom::WindowStateType::RIGHT_SNAPPED, - 0, gfx::Rect(0, 0, 100, 100), 0); + shell_surface->OnBoundsChangeEvent(ash::WindowStateType::kMinimized, + ash::WindowStateType::kRightSnapped, 0, + gfx::Rect(0, 0, 100, 100), 0); EXPECT_EQ(3, bounds_change_count()); EXPECT_EQ( frame_view->GetClientBoundsForWindowBounds(gfx::Rect(0, 0, 100, 100)), @@ -1948,9 +1944,9 @@ // Snapped, in tablet mode. EnableTabletMode(true); - shell_surface->OnBoundsChangeEvent(ash::mojom::WindowStateType::MINIMIZED, - ash::mojom::WindowStateType::RIGHT_SNAPPED, - 0, gfx::Rect(0, 0, 100, 100), 0); + shell_surface->OnBoundsChangeEvent(ash::WindowStateType::kMinimized, + ash::WindowStateType::kRightSnapped, 0, + gfx::Rect(0, 0, 100, 100), 0); EXPECT_EQ(4, bounds_change_count()); EXPECT_EQ(gfx::Rect(0, 0, 100, 100), requested_bounds().back()); } @@ -2086,8 +2082,8 @@ auto shell_surface = exo_test_helper()->CreateClientControlledShellSurface(surface.get()); - shell_surface->set_state_changed_callback(base::BindRepeating( - [](ash::mojom::WindowStateType, ash::mojom::WindowStateType) { + shell_surface->set_state_changed_callback( + base::BindRepeating([](ash::WindowStateType, ash::WindowStateType) { // This callback must not be called when a widget is created. EXPECT_TRUE(false); }));
diff --git a/components/exo/shell_surface.cc b/components/exo/shell_surface.cc index c5bcfff2..44846dd 100644 --- a/components/exo/shell_surface.cc +++ b/components/exo/shell_surface.cc
@@ -418,8 +418,8 @@ void ShellSurface::OnPreWindowStateTypeChange( ash::wm::WindowState* window_state, - ash::mojom::WindowStateType old_type) { - ash::mojom::WindowStateType new_type = window_state->GetStateType(); + ash::WindowStateType old_type) { + ash::WindowStateType new_type = window_state->GetStateType(); if (ash::IsMinimizedWindowStateType(old_type) || ash::IsMinimizedWindowStateType(new_type)) { return; @@ -451,8 +451,8 @@ void ShellSurface::OnPostWindowStateTypeChange( ash::wm::WindowState* window_state, - ash::mojom::WindowStateType old_type) { - ash::mojom::WindowStateType new_type = window_state->GetStateType(); + ash::WindowStateType old_type) { + ash::WindowStateType new_type = window_state->GetStateType(); if (ash::IsMaximizedOrFullscreenOrPinnedWindowStateType(new_type)) { Configure(); } @@ -590,9 +590,9 @@ ash::wm::GetWindowState(widget_->GetNativeWindow())->GetStateType(), IsResizing(), widget_->IsActive(), origin_offset); } else { - serial = configure_callback_.Run(gfx::Size(), - ash::mojom::WindowStateType::NORMAL, - false, false, origin_offset); + serial = + configure_callback_.Run(gfx::Size(), ash::WindowStateType::kNormal, + false, false, origin_offset); } }
diff --git a/components/exo/shell_surface.h b/components/exo/shell_surface.h index aea3623..8e4d880 100644 --- a/components/exo/shell_surface.h +++ b/components/exo/shell_surface.h
@@ -39,7 +39,7 @@ // in steps of NxM pixels). using ConfigureCallback = base::RepeatingCallback<uint32_t(const gfx::Size& size, - ash::mojom::WindowStateType state_type, + ash::WindowStateType state_type, bool resizing, bool activated, const gfx::Vector2d& origin_offset)>; @@ -97,12 +97,10 @@ ui::PropertyChangeReason reason) override; // Overridden from ash::wm::WindowStateObserver: - void OnPreWindowStateTypeChange( - ash::wm::WindowState* window_state, - ash::mojom::WindowStateType old_type) override; - void OnPostWindowStateTypeChange( - ash::wm::WindowState* window_state, - ash::mojom::WindowStateType old_type) override; + void OnPreWindowStateTypeChange(ash::wm::WindowState* window_state, + ash::WindowStateType old_type) override; + void OnPostWindowStateTypeChange(ash::wm::WindowState* window_state, + ash::WindowStateType old_type) override; // Overridden from wm::ActivationChangeObserver: void OnWindowActivated(ActivationReason reason,
diff --git a/components/exo/shell_surface_base.h b/components/exo/shell_surface_base.h index 5f46aaa..b1ac80e8 100644 --- a/components/exo/shell_surface_base.h +++ b/components/exo/shell_surface_base.h
@@ -10,7 +10,6 @@ #include <string> #include "ash/display/window_tree_host_manager.h" -#include "ash/public/interfaces/window_state_type.mojom.h" #include "base/macros.h" #include "base/optional.h" #include "base/strings/string16.h"
diff --git a/components/exo/shell_surface_unittest.cc b/components/exo/shell_surface_unittest.cc index ab630b2..26f291f 100644 --- a/components/exo/shell_surface_unittest.cc +++ b/components/exo/shell_surface_unittest.cc
@@ -53,11 +53,11 @@ uint32_t ConfigureFullscreen(uint32_t serial, const gfx::Size& size, - ash::mojom::WindowStateType state_type, + ash::WindowStateType state_type, bool resizing, bool activated, const gfx::Vector2d& origin_offset) { - EXPECT_EQ(ash::mojom::WindowStateType::FULLSCREEN, state_type); + EXPECT_EQ(ash::WindowStateType::kFullscreen, state_type); return serial; } @@ -473,11 +473,11 @@ } uint32_t Configure(gfx::Size* suggested_size, - ash::mojom::WindowStateType* has_state_type, + ash::WindowStateType* has_state_type, bool* is_resizing, bool* is_active, const gfx::Size& size, - ash::mojom::WindowStateType state_type, + ash::WindowStateType state_type, bool resizing, bool activated, const gfx::Vector2d& origin_offset) { @@ -492,8 +492,7 @@ // Must be before shell_surface so it outlives it, for shell_surface's // destructor calls Configure() referencing these 4 variables. gfx::Size suggested_size; - ash::mojom::WindowStateType has_state_type = - ash::mojom::WindowStateType::NORMAL; + ash::WindowStateType has_state_type = ash::WindowStateType::kNormal; bool is_resizing = false; bool is_active = false; @@ -522,7 +521,7 @@ EXPECT_FALSE(shell_surface->GetWidget()); EXPECT_TRUE(suggested_size.IsEmpty()); - EXPECT_EQ(ash::mojom::WindowStateType::NORMAL, has_state_type); + EXPECT_EQ(ash::WindowStateType::kNormal, has_state_type); gfx::Size buffer_size(64, 64); std::unique_ptr<Buffer> buffer( @@ -534,7 +533,7 @@ display::Screen::GetScreen()->GetPrimaryDisplay().work_area(); EXPECT_TRUE(shell_surface->GetWidget()); EXPECT_EQ(maximized_bounds.size(), suggested_size); - EXPECT_EQ(ash::mojom::WindowStateType::MAXIMIZED, has_state_type); + EXPECT_EQ(ash::WindowStateType::kMaximized, has_state_type); shell_surface->Restore(); shell_surface->AcknowledgeConfigure(0); // It should be restored to the original geometry size. @@ -544,7 +543,7 @@ shell_surface->AcknowledgeConfigure(0); EXPECT_EQ(CurrentContext()->bounds().size().ToString(), suggested_size.ToString()); - EXPECT_EQ(ash::mojom::WindowStateType::FULLSCREEN, has_state_type); + EXPECT_EQ(ash::WindowStateType::kFullscreen, has_state_type); shell_surface->SetFullscreen(false); shell_surface->AcknowledgeConfigure(0); EXPECT_EQ(geometry.size(), shell_surface->CalculatePreferredSize());
diff --git a/components/exo/test/test_client_controlled_state_delegate.cc b/components/exo/test/test_client_controlled_state_delegate.cc index 00f9553..dd7a2c29 100644 --- a/components/exo/test/test_client_controlled_state_delegate.cc +++ b/components/exo/test/test_client_controlled_state_delegate.cc
@@ -4,7 +4,7 @@ #include "components/exo/test/test_client_controlled_state_delegate.h" -#include "ash/public/interfaces/window_state_type.mojom.h" +#include "ash/public/cpp/window_state_type.h" #include "ash/wm/window_state.h" #include "base/bind.h" #include "components/exo/client_controlled_shell_surface.h" @@ -23,7 +23,7 @@ void TestClientControlledStateDelegate::HandleWindowStateRequest( ash::wm::WindowState* window_state, - ash::mojom::WindowStateType next_state) { + ash::WindowStateType next_state) { views::Widget* widget = views::Widget::GetWidgetForNativeWindow(window_state->window()); ClientControlledShellSurface* shell_surface = @@ -33,17 +33,17 @@ next_state); switch (next_state) { - case ash::mojom::WindowStateType::NORMAL: - case ash::mojom::WindowStateType::DEFAULT: + case ash::WindowStateType::kNormal: + case ash::WindowStateType::kDefault: shell_surface->SetRestored(); break; - case ash::mojom::WindowStateType::MINIMIZED: + case ash::WindowStateType::kMinimized: shell_surface->SetMinimized(); break; - case ash::mojom::WindowStateType::MAXIMIZED: + case ash::WindowStateType::kMaximized: shell_surface->SetMaximized(); break; - case ash::mojom::WindowStateType::FULLSCREEN: + case ash::WindowStateType::kFullscreen: shell_surface->SetFullscreen(true); break; default: @@ -55,7 +55,7 @@ void TestClientControlledStateDelegate::HandleBoundsRequest( ash::wm::WindowState* window_state, - ash::mojom::WindowStateType requested_state, + ash::WindowStateType requested_state, const gfx::Rect& bounds) { views::Widget* widget = views::Widget::GetWidgetForNativeWindow(window_state->window()); @@ -70,9 +70,9 @@ shell_surface->SetBounds(display_id, bounds); if (requested_state != window_state->GetStateType()) { - DCHECK(requested_state == ash::mojom::WindowStateType::LEFT_SNAPPED || - requested_state == ash::mojom::WindowStateType::RIGHT_SNAPPED); - if (requested_state == ash::mojom::WindowStateType::LEFT_SNAPPED) + DCHECK(requested_state == ash::WindowStateType::kLeftSnapped || + requested_state == ash::WindowStateType::kRightSnapped); + if (requested_state == ash::WindowStateType::kLeftSnapped) shell_surface->SetSnappedToLeft(); else shell_surface->SetSnappedToRight();
diff --git a/components/exo/test/test_client_controlled_state_delegate.h b/components/exo/test/test_client_controlled_state_delegate.h index 2ba4f96a..5895a5a 100644 --- a/components/exo/test/test_client_controlled_state_delegate.h +++ b/components/exo/test/test_client_controlled_state_delegate.h
@@ -20,11 +20,10 @@ ~TestClientControlledStateDelegate() override; // Overridden from ash::wm::ClientControlledState::Delegate: - void HandleWindowStateRequest( - ash::wm::WindowState* window_state, - ash::mojom::WindowStateType next_state) override; + void HandleWindowStateRequest(ash::wm::WindowState* window_state, + ash::WindowStateType next_state) override; void HandleBoundsRequest(ash::wm::WindowState* window_state, - ash::mojom::WindowStateType requested_state, + ash::WindowStateType requested_state, const gfx::Rect& bounds) override; private:
diff --git a/components/exo/wayland/clients/rects.cc b/components/exo/wayland/clients/rects.cc index 863b9ba5..febeba12 100644 --- a/components/exo/wayland/clients/rects.cc +++ b/components/exo/wayland/clients/rects.cc
@@ -402,7 +402,7 @@ canvas->drawIRect(rect, paint); std::string text = base::NumberToString(event_time.InMicroseconds()); canvas->drawSimpleText(text.c_str(), text.length(), - kUTF8_SkTextEncoding, 8, y + 32, font, + SkTextEncoding::kUTF8, 8, y + 32, font, text_paint); frame->event_times.push_back(event_times.motion_timestamps.back()); event_times.motion_timestamps.pop_back(); @@ -433,7 +433,7 @@ // Draw FPS counter. if (show_fps_counter) { canvas->drawSimpleText(fps_counter_text.c_str(), - fps_counter_text.length(), kUTF8_SkTextEncoding, + fps_counter_text.length(), SkTextEncoding::kUTF8, size_.width() - 48, 32, font, text_paint); } GrContext* gr_context = gr_context_.get();
diff --git a/components/exo/wayland/wl_shell.cc b/components/exo/wayland/wl_shell.cc index 1b283e6..c994d18 100644 --- a/components/exo/wayland/wl_shell.cc +++ b/components/exo/wayland/wl_shell.cc
@@ -125,7 +125,7 @@ uint32_t HandleShellSurfaceConfigureCallback( wl_resource* resource, const gfx::Size& size, - ash::mojom::WindowStateType state_type, + ash::WindowStateType state_type, bool resizing, bool activated, const gfx::Vector2d& origin_offset) {
diff --git a/components/exo/wayland/zcr_remote_shell.cc b/components/exo/wayland/zcr_remote_shell.cc index ed28192..6d00683 100644 --- a/components/exo/wayland/zcr_remote_shell.cc +++ b/components/exo/wayland/zcr_remote_shell.cc
@@ -863,34 +863,34 @@ void HandleRemoteSurfaceStateChangedCallback( wl_resource* resource, - ash::mojom::WindowStateType old_state_type, - ash::mojom::WindowStateType new_state_type) { + ash::WindowStateType old_state_type, + ash::WindowStateType new_state_type) { DCHECK_NE(old_state_type, new_state_type); uint32_t state_type = ZCR_REMOTE_SHELL_V1_STATE_TYPE_NORMAL; switch (new_state_type) { - case ash::mojom::WindowStateType::MINIMIZED: + case ash::WindowStateType::kMinimized: state_type = ZCR_REMOTE_SHELL_V1_STATE_TYPE_MINIMIZED; break; - case ash::mojom::WindowStateType::MAXIMIZED: + case ash::WindowStateType::kMaximized: state_type = ZCR_REMOTE_SHELL_V1_STATE_TYPE_MAXIMIZED; break; - case ash::mojom::WindowStateType::FULLSCREEN: + case ash::WindowStateType::kFullscreen: state_type = ZCR_REMOTE_SHELL_V1_STATE_TYPE_FULLSCREEN; break; - case ash::mojom::WindowStateType::PINNED: + case ash::WindowStateType::kPinned: state_type = ZCR_REMOTE_SHELL_V1_STATE_TYPE_PINNED; break; - case ash::mojom::WindowStateType::TRUSTED_PINNED: + case ash::WindowStateType::kTrustedPinned: state_type = ZCR_REMOTE_SHELL_V1_STATE_TYPE_TRUSTED_PINNED; break; - case ash::mojom::WindowStateType::LEFT_SNAPPED: + case ash::WindowStateType::kLeftSnapped: state_type = ZCR_REMOTE_SHELL_V1_STATE_TYPE_LEFT_SNAPPED; break; - case ash::mojom::WindowStateType::RIGHT_SNAPPED: + case ash::WindowStateType::kRightSnapped: state_type = ZCR_REMOTE_SHELL_V1_STATE_TYPE_RIGHT_SNAPPED; break; - case ash::mojom::WindowStateType::PIP: + case ash::WindowStateType::kPip: state_type = ZCR_REMOTE_SHELL_V1_STATE_TYPE_PIP; break; default: @@ -903,8 +903,8 @@ void HandleRemoteSurfaceBoundsChangedCallback( wl_resource* resource, - ash::mojom::WindowStateType current_state, - ash::mojom::WindowStateType requested_state, + ash::WindowStateType current_state, + ash::WindowStateType requested_state, int64_t display_id, const gfx::Rect& bounds, bool resize, @@ -920,9 +920,9 @@ // Override the reason only if the window enters snapped mode. If the window // resizes by dragging in snapped mode, we need to keep the original reason. if (requested_state != current_state) { - if (requested_state == ash::mojom::WindowStateType::LEFT_SNAPPED) { + if (requested_state == ash::WindowStateType::kLeftSnapped) { reason = ZCR_REMOTE_SURFACE_V1_BOUNDS_CHANGE_REASON_SNAP_TO_LEFT; - } else if (requested_state == ash::mojom::WindowStateType::RIGHT_SNAPPED) { + } else if (requested_state == ash::WindowStateType::kRightSnapped) { reason = ZCR_REMOTE_SURFACE_V1_BOUNDS_CHANGE_REASON_SNAP_TO_RIGHT; } }
diff --git a/components/exo/wayland/zxdg_shell.cc b/components/exo/wayland/zxdg_shell.cc index 26c1fdc7..2e61e69 100644 --- a/components/exo/wayland/zxdg_shell.cc +++ b/components/exo/wayland/zxdg_shell.cc
@@ -10,6 +10,7 @@ #include "ash/public/cpp/shell_window_ids.h" #include "ash/public/cpp/window_properties.h" +#include "ash/public/cpp/window_state_type.h" #include "base/bind.h" #include "base/strings/utf_string_conversions.h" #include "components/exo/display.h" @@ -274,7 +275,7 @@ using XdgSurfaceConfigureCallback = base::Callback<void(const gfx::Size& size, - ash::mojom::WindowStateType state_type, + ash::WindowStateType state_type, bool resizing, bool activated)>; @@ -282,7 +283,7 @@ wl_resource* resource, const XdgSurfaceConfigureCallback& callback, const gfx::Size& size, - ash::mojom::WindowStateType state_type, + ash::WindowStateType state_type, bool resizing, bool activated, const gfx::Vector2d& origin_offset) { @@ -401,14 +402,14 @@ } void OnConfigure(const gfx::Size& size, - ash::mojom::WindowStateType state_type, + ash::WindowStateType state_type, bool resizing, bool activated) { wl_array states; wl_array_init(&states); - if (state_type == ash::mojom::WindowStateType::MAXIMIZED) + if (state_type == ash::WindowStateType::kMaximized) AddState(&states, ZXDG_TOPLEVEL_V6_STATE_MAXIMIZED); - if (state_type == ash::mojom::WindowStateType::FULLSCREEN) + if (state_type == ash::WindowStateType::kFullscreen) AddState(&states, ZXDG_TOPLEVEL_V6_STATE_FULLSCREEN); if (resizing) AddState(&states, ZXDG_TOPLEVEL_V6_STATE_RESIZING); @@ -576,7 +577,7 @@ } void OnConfigure(const gfx::Size& size, - ash::mojom::WindowStateType state_type, + ash::WindowStateType state_type, bool resizing, bool activated) { // Nothing to do here as popups don't have additional configure state.
diff --git a/components/language/core/browser/language_prefs.cc b/components/language/core/browser/language_prefs.cc index 0c0bf016..1af1c453d 100644 --- a/components/language/core/browser/language_prefs.cc +++ b/components/language/core/browser/language_prefs.cc
@@ -99,11 +99,24 @@ base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL)) { language::ToTranslateLanguageSynonym(&language); languages.insert(std::move(language)); + + // crbug.com/958348: The default value for Accept-Language *should* be the + // same as the one for Fluent Languages. However, Accept-Language contains + // English (and more) in addition to the local language in most locales due + // to historical reasons. Exiting early from this loop is a temporary fix + // that allows Fluent Languages to be at least populated with the UI + // language while still allowing Translate to trigger on other languages, + // most importantly English. + // Once the change to remove English from Accept-Language defaults lands, + // this break should be removed to enable the Fluent Language List and the + // Accept-Language list to be initialized to the same values. + break; } #endif base::Value language_values(base::Value::Type::LIST); for (const std::string& language : languages) language_values.GetList().emplace_back(language); + return language_values; }
diff --git a/components/minidump_uploader/android/java/src/org/chromium/components/minidump_uploader/CrashFileManager.java b/components/minidump_uploader/android/java/src/org/chromium/components/minidump_uploader/CrashFileManager.java index 520c84f..3d97f19e 100644 --- a/components/minidump_uploader/android/java/src/org/chromium/components/minidump_uploader/CrashFileManager.java +++ b/components/minidump_uploader/android/java/src/org/chromium/components/minidump_uploader/CrashFileManager.java
@@ -20,6 +20,7 @@ import java.util.Comparator; import java.util.Date; import java.util.List; +import java.util.Map; import java.util.NoSuchElementException; import java.util.Scanner; import java.util.UUID; @@ -345,6 +346,22 @@ } /** + * Imports minidumps from Crashpad's database to the Crash Reports directory, converting them to + * MIME files and returning crash info as key-value pairs. + * + * @return a Map for crash report uuid to this crash info key-value pairs. + */ + public Map<String, Map<String, String>> importMinidumpsCrashKeys() { + File crashpadDir = getCrashpadDirectory(); + if (!crashpadDir.exists() || !ensureCrashDirExists()) { + return null; + } + File crashDir = getCrashDirectory(); + return CrashReportMimeWriter.rewriteMinidumpsAsMIMEsAndGetCrashKeys( + crashpadDir, crashDir); + } + + /** * Returns the most recent minidump without a logcat for a given pid, or null if no such * minidump exists. This method begins by reading all minidumps from Crashpad's database and * rewriting them as MIME files in the Crash Reports directory. @@ -360,8 +377,8 @@ * Returns all minidump files that definitely do not have logcat output, sorted by modification * time stamp. This method begins by reading all minidumps from Crashpad's database and * rewriting them as MIME files in the Crash Reports directory. Note: This method does not - * provide an "if and only if" test: it may return omit some files that lack logcat output, if - * logcat output has been intentionally skipped for those minidumps. However, any files returned + * provide an "if and only if" test: it may return some files that lack logcat output, if logcat + * output has been intentionally skipped for those minidumps. However, any files returned * definitely lack logcat output. */ public File[] getMinidumpsSansLogcat() { @@ -370,6 +387,17 @@ } /** + * Returns all minidump files currently in the Crash Reports directory that definitely do not + * have logcat output, sorted by modification time stamp. Note: This method does not provide an + * "if and only if" test: it may return some files that lack logcat output, if logcat outpuy has + * been intentionally skipped for those minidumps. However, any files returned definitely lack + * logcat output. + */ + public File[] getCurrentMinidumpsSansLogcat() { + return listCrashFiles(MINIDUMP_SANS_LOGCAT_PATTERN); + } + + /** * Returns all minidump files that could still be uploaded, sorted by modification time stamp. * Only returns files that we have tried to upload less than {@param maxTries} number of times. */
diff --git a/components/minidump_uploader/android/java/src/org/chromium/components/minidump_uploader/CrashReportMimeWriter.java b/components/minidump_uploader/android/java/src/org/chromium/components/minidump_uploader/CrashReportMimeWriter.java index 4ba197f..dec66fa 100644 --- a/components/minidump_uploader/android/java/src/org/chromium/components/minidump_uploader/CrashReportMimeWriter.java +++ b/components/minidump_uploader/android/java/src/org/chromium/components/minidump_uploader/CrashReportMimeWriter.java
@@ -7,6 +7,8 @@ import org.chromium.base.annotations.JNINamespace; import java.io.File; +import java.util.HashMap; +import java.util.Map; /** * Rewrites minidumps into MIME messages for uploading. @@ -15,6 +17,8 @@ public class CrashReportMimeWriter { private static final String TAG = "CrashReportMimeWriter"; + private static final String MINIDUMP_KEY = "upload_file_minidump"; + /* * Rewrites minidumps as MIME multipart messages, extracting embedded Crashpad annotations to * include as form data, and including the original minidump as a file attachment. @@ -26,5 +30,42 @@ nativeRewriteMinidumpsAsMIMEs(srcDir.getAbsolutePath(), destDir.getAbsolutePath()); } + /* + * Rewrites minidumps as MIME multipart messages with the embedded Crashpad annotations included + * as form data and the original minidump as a file attachment. The extracted Crashpad + * annotations for eached minidump file are returned as key-value pairs. + * + * @param srcDir A directory containing a crashpad::CrashReportDatabase. + * @param destDir The directory in which to write the MIME files. + * @return Crashpad annotations as key-value pairs mapped by crash file report UUID. + */ + public static Map<String, Map<String, String>> rewriteMinidumpsAsMIMEsAndGetCrashKeys( + File srcDir, File destDir) { + String[] crashesKeyValueArr = nativeRewriteMinidumpsAsMIMEsAndGetCrashKeys( + srcDir.getAbsolutePath(), destDir.getAbsolutePath()); + Map<String, Map<String, String>> crashesInfoMap = new HashMap<>(); + Map<String, String> lastCrashInfo = new HashMap<>(); + // Keys and values for all crash files are flattened in a String array. Each key is followed + // by its value. If the key is the reserved MINIDUMP_KEY, it marks the end of key-value + // pairs for a crash. + assert (crashesKeyValueArr.length % 2 == 0); + for (int i = 0; i < crashesKeyValueArr.length; i += 2) { + String key = crashesKeyValueArr[i]; + String value = crashesKeyValueArr[i + 1]; + // MINIDUMP_KEY is a reserved key with crash report uuid as value to be used to group + // key-value pairs for that specific crash. + if (key.equals(MINIDUMP_KEY)) { + crashesInfoMap.put(value, lastCrashInfo); + lastCrashInfo = new HashMap<>(); + } else { + lastCrashInfo.put(key, value); + } + } + + return crashesInfoMap; + } + private static native void nativeRewriteMinidumpsAsMIMEs(String srcDir, String destDir); + private static native String[] nativeRewriteMinidumpsAsMIMEsAndGetCrashKeys( + String srcDir, String destDir); }
diff --git a/components/minidump_uploader/rewrite_minidumps_as_mimes.cc b/components/minidump_uploader/rewrite_minidumps_as_mimes.cc index e28bac70..937ea77 100644 --- a/components/minidump_uploader/rewrite_minidumps_as_mimes.cc +++ b/components/minidump_uploader/rewrite_minidumps_as_mimes.cc
@@ -6,6 +6,7 @@ #include <utility> +#include "base/android/jni_array.h" #include "base/android/jni_string.h" #include "base/metrics/histogram_macros.h" #include "base/strings/stringprintf.h" @@ -36,31 +37,11 @@ }; #endif // OS_ANDROID -bool MimeifyReportAndWriteToDirectory( +bool MimeifyReportWithKeyValuePairs( const crashpad::CrashReportDatabase::UploadReport& report, - const base::FilePath& dest_dir) { - crashpad::HTTPMultipartBuilder builder; - pid_t pid; - if (!MimeifyReport(report, &builder, &pid)) { - return false; - } - - crashpad::FileWriter writer; - if (!writer.Open(dest_dir.Append(base::StringPrintf( - "%s.dmp%d", report.uuid.ToString().c_str(), pid)), - crashpad::FileWriteMode::kCreateOrFail, - crashpad::FilePermissions::kOwnerOnly)) { - return false; - } - - return WriteBodyToFile(builder.GetBodyStream().get(), &writer); -} - -} // namespace - -bool MimeifyReport(const crashpad::CrashReportDatabase::UploadReport& report, - crashpad::HTTPMultipartBuilder* http_multipart_builder, - pid_t* pid) { + crashpad::HTTPMultipartBuilder* http_multipart_builder, + std::vector<std::string>* crashes_key_value_arr, + pid_t* pid) { crashpad::FileReader* reader = report.Reader(); crashpad::FileOffset start_offset = reader->SeekGet(); if (start_offset < 0) { @@ -91,6 +72,10 @@ << kv.second; } else { http_multipart_builder->SetFormData(kv.first, kv.second); + if (crashes_key_value_arr) { + crashes_key_value_arr->push_back(kv.first); + crashes_key_value_arr->push_back(kv.second); + } #if defined(OS_ANDROID) if (kv.first == kPtypeKey) { const crashpad::ExceptionSnapshot* exception = @@ -124,6 +109,11 @@ } } + if (crashes_key_value_arr) { + crashes_key_value_arr->push_back(kMinidumpKey); + crashes_key_value_arr->push_back(report.uuid.ToString().c_str()); + } + http_multipart_builder->SetFileAttachment(kMinidumpKey, report.uuid.ToString() + ".dmp", reader, "application/octet-stream"); @@ -132,6 +122,37 @@ return true; } +bool MimeifyReportAndWriteToDirectory( + const crashpad::CrashReportDatabase::UploadReport& report, + const base::FilePath& dest_dir, + std::vector<std::string>* crashes_key_value_arr) { + crashpad::HTTPMultipartBuilder builder; + pid_t pid; + if (!MimeifyReportWithKeyValuePairs(report, &builder, crashes_key_value_arr, + &pid)) { + return false; + } + + crashpad::FileWriter writer; + if (!writer.Open(dest_dir.Append(base::StringPrintf( + "%s.dmp%d", report.uuid.ToString().c_str(), pid)), + crashpad::FileWriteMode::kCreateOrFail, + crashpad::FilePermissions::kOwnerOnly)) { + return false; + } + + return WriteBodyToFile(builder.GetBodyStream().get(), &writer); +} + +} // namespace + +bool MimeifyReport(const crashpad::CrashReportDatabase::UploadReport& report, + crashpad::HTTPMultipartBuilder* http_multipart_builder, + pid_t* pid) { + return MimeifyReportWithKeyValuePairs(report, http_multipart_builder, nullptr, + pid); +} + bool WriteBodyToFile(crashpad::HTTPBodyStream* body, crashpad::FileWriterInterface* writer) { uint8_t buffer[4096]; @@ -143,7 +164,8 @@ } void RewriteMinidumpsAsMIMEs(const base::FilePath& src_dir, - const base::FilePath& dest_dir) { + const base::FilePath& dest_dir, + std::vector<std::string>* crashes_key_value_arr) { std::unique_ptr<crashpad::CrashReportDatabase> db = crashpad::CrashReportDatabase::InitializeWithoutCreating(src_dir); if (!db) { @@ -167,7 +189,8 @@ continue; case crashpad::CrashReportDatabase::kNoError: - if (MimeifyReportAndWriteToDirectory(*upload_report.get(), dest_dir)) { + if (MimeifyReportAndWriteToDirectory(*upload_report.get(), dest_dir, + crashes_key_value_arr)) { db->RecordUploadComplete(std::move(upload_report), std::string()); } else { crashpad::Metrics::CrashUploadSkipped( @@ -200,7 +223,24 @@ base::android::ConvertJavaStringToUTF8(env, j_src_dir, &src_dir); base::android::ConvertJavaStringToUTF8(env, j_dest_dir, &dest_dir); - RewriteMinidumpsAsMIMEs(base::FilePath(src_dir), base::FilePath(dest_dir)); + RewriteMinidumpsAsMIMEs(base::FilePath(src_dir), base::FilePath(dest_dir), + nullptr); +} + +static base::android::ScopedJavaLocalRef<jobjectArray> +JNI_CrashReportMimeWriter_RewriteMinidumpsAsMIMEsAndGetCrashKeys( + JNIEnv* env, + const base::android::JavaParamRef<jstring>& j_src_dir, + const base::android::JavaParamRef<jstring>& j_dest_dir) { + std::string src_dir, dest_dir; + base::android::ConvertJavaStringToUTF8(env, j_src_dir, &src_dir); + base::android::ConvertJavaStringToUTF8(env, j_dest_dir, &dest_dir); + + std::vector<std::string> key_value_arr; + RewriteMinidumpsAsMIMEs(base::FilePath(src_dir), base::FilePath(dest_dir), + &key_value_arr); + + return base::android::ToJavaArrayOfStrings(env, key_value_arr); } } // namespace minidump_uploader
diff --git a/components/omnibox/common/omnibox_features.cc b/components/omnibox/common/omnibox_features.cc index 53318476..1243c0e 100644 --- a/components/omnibox/common/omnibox_features.cc +++ b/components/omnibox/common/omnibox_features.cc
@@ -206,8 +206,9 @@ const base::Feature kQueryInOmnibox{"QueryInOmnibox", base::FEATURE_DISABLED_BY_DEFAULT}; -// Feature used for showing the URL suggestion favicons as a UI experiment, -// currently only used on desktop platforms. +// Feature used for showing the URL suggestion favicons as a UI experiment. +// Already launched on Desktop, and currently under development on Android. +// This flag is not used on iOS. const base::Feature kUIExperimentShowSuggestionFavicons{ "OmniboxUIExperimentShowSuggestionFavicons", #if defined(OS_ANDROID)
diff --git a/components/payments/content/payment_request.cc b/components/payments/content/payment_request.cc index 37d877f..a1129cd 100644 --- a/components/payments/content/payment_request.cc +++ b/components/payments/content/payment_request.cc
@@ -23,6 +23,7 @@ #include "components/payments/core/payment_details_validation.h" #include "components/payments/core/payment_instrument.h" #include "components/payments/core/payment_prefs.h" +#include "components/payments/core/payments_experimental_features.h" #include "components/payments/core/payments_validators.h" #include "components/prefs/pref_service.h" #include "components/ukm/content/source_url_recorder.h" @@ -595,6 +596,15 @@ void PaymentRequest::OnShippingAddressSelected( mojom::PaymentAddressPtr address) { + // Redact shipping address before exposing it in ShippingAddressChangeEvent. + // https://w3c.github.io/payment-request/#shipping-address-changed-algorithm + if (PaymentsExperimentalFeatures::IsEnabled( + features::kWebPaymentsRedactShippingAddress)) { + address->organization.clear(); + address->phone.clear(); + address->recipient.clear(); + address->address_line.clear(); + } client_->OnShippingAddressChange(std::move(address)); }
diff --git a/components/payments/content/payment_request_state.cc b/components/payments/content/payment_request_state.cc index 26f8b78..0f5d84ac 100644 --- a/components/payments/content/payment_request_state.cc +++ b/components/payments/content/payment_request_state.cc
@@ -22,7 +22,6 @@ #include "components/payments/content/service_worker_payment_instrument.h" #include "components/payments/core/autofill_payment_instrument.h" #include "components/payments/core/features.h" -#include "components/payments/core/journey_logger.h" #include "components/payments/core/payment_instrument.h" #include "components/payments/core/payment_request_data_util.h" #include "content/public/common/content_features.h" @@ -359,8 +358,10 @@ shipping_profiles_, app_locale_, payment_request_delegate_); available_instruments_.push_back(std::move(instrument)); - if (selected) - SetSelectedInstrument(available_instruments_.back().get()); + if (selected) { + SetSelectedInstrument(available_instruments_.back().get(), + SectionSelectionStatus::kAddedSelected); + } } void PaymentRequestState::AddAutofillShippingProfile( @@ -373,8 +374,10 @@ autofill::AutofillProfile* new_cached_profile = profile_cache_.back().get(); shipping_profiles_.push_back(new_cached_profile); - if (selected) - SetSelectedShippingProfile(new_cached_profile); + if (selected) { + SetSelectedShippingProfile(new_cached_profile, + SectionSelectionStatus::kAddedSelected); + } } void PaymentRequestState::AddAutofillContactProfile( @@ -385,8 +388,10 @@ autofill::AutofillProfile* new_cached_profile = profile_cache_.back().get(); contact_profiles_.push_back(new_cached_profile); - if (selected) - SetSelectedContactProfile(new_cached_profile); + if (selected) { + SetSelectedContactProfile(new_cached_profile, + SectionSelectionStatus::kAddedSelected); + } } void PaymentRequestState::SetSelectedShippingOption( @@ -399,7 +404,8 @@ } void PaymentRequestState::SetSelectedShippingProfile( - autofill::AutofillProfile* profile) { + autofill::AutofillProfile* profile, + SectionSelectionStatus selection_status) { spec_->StartWaitingForUpdateWith( PaymentRequestSpec::UpdateReason::SHIPPING_ADDRESS); selected_shipping_profile_ = profile; @@ -417,10 +423,13 @@ *selected_shipping_profile_, /*timeout_seconds=*/2, base::BindOnce(&PaymentRequestState::OnAddressNormalized, weak_ptr_factory_.GetWeakPtr())); + IncrementSelectionStatus(JourneyLogger::Section::SECTION_SHIPPING_ADDRESS, + selection_status); } void PaymentRequestState::SetSelectedContactProfile( - autofill::AutofillProfile* profile) { + autofill::AutofillProfile* profile, + SectionSelectionStatus selection_status) { selected_contact_profile_ = profile; // Changing the contact information clears contact information validation @@ -433,11 +442,35 @@ delegate_->OnPayerInfoSelected( response_helper_->GeneratePayerDetail(profile)); } + IncrementSelectionStatus(JourneyLogger::Section::SECTION_CONTACT_INFO, + selection_status); } -void PaymentRequestState::SetSelectedInstrument(PaymentInstrument* instrument) { +void PaymentRequestState::SetSelectedInstrument( + PaymentInstrument* instrument, + SectionSelectionStatus selection_status) { selected_instrument_ = instrument; UpdateIsReadyToPayAndNotifyObservers(); + IncrementSelectionStatus(JourneyLogger::Section::SECTION_PAYMENT_METHOD, + selection_status); +} + +void PaymentRequestState::IncrementSelectionStatus( + JourneyLogger::Section section, + SectionSelectionStatus selection_status) { + switch (selection_status) { + case SectionSelectionStatus::kSelected: + journey_logger_->IncrementSelectionChanges(section); + break; + case SectionSelectionStatus::kEditedSelected: + journey_logger_->IncrementSelectionEdits(section); + break; + case SectionSelectionStatus::kAddedSelected: + journey_logger_->IncrementSelectionAdds(section); + break; + default: + NOTREACHED(); + } } const std::string& PaymentRequestState::GetApplicationLocale() {
diff --git a/components/payments/content/payment_request_state.h b/components/payments/content/payment_request_state.h index 75aaec2..517a6679 100644 --- a/components/payments/content/payment_request_state.h +++ b/components/payments/content/payment_request_state.h
@@ -16,6 +16,7 @@ #include "components/payments/content/payment_request_spec.h" #include "components/payments/content/payment_response_helper.h" #include "components/payments/content/service_worker_payment_app_factory.h" +#include "components/payments/core/journey_logger.h" #include "components/payments/core/payments_profile_comparator.h" #include "content/public/browser/payment_app_provider.h" #include "content/public/browser/web_contents.h" @@ -31,7 +32,6 @@ namespace payments { class ContentPaymentRequestDelegate; -class JourneyLogger; class PaymentInstrument; class ServiceWorkerPaymentInstrument; @@ -80,6 +80,24 @@ virtual ~Delegate() {} }; + // Shows the status of the selected section. For example if the user changes + // the shipping address section from A to B then the SectionSelectionStatus + // will be kSelected. If the user edits an item like B from the shipping + // address section before selecting it, then the SectionSelectionStatus will + // be kEditedSelected. Finally if the user decides to add a new item like C to + // the shipping address section, then the SectionSelectionStatus will be + // kAddedSelected. IncrementSelectionStatus uses SectionSelectionStatus to log + // the number of times that the user has decided to change, edit, or add the + // selected item in any of the sections during payment process. + enum class SectionSelectionStatus { + // The newly selected section is neither edited nor added. + kSelected = 1, + // The newly selected section is edited before selection. + kEditedSelected = 2, + // The newly selected section is added before selection. + kAddedSelected = 3, + }; + using StatusCallback = base::OnceCallback<void(bool)>; PaymentRequestState(content::WebContents* web_contents, @@ -193,9 +211,12 @@ // Setters to change the selected information. Will have the side effect of // recomputing "is ready to pay" and notify observers. void SetSelectedShippingOption(const std::string& shipping_option_id); - void SetSelectedShippingProfile(autofill::AutofillProfile* profile); - void SetSelectedContactProfile(autofill::AutofillProfile* profile); - void SetSelectedInstrument(PaymentInstrument* instrument); + void SetSelectedShippingProfile(autofill::AutofillProfile* profile, + SectionSelectionStatus selection_status); + void SetSelectedContactProfile(autofill::AutofillProfile* profile, + SectionSelectionStatus selection_status); + void SetSelectedInstrument(PaymentInstrument* instrument, + SectionSelectionStatus selection_status); bool is_ready_to_pay() { return is_ready_to_pay_; } @@ -292,6 +313,9 @@ void OnAddressNormalized(bool success, const autofill::AutofillProfile& normalized_profile); + void IncrementSelectionStatus(JourneyLogger::Section section, + SectionSelectionStatus selection_status); + bool is_ready_to_pay_; bool get_all_instruments_finished_;
diff --git a/components/payments/content/payment_request_state_unittest.cc b/components/payments/content/payment_request_state_unittest.cc index 99c24be..fb02a9e 100644 --- a/components/payments/content/payment_request_state_unittest.cc +++ b/components/payments/content/payment_request_state_unittest.cc
@@ -351,7 +351,8 @@ // Therefore we are not ready to pay. EXPECT_FALSE(state()->is_ready_to_pay()); - state()->SetSelectedShippingProfile(test_address()); + state()->SetSelectedShippingProfile( + test_address(), PaymentRequestState::SectionSelectionStatus::kSelected); EXPECT_EQ(0, num_on_selected_information_changed_called()); // Simulate that the merchant has validated the shipping address change. @@ -396,12 +397,14 @@ EXPECT_TRUE(state()->is_ready_to_pay()); // Unselecting contact profile. - state()->SetSelectedContactProfile(nullptr); + state()->SetSelectedContactProfile( + nullptr, PaymentRequestState::SectionSelectionStatus::kSelected); EXPECT_EQ(1, num_on_selected_information_changed_called()); EXPECT_FALSE(state()->is_ready_to_pay()); - state()->SetSelectedContactProfile(test_address()); + state()->SetSelectedContactProfile( + test_address(), PaymentRequestState::SectionSelectionStatus::kSelected); EXPECT_EQ(2, num_on_selected_information_changed_called()); // Ready to pay! @@ -422,7 +425,8 @@ // Select an address, nothing should happen until the normalization is // completed and the merchant has validated the address. - state()->SetSelectedShippingProfile(test_address()); + state()->SetSelectedShippingProfile( + test_address(), PaymentRequestState::SectionSelectionStatus::kSelected); EXPECT_EQ(0, num_on_selected_information_changed_called()); EXPECT_FALSE(state()->is_ready_to_pay()); @@ -474,7 +478,8 @@ "Roppongi", "6 Chrome-10-1", "Tokyo", "", "106-6126", "JP", "+81363849000"); - state()->SetSelectedShippingProfile(&profile); + state()->SetSelectedShippingProfile( + &profile, PaymentRequestState::SectionSelectionStatus::kSelected); EXPECT_EQ(0, num_on_selected_information_changed_called()); EXPECT_FALSE(state()->is_ready_to_pay()); @@ -514,7 +519,8 @@ // Therefore we are not ready to pay. EXPECT_FALSE(state()->is_ready_to_pay()); - state()->SetSelectedShippingProfile(test_address()); + state()->SetSelectedShippingProfile( + test_address(), PaymentRequestState::SectionSelectionStatus::kSelected); EXPECT_EQ(0, num_on_selected_information_changed_called()); // Simulate that the merchant has validated the shipping address change. @@ -557,7 +563,8 @@ options->request_payer_email = true; RecreateStateWithOptions(std::move(options)); - state()->SetSelectedContactProfile(test_address()); + state()->SetSelectedContactProfile( + test_address(), PaymentRequestState::SectionSelectionStatus::kSelected); EXPECT_EQ(1, num_on_selected_information_changed_called()); EXPECT_TRUE(state()->is_ready_to_pay());
diff --git a/components/payments/core/BUILD.gn b/components/payments/core/BUILD.gn index 4b7c062f..2f74b864 100644 --- a/components/payments/core/BUILD.gn +++ b/components/payments/core/BUILD.gn
@@ -51,6 +51,8 @@ "payment_response.h", "payment_shipping_option.cc", "payment_shipping_option.h", + "payments_experimental_features.cc", + "payments_experimental_features.h", "payments_profile_comparator.cc", "payments_profile_comparator.h", "payments_validators.cc",
diff --git a/components/payments/core/features.cc b/components/payments/core/features.cc index e96ce47..d588efb 100644 --- a/components/payments/core/features.cc +++ b/components/payments/core/features.cc
@@ -7,6 +7,9 @@ namespace payments { namespace features { +const base::Feature kWebPaymentsExperimentalFeatures{ + "WebPaymentsExperimentalFeatures", base::FEATURE_DISABLED_BY_DEFAULT}; + const base::Feature kReturnGooglePayInBasicCard{ "ReturnGooglePayInBasicCard", base::FEATURE_DISABLED_BY_DEFAULT}; @@ -35,5 +38,8 @@ "WebPaymentsPerMethodCanMakePaymentQuota", base::FEATURE_DISABLED_BY_DEFAULT}; +const base::Feature kWebPaymentsRedactShippingAddress{ + "WebPaymentsRedactShippingAddress", base::FEATURE_DISABLED_BY_DEFAULT}; + } // namespace features } // namespace payments
diff --git a/components/payments/core/features.h b/components/payments/core/features.h index 138db67..f728663 100644 --- a/components/payments/core/features.h +++ b/components/payments/core/features.h
@@ -11,6 +11,10 @@ namespace payments { namespace features { +// Master toggle for all experimental features that will ship in the next +// release. +extern const base::Feature kWebPaymentsExperimentalFeatures; + // Used to control whether Google Pay cards are returned for basic-card. extern const base::Feature kReturnGooglePayInBasicCard; @@ -37,6 +41,10 @@ // Used to control whether canMakePayment() quota is per-method. extern const base::Feature kWebPaymentsPerMethodCanMakePaymentQuota; +// Used to control whether the shipping address returned for the +// ShippingAddressChangeEvent is redacted of fine-grained details. +extern const base::Feature kWebPaymentsRedactShippingAddress; + } // namespace features } // namespace payments
diff --git a/components/payments/core/payments_experimental_features.cc b/components/payments/core/payments_experimental_features.cc new file mode 100644 index 0000000..c8cde08 --- /dev/null +++ b/components/payments/core/payments_experimental_features.cc
@@ -0,0 +1,19 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/payments/core/payments_experimental_features.h" + +#include "base/feature_list.h" +#include "components/payments/core/features.h" + +namespace payments { + +// static +bool PaymentsExperimentalFeatures::IsEnabled(const base::Feature& feature) { + return base::FeatureList::IsEnabled( + features::kWebPaymentsExperimentalFeatures) || + base::FeatureList::IsEnabled(feature); +} + +} // namespace payments
diff --git a/components/payments/core/payments_experimental_features.h b/components/payments/core/payments_experimental_features.h new file mode 100644 index 0000000..6335809d --- /dev/null +++ b/components/payments/core/payments_experimental_features.h
@@ -0,0 +1,29 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_PAYMENTS_CORE_PAYMENTS_EXPERIMENTAL_FEATURES_H_ +#define COMPONENTS_PAYMENTS_CORE_PAYMENTS_EXPERIMENTAL_FEATURES_H_ + +#include "base/macros.h" + +namespace base { +struct Feature; +} // namespace base + +namespace payments { + +class PaymentsExperimentalFeatures { + public: + // Utility wrapper around base::FeatureList::IsEnabled(). Returns true if + // either |feature| or payments::features::kWebPaymentsExperimentalFeatures is + // enabled. + static bool IsEnabled(const base::Feature& feature); + + private: + DISALLOW_IMPLICIT_CONSTRUCTORS(PaymentsExperimentalFeatures); +}; + +} // namespace payments + +#endif // COMPONENTS_PAYMENTS_CORE_PAYMENTS_EXPERIMENTAL_FEATURES_H_
diff --git a/components/policy/resources/policy_templates.json b/components/policy/resources/policy_templates.json index 3c474ed..6d6e5f1 100644 --- a/components/policy/resources/policy_templates.json +++ b/components/policy/resources/policy_templates.json
@@ -12559,7 +12559,7 @@ 'name': 'CloudPolicyOverridesPlatformPolicy', 'type': 'main', 'schema': { 'type': 'boolean'}, - 'supported_on': ['chrome.*:65-'], + 'supported_on': ['chrome.*:75-'], 'features': { 'dynamic_refresh': False, 'per_profile': False,
diff --git a/components/previews/content/hint_cache_store.cc b/components/previews/content/hint_cache_store.cc index e23c8e7..72cce19 100644 --- a/components/previews/content/hint_cache_store.cc +++ b/components/previews/content/hint_cache_store.cc
@@ -650,9 +650,18 @@ // If the hint exists, release it into the Hint unique_ptr contained in the // callback. This eliminates the need for any copies of the entry's hint. - std::unique_ptr<optimization_guide::proto::Hint> loaded_hint( - entry && entry->has_hint() ? entry->release_hint() : nullptr); - std::move(callback).Run(entry_key, std::move(loaded_hint)); + if (entry && entry->has_hint()) { + std::unique_ptr<optimization_guide::proto::Hint> loaded_hint( + entry->release_hint()); + UMA_HISTOGRAM_ENUMERATION( + "Previews.OptimizationGuide.HintCache.HintType.Loaded", + static_cast<StoreEntryType>(entry->entry_type())); + std::move(callback).Run(entry_key, std::move(loaded_hint)); + + } else { + std::unique_ptr<optimization_guide::proto::Hint> loaded_hint(nullptr); + std::move(callback).Run(entry_key, std::move(loaded_hint)); + } } } // namespace previews
diff --git a/components/previews/content/hint_cache_store.h b/components/previews/content/hint_cache_store.h index cf0b54c..4523aaf 100644 --- a/components/previews/content/hint_cache_store.h +++ b/components/previews/content/hint_cache_store.h
@@ -78,6 +78,8 @@ // ==> "2_55_foo.com" // NOTE: The order and value of the existing store entry types within the enum // cannot be changed, but new types can be added to the end. + // StoreEntryType should remain synchronized with the + // HintCacheStoreEntryType in enums.xml. enum class StoreEntryType { kEmpty = 0, kMetadata = 1,
diff --git a/components/previews/core/previews_features.cc b/components/previews/core/previews_features.cc index c2ff5467..027c1db 100644 --- a/components/previews/core/previews_features.cc +++ b/components/previews/core/previews_features.cc
@@ -95,10 +95,6 @@ const base::Feature kHTTPSServerPreviewsUsingURLLoader{ "HTTPSServerPreviewsUsingURLLoader", base::FEATURE_DISABLED_BY_DEFAULT}; -// Uses 'Lite Mode' strings instead of 'Data Saver'. -const base::Feature kDataSaverLiteModeRebranding{ - "DataSaverLiteModeRebranding", base::FEATURE_ENABLED_BY_DEFAULT}; - // When enabled, reloading on a preview will cause the session (5 minute) rule // to trigger. const base::Feature kPreviewsReloadsAreSoftOptOuts{
diff --git a/components/previews/core/previews_features.h b/components/previews/core/previews_features.h index 6b4c3e8..1f889bb 100644 --- a/components/previews/core/previews_features.h +++ b/components/previews/core/previews_features.h
@@ -23,7 +23,6 @@ extern const base::Feature kAndroidOmniboxPreviewsBadge; extern const base::Feature kSlowPageTriggering; extern const base::Feature kHTTPSServerPreviewsUsingURLLoader; -extern const base::Feature kDataSaverLiteModeRebranding; extern const base::Feature kPreviewsReloadsAreSoftOptOuts; extern const base::Feature kOptimizationHintsFetching; extern const base::Feature kOfflinePreviewsFalsePositivePrevention;
diff --git a/components/send_tab_to_self/send_tab_to_self_bridge.cc b/components/send_tab_to_self/send_tab_to_self_bridge.cc index 1cb0c73e..842baf3 100644 --- a/components/send_tab_to_self/send_tab_to_self_bridge.cc +++ b/components/send_tab_to_self/send_tab_to_self_bridge.cc
@@ -556,8 +556,7 @@ return target_device_name_to_cache_info_.empty() || device_info_tracker_->GetAllDeviceInfo().size() != number_of_devices_ || - clock_->Now() - change_processor()->GetEntityModificationTime( - oldest_device_cache_guid_) > + clock_->Now() - oldest_non_expired_device_timestamp_ > kDeviceExpiration; } @@ -567,23 +566,21 @@ number_of_devices_ = all_devices.size(); // Sort the DeviceInfo vector so the most recenly modified devices are first. - const syncer::ModelTypeChangeProcessor* change_processor_ptr = - change_processor(); - std::stable_sort( - all_devices.begin(), all_devices.end(), - [change_processor_ptr]( - const std::unique_ptr<syncer::DeviceInfo>& device1, - const std::unique_ptr<syncer::DeviceInfo>& device2) { - return change_processor_ptr->GetEntityModificationTime( - device1->guid()) > - change_processor_ptr->GetEntityModificationTime(device2->guid()); - }); + std::stable_sort(all_devices.begin(), all_devices.end(), + [](const std::unique_ptr<syncer::DeviceInfo>& device1, + const std::unique_ptr<syncer::DeviceInfo>& device2) { + return device1->last_updated_timestamp() > + device2->last_updated_timestamp(); + }); target_device_name_to_cache_info_.clear(); for (const auto& device : all_devices) { - // TODO(crbug/959487) If the current device is considered expired for our - // purposes, stop here since the next devices in the vector are at least - // as expired than this one. + // If the current device is considered expired for our purposes, stop here + // since the next devices in the vector are at least as expired than this + // one. + if (clock_->Now() - device->last_updated_timestamp() > kDeviceExpiration) { + break; + } // TODO(crbug.com/957716): Dedupe older versions of this device as well. // Don't include this device. @@ -602,7 +599,7 @@ TargetDeviceInfo target_device_info(device->guid(), device->device_type()); target_device_name_to_cache_info_.emplace(device->client_name(), target_device_info); - oldest_device_cache_guid_ = device->guid(); + oldest_non_expired_device_timestamp_ = device->last_updated_timestamp(); } }
diff --git a/components/send_tab_to_self/send_tab_to_self_bridge.h b/components/send_tab_to_self/send_tab_to_self_bridge.h index 63235ff..c99353be 100644 --- a/components/send_tab_to_self/send_tab_to_self_bridge.h +++ b/components/send_tab_to_self/send_tab_to_self_bridge.h
@@ -170,7 +170,7 @@ // The following two variables are used to determine whether we should update // the target device name to cache guid map. - std::string oldest_device_cache_guid_ = ""; + base::Time oldest_non_expired_device_timestamp_; size_t number_of_devices_ = 0; base::WeakPtrFactory<SendTabToSelfBridge> weak_ptr_factory_;
diff --git a/components/send_tab_to_self/send_tab_to_self_bridge_unittest.cc b/components/send_tab_to_self/send_tab_to_self_bridge_unittest.cc index 66ef5214..43c7741a 100644 --- a/components/send_tab_to_self/send_tab_to_self_bridge_unittest.cc +++ b/components/send_tab_to_self/send_tab_to_self_bridge_unittest.cc
@@ -94,6 +94,7 @@ device_info.guid(), device_info.client_name(), device_info.chrome_version(), device_info.sync_user_agent(), device_info.device_type(), device_info.signin_scoped_device_id(), + device_info.last_updated_timestamp(), device_info.send_tab_to_self_receiving_enabled()); } @@ -676,32 +677,26 @@ InitializeBridge(); // Create multiple DeviceInfo objects with the same name but different guids. - syncer::DeviceInfo device1(kOldGuid, "device_name", "72", "agent", - sync_pb::SyncEnums_DeviceType_TYPE_LINUX, - "scoped_is", - /*send_tab_to_self_receiving_enabled=*/true); - AddTestDevice(&device1); + syncer::DeviceInfo recent_device( + kRecentGuid, "device_name", "72", "agent", + sync_pb::SyncEnums_DeviceType_TYPE_LINUX, "scoped_is", + clock()->Now() - base::TimeDelta::FromDays(1), + /*send_tab_to_self_receiving_enabled=*/true); + AddTestDevice(&recent_device); - syncer::DeviceInfo device2(kRecentGuid, "device_name", "72", "agent", - sync_pb::SyncEnums_DeviceType_TYPE_LINUX, - "scoped_is", - /*send_tab_to_self_receiving_enabled=*/true); - AddTestDevice(&device2); + syncer::DeviceInfo old_device( + kOldGuid, "device_name", "72", "agent", + sync_pb::SyncEnums_DeviceType_TYPE_LINUX, "scoped_is", + /*last_updated_timestamp=*/clock()->Now() - base::TimeDelta::FromDays(3), + /*send_tab_to_self_receiving_enabled=*/true); + AddTestDevice(&old_device); - syncer::DeviceInfo device3(kOlderGuid, "device_name", "72", "agent", - sync_pb::SyncEnums_DeviceType_TYPE_LINUX, - "scoped_is", - /*send_tab_to_self_receiving_enabled=*/true); - AddTestDevice(&device3); - - // Make sure the device with cache id "recent_guid" was modified more - // recently. - ON_CALL(*processor(), GetEntityModificationTime(kRecentGuid)) - .WillByDefault(Return(clock()->Now() - base::TimeDelta::FromDays(1))); - ON_CALL(*processor(), GetEntityModificationTime(kOldGuid)) - .WillByDefault(Return(clock()->Now() - base::TimeDelta::FromDays(3))); - ON_CALL(*processor(), GetEntityModificationTime(kOlderGuid)) - .WillByDefault(Return(clock()->Now() - base::TimeDelta::FromDays(5))); + syncer::DeviceInfo older_device( + kOlderGuid, "device_name", "72", "agent", + sync_pb::SyncEnums_DeviceType_TYPE_LINUX, "scoped_is", + /*last_updated_timestamp=*/clock()->Now() - base::TimeDelta::FromDays(5), + /*send_tab_to_self_receiving_enabled=*/true); + AddTestDevice(&older_device); TargetDeviceInfo target_device_info(kRecentGuid, sync_pb::SyncEnums_DeviceType_TYPE_LINUX); @@ -719,21 +714,17 @@ syncer::DeviceInfo enabled_device( "enabled_guid", "enabled_device_name", "72", "agent", sync_pb::SyncEnums_DeviceType_TYPE_LINUX, "scoped_is", + /*last_updated_timestamp=*/clock()->Now(), /*send_tab_to_self_receiving_enabled=*/true); AddTestDevice(&enabled_device); syncer::DeviceInfo disabled_device( "disabled_guid", "disabled_device_name", "72", "agent", sync_pb::SyncEnums_DeviceType_TYPE_LINUX, "scoped_is", + /*last_updated_timestamp=*/clock()->Now(), /*send_tab_to_self_receiving_enabled=*/false); AddTestDevice(&disabled_device); - // Make sure the devices were used recently. - ON_CALL(*processor(), GetEntityModificationTime("enabled_guid")) - .WillByDefault(Return(clock()->Now() - base::TimeDelta::FromDays(1))); - ON_CALL(*processor(), GetEntityModificationTime("disabled_guid")) - .WillByDefault(Return(clock()->Now() - base::TimeDelta::FromDays(1))); - TargetDeviceInfo target_device_info("enabled_guid", sync_pb::SyncEnums_DeviceType_TYPE_LINUX); @@ -750,21 +741,17 @@ syncer::DeviceInfo expired_device( "expired_guid", "expired_device_name", "72", "agent", sync_pb::SyncEnums_DeviceType_TYPE_LINUX, "scoped_is", + /*last_updated_timestamp=*/clock()->Now() - base::TimeDelta::FromDays(11), /*send_tab_to_self_receiving_enabled=*/true); AddTestDevice(&expired_device); syncer::DeviceInfo valid_device( "valid_guid", "valid_device_name", "72", "agent", sync_pb::SyncEnums_DeviceType_TYPE_LINUX, "scoped_is", + /*last_updated_timestamp=*/clock()->Now() - base::TimeDelta::FromDays(1), /*send_tab_to_self_receiving_enabled=*/true); AddTestDevice(&valid_device); - // Set one device to be expired and the other to be valid. - ON_CALL(*processor(), GetEntityModificationTime("expired_guid")) - .WillByDefault(Return(clock()->Now() - base::TimeDelta::FromDays(11))); - ON_CALL(*processor(), GetEntityModificationTime("valid_guid")) - .WillByDefault(Return(clock()->Now() - base::TimeDelta::FromDays(1))); - TargetDeviceInfo target_device_info("valid_guid", sync_pb::SyncEnums_DeviceType_TYPE_LINUX); @@ -780,21 +767,17 @@ syncer::DeviceInfo local_device( kLocalDeviceCacheGuid, "local_device_name", "72", "agent", sync_pb::SyncEnums_DeviceType_TYPE_LINUX, "scoped_is", + /*last_updated_timestamp=*/clock()->Now(), /*send_tab_to_self_receiving_enabled=*/true); AddTestDevice(&local_device); syncer::DeviceInfo other_device( "other_guid", "other_device_name", "72", "agent", sync_pb::SyncEnums_DeviceType_TYPE_LINUX, "scoped_is", + /*last_updated_timestamp=*/clock()->Now(), /*send_tab_to_self_receiving_enabled=*/true); AddTestDevice(&other_device); - // Set both device to not be expired. - ON_CALL(*processor(), GetEntityModificationTime(kLocalDeviceCacheGuid)) - .WillByDefault(Return(clock()->Now() - base::TimeDelta::FromDays(1))); - ON_CALL(*processor(), GetEntityModificationTime("other_guid")) - .WillByDefault(Return(clock()->Now() - base::TimeDelta::FromDays(1))); - TargetDeviceInfo target_device_info("other_guid", sync_pb::SyncEnums_DeviceType_TYPE_LINUX); @@ -809,24 +792,20 @@ InitializeBridge(); // Set a device that is about to expire and a more recent device. - syncer::DeviceInfo older_device("older_guid", "older_name", "72", "agent", - sync_pb::SyncEnums_DeviceType_TYPE_LINUX, - "scoped_is", - /*send_tab_to_self_receiving_enabled=*/true); + syncer::DeviceInfo older_device( + "older_guid", "older_name", "72", "agent", + sync_pb::SyncEnums_DeviceType_TYPE_LINUX, "scoped_is", + /*last_updated_timestamp=*/clock()->Now() - base::TimeDelta::FromDays(9), + /*send_tab_to_self_receiving_enabled=*/true); AddTestDevice(&older_device); - syncer::DeviceInfo recent_device("recent_guid", "recent_name", "72", "agent", - sync_pb::SyncEnums_DeviceType_TYPE_LINUX, - "scoped_is", - /*send_tab_to_self_receiving_enabled=*/true); + syncer::DeviceInfo recent_device( + "recent_guid", "recent_name", "72", "agent", + sync_pb::SyncEnums_DeviceType_TYPE_LINUX, "scoped_is", + /*last_updated_timestamp=*/clock()->Now() - base::TimeDelta::FromDays(1), + /*send_tab_to_self_receiving_enabled=*/true); AddTestDevice(&recent_device); - // Set both device to not be expired. - ON_CALL(*processor(), GetEntityModificationTime("older_guid")) - .WillByDefault(Return(clock()->Now() - base::TimeDelta::FromDays(9))); - ON_CALL(*processor(), GetEntityModificationTime("recent_guid")) - .WillByDefault(Return(clock()->Now() - base::TimeDelta::FromDays(1))); - TargetDeviceInfo device_info_1("older_guid", sync_pb::SyncEnums_DeviceType_TYPE_LINUX); TargetDeviceInfo device_info_2("recent_guid", @@ -851,13 +830,11 @@ InitializeBridge(); // Set a valid device. - syncer::DeviceInfo device("guid", "name", "72", "agent", - sync_pb::SyncEnums_DeviceType_TYPE_LINUX, - "scoped_is", - /*send_tab_to_self_receiving_enabled=*/true); + syncer::DeviceInfo device( + "guid", "name", "72", "agent", sync_pb::SyncEnums_DeviceType_TYPE_LINUX, + "scoped_is", /*last_updated_timestamp=*/clock()->Now(), + /*send_tab_to_self_receiving_enabled=*/true); AddTestDevice(&device); - ON_CALL(*processor(), GetEntityModificationTime("guid")) - .WillByDefault(Return(clock()->Now() - base::TimeDelta::FromDays(1))); // Set the map by calling it. Make sure it has the device. TargetDeviceInfo device_info_1("guid", @@ -870,10 +847,9 @@ syncer::DeviceInfo new_device("new_guid", "new_name", "72", "agent", sync_pb::SyncEnums_DeviceType_TYPE_LINUX, "scoped_is", + /*last_updated_timestamp=*/clock()->Now(), /*send_tab_to_self_receiving_enabled=*/true); AddTestDevice(&new_device); - ON_CALL(*processor(), GetEntityModificationTime("new_guid")) - .WillByDefault(Return(clock()->Now() - base::TimeDelta::FromDays(1))); // Make sure both devices are in the map. TargetDeviceInfo device_info_2("new_guid",
diff --git a/components/sync_device_info/device_info.cc b/components/sync_device_info/device_info.cc index ea461c66..276db02 100644 --- a/components/sync_device_info/device_info.cc +++ b/components/sync_device_info/device_info.cc
@@ -14,6 +14,7 @@ const std::string& sync_user_agent, const sync_pb::SyncEnums::DeviceType device_type, const std::string& signin_scoped_device_id, + base::Time last_updated_timestamp, bool send_tab_to_self_receiving_enabled) : guid_(guid), client_name_(client_name), @@ -21,6 +22,7 @@ sync_user_agent_(sync_user_agent), device_type_(device_type), signin_scoped_device_id_(signin_scoped_device_id), + last_updated_timestamp_(last_updated_timestamp), send_tab_to_self_receiving_enabled_(send_tab_to_self_receiving_enabled) {} DeviceInfo::~DeviceInfo() {} @@ -53,6 +55,10 @@ return signin_scoped_device_id_; } +base::Time DeviceInfo::last_updated_timestamp() const { + return last_updated_timestamp_; +} + bool DeviceInfo::send_tab_to_self_receiving_enabled() const { return send_tab_to_self_receiving_enabled_; } @@ -111,6 +117,7 @@ value->SetString("os", GetOSString()); value->SetString("type", GetDeviceTypeString()); value->SetString("chromeVersion", chrome_version_); + value->SetInteger("lastUpdatedTimestamp", last_updated_timestamp().ToTimeT()); value->SetBoolean("sendTabToSelfReceivingEnabled", send_tab_to_self_receiving_enabled()); return value;
diff --git a/components/sync_device_info/device_info.h b/components/sync_device_info/device_info.h index 8a699d6..e4a2c9a 100644 --- a/components/sync_device_info/device_info.h +++ b/components/sync_device_info/device_info.h
@@ -10,6 +10,7 @@ #include "base/callback.h" #include "base/macros.h" +#include "base/time/time.h" #include "components/sync/protocol/sync.pb.h" namespace base { @@ -27,6 +28,7 @@ const std::string& sync_user_agent, const sync_pb::SyncEnums::DeviceType device_type, const std::string& signin_scoped_device_id, + base::Time last_updated_timestamp, bool send_tab_to_self_receiving_enabled); ~DeviceInfo(); @@ -57,6 +59,9 @@ // annotating login scoped refresh token. const std::string& signin_scoped_device_id() const; + // Returns the time at which this device was last updated to the sync servers. + base::Time last_updated_timestamp() const; + // Whether the receiving side of the SendTabToSelf feature is enabled. bool send_tab_to_self_receiving_enabled() const; @@ -100,6 +105,8 @@ // and they are also reset when app/extension is uninstalled. std::string public_id_; + const base::Time last_updated_timestamp_; + bool send_tab_to_self_receiving_enabled_; DISALLOW_COPY_AND_ASSIGN(DeviceInfo);
diff --git a/components/sync_device_info/device_info_sync_bridge.cc b/components/sync_device_info/device_info_sync_bridge.cc index c70b2de..21ecb50 100644 --- a/components/sync_device_info/device_info_sync_bridge.cc +++ b/components/sync_device_info/device_info_sync_bridge.cc
@@ -58,6 +58,7 @@ specifics.cache_guid(), specifics.client_name(), specifics.chrome_version(), specifics.sync_user_agent(), specifics.device_type(), specifics.signin_scoped_device_id(), + ProtoTimeToTime(specifics.last_updated_timestamp()), specifics.feature_fields().send_tab_to_self_receiving_enabled()); } @@ -70,12 +71,9 @@ return entity_data; } -// Converts DeviceInfo into a freshly allocated DeviceInfoSpecifics. Takes -// |last_updated_timestamp| to set because the model object does not contain -// this concept. -std::unique_ptr<DeviceInfoSpecifics> ModelToSpecifics( - const DeviceInfo& info, - int64_t last_updated_timestamp) { +// Converts a local DeviceInfo into a freshly allocated DeviceInfoSpecifics. +std::unique_ptr<DeviceInfoSpecifics> MakeLocalDeviceSpecifics( + const DeviceInfo& info) { auto specifics = std::make_unique<DeviceInfoSpecifics>(); specifics->set_cache_guid(info.guid()); specifics->set_client_name(info.client_name()); @@ -83,7 +81,10 @@ specifics->set_sync_user_agent(info.sync_user_agent()); specifics->set_device_type(info.device_type()); specifics->set_signin_scoped_device_id(info.signin_scoped_device_id()); - specifics->set_last_updated_timestamp(last_updated_timestamp); + // The local device should have not been updated yet. Set the last updated + // timestamp to now. + DCHECK(info.last_updated_timestamp() == base::Time()); + specifics->set_last_updated_timestamp(TimeToProtoTime(Time::Now())); FeatureSpecificFields* feature_fields = specifics->mutable_feature_fields(); feature_fields->set_send_tab_to_self_receiving_enabled( @@ -471,9 +472,8 @@ DCHECK(local_device_info_provider_->GetLocalDeviceInfo()); DCHECK(change_processor()->IsTrackingMetadata()); - std::unique_ptr<DeviceInfoSpecifics> specifics = - ModelToSpecifics(*local_device_info_provider_->GetLocalDeviceInfo(), - TimeToProtoTime(Time::Now())); + std::unique_ptr<DeviceInfoSpecifics> specifics = MakeLocalDeviceSpecifics( + *local_device_info_provider_->GetLocalDeviceInfo()); change_processor()->Put(specifics->cache_guid(), CopyToEntityData(*specifics), batch->GetMetadataChangeList()); StoreSpecifics(std::move(specifics), batch.get());
diff --git a/components/sync_device_info/device_info_sync_bridge_unittest.cc b/components/sync_device_info/device_info_sync_bridge_unittest.cc index bc63cef..8a4357d 100644 --- a/components/sync_device_info/device_info_sync_bridge_unittest.cc +++ b/components/sync_device_info/device_info_sync_bridge_unittest.cc
@@ -190,7 +190,7 @@ cache_guid, session_name, ChromeVersionForSuffix(kLocalSuffix), SyncUserAgentForSuffix(kLocalSuffix), sync_pb::SyncEnums_DeviceType_TYPE_LINUX, - SigninScopedDeviceIdForSuffix(kLocalSuffix), true); + SigninScopedDeviceIdForSuffix(kLocalSuffix), base::Time(), true); } void Clear() override { local_device_info_.reset(); }
diff --git a/components/sync_device_info/local_device_info_provider_impl.cc b/components/sync_device_info/local_device_info_provider_impl.cc index e3e85dd..22619e3 100644 --- a/components/sync_device_info/local_device_info_provider_impl.cc +++ b/components/sync_device_info/local_device_info_provider_impl.cc
@@ -61,9 +61,12 @@ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK(!cache_guid.empty()); + // The local device doesn't have a last updated timestamps. It will be set in + // the specifics when it will be synced up. local_device_info_ = std::make_unique<DeviceInfo>( cache_guid, session_name, version_, MakeUserAgentForSync(channel_), GetLocalDeviceType(), signin_scoped_device_id_callback_.Run(), + /*last_updated_timestamp=*/base::Time(), send_tab_to_self_receiving_enabled_callback_.Run()); // Notify observers.
diff --git a/components/viz/common/BUILD.gn b/components/viz/common/BUILD.gn index 386bed01..cddcf49 100644 --- a/components/viz/common/BUILD.gn +++ b/components/viz/common/BUILD.gn
@@ -144,6 +144,7 @@ "gpu/context_lost_reason.h", "gpu/context_provider.cc", "gpu/context_provider.h", + "gpu/gpu_vsync_callback.h", "gpu/raster_context_provider.cc", "gpu/raster_context_provider.h", "hit_test/aggregated_hit_test_region.h",
diff --git a/components/viz/common/frame_sinks/begin_frame_source.cc b/components/viz/common/frame_sinks/begin_frame_source.cc index 35dd211..18654a5 100644 --- a/components/viz/common/frame_sinks/begin_frame_source.cc +++ b/components/viz/common/frame_sinks/begin_frame_source.cc
@@ -323,6 +323,10 @@ if (RequestCallbackOnGpuAvailable()) return; last_begin_frame_args_ = CreateBeginFrameArgs(time_source_->LastTickTime()); + TRACE_EVENT2( + "viz", "DelayBasedBeginFrameSource::OnTimerTick", "frame_time", + last_begin_frame_args_.frame_time.since_origin().InMicroseconds(), + "interval", last_begin_frame_args_.interval.InMicroseconds()); base::flat_set<BeginFrameObserver*> observers(observers_); for (auto* obs : observers) IssueBeginFrameToObserver(obs, last_begin_frame_args_); @@ -428,6 +432,11 @@ return; } + TRACE_EVENT2( + "viz", "ExternalBeginFrameSource::OnBeginFrame", "frame_time", + last_begin_frame_args_.frame_time.since_origin().InMicroseconds(), + "interval", last_begin_frame_args_.interval.InMicroseconds()); + last_begin_frame_args_ = args; base::flat_set<BeginFrameObserver*> observers(observers_);
diff --git a/components/viz/common/gpu/gpu_vsync_callback.h b/components/viz/common/gpu/gpu_vsync_callback.h new file mode 100644 index 0000000..dcc6bd08f2 --- /dev/null +++ b/components/viz/common/gpu/gpu_vsync_callback.h
@@ -0,0 +1,19 @@ +// 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 COMPONENTS_VIZ_COMMON_GPU_GPU_VSYNC_CALLBACK_H_ +#define COMPONENTS_VIZ_COMMON_GPU_GPU_VSYNC_CALLBACK_H_ + +#include "base/callback.h" +#include "base/time/time.h" + +namespace viz { + +using GpuVSyncCallback = + base::RepeatingCallback<void(base::TimeTicks vsync_time, + base::TimeDelta vsync_interval)>; + +} // namespace viz + +#endif // COMPONENTS_VIZ_COMMON_GPU_GPU_VSYNC_CALLBACK_H_
diff --git a/components/viz/service/BUILD.gn b/components/viz/service/BUILD.gn index b02337a..bd5eb0a 100644 --- a/components/viz/service/BUILD.gn +++ b/components/viz/service/BUILD.gn
@@ -135,6 +135,8 @@ "frame_sinks/frame_sink_manager_impl.cc", "frame_sinks/frame_sink_manager_impl.h", "frame_sinks/frame_sink_observer.h", + "frame_sinks/gpu_vsync_begin_frame_source.cc", + "frame_sinks/gpu_vsync_begin_frame_source.h", "frame_sinks/primary_begin_frame_source.cc", "frame_sinks/primary_begin_frame_source.h", "frame_sinks/root_compositor_frame_sink_impl.cc",
diff --git a/components/viz/service/display/output_surface.cc b/components/viz/service/display/output_surface.cc index a979681..ed636a68 100644 --- a/components/viz/service/display/output_surface.cc +++ b/components/viz/service/display/output_surface.cc
@@ -55,4 +55,12 @@ DCHECK(!needs_swap_size_notifications); } +void OutputSurface::SetGpuVSyncCallback(GpuVSyncCallback callback) { + NOTREACHED(); +} + +void OutputSurface::SetGpuVSyncEnabled(bool enabled) { + NOTREACHED(); +} + } // namespace viz
diff --git a/components/viz/service/display/output_surface.h b/components/viz/service/display/output_surface.h index fe6bd91..4d51fd6 100644 --- a/components/viz/service/display/output_surface.h +++ b/components/viz/service/display/output_surface.h
@@ -13,6 +13,7 @@ #include "base/threading/thread_checker.h" #include "components/viz/common/display/update_vsync_parameters_callback.h" #include "components/viz/common/gpu/context_provider.h" +#include "components/viz/common/gpu/gpu_vsync_callback.h" #include "components/viz/common/resources/returned_resource.h" #include "components/viz/service/display/overlay_candidate_validator.h" #include "components/viz/service/display/software_output_device.h" @@ -52,6 +53,8 @@ bool supports_stencil = false; // Whether this OutputSurface supports post sub buffer or not. bool supports_post_sub_buffer = false; + // Whether this OutputSurface supports gpu vsync callbacks. + bool supports_gpu_vsync = false; }; // Constructor for skia-based compositing. @@ -138,6 +141,13 @@ virtual void SetUpdateVSyncParametersCallback( UpdateVSyncParametersCallback callback) = 0; + // Set a callback for vsync signal from GPU service for begin frames. The + // callbacks must be received on the calling thread. + virtual void SetGpuVSyncCallback(GpuVSyncCallback callback); + + // Enable or disable vsync callback based on whether begin frames are needed. + virtual void SetGpuVSyncEnabled(bool enabled); + // If set to true, the OutputSurface must deliver // OutputSurfaceclient::DidSwapWithSize notifications to its client. // OutputSurfaces which support delivering swap size notifications should
diff --git a/components/viz/service/display_embedder/gl_output_surface.cc b/components/viz/service/display_embedder/gl_output_surface.cc index 117363e5..1ea3865e 100644 --- a/components/viz/service/display_embedder/gl_output_surface.cc +++ b/components/viz/service/display_embedder/gl_output_surface.cc
@@ -39,9 +39,14 @@ // can use. capabilities_.max_frames_pending = context_provider->ContextCapabilities().num_surface_buffers - 1; + capabilities_.supports_gpu_vsync = + context_provider->ContextCapabilities().gpu_vsync; } GLOutputSurface::~GLOutputSurface() { + viz_context_provider_->SetUpdateVSyncParametersCallback( + UpdateVSyncParametersCallback()); + viz_context_provider_->SetGpuVSyncCallback(GpuVSyncCallback()); if (gpu_fence_id_ > 0) context_provider()->ContextGL()->DestroyGpuFenceCHROMIUM(gpu_fence_id_); } @@ -205,4 +210,14 @@ viz_context_provider_->SetUpdateVSyncParametersCallback(std::move(callback)); } +void GLOutputSurface::SetGpuVSyncCallback(GpuVSyncCallback callback) { + DCHECK(capabilities_.supports_gpu_vsync); + viz_context_provider_->SetGpuVSyncCallback(std::move(callback)); +} + +void GLOutputSurface::SetGpuVSyncEnabled(bool enabled) { + DCHECK(capabilities_.supports_gpu_vsync); + viz_context_provider_->SetGpuVSyncEnabled(enabled); +} + } // namespace viz
diff --git a/components/viz/service/display_embedder/gl_output_surface.h b/components/viz/service/display_embedder/gl_output_surface.h index 1820e59..44d2f15e 100644 --- a/components/viz/service/display_embedder/gl_output_surface.h +++ b/components/viz/service/display_embedder/gl_output_surface.h
@@ -47,6 +47,8 @@ bool needs_swap_size_notifications) override; void SetUpdateVSyncParametersCallback( UpdateVSyncParametersCallback callback) override; + void SetGpuVSyncCallback(GpuVSyncCallback callback) override; + void SetGpuVSyncEnabled(bool enabled) override; protected: OutputSurfaceClient* client() const { return client_; } @@ -70,6 +72,7 @@ const gfx::Size& pixel_size, const gpu::SwapBuffersCompleteParams& params); void OnPresentation(const gfx::PresentationFeedback& feedback); + void OnGpuVSync(base::TimeTicks vsync_time, base::TimeDelta vsync_interval); scoped_refptr<VizProcessContextProvider> viz_context_provider_; OutputSurfaceClient* client_ = nullptr;
diff --git a/components/viz/service/display_embedder/viz_process_context_provider.cc b/components/viz/service/display_embedder/viz_process_context_provider.cc index 36b274b..52738a7 100644 --- a/components/viz/service/display_embedder/viz_process_context_provider.cc +++ b/components/viz/service/display_embedder/viz_process_context_provider.cc
@@ -207,9 +207,16 @@ } void VizProcessContextProvider::SetUpdateVSyncParametersCallback( - const gpu::InProcessCommandBuffer::UpdateVSyncParametersCallback& - callback) { - command_buffer_->SetUpdateVSyncParametersCallback(callback); + UpdateVSyncParametersCallback callback) { + command_buffer_->SetUpdateVSyncParametersCallback(std::move(callback)); +} + +void VizProcessContextProvider::SetGpuVSyncCallback(GpuVSyncCallback callback) { + command_buffer_->SetGpuVSyncCallback(std::move(callback)); +} + +void VizProcessContextProvider::SetGpuVSyncEnabled(bool enabled) { + command_buffer_->SetGpuVSyncEnabled(enabled); } bool VizProcessContextProvider::UseRGB565PixelFormat() const {
diff --git a/components/viz/service/display_embedder/viz_process_context_provider.h b/components/viz/service/display_embedder/viz_process_context_provider.h index e0ea6a38..e3fd2ad 100644 --- a/components/viz/service/display_embedder/viz_process_context_provider.h +++ b/components/viz/service/display_embedder/viz_process_context_provider.h
@@ -70,9 +70,9 @@ void AddObserver(ContextLostObserver* obs) override; void RemoveObserver(ContextLostObserver* obs) override; - void SetUpdateVSyncParametersCallback( - const gpu::InProcessCommandBuffer::UpdateVSyncParametersCallback& - callback); + void SetUpdateVSyncParametersCallback(UpdateVSyncParametersCallback callback); + void SetGpuVSyncCallback(GpuVSyncCallback callback); + void SetGpuVSyncEnabled(bool enabled); bool UseRGB565PixelFormat() const; // Provides the GL internal format that should be used when calling
diff --git a/components/viz/service/frame_sinks/gpu_vsync_begin_frame_source.cc b/components/viz/service/frame_sinks/gpu_vsync_begin_frame_source.cc new file mode 100644 index 0000000..340cb3e9a --- /dev/null +++ b/components/viz/service/frame_sinks/gpu_vsync_begin_frame_source.cc
@@ -0,0 +1,36 @@ +// 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 "components/viz/service/frame_sinks/gpu_vsync_begin_frame_source.h" + +#include "base/bind.h" +#include "components/viz/service/display/output_surface.h" + +namespace viz { + +GpuVSyncBeginFrameSource::GpuVSyncBeginFrameSource( + uint32_t restart_id, + OutputSurface* output_surface) + : ExternalBeginFrameSource(this, restart_id), + output_surface_(output_surface) { + DCHECK(output_surface->capabilities().supports_gpu_vsync); + output_surface->SetGpuVSyncCallback(base::BindRepeating( + &GpuVSyncBeginFrameSource::OnGpuVSync, base::Unretained(this))); +} + +GpuVSyncBeginFrameSource::~GpuVSyncBeginFrameSource() = default; + +void GpuVSyncBeginFrameSource::OnGpuVSync(base::TimeTicks vsync_time, + base::TimeDelta vsync_interval) { + ExternalBeginFrameSource::OnBeginFrame(BeginFrameArgs::Create( + BEGINFRAME_FROM_HERE, source_id(), next_begin_frame_sequence_number_++, + vsync_time, vsync_time + vsync_interval, vsync_interval, + BeginFrameArgs::NORMAL)); +} + +void GpuVSyncBeginFrameSource::OnNeedsBeginFrames(bool needs_begin_frames) { + output_surface_->SetGpuVSyncEnabled(needs_begin_frames); +} + +} // namespace viz
diff --git a/components/viz/service/frame_sinks/gpu_vsync_begin_frame_source.h b/components/viz/service/frame_sinks/gpu_vsync_begin_frame_source.h new file mode 100644 index 0000000..ec91631 --- /dev/null +++ b/components/viz/service/frame_sinks/gpu_vsync_begin_frame_source.h
@@ -0,0 +1,41 @@ +// 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 COMPONENTS_VIZ_SERVICE_FRAME_SINKS_GPU_VSYNC_BEGIN_FRAME_SOURCE_H_ +#define COMPONENTS_VIZ_SERVICE_FRAME_SINKS_GPU_VSYNC_BEGIN_FRAME_SOURCE_H_ + +#include "base/macros.h" +#include "components/viz/common/frame_sinks/begin_frame_source.h" +#include "components/viz/service/viz_service_export.h" + +namespace viz { + +class OutputSurface; + +// Receives begin frames via OutputSurface::SetGpuVSyncCallback(). Output +// surface must have |supports_gpu_vsync| capability. This class is not thread +// safe so the callbacks must be received on the original thread. The BFS is +// guaranteed to outlive the OutputSurface. +class VIZ_SERVICE_EXPORT GpuVSyncBeginFrameSource + : public ExternalBeginFrameSource, + public ExternalBeginFrameSourceClient { + public: + GpuVSyncBeginFrameSource(uint32_t restart_id, OutputSurface* output_surface); + ~GpuVSyncBeginFrameSource() override; + + // ExternalBeginFrameSourceClient implementation. + void OnNeedsBeginFrames(bool needs_begin_frames) override; + + private: + void OnGpuVSync(base::TimeTicks vsync_time, base::TimeDelta vsync_interval); + + OutputSurface* const output_surface_; + uint64_t next_begin_frame_sequence_number_ = 1; + + DISALLOW_COPY_AND_ASSIGN(GpuVSyncBeginFrameSource); +}; + +} // namespace viz + +#endif // COMPONENTS_VIZ_SERVICE_FRAME_SINKS_GPU_VSYNC_BEGIN_FRAME_SOURCE_H_
diff --git a/components/viz/service/frame_sinks/root_compositor_frame_sink_impl.cc b/components/viz/service/frame_sinks/root_compositor_frame_sink_impl.cc index ed8b0880..3df38432 100644 --- a/components/viz/service/frame_sinks/root_compositor_frame_sink_impl.cc +++ b/components/viz/service/frame_sinks/root_compositor_frame_sink_impl.cc
@@ -16,6 +16,7 @@ #include "components/viz/service/display_embedder/vsync_parameter_listener.h" #include "components/viz/service/frame_sinks/external_begin_frame_source_mojo.h" #include "components/viz/service/frame_sinks/frame_sink_manager_impl.h" +#include "components/viz/service/frame_sinks/gpu_vsync_begin_frame_source.h" #include "components/viz/service/hit_test/hit_test_aggregator.h" #if defined(OS_ANDROID) @@ -77,6 +78,9 @@ std::make_unique<BackToBackBeginFrameSource>( std::make_unique<DelayBasedTimeSource>( base::ThreadTaskRunnerHandle::Get().get())); + } else if (output_surface->capabilities().supports_gpu_vsync) { + external_begin_frame_source = std::make_unique<GpuVSyncBeginFrameSource>( + restart_id, output_surface.get()); } else { synthetic_begin_frame_source = std::make_unique<DelayBasedBeginFrameSource>( @@ -84,7 +88,7 @@ base::ThreadTaskRunnerHandle::Get().get()), restart_id); } -#endif +#endif // OS_ANDROID } BeginFrameSource* begin_frame_source = synthetic_begin_frame_source.get();
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn index 79d85fc..c500490 100644 --- a/content/browser/BUILD.gn +++ b/content/browser/BUILD.gn
@@ -521,6 +521,8 @@ "bluetooth/bluetooth_blocklist.h", "bluetooth/bluetooth_device_chooser_controller.cc", "bluetooth/bluetooth_device_chooser_controller.h", + "bluetooth/bluetooth_device_scanning_prompt_controller.cc", + "bluetooth/bluetooth_device_scanning_prompt_controller.h", "bluetooth/bluetooth_metrics.cc", "bluetooth/bluetooth_metrics.h", "bluetooth/frame_connected_bluetooth_devices.cc",
diff --git a/content/browser/bluetooth/bluetooth_device_scanning_prompt_controller.cc b/content/browser/bluetooth/bluetooth_device_scanning_prompt_controller.cc new file mode 100644 index 0000000..276f52f3 --- /dev/null +++ b/content/browser/bluetooth/bluetooth_device_scanning_prompt_controller.cc
@@ -0,0 +1,61 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/browser/bluetooth/bluetooth_device_scanning_prompt_controller.h" + +#include "base/bind.h" +#include "base/bind_helpers.h" +#include "content/browser/bluetooth/web_bluetooth_service_impl.h" +#include "content/public/browser/render_frame_host.h" +#include "content/public/browser/web_contents.h" +#include "content/public/browser/web_contents_delegate.h" + +namespace content { + +BluetoothDeviceScanningPromptController:: + BluetoothDeviceScanningPromptController( + WebBluetoothServiceImpl* web_bluetooth_service, + RenderFrameHost* render_frame_host) + : web_bluetooth_service_(web_bluetooth_service), + render_frame_host_(render_frame_host), + web_contents_(WebContents::FromRenderFrameHost(render_frame_host_)) {} + +BluetoothDeviceScanningPromptController:: + ~BluetoothDeviceScanningPromptController() { + if (!prompt_event_received_) + OnBluetoothScanningPromptEvent(BluetoothScanningPrompt::Event::kCanceled); +} + +void BluetoothDeviceScanningPromptController::ShowPermissionPrompt() { + BluetoothScanningPrompt::EventHandler prompt_event_handler = base::Bind( + &BluetoothDeviceScanningPromptController::OnBluetoothScanningPromptEvent, + base::Unretained(this)); + WebContentsDelegate* delegate = + WebContents::FromRenderFrameHost(render_frame_host_)->GetDelegate(); + if (delegate) { + prompt_ = delegate->ShowBluetoothScanningPrompt( + render_frame_host_, std::move(prompt_event_handler)); + } +} + +void BluetoothDeviceScanningPromptController::OnBluetoothScanningPromptEvent( + BluetoothScanningPrompt::Event event) { + DCHECK(web_bluetooth_service_); + + web_bluetooth_service_->OnBluetoothScanningPromptEvent(event, this); + prompt_event_received_ = true; + + // Close prompt. + prompt_.reset(); +} + +void BluetoothDeviceScanningPromptController::AddFilteredDevice( + const std::string& device_id, + bool should_update_name, + const base::string16& device_name) { + if (prompt_) + prompt_->AddOrUpdateDevice(device_id, should_update_name, device_name); +} + +} // namespace content
diff --git a/content/browser/bluetooth/bluetooth_device_scanning_prompt_controller.h b/content/browser/bluetooth/bluetooth_device_scanning_prompt_controller.h new file mode 100644 index 0000000..2473df4 --- /dev/null +++ b/content/browser/bluetooth/bluetooth_device_scanning_prompt_controller.h
@@ -0,0 +1,66 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_BROWSER_BLUETOOTH_BLUETOOTH_DEVICE_SCANNING_PROMPT_CONTROLLER_H_ +#define CONTENT_BROWSER_BLUETOOTH_BLUETOOTH_DEVICE_SCANNING_PROMPT_CONTROLLER_H_ + +#include <memory> +#include <string> + +#include "base/memory/weak_ptr.h" +#include "base/strings/string16.h" +#include "content/common/content_export.h" +#include "content/public/browser/bluetooth_scanning_prompt.h" + +namespace content { + +class RenderFrameHost; +class WebContents; +class WebBluetoothServiceImpl; + +// Class that interacts with a prompt. +class CONTENT_EXPORT BluetoothDeviceScanningPromptController final { + public: + // |web_bluetooth_service_| service that owns this class. + // |render_frame_host| should be the RenderFrameHost that owns the + // |web_bluetooth_service_|. + BluetoothDeviceScanningPromptController( + WebBluetoothServiceImpl* web_bluetooth_service, + RenderFrameHost* render_frame_host); + ~BluetoothDeviceScanningPromptController(); + + void ShowPermissionPrompt(); + + void OnBluetoothScanningPromptEvent(BluetoothScanningPrompt::Event event); + + // Adds a device to the prompt. Should only be called after + // ShowPermissionPrompt() is called. + void AddFilteredDevice(const std::string& device_id, + bool should_update_name, + const base::string16& device_name); + + private: + // The WebBluetoothServiceImpl that owns this instance. + WebBluetoothServiceImpl* const web_bluetooth_service_; + // The RenderFrameHost that owns |web_bluetooth_service_|. + RenderFrameHost* const render_frame_host_; + // The WebContents that owns |render_frame_host_|. + WebContents* const web_contents_; + + // The currently opened BluetoothScanningPrompt. + std::unique_ptr<BluetoothScanningPrompt> prompt_; + + bool prompt_event_received_ = false; + + // Weak pointer factory for generating 'this' pointers that might live longer + // than we do. + // Note: This should remain the last member so it'll be destroyed and + // invalidate its weak pointers before any other members are destroyed. + base::WeakPtrFactory<BluetoothDeviceScanningPromptController> + weak_ptr_factory_{this}; +}; + +} // namespace content + +#endif // CONTENT_BROWSER_BLUETOOTH_BLUETOOTH_DEVICE_SCANNING_PROMPT_CONTROLLER_H_
diff --git a/content/browser/bluetooth/web_bluetooth_service_impl.cc b/content/browser/bluetooth/web_bluetooth_service_impl.cc index 6952610..5aa7340c 100644 --- a/content/browser/bluetooth/web_bluetooth_service_impl.cc +++ b/content/browser/bluetooth/web_bluetooth_service_impl.cc
@@ -19,8 +19,10 @@ #include "base/threading/thread_task_runner_handle.h" #include "content/browser/bluetooth/bluetooth_blocklist.h" #include "content/browser/bluetooth/bluetooth_device_chooser_controller.h" +#include "content/browser/bluetooth/bluetooth_device_scanning_prompt_controller.h" #include "content/browser/bluetooth/bluetooth_metrics.h" #include "content/browser/bluetooth/frame_connected_bluetooth_devices.h" +#include "content/browser/permissions/permission_controller_impl.h" #include "content/browser/renderer_host/render_process_host_impl.h" #include "content/browser/storage_partition_impl.h" #include "content/common/bluetooth/web_bluetooth_device_id.h" @@ -29,6 +31,7 @@ #include "content/public/browser/navigation_handle.h" #include "content/public/browser/render_frame_host.h" #include "content/public/browser/web_contents.h" +#include "content/public/browser/web_contents_delegate.h" #include "device/bluetooth/bluetooth_adapter_factory_wrapper.h" #include "device/bluetooth/bluetooth_remote_gatt_characteristic.h" #include "device/bluetooth/bluetooth_remote_gatt_descriptor.h" @@ -245,10 +248,42 @@ return allowed_devices().GetDeviceId(device_address) != nullptr; } +void WebBluetoothServiceImpl::OnBluetoothScanningPromptEvent( + BluetoothScanningPrompt::Event event, + BluetoothDeviceScanningPromptController* prompt_controller) { + DCHECK(!scanning_clients_.empty()); + + auto client = scanning_clients_.end() - 1; + + DCHECK((*client)->prompt_controller() == prompt_controller); + + auto result = blink::mojom::WebBluetoothResult::SUCCESS; + if (event == BluetoothScanningPrompt::Event::kAllow) + result = blink::mojom::WebBluetoothResult::SUCCESS; + else if (event == BluetoothScanningPrompt::Event::kBlock) + result = blink::mojom::WebBluetoothResult::SCANNING_BLOCKED; + else if (event == BluetoothScanningPrompt::Event::kCanceled) + result = blink::mojom::WebBluetoothResult::PROMPT_CANCELED; + else + NOTREACHED(); + + (*client)->RunRequestScanningStartCallback(std::move(result)); + (*client)->set_prompt_controller(nullptr); + if (event == BluetoothScanningPrompt::Event::kAllow) + (*client)->set_allow_send_event(true); + else + scanning_clients_.erase(client); +} + WebBluetoothServiceImpl::ScanningClient::ScanningClient( blink::mojom::WebBluetoothScanClientAssociatedPtr client, - blink::mojom::WebBluetoothRequestLEScanOptionsPtr options) - : client_(std::move(client)), options_(std::move(options)) { + blink::mojom::WebBluetoothRequestLEScanOptionsPtr options, + RequestScanningStartCallback callback, + BluetoothDeviceScanningPromptController* prompt_controller) + : client_(std::move(client)), + options_(std::move(options)), + callback_(std::move(callback)), + prompt_controller_(prompt_controller) { DCHECK(options_->filters.has_value() || options_->accept_all_advertisements); client_.set_connection_error_handler(base::BindRepeating( &ScanningClient::DisconnectionHandler, base::Unretained(this))); @@ -262,7 +297,12 @@ return false; if (options_->accept_all_advertisements) { - client_->ScanEvent(std::move(result)); + if (prompt_controller_) + AddFilteredDeviceToPrompt(result->device->id.str(), result->name); + + if (allow_send_event_) + client_->ScanEvent(std::move(result)); + return true; } @@ -308,7 +348,11 @@ } // TODO(crbug.com/707635): Support manufacturerData and serviceData filters. - client_->ScanEvent(std::move(result)); + if (prompt_controller_) + AddFilteredDeviceToPrompt(result->device->id.str(), result->name); + + if (allow_send_event_) + client_->ScanEvent(std::move(result)); return true; } @@ -316,10 +360,36 @@ return true; } +void WebBluetoothServiceImpl::ScanningClient::RunRequestScanningStartCallback( + blink::mojom::WebBluetoothResult result) { + if (result == blink::mojom::WebBluetoothResult::SUCCESS) { + auto scanning_result = + blink::mojom::RequestScanningStartResult::NewOptions(options_.Clone()); + std::move(callback_).Run(std::move(scanning_result)); + } else if (result == blink::mojom::WebBluetoothResult::SCANNING_BLOCKED || + result == blink::mojom::WebBluetoothResult::PROMPT_CANCELED) { + auto scanning_result = + blink::mojom::RequestScanningStartResult::NewErrorResult(result); + std::move(callback_).Run(std::move(scanning_result)); + } else { + NOTREACHED(); + } +} + void WebBluetoothServiceImpl::ScanningClient::DisconnectionHandler() { disconnected_ = true; } +void WebBluetoothServiceImpl::ScanningClient::AddFilteredDeviceToPrompt( + const std::string& device_id, + const base::Optional<std::string>& device_name) { + bool should_update_name = device_name.has_value(); + base::string16 device_name_for_display = + base::UTF8ToUTF16(device_name.value_or("")); + prompt_controller_->AddFilteredDevice(device_id, should_update_name, + device_name_for_display); +} + void WebBluetoothServiceImpl::DidFinishNavigation( NavigationHandle* navigation_handle) { if (navigation_handle->HasCommitted() && @@ -1077,21 +1147,29 @@ return; } - if (discovery_session_) { - scanning_clients_.push_back( - std::make_unique<ScanningClient>(std::move(client), options.Clone())); - auto result = blink::mojom::RequestScanningStartResult::NewOptions( - std::move(options)); + if (discovery_callback_) { + auto result = blink::mojom::RequestScanningStartResult::NewErrorResult( + blink::mojom::WebBluetoothResult::PROMPT_CANCELED); std::move(callback).Run(std::move(result)); return; } - discovery_callbacks_.push_back(std::move(callback)); + if (discovery_session_) { + // By resetting |device_scanning_prompt_controller_|, it returns an error if + // there are duplicate calls to RequestScanningStart(). + device_scanning_prompt_controller_ = + std::make_unique<BluetoothDeviceScanningPromptController>( + this, render_frame_host_); - if (discovery_request_pending_) + scanning_clients_.push_back(std::make_unique<ScanningClient>( + std::move(client), std::move(options), std::move(callback), + device_scanning_prompt_controller_.get())); + device_scanning_prompt_controller_->ShowPermissionPrompt(); return; + } - discovery_request_pending_ = true; + discovery_callback_ = std::move(callback); + adapter->StartDiscoverySession( base::Bind(&WebBluetoothServiceImpl::OnStartDiscoverySession, weak_ptr_factory_.GetWeakPtr(), base::Passed(&client), @@ -1107,31 +1185,25 @@ DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK(!discovery_session_); - discovery_request_pending_ = false; + device_scanning_prompt_controller_ = + std::make_unique<BluetoothDeviceScanningPromptController>( + this, render_frame_host_); + discovery_session_ = std::move(session); - scanning_clients_.push_back( - std::make_unique<ScanningClient>(std::move(client), options.Clone())); - - for (auto& callback : discovery_callbacks_) { - auto result = - blink::mojom::RequestScanningStartResult::NewOptions(options.Clone()); - std::move(callback).Run(std::move(result)); - } - - discovery_callbacks_.clear(); + scanning_clients_.push_back(std::make_unique<ScanningClient>( + std::move(client), std::move(options), std::move(discovery_callback_), + device_scanning_prompt_controller_.get())); + device_scanning_prompt_controller_->ShowPermissionPrompt(); } void WebBluetoothServiceImpl::OnDiscoverySessionError() { DCHECK_CURRENTLY_ON(BrowserThread::UI); - discovery_request_pending_ = false; - for (auto& callback : discovery_callbacks_) { - auto result = blink::mojom::RequestScanningStartResult::NewErrorResult( - blink::mojom::WebBluetoothResult::NO_BLUETOOTH_ADAPTER); - std::move(callback).Run(std::move(result)); - } + device_scanning_prompt_controller_.reset(); - discovery_callbacks_.clear(); + auto result = blink::mojom::RequestScanningStartResult::NewErrorResult( + blink::mojom::WebBluetoothResult::NO_BLUETOOTH_ADAPTER); + std::move(discovery_callback_).Run(std::move(result)); } void WebBluetoothServiceImpl::RequestDeviceImpl( @@ -1576,6 +1648,7 @@ connected_devices_.reset( new FrameConnectedBluetoothDevices(render_frame_host_)); device_chooser_controller_.reset(); + device_scanning_prompt_controller_.reset(); BluetoothAdapterFactoryWrapper::Get().ReleaseAdapter(this); }
diff --git a/content/browser/bluetooth/web_bluetooth_service_impl.h b/content/browser/bluetooth/web_bluetooth_service_impl.h index 99969bbc..5115a57 100644 --- a/content/browser/bluetooth/web_bluetooth_service_impl.h +++ b/content/browser/bluetooth/web_bluetooth_service_impl.h
@@ -14,6 +14,7 @@ #include "content/browser/bad_message.h" #include "content/browser/bluetooth/bluetooth_allowed_devices.h" #include "content/common/content_export.h" +#include "content/public/browser/bluetooth_scanning_prompt.h" #include "content/public/browser/web_contents_observer.h" #include "device/bluetooth/bluetooth_adapter.h" #include "device/bluetooth/bluetooth_discovery_session.h" @@ -32,6 +33,7 @@ namespace content { class BluetoothDeviceChooserController; +class BluetoothDeviceScanningPromptController; struct CacheQueryResult; class FrameConnectedBluetoothDevices; struct GATTNotifySessionAndCharacteristicClient; @@ -72,6 +74,12 @@ // GetLastCommittedOrigin(). bool IsDevicePaired(const std::string& device_address); + // Informs each client in |scanning_clients_| of the user's permission + // decision. + void OnBluetoothScanningPromptEvent( + BluetoothScanningPrompt::Event event, + BluetoothDeviceScanningPromptController* prompt_controller); + private: friend class FrameConnectedBluetoothDevicesTest; using PrimaryServicesRequestCallback = @@ -80,16 +88,40 @@ class ScanningClient { public: ScanningClient(blink::mojom::WebBluetoothScanClientAssociatedPtr client, - blink::mojom::WebBluetoothRequestLEScanOptionsPtr options); + blink::mojom::WebBluetoothRequestLEScanOptionsPtr options, + RequestScanningStartCallback callback, + BluetoothDeviceScanningPromptController* prompt_controller); ~ScanningClient(); bool SendEvent(blink::mojom::WebBluetoothScanResultPtr result); + void set_prompt_controller( + BluetoothDeviceScanningPromptController* prompt_controller) { + prompt_controller_ = prompt_controller; + } + + BluetoothDeviceScanningPromptController* prompt_controller() { + return prompt_controller_; + } + + void set_allow_send_event(bool allow_send_event) { + allow_send_event_ = allow_send_event; + } + + void RunRequestScanningStartCallback( + blink::mojom::WebBluetoothResult result); + private: void DisconnectionHandler(); + void AddFilteredDeviceToPrompt( + const std::string& device_id, + const base::Optional<std::string>& device_name); bool disconnected_ = false; + bool allow_send_event_ = false; mojo::AssociatedInterfacePtr<blink::mojom::WebBluetoothScanClient> client_; blink::mojom::WebBluetoothRequestLEScanOptionsPtr options_; + RequestScanningStartCallback callback_; + BluetoothDeviceScanningPromptController* prompt_controller_; }; // WebContentsObserver: @@ -309,6 +341,10 @@ // Used to open a BluetoothChooser and start a device discovery session. std::unique_ptr<BluetoothDeviceChooserController> device_chooser_controller_; + // Used to open a BluetoothScanningPrompt. + std::unique_ptr<BluetoothDeviceScanningPromptController> + device_scanning_prompt_controller_; + // Maps to get the object's parent based on its instanceID. std::unordered_map<std::string, std::string> service_id_to_device_address_; std::unordered_map<std::string, std::string> characteristic_id_to_service_id_; @@ -331,15 +367,12 @@ // The RFH that owns this instance. RenderFrameHost* render_frame_host_; - // True, if there is a pending request to start or stop discovery. - bool discovery_request_pending_ = false; - // Keeps track of our BLE scanning session. std::unique_ptr<device::BluetoothDiscoverySession> discovery_session_; - // This vector queues up start callbacks so that we only have one + // This queues up start callback so that we only have one // BluetoothDiscoverySession start request at a time. - std::vector<RequestScanningStartCallback> discovery_callbacks_; + RequestScanningStartCallback discovery_callback_; // List of clients that we must broadcast scan changes to. std::vector<std::unique_ptr<ScanningClient>> scanning_clients_;
diff --git a/content/browser/indexed_db/indexed_db_callbacks.cc b/content/browser/indexed_db/indexed_db_callbacks.cc index 7cc498b..18a11e3 100644 --- a/content/browser/indexed_db/indexed_db_callbacks.cc +++ b/content/browser/indexed_db/indexed_db_callbacks.cc
@@ -165,9 +165,7 @@ // static bool IndexedDBCallbacks::CreateAllBlobs( scoped_refptr<ChromeBlobStorageContext> blob_context, - scoped_refptr<base::SequencedTaskRunner> idb_runner, std::vector<IndexedDBValueBlob> value_blobs) { - DCHECK(idb_runner->RunsTasksInCurrentSequence()); IDB_TRACE("IndexedDBCallbacks::CreateAllBlobs"); if (value_blobs.empty()) @@ -206,7 +204,7 @@ } *inner_result = true; }, - std::move(blob_context), std::move(idb_runner), + std::move(blob_context), base::SequencedTaskRunnerHandle::Get(), std::move(value_blobs), &signal_when_finished, &result)); signal_when_finished.Wait(); return result; @@ -395,7 +393,7 @@ std::make_unique<CursorImpl>(std::move(cursor_wrapper.cursor_), origin_, dispatcher_host_.get(), idb_runner_); if (mojo_value && !IndexedDBCallbacks::CreateAllBlobs( - dispatcher_host_->blob_storage_context(), idb_runner_, + dispatcher_host_->blob_storage_context(), IndexedDBValueBlob::GetIndexedDBValueBlobs( blob_info, &mojo_value->blob_or_file_info))) { return; @@ -432,7 +430,7 @@ if (mojo_value && !IndexedDBCallbacks::CreateAllBlobs( - dispatcher_host_->blob_storage_context(), idb_runner_, + dispatcher_host_->blob_storage_context(), IndexedDBValueBlob::GetIndexedDBValueBlobs( blob_info, &mojo_value->value->blob_or_file_info))) { return; @@ -471,8 +469,7 @@ } if (!IndexedDBCallbacks::CreateAllBlobs( - dispatcher_host_->blob_storage_context(), idb_runner_, - std::move(value_blobs))) { + dispatcher_host_->blob_storage_context(), std::move(value_blobs))) { return; }
diff --git a/content/browser/indexed_db/indexed_db_callbacks.h b/content/browser/indexed_db/indexed_db_callbacks.h index b26cb874..59c3e7a 100644 --- a/content/browser/indexed_db/indexed_db_callbacks.h +++ b/content/browser/indexed_db/indexed_db_callbacks.h
@@ -82,7 +82,6 @@ static bool CreateAllBlobs( scoped_refptr<ChromeBlobStorageContext> blob_context, - scoped_refptr<base::SequencedTaskRunner> idb_runner, std::vector<IndexedDBValueBlob> value_blobs); IndexedDBCallbacks(base::WeakPtr<IndexedDBDispatcherHost> dispatcher_host,
diff --git a/content/browser/indexed_db/indexed_db_cursor.cc b/content/browser/indexed_db/indexed_db_cursor.cc index 9aaf05d6..5a9ae0e 100644 --- a/content/browser/indexed_db/indexed_db_cursor.cc +++ b/content/browser/indexed_db/indexed_db_cursor.cc
@@ -112,14 +112,12 @@ BindWeakOperation( &IndexedDBCursor::CursorAdvanceOperation, ptr_factory_.GetWeakPtr(), count, std::move(dispatcher_host), - base::WrapRefCounted(dispatcher_host->context()->TaskRunner()), std::move(callback))); } leveldb::Status IndexedDBCursor::CursorAdvanceOperation( uint32_t count, base::WeakPtr<IndexedDBDispatcherHost> dispatcher_host, - scoped_refptr<base::SequencedTaskRunner> idb_runner, blink::mojom::IDBCursor::AdvanceCallback callback, IndexedDBTransaction* /*transaction*/) { IDB_TRACE("IndexedDBCursor::CursorAdvanceOperation"); @@ -155,7 +153,7 @@ blob_info.swap(value->blob_info); if (!IndexedDBCallbacks::CreateAllBlobs( - dispatcher_host->blob_storage_context(), idb_runner, + dispatcher_host->blob_storage_context(), IndexedDBCallbacks::IndexedDBValueBlob::GetIndexedDBValueBlobs( blob_info, &mojo_value->blob_or_file_info))) { return s; @@ -196,13 +194,11 @@ BindWeakOperation( &IndexedDBCursor::CursorContinueOperation, ptr_factory_.GetWeakPtr(), std::move(dispatcher_host), - base::WrapRefCounted(dispatcher_host->context()->TaskRunner()), base::Passed(&key), base::Passed(&primary_key), std::move(callback))); } leveldb::Status IndexedDBCursor::CursorContinueOperation( base::WeakPtr<IndexedDBDispatcherHost> dispatcher_host, - scoped_refptr<base::SequencedTaskRunner> idb_runner, std::unique_ptr<IndexedDBKey> key, std::unique_ptr<IndexedDBKey> primary_key, blink::mojom::IDBCursor::CursorContinueCallback callback, @@ -243,7 +239,7 @@ blob_info.swap(value->blob_info); if (!IndexedDBCallbacks::CreateAllBlobs( - dispatcher_host->blob_storage_context(), idb_runner, + dispatcher_host->blob_storage_context(), IndexedDBCallbacks::IndexedDBValueBlob::GetIndexedDBValueBlobs( blob_info, &mojo_value->blob_or_file_info))) { return s; @@ -284,13 +280,11 @@ BindWeakOperation( &IndexedDBCursor::CursorPrefetchIterationOperation, ptr_factory_.GetWeakPtr(), std::move(dispatcher_host), - base::WrapRefCounted(dispatcher_host->context()->TaskRunner()), number_to_fetch, std::move(callback))); } leveldb::Status IndexedDBCursor::CursorPrefetchIterationOperation( base::WeakPtr<IndexedDBDispatcherHost> dispatcher_host, - scoped_refptr<base::SequencedTaskRunner> idb_runner, int number_to_fetch, blink::mojom::IDBCursor::PrefetchCallback callback, IndexedDBTransaction* /*transaction*/) { @@ -371,9 +365,10 @@ std::vector<blink::mojom::IDBValuePtr> mojo_values; mojo_values.reserve(found_values.size()); - for (size_t i = 0; i < found_values.size(); ++i) + for (size_t i = 0; i < found_values.size(); ++i) { mojo_values.push_back( IndexedDBValue::ConvertAndEraseValue(&found_values[i])); + } std::vector<IndexedDBCallbacks::IndexedDBValueBlob> value_blobs; for (size_t i = 0; i < mojo_values.size(); ++i) { @@ -383,8 +378,7 @@ } if (!IndexedDBCallbacks::CreateAllBlobs( - dispatcher_host->blob_storage_context(), idb_runner, - std::move(value_blobs))) { + dispatcher_host->blob_storage_context(), std::move(value_blobs))) { return s; }
diff --git a/content/browser/indexed_db/indexed_db_cursor.h b/content/browser/indexed_db/indexed_db_cursor.h index 261f6a8..5e0e26f 100644 --- a/content/browser/indexed_db/indexed_db_cursor.h +++ b/content/browser/indexed_db/indexed_db_cursor.h
@@ -59,7 +59,6 @@ leveldb::Status CursorContinueOperation( base::WeakPtr<IndexedDBDispatcherHost> dispatcher_host, - scoped_refptr<base::SequencedTaskRunner> idb_runner, std::unique_ptr<blink::IndexedDBKey> key, std::unique_ptr<blink::IndexedDBKey> primary_key, blink::mojom::IDBCursor::CursorContinueCallback callback, @@ -67,12 +66,10 @@ leveldb::Status CursorAdvanceOperation( uint32_t count, base::WeakPtr<IndexedDBDispatcherHost> dispatcher_host, - scoped_refptr<base::SequencedTaskRunner> idb_runner, blink::mojom::IDBCursor::AdvanceCallback callback, IndexedDBTransaction* transaction); leveldb::Status CursorPrefetchIterationOperation( base::WeakPtr<IndexedDBDispatcherHost> dispatcher_host, - scoped_refptr<base::SequencedTaskRunner> idb_runner, int number_to_fetch, blink::mojom::IDBCursor::PrefetchCallback callback, IndexedDBTransaction* transaction);
diff --git a/content/browser/indexed_db/indexed_db_database.cc b/content/browser/indexed_db/indexed_db_database.cc index b8efc693..8c7f864 100644 --- a/content/browser/indexed_db/indexed_db_database.cc +++ b/content/browser/indexed_db/indexed_db_database.cc
@@ -1262,8 +1262,7 @@ } if (!IndexedDBCallbacks::CreateAllBlobs( - dispatcher_host->blob_storage_context(), - dispatcher_host->context()->TaskRunner(), std::move(value_blobs))) { + dispatcher_host->blob_storage_context(), std::move(value_blobs))) { return s; }
diff --git a/content/browser/portal/portal.cc b/content/browser/portal/portal.cc index de0c4d6..ada87ca 100644 --- a/content/browser/portal/portal.cc +++ b/content/browser/portal/portal.cc
@@ -185,8 +185,19 @@ auto* outer_contents_main_frame_view = static_cast<RenderWidgetHostViewBase*>( outer_contents->GetMainFrame()->GetView()); - if (outer_contents_main_frame_view) + + if (outer_contents_main_frame_view) { + // Take fallback contents from previous WebContents so that the activation + // is smooth without flashes. + auto* portal_contents_main_frame_view = + static_cast<RenderWidgetHostViewBase*>( + portal_contents_impl_->GetMainFrame()->GetView()); + portal_contents_main_frame_view->TakeFallbackContentFrom( + outer_contents_main_frame_view); + outer_contents_main_frame_view->Destroy(); + } + std::unique_ptr<WebContents> predecessor_web_contents = delegate->SwapWebContents(outer_contents, std::move(portal_contents), true, is_loading);
diff --git a/content/browser/site_instance_impl.cc b/content/browser/site_instance_impl.cc index e5d990b5..a432090 100644 --- a/content/browser/site_instance_impl.cc +++ b/content/browser/site_instance_impl.cc
@@ -618,7 +618,13 @@ // (which ignores the hostname in this case - see https://crbug.com/776160). GURL site_url; if (!origin.host().empty() && origin.scheme() != url::kFileScheme) { - if (SiteIsolationPolicy::IsStrictOriginIsolationEnabled()) + // For Strict Origin Isolation, use the full origin instead of site for all + // HTTP/HTTPS URLs. Note that the HTTP/HTTPS restriction guarantees that + // we won't hit this for hosted app effective URLs, which would otherwise + // need to append a non-translated site URL to the hash below (see + // https://crbug.com/961386). + if (SiteIsolationPolicy::IsStrictOriginIsolationEnabled() && + origin.GetURL().SchemeIsHTTPOrHTTPS()) return origin.GetURL(); site_url = GetSiteForOrigin(origin);
diff --git a/content/browser/site_instance_impl_unittest.cc b/content/browser/site_instance_impl_unittest.cc index 40c1e24..083957ab9 100644 --- a/content/browser/site_instance_impl_unittest.cc +++ b/content/browser/site_instance_impl_unittest.cc
@@ -943,6 +943,34 @@ file_url); } +// Ensure that the site URL for a URL that resolves to a non-HTTP/HTTPS +// effective site URL won't break with strict origin isolation. The effective +// site URL should still contain the non-translated site URL in its hash. See +// https://crbug.com/961386. +TEST_F(SiteInstanceTest, StrictOriginIsolationWithEffectiveURLs) { + base::test::ScopedFeatureList feature_list; + feature_list.InitAndEnableFeature(features::kStrictOriginIsolation); + EXPECT_TRUE(base::FeatureList::IsEnabled(features::kStrictOriginIsolation)); + + const GURL kOriginalUrl("https://original.com"); + const GURL kTranslatedUrl(GetWebUIURL("translated")); + EffectiveURLContentBrowserClient modified_client(kOriginalUrl, + kTranslatedUrl); + ContentBrowserClient* regular_client = + SetBrowserClientForTesting(&modified_client); + + TestBrowserContext browser_context; + IsolationContext isolation_context(&browser_context); + + // Ensure that original.com's effective site URL still contains the + // non-translated site URL in its hash. + GURL expected_site_url(kTranslatedUrl.spec() + "#" + kOriginalUrl.spec()); + EXPECT_EQ(SiteInstanceImpl::GetSiteForURL(isolation_context, kOriginalUrl), + expected_site_url); + + SetBrowserClientForTesting(regular_client); +} + TEST_F(SiteInstanceTest, IsolatedOrigins) { GURL foo_url("http://www.foo.com"); GURL isolated_foo_url("http://isolated.foo.com");
diff --git a/content/browser/site_per_process_hit_test_browsertest.cc b/content/browser/site_per_process_hit_test_browsertest.cc index aa9717c..982cae3 100644 --- a/content/browser/site_per_process_hit_test_browsertest.cc +++ b/content/browser/site_per_process_hit_test_browsertest.cc
@@ -927,7 +927,7 @@ } IN_PROC_BROWSER_TEST_P(SitePerProcessInternalsHitTestBrowserTest, - NestedLocalNonFastScrollableDivCoordsAreLocal) { + DISABLED_NestedLocalNonFastScrollableDivCoordsAreLocal) { GURL main_url(embedded_test_server()->GetURL( "a.com", "/cross_site_iframe_factory.html?a(b)")); EXPECT_TRUE(NavigateToURL(shell(), main_url));
diff --git a/content/browser/tracing/perfetto_file_tracer.cc b/content/browser/tracing/perfetto_file_tracer.cc index d2d3cd4..2f2f3f7 100644 --- a/content/browser/tracing/perfetto_file_tracer.cc +++ b/content/browser/tracing/perfetto_file_tracer.cc
@@ -91,18 +91,11 @@ const auto& chrome_config = tracing::TraceStartupConfig::GetInstance()->GetTraceConfig(); + // The output is always proto based. So, enable privacy filtering if argument + // filter is enabled. + bool privacy_filtering = chrome_config.IsArgumentFilterEnabled(); perfetto::TraceConfig trace_config = - tracing::GetDefaultPerfettoConfig(chrome_config); - - // TODO(ssid): This should be moved to GetDefaultPerfettoConfig(). But, - // currently we only require this for proto output since JSON exporter still - // needs sensitive fields in trace, which will later be stripped. - for (auto& source : *trace_config.mutable_data_sources()) { - source.mutable_config() - ->mutable_chrome_config() - ->set_privacy_filtering_enabled( - chrome_config.IsArgumentFilterEnabled()); - } + tracing::GetDefaultPerfettoConfig(chrome_config, privacy_filtering); int duration_in_seconds = tracing::TraceStartupConfig::GetInstance()->GetStartupDuration();
diff --git a/content/public/browser/BUILD.gn b/content/public/browser/BUILD.gn index 93bb2557..2865a26c 100644 --- a/content/public/browser/BUILD.gn +++ b/content/public/browser/BUILD.gn
@@ -63,6 +63,8 @@ "blob_handle.h", "bluetooth_chooser.cc", "bluetooth_chooser.h", + "bluetooth_scanning_prompt.cc", + "bluetooth_scanning_prompt.h", "browser_accessibility_state.h", "browser_associated_interface.h", "browser_child_process_host.h",
diff --git a/content/public/browser/bluetooth_scanning_prompt.cc b/content/public/browser/bluetooth_scanning_prompt.cc new file mode 100644 index 0000000..669c18f --- /dev/null +++ b/content/public/browser/bluetooth_scanning_prompt.cc
@@ -0,0 +1,13 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/public/browser/bluetooth_scanning_prompt.h" + +namespace content { + +BluetoothScanningPrompt::BluetoothScanningPrompt() = default; + +BluetoothScanningPrompt::~BluetoothScanningPrompt() = default; + +} // namespace content
diff --git a/content/public/browser/bluetooth_scanning_prompt.h b/content/public/browser/bluetooth_scanning_prompt.h new file mode 100644 index 0000000..6f8b339 --- /dev/null +++ b/content/public/browser/bluetooth_scanning_prompt.h
@@ -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. + +#ifndef CONTENT_PUBLIC_BROWSER_BLUETOOTH_SCANNING_PROMPT_H_ +#define CONTENT_PUBLIC_BROWSER_BLUETOOTH_SCANNING_PROMPT_H_ + +#include <string> + +#include "base/callback_forward.h" +#include "base/strings/string16.h" +#include "content/common/content_export.h" + +namespace content { + +// Represents a way to ask the user permission to allow a site to receive +// Bluetooth advertisement packets from Bluetooth devices. +class CONTENT_EXPORT BluetoothScanningPrompt { + public: + enum class Event { + kAllow, + kBlock, + // This can happen when multiple request scanning functions are called, + // and in this case, the previous prompts will be closed. + kCanceled, + }; + + // Prompt implementations are constructed with an |EventHandler| and report + // user interaction with the prompt through it. + // + // The EventHandler won't be called after the prompt object is destroyed. + // + // After the EventHandler is called, it won't be called again, and + // users must not call any more BluetoothScanningPrompt methods. + using EventHandler = base::RepeatingCallback<void(Event)>; + + BluetoothScanningPrompt(); + virtual ~BluetoothScanningPrompt(); + + // Adds a new device to the prompt or updates the information of an + // existing device. + // + // Sometimes when a Bluetooth device stops advertising, the |device_name| + // can be invalid, and in that case |should_update_name| will be set + // false. + virtual void AddOrUpdateDevice(const std::string& device_id, + bool should_update_name, + const base::string16& device_name) {} +}; + +} // namespace content + +#endif // CONTENT_PUBLIC_BROWSER_BLUETOOTH_SCANNING_PROMPT_H_
diff --git a/content/public/browser/web_contents_delegate.cc b/content/public/browser/web_contents_delegate.cc index 66dea66..848f890 100644 --- a/content/public/browser/web_contents_delegate.cc +++ b/content/public/browser/web_contents_delegate.cc
@@ -143,6 +143,13 @@ return nullptr; } +std::unique_ptr<BluetoothScanningPrompt> +WebContentsDelegate::ShowBluetoothScanningPrompt( + RenderFrameHost* frame, + const BluetoothScanningPrompt::EventHandler& event_handler) { + return nullptr; +} + bool WebContentsDelegate::EmbedsFullscreenWidget() const { return false; }
diff --git a/content/public/browser/web_contents_delegate.h b/content/public/browser/web_contents_delegate.h index fddb2dac..e99b9c521 100644 --- a/content/public/browser/web_contents_delegate.h +++ b/content/public/browser/web_contents_delegate.h
@@ -17,6 +17,7 @@ #include "build/build_config.h" #include "content/common/content_export.h" #include "content/public/browser/bluetooth_chooser.h" +#include "content/public/browser/bluetooth_scanning_prompt.h" #include "content/public/browser/invalidate_type.h" #include "content/public/browser/media_stream_request.h" #include "content/public/browser/serial_chooser.h" @@ -397,6 +398,12 @@ RenderFrameHost* frame, const BluetoothChooser::EventHandler& event_handler); + // Shows a prompt for the user to allow/block Bluetooth scanning. The + // observer must live at least as long as the returned prompt object. + virtual std::unique_ptr<BluetoothScanningPrompt> ShowBluetoothScanningPrompt( + RenderFrameHost* frame, + const BluetoothScanningPrompt::EventHandler& event_handler); + // Returns true if the delegate will embed a WebContents-owned fullscreen // render widget. In this case, the delegate may access the widget by calling // WebContents::GetFullscreenRenderWidgetHostView(). If false is returned,
diff --git a/content/renderer/BUILD.gn b/content/renderer/BUILD.gn index 2d3f1df1..fff02ff 100644 --- a/content/renderer/BUILD.gn +++ b/content/renderer/BUILD.gn
@@ -357,8 +357,6 @@ "media/webrtc_local_audio_source_provider.h", "media/webrtc_logging.cc", "media/webrtc_logging.h", - "media_capture_from_element/canvas_capture_handler.cc", - "media_capture_from_element/canvas_capture_handler.h", "media_capture_from_element/html_audio_element_capturer_source.cc", "media_capture_from_element/html_audio_element_capturer_source.h", "media_capture_from_element/html_video_element_capturer_source.cc",
diff --git a/content/renderer/renderer_blink_platform_impl.cc b/content/renderer/renderer_blink_platform_impl.cc index ccaf0f0..5a6bc392 100644 --- a/content/renderer/renderer_blink_platform_impl.cc +++ b/content/renderer/renderer_blink_platform_impl.cc
@@ -55,7 +55,6 @@ #include "content/renderer/media/audio_decoder.h" #include "content/renderer/media/renderer_webaudiodevice_impl.h" #include "content/renderer/media/webrtc/transmission_encoding_info_handler.h" -#include "content/renderer/media_capture_from_element/canvas_capture_handler.h" #include "content/renderer/media_capture_from_element/html_audio_element_capturer_source.h" #include "content/renderer/media_capture_from_element/html_video_element_capturer_source.h" #include "content/renderer/media_recorder/media_recorder_handler.h" @@ -129,7 +128,6 @@ using blink::WebAudioDevice; using blink::WebAudioLatencyHint; using blink::WebBlobRegistry; -using blink::WebCanvasCaptureHandler; using blink::WebDatabaseObserver; using blink::WebMediaPlayer; using blink::WebMediaRecorderHandler; @@ -759,17 +757,6 @@ //------------------------------------------------------------------------------ -std::unique_ptr<WebCanvasCaptureHandler> -RendererBlinkPlatformImpl::CreateCanvasCaptureHandler( - const WebSize& size, - double frame_rate, - WebMediaStreamTrack* track) { - return CanvasCaptureHandler::CreateCanvasCaptureHandler( - size, frame_rate, RenderThread::Get()->GetIOTaskRunner(), track); -} - -//------------------------------------------------------------------------------ - void RendererBlinkPlatformImpl::CreateHTMLVideoElementCapturer( WebMediaStream* web_media_stream, WebMediaPlayer* web_media_player,
diff --git a/content/renderer/renderer_blink_platform_impl.h b/content/renderer/renderer_blink_platform_impl.h index b3b1da1..62347939 100644 --- a/content/renderer/renderer_blink_platform_impl.h +++ b/content/renderer/renderer_blink_platform_impl.h
@@ -39,7 +39,6 @@ namespace scheduler { class WebThreadScheduler; } -class WebCanvasCaptureHandler; class WebGraphicsContext3DProvider; class WebMediaPlayer; class WebMediaRecorderHandler; @@ -160,10 +159,6 @@ blink::WebLocalFrame* frame) override; std::unique_ptr<webrtc::AsyncResolverFactory> CreateWebRtcAsyncResolverFactory() override; - std::unique_ptr<blink::WebCanvasCaptureHandler> CreateCanvasCaptureHandler( - const blink::WebSize& size, - double frame_rate, - blink::WebMediaStreamTrack* track) override; void CreateHTMLVideoElementCapturer( blink::WebMediaStream* web_media_stream, blink::WebMediaPlayer* web_media_player,
diff --git a/content/shell/BUILD.gn b/content/shell/BUILD.gn index 667a1b5..432cd72 100644 --- a/content/shell/BUILD.gn +++ b/content/shell/BUILD.gn
@@ -166,6 +166,8 @@ "browser/web_test/devtools_protocol_test_bindings.h", "browser/web_test/fake_bluetooth_chooser.cc", "browser/web_test/fake_bluetooth_chooser.h", + "browser/web_test/fake_bluetooth_scanning_prompt.cc", + "browser/web_test/fake_bluetooth_scanning_prompt.h", "browser/web_test/leak_detector.cc", "browser/web_test/leak_detector.h", "browser/web_test/mojo_web_test_helper.cc",
diff --git a/content/shell/browser/shell.cc b/content/shell/browser/shell.cc index a88c961e..4f881c65 100644 --- a/content/shell/browser/shell.cc +++ b/content/shell/browser/shell.cc
@@ -36,6 +36,7 @@ #include "content/shell/browser/shell_devtools_frontend.h" #include "content/shell/browser/shell_javascript_dialog_manager.h" #include "content/shell/browser/web_test/blink_test_controller.h" +#include "content/shell/browser/web_test/fake_bluetooth_scanning_prompt.h" #include "content/shell/browser/web_test/secondary_test_window_observer.h" #include "content/shell/browser/web_test/web_test_bluetooth_chooser_factory.h" #include "content/shell/browser/web_test/web_test_devtools_bindings.h" @@ -554,6 +555,12 @@ return nullptr; } +std::unique_ptr<BluetoothScanningPrompt> Shell::ShowBluetoothScanningPrompt( + RenderFrameHost* frame, + const BluetoothScanningPrompt::EventHandler& event_handler) { + return std::make_unique<FakeBluetoothScanningPrompt>(event_handler); +} + bool Shell::DidAddMessageToConsole(WebContents* source, blink::mojom::ConsoleMessageLevel log_level, const base::string16& message,
diff --git a/content/shell/browser/shell.h b/content/shell/browser/shell.h index 9080bde..c9103f60f 100644 --- a/content/shell/browser/shell.h +++ b/content/shell/browser/shell.h
@@ -170,6 +170,9 @@ std::unique_ptr<BluetoothChooser> RunBluetoothChooser( RenderFrameHost* frame, const BluetoothChooser::EventHandler& event_handler) override; + std::unique_ptr<BluetoothScanningPrompt> ShowBluetoothScanningPrompt( + RenderFrameHost* frame, + const BluetoothScanningPrompt::EventHandler& event_handler) override; #if defined(OS_MACOSX) bool HandleKeyboardEvent(WebContents* source, const NativeWebKeyboardEvent& event) override;
diff --git a/content/shell/browser/web_test/fake_bluetooth_scanning_prompt.cc b/content/shell/browser/web_test/fake_bluetooth_scanning_prompt.cc new file mode 100644 index 0000000..fb173c6 --- /dev/null +++ b/content/shell/browser/web_test/fake_bluetooth_scanning_prompt.cc
@@ -0,0 +1,18 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/shell/browser/web_test/fake_bluetooth_scanning_prompt.h" + +#include "base/callback.h" + +namespace content { + +FakeBluetoothScanningPrompt::FakeBluetoothScanningPrompt( + const EventHandler& event_handler) { + event_handler.Run(content::BluetoothScanningPrompt::Event::kAllow); +} + +FakeBluetoothScanningPrompt::~FakeBluetoothScanningPrompt() = default; + +} // namespace content
diff --git a/content/shell/browser/web_test/fake_bluetooth_scanning_prompt.h b/content/shell/browser/web_test/fake_bluetooth_scanning_prompt.h new file mode 100644 index 0000000..adc4650 --- /dev/null +++ b/content/shell/browser/web_test/fake_bluetooth_scanning_prompt.h
@@ -0,0 +1,23 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_SHELL_BROWSER_WEB_TEST_FAKE_BLUETOOTH_SCANNING_PROMPT_H_ +#define CONTENT_SHELL_BROWSER_WEB_TEST_FAKE_BLUETOOTH_SCANNING_PROMPT_H_ + +#include "base/macros.h" +#include "content/public/browser/bluetooth_scanning_prompt.h" + +namespace content { + +class FakeBluetoothScanningPrompt : public BluetoothScanningPrompt { + public: + explicit FakeBluetoothScanningPrompt(const EventHandler& event_handler); + ~FakeBluetoothScanningPrompt() override; + + DISALLOW_COPY_AND_ASSIGN(FakeBluetoothScanningPrompt); +}; + +} // namespace content + +#endif // CONTENT_SHELL_BROWSER_WEB_TEST_FAKE_BLUETOOTH_SCANNING_PROMPT_H_
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn index 0337e883..0182b8e 100644 --- a/content/test/BUILD.gn +++ b/content/test/BUILD.gn
@@ -1865,7 +1865,6 @@ "../renderer/media/webrtc/webrtc_set_description_observer_unittest.cc", "../renderer/media/webrtc/webrtc_video_track_source_unittest.cc", "../renderer/media/webrtc_local_audio_source_provider_unittest.cc", - "../renderer/media_capture_from_element/canvas_capture_handler_unittest.cc", "../renderer/media_capture_from_element/html_audio_element_capturer_source_unittest.cc", "../renderer/media_capture_from_element/html_video_element_capturer_source_unittest.cc", "../renderer/media_recorder/audio_track_recorder_unittest.cc",
diff --git a/extensions/browser/api/web_request/web_request_api_helpers.cc b/extensions/browser/api/web_request/web_request_api_helpers.cc index 557ed4b..8adac17 100644 --- a/extensions/browser/api/web_request/web_request_api_helpers.cc +++ b/extensions/browser/api/web_request/web_request_api_helpers.cc
@@ -100,7 +100,7 @@ UMA_HISTOGRAM_ENUMERATION("Extensions.WebRequest.RequestHeaderChanged", type); } -bool IsStringLowerCaseASCII(const std::string& s) { +bool IsStringLowerCaseASCII(base::StringPiece s) { return std::none_of(s.begin(), s.end(), base::IsAsciiUpper<char>); } @@ -165,9 +165,10 @@ return true; } -constexpr bool ValidateRequestHeaderEntries() { - for (size_t i = 0; i < base::size(kRequestHeaderEntries); ++i) { - if (!IsValidHeaderName(kRequestHeaderEntries[i].first)) +template <typename T> +constexpr bool ValidateHeaderEntries(const T& entries) { + for (size_t i = 0; i < base::size(entries); ++i) { + if (!IsValidHeaderName(entries[i].first)) return false; } return true; @@ -178,7 +179,8 @@ base::size(kRequestHeaderEntries), "Invalid number of request header entries"); -static_assert(ValidateRequestHeaderEntries(), "Invalid request header entries"); +static_assert(ValidateHeaderEntries(kRequestHeaderEntries), + "Invalid request header entries"); // Uses |record_func| to record |header|. If |header| is not recorded, false is // returned. @@ -200,6 +202,116 @@ record_func(type); } +void RecordResponseHeaderChanged(ResponseHeaderType type) { + UMA_HISTOGRAM_ENUMERATION("Extensions.WebRequest.ResponseHeaderChanged", + type); +} + +void RecordResponseHeaderAdded(ResponseHeaderType type) { + UMA_HISTOGRAM_ENUMERATION("Extensions.WebRequest.ResponseHeaderAdded", type); +} + +void RecordResponseHeaderRemoved(ResponseHeaderType type) { + UMA_HISTOGRAM_ENUMERATION("Extensions.WebRequest.ResponseHeaderRemoved", + type); +} + +using ResponseHeaderEntry = std::pair<const char*, ResponseHeaderType>; +constexpr ResponseHeaderEntry kResponseHeaderEntries[] = { + {"accept-patch", ResponseHeaderType::kAcceptPatch}, + {"accept-ranges", ResponseHeaderType::kAcceptRanges}, + {"access-control-allow-credentials", + ResponseHeaderType::kAccessControlAllowCredentials}, + {"access-control-allow-headers", + ResponseHeaderType::kAccessControlAllowHeaders}, + {"access-control-allow-methods", + ResponseHeaderType::kAccessControlAllowMethods}, + {"access-control-allow-origin", + ResponseHeaderType::kAccessControlAllowOrigin}, + {"access-control-expose-headers", + ResponseHeaderType::kAccessControlExposeHeaders}, + {"access-control-max-age", ResponseHeaderType::kAccessControlMaxAge}, + {"age", ResponseHeaderType::kAge}, + {"allow", ResponseHeaderType::kAllow}, + {"alt-svc", ResponseHeaderType::kAltSvc}, + {"cache-control", ResponseHeaderType::kCacheControl}, + {"clear-site-data", ResponseHeaderType::kClearSiteData}, + {"connection", ResponseHeaderType::kConnection}, + {"content-disposition", ResponseHeaderType::kContentDisposition}, + {"content-encoding", ResponseHeaderType::kContentEncoding}, + {"content-language", ResponseHeaderType::kContentLanguage}, + {"content-length", ResponseHeaderType::kContentLength}, + {"content-location", ResponseHeaderType::kContentLocation}, + {"content-range", ResponseHeaderType::kContentRange}, + {"content-security-policy", ResponseHeaderType::kContentSecurityPolicy}, + {"content-security-policy-report-only", + ResponseHeaderType::kContentSecurityPolicyReportOnly}, + {"content-type", ResponseHeaderType::kContentType}, + {"date", ResponseHeaderType::kDate}, + {"etag", ResponseHeaderType::kETag}, + {"expect-ct", ResponseHeaderType::kExpectCT}, + {"expires", ResponseHeaderType::kExpires}, + {"feature-policy", ResponseHeaderType::kFeaturePolicy}, + {"keep-alive", ResponseHeaderType::kKeepAlive}, + {"large-allocation", ResponseHeaderType::kLargeAllocation}, + {"last-modified", ResponseHeaderType::kLastModified}, + {"location", ResponseHeaderType::kLocation}, + {"pragma", ResponseHeaderType::kPragma}, + {"proxy-authenticate", ResponseHeaderType::kProxyAuthenticate}, + {"proxy-connection", ResponseHeaderType::kProxyConnection}, + {"public-key-pins", ResponseHeaderType::kPublicKeyPins}, + {"public-key-pins-report-only", + ResponseHeaderType::kPublicKeyPinsReportOnly}, + {"referrer-policy", ResponseHeaderType::kReferrerPolicy}, + {"refresh", ResponseHeaderType::kRefresh}, + {"retry-after", ResponseHeaderType::kRetryAfter}, + {"sec-websocket-accept", ResponseHeaderType::kSecWebSocketAccept}, + {"server", ResponseHeaderType::kServer}, + {"server-timing", ResponseHeaderType::kServerTiming}, + {"set-cookie", ResponseHeaderType::kSetCookie}, + {"sourcemap", ResponseHeaderType::kSourceMap}, + {"strict-transport-security", ResponseHeaderType::kStrictTransportSecurity}, + {"timing-allow-origin", ResponseHeaderType::kTimingAllowOrigin}, + {"tk", ResponseHeaderType::kTk}, + {"trailer", ResponseHeaderType::kTrailer}, + {"transfer-encoding", ResponseHeaderType::kTransferEncoding}, + {"upgrade", ResponseHeaderType::kUpgrade}, + {"vary", ResponseHeaderType::kVary}, + {"via", ResponseHeaderType::kVia}, + {"warning", ResponseHeaderType::kWarning}, + {"www-authenticate", ResponseHeaderType::kWWWAuthenticate}, + {"x-content-type-options", ResponseHeaderType::kXContentTypeOptions}, + {"x-dns-prefetch-control", ResponseHeaderType::kXDNSPrefetchControl}, + {"x-frame-options", ResponseHeaderType::kXFrameOptions}, + {"x-xss-protection", ResponseHeaderType::kXXSSProtection}, +}; + +void RecordResponseHeader(base::StringPiece header, + void (*record_func)(ResponseHeaderType)) { + using HeaderMapType = base::flat_map<base::StringPiece, ResponseHeaderType>; + static const base::NoDestructor<HeaderMapType> kHeaderMap([] { + std::vector<std::pair<base::StringPiece, ResponseHeaderType>> entries; + entries.reserve(base::size(kResponseHeaderEntries)); + for (const auto& entry : kResponseHeaderEntries) + entries.emplace_back(entry.first, entry.second); + return HeaderMapType(entries.begin(), entries.end()); + }()); + + DCHECK(IsStringLowerCaseASCII(header)); + auto it = kHeaderMap->find(header); + ResponseHeaderType type = + it != kHeaderMap->end() ? it->second : ResponseHeaderType::kOther; + record_func(type); +} + +// All entries other than kOther and kNone are mapped. +static_assert(static_cast<size_t>(ResponseHeaderType::kMaxValue) - 1 == + base::size(kResponseHeaderEntries), + "Invalid number of response header entries"); + +static_assert(ValidateHeaderEntries(kResponseHeaderEntries), + "Invalid response header entries"); + } // namespace IgnoredAction::IgnoredAction(extensions::ExtensionId extension_id, @@ -1299,26 +1411,54 @@ *allowed_unsafe_redirect_url = new_url; } - // TODO(https://crbug.com/827582): Remove once data is gathered. - bool set_cookie_modified = false; - for (const auto& header : added_headers) { - if (header.first == "set-cookie") { - set_cookie_modified = true; - break; - } - } - UMA_HISTOGRAM_BOOLEAN("Extensions.WebRequest.SetCookieResponseHeaderChanged", - set_cookie_modified); + // Record metrics. + { + auto record_response_headers = + [](const std::set<base::StringPiece>& headers, + void (*record_func)(ResponseHeaderType)) { + if (headers.empty()) { + record_func(ResponseHeaderType::kNone); + return; + } - bool set_cookie_removed = false; - for (const auto& header : removed_headers) { - if (header.first == "set-cookie") { - set_cookie_removed = true; - break; + for (const auto& header : headers) + RecordResponseHeader(header, record_func); + }; + + std::set<base::StringPiece> modified_header_names; + std::set<base::StringPiece> added_header_names; + std::set<base::StringPiece> removed_header_names; + for (const ResponseHeader& header : added_headers) { + // Skip logging this header if this was subsequently removed by an + // extension. + if (!override_response_headers->get()->HasHeader(header.first)) + continue; + + if (original_response_headers->HasHeader(header.first)) + modified_header_names.insert(header.first); + else + added_header_names.insert(header.first); } + + for (const ResponseHeader& header : removed_headers) { + if (!override_response_headers->get()->HasHeader(header.first)) + removed_header_names.insert(header.first); + else + modified_header_names.insert(header.first); + } + + DCHECK(std::all_of(modified_header_names.begin(), + modified_header_names.end(), IsStringLowerCaseASCII)); + DCHECK(std::all_of(added_header_names.begin(), added_header_names.end(), + IsStringLowerCaseASCII)); + DCHECK(std::all_of(removed_header_names.begin(), removed_header_names.end(), + IsStringLowerCaseASCII)); + + record_response_headers(modified_header_names, + &RecordResponseHeaderChanged); + record_response_headers(added_header_names, &RecordResponseHeaderAdded); + record_response_headers(removed_header_names, &RecordResponseHeaderRemoved); } - UMA_HISTOGRAM_BOOLEAN("Extensions.WebRequest.SetCookieResponseHeaderRemoved", - set_cookie_removed && !set_cookie_modified); } bool MergeOnAuthRequiredResponses(const EventResponseDeltas& deltas,
diff --git a/extensions/browser/api/web_request/web_request_api_helpers.h b/extensions/browser/api/web_request/web_request_api_helpers.h index bc3ee60..b02827fa 100644 --- a/extensions/browser/api/web_request/web_request_api_helpers.h +++ b/extensions/browser/api/web_request/web_request_api_helpers.h
@@ -94,6 +94,73 @@ kMaxValue = kXForwardedProto, }; +// These values are persisted to logs. Entries should not be renumbered and +// numeric values should never be reused. +enum class ResponseHeaderType { + kNone = 0, + kOther = 1, + kAcceptPatch = 2, + kAcceptRanges = 3, + kAccessControlAllowCredentials = 4, + kAccessControlAllowHeaders = 5, + kAccessControlAllowMethods = 6, + kAccessControlAllowOrigin = 7, + kAccessControlExposeHeaders = 8, + kAccessControlMaxAge = 9, + kAge = 10, + kAllow = 11, + kAltSvc = 12, + kCacheControl = 13, + kClearSiteData = 14, + kConnection = 15, + kContentDisposition = 16, + kContentEncoding = 17, + kContentLanguage = 18, + kContentLength = 19, + kContentLocation = 20, + kContentRange = 21, + kContentSecurityPolicy = 22, + kContentSecurityPolicyReportOnly = 23, + kContentType = 24, + kDate = 25, + kETag = 26, + kExpectCT = 27, + kExpires = 28, + kFeaturePolicy = 29, + kKeepAlive = 30, + kLargeAllocation = 31, + kLastModified = 32, + kLocation = 33, + kPragma = 34, + kProxyAuthenticate = 35, + kProxyConnection = 36, + kPublicKeyPins = 37, + kPublicKeyPinsReportOnly = 38, + kReferrerPolicy = 39, + kRefresh = 40, + kRetryAfter = 41, + kSecWebSocketAccept = 42, + kServer = 43, + kServerTiming = 44, + kSetCookie = 45, + kSourceMap = 46, + kStrictTransportSecurity = 47, + kTimingAllowOrigin = 48, + kTk = 49, + kTrailer = 50, + kTransferEncoding = 51, + kUpgrade = 52, + kVary = 53, + kVia = 54, + kWarning = 55, + kWWWAuthenticate = 56, + kXContentTypeOptions = 57, + kXDNSPrefetchControl = 58, + kXFrameOptions = 59, + kXXSSProtection = 60, + kMaxValue = kXXSSProtection +}; + struct IgnoredAction { IgnoredAction(extensions::ExtensionId extension_id, extensions::api::web_request::IgnoredActionType action_type);
diff --git a/extensions/common/api/networking_onc.idl b/extensions/common/api/networking_onc.idl index 9776b3ee..2f4c075 100644 --- a/extensions/common/api/networking_onc.idl +++ b/extensions/common/api/networking_onc.idl
@@ -295,8 +295,14 @@ // The IP address for a connection. Can be IPv4 or IPv6 address, depending // on value of <code>Type</code>. DOMString? IPAddress; + // Array of IP blocks in CIDR notation, see onc_spec.md for details. + DOMString[]? ExcludedRoutes; + // Array of IP blocks in CIDR notation, see onc_spec.md for details. + DOMString[]? IncludedRoutes; // Array of addresses used for name servers. DOMString[]? NameServers; + // Array of strings for name resolution, see onc_spec.md for details. + DOMString[]? SearchDomains; // The routing prefix. long? RoutingPrefix; // The IP configuration type. Can be <code>IPv4</code> or <code>IPv6</code>.
diff --git a/extensions/common/api/networking_private.idl b/extensions/common/api/networking_private.idl index 94d1085..a566854 100644 --- a/extensions/common/api/networking_private.idl +++ b/extensions/common/api/networking_private.idl
@@ -281,7 +281,10 @@ dictionary IPConfigProperties { DOMString? Gateway; DOMString? IPAddress; + DOMString[]? ExcludedRoutes; + DOMString[]? IncludedRoutes; DOMString[]? NameServers; + DOMString[]? SearchDomains; long? RoutingPrefix; DOMString? Type; DOMString? WebProxyAutoDiscoveryUrl;
diff --git a/extensions/common/extension.cc b/extensions/common/extension.cc index 56180dc..7858de7 100644 --- a/extensions/common/extension.cc +++ b/extensions/common/extension.cc
@@ -17,7 +17,6 @@ #include "base/json/json_writer.h" #include "base/logging.h" #include "base/memory/singleton.h" -#include "base/metrics/histogram_macros.h" #include "base/stl_util.h" #include "base/strings/strcat.h" #include "base/strings/string16.h" @@ -30,7 +29,6 @@ #include "base/values.h" #include "base/version.h" #include "components/crx_file/id_util.h" -#include "content/public/common/content_switches.h" #include "content/public/common/url_constants.h" #include "extensions/common/constants.h" #include "extensions/common/error_utils.h" @@ -194,27 +192,6 @@ return NULL; } - const base::CommandLine& command_line = - *base::CommandLine::ForCurrentProcess(); - std::string process_type = - command_line.GetSwitchValueASCII(::switches::kProcessType); - // Use microsecond accuracy for increased granularity. Max at 10 seconds. - base::TimeDelta elapsed_time = timer.Elapsed(); - const int kMaxTimeInMicroseconds = 10000000; - if (process_type.empty()) { - UMA_HISTOGRAM_CUSTOM_COUNTS( - "Extensions.ExtensionCreationTime.BrowserProcess", - elapsed_time.InMicroseconds(), 1, kMaxTimeInMicroseconds, 100); - } else if (command_line.HasSwitch(switches::kExtensionProcess)) { - UMA_HISTOGRAM_CUSTOM_COUNTS( - "Extensions.ExtensionCreationTime.ExtensionProcess", - elapsed_time.InMicroseconds(), 1, kMaxTimeInMicroseconds, 100); - } else if (process_type == ::switches::kRendererProcess) { - UMA_HISTOGRAM_CUSTOM_COUNTS( - "Extensions.ExtensionCreationTime.RendererProcess", - elapsed_time.InMicroseconds(), 1, kMaxTimeInMicroseconds, 100); - } - return extension; }
diff --git a/extensions/common/switches.cc b/extensions/common/switches.cc index 3b67662..fa7f9ad9 100644 --- a/extensions/common/switches.cc +++ b/extensions/common/switches.cc
@@ -26,14 +26,6 @@ const char kDisableDesktopCaptureAudio[] = "disable-audio-support-for-desktop-share"; -// FeatureSwitch and about_flags don't play nice. Feature switch expects either -// --enable-<feature> or --<feature>=1, but about_flags expects the command -// line argument to enable it (or a selection). Hack this in, so enabling it -// in about_flags enables the feature. Appending this flag has the same effect -// as --embedded-extension-options=1. -const char kEnableEmbeddedExtensionOptions[] = - "enable-embedded-extension-options"; - // Enables extension APIs that are in development. const char kEnableExperimentalExtensionApis[] = "enable-experimental-extension-apis";
diff --git a/extensions/common/switches.h b/extensions/common/switches.h index e992d5f2..96161b1 100644 --- a/extensions/common/switches.h +++ b/extensions/common/switches.h
@@ -16,7 +16,6 @@ extern const char kDisableDesktopCaptureAudio[]; extern const char kDisableExtensionsHttpThrottling[]; extern const char kEmbeddedExtensionOptions[]; -extern const char kEnableEmbeddedExtensionOptions[]; extern const char kEnableExperimentalExtensionApis[]; extern const char kEnableOverrideBookmarksUI[]; extern const char kEnableBLEAdvertising[];
diff --git a/gpu/command_buffer/common/capabilities.h b/gpu/command_buffer/common/capabilities.h index 0a03c8e..b9ea901 100644 --- a/gpu/command_buffer/common/capabilities.h +++ b/gpu/command_buffer/common/capabilities.h
@@ -171,6 +171,7 @@ bool dc_layers = false; bool use_dc_overlays_for_video = false; bool protected_video_swap_chain = false; + bool gpu_vsync = false; // When this parameter is true, a CHROMIUM image created with RGB format will // actually have RGBA format. The client is responsible for handling most of
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc index bdf18ec6..a29de70 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -4242,6 +4242,7 @@ caps.dc_layers = supports_dc_layers_; caps.use_dc_overlays_for_video = surface_->UseOverlaysForVideo(); caps.protected_video_swap_chain = surface_->SupportsProtectedVideo(); + caps.gpu_vsync = surface_->SupportsGpuVSync(); caps.blend_equation_advanced = feature_info_->feature_flags().blend_equation_advanced;
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc index 3c043a23..cf2fcb3 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc
@@ -1369,6 +1369,7 @@ caps.commit_overlay_planes = surface_->SupportsCommitOverlayPlanes(); caps.use_dc_overlays_for_video = surface_->UseOverlaysForVideo(); caps.protected_video_swap_chain = surface_->SupportsProtectedVideo(); + caps.gpu_vsync = surface_->SupportsGpuVSync(); caps.texture_npot = feature_info_->feature_flags().npot_ok; caps.chromium_gpu_fence = feature_info_->feature_flags().chromium_gpu_fence; caps.chromium_nonblocking_readback = true;
diff --git a/gpu/config/gpu_finch_features.cc b/gpu/config/gpu_finch_features.cc index a1d8134..60f320a7 100644 --- a/gpu/config/gpu_finch_features.cc +++ b/gpu/config/gpu_finch_features.cc
@@ -63,6 +63,8 @@ const base::Feature kDefaultPassthroughCommandDecoder{ "DefaultPassthroughCommandDecoder", base::FEATURE_DISABLED_BY_DEFAULT}; +const base::Feature kDirectCompositionGpuVSync{ + "DirectCompositionGpuVSync", base::FEATURE_DISABLED_BY_DEFAULT}; // Overrides preferred overlay format to NV12 instead of YUY2. const base::Feature kDirectCompositionPreferNV12Overlays{
diff --git a/gpu/config/gpu_finch_features.h b/gpu/config/gpu_finch_features.h index a5c12e52..08ce217 100644 --- a/gpu/config/gpu_finch_features.h +++ b/gpu/config/gpu_finch_features.h
@@ -27,6 +27,8 @@ GPU_EXPORT extern const base::Feature kDefaultPassthroughCommandDecoder; +GPU_EXPORT extern const base::Feature kDirectCompositionGpuVSync; + GPU_EXPORT extern const base::Feature kDirectCompositionPreferNV12Overlays; GPU_EXPORT extern const base::Feature kDirectCompositionUnderlays;
diff --git a/gpu/ipc/DEPS b/gpu/ipc/DEPS index b82b151b..1adc037f 100644 --- a/gpu/ipc/DEPS +++ b/gpu/ipc/DEPS
@@ -1,5 +1,7 @@ include_rules = [ "+components/viz/common/features.h", + "+components/viz/common/display/update_vsync_parameters_callback.h", + "+components/viz/common/gpu/gpu_vsync_callback.h", "+components/viz/common/resources/resource_format.h", ]
diff --git a/gpu/ipc/common/gpu_command_buffer_traits_multi.h b/gpu/ipc/common/gpu_command_buffer_traits_multi.h index b6a8e1a..775ae704 100644 --- a/gpu/ipc/common/gpu_command_buffer_traits_multi.h +++ b/gpu/ipc/common/gpu_command_buffer_traits_multi.h
@@ -139,6 +139,7 @@ IPC_STRUCT_TRAITS_MEMBER(dc_layers) IPC_STRUCT_TRAITS_MEMBER(use_dc_overlays_for_video) IPC_STRUCT_TRAITS_MEMBER(protected_video_swap_chain) + IPC_STRUCT_TRAITS_MEMBER(gpu_vsync) IPC_STRUCT_TRAITS_MEMBER(disable_non_empty_post_sub_buffers) IPC_STRUCT_TRAITS_MEMBER(avoid_stencil_buffers) IPC_STRUCT_TRAITS_MEMBER(disable_2d_canvas_copy_on_write)
diff --git a/gpu/ipc/in_process_command_buffer.cc b/gpu/ipc/in_process_command_buffer.cc index c1e240e3..7be22bfd 100644 --- a/gpu/ipc/in_process_command_buffer.cc +++ b/gpu/ipc/in_process_command_buffer.cc
@@ -381,6 +381,8 @@ origin_task_runner_ = std::move(task_runner); } + client_thread_weak_ptr_ = client_thread_weak_ptr_factory_.GetWeakPtr(); + Capabilities capabilities; InitializeOnGpuThreadParams params(surface_handle, attribs, &capabilities, image_factory, gr_shader_cache, @@ -824,9 +826,8 @@ } } - PostOrRunClientCallback( - base::BindOnce(&InProcessCommandBuffer::OnContextLost, - client_thread_weak_ptr_factory_.GetWeakPtr())); + PostOrRunClientCallback(base::BindOnce(&InProcessCommandBuffer::OnContextLost, + client_thread_weak_ptr_)); } void InProcessCommandBuffer::OnContextLost() { @@ -1252,9 +1253,9 @@ void InProcessCommandBuffer::HandleReturnData(base::span<const uint8_t> data) { DCHECK_CALLED_ON_VALID_SEQUENCE(gpu_sequence_checker_); std::vector<uint8_t> vec(data.data(), data.data() + data.size()); - PostOrRunClientCallback(base::BindOnce( - &InProcessCommandBuffer::HandleReturnDataOnOriginThread, - client_thread_weak_ptr_factory_.GetWeakPtr(), std::move(vec))); + PostOrRunClientCallback( + base::BindOnce(&InProcessCommandBuffer::HandleReturnDataOnOriginThread, + client_thread_weak_ptr_, std::move(vec))); } void InProcessCommandBuffer::PostOrRunClientCallback( @@ -1562,7 +1563,7 @@ PostOrRunClientCallback(base::BindOnce( &InProcessCommandBuffer::DidSwapBuffersCompleteOnOriginThread, - client_thread_weak_ptr_factory_.GetWeakPtr(), base::Passed(¶ms))); + client_thread_weak_ptr_, base::Passed(¶ms))); } const gles2::FeatureInfo* InProcessCommandBuffer::GetFeatureInfo() const { @@ -1582,10 +1583,9 @@ SwapBufferParams params = pending_presented_params_.front(); pending_presented_params_.pop_front(); - PostOrRunClientCallback( - base::BindOnce(&InProcessCommandBuffer::BufferPresentedOnOriginThread, - client_thread_weak_ptr_factory_.GetWeakPtr(), - params.swap_id, params.flags, feedback)); + PostOrRunClientCallback(base::BindOnce( + &InProcessCommandBuffer::BufferPresentedOnOriginThread, + client_thread_weak_ptr_, params.swap_id, params.flags, feedback)); } void InProcessCommandBuffer::AddFilter(IPC::MessageFilter* message_filter) { @@ -1612,10 +1612,9 @@ if (gpu_control_client_) gpu_control_client_->OnSwapBufferPresented(swap_id, feedback); - if (update_vsync_parameters_completion_callback_ && - ShouldUpdateVsyncParams(feedback)) { - update_vsync_parameters_completion_callback_.Run(feedback.timestamp, - feedback.interval); + if (update_vsync_parameters_callback_ && ShouldUpdateVsyncParams(feedback)) { + update_vsync_parameters_callback_.Run(feedback.timestamp, + feedback.interval); } } @@ -1628,9 +1627,9 @@ } void InProcessCommandBuffer::SetUpdateVSyncParametersCallback( - const UpdateVSyncParametersCallback& callback) { + viz::UpdateVSyncParametersCallback callback) { DCHECK_CALLED_ON_VALID_SEQUENCE(client_sequence_checker_); - update_vsync_parameters_completion_callback_ = callback; + update_vsync_parameters_callback_ = std::move(callback); } void InProcessCommandBuffer::UpdateActiveUrl() { @@ -1638,4 +1637,47 @@ ContextUrl::SetActiveUrl(active_url_); } +void InProcessCommandBuffer::SetGpuVSyncCallback( + viz::GpuVSyncCallback callback) { + DCHECK_CALLED_ON_VALID_SEQUENCE(client_sequence_checker_); + gpu_vsync_callback_ = std::move(callback); +} + +void InProcessCommandBuffer::SetGpuVSyncEnabled(bool enabled) { + DCHECK_CALLED_ON_VALID_SEQUENCE(client_sequence_checker_); + ScheduleGpuTask( + base::BindOnce(&InProcessCommandBuffer::SetGpuVSyncEnabledOnThread, + gpu_thread_weak_ptr_factory_.GetWeakPtr(), enabled)); +} + +void InProcessCommandBuffer::SetGpuVSyncEnabledOnThread(bool enabled) { + DCHECK_CALLED_ON_VALID_SEQUENCE(gpu_sequence_checker_); + if (surface_) + surface_->SetGpuVSyncEnabled(enabled); +} + +viz::GpuVSyncCallback InProcessCommandBuffer::GetGpuVSyncCallback() { + auto handle_gpu_vsync_callback = + base::BindRepeating(&InProcessCommandBuffer::HandleGpuVSyncOnOriginThread, + client_thread_weak_ptr_); + auto forward_callback = + [](scoped_refptr<base::SequencedTaskRunner> task_runner, + viz::GpuVSyncCallback callback, base::TimeTicks vsync_time, + base::TimeDelta vsync_interval) { + task_runner->PostTask( + FROM_HERE, base::BindOnce(callback, vsync_time, vsync_interval)); + }; + return base::BindRepeating(forward_callback, + base::RetainedRef(origin_task_runner_), + std::move(handle_gpu_vsync_callback)); +} + +void InProcessCommandBuffer::HandleGpuVSyncOnOriginThread( + base::TimeTicks vsync_time, + base::TimeDelta vsync_interval) { + DCHECK_CALLED_ON_VALID_SEQUENCE(client_sequence_checker_); + if (gpu_vsync_callback_) + gpu_vsync_callback_.Run(vsync_time, vsync_interval); +} + } // namespace gpu
diff --git a/gpu/ipc/in_process_command_buffer.h b/gpu/ipc/in_process_command_buffer.h index 34ee148..db5450bc 100644 --- a/gpu/ipc/in_process_command_buffer.h +++ b/gpu/ipc/in_process_command_buffer.h
@@ -23,6 +23,8 @@ #include "base/single_thread_task_runner.h" #include "base/synchronization/lock.h" #include "base/synchronization/waitable_event.h" +#include "components/viz/common/display/update_vsync_parameters_callback.h" +#include "components/viz/common/gpu/gpu_vsync_callback.h" #include "components/viz/common/resources/resource_format.h" #include "gpu/command_buffer/client/gpu_control.h" #include "gpu/command_buffer/common/command_buffer.h" @@ -170,16 +172,19 @@ void BufferPresented(const gfx::PresentationFeedback& feedback) override; void AddFilter(IPC::MessageFilter* message_filter) override; int32_t GetRouteID() const override; + viz::GpuVSyncCallback GetGpuVSyncCallback() override; // Upstream this function to GpuControl if needs arise. Can be called on any // thread. const GpuFeatureInfo& GetGpuFeatureInfo() const; - using UpdateVSyncParametersCallback = - base::RepeatingCallback<void(base::TimeTicks timebase, - base::TimeDelta interval)>; void SetUpdateVSyncParametersCallback( - const UpdateVSyncParametersCallback& callback); + viz::UpdateVSyncParametersCallback callback); + + void SetGpuVSyncCallback(viz::GpuVSyncCallback callback); + void SetGpuVSyncEnabled(bool enabled); + + void SetGpuVSyncEnabledOnThread(bool enabled); gpu::ServiceTransferCache* GetTransferCacheForTest() const; int GetRasterDecoderIdForTest() const; @@ -308,6 +313,8 @@ const gfx::PresentationFeedback& feedback); void HandleReturnDataOnOriginThread(std::vector<uint8_t> data); + void HandleGpuVSyncOnOriginThread(base::TimeTicks vsync_time, + base::TimeDelta vsync_interval); const CommandBufferId command_buffer_id_; const ContextUrl active_url_; @@ -364,7 +371,9 @@ scoped_refptr<gl::GLShareGroup> gl_share_group_; base::WaitableEvent fence_sync_wait_event_; - UpdateVSyncParametersCallback update_vsync_parameters_completion_callback_; + // Callbacks on client thread. + viz::UpdateVSyncParametersCallback update_vsync_parameters_callback_; + viz::GpuVSyncCallback gpu_vsync_callback_; // Params pushed each time we call OnSwapBuffers, and popped when a buffer // is presented or a swap completed. @@ -377,6 +386,10 @@ scoped_refptr<SharedContextState> context_state_; + base::WeakPtr<InProcessCommandBuffer> client_thread_weak_ptr_; + + // Don't use |client_thread_weak_ptr_factory_| on GPU thread. Use the cached + // |client_thread_weak_ptr_| instead. base::WeakPtrFactory<InProcessCommandBuffer> client_thread_weak_ptr_factory_; base::WeakPtrFactory<InProcessCommandBuffer> gpu_thread_weak_ptr_factory_;
diff --git a/gpu/ipc/service/DEPS b/gpu/ipc/service/DEPS index 91c8d49..c6f813963 100644 --- a/gpu/ipc/service/DEPS +++ b/gpu/ipc/service/DEPS
@@ -2,6 +2,7 @@ "+cc/paint", "+components/crash/core/common/crash_key.h", "+components/viz/common/features.h", + "+components/viz/common/gpu/gpu_vsync_callback.h", "+components/viz/common/gpu/vulkan_context_provider.h", "+components/viz/common/resources/resource_format.h", "+third_party/skia",
diff --git a/gpu/ipc/service/direct_composition_surface_win.cc b/gpu/ipc/service/direct_composition_surface_win.cc index 1663a26..b6f06c8 100644 --- a/gpu/ipc/service/direct_composition_surface_win.cc +++ b/gpu/ipc/service/direct_composition_surface_win.cc
@@ -9,6 +9,7 @@ #include <memory> #include <utility> +#include "base/bind.h" #include "base/metrics/histogram_functions.h" #include "base/metrics/histogram_macros.h" #include "base/trace_event/trace_event.h" @@ -19,6 +20,7 @@ #include "gpu/ipc/service/direct_composition_child_surface_win.h" #include "ui/gl/gl_angle_util_win.h" #include "ui/gl/gl_surface_presentation_helper.h" +#include "ui/gl/vsync_thread_win.h" #ifndef EGL_ANGLE_flexible_surface_compatibility #define EGL_ANGLE_flexible_surface_compatibility 1 @@ -197,6 +199,7 @@ root_surface_(new DirectCompositionChildSurfaceWin()), layer_tree_(std::make_unique<DCLayerTree>( delegate->GetFeatureInfo()->workarounds())), + delegate_(delegate), vsync_provider_(std::move(vsync_provider)), presentation_helper_(std::make_unique<gl::GLSurfacePresentationHelper>( vsync_provider_.get())) {} @@ -386,7 +389,6 @@ return hdr_monitor_found; } -// static bool DirectCompositionSurfaceWin::Initialize(gl::GLSurfaceFormat format) { d3d11_device_ = gl::QueryD3D11DeviceObjectFromANGLE(); if (!d3d11_device_) { @@ -407,6 +409,12 @@ } window_ = child_window_.window(); + auto vsync_callback = delegate_->GetGpuVSyncCallback(); + if (SupportsGpuVSync() && vsync_callback) { + vsync_thread_ = std::make_unique<gl::VSyncThreadWin>( + window_, d3d11_device_, std::move(vsync_callback)); + } + if (!layer_tree_->Initialize(window_, d3d11_device_, dcomp_device_)) return false; @@ -417,6 +425,8 @@ } void DirectCompositionSurfaceWin::Destroy() { + // Destroy vsync thread because joining it could call OnVSync. + vsync_thread_ = nullptr; // Destroy presentation helper first because its dtor calls GetHandle. presentation_helper_ = nullptr; root_surface_->Destroy(); @@ -453,16 +463,12 @@ gl::GLSurfacePresentationHelper::ScopedSwapBuffers scoped_swap_buffers( presentation_helper_.get(), std::move(callback)); - bool succeeded = true; - if (root_surface_->SwapBuffers(PresentationCallback()) == - gfx::SwapResult::SWAP_FAILED) - succeeded = false; + gfx::SwapResult swap_result = + root_surface_->SwapBuffers(PresentationCallback()); if (!layer_tree_->CommitAndClearPendingOverlays(root_surface_.get())) - succeeded = false; + swap_result = gfx::SwapResult::SWAP_FAILED; - auto swap_result = - succeeded ? gfx::SwapResult::SWAP_ACK : gfx::SwapResult::SWAP_FAILED; scoped_swap_buffers.set_result(swap_result); return swap_result; } @@ -535,6 +541,15 @@ return root_surface_->GetDrawOffset(); } +bool DirectCompositionSurfaceWin::SupportsGpuVSync() const { + return base::FeatureList::IsEnabled(features::kDirectCompositionGpuVSync); +} + +void DirectCompositionSurfaceWin::SetGpuVSyncEnabled(bool enabled) { + DCHECK(vsync_thread_); + vsync_thread_->SetEnabled(enabled); +} + scoped_refptr<base::TaskRunner> DirectCompositionSurfaceWin::GetWindowTaskRunnerForTesting() { return child_window_.GetTaskRunnerForTesting();
diff --git a/gpu/ipc/service/direct_composition_surface_win.h b/gpu/ipc/service/direct_composition_surface_win.h index 3c347e1..ab66705 100644 --- a/gpu/ipc/service/direct_composition_surface_win.h +++ b/gpu/ipc/service/direct_composition_surface_win.h
@@ -17,6 +17,7 @@ namespace gl { class GLSurfacePresentationHelper; +class VSyncThreadWin; } namespace gpu { @@ -98,6 +99,8 @@ bool SupportsProtectedVideo() const override; bool SetDrawRectangle(const gfx::Rect& rect) override; gfx::Vector2d GetDrawOffset() const override; + bool SupportsGpuVSync() const override; + void SetGpuVSyncEnabled(bool enabled) override; // This schedules an overlay plane to be displayed on the next SwapBuffers // or PostSubBuffer call. Overlay planes must be scheduled before every swap @@ -121,8 +124,10 @@ HWND window_ = nullptr; ChildWindowWin child_window_; + std::unique_ptr<gl::VSyncThreadWin> vsync_thread_; scoped_refptr<DirectCompositionChildSurfaceWin> root_surface_; std::unique_ptr<DCLayerTree> layer_tree_; + base::WeakPtr<ImageTransportSurfaceDelegate> delegate_; std::unique_ptr<gfx::VSyncProvider> vsync_provider_; std::unique_ptr<gl::GLSurfacePresentationHelper> presentation_helper_;
diff --git a/gpu/ipc/service/direct_composition_surface_win_unittest.cc b/gpu/ipc/service/direct_composition_surface_win_unittest.cc index 88a3195..de2aac4 100644 --- a/gpu/ipc/service/direct_composition_surface_win_unittest.cc +++ b/gpu/ipc/service/direct_composition_surface_win_unittest.cc
@@ -69,6 +69,9 @@ void BufferPresented(const gfx::PresentationFeedback& feedback) override {} void AddFilter(IPC::MessageFilter* message_filter) override {} int32_t GetRouteID() const override { return 0; } + viz::GpuVSyncCallback GetGpuVSyncCallback() override { + return viz::GpuVSyncCallback(); + } private: scoped_refptr<gpu::gles2::FeatureInfo> feature_info_;
diff --git a/gpu/ipc/service/gles2_command_buffer_stub.cc b/gpu/ipc/service/gles2_command_buffer_stub.cc index 2559626..939397d 100644 --- a/gpu/ipc/service/gles2_command_buffer_stub.cc +++ b/gpu/ipc/service/gles2_command_buffer_stub.cc
@@ -428,6 +428,10 @@ return route_id_; } +viz::GpuVSyncCallback GLES2CommandBufferStub::GetGpuVSyncCallback() { + return viz::GpuVSyncCallback(); +} + MemoryTracker* GLES2CommandBufferStub::GetMemoryTracker() const { return context_group_->memory_tracker(); }
diff --git a/gpu/ipc/service/gles2_command_buffer_stub.h b/gpu/ipc/service/gles2_command_buffer_stub.h index 6e09643..8ef5016 100644 --- a/gpu/ipc/service/gles2_command_buffer_stub.h +++ b/gpu/ipc/service/gles2_command_buffer_stub.h
@@ -52,6 +52,7 @@ void AddFilter(IPC::MessageFilter* message_filter) override; int32_t GetRouteID() const override; + viz::GpuVSyncCallback GetGpuVSyncCallback() override; private: bool HandleMessage(const IPC::Message& message) override;
diff --git a/gpu/ipc/service/image_transport_surface_delegate.h b/gpu/ipc/service/image_transport_surface_delegate.h index 76a99b9..52f9d6f 100644 --- a/gpu/ipc/service/image_transport_surface_delegate.h +++ b/gpu/ipc/service/image_transport_surface_delegate.h
@@ -6,6 +6,7 @@ #define GPU_IPC_SERVICE_IMAGE_TRANSPORT_SURFACE_DELEGATE_H_ #include "base/callback.h" +#include "components/viz/common/gpu/gpu_vsync_callback.h" #include "gpu/command_buffer/common/texture_in_use_response.h" #include "gpu/ipc/common/surface_handle.h" #include "gpu/ipc/service/gpu_ipc_service_export.h" @@ -51,6 +52,9 @@ // Gets route ID for sending / receiving IPC messages. virtual int32_t GetRouteID() const = 0; + // Callback for GPU vsync signal. May be called on a different thread. + virtual viz::GpuVSyncCallback GetGpuVSyncCallback() = 0; + protected: virtual ~ImageTransportSurfaceDelegate() = default; };
diff --git a/ios/chrome/browser/about_flags.mm b/ios/chrome/browser/about_flags.mm index eee58f5..dcd496c 100644 --- a/ios/chrome/browser/about_flags.mm +++ b/ios/chrome/browser/about_flags.mm
@@ -583,6 +583,9 @@ {"language-settings", flag_descriptions::kLanguageSettingsName, flag_descriptions::kLanguageSettingsDescription, flags_ui::kOsIos, FEATURE_VALUE_TYPE(kLanguageSettings)}, + {"lock-bottom-toolbar", flag_descriptions::kLockBottomToolbarName, + flag_descriptions::kLockBottomToolbarDescription, flags_ui::kOsIos, + FEATURE_VALUE_TYPE(fullscreen::features::kLockBottomToolbar)}, }; // Add all switches from experimental flags to |command_line|.
diff --git a/ios/chrome/browser/infobars/infobar_metrics_recorder.h b/ios/chrome/browser/infobars/infobar_metrics_recorder.h index 1c944ee..30cb4dd 100644 --- a/ios/chrome/browser/infobars/infobar_metrics_recorder.h +++ b/ios/chrome/browser/infobars/infobar_metrics_recorder.h
@@ -41,6 +41,24 @@ kMaxValue = ExpandedToModal, }; +// Values for the UMA Mobile.Messages.Modal.Event histogram. These values +// are persisted to logs. Entries should not be renumbered and numeric values +// should never be reused. +enum class MobileMessagesModalEvent { + // Infobar Modal was accepted. + Accepted = 0, + // Infobar Modal was canceled. + Canceled = 1, + // Infobar Modal was dismissed. + Dismissed = 2, + // Infobar Modal was presented. + Presented = 3, + // Infobar Modal settings were opened. + SettingsOpened = 4, + // Highest enumerator. Recommended by Histogram metrics best practices. + kMaxValue = SettingsOpened, +}; + // Used to record metrics related to Infobar events. @interface InfobarMetricsRecorder : NSObject @@ -55,6 +73,9 @@ // Records histogram for Banner |dismissType|. - (void)recordBannerDismissType:(MobileMessagesBannerDismissType)dismissType; +// Records histogram for Modal |event|. +- (void)recordModalEvent:(MobileMessagesModalEvent)event; + @end #endif // IOS_CHROME_BROWSER_INFOBARS_INFOBAR_METRICS_RECORDER_H_
diff --git a/ios/chrome/browser/infobars/infobar_metrics_recorder.mm b/ios/chrome/browser/infobars/infobar_metrics_recorder.mm index 7658109..8b90820f 100644 --- a/ios/chrome/browser/infobars/infobar_metrics_recorder.mm +++ b/ios/chrome/browser/infobars/infobar_metrics_recorder.mm
@@ -18,13 +18,29 @@ "Mobile.Messages.Banner.Event.InfobarTypeConfirm"; const char kInfobarConfirmBannerDismissTypeHistogram[] = "Mobile.Messages.Banner.Dismiss.InfobarTypeConfirm"; +// Modal. +const char kInfobarConfirmModalEventHistogram[] = + "Mobile.Messages.Modal.Event.InfobarTypeConfirm"; -// Histogram names for InfobarTypePassword. +// Histogram names for InfobarTypePasswordSave. // Banner. -const char kInfobarPasswordBannerEventHistogram[] = - "Mobile.Messages.Banner.Event.InfobarTypePassword"; -const char kInfobarPasswordBannerDismissTypeHistogram[] = - "Mobile.Messages.Banner.Dismiss.InfobarTypePassword"; +const char kInfobarPasswordSaveBannerEventHistogram[] = + "Mobile.Messages.Banner.Event.InfobarTypePasswordSave"; +const char kInfobarPasswordSaveBannerDismissTypeHistogram[] = + "Mobile.Messages.Banner.Dismiss.InfobarTypePasswordSave"; +// Modal. +const char kInfobarPasswordSaveModalEventHistogram[] = + "Mobile.Messages.Modal.Event.InfobarTypePasswordSave"; + +// Histogram names for InfobarTypePasswordUpdate. +// Banner. +const char kInfobarPasswordUpdateBannerEventHistogram[] = + "Mobile.Messages.Banner.Event.InfobarTypePasswordUpdate"; +const char kInfobarPasswordUpdateBannerDismissTypeHistogram[] = + "Mobile.Messages.Banner.Dismiss.InfobarTypePasswordUpdate"; +// Modal. +const char kInfobarPasswordUpdateModalEventHistogram[] = + "Mobile.Messages.Modal.Event.InfobarTypePasswordUpdate"; } // namespace @@ -50,8 +66,13 @@ case InfobarType::kInfobarTypeConfirm: UMA_HISTOGRAM_ENUMERATION(kInfobarConfirmBannerEventHistogram, event); break; - case InfobarType::kInfobarTypePassword: - UMA_HISTOGRAM_ENUMERATION(kInfobarPasswordBannerEventHistogram, event); + case InfobarType::kInfobarTypePasswordSave: + UMA_HISTOGRAM_ENUMERATION(kInfobarPasswordSaveBannerEventHistogram, + event); + break; + case InfobarType::kInfobarTypePasswordUpdate: + UMA_HISTOGRAM_ENUMERATION(kInfobarPasswordUpdateBannerEventHistogram, + event); break; } } @@ -62,10 +83,29 @@ UMA_HISTOGRAM_ENUMERATION(kInfobarConfirmBannerDismissTypeHistogram, dismissType); break; - case InfobarType::kInfobarTypePassword: - UMA_HISTOGRAM_ENUMERATION(kInfobarPasswordBannerDismissTypeHistogram, + case InfobarType::kInfobarTypePasswordSave: + UMA_HISTOGRAM_ENUMERATION(kInfobarPasswordSaveBannerDismissTypeHistogram, dismissType); break; + case InfobarType::kInfobarTypePasswordUpdate: + UMA_HISTOGRAM_ENUMERATION( + kInfobarPasswordUpdateBannerDismissTypeHistogram, dismissType); + break; + } +} + +- (void)recordModalEvent:(MobileMessagesModalEvent)event { + switch (self.infobarType) { + case InfobarType::kInfobarTypeConfirm: + UMA_HISTOGRAM_ENUMERATION(kInfobarConfirmModalEventHistogram, event); + break; + case InfobarType::kInfobarTypePasswordSave: + UMA_HISTOGRAM_ENUMERATION(kInfobarPasswordSaveModalEventHistogram, event); + break; + case InfobarType::kInfobarTypePasswordUpdate: + UMA_HISTOGRAM_ENUMERATION(kInfobarPasswordUpdateModalEventHistogram, + event); + break; } }
diff --git a/ios/chrome/browser/infobars/infobar_type.h b/ios/chrome/browser/infobars/infobar_type.h index 2043c5f9..2955658f 100644 --- a/ios/chrome/browser/infobars/infobar_type.h +++ b/ios/chrome/browser/infobars/infobar_type.h
@@ -10,8 +10,10 @@ enum class InfobarType { // Generic Infobar that contains a Message and an action Button. kInfobarTypeConfirm = 0, - // Message Infobar for Saving or Updating a password. - kInfobarTypePassword = 1, + // Message Infobar for Saving a password. + kInfobarTypePasswordSave = 1, + // Message Infobar for Updating a password. + kInfobarTypePasswordUpdate = 2, }; #endif // IOS_CHROME_BROWSER_INFOBARS_INFOBAR_TYPE_H_
diff --git a/ios/chrome/browser/ios_chrome_flag_descriptions.cc b/ios/chrome/browser/ios_chrome_flag_descriptions.cc index 774cbdfa..835ebdf 100644 --- a/ios/chrome/browser/ios_chrome_flag_descriptions.cc +++ b/ios/chrome/browser/ios_chrome_flag_descriptions.cc
@@ -294,6 +294,11 @@ "Enables the Language Settings page allowing modifications to user " "preferred languages and translate preferences."; +const char kLockBottomToolbarName[] = "Lock bottom toolbar"; +const char kLockBottomToolbarDescription[] = + "When enabled, the bottom toolbar will not get collapsed when scrolling " + "into fullscreen mode."; + const char kMarkHttpAsName[] = "Mark non-secure origins as non-secure"; const char kMarkHttpAsDescription[] = "Change the UI treatment for HTTP pages";
diff --git a/ios/chrome/browser/ios_chrome_flag_descriptions.h b/ios/chrome/browser/ios_chrome_flag_descriptions.h index 32a07345..cf6c92bb 100644 --- a/ios/chrome/browser/ios_chrome_flag_descriptions.h +++ b/ios/chrome/browser/ios_chrome_flag_descriptions.h
@@ -240,6 +240,10 @@ extern const char kLanguageSettingsName[]; extern const char kLanguageSettingsDescription[]; +// Title and description for the flag to lock the bottom toolbar into place. +extern const char kLockBottomToolbarName[]; +extern const char kLockBottomToolbarDescription[]; + // Title, description, and options for the MarkHttpAs setting that controls // display of omnibox warnings about non-secure pages. extern const char kMarkHttpAsName[];
diff --git a/ios/chrome/browser/passwords/BUILD.gn b/ios/chrome/browser/passwords/BUILD.gn index 9104cc88..3ea6c87 100644 --- a/ios/chrome/browser/passwords/BUILD.gn +++ b/ios/chrome/browser/passwords/BUILD.gn
@@ -108,6 +108,7 @@ "ios_chrome_save_password_infobar_delegate.mm", ] deps = [ + ":public", "//base", "//components/infobars/core", "//components/password_manager/core/browser", @@ -119,6 +120,17 @@ ] } +source_set("public") { + configs += [ "//build/config/compiler:enable_arc" ] + sources = [ + "ios_chrome_password_infobar_metrics_recorder.h", + "ios_chrome_password_infobar_metrics_recorder.mm", + ] + deps = [ + "//base", + ] +} + source_set("feature_flags") { configs += [ "//build/config/compiler:enable_arc" ] sources = [
diff --git a/ios/chrome/browser/passwords/ios_chrome_password_infobar_metrics_recorder.h b/ios/chrome/browser/passwords/ios_chrome_password_infobar_metrics_recorder.h new file mode 100644 index 0000000..ff02acb96 --- /dev/null +++ b/ios/chrome/browser/passwords/ios_chrome_password_infobar_metrics_recorder.h
@@ -0,0 +1,81 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_PASSWORDS_IOS_CHROME_PASSWORD_INFOBAR_METRICS_RECORDER_H_ +#define IOS_CHROME_BROWSER_PASSWORDS_IOS_CHROME_PASSWORD_INFOBAR_METRICS_RECORDER_H_ + +#import <Foundation/Foundation.h> + +// Password Infobars types. Since these are used for metrics, entries should not +// be renumbered and numeric values should never be reused. +enum class PasswordInfobarType { + // Message Infobar for Saving a password. + kPasswordInfobarTypeSave = 0, + // Message Infobar for Updating a password. + kPasswordInfobarTypeUpdate = 1, +}; + +// Values for the UMA Mobile.Messages.Passwords.Modal.Event histogram. These +// values are persisted to logs. Entries should not be renumbered and numeric +// values should never be reused. +enum class MobileMessagesPasswordsModalEvent { + // PasswordInfobar username was edited. + EditedUserName = 1, + // PasswordInfobar password was edited. + EditedPassword = 2, + // PasswordInfobar password was unmasked. + UnmaskedPassword = 3, + // Highest enumerator. Recommended by Histogram metrics best practices. + kMaxValue = UnmaskedPassword, +}; + +// Values for the UMA Mobile.Messages.Passwords.Modal.Dismiss histogram. These +// values are persisted to logs. Entries should not be renumbered and numeric +// values should never be reused. +enum class MobileMessagesPasswordsModalDismiss { + // PasswordInfobar was tapped on Never For This Site. + TappedNeverForThisSite = 0, + // PasswordInfobar credentials were saved. + SavedCredentials = 1, + // PasswordInfobar credentials were updated. + UpdatedCredentials = 2, + // Highest enumerator. Recommended by Histogram metrics best practices. + kMaxValue = UpdatedCredentials, +}; + +// Values for the UMA Mobile.Messages.Passwords.Modal.Present histogram. These +// values are persisted to logs. Entries should not be renumbered and numeric +// values should never be reused. +enum class MobileMessagesPasswordsModalPresent { + // PasswordInfobar was presented after a Save Password banner was + // presented. + PresentedAfterSaveBanner = 0, + // PasswordInfobar was presented after an Update Password banner was + // presented. + PresentedAfterUpdateBanner = 1, + // Highest enumerator. Recommended by Histogram metrics best practices. + kMaxValue = PresentedAfterUpdateBanner, +}; + +// Used to record metrics related to Password Infobar events. +@interface IOSChromePasswordInfobarMetricsRecorder : NSObject + +// Designated initializer. IOSChromePasswordInfobarMetricsRecorder will record +// metrics for |passwordInfobarType|. +- (instancetype)initWithType:(PasswordInfobarType)passwordInfobarType + NS_DESIGNATED_INITIALIZER; +- (instancetype)init NS_UNAVAILABLE; + +// Records histogram for Modal |event|. +- (void)recordModalEvent:(MobileMessagesPasswordsModalEvent)event; + +// Records histogram for Modal |dismissType|. +- (void)recordModalDismiss:(MobileMessagesPasswordsModalDismiss)dismissType; + +// Records histogram for Modal |presentContext|. +- (void)recordModalPresent:(MobileMessagesPasswordsModalPresent)presentContext; + +@end + +#endif // IOS_CHROME_BROWSER_PASSWORDS_IOS_CHROME_PASSWORD_INFOBAR_METRICS_RECORDER_H_
diff --git a/ios/chrome/browser/passwords/ios_chrome_password_infobar_metrics_recorder.mm b/ios/chrome/browser/passwords/ios_chrome_password_infobar_metrics_recorder.mm new file mode 100644 index 0000000..2003da0 --- /dev/null +++ b/ios/chrome/browser/passwords/ios_chrome_password_infobar_metrics_recorder.mm
@@ -0,0 +1,88 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ios/chrome/browser/passwords/ios_chrome_password_infobar_metrics_recorder.h" + +#include "base/metrics/histogram_macros.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +namespace { + +// Histogram names for PasswordInfobarTypeSave. +// Modal. +const char kPasswordInfobarSaveModalEventHistogram[] = + "Mobile.Messages.Passwords.Modal.Event.InfobarTypePasswordSave"; +const char kPasswordInfobarSaveModalDismissHistogram[] = + "Mobile.Messages.Passwords.Modal.Dismiss.InfobarTypePasswordSave"; +const char kPasswordInfobarSaveModalPresentHistogram[] = + "Mobile.Messages.Passwords.Modal.Present.InfobarTypePasswordSave"; + +// Histogram names for PasswordInfobarTypeUpdate. +// Modal. +const char kPasswordInfobarUpdateModalEventHistogram[] = + "Mobile.Messages.Passwords.Modal.Event.InfobarTypePasswordUpdate"; +const char kPasswordInfobarUpdateModalDismissHistogram[] = + "Mobile.Messages.Passwords.Modal.Dismiss.InfobarTypePasswordUpdate"; +const char kPasswordInfobarUpdateModalPresentHistogram[] = + "Mobile.Messages.Passwords.Modal.Present.InfobarTypePasswordUpdate"; + +} // namespace + +@interface IOSChromePasswordInfobarMetricsRecorder () +// The Password Infobar type for the metrics recorder. +@property(nonatomic, assign) PasswordInfobarType passwordInfobarType; +@end + +@implementation IOSChromePasswordInfobarMetricsRecorder + +- (instancetype)initWithType:(PasswordInfobarType)passwordInfobarType { + self = [super init]; + if (self) { + _passwordInfobarType = passwordInfobarType; + } + return self; +} + +- (void)recordModalEvent:(MobileMessagesPasswordsModalEvent)event { + switch (self.passwordInfobarType) { + case PasswordInfobarType::kPasswordInfobarTypeSave: + UMA_HISTOGRAM_ENUMERATION(kPasswordInfobarSaveModalEventHistogram, event); + break; + case PasswordInfobarType::kPasswordInfobarTypeUpdate: + UMA_HISTOGRAM_ENUMERATION(kPasswordInfobarUpdateModalEventHistogram, + event); + break; + } +} + +- (void)recordModalDismiss:(MobileMessagesPasswordsModalDismiss)dismissType { + switch (self.passwordInfobarType) { + case PasswordInfobarType::kPasswordInfobarTypeSave: + UMA_HISTOGRAM_ENUMERATION(kPasswordInfobarSaveModalDismissHistogram, + dismissType); + break; + case PasswordInfobarType::kPasswordInfobarTypeUpdate: + UMA_HISTOGRAM_ENUMERATION(kPasswordInfobarUpdateModalDismissHistogram, + dismissType); + break; + } +} + +- (void)recordModalPresent:(MobileMessagesPasswordsModalPresent)presentContext { + switch (self.passwordInfobarType) { + case PasswordInfobarType::kPasswordInfobarTypeSave: + UMA_HISTOGRAM_ENUMERATION(kPasswordInfobarSaveModalPresentHistogram, + presentContext); + break; + case PasswordInfobarType::kPasswordInfobarTypeUpdate: + UMA_HISTOGRAM_ENUMERATION(kPasswordInfobarUpdateModalPresentHistogram, + presentContext); + break; + } +} + +@end
diff --git a/ios/chrome/browser/passwords/ios_chrome_save_password_infobar_delegate.h b/ios/chrome/browser/passwords/ios_chrome_save_password_infobar_delegate.h index 3961a02..3c348d8 100644 --- a/ios/chrome/browser/passwords/ios_chrome_save_password_infobar_delegate.h +++ b/ios/chrome/browser/passwords/ios_chrome_save_password_infobar_delegate.h
@@ -8,6 +8,7 @@ #include <memory> #include "base/macros.h" +#import "ios/chrome/browser/passwords/ios_chrome_password_infobar_metrics_recorder.h" #include "ios/chrome/browser/passwords/ios_chrome_password_manager_infobar_delegate.h" @protocol ApplicationCommands; @@ -65,7 +66,11 @@ // true if the current set of credentials has already been saved at the moment // the InfobarModal is created. - bool current_password_saved = false; + bool current_password_saved_ = false; + + // The PasswordInfobarType for this delegate. Set at initialization and won't + // change throughout the life of the delegate. + const PasswordInfobarType infobar_type_; DISALLOW_COPY_AND_ASSIGN(IOSChromeSavePasswordInfoBarDelegate); };
diff --git a/ios/chrome/browser/passwords/ios_chrome_save_password_infobar_delegate.mm b/ios/chrome/browser/passwords/ios_chrome_save_password_infobar_delegate.mm index c94abb9..abc12d5 100644 --- a/ios/chrome/browser/passwords/ios_chrome_save_password_infobar_delegate.mm +++ b/ios/chrome/browser/passwords/ios_chrome_save_password_infobar_delegate.mm
@@ -32,14 +32,35 @@ std::unique_ptr<PasswordFormManagerForUI> form_manager) : IOSChromePasswordManagerInfoBarDelegate(is_sync_user, std::move(form_manager)), - password_update_(password_update) { - form_to_save()->GetMetricsRecorder()->RecordPasswordBubbleShown( - form_to_save()->GetCredentialSource(), - password_manager::metrics_util::AUTOMATIC_WITH_PASSWORD_PENDING); + password_update_(password_update), + infobar_type_(password_update + ? PasswordInfobarType::kPasswordInfobarTypeUpdate + : PasswordInfobarType::kPasswordInfobarTypeSave) { + if (password_update) { + form_to_save()->GetMetricsRecorder()->RecordPasswordBubbleShown( + form_to_save()->GetCredentialSource(), + password_manager::metrics_util::AUTOMATIC_WITH_PASSWORD_PENDING_UPDATE); + + } else { + form_to_save()->GetMetricsRecorder()->RecordPasswordBubbleShown( + form_to_save()->GetCredentialSource(), + password_manager::metrics_util::AUTOMATIC_WITH_PASSWORD_PENDING); + } } IOSChromeSavePasswordInfoBarDelegate::~IOSChromeSavePasswordInfoBarDelegate() { - password_manager::metrics_util::LogSaveUIDismissalReason(infobar_response()); + switch (infobar_type_) { + case PasswordInfobarType::kPasswordInfobarTypeUpdate: { + DCHECK(IsInfobarUIRebootEnabled()); + password_manager::metrics_util::LogUpdateUIDismissalReason( + infobar_response()); + break; + } + case PasswordInfobarType::kPasswordInfobarTypeSave: + password_manager::metrics_util::LogSaveUIDismissalReason( + infobar_response()); + break; + } form_to_save()->GetMetricsRecorder()->RecordUIDismissalReason( infobar_response()); } @@ -93,7 +114,7 @@ form_to_save()->Save(); set_infobar_response(password_manager::metrics_util::CLICKED_SAVE); password_update_ = true; - current_password_saved = true; + current_password_saved_ = true; return true; } @@ -127,5 +148,5 @@ bool IOSChromeSavePasswordInfoBarDelegate::IsCurrentPasswordSaved() const { DCHECK(IsInfobarUIRebootEnabled()); - return current_password_saved; + return current_password_saved_; }
diff --git a/ios/chrome/browser/ui/browser_view/browser_view_controller.mm b/ios/chrome/browser/ui/browser_view/browser_view_controller.mm index 3e82ad9..4219053 100644 --- a/ios/chrome/browser/ui/browser_view/browser_view_controller.mm +++ b/ios/chrome/browser/ui/browser_view/browser_view_controller.mm
@@ -3749,6 +3749,10 @@ // Translates the footer view up and down according to |progress|, where a // progress of 1.0 fully shows the footer and a progress of 0.0 fully hides it. - (void)updateFootersForFullscreenProgress:(CGFloat)progress { + // If the bottom toolbar is locked into place, reset |progress| to 1.0. + if (base::FeatureList::IsEnabled(fullscreen::features::kLockBottomToolbar)) + progress = 1.0; + self.footerFullscreenProgress = progress; CGFloat height = 0.0; @@ -3790,8 +3794,13 @@ // safe area, so the unsafe top height must be added. CGFloat top = AlignValueToPixel( self.headerHeight + (progress - 1.0) * [self nonFullscreenToolbarHeight]); - CGFloat bottom = - AlignValueToPixel(progress * [self secondaryToolbarHeightWithInset]); + // If the bottom toolbar is locked into place, use 1.0 instead of |progress|. + CGFloat bottomProgress = + base::FeatureList::IsEnabled(fullscreen::features::kLockBottomToolbar) + ? 1.0 + : progress; + CGFloat bottom = AlignValueToPixel(bottomProgress * + [self secondaryToolbarHeightWithInset]); if (self.usesSafeInsetsForViewportAdjustments) { if (fullscreen::features::GetActiveViewportExperiment() ==
diff --git a/ios/chrome/browser/ui/fullscreen/fullscreen_features.h b/ios/chrome/browser/ui/fullscreen/fullscreen_features.h index 59e5ac6..916a651a 100644 --- a/ios/chrome/browser/ui/fullscreen/fullscreen_features.h +++ b/ios/chrome/browser/ui/fullscreen/fullscreen_features.h
@@ -5,6 +5,7 @@ #ifndef IOS_CHROME_BROWSER_UI_FULLSCREEN_FULLSCREEN_FEATURES_H_ #define IOS_CHROME_BROWSER_UI_FULLSCREEN_FULLSCREEN_FEATURES_H_ +#include "base/feature_list.h" #include "components/flags_ui/feature_entry.h" namespace fullscreen { @@ -36,6 +37,10 @@ // from the command line. ViewportAdjustmentExperiment GetActiveViewportExperiment(); +// Used to control whether the bottom toolbar should be locked into the extended +// position (i.e. fullscreen progress == 1.0). +extern const base::Feature kLockBottomToolbar; + } // namespace features } // namespace fullscreen
diff --git a/ios/chrome/browser/ui/fullscreen/fullscreen_features.mm b/ios/chrome/browser/ui/fullscreen/fullscreen_features.mm index 247e7f1..0d4f0b9d 100644 --- a/ios/chrome/browser/ui/fullscreen/fullscreen_features.mm +++ b/ios/chrome/browser/ui/fullscreen/fullscreen_features.mm
@@ -66,5 +66,8 @@ : ViewportAdjustmentExperiment::FRAME; } +const base::Feature kLockBottomToolbar{"LockBottomToolbar", + base::FEATURE_DISABLED_BY_DEFAULT}; + } // namespace features } // namespace fullscreen
diff --git a/ios/chrome/browser/ui/fullscreen/fullscreen_model.h b/ios/chrome/browser/ui/fullscreen/fullscreen_model.h index 2861938..f750501 100644 --- a/ios/chrome/browser/ui/fullscreen/fullscreen_model.h +++ b/ios/chrome/browser/ui/fullscreen/fullscreen_model.h
@@ -11,6 +11,7 @@ #include "base/macros.h" #include "base/observer_list.h" #import "ios/chrome/browser/ui/broadcaster/chrome_broadcast_observer_bridge.h" +#import "ios/chrome/browser/ui/fullscreen/fullscreen_features.h" #import "ios/chrome/browser/ui/fullscreen/scoped_fullscreen_disabler.h" class FullscreenModelObserver; @@ -72,10 +73,14 @@ // Returns the toolbar insets at |progress|. UIEdgeInsets GetToolbarInsetsAtProgress(CGFloat progress) const { + const CGFloat kBottomToolbarProgress = + base::FeatureList::IsEnabled(fullscreen::features::kLockBottomToolbar) + ? 1.0 + : progress; return UIEdgeInsetsMake( collapsed_toolbar_height_ + progress * (expanded_toolbar_height_ - collapsed_toolbar_height_), - 0, progress * bottom_toolbar_height_, 0); + 0, kBottomToolbarProgress * bottom_toolbar_height_, 0); } // Increments and decrements |disabled_counter_| for features that require the
diff --git a/ios/chrome/browser/ui/infobars/coordinators/BUILD.gn b/ios/chrome/browser/ui/infobars/coordinators/BUILD.gn index e87f773..12eb5e1 100644 --- a/ios/chrome/browser/ui/infobars/coordinators/BUILD.gn +++ b/ios/chrome/browser/ui/infobars/coordinators/BUILD.gn
@@ -17,7 +17,9 @@ "//base", "//components/infobars/core", "//ios/chrome/browser/infobars:public", + "//ios/chrome/browser/infobars:public", "//ios/chrome/browser/passwords:infobar_delegates", + "//ios/chrome/browser/passwords:public", "//ios/chrome/browser/ui/commands", "//ios/chrome/browser/ui/coordinators:chrome_coordinators", "//ios/chrome/browser/ui/fullscreen",
diff --git a/ios/chrome/browser/ui/infobars/coordinators/infobar_coordinator.mm b/ios/chrome/browser/ui/infobars/coordinators/infobar_coordinator.mm index 5539427..73975416 100644 --- a/ios/chrome/browser/ui/infobars/coordinators/infobar_coordinator.mm +++ b/ios/chrome/browser/ui/infobars/coordinators/infobar_coordinator.mm
@@ -213,10 +213,6 @@ // Deselect infobar badge in parallel with modal dismissal. [self.badgeDelegate infobarModalWillDismiss]; __weak __typeof(self) weakSelf = self; - ProceduralBlock modalCleanUp = ^{ - weakSelf.modalTransitionDriver = nil; - [weakSelf infobarWasDismissed]; - }; // If the Modal is being presented by the Banner, call dismiss on it. // This way the modal dismissal will animate correctly and the completion @@ -225,7 +221,6 @@ [self.bannerViewController dismissViewControllerAnimated:animated completion:^{ - modalCleanUp(); [weakSelf dismissInfobarBannerAnimated:NO completion:completion]; @@ -233,7 +228,6 @@ } else { [self.baseViewController dismissViewControllerAnimated:animated completion:^{ - modalCleanUp(); if (completion) completion(); }]; @@ -244,6 +238,15 @@ } } +- (void)modalInfobarWasDismissed:(id)sender { + // infobarModalWillDismiss call is needed, because sometimes the + // baseViewController will dismiss the modal without going through the + // coordinator. + [self.badgeDelegate infobarModalWillDismiss]; + self.modalTransitionDriver = nil; + [self infobarWasDismissed]; +} + #pragma mark InfobarModalPositioner - (CGFloat)modalHeight {
diff --git a/ios/chrome/browser/ui/infobars/coordinators/infobar_password_coordinator.mm b/ios/chrome/browser/ui/infobars/coordinators/infobar_password_coordinator.mm index 117ecfc..1d87991 100644 --- a/ios/chrome/browser/ui/infobars/coordinators/infobar_password_coordinator.mm +++ b/ios/chrome/browser/ui/infobars/coordinators/infobar_password_coordinator.mm
@@ -6,6 +6,7 @@ #include "base/strings/sys_string_conversions.h" #include "ios/chrome/browser/infobars/infobar_controller_delegate.h" +#import "ios/chrome/browser/passwords/ios_chrome_password_infobar_metrics_recorder.h" #import "ios/chrome/browser/passwords/ios_chrome_save_password_infobar_delegate.h" #import "ios/chrome/browser/ui/commands/application_commands.h" #import "ios/chrome/browser/ui/infobars/banners/infobar_banner_view_controller.h" @@ -29,6 +30,8 @@ // InfobarPasswordTableViewController owned by this Coordinator. @property(nonatomic, strong) InfobarPasswordTableViewController* modalViewController; +// The InfobarType for the banner presented by this Coordinator. +@property(nonatomic, assign, readonly) InfobarType infobarBannerType; @end @@ -43,6 +46,12 @@ self = [super initWithInfoBarDelegate:passwordInfoBarDelegate]; if (self) { _passwordInfoBarDelegate = passwordInfoBarDelegate; + // Set |_infobarBannerType| at init time since + // passwordInfoBarDelegate->IsPasswordUpdate() can change after the user has + // interacted with the ModalInfobar. + _infobarBannerType = passwordInfoBarDelegate->IsPasswordUpdate() + ? InfobarType::kInfobarTypePasswordUpdate + : InfobarType::kInfobarTypePasswordSave; } return self; } @@ -54,7 +63,7 @@ self.started = YES; self.bannerViewController = [[InfobarBannerViewController alloc] initWithDelegate:self - type:InfobarType::kInfobarTypePassword]; + type:self.infobarBannerType]; self.bannerViewController.titleText = base::SysUTF16ToNSString( self.passwordInfoBarDelegate->GetMessageText()); NSString* username = self.passwordInfoBarDelegate->GetUserNameText(); @@ -84,10 +93,17 @@ #pragma mark - InfobarCoordinatorImplementation - (void)configureModalViewController { + // Do not use |self.infobarBannerType| since the modal type might change each + // time is presented. e.g. We present a Modal of type Save and tap on "Save". + // The next time the Modal is presented we'll present a Modal of Type "Update" + // since the credentials are currently saved. + InfobarType infobarModalType = + self.passwordInfoBarDelegate->IsPasswordUpdate() + ? InfobarType::kInfobarTypePasswordUpdate + : InfobarType::kInfobarTypePasswordSave; self.modalViewController = [[InfobarPasswordTableViewController alloc] - initWithTableViewStyle:UITableViewStylePlain - appBarStyle:ChromeTableViewControllerStyleNoAppBar]; - self.modalViewController.infobarModalDelegate = self; + initWithDelegate:self + type:infobarModalType]; self.modalViewController.title = self.passwordInfoBarDelegate->GetInfobarModalTitleText(); self.modalViewController.username = @@ -109,6 +125,8 @@ self.modalViewController.URL = self.passwordInfoBarDelegate->GetURLHostText(); self.modalViewController.currentCredentialsSaved = self.passwordInfoBarDelegate->IsCurrentPasswordSaved(); + + [self recordModalPresentationMetricsUsingModalType:infobarModalType]; } - (void)dismissBannerWhenInteractionIsFinished { @@ -158,4 +176,39 @@ }]; } +#pragma mark - Helpers + +- (void)recordModalPresentationMetricsUsingModalType: + (InfobarType)infobarModalType { + IOSChromePasswordInfobarMetricsRecorder* passwordMetricsRecorder; + switch (infobarModalType) { + case InfobarType::kInfobarTypePasswordUpdate: + passwordMetricsRecorder = [[IOSChromePasswordInfobarMetricsRecorder alloc] + initWithType:PasswordInfobarType::kPasswordInfobarTypeUpdate]; + break; + case InfobarType::kInfobarTypePasswordSave: + passwordMetricsRecorder = [[IOSChromePasswordInfobarMetricsRecorder alloc] + initWithType:PasswordInfobarType::kPasswordInfobarTypeSave]; + break; + default: + NOTREACHED(); + break; + } + switch (self.infobarBannerType) { + case InfobarType::kInfobarTypePasswordUpdate: + [passwordMetricsRecorder + recordModalPresent:MobileMessagesPasswordsModalPresent:: + PresentedAfterUpdateBanner]; + break; + case InfobarType::kInfobarTypePasswordSave: + [passwordMetricsRecorder + recordModalPresent:MobileMessagesPasswordsModalPresent:: + PresentedAfterSaveBanner]; + break; + default: + NOTREACHED(); + break; + } +} + @end
diff --git a/ios/chrome/browser/ui/infobars/modals/BUILD.gn b/ios/chrome/browser/ui/infobars/modals/BUILD.gn index 930a93bd..0c4a7390 100644 --- a/ios/chrome/browser/ui/infobars/modals/BUILD.gn +++ b/ios/chrome/browser/ui/infobars/modals/BUILD.gn
@@ -16,6 +16,8 @@ ":public", "//base", "//ios/chrome/app/strings:ios_strings_grit", + "//ios/chrome/browser/infobars:public", + "//ios/chrome/browser/passwords:public", "//ios/chrome/browser/ui/table_view", "//ios/chrome/browser/ui/table_view:styler", "//ios/chrome/browser/ui/util",
diff --git a/ios/chrome/browser/ui/infobars/modals/infobar_modal_delegate.h b/ios/chrome/browser/ui/infobars/modals/infobar_modal_delegate.h index 88d296d..765f8af 100644 --- a/ios/chrome/browser/ui/infobars/modals/infobar_modal_delegate.h +++ b/ios/chrome/browser/ui/infobars/modals/infobar_modal_delegate.h
@@ -21,6 +21,9 @@ // action. - (void)modalInfobarButtonWasAccepted:(id)sender; +// Called when the InfobarModal was dismissed. +- (void)modalInfobarWasDismissed:(id)sender; + @end #endif // IOS_CHROME_BROWSER_UI_INFOBARS_MODALS_INFOBAR_MODAL_DELEGATE_H_
diff --git a/ios/chrome/browser/ui/infobars/modals/infobar_modal_view_controller.mm b/ios/chrome/browser/ui/infobars/modals/infobar_modal_view_controller.mm index bdf96e3..5856264 100644 --- a/ios/chrome/browser/ui/infobars/modals/infobar_modal_view_controller.mm +++ b/ios/chrome/browser/ui/infobars/modals/infobar_modal_view_controller.mm
@@ -52,6 +52,11 @@ self.navigationItem.rightBarButtonItem = settingsButton; } +- (void)viewDidDisappear:(BOOL)animated { + [self.infobarModalDelegate modalInfobarWasDismissed:self]; + [super viewDidDisappear:animated]; +} + #pragma mark - Private Methods - (void)dismissInfobarModal:(UIButton*)sender {
diff --git a/ios/chrome/browser/ui/infobars/modals/infobar_password_table_view_controller.h b/ios/chrome/browser/ui/infobars/modals/infobar_password_table_view_controller.h index 24da1a75..0167587c 100644 --- a/ios/chrome/browser/ui/infobars/modals/infobar_password_table_view_controller.h +++ b/ios/chrome/browser/ui/infobars/modals/infobar_password_table_view_controller.h
@@ -7,15 +7,22 @@ #import "ios/chrome/browser/ui/table_view/chrome_table_view_controller.h" +#import "ios/chrome/browser/infobars/infobar_type.h" + @protocol InfobarPasswordModalDelegate; // InfobarPasswordTableViewController represents the content for the Passwords // InfobarModal. @interface InfobarPasswordTableViewController : ChromeTableViewController -// InfobarPasswordModalDelegate for this ViewController. -@property(nonatomic, strong) id<InfobarPasswordModalDelegate> - infobarModalDelegate; +- (instancetype)initWithDelegate:(id<InfobarPasswordModalDelegate>)modalDelegate + type:(InfobarType)infobarType + NS_DESIGNATED_INITIALIZER; +- (instancetype)initWithTableViewStyle:(UITableViewStyle)style + appBarStyle: + (ChromeTableViewControllerStyle)appBarStyle + NS_UNAVAILABLE; + // The username being displayed in the InfobarModal. @property(nonatomic, copy) NSString* username; // The masked password being displayed in the InfobarModal.
diff --git a/ios/chrome/browser/ui/infobars/modals/infobar_password_table_view_controller.mm b/ios/chrome/browser/ui/infobars/modals/infobar_password_table_view_controller.mm index 9b02740..0a014471 100644 --- a/ios/chrome/browser/ui/infobars/modals/infobar_password_table_view_controller.mm +++ b/ios/chrome/browser/ui/infobars/modals/infobar_password_table_view_controller.mm
@@ -6,6 +6,8 @@ #include "base/logging.h" #include "base/mac/foundation_util.h" +#include "ios/chrome/browser/infobars/infobar_metrics_recorder.h" +#import "ios/chrome/browser/passwords/ios_chrome_password_infobar_metrics_recorder.h" #import "ios/chrome/browser/ui/infobars/modals/infobar_modal_constants.h" #import "ios/chrome/browser/ui/infobars/modals/infobar_password_modal_delegate.h" #import "ios/chrome/browser/ui/table_view/cells/table_view_cells_constants.h" @@ -49,10 +51,45 @@ @property(nonatomic, strong) TableViewTextButtonItem* cancelInfobarItem; // Username at the time the InfobarModal is presented. @property(nonatomic, copy) NSString* originalUsername; +// InfobarPasswordModalDelegate for this ViewController. +@property(nonatomic, strong) id<InfobarPasswordModalDelegate> + infobarModalDelegate; +// Used to build and record metrics. +@property(nonatomic, strong) InfobarMetricsRecorder* metricsRecorder; +// Used to build and record metrics specific to passwords. +@property(nonatomic, strong) + IOSChromePasswordInfobarMetricsRecorder* passwordMetricsRecorder; @end @implementation InfobarPasswordTableViewController +- (instancetype)initWithDelegate:(id<InfobarPasswordModalDelegate>)modalDelegate + type:(InfobarType)infobarType { + self = [super initWithTableViewStyle:UITableViewStylePlain + appBarStyle:ChromeTableViewControllerStyleNoAppBar]; + if (self) { + _infobarModalDelegate = modalDelegate; + _metricsRecorder = + [[InfobarMetricsRecorder alloc] initWithType:infobarType]; + switch (infobarType) { + case InfobarType::kInfobarTypePasswordUpdate: + _passwordMetricsRecorder = + [[IOSChromePasswordInfobarMetricsRecorder alloc] + initWithType:PasswordInfobarType::kPasswordInfobarTypeUpdate]; + break; + case InfobarType::kInfobarTypePasswordSave: + _passwordMetricsRecorder = + [[IOSChromePasswordInfobarMetricsRecorder alloc] + initWithType:PasswordInfobarType::kPasswordInfobarTypeSave]; + break; + default: + NOTREACHED(); + break; + } + } + return self; +} + #pragma mark - ViewController Lifecycle - (void)viewDidLoad { @@ -74,7 +111,7 @@ UIBarButtonItem* settingsButton = [[UIBarButtonItem alloc] initWithImage:settingsImage style:UIBarButtonItemStylePlain - target:self.infobarModalDelegate + target:self action:@selector(presentPasswordSettings)]; self.navigationItem.leftBarButtonItem = cancelButton; self.navigationItem.rightBarButtonItem = settingsButton; @@ -83,6 +120,17 @@ [self loadModel]; } +- (void)viewDidAppear:(BOOL)animated { + [super viewDidAppear:animated]; + [self.metricsRecorder recordModalEvent:MobileMessagesModalEvent::Presented]; +} + +- (void)viewDidDisappear:(BOOL)animated { + [self.infobarModalDelegate modalInfobarWasDismissed:self]; + [self.metricsRecorder recordModalEvent:MobileMessagesModalEvent::Dismissed]; + [super viewDidDisappear:animated]; +} + - (void)viewDidLayoutSubviews { [super viewDidLayoutSubviews]; self.tableView.scrollEnabled = @@ -169,19 +217,29 @@ TableViewTextButtonCell* tableViewTextButtonCell = base::mac::ObjCCastStrict<TableViewTextButtonCell>(cell); [tableViewTextButtonCell.button - addTarget:self.infobarModalDelegate + addTarget:self action:@selector(neverSaveCredentialsForCurrentSite) forControlEvents:UIControlEventTouchUpInside]; break; } - case ItemTypeUsername: - case ItemTypePassword: { + case ItemTypeUsername: { TableViewTextEditCell* editCell = base::mac::ObjCCast<TableViewTextEditCell>(cell); [editCell.textField addTarget:self + action:@selector(usernameEditDidBegin) + forControlEvents:UIControlEventEditingDidBegin]; + [editCell.textField addTarget:self action:@selector(updateSaveCredentialsButtonState) forControlEvents:UIControlEventEditingChanged]; + break; + } + case ItemTypePassword: { + TableViewTextEditCell* editCell = + base::mac::ObjCCast<TableViewTextEditCell>(cell); editCell.textField.delegate = self; + [editCell.textField addTarget:self + action:@selector(updateSaveCredentialsButtonState) + forControlEvents:UIControlEventEditingChanged]; break; } case ItemTypeURL: @@ -222,15 +280,46 @@ } - (void)dismissInfobarModal:(UIButton*)sender { + [self.metricsRecorder recordModalEvent:MobileMessagesModalEvent::Canceled]; [self.infobarModalDelegate dismissInfobarModal:sender animated:YES completion:nil]; } - (void)saveCredentialsButtonWasPressed:(UIButton*)sender { + [self.metricsRecorder recordModalEvent:MobileMessagesModalEvent::Accepted]; + if ([self.saveCredentialsItem.buttonText + isEqualToString:l10n_util::GetNSString( + IDS_IOS_PASSWORD_MANAGER_SAVE_BUTTON)]) { + [self.passwordMetricsRecorder + recordModalDismiss:MobileMessagesPasswordsModalDismiss:: + SavedCredentials]; + } else { + [self.passwordMetricsRecorder + recordModalDismiss:MobileMessagesPasswordsModalDismiss:: + UpdatedCredentials]; + } [self.infobarModalDelegate updateCredentialsWithUsername:self.usernameItem.textFieldValue password:self.unmaskedPassword]; } +- (void)presentPasswordSettings { + [self.metricsRecorder + recordModalEvent:MobileMessagesModalEvent::SettingsOpened]; + [self.infobarModalDelegate presentPasswordSettings]; +} + +- (void)neverSaveCredentialsForCurrentSite { + [self.passwordMetricsRecorder + recordModalDismiss:MobileMessagesPasswordsModalDismiss:: + TappedNeverForThisSite]; + [self.infobarModalDelegate neverSaveCredentialsForCurrentSite]; +} + +- (void)usernameEditDidBegin { + [self.passwordMetricsRecorder + recordModalEvent:MobileMessagesPasswordsModalEvent::EditedUserName]; +} + @end
diff --git a/ios/chrome/test/app/chrome_test_util.h b/ios/chrome/test/app/chrome_test_util.h index 8486bfcb..e3925efb 100644 --- a/ios/chrome/test/app/chrome_test_util.h +++ b/ios/chrome/test/app/chrome_test_util.h
@@ -1,3 +1,4 @@ + // Copyright 2016 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file.
diff --git a/ios/showcase/infobars/sc_infobar_banner_coordinator.mm b/ios/showcase/infobars/sc_infobar_banner_coordinator.mm index eacb502..9bd773ad 100644 --- a/ios/showcase/infobars/sc_infobar_banner_coordinator.mm +++ b/ios/showcase/infobars/sc_infobar_banner_coordinator.mm
@@ -147,4 +147,7 @@ completion:nil]; } +- (void)modalInfobarWasDismissed:(id)sender { +} + @end
diff --git a/ios/web/navigation/resources/restore_session.html b/ios/web/navigation/resources/restore_session.html index 8ee2e20..cd4d85c 100644 --- a/ios/web/navigation/resources/restore_session.html +++ b/ios/web/navigation/resources/restore_session.html
@@ -47,15 +47,6 @@ }; /** - * The window.onpopstate event fires when the user navigates to one of the - * history entries created by restoreSession(). This handler forces a reload - * to reidrect to the target URL. - */ - window.onpopstate = function(event) { - location.reload(); - } - - /** * Manipulates the current session history to mimic the provided serialized * history. * @param {string} sessionHistory An string serialization of a JSON object @@ -104,9 +95,15 @@ // history.length reaches sessionHistory.length. var currentItemOffset = parseInt(sessionHistoryObject.offset); var goWhenReady = setInterval(() => { - if (history.length == sessionHistoryObject.urls.length) { - history.go(currentItemOffset); - window.clearInterval(goWhenReady); + if (history.length == sessionHistoryObject.urls.length) { + history.go(currentItemOffset); + window.clearInterval(goWhenReady); + + // Queue a reload to redirect to the target URL after history.go + // is processed. + setTimeout(() => { + location.reload(); + }); } }, 10); } catch (e) {
diff --git a/ios/web/web_state/web_state_observer_inttest.mm b/ios/web/web_state/web_state_observer_inttest.mm index 67af665..f4f5fd9e 100644 --- a/ios/web/web_state/web_state_observer_inttest.mm +++ b/ios/web/web_state/web_state_observer_inttest.mm
@@ -2559,15 +2559,6 @@ /*for_main_frame=*/true)) .WillOnce(Return(true)); - // decide policy for restore_session.html?targetUrl=url0 again due to reload - // in onpopstate(). - EXPECT_CALL(*decider_, - ShouldAllowRequest(URLMatch(CreateRedirectUrl(url0)), _)) - .WillOnce(Return(true)); - EXPECT_CALL(*decider_, ShouldAllowResponse(URLMatch(CreateRedirectUrl(url0)), - /*for_main_frame=*/true)) - .WillOnce(Return(true)); - // Client-side redirect to |url0|. EXPECT_CALL(*decider_, ShouldAllowRequest(URLMatch(url0), _)) .WillOnce(Return(true));
diff --git a/media/audio/fuchsia/audio_output_stream_fuchsia.cc b/media/audio/fuchsia/audio_output_stream_fuchsia.cc index ae9435d..f247d5c 100644 --- a/media/audio/fuchsia/audio_output_stream_fuchsia.cc +++ b/media/audio/fuchsia/audio_output_stream_fuchsia.cc
@@ -148,6 +148,10 @@ if (payload_buffer_.IsValid() && GetMinBufferSize() > payload_buffer_.size()) { payload_buffer_ = {}; + + // Discard all packets currently in flight. This is required because + // AddPayloadBuffer() will fail if there are any packets in flight. + audio_renderer_->DiscardAllPacketsNoReply(); } }
diff --git a/media/capture/video/fake_video_capture_device.cc b/media/capture/video/fake_video_capture_device.cc index e95dcfb..25087db 100644 --- a/media/capture/video/fake_video_capture_device.cc +++ b/media/capture/video/fake_video_capture_device.cc
@@ -366,7 +366,7 @@ milliseconds, frame_count); canvas.scale(3, 3); canvas.drawSimpleText(time_string.data(), time_string.length(), - kUTF8_SkTextEncoding, 30, 20, font, paint); + SkTextEncoding::kUTF8, 30, 20, font, paint); if (pixel_format_ == Format::Y16) { // Use 8 bit bitmap rendered to first half of the buffer as high byte values
diff --git a/media/cast/receiver/video_decoder_unittest.cc b/media/cast/receiver/video_decoder_unittest.cc index e731618..85186498 100644 --- a/media/cast/receiver/video_decoder_unittest.cc +++ b/media/cast/receiver/video_decoder_unittest.cc
@@ -142,7 +142,7 @@ video_frame->coded_size().width()); EXPECT_EQ(expected_video_frame->coded_size().height(), video_frame->coded_size().height()); - EXPECT_LT(40.0, I420PSNR(expected_video_frame, video_frame)); + EXPECT_LT(40.0, I420PSNR(*expected_video_frame, *video_frame)); // TODO(miu): Once we start using VideoFrame::timestamp_, check that here. // Signal the main test thread that more video was decoded.
diff --git a/media/cast/sender/h264_vt_encoder_unittest.cc b/media/cast/sender/h264_vt_encoder_unittest.cc index 814cbc4..187603a 100644 --- a/media/cast/sender/h264_vt_encoder_unittest.cc +++ b/media/cast/sender/h264_vt_encoder_unittest.cc
@@ -153,7 +153,7 @@ ASSERT_LT(0u, expectations_.size()); auto& e = expectations_.front(); expectations_.pop(); - EXPECT_LE(kVideoAcceptedPSNR, I420PSNR(e, frame)); + EXPECT_LE(kVideoAcceptedPSNR, I420PSNR(*e, *frame)); ++count_frames_checked_; }
diff --git a/media/cast/test/end2end_unittest.cc b/media/cast/test/end2end_unittest.cc index a403c59..5c5f134 100644 --- a/media/cast/test/end2end_unittest.cc +++ b/media/cast/test/end2end_unittest.cc
@@ -364,7 +364,8 @@ base::TimeDelta()); PopulateVideoFrame(expected_I420_frame.get(), expected_video_frame.frame_number); - EXPECT_LE(kVideoAcceptedPSNR, I420PSNR(expected_I420_frame, video_frame)); + EXPECT_LE(kVideoAcceptedPSNR, + I420PSNR(*expected_I420_frame, *video_frame)); } EXPECT_NEAR(
diff --git a/media/cast/test/simulator.cc b/media/cast/test/simulator.cc index 70bb82a..c2404627 100644 --- a/media/cast/test/simulator.cc +++ b/media/cast/test/simulator.cc
@@ -270,8 +270,8 @@ if (video_frame_tracker) { scoped_refptr<media::VideoFrame> src_frame = video_frame_tracker->PopOldestEncodedFrame(); - metrics_output->psnr.push_back(I420PSNR(src_frame, video_frame)); - metrics_output->ssim.push_back(I420SSIM(src_frame, video_frame)); + metrics_output->psnr.push_back(I420PSNR(*src_frame, *video_frame)); + metrics_output->ssim.push_back(I420SSIM(*src_frame, *video_frame)); } if (!yuv_output.empty()) {
diff --git a/media/cast/test/utility/video_utility.cc b/media/cast/test/utility/video_utility.cc index e957c684..5319daa 100644 --- a/media/cast/test/utility/video_utility.cc +++ b/media/cast/test/utility/video_utility.cc
@@ -18,48 +18,48 @@ namespace media { namespace cast { -double I420PSNR(const scoped_refptr<media::VideoFrame>& frame1, - const scoped_refptr<media::VideoFrame>& frame2) { - if (frame1->visible_rect().width() != frame2->visible_rect().width() || - frame1->visible_rect().height() != frame2->visible_rect().height()) +double I420PSNR(const media::VideoFrame& frame1, + const media::VideoFrame& frame2) { + if (frame1.visible_rect().width() != frame2.visible_rect().width() || + frame1.visible_rect().height() != frame2.visible_rect().height()) return -1; - return libyuv::I420Psnr(frame1->visible_data(VideoFrame::kYPlane), - frame1->stride(VideoFrame::kYPlane), - frame1->visible_data(VideoFrame::kUPlane), - frame1->stride(VideoFrame::kUPlane), - frame1->visible_data(VideoFrame::kVPlane), - frame1->stride(VideoFrame::kVPlane), - frame2->visible_data(VideoFrame::kYPlane), - frame2->stride(VideoFrame::kYPlane), - frame2->visible_data(VideoFrame::kUPlane), - frame2->stride(VideoFrame::kUPlane), - frame2->visible_data(VideoFrame::kVPlane), - frame2->stride(VideoFrame::kVPlane), - frame1->visible_rect().width(), - frame1->visible_rect().height()); + return libyuv::I420Psnr(frame1.visible_data(VideoFrame::kYPlane), + frame1.stride(VideoFrame::kYPlane), + frame1.visible_data(VideoFrame::kUPlane), + frame1.stride(VideoFrame::kUPlane), + frame1.visible_data(VideoFrame::kVPlane), + frame1.stride(VideoFrame::kVPlane), + frame2.visible_data(VideoFrame::kYPlane), + frame2.stride(VideoFrame::kYPlane), + frame2.visible_data(VideoFrame::kUPlane), + frame2.stride(VideoFrame::kUPlane), + frame2.visible_data(VideoFrame::kVPlane), + frame2.stride(VideoFrame::kVPlane), + frame1.visible_rect().width(), + frame1.visible_rect().height()); } -double I420SSIM(const scoped_refptr<media::VideoFrame>& frame1, - const scoped_refptr<media::VideoFrame>& frame2) { - if (frame1->visible_rect().width() != frame2->visible_rect().width() || - frame1->visible_rect().height() != frame2->visible_rect().height()) +double I420SSIM(const media::VideoFrame& frame1, + const media::VideoFrame& frame2) { + if (frame1.visible_rect().width() != frame2.visible_rect().width() || + frame1.visible_rect().height() != frame2.visible_rect().height()) return -1; - return libyuv::I420Ssim(frame1->visible_data(VideoFrame::kYPlane), - frame1->stride(VideoFrame::kYPlane), - frame1->visible_data(VideoFrame::kUPlane), - frame1->stride(VideoFrame::kUPlane), - frame1->visible_data(VideoFrame::kVPlane), - frame1->stride(VideoFrame::kVPlane), - frame2->visible_data(VideoFrame::kYPlane), - frame2->stride(VideoFrame::kYPlane), - frame2->visible_data(VideoFrame::kUPlane), - frame2->stride(VideoFrame::kUPlane), - frame2->visible_data(VideoFrame::kVPlane), - frame2->stride(VideoFrame::kVPlane), - frame1->visible_rect().width(), - frame1->visible_rect().height()); + return libyuv::I420Ssim(frame1.visible_data(VideoFrame::kYPlane), + frame1.stride(VideoFrame::kYPlane), + frame1.visible_data(VideoFrame::kUPlane), + frame1.stride(VideoFrame::kUPlane), + frame1.visible_data(VideoFrame::kVPlane), + frame1.stride(VideoFrame::kVPlane), + frame2.visible_data(VideoFrame::kYPlane), + frame2.stride(VideoFrame::kYPlane), + frame2.visible_data(VideoFrame::kUPlane), + frame2.stride(VideoFrame::kUPlane), + frame2.visible_data(VideoFrame::kVPlane), + frame2.stride(VideoFrame::kVPlane), + frame1.visible_rect().width(), + frame1.visible_rect().height()); } void PopulateVideoFrame(VideoFrame* frame, int start_value) {
diff --git a/media/cast/test/utility/video_utility.h b/media/cast/test/utility/video_utility.h index 4987791a..8f7db30e 100644 --- a/media/cast/test/utility/video_utility.h +++ b/media/cast/test/utility/video_utility.h
@@ -13,12 +13,12 @@ namespace cast { // Compute and return PSNR between two frames. -double I420PSNR(const scoped_refptr<media::VideoFrame>& frame1, - const scoped_refptr<media::VideoFrame>& frame2); +double I420PSNR(const media::VideoFrame& frame1, + const media::VideoFrame& frame2); // Compute and return SSIM between two frames. -double I420SSIM(const scoped_refptr<media::VideoFrame>& frame1, - const scoped_refptr<media::VideoFrame>& frame2); +double I420SSIM(const media::VideoFrame& frame1, + const media::VideoFrame& frame2); // Populate a video |frame| with a plaid pattern, cycling from the given // |start_value|.
diff --git a/media/filters/dav1d_video_decoder.cc b/media/filters/dav1d_video_decoder.cc index b64d9d0..b533e99 100644 --- a/media/filters/dav1d_video_decoder.cc +++ b/media/filters/dav1d_video_decoder.cc
@@ -194,10 +194,13 @@ // // We only want 1 frame thread in low delay mode, since otherwise we'll // require at least two buffers before the first frame can be output. + // + // 2 frame threads seems desirable even on low core machines: + // https://crbug.com/957511 if (low_delay) s.n_frame_threads = 1; else if (s.n_frame_threads > max_threads - s.n_tile_threads) - s.n_frame_threads = std::max(1, max_threads - s.n_tile_threads); + s.n_frame_threads = std::max(2, max_threads - s.n_tile_threads); // Route dav1d internal logs through Chrome's DLOG system. s.logger = {nullptr, &LogDav1dMessage};
diff --git a/media/filters/stream_parser_factory.cc b/media/filters/stream_parser_factory.cc index 5b457773..8a6c43f 100644 --- a/media/filters/stream_parser_factory.cc +++ b/media/filters/stream_parser_factory.cc
@@ -230,6 +230,7 @@ CodecInfo::HISTOGRAM_FLAC}; static const CodecInfo* const kVideoMP4Codecs[] = {&kMPEG4FLACCodecInfo, + &kOpusCodecInfo, &kMPEG4VP09CodecInfo, #if BUILDFLAG(USE_PROPRIETARY_CODECS) &kH264AVC1CodecInfo,
diff --git a/media/gpu/test/video_player/test_vda_video_decoder.cc b/media/gpu/test/video_player/test_vda_video_decoder.cc index 989e915..8b7fc17 100644 --- a/media/gpu/test/video_player/test_vda_video_decoder.cc +++ b/media/gpu/test/video_player/test_vda_video_decoder.cc
@@ -241,8 +241,10 @@ } void TestVDAVideoDecoder::DismissPictureBuffer(int32_t picture_buffer_id) { - // TODO(dstaessens@) support dismissing picture buffers. - NOTIMPLEMENTED(); + // Drop reference to the video frame associated with the picture buffer, so + // the video frame and related texture are automatically destroyed once the + // renderer and video frame processors are done using them. + ASSERT_EQ(video_frames_.erase(picture_buffer_id), 1u); } void TestVDAVideoDecoder::PictureReady(const Picture& picture) {
diff --git a/net/http/transport_security_state_static.json b/net/http/transport_security_state_static.json index 8c9488e2..cffef64c 100644 --- a/net/http/transport_security_state_static.json +++ b/net/http/transport_security_state_static.json
@@ -339,6 +339,7 @@ { "name": "cdn.ampproject.org", "policy": "google", "mode": "force-https", "include_subdomains": true, "pins": "google" }, { "name": "chrome.com", "policy": "google", "mode": "force-https", "include_subdomains": true, "pins": "google" }, { "name": "chrome-devtools-frontend.appspot.com", "policy": "google", "mode": "force-https", "include_subdomains": true, "pins": "google" }, + { "name": "chromereporting-pa.googleapis.com", "policy": "google", "mode": "force-https", "include_subdomains": true, "pins": "google" }, { "name": "chromiumcodereview.appspot.com", "policy": "google", "mode": "force-https", "include_subdomains": true, "pins": "google" }, { "name": "codereview.appspot.com", "policy": "google", "mode": "force-https", "include_subdomains": true, "pins": "google" }, { "name": "codereview.chromium.org", "policy": "google", "mode": "force-https", "include_subdomains": true, "pins": "google" },
diff --git a/net/quic/platform/impl/quic_test_mem_slice_vector_impl.cc b/net/quic/platform/impl/quic_test_mem_slice_vector_impl.cc index ff0c376f..b1c3198d 100644 --- a/net/quic/platform/impl/quic_test_mem_slice_vector_impl.cc +++ b/net/quic/platform/impl/quic_test_mem_slice_vector_impl.cc
@@ -21,6 +21,20 @@ } } +QuicTestMemSliceVectorImpl::QuicTestMemSliceVectorImpl( + QuicTestMemSliceVectorImpl&& other) { + *this = std::move(other); +} + +QuicTestMemSliceVectorImpl& QuicTestMemSliceVectorImpl::operator=( + QuicTestMemSliceVectorImpl&& other) { + if (this != &other) { + buffers_ = std::move(other.buffers_); + lengths_ = std::move(other.lengths_); + } + return *this; +} + QuicMemSliceSpanImpl QuicTestMemSliceVectorImpl::span() { return QuicMemSliceSpanImpl(buffers_.data(), lengths_.data(), buffers_.size());
diff --git a/net/quic/platform/impl/quic_test_mem_slice_vector_impl.h b/net/quic/platform/impl/quic_test_mem_slice_vector_impl.h index 26acc2f..f256d400 100644 --- a/net/quic/platform/impl/quic_test_mem_slice_vector_impl.h +++ b/net/quic/platform/impl/quic_test_mem_slice_vector_impl.h
@@ -5,6 +5,8 @@ #ifndef NET_QUIC_PLATFORM_IMPL_QUIC_TEST_MEM_SLICE_VECTOR_IMPL_H_ #define NET_QUIC_PLATFORM_IMPL_QUIC_TEST_MEM_SLICE_VECTOR_IMPL_H_ +#include <memory> + #include "net/quic/platform/impl/quic_mem_slice_span_impl.h" namespace quic { @@ -25,6 +27,9 @@ std::vector<std::pair<char*, size_t>> buffers); ~QuicTestMemSliceVectorImpl(); + QuicTestMemSliceVectorImpl(QuicTestMemSliceVectorImpl&& other); + QuicTestMemSliceVectorImpl& operator=(QuicTestMemSliceVectorImpl&& other); + QuicMemSliceSpanImpl span(); private:
diff --git a/net/quic/quic_flags_list.h b/net/quic/quic_flags_list.h index 769a92d..c396147 100644 --- a/net/quic/quic_flags_list.h +++ b/net/quic/quic_flags_list.h
@@ -358,3 +358,9 @@ QUIC_FLAG(bool, FLAGS_quic_restart_flag_quic_server_drop_version_negotiation, false) + +// When true, version negotiation packets sent by the server will set the fixed +// bit. +QUIC_FLAG(bool, + FLAGS_quic_reloadable_flag_quic_send_version_negotiation_fixed_bit, + false)
diff --git a/printing/backend/cups_printer.cc b/printing/backend/cups_printer.cc index f2235bdb..07b91fff 100644 --- a/printing/backend/cups_printer.cc +++ b/printing/backend/cups_printer.cc
@@ -148,15 +148,19 @@ ipp_status_t CupsPrinter::CreateJob(int* job_id, const std::string& title, + const base::Optional<std::string>& username, const std::vector<cups_option_t>& options) { DCHECK(dest_info_) << "Verify availability before starting a print job"; cups_option_t* data = const_cast<cups_option_t*>( options.data()); // createDestJob will not modify the data + if (username) + cupsSetUser(username->c_str()); + ipp_status_t create_status = cupsCreateDestJob(cups_http_, destination_.get(), dest_info_.get(), job_id, title.c_str(), options.size(), data); - + cupsSetUser(nullptr); // reset to default username ("anonymous") return create_status; }
diff --git a/printing/backend/cups_printer.h b/printing/backend/cups_printer.h index 2d98a8c..d1b666d 100644 --- a/printing/backend/cups_printer.h +++ b/printing/backend/cups_printer.h
@@ -91,6 +91,7 @@ // Usage on an unavailable printer is undefined. ipp_status_t CreateJob(int* job_id, const std::string& title, + const base::Optional<std::string>& username, const std::vector<cups_option_t>& options); // Add a document to a print job. |job_id| must be non-zero and refer to a
diff --git a/printing/printing_context_chromeos.cc b/printing/printing_context_chromeos.cc index c3207b44..db0972f 100644 --- a/printing/printing_context_chromeos.cc +++ b/printing/printing_context_chromeos.cc
@@ -297,8 +297,12 @@ std::vector<ScopedCupsOption> cups_options = SettingsToCupsOptions(settings_); std::vector<cups_option_t> options; + base::Optional<std::string> username; + const base::StringPiece requestingUserName(kIppRequestingUserName); for (const ScopedCupsOption& option : cups_options) { - if (printer_->CheckOptionSupported(option->name, option->value)) { + if (option->name == requestingUserName) { + username = option->value; + } else if (printer_->CheckOptionSupported(option->name, option->value)) { options.push_back(*(option.get())); } else { DVLOG(1) << "Unsupported option skipped " << option->name << ", " @@ -306,7 +310,8 @@ } } - ipp_status_t create_status = printer_->CreateJob(&job_id_, title, options); + ipp_status_t create_status = + printer_->CreateJob(&job_id_, title, username, options); if (job_id_ == 0) { DLOG(WARNING) << "Creating cups job failed"
diff --git a/remoting/android/java/src/org/chromium/chromoting/Chromoting.java b/remoting/android/java/src/org/chromium/chromoting/Chromoting.java index 017a95262..84f3a53 100644 --- a/remoting/android/java/src/org/chromium/chromoting/Chromoting.java +++ b/remoting/android/java/src/org/chromium/chromoting/Chromoting.java
@@ -60,7 +60,10 @@ private static final String ACCOUNT_TYPE = "com.google"; /** Scope to use when fetching the OAuth token. */ - private static final String TOKEN_SCOPE = "oauth2:https://www.googleapis.com/auth/chromoting " + // To use these scopes in a debug build, your development account will need to be whitelisted. + private static final String TOKEN_SCOPE = + "oauth2:https://www.googleapis.com/auth/chromoting.directory " + + "https://www.googleapis.com/auth/tachyon " + "https://www.googleapis.com/auth/googletalk"; /** Result code used for starting {@link DesktopActivity}. */
diff --git a/remoting/android/java/src/org/chromium/chromoting/jni/JniOAuthTokenGetter.java b/remoting/android/java/src/org/chromium/chromoting/jni/JniOAuthTokenGetter.java index bba766c..13d59429 100644 --- a/remoting/android/java/src/org/chromium/chromoting/jni/JniOAuthTokenGetter.java +++ b/remoting/android/java/src/org/chromium/chromoting/jni/JniOAuthTokenGetter.java
@@ -21,7 +21,13 @@ @JNINamespace("remoting") public class JniOAuthTokenGetter { private static final String TAG = "Chromoting"; - private static final String TOKEN_SCOPE = "oauth2:https://www.googleapis.com/auth/chromoting"; + // Note: Any scope requested here must also be requested in Chromoting.java. (I.e., this must be + // a subset of Chromoting.java's TOKEN_SCOPE.) This is because the context passed to + // OAuthTokenFetcher below is not an activity, and thus it will not be possible to show a + // consent page requesting new scopes. + private static final String TOKEN_SCOPE = + "oauth2:https://www.googleapis.com/auth/chromoting.directory " + + "https://www.googleapis.com/auth/tachyon"; private static String sAccount; private static String sLatestToken;
diff --git a/services/audio/input_controller.cc b/services/audio/input_controller.cc index 8aa87f8..c88dde8 100644 --- a/services/audio/input_controller.cc +++ b/services/audio/input_controller.cc
@@ -11,6 +11,7 @@ #include <utility> #include "base/bind.h" +#include "base/logging.h" #include "base/memory/ptr_util.h" #include "base/metrics/histogram_macros.h" #include "base/single_thread_task_runner.h" @@ -93,9 +94,62 @@ #endif // AUDIO_POWER_MONITORING #if defined(AUDIO_PROCESSING_IN_AUDIO_SERVICE) + bool CanRunApm() { return base::FeatureList::IsEnabled(features::kWebRtcApmInAudioService); } + +bool SamplesNeedClamping(const media::AudioBus& bus) { + const auto IsOutOfRange = [](float sample) { + // See comment in CopySamplesWithClamping() for why the conditional is + // written this way. + if (UNLIKELY(!(sample >= -1.f && sample <= 1.f))) { + return true; + } + return false; + }; + + const int frames = bus.frames(); + for (int i = 0; i < bus.channels(); ++i) { + auto* const channel = bus.channel(i); + if (UNLIKELY(std::any_of(channel, channel + frames, IsOutOfRange))) { + return true; + } + } + return false; +} + +void CopySamplesWithClamping(const media::AudioBus& src_bus, + media::AudioBus* dest_bus) { + DCHECK_EQ(src_bus.channels(), dest_bus->channels()); + DCHECK_EQ(src_bus.frames(), dest_bus->frames()); + + const auto ToClampedSample = [](float sample) { + // First check for all the invalid cases with a single conditional to + // optimize for the typical (data ok) case. Different cases are handled + // inside of the conditional. The condition is written like this to catch + // NaN. It cannot be simplified to "channel[j] < -1.f || channel[j] > 1.f", + // which isn't equivalent. + if (UNLIKELY(!(sample >= -1.f && sample <= 1.f))) { + // Don't just set all bad values to 0. If a value like 1.0001 is produced + // due to floating-point shenanigans, 1 will sound better than 0. + if (sample < -1.f) { + return -1.f; + } else { + // channel[j] > 1 or NaN. + return 1.f; + } + } + return sample; + }; + + const int frames = src_bus.frames(); + for (int i = 0; i < src_bus.channels(); ++i) { + auto* const src = src_bus.channel(i); + std::transform(src, src + frames, dest_bus->channel(i), ToClampedSample); + } +} + #endif // defined(AUDIO_PROCESSING_IN_AUDIO_SERVICE) } // namespace @@ -125,8 +179,7 @@ return; if (monitored_output_stream_) { - monitored_output_stream_->StopSnooping(this, - Snoopable::SnoopingMode::kRealtime); + monitored_output_stream_->StopSnooping(this); if (!stream) { audio_processor_->set_has_reverse_stream(false); } @@ -134,24 +187,39 @@ monitored_output_stream_ = stream; if (!monitored_output_stream_) { output_params_ = media::AudioParameters(); + clamped_bus_.reset(); return; } output_params_ = monitored_output_stream_->GetAudioParameters(); audio_processor_->set_has_reverse_stream(true); - monitored_output_stream_->StartSnooping(this, - Snoopable::SnoopingMode::kRealtime); + monitored_output_stream_->StartSnooping(this); } void InputController::ProcessingHelper::OnData(const media::AudioBus& audio_bus, base::TimeTicks reference_time, double volume) { TRACE_EVENT0("audio", "APM AnalyzePlayout"); + // OnData gets called when the InputController is snooping on an output stream // for audio processing purposes. |audio_bus| contains the data from the // snooped-upon output stream, not the input stream's data. // |volume| is applied in the WebRTC mixer in the renderer, so we don't have // to inform the |audio_processor_| of the new volume. - audio_processor_->AnalyzePlayout(audio_bus, output_params_, reference_time); + + // If there are out-of-range samples, clamp them. + const media::AudioBus* bus_to_analyze = &audio_bus; + if (SamplesNeedClamping(audio_bus)) { + if (!clamped_bus_ || clamped_bus_->channels() != audio_bus.channels() || + clamped_bus_->frames() != audio_bus.frames()) { + clamped_bus_ = + media::AudioBus::Create(audio_bus.channels(), audio_bus.frames()); + } + CopySamplesWithClamping(audio_bus, clamped_bus_.get()); + bus_to_analyze = clamped_bus_.get(); + } + + audio_processor_->AnalyzePlayout(*bus_to_analyze, output_params_, + reference_time); } void InputController::ProcessingHelper::GetStats(GetStatsCallback callback) {
diff --git a/services/audio/input_controller.h b/services/audio/input_controller.h index e9a8700..07a8d849 100644 --- a/services/audio/input_controller.h +++ b/services/audio/input_controller.h
@@ -230,6 +230,7 @@ const std::unique_ptr<media::AudioProcessor> audio_processor_; media::AudioParameters output_params_; Snoopable* monitored_output_stream_ = nullptr; + std::unique_ptr<media::AudioBus> clamped_bus_; }; #endif // defined(AUDIO_PROCESSING_IN_AUDIO_SERVICE)
diff --git a/services/audio/loopback_stream.cc b/services/audio/loopback_stream.cc index fcb9a75..fed7bb1 100644 --- a/services/audio/loopback_stream.cc +++ b/services/audio/loopback_stream.cc
@@ -183,7 +183,7 @@ std::forward_as_tuple(input_params, network_->output_params())); DCHECK(emplace_result.second); // There was no pre-existing map entry. SnooperNode* const snooper = &(emplace_result.first->second); - member->StartSnooping(snooper, Snoopable::SnoopingMode::kDeferred); + member->StartSnooping(snooper); network_->AddInput(snooper); } @@ -199,7 +199,7 @@ const auto snoop_it = snoopers_.find(member); DCHECK(snoop_it != snoopers_.end()); SnooperNode* const snooper = &(snoop_it->second); - member->StopSnooping(snooper, Snoopable::SnoopingMode::kDeferred); + member->StopSnooping(snooper); network_->RemoveInput(snooper); snoopers_.erase(snoop_it); }
diff --git a/services/audio/output_controller.cc b/services/audio/output_controller.cc index 3ca0256c..26c06fa 100644 --- a/services/audio/output_controller.cc +++ b/services/audio/output_controller.cc
@@ -53,31 +53,6 @@ STREAM_CREATION_RESULT_MAX + 1); } -void SanitizeAudioBus(media::AudioBus* bus) { - size_t channel_size = bus->frames(); - for (int i = 0; i < bus->channels(); ++i) { - float* channel = bus->channel(i); - for (size_t j = 0; j < channel_size; ++j) { - // First check for all the invalid cases with a single conditional to - // optimize for the typical (data ok) case. Different cases are handled - // inside of the conditional. The condition is written like this to catch - // NaN. It cannot be simplified to "channel[j] < -1.f || channel[j] > - // 1.f", which isn't equivalent. - if (UNLIKELY(!(channel[j] >= -1.f && channel[j] <= 1.f))) { - // Don't just set all bad values to 0. If a value like 1.0001 is - // produced due to floating-point shenanigans, 1 will sound better than - // 0. - if (channel[j] < -1.f) { - channel[j] = -1.f; - } else { - // channel[j] > 1 or NaN. - channel[j] = 1.f; - } - } - } - } -} - } // namespace OutputController::ErrorStatisticsTracker::ErrorStatisticsTracker() @@ -130,7 +105,6 @@ output_device_id_(output_device_id), stream_(NULL), disable_local_output_(false), - should_duplicate_(0), volume_(1.0), state_(kEmpty), sync_reader_(sync_reader), @@ -152,7 +126,6 @@ DCHECK_EQ(kClosed, state_); DCHECK_EQ(nullptr, stream_); DCHECK(snoopers_.empty()); - DCHECK(should_duplicate_.IsZero()); UMA_HISTOGRAM_LONG_TIMES("Media.AudioOutputController.LifeTime", base::TimeTicks::Now() - construction_time_); } @@ -401,10 +374,12 @@ const base::TimeTicks reference_time = delay_timestamp + delay; if (!dest->is_bitstream_format()) { - base::AutoLock lock(realtime_snooper_lock_); - if (!realtime_snoopers_.empty()) { - SanitizeAudioBus(dest); - for (Snooper* snooper : realtime_snoopers_) { + base::AutoLock lock(snooper_lock_); + if (!snoopers_.empty()) { + TRACE_EVENT1("audio", "OutputController::BroadcastDataToSnoopers", + "reference_time (ms)", + (reference_time - base::TimeTicks()).InMillisecondsF()); + for (Snooper* snooper : snoopers_) { snooper->OnData(*dest, reference_time, volume_); } } @@ -417,15 +392,6 @@ sync_reader_->RequestMoreData(delay, delay_timestamp, prior_frames_skipped); - if (!should_duplicate_.IsZero() && !dest->is_bitstream_format()) { - std::unique_ptr<media::AudioBus> copy(media::AudioBus::Create(params_)); - dest->CopyTo(copy.get()); - task_runner_->PostTask( - FROM_HERE, - base::BindOnce(&OutputController::BroadcastDataToSnoopers, - weak_this_for_stream_, std::move(copy), reference_time)); - } - if (will_monitor_audio_levels()) { // Note: this code path should never be hit when using bitstream streams. // Scan doesn't expect compressed audio, so it may go out of bounds trying @@ -447,20 +413,6 @@ return frames; } -void OutputController::BroadcastDataToSnoopers( - std::unique_ptr<media::AudioBus> audio_bus, - base::TimeTicks reference_time) { - DCHECK(task_runner_->BelongsToCurrentThread()); - TRACE_EVENT1("audio", "OutputController::BroadcastDataToSnoopers", - "reference_time (ms)", - (reference_time - base::TimeTicks()).InMillisecondsF()); - if (state_ != kPlaying) - return; - - for (Snooper* snooper : snoopers_) - snooper->OnData(*audio_bus, reference_time, volume_); -} - void OutputController::LogAudioPowerLevel(const char* call_name) { std::pair<float, bool> power_and_clip = power_monitor_.ReadCurrentPowerAndClip(); @@ -525,42 +477,28 @@ : output_device_id_; } -void OutputController::StartSnooping(Snooper* snooper, SnoopingMode mode) { +void OutputController::StartSnooping(Snooper* snooper) { DCHECK(task_runner_->BelongsToCurrentThread()); DCHECK(snooper); - if (mode == SnoopingMode::kDeferred) { - if (snoopers_.empty()) - should_duplicate_.Increment(); - DCHECK(!base::ContainsValue(snoopers_, snooper)); - snoopers_.push_back(snooper); - } else { // SnoopingMode::kRealtime - // The list will only update on this thread, but may be read from another. - DCHECK(!base::ContainsValue(realtime_snoopers_, snooper)); - base::AutoLock lock(realtime_snooper_lock_); - realtime_snoopers_.push_back(snooper); - } + // The list will only update on this thread, and only be read on the realtime + // audio thread. + DCHECK(!base::ContainsValue(snoopers_, snooper)); + base::AutoLock lock(snooper_lock_); + snoopers_.push_back(snooper); } -void OutputController::StopSnooping(Snooper* snooper, SnoopingMode mode) { +void OutputController::StopSnooping(Snooper* snooper) { DCHECK(task_runner_->BelongsToCurrentThread()); - if (mode == SnoopingMode::kDeferred) { - const auto it = std::find(snoopers_.begin(), snoopers_.end(), snooper); - DCHECK(it != snoopers_.end()); - snoopers_.erase(it); - if (snoopers_.empty()) - should_duplicate_.Decrement(); - } else { // SnoopingMode::kRealtime - // The list will only update on this thread, but may be read from another. - const auto it = std::find(realtime_snoopers_.begin(), - realtime_snoopers_.end(), snooper); - DCHECK(it != realtime_snoopers_.end()); - // We also don't care about ordering, so swap and pop rather than erase. - base::AutoLock lock(realtime_snooper_lock_); - *it = realtime_snoopers_.back(); - realtime_snoopers_.pop_back(); - } + // The list will only update on this thread, and only be read on the realtime + // audio thread. + const auto it = std::find(snoopers_.begin(), snoopers_.end(), snooper); + DCHECK(it != snoopers_.end()); + // We also don't care about ordering, so swap and pop rather than erase. + base::AutoLock lock(snooper_lock_); + *it = snoopers_.back(); + snoopers_.pop_back(); } void OutputController::StartMuting() {
diff --git a/services/audio/output_controller.h b/services/audio/output_controller.h index 99b96a4..d4a2f342 100644 --- a/services/audio/output_controller.h +++ b/services/audio/output_controller.h
@@ -155,8 +155,8 @@ // LoopbackGroupMember implementation. const media::AudioParameters& GetAudioParameters() const override; std::string GetDeviceId() const override; - void StartSnooping(Snooper* snooper, SnoopingMode mode) override; - void StopSnooping(Snooper* snooper, SnoopingMode mode) override; + void StartSnooping(Snooper* snooper) override; + void StopSnooping(Snooper* snooper) override; void StartMuting() override; void StopMuting() override; @@ -243,10 +243,6 @@ // Helper method that stops, closes, and NULLs |*stream_|. void StopCloseAndClearStream(); - // Send audio data to each Snooper. - void BroadcastDataToSnoopers(std::unique_ptr<media::AudioBus> audio_bus, - base::TimeTicks reference_time); - // Log the current average power level measured by power_monitor_. void LogAudioPowerLevel(const char* call_name); @@ -276,14 +272,10 @@ // diverted to |diverting_to_stream_|, or a fake AudioOutputStream. bool disable_local_output_; - // The targets for audio stream to be copied to. |should_duplicate_| is set to - // 1 when the OnMoreData() call should proxy the data to - // BroadcastDataToSnoopers(). + // The snoopers examining or grabbing a copy of the audio data from the + // OnMoreData() calls. + base::Lock snooper_lock_; std::vector<Snooper*> snoopers_; - base::AtomicRefCount should_duplicate_; - - base::Lock realtime_snooper_lock_; - std::vector<Snooper*> realtime_snoopers_; // The current volume of the audio stream. double volume_;
diff --git a/services/audio/output_controller_unittest.cc b/services/audio/output_controller_unittest.cc index c79b1be1..6df8522 100644 --- a/services/audio/output_controller_unittest.cc +++ b/services/audio/output_controller_unittest.cc
@@ -415,8 +415,8 @@ Mock::VerifyAndClearExpectations(&mock_event_handler_); } - void StartSnooping(MockSnooper* snooper, Snoopable::SnoopingMode mode) { - controller_->StartSnooping(snooper, mode); + void StartSnooping(MockSnooper* snooper) { + controller_->StartSnooping(snooper); } void WaitForSnoopedData(MockSnooper* snooper) { @@ -428,8 +428,8 @@ Mock::VerifyAndClearExpectations(snooper); } - void StopSnooping(MockSnooper* snooper, Snoopable::SnoopingMode mode) { - controller_->StopSnooping(snooper, mode); + void StopSnooping(MockSnooper* snooper) { + controller_->StopSnooping(snooper); } Snoopable* GetSnoopable() { return &(*controller_); } @@ -609,72 +609,68 @@ EXPECT_EQ(playout_stream, last_closed_stream()); } -class WithSnoopingMode - : public OutputControllerTest, - public ::testing::WithParamInterface<Snoopable::SnoopingMode> {}; - -TEST_P(WithSnoopingMode, SnoopCreatePlayStopClose) { +TEST_F(OutputControllerTest, SnoopCreatePlayStopClose) { NiceMock<MockSnooper> snooper; - StartSnooping(&snooper, GetParam()); + StartSnooping(&snooper); Create(); Play(); WaitForSnoopedData(&snooper); - StopSnooping(&snooper, GetParam()); + StopSnooping(&snooper); Close(); } -TEST_P(WithSnoopingMode, CreatePlaySnoopStopClose) { +TEST_F(OutputControllerTest, CreatePlaySnoopStopClose) { NiceMock<MockSnooper> snooper; Create(); Play(); - StartSnooping(&snooper, GetParam()); + StartSnooping(&snooper); WaitForSnoopedData(&snooper); - StopSnooping(&snooper, GetParam()); + StopSnooping(&snooper); Close(); } -TEST_P(WithSnoopingMode, CreatePlaySnoopCloseStop) { +TEST_F(OutputControllerTest, CreatePlaySnoopCloseStop) { NiceMock<MockSnooper> snooper; Create(); Play(); - StartSnooping(&snooper, GetParam()); + StartSnooping(&snooper); WaitForSnoopedData(&snooper); Close(); - StopSnooping(&snooper, GetParam()); + StopSnooping(&snooper); } -TEST_P(WithSnoopingMode, TwoSnoopers_StartAtDifferentTimes) { +TEST_F(OutputControllerTest, TwoSnoopers_StartAtDifferentTimes) { NiceMock<MockSnooper> snooper1; NiceMock<MockSnooper> snooper2; - StartSnooping(&snooper1, GetParam()); + StartSnooping(&snooper1); Create(); Play(); WaitForSnoopedData(&snooper1); - StartSnooping(&snooper2, GetParam()); + StartSnooping(&snooper2); WaitForSnoopedData(&snooper2); WaitForSnoopedData(&snooper1); WaitForSnoopedData(&snooper2); Close(); - StopSnooping(&snooper1, GetParam()); - StopSnooping(&snooper2, GetParam()); + StopSnooping(&snooper1); + StopSnooping(&snooper2); } -TEST_P(WithSnoopingMode, TwoSnoopers_StopAtDifferentTimes) { +TEST_F(OutputControllerTest, TwoSnoopers_StopAtDifferentTimes) { NiceMock<MockSnooper> snooper1; NiceMock<MockSnooper> snooper2; Create(); Play(); - StartSnooping(&snooper1, GetParam()); + StartSnooping(&snooper1); WaitForSnoopedData(&snooper1); - StartSnooping(&snooper2, GetParam()); + StartSnooping(&snooper2); WaitForSnoopedData(&snooper2); - StopSnooping(&snooper1, GetParam()); + StopSnooping(&snooper1); WaitForSnoopedData(&snooper2); Close(); - StopSnooping(&snooper2, GetParam()); + StopSnooping(&snooper2); } -TEST_P(WithSnoopingMode, SnoopWhileMuting) { +TEST_F(OutputControllerTest, SnoopWhileMuting) { NiceMock<MockSnooper> snooper; StartMutingBeforePlaying(); @@ -691,13 +687,13 @@ EXPECT_EQ(nullptr, last_closed_stream()); EXPECT_EQ(AudioParameters::AUDIO_FAKE, mute_stream->format()); - StartSnooping(&snooper, GetParam()); + StartSnooping(&snooper); ASSERT_EQ(mute_stream, last_created_stream()); EXPECT_EQ(nullptr, last_closed_stream()); EXPECT_EQ(AudioParameters::AUDIO_FAKE, mute_stream->format()); WaitForSnoopedData(&snooper); - StopSnooping(&snooper, GetParam()); + StopSnooping(&snooper); ASSERT_EQ(mute_stream, last_created_stream()); EXPECT_EQ(nullptr, last_closed_stream()); EXPECT_EQ(AudioParameters::AUDIO_FAKE, mute_stream->format()); @@ -707,11 +703,6 @@ EXPECT_EQ(mute_stream, last_closed_stream()); } -INSTANTIATE_TEST_SUITE_P(OutputControllerSnoopingTest, - WithSnoopingMode, - ::testing::Values(Snoopable::SnoopingMode::kDeferred, - Snoopable::SnoopingMode::kRealtime)); - TEST_F(OutputControllerTest, InformsStreamMonitorsAlreadyInGroup) { MockStreamMonitor monitor; EXPECT_CALL(monitor, OnStreamActive(GetSnoopable()));
diff --git a/services/audio/snoopable.h b/services/audio/snoopable.h index 0089dcf..6825f83 100644 --- a/services/audio/snoopable.h +++ b/services/audio/snoopable.h
@@ -19,7 +19,9 @@ public: class Snooper { public: - // Provides read-only access to the data flowing through a GroupMember. + // Provides read-only access to the data flowing through a GroupMember. This + // must execute quickly, as it will typically be called on a realtime + // thread; otherwise, audio glitches may occur. virtual void OnData(const media::AudioBus& audio_bus, base::TimeTicks reference_time, double volume) = 0; @@ -28,11 +30,6 @@ virtual ~Snooper() = default; }; - enum class SnoopingMode { - kDeferred, // Deferred snooping is done on the audio thread. - kRealtime // Realtime snooping is done on the device thread. Must be fast! - }; - // Returns the audio parameters of the snoopable audio data. The parameters // must not change for the lifetime of this group member, but can be different // than those of other members. @@ -42,11 +39,8 @@ virtual std::string GetDeviceId() const = 0; // Starts/Stops snooping on the audio data flowing through this group member. - // The snooping modes are handled individually, so it's possible (though - // inadvisable) to call StartSnooping twice with the same snooper, but with - // different modes. - virtual void StartSnooping(Snooper* snooper, SnoopingMode mode) = 0; - virtual void StopSnooping(Snooper* snooper, SnoopingMode mode) = 0; + virtual void StartSnooping(Snooper* snooper) = 0; + virtual void StopSnooping(Snooper* snooper) = 0; protected: virtual ~Snoopable() = default;
diff --git a/services/audio/snooper_node_unittest.cc b/services/audio/snooper_node_unittest.cc index 8154910..2e78aa76 100644 --- a/services/audio/snooper_node_unittest.cc +++ b/services/audio/snooper_node_unittest.cc
@@ -200,7 +200,7 @@ group_member_->SetVolume(kSourceVolume); node_.emplace(input_params(), output_params()); - group_member_->StartSnooping(node(), Snoopable::SnoopingMode::kDeferred); + group_member_->StartSnooping(node()); consumer_.emplace(output_params().channels(), output_params().sample_rate());
diff --git a/services/audio/stream_factory.cc b/services/audio/stream_factory.cc index ae717272..e15e6c2 100644 --- a/services/audio/stream_factory.cc +++ b/services/audio/stream_factory.cc
@@ -20,7 +20,8 @@ namespace audio { StreamFactory::StreamFactory(media::AudioManager* audio_manager) - : audio_manager_(audio_manager) { + : audio_manager_(audio_manager), + loopback_worker_thread_("Loopback Worker") { magic_bytes_ = 0x600DC0DEu; SetStateForCrashing("constructed"); } @@ -189,13 +190,40 @@ group_id.GetLowForSerialization(), "params", params.AsHumanReadableString()); + // All LoopbackStreams share a single realtime worker thread. This is because + // the execution timing of scheduled tasks must be precise, and top priority + // should be given to the smooth continuous flow of audio while in low-CPU + // situations; all to avoid glitches. The thread is started just before the + // first LoopbackStream will be created, and stopped after all LoopbackStreams + // are gone. + scoped_refptr<base::SequencedTaskRunner> task_runner; + if (loopback_worker_thread_.IsRunning()) { + task_runner = loopback_worker_thread_.task_runner(); + } else { + TRACE_EVENT_BEGIN0("audio", "Start Loopback Worker"); + base::Thread::Options options; + options.timer_slack = base::TIMER_SLACK_NONE; + options.priority = base::ThreadPriority::REALTIME_AUDIO; + if (loopback_worker_thread_.StartWithOptions(options)) { + task_runner = loopback_worker_thread_.task_runner(); + TRACE_EVENT_END1("audio", "Start Loopback Worker", "success", true); + } else { + // Something about this platform or its current environment has prevented + // a realtime audio thread from being started. Fall-back to using the + // AudioManager worker thread. + LOG(ERROR) << "Unable to start realtime loopback worker thread."; + task_runner = audio_manager_->GetWorkerTaskRunner(); + TRACE_EVENT_END1("audio", "Start Loopback Worker", "success", false); + } + } + auto stream = std::make_unique<LoopbackStream>( std::move(created_callback), base::BindOnce(&StreamFactory::DestroyLoopbackStream, base::Unretained(this)), - audio_manager_->GetWorkerTaskRunner(), std::move(receiver), - std::move(client), std::move(observer), params, shared_memory_count, - &coordinator_, group_id); + std::move(task_runner), std::move(receiver), std::move(client), + std::move(observer), params, shared_memory_count, &coordinator_, + group_id); loopback_streams_.emplace_back(std::move(stream)); SetStateForCrashing("created loopback stream"); } @@ -225,7 +253,7 @@ // Output streams have a task posting before destruction (see the OnError // function in output_stream.cc). To ensure that stream destruction and - // unmuting is done in the intended order (the order in which the messeges are + // unmuting is done in the intended order (the order in which the messages are // received by the service), we post a task for destroying the muter as well. // Otherwise, a "destroy all streams, then destroy the muter" sequence may // result in a brief blip of audio. @@ -262,6 +290,12 @@ loopback_streams_.erase(it); SetStateForCrashing("destroyed loopback stream"); + + // If all LoopbackStreams have ended, stop and join the worker thread. + if (loopback_streams_.empty()) { + TRACE_EVENT0("audio", "Stop Loopback Worker"); + loopback_worker_thread_.Stop(); + } } void StreamFactory::SetStateForCrashing(const char* state) {
diff --git a/services/audio/stream_factory.h b/services/audio/stream_factory.h index 1097dce..f8b6b14d7 100644 --- a/services/audio/stream_factory.h +++ b/services/audio/stream_factory.h
@@ -15,6 +15,7 @@ #include "base/macros.h" #include "base/memory/weak_ptr.h" #include "base/sequence_checker.h" +#include "base/threading/thread.h" #include "media/mojo/interfaces/audio_logging.mojom.h" #include "media/mojo/interfaces/audio_output_stream.mojom.h" #include "mojo/public/cpp/bindings/receiver_set.h" @@ -113,6 +114,7 @@ // Order of the following members is important for a clean shutdown. LoopbackCoordinator coordinator_; std::vector<std::unique_ptr<LocalMuter>> muters_; + base::Thread loopback_worker_thread_; std::vector<std::unique_ptr<LoopbackStream>> loopback_streams_; StreamMonitorCoordinator stream_monitor_coordinator_; InputStreamSet input_streams_;
diff --git a/services/audio/test/fake_loopback_group_member.cc b/services/audio/test/fake_loopback_group_member.cc index b7bb5503..de778ab 100644 --- a/services/audio/test/fake_loopback_group_member.cc +++ b/services/audio/test/fake_loopback_group_member.cc
@@ -67,14 +67,12 @@ return media::AudioDeviceDescription::kDefaultDeviceId; } -void FakeLoopbackGroupMember::StartSnooping(Snooper* snooper, - SnoopingMode mode) { +void FakeLoopbackGroupMember::StartSnooping(Snooper* snooper) { CHECK(!snooper_); snooper_ = snooper; } -void FakeLoopbackGroupMember::StopSnooping(Snooper* snooper, - SnoopingMode mode) { +void FakeLoopbackGroupMember::StopSnooping(Snooper* snooper) { snooper_ = nullptr; }
diff --git a/services/audio/test/fake_loopback_group_member.h b/services/audio/test/fake_loopback_group_member.h index 05c6cf5..b6e01ea 100644 --- a/services/audio/test/fake_loopback_group_member.h +++ b/services/audio/test/fake_loopback_group_member.h
@@ -50,8 +50,8 @@ // LoopbackGroupMember implementation. const media::AudioParameters& GetAudioParameters() const override; std::string GetDeviceId() const override; - void StartSnooping(Snooper* snooper, SnoopingMode mode) override; - void StopSnooping(Snooper* snooper, SnoopingMode mode) override; + void StartSnooping(Snooper* snooper) override; + void StopSnooping(Snooper* snooper) override; void StartMuting() override; void StopMuting() override;
diff --git a/services/audio/test/mock_group_member.h b/services/audio/test/mock_group_member.h index 992d18f..40efceb8 100644 --- a/services/audio/test/mock_group_member.h +++ b/services/audio/test/mock_group_member.h
@@ -21,8 +21,8 @@ MOCK_CONST_METHOD0(GetAudioParameters, const media::AudioParameters&()); MOCK_CONST_METHOD0(GetDeviceId, std::string()); - MOCK_METHOD2(StartSnooping, void(Snooper* snooper, SnoopingMode mode)); - MOCK_METHOD2(StopSnooping, void(Snooper* snooper, SnoopingMode mode)); + MOCK_METHOD1(StartSnooping, void(Snooper* snooper)); + MOCK_METHOD1(StopSnooping, void(Snooper* snooper)); MOCK_METHOD0(StartMuting, void()); MOCK_METHOD0(StopMuting, void()); MOCK_METHOD0(IsMuting, bool());
diff --git a/services/content/BUILD.gn b/services/content/BUILD.gn index 5ed7974..fd9325f 100644 --- a/services/content/BUILD.gn +++ b/services/content/BUILD.gn
@@ -3,7 +3,6 @@ # found in the LICENSE file. import("//build/config/ui.gni") -import("//services/content/public/features.gni") source_set("impl") { visibility = [ @@ -29,7 +28,6 @@ public_deps = [ "//base", - "//services/content/public/cpp:buildflags", "//services/service_manager/public/cpp", "//ui/gfx", ] @@ -49,10 +47,6 @@ if (use_aura) { deps += [ "//ui/aura" ] } - - if (enable_remote_navigable_contents_view) { - deps += [ "//ui/views/mus/remote_view:remote_view_provider" ] - } } }
diff --git a/services/content/navigable_contents_impl.cc b/services/content/navigable_contents_impl.cc index f375e58..12b39bb42 100644 --- a/services/content/navigable_contents_impl.cc +++ b/services/content/navigable_contents_impl.cc
@@ -6,24 +6,14 @@ #include "base/bind.h" #include "services/content/navigable_contents_delegate.h" -#include "services/content/public/cpp/buildflags.h" #include "services/content/public/cpp/navigable_contents_view.h" #include "services/content/service.h" #include "services/content/service_delegate.h" -#if defined(TOOLKIT_VIEWS) -#include "ui/views/controls/native/native_view_host.h" // nogncheck - #if defined(USE_AURA) #include "ui/aura/window.h" // nogncheck #endif -#if BUILDFLAG(ENABLE_REMOTE_NAVIGABLE_CONTENTS_VIEW) -#include "ui/base/ui_base_features.h" // nogncheck -#include "ui/views/mus/remote_view/remote_view_provider.h" // nogncheck -#endif -#endif // defined(TOOLKIT_VIEWS) - namespace content { NavigableContentsImpl::NavigableContentsImpl( @@ -58,36 +48,6 @@ delegate_->GoBack(std::move(callback)); } -void NavigableContentsImpl::CreateView(bool use_window_service, - CreateViewCallback callback) { - DCHECK(native_content_view_); - -#if BUILDFLAG(ENABLE_REMOTE_NAVIGABLE_CONTENTS_VIEW) - if (use_window_service) { - remote_view_provider_ = - std::make_unique<views::RemoteViewProvider>(native_content_view_); - remote_view_provider_->GetEmbedToken( - base::BindOnce(&NavigableContentsImpl::OnEmbedTokenReceived, - base::Unretained(this), std::move(callback))); - return; - } -#else - if (use_window_service) { - DLOG(ERROR) << "Remote NavigableContentsView clients are not supported on " - << "this platform."; - return; - } -#endif - - // Create and stash a new callback (indexed by token) which the in-process - // client library can use to establish an "embedding" of the contents' view. - auto token = base::UnguessableToken::Create(); - NavigableContentsView::RegisterInProcessEmbedCallback( - token, base::BindOnce(&NavigableContentsImpl::EmbedInProcessClientView, - weak_ptr_factory_.GetWeakPtr())); - std::move(callback).Run(token); -} - void NavigableContentsImpl::Focus() { delegate_->Focus(); } @@ -96,30 +56,4 @@ delegate_->FocusThroughTabTraversal(reverse); } -#if BUILDFLAG(ENABLE_REMOTE_NAVIGABLE_CONTENTS_VIEW) -void NavigableContentsImpl::OnEmbedTokenReceived( - CreateViewCallback callback, - const base::UnguessableToken& token) { -#if defined(TOOLKIT_VIEWS) && defined(USE_AURA) - DCHECK(native_content_view_); - native_content_view_->Show(); -#endif // defined(TOOLKIT_VIEWS) && defined(USE_AURA) - std::move(callback).Run(token); -} -#endif // BUILDFLAG(ENABLE_REMOTE_NAVIGABLE_CONTENTS_VIEW) - -void NavigableContentsImpl::EmbedInProcessClientView( - NavigableContentsView* view) { - DCHECK(native_content_view_); -#if defined(TOOLKIT_VIEWS) && defined(USE_AURA) - view->native_view()->AddChild(native_content_view_); - native_content_view_->Show(); -#else - // TODO(https://crbug.com/855092): Support embedding of other native client - // views without Views + Aura. - NOTREACHED() - << "NavigableContents views are currently only supported on Views UI."; -#endif -} - } // namespace content
diff --git a/services/content/navigable_contents_impl.h b/services/content/navigable_contents_impl.h index c3dd4763..1096b85 100644 --- a/services/content/navigable_contents_impl.h +++ b/services/content/navigable_contents_impl.h
@@ -12,20 +12,14 @@ #include "mojo/public/cpp/bindings/pending_remote.h" #include "mojo/public/cpp/bindings/receiver.h" #include "mojo/public/cpp/bindings/remote.h" -#include "services/content/public/cpp/buildflags.h" #include "services/content/public/mojom/navigable_contents.mojom.h" #include "services/content/public/mojom/navigable_contents_factory.mojom.h" #include "ui/gfx/native_widget_types.h" -namespace views { -class RemoteViewProvider; -} - namespace content { class Service; class NavigableContentsDelegate; -class NavigableContentsView; // This is the state which backs an individual NavigableContents owned by some // client of the Content Service. In terms of the classical Content API, this is @@ -43,20 +37,9 @@ // mojom::NavigableContents: void Navigate(const GURL& url, mojom::NavigateParamsPtr params) override; void GoBack(mojom::NavigableContents::GoBackCallback callback) override; - void CreateView(bool in_service_process, - CreateViewCallback callback) override; void Focus() override; void FocusThroughTabTraversal(bool reverse) override; -#if BUILDFLAG(ENABLE_REMOTE_NAVIGABLE_CONTENTS_VIEW) - void OnEmbedTokenReceived(CreateViewCallback callback, - const base::UnguessableToken& token); -#endif - - // Used (indirectly) by the client library when run in the same process as the - // service. See the |CreateView()| implementation for details. - void EmbedInProcessClientView(NavigableContentsView* view); - Service* const service_; mojo::Receiver<mojom::NavigableContents> receiver_; @@ -64,10 +47,6 @@ std::unique_ptr<NavigableContentsDelegate> delegate_; gfx::NativeView native_content_view_; -#if BUILDFLAG(ENABLE_REMOTE_NAVIGABLE_CONTENTS_VIEW) - std::unique_ptr<views::RemoteViewProvider> remote_view_provider_; -#endif - base::WeakPtrFactory<NavigableContentsImpl> weak_ptr_factory_{this}; DISALLOW_COPY_AND_ASSIGN(NavigableContentsImpl);
diff --git a/services/content/public/cpp/BUILD.gn b/services/content/public/cpp/BUILD.gn index 70d3881..06172729 100644 --- a/services/content/public/cpp/BUILD.gn +++ b/services/content/public/cpp/BUILD.gn
@@ -2,12 +2,7 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -import("//services/content/public/features.gni") - -buildflag_header("buildflags") { - header = "buildflags.h" - flags = [ "ENABLE_REMOTE_NAVIGABLE_CONTENTS_VIEW=$enable_remote_navigable_contents_view" ] -} +import("//build/config/ui.gni") component("cpp") { output_name = "content_service_cpp" @@ -28,7 +23,6 @@ defines = [ "IS_CONTENT_SERVICE_CPP_IMPL" ] public_deps = [ - ":buildflags", "//base", "//net", "//services/content/public/mojom", @@ -43,13 +37,6 @@ deps = [] if (toolkit_views) { deps += [ "//ui/views" ] - - if (enable_remote_navigable_contents_view) { - deps += [ - "//services/ws/public/mojom", - "//ui/views/mus/remote_view:remote_view_host", - ] - } } if (use_aura) {
diff --git a/services/content/public/cpp/navigable_contents.cc b/services/content/public/cpp/navigable_contents.cc index f60cb2e..854e9619 100644 --- a/services/content/public/cpp/navigable_contents.cc +++ b/services/content/public/cpp/navigable_contents.cc
@@ -34,10 +34,6 @@ NavigableContentsView* NavigableContents::GetView() { if (!view_) { view_ = base::WrapUnique(new NavigableContentsView(this)); - contents_->CreateView( - ShouldUseWindowService(), - base::BindOnce(&NavigableContents::OnEmbedTokenReceived, - base::Unretained(this))); } return view_.get(); } @@ -64,18 +60,6 @@ contents_->FocusThroughTabTraversal(reverse); } -void NavigableContents::ForceUseWindowService() { - // This should only be called before |view_| is created. - DCHECK(!view_); - - force_use_window_service_ = true; -} - -bool NavigableContents::ShouldUseWindowService() const { - return !NavigableContentsView::IsClientRunningInServiceProcess() || - force_use_window_service_; -} - void NavigableContents::ClearViewFocus() { if (view_) view_->ClearNativeFocus(); @@ -115,10 +99,4 @@ view_->NotifyAccessibilityTreeChange(); } -void NavigableContents::OnEmbedTokenReceived( - const base::UnguessableToken& token) { - DCHECK(view_); - view_->EmbedUsingToken(token); -} - } // namespace content
diff --git a/services/content/public/cpp/navigable_contents.h b/services/content/public/cpp/navigable_contents.h index 3d98e84..a43d236 100644 --- a/services/content/public/cpp/navigable_contents.h +++ b/services/content/public/cpp/navigable_contents.h
@@ -70,13 +70,6 @@ // being done via Tab-key cycling or a similar mechanism. void FocusThroughTabTraversal(bool reverse); - // Force NavigableContents to use Window Service for embedding. Note this must - // be called before its view is created. - void ForceUseWindowService(); - - // Whether to use Window Service for embedding. - bool ShouldUseWindowService() const; - private: // mojom::NavigableContentsClient: void ClearViewFocus() override; @@ -92,8 +85,6 @@ bool from_user_gesture) override; void UpdateContentAXTree(const ui::AXTreeID& id) override; - void OnEmbedTokenReceived(const base::UnguessableToken& token); - mojo::Remote<mojom::NavigableContents> contents_; mojo::Receiver<mojom::NavigableContentsClient> client_receiver_; std::unique_ptr<NavigableContentsView> view_; @@ -102,8 +93,6 @@ ui::AXTreeID content_ax_tree_id_; - bool force_use_window_service_ = false; - DISALLOW_COPY_AND_ASSIGN(NavigableContents); };
diff --git a/services/content/public/cpp/navigable_contents_view.cc b/services/content/public/cpp/navigable_contents_view.cc index 75b7e99..6c7ccc4c8 100644 --- a/services/content/public/cpp/navigable_contents_view.cc +++ b/services/content/public/cpp/navigable_contents_view.cc
@@ -4,14 +4,11 @@ #include "services/content/public/cpp/navigable_contents_view.h" -#include <map> - #include "base/bind_helpers.h" #include "base/callback.h" #include "base/no_destructor.h" #include "base/synchronization/atomic_flag.h" #include "base/unguessable_token.h" -#include "services/content/public/cpp/buildflags.h" #include "services/content/public/cpp/navigable_contents.h" #include "ui/accessibility/ax_enums.mojom.h" #include "ui/accessibility/ax_node_data.h" @@ -20,13 +17,6 @@ #include "ui/views/focus/focus_manager.h" // nogncheck #include "ui/views/layout/fill_layout.h" // nogncheck #include "ui/views/view.h" // nogncheck - -#if BUILDFLAG(ENABLE_REMOTE_NAVIGABLE_CONTENTS_VIEW) -#include "services/ws/public/mojom/window_tree_constants.mojom.h" // nogncheck -#include "ui/base/ui_base_features.h" // nogncheck -#include "ui/views/controls/native/native_view_host.h" // nogncheck -#include "ui/views/mus/remote_view/remote_view_host.h" // nogncheck -#endif // BUILDFLAG(ENABLE_REMOTE_NAVIGABLE_CONTENTS_VIEW) #endif // defined(TOOLKIT_VIEWS) #if defined(USE_AURA) @@ -38,32 +28,11 @@ namespace { -using InProcessEmbeddingMap = - std::map<base::UnguessableToken, - base::OnceCallback<void(NavigableContentsView*)>>; - -InProcessEmbeddingMap& GetInProcessEmbeddingMap() { - static base::NoDestructor<InProcessEmbeddingMap> embedding_map; - return *embedding_map; -} - base::AtomicFlag& GetInServiceProcessFlag() { static base::NoDestructor<base::AtomicFlag> in_service_process; return *in_service_process; } -#if BUILDFLAG(ENABLE_REMOTE_NAVIGABLE_CONTENTS_VIEW) - -std::unique_ptr<NavigableContentsView::RemoteViewManager>& -GetRemoteViewManager() { - static base::NoDestructor< - std::unique_ptr<NavigableContentsView::RemoteViewManager>> - manager; - return *manager; -} - -#endif // BUILDFLAG(ENABLE_REMOTE_NAVIGABLE_CONTENTS_VIEW) - #if defined(TOOLKIT_VIEWS) && defined(USE_AURA) // Keeps child windows sized to the same bounds as the owning window. @@ -163,18 +132,6 @@ NavigableContentsView::NavigableContentsView(NavigableContents* contents) : contents_(contents) { #if defined(TOOLKIT_VIEWS) && defined(USE_AURA) -#if BUILDFLAG(ENABLE_REMOTE_NAVIGABLE_CONTENTS_VIEW) - if (contents_->ShouldUseWindowService()) { - RemoteViewManager* manager = GetRemoteViewManager().get(); - if (manager) - view_ = manager->CreateRemoteViewHost(); - else - view_ = std::make_unique<views::RemoteViewHost>(); - view_->set_owned_by_client(); - return; - } -#endif // BUILDFLAG(ENABLE_REMOTE_NAVIGABLE_CONTENTS_VIEW) - window_ = std::make_unique<aura::Window>(nullptr); window_->set_owned_by_parent(false); window_->SetName("NavigableContentsViewWindow"); @@ -187,61 +144,4 @@ #endif // defined(TOOLKIT_VIEWS) && defined(USE_AURA) } -#if BUILDFLAG(ENABLE_REMOTE_NAVIGABLE_CONTENTS_VIEW) - -// static -void NavigableContentsView::SetRemoteViewManager( - std::unique_ptr<RemoteViewManager> manager) { - GetRemoteViewManager() = std::move(manager); -} - -#endif // BUILDFLAG(ENABLE_REMOTE_NAVIGABLE_CONTENTS_VIEW) - -void NavigableContentsView::EmbedUsingToken( - const base::UnguessableToken& token) { -#if defined(TOOLKIT_VIEWS) -#if BUILDFLAG(ENABLE_REMOTE_NAVIGABLE_CONTENTS_VIEW) - if (contents_->ShouldUseWindowService()) { - RemoteViewManager* manager = GetRemoteViewManager().get(); - if (manager) { - manager->EmbedUsingToken(view_.get(), token); - } else { - constexpr uint32_t kEmbedFlags = - ws::mojom::kEmbedFlagEmbedderInterceptsEvents | - ws::mojom::kEmbedFlagEmbedderControlsVisibility; - static_cast<views::RemoteViewHost*>(view_.get()) - ->EmbedUsingToken(token, kEmbedFlags, base::DoNothing()); - } - - return; - } -#endif // BUILDFLAG(ENABLE_REMOTE_NAVIGABLE_CONTENTS_VIEW) - - DCHECK(IsClientRunningInServiceProcess()); - - // |token| should already have an embed callback entry in the in-process - // callback map, injected by the in-process Content Service implementation. - auto& embeddings = GetInProcessEmbeddingMap(); - auto it = embeddings.find(token); - if (it == embeddings.end()) { - DLOG(ERROR) << "Unable to embed with unknown token " << token.ToString(); - return; - } - - // Invoke a callback provided by the Content Service's host environment. This - // should parent a web content view to our own |view()|, as well as set - // |native_view_| to the corresponding web contents' own NativeView. - auto callback = std::move(it->second); - embeddings.erase(it); - std::move(callback).Run(this); -#endif // defined(TOOLKIT_VIEWS) -} - -// static -void NavigableContentsView::RegisterInProcessEmbedCallback( - const base::UnguessableToken& token, - base::OnceCallback<void(NavigableContentsView*)> callback) { - GetInProcessEmbeddingMap()[token] = std::move(callback); -} - } // namespace content
diff --git a/services/content/public/cpp/navigable_contents_view.h b/services/content/public/cpp/navigable_contents_view.h index 30a2913..6983734 100644 --- a/services/content/public/cpp/navigable_contents_view.h +++ b/services/content/public/cpp/navigable_contents_view.h
@@ -9,8 +9,6 @@ #include "base/callback.h" #include "base/component_export.h" -#include "base/unguessable_token.h" -#include "services/content/public/cpp/buildflags.h" #include "ui/gfx/native_widget_types.h" #if defined(TOOLKIT_VIEWS) && defined(USE_AURA) @@ -39,29 +37,6 @@ // Views UI on Aura. class COMPONENT_EXPORT(CONTENT_SERVICE_CPP) NavigableContentsView { public: -#if BUILDFLAG(ENABLE_REMOTE_NAVIGABLE_CONTENTS_VIEW) - // May be used if the Content Service client is running within a process whose - // UI environment requires a different remote View implementation from - // the default one. For example, on Chrome OS when Ash and the Window Service - // are running in the same process, the default implementation - // (views::RemoteViewHost) will not work. - class RemoteViewManager { - public: - virtual ~RemoteViewManager() {} - - // Creates a new NativeViewHost suitable for remote embedding. - virtual std::unique_ptr<views::NativeViewHost> CreateRemoteViewHost() = 0; - - // Initiates an embedding of a remote client -- identified by |token| -- - // within |view_host|. Note that |view_host| is always an object returned by - // |CreateRemoteViewHost()| on the same RemoteViewManager. - virtual void EmbedUsingToken(views::NativeViewHost* view_host, - const base::UnguessableToken& token) = 0; - }; - - static void SetRemoteViewManager(std::unique_ptr<RemoteViewManager> manager); -#endif - ~NavigableContentsView(); // Used to set/query whether the calling process is the same process in which @@ -91,16 +66,6 @@ explicit NavigableContentsView(NavigableContents* contents_); - // Establishes a hierarchical relationship between this view's native UI - // object and another native UI object within the Content Service. - void EmbedUsingToken(const base::UnguessableToken& token); - - // Used by the service directly when running in the same process. Establishes - // a way for an embed token to be used without the UI service. - static void RegisterInProcessEmbedCallback( - const base::UnguessableToken& token, - base::OnceCallback<void(NavigableContentsView*)> callback); - NavigableContents* const contents_; #if defined(TOOLKIT_VIEWS) && defined(USE_AURA)
diff --git a/services/content/public/cpp/test/fake_navigable_contents.cc b/services/content/public/cpp/test/fake_navigable_contents.cc index 1edd54f..31a98dec 100644 --- a/services/content/public/cpp/test/fake_navigable_contents.cc +++ b/services/content/public/cpp/test/fake_navigable_contents.cc
@@ -6,7 +6,6 @@ #include "base/bind.h" #include "base/bind_helpers.h" -#include "base/unguessable_token.h" #include "services/content/public/cpp/navigable_contents_view.h" #include "services/content/public/cpp/test/fake_navigable_contents_factory.h" @@ -43,14 +42,6 @@ std::move(callback).Run(false /* success */); } -void FakeNavigableContents::CreateView(bool in_service_process, - CreateViewCallback callback) { - auto token = base::UnguessableToken::Create(); - NavigableContentsView::RegisterInProcessEmbedCallback(token, - base::DoNothing()); - std::move(callback).Run(token); -} - void FakeNavigableContents::Focus() {} void FakeNavigableContents::FocusThroughTabTraversal(bool reverse) {}
diff --git a/services/content/public/cpp/test/fake_navigable_contents.h b/services/content/public/cpp/test/fake_navigable_contents.h index 524bb9ac..2e23114 100644 --- a/services/content/public/cpp/test/fake_navigable_contents.h +++ b/services/content/public/cpp/test/fake_navigable_contents.h
@@ -40,8 +40,6 @@ // mojom::NavigableContents: void Navigate(const GURL& url, mojom::NavigateParamsPtr params) override; void GoBack(mojom::NavigableContents::GoBackCallback callback) override; - void CreateView(bool in_service_process, - CreateViewCallback callback) override; void Focus() override; void FocusThroughTabTraversal(bool reverse) override;
diff --git a/services/content/public/features.gni b/services/content/public/features.gni deleted file mode 100644 index 0cdc2ea..0000000 --- a/services/content/public/features.gni +++ /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. - -import("//build/buildflag_header.gni") -import("//build/config/chromecast_build.gni") -import("//build/config/ui.gni") - -declare_args() { - # Determines whether or not the Content Service should support remote - # (i.e., out-of-process) clients embedding NavigableContentsViews within their - # UI. If this is false, only clients in the same process as the Content - # Service may use NavigableContentsView. - # - # Currently only supported on Chrome OS, where |toolkit_views| is implied and - # the UI service (i.e. Mus) is available. - enable_remote_navigable_contents_view = is_chromeos -} - -assert(!enable_remote_navigable_contents_view || toolkit_views)
diff --git a/services/content/public/mojom/navigable_contents.mojom b/services/content/public/mojom/navigable_contents.mojom index adc9294..6e78a90 100644 --- a/services/content/public/mojom/navigable_contents.mojom +++ b/services/content/public/mojom/navigable_contents.mojom
@@ -4,7 +4,6 @@ module content.mojom; -import "mojo/public/mojom/base/unguessable_token.mojom"; import "services/network/public/mojom/network_param.mojom"; import "ui/accessibility/mojom/ax_tree_id.mojom"; import "ui/base/mojo/window_open_disposition.mojom"; @@ -32,20 +31,6 @@ // navigation attempt will fail if the history stack is empty. GoBack() => (bool success); - // Creates a visual representation of the navigated contents, which is - // maintained by the Content Service. Responds with a |embed_token| which can - // be given to Mus in order to authorize embedding of that visual - // representation within the client application's own window tree. - // - // |use_window_service| is true when the client calling this method wants to - // use Window Service for embedding. This is the case when the client and the - // Content Service are using different window trees. - // - // TODO(https://crbug.com/874143): Remove the |use_window_service| flag once - // we have more widely available UI Service support. - CreateView(bool use_window_service) - => (mojo_base.mojom.UnguessableToken embed_token); - // Attempts to transfer global input focus to the navigated contents if they // have an active visual representation. Focus();
diff --git a/services/content/simple_browser/BUILD.gn b/services/content/simple_browser/BUILD.gn index 1e0e96ae..f538aa7 100644 --- a/services/content/simple_browser/BUILD.gn +++ b/services/content/simple_browser/BUILD.gn
@@ -3,7 +3,6 @@ # found in the LICENSE file. import("//build/config/ui.gni") -import("//services/content/public/features.gni") component("simple_browser") { public = [ @@ -39,10 +38,6 @@ deps += [ "//ui/aura" ] } - if (enable_remote_navigable_contents_view) { - deps += [ "//ui/views/mus" ] - } - if (is_linux) { public_deps += [ "//components/services/font/public/cpp",
diff --git a/services/content/simple_browser/simple_browser_service.cc b/services/content/simple_browser/simple_browser_service.cc index e32e890e..f9d8afb 100644 --- a/services/content/simple_browser/simple_browser_service.cc +++ b/services/content/simple_browser/simple_browser_service.cc
@@ -11,10 +11,6 @@ #include "third_party/skia/include/ports/SkFontConfigInterface.h" // nogncheck #endif -#if defined(USE_AURA) && BUILDFLAG(ENABLE_REMOTE_NAVIGABLE_CONTENTS_VIEW) -#include "ui/views/mus/aura_init.h" // nogncheck -#endif - namespace simple_browser { SimpleBrowserService::SimpleBrowserService( @@ -32,18 +28,6 @@ sk_make_sp<font_service::FontLoader>(service_binding_.GetConnector()); SkFontConfigInterface::SetGlobal(font_loader_); #endif - -#if defined(USE_AURA) && BUILDFLAG(ENABLE_REMOTE_NAVIGABLE_CONTENTS_VIEW) - views::AuraInit::InitParams params; - params.connector = service_binding_.GetConnector(); - params.identity = service_binding_.identity(); - params.register_path_provider = false; - aura_init_ = views::AuraInit::Create(params); - CHECK(aura_init_); -#else - NOTREACHED() << "Remote UI embedding not supported on this platform."; - -#endif } window_ = std::make_unique<Window>(service_binding_.GetConnector());
diff --git a/services/content/simple_browser/simple_browser_service.h b/services/content/simple_browser/simple_browser_service.h index 7d77cdd..7a8e866 100644 --- a/services/content/simple_browser/simple_browser_service.h +++ b/services/content/simple_browser/simple_browser_service.h
@@ -11,7 +11,6 @@ #include "base/component_export.h" #include "base/macros.h" #include "build/build_config.h" -#include "services/content/public/cpp/buildflags.h" #include "services/service_manager/public/cpp/service.h" #include "services/service_manager/public/cpp/service_binding.h" #include "services/service_manager/public/mojom/service.mojom.h" @@ -20,10 +19,6 @@ #include "components/services/font/public/cpp/font_loader.h" // nogncheck #endif -namespace views { -class AuraInit; -} - namespace simple_browser { class Window; @@ -57,10 +52,6 @@ service_manager::ServiceBinding service_binding_; const UIInitializationMode ui_initialization_mode_; -#if defined(USE_AURA) && BUILDFLAG(ENABLE_REMOTE_NAVIGABLE_CONTENTS_VIEW) - std::unique_ptr<views::AuraInit> aura_init_; -#endif - std::unique_ptr<Window> window_; DISALLOW_COPY_AND_ASSIGN(SimpleBrowserService);
diff --git a/services/network/public/cpp/features.cc b/services/network/public/cpp/features.cc index f63885e5..a73c894 100644 --- a/services/network/public/cpp/features.cc +++ b/services/network/public/cpp/features.cc
@@ -45,6 +45,13 @@ const base::Feature kThrottleDelayable{"ThrottleDelayable", base::FEATURE_ENABLED_BY_DEFAULT}; +// When kPriorityRequestsDelayableOnSlowConnections is enabled, HTTP +// requests fetched from a SPDY/QUIC/H2 proxies can be delayed by the +// ResourceScheduler just as HTTP/1.1 resources are. However, requests from such +// servers are not subject to kMaxNumDelayableRequestsPerHostPerClient limit. +const base::Feature kDelayRequestsOnMultiplexedConnections{ + "DelayRequestsOnMultiplexedConnections", base::FEATURE_ENABLED_BY_DEFAULT}; + // Kill switch for enforcing // URLLoaderFactoryParams::request_initiator_origin_lock for Cross-Origin Read // Blocking. When enabled, then CORB treats |request_initiator| as opaque
diff --git a/services/network/public/cpp/features.h b/services/network/public/cpp/features.h index 5a54659..d10a61c 100644 --- a/services/network/public/cpp/features.h +++ b/services/network/public/cpp/features.h
@@ -24,6 +24,8 @@ COMPONENT_EXPORT(NETWORK_CPP) extern const base::Feature kThrottleDelayable; COMPONENT_EXPORT(NETWORK_CPP) +extern const base::Feature kDelayRequestsOnMultiplexedConnections; +COMPONENT_EXPORT(NETWORK_CPP) extern const base::Feature kEnforceRequestInitiatorLockForCorb; COMPONENT_EXPORT(NETWORK_CPP) extern const base::Feature kFetchMetadata;
diff --git a/services/network/resource_scheduler_params_manager.cc b/services/network/resource_scheduler_params_manager.cc index 7594464..17dd66b 100644 --- a/services/network/resource_scheduler_params_manager.cc +++ b/services/network/resource_scheduler_params_manager.cc
@@ -56,17 +56,17 @@ result.emplace(std::make_pair( net::EFFECTIVE_CONNECTION_TYPE_SLOW_2G, ResourceSchedulerParamsManager::ParamsForNetworkQuality( - 8, 3.0, true /* delay_requests_on_multiplexed_connections */, + 8, 3.0, false /* delay_requests_on_multiplexed_connections */, base::nullopt))); result.emplace(std::make_pair( net::EFFECTIVE_CONNECTION_TYPE_2G, ResourceSchedulerParamsManager::ParamsForNetworkQuality( - 8, 3.0, true /* delay_requests_on_multiplexed_connections */, + 8, 3.0, false /* delay_requests_on_multiplexed_connections */, base::nullopt))); result.emplace(std::make_pair( net::EFFECTIVE_CONNECTION_TYPE_3G, ResourceSchedulerParamsManager::ParamsForNetworkQuality( - 8, 3.0, true /* delay_requests_on_multiplexed_connections */, + 8, 3.0, false /* delay_requests_on_multiplexed_connections */, base::nullopt))); for (int config_param_index = 1; config_param_index <= 20; @@ -110,6 +110,40 @@ } } + // Next, read the experiments params for + // DelayRequestsOnMultiplexedConnections finch experiment, and modify |result| + // based on the experiment params. + if (base::FeatureList::IsEnabled( + features::kDelayRequestsOnMultiplexedConnections)) { + base::Optional<net::EffectiveConnectionType> max_effective_connection_type = + net::GetEffectiveConnectionTypeForName( + base::GetFieldTrialParamValueByFeature( + features::kDelayRequestsOnMultiplexedConnections, + "MaxEffectiveConnectionType")); + + if (!max_effective_connection_type) { + // Use a default value if one is not set using field trial params. + max_effective_connection_type = net::EFFECTIVE_CONNECTION_TYPE_3G; + } + + for (int ect = net::EFFECTIVE_CONNECTION_TYPE_SLOW_2G; + ect <= max_effective_connection_type.value(); ++ect) { + net::EffectiveConnectionType effective_connection_type = + static_cast<net::EffectiveConnectionType>(ect); + ResourceSchedulerParamsManager::ParamsForNetworkQualityContainer::iterator + iter = result.find(effective_connection_type); + if (iter != result.end()) { + iter->second.delay_requests_on_multiplexed_connections = true; + } else { + result.emplace(std::make_pair( + effective_connection_type, + ResourceSchedulerParamsManager::ParamsForNetworkQuality( + kDefaultMaxNumDelayableRequestsPerClient, 0.0, true, + base::nullopt))); + } + } + } + for (int ect = net::EFFECTIVE_CONNECTION_TYPE_UNKNOWN; ect <= net::EFFECTIVE_CONNECTION_TYPE_4G; ++ect) { net::EffectiveConnectionType effective_connection_type =
diff --git a/services/network/resource_scheduler_params_manager.h b/services/network/resource_scheduler_params_manager.h index 677555f..ab866e2 100644 --- a/services/network/resource_scheduler_params_manager.h +++ b/services/network/resource_scheduler_params_manager.h
@@ -42,8 +42,6 @@ // True if requests to servers that support prioritization (e.g., // H2/SPDY/QUIC) should be delayed similar to other HTTP 1.1 requests. - // However, requests from such servers are not subject to - // kMaxNumDelayableRequestsPerHostPerClient limit. bool delay_requests_on_multiplexed_connections; // The maximum duration for which a request is queued after after which the
diff --git a/services/network/resource_scheduler_params_manager_unittest.cc b/services/network/resource_scheduler_params_manager_unittest.cc index a5f43e91..7da56710e 100644 --- a/services/network/resource_scheduler_params_manager_unittest.cc +++ b/services/network/resource_scheduler_params_manager_unittest.cc
@@ -177,11 +177,10 @@ } } -// Verify that the params are parsed correctly. +// Verify that the params are parsed correctly when +// kDelayRequestsOnMultiplexedConnections is enabled. TEST_F(ResourceSchedulerParamsManagerTest, DelayRequestsOnMultiplexedConnections) { - base::FieldTrialParamAssociator::GetInstance()->ClearAllParamsForTesting(); - ResourceSchedulerParamsManager resource_scheduler_params_manager; for (int effective_connection_type = net::EFFECTIVE_CONNECTION_TYPE_UNKNOWN; @@ -213,6 +212,45 @@ } } +// Verify that the params are parsed correctly when +// kDelayRequestsOnMultiplexedConnections is disabled. +TEST_F(ResourceSchedulerParamsManagerTest, + DisableDelayRequestsOnMultiplexedConnections) { + base::test::ScopedFeatureList scoped_feature_list; + scoped_feature_list.InitAndDisableFeature( + features::kDelayRequestsOnMultiplexedConnections); + + ResourceSchedulerParamsManager resource_scheduler_params_manager; + + for (int effective_connection_type = net::EFFECTIVE_CONNECTION_TYPE_UNKNOWN; + effective_connection_type < net::EFFECTIVE_CONNECTION_TYPE_LAST; + ++effective_connection_type) { + net::EffectiveConnectionType ect = + static_cast<net::EffectiveConnectionType>(effective_connection_type); + if (effective_connection_type == net::EFFECTIVE_CONNECTION_TYPE_SLOW_2G || + effective_connection_type == net::EFFECTIVE_CONNECTION_TYPE_2G || + effective_connection_type == net::EFFECTIVE_CONNECTION_TYPE_3G) { + EXPECT_EQ(8u, resource_scheduler_params_manager + .GetParamsForEffectiveConnectionType(ect) + .max_delayable_requests); + EXPECT_EQ(3.0, resource_scheduler_params_manager + .GetParamsForEffectiveConnectionType(ect) + .non_delayable_weight); + EXPECT_FALSE(resource_scheduler_params_manager + .GetParamsForEffectiveConnectionType(ect) + .delay_requests_on_multiplexed_connections); + EXPECT_TRUE(resource_scheduler_params_manager + .GetParamsForEffectiveConnectionType(ect) + .max_queuing_time.has_value()); + + } else { + VerifyDefaultParams( + resource_scheduler_params_manager, + static_cast<net::EffectiveConnectionType>(effective_connection_type)); + } + } +} + TEST_F(ResourceSchedulerParamsManagerTest, MaxQueuingTime) { base::FieldTrialParamAssociator::GetInstance()->ClearAllParamsForTesting(); const std::string kTrialName = "TrialFoo"; @@ -295,8 +333,8 @@ } } -// Verify that the params are parsed correctly when kThrottleDelayable is -// enabled. +// Verify that the params are parsed correctly when +// kDelayRequestsOnMultiplexedConnections and kThrottleDelayable are enabled. TEST_F(ResourceSchedulerParamsManagerTest, MultipleFieldTrialsEnabled) { base::FieldTrialParamAssociator::GetInstance()->ClearAllParamsForTesting(); const std::string kTrialNameMultiplex = "TrialMultiplex"; @@ -305,8 +343,20 @@ base::test::ScopedFeatureList scoped_feature_list; - // Configure kThrottleDelayable experiment params. + // Configure kDelayRequestsOnMultiplexedConnections experiment params. + std::map<std::string, std::string> params_multiplex; + params_multiplex["MaxEffectiveConnectionType"] = "3G"; + scoped_refptr<base::FieldTrial> trial_multiplex = + base::FieldTrialList::CreateFieldTrial(kTrialNameMultiplex, kGroupName); + ASSERT_TRUE( + base::FieldTrialParamAssociator::GetInstance()->AssociateFieldTrialParams( + kTrialNameMultiplex, kGroupName, params_multiplex)); std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList); + feature_list->RegisterFieldTrialOverride( + features::kDelayRequestsOnMultiplexedConnections.name, + base::FeatureList::OVERRIDE_ENABLE_FEATURE, trial_multiplex.get()); + + // Configure kThrottleDelayable experiment params. std::map<std::string, std::string> params_throttle_delayable; params_throttle_delayable["EffectiveConnectionType1"] = "3G"; params_throttle_delayable["MaxDelayableRequests1"] = "12";
diff --git a/services/tracing/BUILD.gn b/services/tracing/BUILD.gn index ee45f2c..867ff04e 100644 --- a/services/tracing/BUILD.gn +++ b/services/tracing/BUILD.gn
@@ -62,6 +62,7 @@ testonly = true sources = [ + "perfetto/privacy_filtered_fields-inl.h", "perfetto/privacy_filtering_check.cc", "perfetto/privacy_filtering_check.h", ]
diff --git a/services/tracing/perfetto/privacy_filtered_fields-inl.h b/services/tracing/perfetto/privacy_filtered_fields-inl.h new file mode 100644 index 0000000..9ec0233 --- /dev/null +++ b/services/tracing/perfetto/privacy_filtered_fields-inl.h
@@ -0,0 +1,98 @@ +// 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 SERVICES_TRACING_PERFETTO_PRIVACY_FILTERED_FIELDS_INL_H_ +#define SERVICES_TRACING_PERFETTO_PRIVACY_FILTERED_FIELDS_INL_H_ + +// This file is auto generated from internal copy of the TracePacket proto, that +// does not contain any privacy sensitive fields. Updates to this file should be +// made by changing internal copy and then running the generator script. Follow +// instructions at: +// https://goto.google.com/chrome-trace-privacy-filtered-fields + +namespace tracing { + +// A MessageInfo node created from a tree of TracePacket proto messages. +struct MessageInfo { + // List of accepted field ids in the output for this message. The end of list + // is marked by a -1. + const int* accepted_field_ids; + + // List of sub messages that correspond to the accepted field ids list. There + // is no end of list marker and the length is this list is equal to length of + // |accepted_field_ids| - 1. + const MessageInfo* const* const sub_messages; +}; + +// Proto Message: TaskExecution +constexpr int kTaskExecutionIndices[] = {1, -1}; +constexpr MessageInfo kTaskExecution = {kTaskExecutionIndices, nullptr}; + +// Proto Message: LegacyEvent +constexpr int kLegacyEventIndices[] = {1, 2, 3, 4, 6, 8, 9, 10, + 11, 12, 13, 14, 18, 19, -1}; +constexpr MessageInfo kLegacyEvent = {kLegacyEventIndices, nullptr}; + +// Proto Message: TrackEvent +constexpr int kTrackEventIndices[] = {1, 2, 3, 5, 6, 16, 17, -1}; +constexpr MessageInfo const* kTrackEventComplexMessages[] = { + nullptr, nullptr, nullptr, &kTaskExecution, + &kLegacyEvent, nullptr, nullptr}; +constexpr MessageInfo kTrackEvent = {kTrackEventIndices, + kTrackEventComplexMessages}; + +// Proto Message: EventCategory +constexpr int kEventCategoryIndices[] = {1, 2, -1}; +constexpr MessageInfo kEventCategory = {kEventCategoryIndices, nullptr}; + +// Proto Message: LegacyEventName +constexpr int kLegacyEventNameIndices[] = {1, 2, -1}; +constexpr MessageInfo kLegacyEventName = {kLegacyEventNameIndices, nullptr}; + +// Proto Message: SourceLocation +constexpr int kSourceLocationIndices[] = {1, 2, 3, -1}; +constexpr MessageInfo kSourceLocation = {kSourceLocationIndices, nullptr}; + +// Proto Message: InternedData +constexpr int kInternedDataIndices[] = {1, 2, 4, -1}; +constexpr MessageInfo const* kInternedDataComplexMessages[] = { + &kEventCategory, &kLegacyEventName, &kSourceLocation}; +constexpr MessageInfo kInternedData = {kInternedDataIndices, + kInternedDataComplexMessages}; + +// Proto Message: BufferStats +constexpr int kBufferStatsIndices[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, + 11, 12, 13, 14, 15, 16, 17, 18, -1}; +constexpr MessageInfo kBufferStats = {kBufferStatsIndices, nullptr}; + +// Proto Message: TraceStats +constexpr int kTraceStatsIndices[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, -1}; +constexpr MessageInfo const* kTraceStatsComplexMessages[] = { + &kBufferStats, nullptr, nullptr, nullptr, nullptr, + nullptr, nullptr, nullptr, nullptr}; +constexpr MessageInfo kTraceStats = {kTraceStatsIndices, + kTraceStatsComplexMessages}; + +// Proto Message: ProcessDescriptor +constexpr int kProcessDescriptorIndices[] = {1, 4, -1}; +constexpr MessageInfo kProcessDescriptor = {kProcessDescriptorIndices, nullptr}; + +// Proto Message: ThreadDescriptor +constexpr int kThreadDescriptorIndices[] = {1, 2, 4, 6, 7, -1}; +constexpr MessageInfo kThreadDescriptor = {kThreadDescriptorIndices, nullptr}; + +// EDIT: Contains field numbers: {3} which are not autogenerated. + +// Proto Message: TracePacket +constexpr int kTracePacketIndices[] = {3, 10, 11, 12, 35, 36, + 41, 42, 43, 44, -1}; +constexpr MessageInfo const* kTracePacketComplexMessages[] = { + nullptr, nullptr, &kTrackEvent, &kInternedData, &kTraceStats, + nullptr, nullptr, nullptr, &kProcessDescriptor, &kThreadDescriptor}; +constexpr MessageInfo kTracePacket = {kTracePacketIndices, + kTracePacketComplexMessages}; + +} // namespace tracing + +#endif // SERVICES_TRACING_PERFETTO_PRIVACY_FILTERED_FIELDS_INL_H_
diff --git a/services/tracing/perfetto/privacy_filtering_check.cc b/services/tracing/perfetto/privacy_filtering_check.cc index 03e994c..15af537 100644 --- a/services/tracing/perfetto/privacy_filtering_check.cc +++ b/services/tracing/perfetto/privacy_filtering_check.cc
@@ -5,6 +5,7 @@ #include "services/tracing/perfetto/privacy_filtering_check.h" #include "base/logging.h" +#include "services/tracing/perfetto/privacy_filtered_fields-inl.h" #include "third_party/perfetto/protos/perfetto/trace/interned_data/interned_data.pbzero.h" #include "third_party/perfetto/protos/perfetto/trace/trace.pbzero.h" #include "third_party/perfetto/protos/perfetto/trace/trace_packet.pbzero.h" @@ -18,79 +19,6 @@ using perfetto::protos::pbzero::TrackEvent; using protozero::ProtoDecoder; -// A Message node created from a tree of trace packet proto messages. -struct Message { - // List of accepted field ids in the output for this message. The end of list - // is marked by a -1. - const int* accepted_field_ids; - - // List of sub messages that correspond to the accepted field ids list. There - // is no end of list marker and the length is this list is equal to length of - // |accepted_field_ids| - 1. - const Message* const* const sub_messages; -}; - -// The structure of acceptable field IDs in the output proto. -// TODO(ssid): This should be generated as a resource file using the proto -// definitions using a script. - -// Interned data types: -constexpr int kSourceLocationIndices[] = {1, 2, 3, -1}; -constexpr Message kSourceLocation = {kSourceLocationIndices, nullptr}; - -constexpr int kLegacyEventNameIndices[] = {1, 2, -1}; -constexpr Message kLegacyEventName = {kLegacyEventNameIndices, nullptr}; - -constexpr int kEventCategoryIndices[] = {1, 2, -1}; -constexpr Message kEventCategory = {kEventCategoryIndices, nullptr}; - -constexpr int kInternedDataIndices[] = {1, 2, 4, -1}; -constexpr Message const* kInternedDataComplexMessages[] = { - &kEventCategory, &kLegacyEventName, &kSourceLocation}; -constexpr Message kInternedData = {kInternedDataIndices, - kInternedDataComplexMessages}; - -// Typed track events: -constexpr int kTaskExecutionIndices[] = {1, -1}; -constexpr Message kTaskExecution = {kTaskExecutionIndices, nullptr}; - -// Track event tree: -constexpr int kThreadDescriptorIndices[] = {1, 2, 4, 6, 7, -1}; -constexpr Message kThreadDescriptor = {kThreadDescriptorIndices, nullptr}; - -constexpr int kProcessDescriptorIndices[] = {1, 4, -1}; -constexpr Message kProcessDescriptor = {kProcessDescriptorIndices, nullptr}; - -constexpr int kLegacyEventIndices[] = {1, 2, 3, 4, 6, 8, 9, 10, - 11, 12, 13, 14, 18, 19, -1}; -constexpr Message kLegacyEvent = {kLegacyEventIndices, nullptr}; - -constexpr int kTrackEventIndices[] = {1, 2, 3, 5, 6, 16, 17, -1}; -constexpr Message const* kTrackEventComplexMessages[] = { - nullptr, nullptr, nullptr, &kTaskExecution, - &kLegacyEvent, nullptr, nullptr}; -constexpr Message kTrackEvent = {kTrackEventIndices, - kTrackEventComplexMessages}; - -// Trace packet: -constexpr int kTracePacketIndices[] = {10, 11, 12, 41, 42, 43, 44, - // These should be removed or whitelisted - 3, 33, 35, 36, 45, -1}; -constexpr Message const* kTracePacketComplexMessages[] = {nullptr, - &kTrackEvent, - &kInternedData, - nullptr, - nullptr, - &kProcessDescriptor, - &kThreadDescriptor, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr}; -constexpr Message kTracePacket = {kTracePacketIndices, - kTracePacketComplexMessages}; - int FindIndexOfValue(const int* const arr, uint32_t value) { for (unsigned i = 0; arr[i] != -1; ++i) { if (static_cast<int>(value) == arr[i]) @@ -101,7 +29,7 @@ // Recursively verifies that the |proto| contains only accepted field IDs // including all sub messages. -void VerifyProto(const Message* root, ProtoDecoder* proto) { +void VerifyProto(const MessageInfo* root, ProtoDecoder* proto) { proto->Reset(); for (auto f = proto->ReadField(); f.valid(); f = proto->ReadField()) { int index = FindIndexOfValue(root->accepted_field_ids, f.id()); @@ -129,7 +57,7 @@ for (auto it = trace.packet(); !!it; ++it) { TracePacket::Decoder packet(it->data(), it->size()); - const Message* root = &kTracePacket; + const MessageInfo* root = &kTracePacket; VerifyProto(root, &packet); if (packet.has_track_event()) {
diff --git a/services/tracing/public/cpp/perfetto/perfetto_config.cc b/services/tracing/public/cpp/perfetto/perfetto_config.cc index b77f14a..4f85779 100644 --- a/services/tracing/public/cpp/perfetto/perfetto_config.cc +++ b/services/tracing/public/cpp/perfetto/perfetto_config.cc
@@ -29,6 +29,8 @@ // blocked by the sandboxed and isn't needed for Chrome regardless. auto* builtin_data_sources = perfetto_config.mutable_builtin_data_sources(); builtin_data_sources->set_disable_clock_snapshotting(true); + builtin_data_sources->set_disable_trace_config(privacy_filtering_enabled); + builtin_data_sources->set_disable_system_info(privacy_filtering_enabled); // Capture actual trace events. auto* trace_event_data_source = perfetto_config.add_data_sources();
diff --git a/services/tracing/public/mojom/perfetto_service.mojom b/services/tracing/public/mojom/perfetto_service.mojom index b4dedf0..799b2c4 100644 --- a/services/tracing/public/mojom/perfetto_service.mojom +++ b/services/tracing/public/mojom/perfetto_service.mojom
@@ -149,11 +149,18 @@ array<string> producer_name_filter; }; +struct PerfettoBuiltinDataSource { + bool disable_clock_snapshotting; + bool disable_trace_config; + bool disable_system_info; +}; + // The configuration provided by a Consumer to the Perfetto service which // primarily configures which named data sources it would like to enable and // receive tracing data from, and how large the destination buffers should be. struct TraceConfig { array<DataSource> data_sources; + PerfettoBuiltinDataSource perfetto_builtin_data_source; array<BufferConfig> buffers; uint32 duration_ms;
diff --git a/services/tracing/public/mojom/perfetto_service.typemap b/services/tracing/public/mojom/perfetto_service.typemap index 5bec6e4..2671fac 100644 --- a/services/tracing/public/mojom/perfetto_service.typemap +++ b/services/tracing/public/mojom/perfetto_service.typemap
@@ -36,5 +36,6 @@ "tracing.mojom.DataSourceConfig=perfetto::DataSourceConfig", "tracing.mojom.ChromeConfig=perfetto::ChromeConfig", "tracing.mojom.DataSourceRegistration=perfetto::DataSourceDescriptor", + "tracing.mojom.PerfettoBuiltinDataSource=perfetto::TraceConfig::BuiltinDataSource", "tracing.mojom.TraceConfig=perfetto::TraceConfig", ]
diff --git a/services/tracing/public/mojom/trace_config_mojom_traits.cc b/services/tracing/public/mojom/trace_config_mojom_traits.cc index 649fbe9..9e78d913 100644 --- a/services/tracing/public/mojom/trace_config_mojom_traits.cc +++ b/services/tracing/public/mojom/trace_config_mojom_traits.cc
@@ -45,11 +45,24 @@ } // static +bool StructTraits<tracing::mojom::PerfettoBuiltinDataSourceDataView, + perfetto::TraceConfig::BuiltinDataSource>:: + Read(tracing::mojom::PerfettoBuiltinDataSourceDataView data, + perfetto::TraceConfig::BuiltinDataSource* out) { + out->set_disable_clock_snapshotting(data.disable_clock_snapshotting()); + out->set_disable_trace_config(data.disable_trace_config()); + out->set_disable_system_info(data.disable_system_info()); + return true; +} + +// static bool StructTraits<tracing::mojom::TraceConfigDataView, perfetto::TraceConfig>:: Read(tracing::mojom::TraceConfigDataView data, perfetto::TraceConfig* out) { std::vector<perfetto::TraceConfig::DataSource> data_sources; std::vector<perfetto::TraceConfig::BufferConfig> buffers; - if (!data.ReadDataSources(&data_sources) || !data.ReadBuffers(&buffers)) { + if (!data.ReadDataSources(&data_sources) || !data.ReadBuffers(&buffers) || + !data.ReadPerfettoBuiltinDataSource( + out->mutable_builtin_data_sources())) { return false; }
diff --git a/services/tracing/public/mojom/trace_config_mojom_traits.h b/services/tracing/public/mojom/trace_config_mojom_traits.h index 018d1bd..bb274ef 100644 --- a/services/tracing/public/mojom/trace_config_mojom_traits.h +++ b/services/tracing/public/mojom/trace_config_mojom_traits.h
@@ -49,6 +49,30 @@ perfetto::TraceConfig::DataSource* out); }; +// perfetto::TraceConfig::BuiltinDataSource +template <> +class StructTraits<tracing::mojom::PerfettoBuiltinDataSourceDataView, + perfetto::TraceConfig::BuiltinDataSource> { + public: + static bool disable_clock_snapshotting( + const perfetto::TraceConfig::BuiltinDataSource& src) { + return src.disable_clock_snapshotting(); + } + + static bool disable_trace_config( + const perfetto::TraceConfig::BuiltinDataSource& src) { + return src.disable_trace_config(); + } + + static bool disable_system_info( + const perfetto::TraceConfig::BuiltinDataSource& src) { + return src.disable_system_info(); + } + + static bool Read(tracing::mojom::PerfettoBuiltinDataSourceDataView data, + perfetto::TraceConfig::BuiltinDataSource* out); +}; + // perfetto::TraceConfig template <> class StructTraits<tracing::mojom::TraceConfigDataView, perfetto::TraceConfig> { @@ -58,6 +82,11 @@ return src.data_sources(); } + static const perfetto::TraceConfig::BuiltinDataSource& + perfetto_builtin_data_source(const perfetto::TraceConfig& src) { + return src.builtin_data_sources(); + } + static const std::vector<perfetto::TraceConfig::BufferConfig>& buffers( const perfetto::TraceConfig& src) { return src.buffers();
diff --git a/testing/buildbot/chromium.android.json b/testing/buildbot/chromium.android.json index 5b576c76..0599546 100644 --- a/testing/buildbot/chromium.android.json +++ b/testing/buildbot/chromium.android.json
@@ -17797,16 +17797,21 @@ "test": "net_unittests" } ], - "scripts": [ + "isolated_scripts": [ { - "args": [ - "--platform", - "android-cronet", - "--target", - "Debug" - ], - "name": "sizes", - "script": "cronet_sizes.py" + "isolate_name": "cronet_sizes", + "merge": { + "script": "//tools/perf/process_perf_results.py" + }, + "name": "cronet_sizes", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-14.04" + } + ] + } } ] }, @@ -17845,18 +17850,6 @@ ] } } - ], - "scripts": [ - { - "args": [ - "--platform", - "android-cronet", - "--target", - "Release" - ], - "name": "sizes", - "script": "cronet_sizes.py" - } ] }, "android-cronet-arm64-dbg": { @@ -17871,16 +17864,21 @@ "cronet_unittests_android", "net_unittests" ], - "scripts": [ + "isolated_scripts": [ { - "args": [ - "--platform", - "android-cronet", - "--target", - "Debug" - ], - "name": "sizes", - "script": "cronet_sizes.py" + "isolate_name": "cronet_sizes", + "merge": { + "script": "//tools/perf/process_perf_results.py" + }, + "name": "cronet_sizes", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-14.04" + } + ] + } } ] }, @@ -17927,18 +17925,6 @@ ] } } - ], - "scripts": [ - { - "args": [ - "--platform", - "android-cronet", - "--target", - "Release" - ], - "name": "sizes", - "script": "cronet_sizes.py" - } ] }, "android-cronet-asan-arm-rel": { @@ -18876,16 +18862,21 @@ "cronet_unittests_android", "net_unittests" ], - "scripts": [ + "isolated_scripts": [ { - "args": [ - "--platform", - "android-cronet", - "--target", - "Debug" - ], - "name": "sizes", - "script": "cronet_sizes.py" + "isolate_name": "cronet_sizes", + "merge": { + "script": "//tools/perf/process_perf_results.py" + }, + "name": "cronet_sizes", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-14.04" + } + ] + } } ] }, @@ -18932,18 +18923,6 @@ ] } } - ], - "scripts": [ - { - "args": [ - "--platform", - "android-cronet", - "--target", - "Release" - ], - "name": "sizes", - "script": "cronet_sizes.py" - } ] }, "android-incremental-dbg": {
diff --git a/testing/buildbot/chromium.linux.json b/testing/buildbot/chromium.linux.json index b1c22ed..17be05d 100644 --- a/testing/buildbot/chromium.linux.json +++ b/testing/buildbot/chromium.linux.json
@@ -1784,6 +1784,24 @@ "test": "fidlgen_js_unittests" }, { + "args": [ + "--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.gfx_unittests.filter" + ], + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "kvm": "1" + } + ] + }, + "test": "gfx_unittests" + }, + { "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py"
diff --git a/testing/buildbot/generate_buildbot_json.py b/testing/buildbot/generate_buildbot_json.py index 3aadda73..93f5e08 100755 --- a/testing/buildbot/generate_buildbot_json.py +++ b/testing/buildbot/generate_buildbot_json.py
@@ -353,12 +353,15 @@ raise BBGenErr('Error merging list keys ' + str(key) + ' and indices ' + str(idx) + ' between ' + str(a) + ' and ' + str(b)) # pragma: no cover - elif update: # pragma: no cover - a[key] = b[key] # pragma: no cover + elif update: + if b[key] is None: + del a[key] + else: + a[key] = b[key] else: raise BBGenErr('Conflict at %s' % '.'.join( path + [str(key)])) # pragma: no cover - else: + elif b[key] is not None: a[key] = b[key] return a
diff --git a/testing/buildbot/generate_buildbot_json_unittest.py b/testing/buildbot/generate_buildbot_json_unittest.py index b4e6c09..e227840 100755 --- a/testing/buildbot/generate_buildbot_json_unittest.py +++ b/testing/buildbot/generate_buildbot_json_unittest.py
@@ -854,6 +854,24 @@ } """ +FOO_TEST_EXPLICIT_NONE_EXCEPTIONS = """\ +{ + 'foo_test': { + 'modifications': { + 'Fake Tester': { + 'swarming': { + 'dimension_sets': [ + { + 'integrity': None, + }, + ], + }, + }, + }, + }, +} +""" + NONEXISTENT_REMOVAL = """\ { 'foo_test': { @@ -1121,6 +1139,33 @@ } """ +EXPLICIT_NONE_OUTPUT = """\ +{ + "AAAAA1 AUTOGENERATED FILE DO NOT EDIT": {}, + "AAAAA2 See generate_buildbot_json.py to make changes": {}, + "Fake Tester": { + "gtest_tests": [ + { + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "kvm": "1" + } + ], + "expiration": 120 + }, + "test": "foo_test" + } + ] + } +} +""" + ISOLATED_SCRIPT_OUTPUT = """\ { "AAAAA1 AUTOGENERATED FILE DO NOT EDIT": {}, @@ -2048,6 +2093,16 @@ fbb.check_output_file_consistency(verbose=True) self.assertFalse(fbb.printed_lines) + def test_test_with_explicit_none(self): + fbb = FakeBBGen(FOO_GTESTS_WATERFALL, + FOO_TEST_SUITE, + FOO_TEST_EXPLICIT_NONE_EXCEPTIONS, + SWARMING_MIXINS, + LUCI_MILO_CFG) + fbb.files['chromium.test.json'] = EXPLICIT_NONE_OUTPUT + fbb.check_output_file_consistency(verbose=True) + self.assertFalse(fbb.printed_lines) + def test_isolated_script_tests(self): fbb = FakeBBGen(FOO_ISOLATED_SCRIPTS_WATERFALL, GOOD_COMPOSITION_TEST_SUITES,
diff --git a/testing/buildbot/test_suite_exceptions.pyl b/testing/buildbot/test_suite_exceptions.pyl index eda4f12f..c1406a8 100644 --- a/testing/buildbot/test_suite_exceptions.pyl +++ b/testing/buildbot/test_suite_exceptions.pyl
@@ -474,6 +474,21 @@ 'linux-win_cross-rel', # https://crbug.com/762167 ], }, + 'cronet_sizes': { + 'modifications': { + 'android-cronet-arm-dbg': { + 'swarming': { + 'dimension_sets': [ + { + 'device_os': None, + 'device_type': None, + 'os': 'Ubuntu-14.04', + }, + ], + }, + }, + }, + }, 'dawn_end2end_tests': { 'remove_from': [ # chromium.gpu.fyi @@ -492,12 +507,6 @@ }, }, }, - 'gfx_unittests': { - 'remove_from': [ - # chromium.linux - 'Fuchsia x64', # https://crbug.com/952652 - ], - }, 'gin_unittests': { 'remove_from': [ # chromium.clang @@ -1162,46 +1171,6 @@ 'Linux MSan Tests', # https://crbug.com/831676 ], }, - 'sizes': { - 'modifications': { - 'android-cronet-arm-dbg': { - 'args': [ - '--platform', 'android-cronet', - '--target', 'Debug', - ], - }, - 'android-cronet-arm-rel': { - 'args': [ - '--platform', 'android-cronet', - '--target', 'Release', - ], - }, - 'android-cronet-arm64-dbg': { - 'args': [ - '--platform', 'android-cronet', - '--target', 'Debug', - ], - }, - 'android-cronet-arm64-rel': { - 'args': [ - '--platform', 'android-cronet', - '--target', 'Release', - ], - }, - 'android-cronet-x86-dbg': { - 'args': [ - '--platform', 'android-cronet', - '--target', 'Debug', - ], - }, - 'android-cronet-x86-rel': { - 'args': [ - '--platform', 'android-cronet', - '--target', 'Release', - ], - }, - }, - }, 'swiftshader_unittests': { 'remove_from': [ # Save capacity on the hardware where we have only a few machines.
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl index aa7abbd..ff919409 100644 --- a/testing/buildbot/test_suites.pyl +++ b/testing/buildbot/test_suites.pyl
@@ -2545,25 +2545,15 @@ }, }, - 'cronet_isolated_scripts': { - 'cronet_sizes': { - 'merge': { - 'script': '//tools/perf/process_perf_results.py', - }, - 'swarming': { - 'dimension_sets': [ - { - 'os': 'Ubuntu-14.04' - }, - ], - }, - }, + 'cronet_resource_sizes': { 'resource_sizes_cronet_sample_apk': { 'merge': { 'script': '//tools/perf/process_perf_results.py', }, 'swarming': { 'dimension_sets': [ + # This suite simply analyzes build targets without running them. + # It can thus run on a standard linux machine w/o a device. { 'os': 'Ubuntu-14.04' }, @@ -2572,9 +2562,20 @@ }, }, - 'cronet_scripts': { - 'sizes': { - 'script': 'cronet_sizes.py', + 'cronet_sizes': { + 'cronet_sizes': { + 'merge': { + 'script': '//tools/perf/process_perf_results.py', + }, + 'swarming': { + 'dimension_sets': [ + # This suite simply analyzes build targets without running them. + # It can thus run on a standard linux machine w/o a device. + { + 'os': 'Ubuntu-14.04' + }, + ], + }, }, }, @@ -4552,6 +4553,15 @@ 'win_specific_isolated_scripts', ], + 'cronet_dbg_isolated_scripts': [ + 'cronet_sizes', + ], + + 'cronet_rel_isolated_scripts': [ + 'cronet_sizes', + 'cronet_resource_sizes', + ], + # BEGIN composition test suites used by the GPU bots 'gpu_angle_and_representative_perf_fyi_isolated_scripts': [
diff --git a/testing/buildbot/waterfalls.pyl b/testing/buildbot/waterfalls.pyl index 95d4ef0..809b854c 100644 --- a/testing/buildbot/waterfalls.pyl +++ b/testing/buildbot/waterfalls.pyl
@@ -389,7 +389,7 @@ ], 'test_suites': { 'gtest_tests': 'cronet_gtests', - 'scripts': 'cronet_scripts', + 'isolated_scripts': 'cronet_dbg_isolated_scripts', }, 'swarming': { 'dimension_sets': [ @@ -407,8 +407,7 @@ 'cronet_package', ], 'test_suites': { - 'isolated_scripts': 'cronet_isolated_scripts', - 'scripts': 'cronet_scripts', + 'isolated_scripts': 'cronet_rel_isolated_scripts', }, }, 'android-cronet-arm64-dbg': { @@ -424,7 +423,7 @@ 'net_unittests', ], 'test_suites': { - 'scripts': 'cronet_scripts', + 'isolated_scripts': 'cronet_dbg_isolated_scripts', }, }, 'android-cronet-arm64-rel': { @@ -440,8 +439,7 @@ 'net_unittests', ], 'test_suites': { - 'isolated_scripts': 'cronet_isolated_scripts', - 'scripts': 'cronet_scripts', + 'isolated_scripts': 'cronet_rel_isolated_scripts', }, }, 'android-cronet-asan-arm-rel': { @@ -507,7 +505,7 @@ 'net_unittests', ], 'test_suites': { - 'scripts': 'cronet_scripts', + 'isolated_scripts': 'cronet_dbg_isolated_scripts', }, }, 'android-cronet-x86-rel': { @@ -523,8 +521,7 @@ 'net_unittests', ], 'test_suites': { - 'isolated_scripts': 'cronet_isolated_scripts', - 'scripts': 'cronet_scripts', + 'isolated_scripts': 'cronet_rel_isolated_scripts', }, }, 'android-incremental-dbg': {
diff --git a/testing/libfuzzer/fuzzer_test.gni b/testing/libfuzzer/fuzzer_test.gni index db47fb9..b8078f95 100644 --- a/testing/libfuzzer/fuzzer_test.gni +++ b/testing/libfuzzer/fuzzer_test.gni
@@ -17,6 +17,7 @@ # - additional_configs - additional configs to be used for compilation # - dict - a dictionary file for the fuzzer. # - environment_variables - certain whitelisted environment variables for the +# - configs_to_remove - (EXPERIMENTAL, don't use) configs to remove. # fuzzer (AFL_DRIVER_DONT_DEFER is the only one allowed currently). # - libfuzzer_options - options for the fuzzer (e.g. -max_len=N or -timeout=N). # - asan_options - AddressSanitizer options (e.g. allow_user_segv_handler=1). @@ -195,6 +196,9 @@ ]) deps = test_deps + if (defined(invoker.configs_to_remove)) { + configs -= invoker.configs_to_remove + } if (defined(invoker.additional_configs)) { configs += invoker.additional_configs }
diff --git a/testing/merge_scripts/code_coverage/merge_results.py b/testing/merge_scripts/code_coverage/merge_results.py index aedfb267..333e0d4 100755 --- a/testing/merge_scripts/code_coverage/merge_results.py +++ b/testing/merge_scripts/code_coverage/merge_results.py
@@ -17,6 +17,7 @@ import os import subprocess import sys +import tempfile import merge_lib as coverage_merger @@ -82,6 +83,25 @@ '--output-json', params.output_json, ] + + # TODO(crbug.com/960994): Without specifying an output directory, the layout + # merge script will use the CWD as the output directory and then tries to + # wipe out the content in that directory, and unfortunately, the CWD is a + # temporary directory that has been used to hold the coverage profdata, so + # without the following hack, the merge script will deletes all the profdata + # files and lead to build failures. + # + # This temporary workaround is only used for evaluating the stability of the + # linux-coverage-rel trybot, it should be removed before merging into + # linxu-rel as it's not reliable enough, for example, things could break if + # the name or arguments of the script are changed. + if params.additional_merge_script.endswith('merge_web_test_results.py'): + new_args.extend([ + '--output-directory', + tempfile.mkdtemp(), + '--allow-existing-output-directory', + ]) + if params.additional_merge_script_args: new_args += json.loads(params.additional_merge_script_args)
diff --git a/testing/scripts/cronet_sizes.py b/testing/scripts/cronet_sizes.py deleted file mode 100755 index 26a6d77..0000000 --- a/testing/scripts/cronet_sizes.py +++ /dev/null
@@ -1,22 +0,0 @@ -#!/usr/bin/env vpython -# Copyright 2019 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import json -import sys - -import common -import sizes_common - - -def main_compile_targets(args): - json.dump(['cronet_package'], args.output) - - -if __name__ == '__main__': - funcs = { - 'run': sizes_common.main_run, - 'compile_targets': main_compile_targets - } - sys.exit(common.run_script(sys.argv[1:], funcs))
diff --git a/testing/scripts/sizes_common.py b/testing/scripts/sizes_common.py deleted file mode 100644 index 6b1d22cc..0000000 --- a/testing/scripts/sizes_common.py +++ /dev/null
@@ -1,51 +0,0 @@ -# Copyright 2015 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import argparse -import json -import os -import sys - -import common - -PERF_DASHBOARD_URL = 'https://chromeperf.appspot.com' - - -def create_argparser(): - parser = argparse.ArgumentParser() - parser.add_argument('--perf-id') - parser.add_argument('--results-url', default=PERF_DASHBOARD_URL) - return parser - - -def main_run(script_args): - parser = create_argparser() - args, sizes_args = parser.parse_known_args(script_args.args) - - runtest_args = [ - '--test-type', - 'sizes', - '--run-python-script', - ] - if args.perf_id: - runtest_args.extend([ - '--perf-id', - args.perf_id, - '--results-url=%s' % args.results_url, - '--perf-dashboard-id=sizes', - '--annotate=graphing', - ]) - sizes_cmd = [ - os.path.join(common.SRC_DIR, 'infra', 'scripts', 'legacy', 'scripts', - 'slave', 'chromium', 'sizes.py') - ] - sizes_cmd.extend(sizes_args) - rc = common.run_runtest(script_args, runtest_args + sizes_cmd) - - json.dump({ - 'valid': rc == 0, - 'failures': [], - }, script_args.output) - - return rc
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index 7d3499a..9d61bb7f 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -1286,6 +1286,28 @@ ] } ], + "CerseiFakeboxOnNtp": [ + { + "platforms": [ + "chromeos", + "linux", + "mac", + "windows" + ], + "experiments": [ + { + "name": "CerseiFakeboxOnNtp", + "enable_features": [ + "FakeboxSearchIconColorOnNtp", + "FakeboxSearchIconOnNtp", + "FakeboxShortHintTextOnNtp", + "UseAlternateFakeboxOnNtp", + "UseAlternateFakeboxRectOnNtp" + ] + } + ] + } + ], "CertDualVerificationTrial": [ { "platforms": [ @@ -4475,6 +4497,9 @@ "experiments": [ { "name": "Enabled_20190318", + "params": { + "sw_cache_strategy": "idletask" + }, "enable_features": [ "ServiceWorkerAggressiveCodeCache" ] @@ -5234,25 +5259,6 @@ ] } ], - "UseAlternateFakeboxOnNtp": [ - { - "platforms": [ - "chromeos", - "linux", - "mac", - "windows" - ], - "experiments": [ - { - "name": "UseAlternateFakeboxOnNtp", - "enable_features": [ - "FakeboxSearchIconOnNtp", - "UseAlternateFakeboxOnNtp" - ] - } - ] - } - ], "UseFluentLanguageModel": [ { "platforms": [
diff --git a/third_party/blink/public/mojom/bluetooth/web_bluetooth.mojom b/third_party/blink/public/mojom/bluetooth/web_bluetooth.mojom index 4d907a9..1593dffd 100644 --- a/third_party/blink/public/mojom/bluetooth/web_bluetooth.mojom +++ b/third_party/blink/public/mojom/bluetooth/web_bluetooth.mojom
@@ -51,6 +51,7 @@ // InvalidStateError: SERVICE_NO_LONGER_EXISTS, CHARACTERISTIC_NO_LONGER_EXISTS, + PROMPT_CANCELED, // NetworkError: CONNECT_ALREADY_IN_PROGRESS, CONNECT_AUTH_CANCELED, @@ -95,6 +96,8 @@ REQUEST_DEVICE_WITH_BLOCKLISTED_UUID, REQUEST_DEVICE_FROM_CROSS_ORIGIN_IFRAME, DESCRIPTOR_NO_LONGER_EXISTS, + // NotAllowedError: + SCANNING_BLOCKED, }; struct WebBluetoothLeScanFilter {
diff --git a/third_party/blink/public/platform/platform.h b/third_party/blink/public/platform/platform.h index 4f8c145..fc0f5c16 100644 --- a/third_party/blink/public/platform/platform.h +++ b/third_party/blink/public/platform/platform.h
@@ -105,7 +105,6 @@ class WebAudioBus; class WebAudioLatencyHint; class WebBlobRegistry; -class WebCanvasCaptureHandler; class WebCookieJar; class WebCrypto; class WebDatabaseObserver; @@ -117,7 +116,6 @@ class WebMediaRecorderHandler; class WebMediaStream; class WebMediaStreamCenter; -class WebMediaStreamTrack; class WebPrescientNetworking; class WebPublicSuffixList; class WebPushProvider; @@ -134,7 +132,6 @@ class WebURLLoaderMockFactory; class WebURLResponse; class WebURLResponse; -struct WebSize; namespace scheduler { class WebThreadScheduler; @@ -640,10 +637,6 @@ virtual std::unique_ptr<webrtc::AsyncResolverFactory> CreateWebRtcAsyncResolverFactory(); - // Creates a WebCanvasCaptureHandler to capture Canvas output. - virtual std::unique_ptr<WebCanvasCaptureHandler> - CreateCanvasCaptureHandler(const WebSize&, double, WebMediaStreamTrack*); - // Fills in the WebMediaStream to capture from the WebMediaPlayer identified // by the second parameter. virtual void CreateHTMLVideoElementCapturer(
diff --git a/third_party/blink/renderer/core/BUILD.gn b/third_party/blink/renderer/core/BUILD.gn index 01b448dd..33ac4e1 100644 --- a/third_party/blink/renderer/core/BUILD.gn +++ b/third_party/blink/renderer/core/BUILD.gn
@@ -1982,7 +1982,6 @@ "layout/ng/exclusions/ng_exclusion_space_test.cc", "layout/ng/geometry/ng_box_strut_test.cc", "layout/ng/inline/ng_baseline_test.cc", - "layout/ng/inline/ng_caret_navigator_test.cc", "layout/ng/inline/ng_caret_position_test.cc", "layout/ng/inline/ng_inline_fragment_traversal_test.cc", "layout/ng/inline/ng_inline_items_builder_test.cc",
diff --git a/third_party/blink/renderer/core/animation/animation_input_helpers_test.cc b/third_party/blink/renderer/core/animation/animation_input_helpers_test.cc index 699fa98..aae5ad9d 100644 --- a/third_party/blink/renderer/core/animation/animation_input_helpers_test.cc +++ b/third_party/blink/renderer/core/animation/animation_input_helpers_test.cc
@@ -130,7 +130,6 @@ TimingFunctionRoundTrips("ease-in", exception_state); TimingFunctionRoundTrips("ease-out", exception_state); TimingFunctionRoundTrips("ease-in-out", exception_state); - TimingFunctionRoundTrips("frames(3)", exception_state); TimingFunctionRoundTrips("cubic-bezier(0.1, 5, 0.23, 0)", exception_state); EXPECT_EQ("steps(1, start)", @@ -147,8 +146,6 @@ TimingFunctionThrows("steps(3, nowhere)", exception_state); TimingFunctionThrows("steps(-3, end)", exception_state); - TimingFunctionThrows("frames(3, end)", exception_state); - TimingFunctionThrows("frames(1)", exception_state); TimingFunctionThrows("cubic-bezier(0.1, 0, 4, 0.4)", exception_state); }
diff --git a/third_party/blink/renderer/core/animation/compositor_animations_test.cc b/third_party/blink/renderer/core/animation/compositor_animations_test.cc index 44b51d10..fe3276a 100644 --- a/third_party/blink/renderer/core/animation/compositor_animations_test.cc +++ b/third_party/blink/renderer/core/animation/compositor_animations_test.cc
@@ -84,7 +84,6 @@ scoped_refptr<TimingFunction> cubic_ease_timing_function_; scoped_refptr<TimingFunction> cubic_custom_timing_function_; scoped_refptr<TimingFunction> step_timing_function_; - scoped_refptr<TimingFunction> frames_timing_function_; Timing timing_; CompositorAnimations::CompositorTiming compositor_timing_; @@ -106,7 +105,6 @@ CubicBezierTimingFunction::Create(1, 2, 3, 4); step_timing_function_ = StepsTimingFunction::Create(1, StepsTimingFunction::StepPosition::END); - frames_timing_function_ = FramesTimingFunction::Create(2); timing_ = CreateCompositableTiming(); compositor_timing_ = CompositorAnimations::CompositorTiming(); @@ -767,15 +765,6 @@ } TEST_P(AnimationCompositorAnimationsTest, - CanStartEffectOnCompositorTimingFunctionFrames) { - timing_.timing_function = frames_timing_function_; - EXPECT_TRUE( - CanStartEffectOnCompositor(timing_, *keyframe_animation_effect2_)); - EXPECT_TRUE( - CanStartEffectOnCompositor(timing_, *keyframe_animation_effect5_)); -} - -TEST_P(AnimationCompositorAnimationsTest, CanStartEffectOnCompositorTimingFunctionChainedLinear) { EXPECT_TRUE( CanStartEffectOnCompositor(timing_, *keyframe_animation_effect2_)); @@ -1187,22 +1176,14 @@ EXPECT_TRUE( CanStartEffectOnCompositor(timing_, *keyframe_animation_effect2_)); - keyframe_vector2_->at(0)->SetEasing(frames_timing_function_.get()); - keyframe_animation_effect2_ = - StringKeyframeEffectModel::Create(*keyframe_vector2_); - EXPECT_TRUE( - CanStartEffectOnCompositor(timing_, *keyframe_animation_effect2_)); - keyframe_vector5_->at(0)->SetEasing(step_timing_function_.get()); keyframe_vector5_->at(1)->SetEasing(linear_timing_function_.get()); keyframe_vector5_->at(2)->SetEasing(cubic_ease_timing_function_.get()); - keyframe_vector5_->at(3)->SetEasing(frames_timing_function_.get()); keyframe_animation_effect5_ = StringKeyframeEffectModel::Create(*keyframe_vector5_); EXPECT_TRUE( CanStartEffectOnCompositor(timing_, *keyframe_animation_effect5_)); - keyframe_vector5_->at(0)->SetEasing(frames_timing_function_.get()); keyframe_vector5_->at(1)->SetEasing(step_timing_function_.get()); keyframe_vector5_->at(2)->SetEasing(cubic_ease_timing_function_.get()); keyframe_vector5_->at(3)->SetEasing(linear_timing_function_.get()); @@ -1212,7 +1193,6 @@ CanStartEffectOnCompositor(timing_, *keyframe_animation_effect5_)); keyframe_vector5_->at(0)->SetEasing(linear_timing_function_.get()); - keyframe_vector5_->at(1)->SetEasing(frames_timing_function_.get()); keyframe_vector5_->at(2)->SetEasing(cubic_ease_timing_function_.get()); keyframe_vector5_->at(3)->SetEasing(step_timing_function_.get()); keyframe_animation_effect5_ =
diff --git a/third_party/blink/renderer/core/animation/timing_input_test.cc b/third_party/blink/renderer/core/animation/timing_input_test.cc index 40695b5..0b2487d 100644 --- a/third_party/blink/renderer/core/animation/timing_input_test.cc +++ b/third_party/blink/renderer/core/animation/timing_input_test.cc
@@ -401,11 +401,6 @@ success) .timing_function); EXPECT_TRUE(success); - EXPECT_EQ(*FramesTimingFunction::Create(5), - *ApplyTimingInputString(scope.GetIsolate(), "easing", "frames(5)", - success) - .timing_function); - EXPECT_TRUE(success); ApplyTimingInputString(scope.GetIsolate(), "easing", "", success); EXPECT_FALSE(success); @@ -415,11 +410,6 @@ ApplyTimingInputString(scope.GetIsolate(), "easing", "cubic-bezier(2, 2, 0.3, 0.3)", success); EXPECT_FALSE(success); - ApplyTimingInputString(scope.GetIsolate(), "easing", "frames(1)", success); - EXPECT_FALSE(success); - ApplyTimingInputString(scope.GetIsolate(), "easing", "frames(3, start)", - success); - EXPECT_FALSE(success); ApplyTimingInputString(scope.GetIsolate(), "easing", "rubbish", success); EXPECT_FALSE(success); ApplyTimingInputNumber(scope.GetIsolate(), "easing", 2, success);
diff --git a/third_party/blink/renderer/core/css/css_timing_function_value.cc b/third_party/blink/renderer/core/css/css_timing_function_value.cc index 09afdef..c58c4101 100644 --- a/third_party/blink/renderer/core/css/css_timing_function_value.cc +++ b/third_party/blink/renderer/core/css/css_timing_function_value.cc
@@ -59,14 +59,5 @@ return steps_ == other.steps_ && step_position_ == other.step_position_; } -String CSSFramesTimingFunctionValue::CustomCSSText() const { - return "frames(" + String::Number(frames_) + ")"; -} - -bool CSSFramesTimingFunctionValue::Equals( - const CSSFramesTimingFunctionValue& other) const { - return frames_ == other.frames_; -} - } // namespace cssvalue } // namespace blink
diff --git a/third_party/blink/renderer/core/css/css_timing_function_value.h b/third_party/blink/renderer/core/css/css_timing_function_value.h index f8682a3..5cab5ad 100644 --- a/third_party/blink/renderer/core/css/css_timing_function_value.h +++ b/third_party/blink/renderer/core/css/css_timing_function_value.h
@@ -97,31 +97,6 @@ StepsTimingFunction::StepPosition step_position_; }; -class CSSFramesTimingFunctionValue : public CSSValue { - public: - static CSSFramesTimingFunctionValue* Create(int frames) { - return MakeGarbageCollected<CSSFramesTimingFunctionValue>(frames); - } - - CSSFramesTimingFunctionValue(int frames) - : CSSValue(kFramesTimingFunctionClass), frames_(frames) { - DCHECK(RuntimeEnabledFeatures::FramesTimingFunctionEnabled()); - } - - int NumberOfFrames() const { return frames_; } - - String CustomCSSText() const; - - bool Equals(const CSSFramesTimingFunctionValue&) const; - - void TraceAfterDispatch(blink::Visitor* visitor) { - CSSValue::TraceAfterDispatch(visitor); - } - - private: - int frames_; -}; - } // namespace cssvalue template <> @@ -138,13 +113,6 @@ } }; -template <> -struct DowncastTraits<cssvalue::CSSFramesTimingFunctionValue> { - static bool AllowFrom(const CSSValue& value) { - return value.IsFramesTimingFunctionValue(); - } -}; - } // namespace blink #endif
diff --git a/third_party/blink/renderer/core/css/css_value.cc b/third_party/blink/renderer/core/css/css_value.cc index 5c57d38..9e9eeaa 100644 --- a/third_party/blink/renderer/core/css/css_value.cc +++ b/third_party/blink/renderer/core/css/css_value.cc
@@ -230,8 +230,6 @@ other); case kStepsTimingFunctionClass: return CompareCSSValues<CSSStepsTimingFunctionValue>(*this, other); - case kFramesTimingFunctionClass: - return CompareCSSValues<CSSFramesTimingFunctionValue>(*this, other); case kUnicodeRangeClass: return CompareCSSValues<CSSUnicodeRangeValue>(*this, other); case kURIClass: @@ -339,8 +337,6 @@ return To<CSSCubicBezierTimingFunctionValue>(this)->CustomCSSText(); case kStepsTimingFunctionClass: return To<CSSStepsTimingFunctionValue>(this)->CustomCSSText(); - case kFramesTimingFunctionClass: - return To<CSSFramesTimingFunctionValue>(this)->CustomCSSText(); case kUnicodeRangeClass: return To<CSSUnicodeRangeValue>(this)->CustomCSSText(); case kURIClass: @@ -486,9 +482,6 @@ case kStepsTimingFunctionClass: To<CSSStepsTimingFunctionValue>(this)->~CSSStepsTimingFunctionValue(); return; - case kFramesTimingFunctionClass: - To<CSSFramesTimingFunctionValue>(this)->~CSSFramesTimingFunctionValue(); - return; case kUnicodeRangeClass: To<CSSUnicodeRangeValue>(this)->~CSSUnicodeRangeValue(); return; @@ -642,9 +635,6 @@ case kStepsTimingFunctionClass: To<CSSStepsTimingFunctionValue>(this)->TraceAfterDispatch(visitor); return; - case kFramesTimingFunctionClass: - To<CSSFramesTimingFunctionValue>(this)->TraceAfterDispatch(visitor); - return; case kUnicodeRangeClass: To<CSSUnicodeRangeValue>(this)->TraceAfterDispatch(visitor); return;
diff --git a/third_party/blink/renderer/core/css/css_value.h b/third_party/blink/renderer/core/css/css_value.h index 855c2239..e31ff18 100644 --- a/third_party/blink/renderer/core/css/css_value.h +++ b/third_party/blink/renderer/core/css/css_value.h
@@ -136,9 +136,6 @@ bool IsStepsTimingFunctionValue() const { return class_type_ == kStepsTimingFunctionClass; } - bool IsFramesTimingFunctionValue() const { - return class_type_ == kFramesTimingFunctionClass; - } bool IsGridTemplateAreasValue() const { return class_type_ == kGridTemplateAreasClass; } @@ -216,7 +213,6 @@ // Timing function classes. kCubicBezierTimingFunctionClass, kStepsTimingFunctionClass, - kFramesTimingFunctionClass, // Other class types. kBorderImageSliceClass,
diff --git a/third_party/blink/renderer/core/css/properties/computed_style_utils.cc b/third_party/blink/renderer/core/css/properties/computed_style_utils.cc index eeb8310d..a2465f6 100644 --- a/third_party/blink/renderer/core/css/properties/computed_style_utils.cc +++ b/third_party/blink/renderer/core/css/properties/computed_style_utils.cc
@@ -1541,13 +1541,6 @@ return CSSIdentifierValue::Create(value_id); } - case TimingFunction::Type::FRAMES: { - const FramesTimingFunction* frames_timing_function = - ToFramesTimingFunction(timing_function); - int frames = frames_timing_function->NumberOfFrames(); - return CSSFramesTimingFunctionValue::Create(frames); - } - default: return CSSIdentifierValue::Create(CSSValueID::kLinear); }
diff --git a/third_party/blink/renderer/core/css/properties/css_parsing_utils.cc b/third_party/blink/renderer/core/css/properties/css_parsing_utils.cc index 63e64d0..8e66782 100644 --- a/third_party/blink/renderer/core/css/properties/css_parsing_utils.cc +++ b/third_party/blink/renderer/core/css/properties/css_parsing_utils.cc
@@ -152,28 +152,6 @@ return CSSStepsTimingFunctionValue::Create(steps->GetIntValue(), position); } -CSSValue* ConsumeFrames(CSSParserTokenRange& range) { - DCHECK_EQ(range.Peek().FunctionId(), CSSValueID::kFrames); - CSSParserTokenRange range_copy = range; - CSSParserTokenRange args = - css_property_parser_helpers::ConsumeFunction(range_copy); - - CSSPrimitiveValue* frames = - css_property_parser_helpers::ConsumePositiveInteger(args); - if (!frames) - return nullptr; - - int frames_int = frames->GetIntValue(); - if (frames_int <= 1) - return nullptr; - - if (!args.AtEnd()) - return nullptr; - - range = range_copy; - return CSSFramesTimingFunctionValue::Create(frames_int); -} - CSSValue* ConsumeCubicBezier(CSSParserTokenRange& range) { DCHECK_EQ(range.Peek().FunctionId(), CSSValueID::kCubicBezier); CSSParserTokenRange range_copy = range; @@ -553,10 +531,6 @@ CSSValueID function = range.Peek().FunctionId(); if (function == CSSValueID::kSteps) return ConsumeSteps(range); - if (RuntimeEnabledFeatures::FramesTimingFunctionEnabled() && - function == CSSValueID::kFrames) { - return ConsumeFrames(range); - } if (function == CSSValueID::kCubicBezier) return ConsumeCubicBezier(range); return nullptr;
diff --git a/third_party/blink/renderer/core/css/resolver/css_to_style_map.cc b/third_party/blink/renderer/core/css/resolver/css_to_style_map.cc index 8507f1e..aadd6656 100644 --- a/third_party/blink/renderer/core/css/resolver/css_to_style_map.cc +++ b/third_party/blink/renderer/core/css/resolver/css_to_style_map.cc
@@ -457,12 +457,6 @@ if (value.IsInitialValue()) return CSSTimingData::InitialTimingFunction(); - if (const auto* frames_timing_function = - DynamicTo<cssvalue::CSSFramesTimingFunctionValue>(value)) { - return FramesTimingFunction::Create( - frames_timing_function->NumberOfFrames()); - } - const auto& steps_timing_function = To<cssvalue::CSSStepsTimingFunctionValue>(value); return StepsTimingFunction::Create(steps_timing_function.NumberOfSteps(),
diff --git a/third_party/blink/renderer/core/editing/visible_position.cc b/third_party/blink/renderer/core/editing/visible_position.cc index 00ff490..ebca803 100644 --- a/third_party/blink/renderer/core/editing/visible_position.cc +++ b/third_party/blink/renderer/core/editing/visible_position.cc
@@ -31,14 +31,13 @@ #include "third_party/blink/renderer/core/dom/document.h" #include "third_party/blink/renderer/core/dom/text.h" #include "third_party/blink/renderer/core/editing/editing_utilities.h" +#include "third_party/blink/renderer/core/editing/local_caret_rect.h" #include "third_party/blink/renderer/core/editing/ng_flat_tree_shorthands.h" #include "third_party/blink/renderer/core/editing/text_affinity.h" #include "third_party/blink/renderer/core/editing/visible_units.h" #include "third_party/blink/renderer/core/html/html_element.h" #include "third_party/blink/renderer/core/html_names.h" #include "third_party/blink/renderer/core/layout/layout_object.h" -#include "third_party/blink/renderer/core/layout/ng/inline/ng_caret_navigator.h" -#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.h" #include "third_party/blink/renderer/core/layout/ng/inline/ng_offset_mapping.h" #include "third_party/blink/renderer/platform/bindings/exception_state.h" #include "third_party/blink/renderer/platform/geometry/float_quad.h" @@ -100,36 +99,10 @@ const PositionWithAffinityTemplate<Strategy> upstream_position( deep_position, TextAffinity::kUpstream); - if (!InSameLine(downstream_position, upstream_position)) + if (AbsoluteCaretBoundsOf(downstream_position) != + AbsoluteCaretBoundsOf(upstream_position)) { return VisiblePositionTemplate<Strategy>(upstream_position); - - if (!NGOffsetMapping::AcceptsPosition(ToPositionInDOMTree(deep_position))) { - // editing/selection/mixed-editability-10.html reaches here. - // We can't check bidi in such case. Use downstream as the default. - // TODO(xiaochengh): Investigate why we reach here and how to work around. - return VisiblePositionTemplate<Strategy>(downstream_position); } - - // Check if the position is at bidi boundary. - const LayoutObject* layout_object = - deep_position.AnchorNode()->GetLayoutObject(); - DCHECK(layout_object) << position_with_affinity; - if (!layout_object->IsInline()) - return VisiblePositionTemplate<Strategy>(downstream_position); - LayoutBlockFlow* const context = - NGOffsetMapping::GetInlineFormattingContextOf(*layout_object); - DCHECK(context); - DCHECK(context->IsLayoutNGMixin()); - - const NGOffsetMapping* mapping = NGInlineNode::GetOffsetMapping(context); - DCHECK(mapping); - - const base::Optional<unsigned> offset = - mapping->GetTextContentOffset(ToPositionInDOMTree(deep_position)); - DCHECK(offset.has_value()); - - if (NGCaretNavigator(*context).OffsetIsBidiBoundary(offset.value())) - return VisiblePositionTemplate<Strategy>(upstream_position); return VisiblePositionTemplate<Strategy>(downstream_position); }
diff --git a/third_party/blink/renderer/core/frame/local_frame_view.cc b/third_party/blink/renderer/core/frame/local_frame_view.cc index aa60dff..5da236b 100644 --- a/third_party/blink/renderer/core/frame/local_frame_view.cc +++ b/third_party/blink/renderer/core/frame/local_frame_view.cc
@@ -2474,7 +2474,6 @@ } }); } - paint_controller_ = nullptr; } } } @@ -2508,18 +2507,6 @@ static void RecordGraphicsLayerAsForeignLayer( GraphicsContext& context, const GraphicsLayer* graphics_layer) { - // Copy the first chunk's safe opaque background color over to the cc::Layer - // in the foreign layer wrapper. - if (graphics_layer->DrawsContent()) { - auto& chunks = - graphics_layer->GetPaintController().GetPaintArtifact().PaintChunks(); - SkColor safe_background_color = SK_ColorWHITE; - if (chunks.size()) { - safe_background_color = chunks[0].safe_opaque_background_color; - } - graphics_layer->CcLayer()->SetSafeOpaqueBackgroundColor( - safe_background_color); - } // TODO(trchen): Currently the GraphicsLayer hierarchy is still built during // CompositingUpdate, and we have to clear them here to ensure no extraneous // layers are still attached. In future we will disable all those layer @@ -2719,6 +2706,13 @@ SCOPED_UMA_AND_UKM_TIMER(EnsureUkmAggregator(), LocalFrameUkmAggregator::kCompositingCommit); + // Skip updating property trees, pushing cc::Layers, and issuing raster + // invalidations if possible. + if (!paint_artifact_compositor_->NeedsUpdate()) { + DCHECK(paint_controller_); + return; + } + PaintArtifactCompositor::ViewportProperties viewport_properties; if (GetFrame().IsMainFrame()) { const auto& viewport = page->GetVisualViewport(); @@ -2731,17 +2725,14 @@ settings.prefer_compositing_to_lcd_text = page->GetSettings().GetPreferCompositingToLCDTextEnabled(); - // Skip updating property trees, pushing cc::Layers, and issuing raster - // invalidations if possible. - if (!paint_artifact_compositor_->NeedsUpdate()) - return; - if (RuntimeEnabledFeatures::BlinkGenPropertyTreesEnabled() && - !RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) { - // BlinkGenPropertyTrees just needs a transient PaintController to - // collect the foreign layers which doesn't need caching. It also - // shouldn't affect caching status of DisplayItemClients because it's - // FinishCycle() is not synchronized with other PaintControllers. + !RuntimeEnabledFeatures::CompositeAfterPaintEnabled() && + !paint_controller_) { + // BlinkGenPropertyTrees just needs a transient PaintController to collect + // the foreign layers which doesn't need caching. It also shouldn't affect + // caching status of DisplayItemClients because it's FinishCycle() is not + // synchronized with other PaintControllers. It may live across frame update + // until GraphicsLayersDidChange() is called. paint_controller_ = std::make_unique<PaintController>(PaintController::kTransient); @@ -4000,12 +3991,22 @@ intersection_observation_state_ = state; } -void LocalFrameView::SetPaintArtifactCompositorNeedsUpdate() const { +void LocalFrameView::SetPaintArtifactCompositorNeedsUpdate() { LocalFrameView* root = GetFrame().LocalFrameRoot().View(); if (root && root->paint_artifact_compositor_) root->paint_artifact_compositor_->SetNeedsUpdate(); } +void LocalFrameView::GraphicsLayersDidChange() { + LocalFrameView* root = GetFrame().LocalFrameRoot().View(); + if (root) { + // We will re-collect GraphicsLayers in PushPaintArtifactsToCompositor(). + root->paint_controller_ = nullptr; + if (root->paint_artifact_compositor_) + root->paint_artifact_compositor_->SetNeedsUpdate(); + } +} + PaintArtifactCompositor* LocalFrameView::GetPaintArtifactCompositor() const { LocalFrameView* root = GetFrame().LocalFrameRoot().View(); return root ? root->paint_artifact_compositor_.get() : nullptr;
diff --git a/third_party/blink/renderer/core/frame/local_frame_view.h b/third_party/blink/renderer/core/frame/local_frame_view.h index 08f8ef8a..9e26748d 100644 --- a/third_party/blink/renderer/core/frame/local_frame_view.h +++ b/third_party/blink/renderer/core/frame/local_frame_view.h
@@ -205,7 +205,8 @@ void ForceUpdateViewportIntersections(); - void SetPaintArtifactCompositorNeedsUpdate() const; + void SetPaintArtifactCompositorNeedsUpdate(); + void GraphicsLayersDidChange(); // Marks this frame, and ancestor frames, as needing a mandatory compositing // update. This overrides throttling for one frame, up to kCompositingClean. @@ -938,7 +939,14 @@ std::unique_ptr<Vector<ObjectPaintInvalidation>> tracked_object_paint_invalidations_; - // For CompositeAfterPaint only. + // For BlinkGenPropertyTrees/CompositeAfterPaint only. It's created lazily + // when it's used. + // - For BlinkGenPropertyTrees, we use it in PushPaintArtifactToCompositor() + // to collect GraphicsLayers as foreign layers. It's transient, but may live + // across frame updates until GraphicsLayersDidChange() is called. + // - For CompositeAfterPaint, we use it in PaintTree() for all paintings of + // the frame tree in PaintTree(). It caches display items and subsequences + // across frame updates and repaints. std::unique_ptr<PaintController> paint_controller_; std::unique_ptr<PaintArtifactCompositor> paint_artifact_compositor_;
diff --git a/third_party/blink/renderer/core/frame/visual_viewport.cc b/third_party/blink/renderer/core/frame/visual_viewport.cc index 4324363..85c3d1e 100644 --- a/third_party/blink/renderer/core/frame/visual_viewport.cc +++ b/third_party/blink/renderer/core/frame/visual_viewport.cc
@@ -1156,9 +1156,9 @@ ScrollableArea::SetScrollbarsHiddenIfOverlay(hidden); } -void VisualViewport::SetPaintArtifactCompositorNeedsUpdate() const { +void VisualViewport::GraphicsLayersDidChange() { if (MainFrame() && MainFrame()->View()) - MainFrame()->View()->SetPaintArtifactCompositorNeedsUpdate(); + MainFrame()->View()->GraphicsLayersDidChange(); } PaintArtifactCompositor* VisualViewport::GetPaintArtifactCompositor() const {
diff --git a/third_party/blink/renderer/core/frame/visual_viewport.h b/third_party/blink/renderer/core/frame/visual_viewport.h index 7f1dc1a1..3b01de3d 100644 --- a/third_party/blink/renderer/core/frame/visual_viewport.h +++ b/third_party/blink/renderer/core/frame/visual_viewport.h
@@ -295,7 +295,7 @@ GraphicsLayerPaintingPhase, const IntRect&) const override; void SetOverlayScrollbarsHidden(bool) override; - void SetPaintArtifactCompositorNeedsUpdate() const override; + void GraphicsLayersDidChange() override; String DebugName(const GraphicsLayer*) const override; const ScrollableArea* GetScrollableAreaForTesting(
diff --git a/third_party/blink/renderer/core/layout/BUILD.gn b/third_party/blink/renderer/core/layout/BUILD.gn index 8ddc952..e218a21 100644 --- a/third_party/blink/renderer/core/layout/BUILD.gn +++ b/third_party/blink/renderer/core/layout/BUILD.gn
@@ -329,8 +329,6 @@ "ng/inline/ng_baseline.h", "ng/inline/ng_bidi_paragraph.cc", "ng/inline/ng_bidi_paragraph.h", - "ng/inline/ng_caret_navigator.cc", - "ng/inline/ng_caret_navigator.h", "ng/inline/ng_caret_position.cc", "ng/inline/ng_caret_position.h", "ng/inline/ng_caret_rect.cc",
diff --git a/third_party/blink/renderer/core/layout/ng/inline/README.md b/third_party/blink/renderer/core/layout/ng/inline/README.md index c604426..a9b42d7c 100644 --- a/third_party/blink/renderer/core/layout/ng/inline/README.md +++ b/third_party/blink/renderer/core/layout/ng/inline/README.md
@@ -309,11 +309,6 @@ content of an inline formatting context (computed in [pre-layout]) and DOM positions in the context. See [design doc](https://goo.gl/CJbxky) for details. -[NGCaretNavigator] provides functions for inspecting bidi levels and visual -ordering of text content, and supports visual left/right caret movements in the -text. See [design doc](http://bit.ly/2QVAwGq) for details. - - [ICU BiDi]: http://userguide.icu-project.org/transforms/bidi [UAX#9 Unicode Bidirectional Algorithm]: http://unicode.org/reports/tr9/ [UAX#9 Resolving Embedding Levels]: http://www.unicode.org/reports/tr9/#Resolving_Embedding_Levels @@ -322,7 +317,6 @@ [FontBaseline]: ../../../platform/fonts/FontBaseline.h [NGBaselineAlgorithmType]: ng_baseline.h [NGBaselineRequest]: ng_baseline.h -[NGCaretNavigator]: ng_caret_navigator.h [NGBidiParagraph]: ng_bidi_paragraph.h [NGBlockNode]: ../ng_block_node.h [NGBoxFragment]: ../ng_box_fragment.h
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_caret_navigator.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_caret_navigator.cc deleted file mode 100644 index 5b2f37f..0000000 --- a/third_party/blink/renderer/core/layout/ng/inline/ng_caret_navigator.cc +++ /dev/null
@@ -1,426 +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. - -#include "third_party/blink/renderer/core/layout/ng/inline/ng_caret_navigator.h" - -#include "third_party/blink/renderer/core/layout/layout_text_fragment.h" -#include "third_party/blink/renderer/core/layout/ng/inline/ng_bidi_paragraph.h" -#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_break_token.h" -#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.h" -#include "third_party/blink/renderer/core/layout/ng/inline/ng_physical_line_box_fragment.h" -#include "third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h" - -namespace blink { - -std::ostream& operator<<(std::ostream& out, - const NGCaretNavigator::Position& position) { - return out << position.index << "/" - << (position.IsBeforeCharacter() ? "BeforeCharacter" - : "AfterCharacter"); -} - -NGCaretNavigator::~NGCaretNavigator() = default; - -NGCaretNavigator::NGCaretNavigator(const LayoutBlockFlow& context) - : context_(context), - disallow_transition_(context.GetDocument().Lifecycle()) { - DCHECK(RuntimeEnabledFeatures::BidiCaretAffinityEnabled()); - DCHECK(context.IsLayoutNGMixin()); - DCHECK(context.ChildrenInline()); - DCHECK(context.GetNGInlineNodeData()); - DCHECK(!context.GetDocument().NeedsLayoutTreeUpdate()); -} - -const NGInlineNodeData& NGCaretNavigator::GetData() const { - return *context_.GetNGInlineNodeData(); -} - -const String& NGCaretNavigator::GetText() const { - return GetData().text_content; -} - -bool NGCaretNavigator::IsBidiEnabled() const { - return GetData().IsBidiEnabled(); -} - -UBiDiLevel NGCaretNavigator::BidiLevelAt(unsigned index) const { - DCHECK_LT(index, GetText().length()); - if (!IsBidiEnabled()) - return 0; - return GetData().FindItemForTextOffset(index).BidiLevel(); -} - -TextDirection NGCaretNavigator::TextDirectionAt(unsigned index) const { - UBiDiLevel level = BidiLevelAt(index); - return DirectionFromLevel(level); -} - -bool NGCaretNavigator::OffsetIsBidiBoundary(unsigned offset) const { - DCHECK_LE(offset, GetText().length()); - if (!IsBidiEnabled()) - return false; - if (!offset || offset == GetText().length()) - return false; - return BidiLevelAt(offset - 1) != BidiLevelAt(offset); -} - -NGCaretNavigator::Position -NGCaretNavigator::CaretPositionFromTextContentOffsetAndAffinity( - unsigned offset, - TextAffinity affinity) const { - DCHECK_LE(offset, GetText().length()); - // Callers sometimes pass in (0, upstream) or (length, downstream), which - // originate from legacy callers. Make sure they are fixed up. - // TODO(xiaochengh): Catch and eliminate such callers. - if (affinity == TextAffinity::kUpstream) { - if (offset) - return {offset - 1, PositionAnchorType::kAfter}; - return {0, PositionAnchorType::kBefore}; - } - - if (offset < GetText().length()) - return {offset, PositionAnchorType::kBefore}; - return {GetText().length() - 1, PositionAnchorType::kAfter}; -} - -// static -NGCaretNavigator::MoveDirection NGCaretNavigator::OppositeDirectionOf( - MoveDirection direction) { - if (direction == MoveDirection::kTowardsLeft) - return MoveDirection::kTowardsRight; - return MoveDirection::kTowardsLeft; -} - -// static -bool NGCaretNavigator::TowardsSameDirection(MoveDirection move_direction, - TextDirection text_direction) { - if (IsLtr(text_direction)) - return move_direction == MoveDirection::kTowardsRight; - return move_direction == MoveDirection::kTowardsLeft; -} - -NGCaretNavigator::Line NGCaretNavigator::ContainingLineOf( - unsigned index) const { - DCHECK_LT(index, GetText().length()); - // TODO(xiaochengh): Make it work for multi-col - DCHECK(context_.CurrentFragment()); - unsigned last_line_end = 0; - for (const auto child : context_.CurrentFragment()->Children()) { - if (!child->IsLineBox()) - continue; - const auto* line = To<NGPhysicalLineBoxFragment>(child.get()); - const auto* token = To<NGInlineBreakToken>(line->BreakToken()); - const unsigned line_end = - token->IsFinished() ? GetText().length() : token->TextOffset(); - if (line_end > index) - return {last_line_end, line_end, line->BaseDirection()}; - last_line_end = line_end; - } - NOTREACHED(); - return {}; -} - -bool NGCaretNavigator::IsValidCaretPosition(const Position& position) const { - unsigned index = position.index; - if (position.IsAfterCharacter() && IsLineBreak(index)) - return false; - if (IsCollapsedSpaceByLineWrap(index)) - return false; - if (IsIgnoredInCaretMovement(index)) - return false; - return true; -} - -bool NGCaretNavigator::IsCollapsibleWhitespace(unsigned index) const { - DCHECK_LT(index, GetText().length()); - if (GetText()[index] != kSpaceCharacter) - return false; - const NGInlineItem& item = GetData().FindItemForTextOffset(index); - return item.Style()->CollapseWhiteSpace(); -} - -bool NGCaretNavigator::IsLineBreak(unsigned index) const { - DCHECK_LT(index, GetText().length()); - return GetText()[index] == kNewlineCharacter; -} - -bool NGCaretNavigator::IsCollapsedSpaceByLineWrap(unsigned index) const { - DCHECK_LT(index, GetText().length()); - if (!IsCollapsibleWhitespace(index)) - return false; - return index + 1 == ContainingLineOf(index).end_offset; -} - -bool NGCaretNavigator::IsIgnoredInCaretMovement(unsigned index) const { - DCHECK_LT(index, GetText().length()); - const NGInlineItem& item = GetData().FindItemForTextOffset(index); - - // Caret navigation works on text, atomic inlines and non-ZWS controls only. - switch (item.Type()) { - case NGInlineItem::kText: - case NGInlineItem::kAtomicInline: - break; - case NGInlineItem::kControl: - if (GetText()[index] == kZeroWidthSpaceCharacter) - return true; - break; - default: - return true; - } - - // Ignore CSS generate contents. - // TODO(xiaochengh): This might be general enough to be merged into - // |NGInlineItem| as a member function. - DCHECK(item.GetLayoutObject()); - const LayoutObject* object = item.GetLayoutObject(); - if (const auto* text_fragment = ToLayoutTextFragmentOrNull(object)) { - // ::first-letter |LayoutTextFragment| returns null for |GetNode()|. Check - // |AssociatedTextNode()| to see if it's created by a text node. - if (!text_fragment->AssociatedTextNode()) - return true; - } else { - if (!object->NonPseudoNode()) - return true; - } - - // Ignore collapsed whitespaces that not visually at line end due to bidi. - // Caret movement should move over them as if they don't exist to match the - // existing behavior. - return IsCollapsedSpaceByLineWrap(index) && - index != VisualLastCharacterOf(ContainingLineOf(index)); -} - -bool NGCaretNavigator::IsEnterableChildContext(unsigned index) const { - DCHECK_LT(index, GetText().length()); - if (GetText()[index] != kObjectReplacementCharacter) - return false; - - const NGInlineItem& item = GetData().FindItemForTextOffset(index); - if (item.Type() != NGInlineItem::kAtomicInline) - return false; - DCHECK(item.GetLayoutObject()); - const LayoutObject* object = item.GetLayoutObject(); - if (!object->IsLayoutBlockFlow()) - return false; - if (!object->NonPseudoNode() || !object->GetNode()->IsElementNode()) - return false; - const Element* node = ToElement(object->GetNode()); - return !node->GetShadowRoot() || !node->GetShadowRoot()->IsUserAgent(); -} - -NGCaretNavigator::Position NGCaretNavigator::LeftEdgeOf(unsigned index) const { - return EdgeOfInternal(index, MoveDirection::kTowardsLeft); -} - -NGCaretNavigator::Position NGCaretNavigator::RightEdgeOf(unsigned index) const { - return EdgeOfInternal(index, MoveDirection::kTowardsRight); -} - -NGCaretNavigator::Position NGCaretNavigator::EdgeOfInternal( - unsigned index, - MoveDirection edge_direction) const { - DCHECK_LT(index, GetText().length()); - const TextDirection character_direction = TextDirectionAt(index); - return {index, TowardsSameDirection(edge_direction, character_direction) - ? PositionAnchorType::kAfter - : PositionAnchorType::kBefore}; -} - -NGCaretNavigator::VisualCharacterMovementResult -NGCaretNavigator::LeftCharacterOf(unsigned index) const { - return MoveCharacterInternal(index, MoveDirection::kTowardsLeft); -} - -NGCaretNavigator::VisualCharacterMovementResult -NGCaretNavigator::RightCharacterOf(unsigned index) const { - return MoveCharacterInternal(index, MoveDirection::kTowardsRight); -} - -Vector<int32_t, 32> NGCaretNavigator::CharacterIndicesInVisualOrder( - const Line& line) const { - DCHECK(IsBidiEnabled()); - - Vector<UBiDiLevel, 32> levels; - levels.ReserveCapacity(line.end_offset - line.start_offset); - for (unsigned i = line.start_offset; i < line.end_offset; ++i) - levels.push_back(BidiLevelAt(i)); - - Vector<int32_t, 32> indices(levels.size()); - NGBidiParagraph::IndicesInVisualOrder(levels, &indices); - - for (auto& index : indices) - index += line.start_offset; - return indices; -} - -unsigned NGCaretNavigator::VisualMostForwardCharacterOf( - const Line& line, - MoveDirection direction) const { - if (!IsBidiEnabled()) { - if (direction == MoveDirection::kTowardsLeft) - return line.start_offset; - return line.end_offset - 1; - } - - const auto indices_in_visual_order = CharacterIndicesInVisualOrder(line); - if (direction == MoveDirection::kTowardsLeft) - return indices_in_visual_order.front(); - return indices_in_visual_order.back(); -} - -unsigned NGCaretNavigator::VisualFirstCharacterOf(const Line& line) const { - return VisualMostForwardCharacterOf(line, IsLtr(line.base_direction) - ? MoveDirection::kTowardsLeft - : MoveDirection::kTowardsRight); -} - -unsigned NGCaretNavigator::VisualLastCharacterOf(const Line& line) const { - return VisualMostForwardCharacterOf(line, IsLtr(line.base_direction) - ? MoveDirection::kTowardsRight - : MoveDirection::kTowardsLeft); -} - -NGCaretNavigator::VisualCharacterMovementResult -NGCaretNavigator::MoveCharacterInternal(unsigned index, - MoveDirection move_direction) const { - const Line line = ContainingLineOf(index); - - if (index == VisualMostForwardCharacterOf(line, move_direction)) { - if (TowardsSameDirection(move_direction, line.base_direction)) { - if (line.end_offset == GetText().length()) - return {VisualMovementResultType::kAfterContext, base::nullopt}; - const Line next_line = ContainingLineOf(line.end_offset); - return {VisualMovementResultType::kWithinContext, - VisualFirstCharacterOf(next_line)}; - } - - if (!line.start_offset) - return {VisualMovementResultType::kBeforeContext, base::nullopt}; - const Line last_line = ContainingLineOf(line.start_offset - 1); - return {VisualMovementResultType::kWithinContext, - VisualLastCharacterOf(last_line)}; - } - - if (!IsBidiEnabled()) { - if (move_direction == MoveDirection::kTowardsLeft) - return {VisualMovementResultType::kWithinContext, index - 1}; - return {VisualMovementResultType::kWithinContext, index + 1}; - } - - Vector<int32_t, 32> indices_in_visual_order = - CharacterIndicesInVisualOrder(line); - const int32_t* visual_location = std::find( - indices_in_visual_order.begin(), indices_in_visual_order.end(), index); - DCHECK_NE(visual_location, indices_in_visual_order.end()); - if (move_direction == MoveDirection::kTowardsLeft) { - DCHECK_NE(visual_location, indices_in_visual_order.begin()); - return {VisualMovementResultType::kWithinContext, - *std::prev(visual_location)}; - } - DCHECK_NE(std::next(visual_location), indices_in_visual_order.end()); - return {VisualMovementResultType::kWithinContext, - *std::next(visual_location)}; -} - -NGCaretNavigator::VisualCaretMovementResult NGCaretNavigator::LeftPositionOf( - const Position& caret_position) const { - return MoveCaretInternal(caret_position, MoveDirection::kTowardsLeft); -} - -NGCaretNavigator::VisualCaretMovementResult NGCaretNavigator::RightPositionOf( - const Position& caret_position) const { - return MoveCaretInternal(caret_position, MoveDirection::kTowardsRight); -} - -NGCaretNavigator::UnvalidatedVisualCaretMovementResult -NGCaretNavigator::MoveCaretWithoutValidation( - const Position& caret_position, - MoveDirection move_direction) const { - const unsigned index = caret_position.index; - const MoveDirection opposite_direction = OppositeDirectionOf(move_direction); - if (caret_position == EdgeOfInternal(index, opposite_direction)) { - // TODO(xiaochengh): Consider grapheme cluster - return {VisualMovementResultType::kWithinContext, - EdgeOfInternal(index, move_direction), - !IsIgnoredInCaretMovement(index)}; - } - - VisualCharacterMovementResult forward_character = - MoveCharacterInternal(index, move_direction); - if (!forward_character.IsWithinContext()) - return {forward_character.type}; - - DCHECK(forward_character.index.has_value()); - const Position forward_caret = - EdgeOfInternal(*forward_character.index, opposite_direction); - return {VisualMovementResultType::kWithinContext, forward_caret}; -} - -NGCaretNavigator::VisualCaretMovementResult NGCaretNavigator::MoveCaretInternal( - const Position& caret_position, - MoveDirection move_direction) const { - bool has_passed_character = false; - base::Optional<Position> last_position; - for (Position runner = caret_position; - !has_passed_character || !IsValidCaretPosition(runner);) { - const UnvalidatedVisualCaretMovementResult next = - MoveCaretWithoutValidation(runner, move_direction); - if (next.type != VisualMovementResultType::kWithinContext) - return {next.type, base::nullopt}; - - if (next.has_passed_character) { - has_passed_character = true; - - const unsigned last_passed_character = next.position->index; - if (IsEnterableChildContext(last_passed_character)) - return {VisualMovementResultType::kEnteredChildContext, runner}; - } - - runner = *next.position; - last_position = runner; - - // TODO(xiaochengh): Handle the case where we reach a different line with a - // different base direction, which occurs with 'unicode-bidi: plain-text'. - } - DCHECK(last_position.has_value()); - return {VisualMovementResultType::kWithinContext, *last_position}; -} - -NGCaretNavigator::Position NGCaretNavigator::LeftmostPositionInFirstLine() - const { - Line first_line = ContainingLineOf(0); - unsigned leftmost_character = - VisualMostForwardCharacterOf(first_line, MoveDirection::kTowardsLeft); - // TODO(xiaochengh): Handle if the caret position is invalid. - return LeftEdgeOf(leftmost_character); -} - -NGCaretNavigator::Position NGCaretNavigator::RightmostPositionInFirstLine() - const { - Line first_line = ContainingLineOf(0); - unsigned rightmost_character = - VisualMostForwardCharacterOf(first_line, MoveDirection::kTowardsRight); - // TODO(xiaochengh): Handle if the caret position is invalid. - return RightEdgeOf(rightmost_character); -} - -NGCaretNavigator::Position NGCaretNavigator::LeftmostPositionInLastLine() - const { - Line last_line = ContainingLineOf(GetText().length() - 1); - unsigned leftmost_character = - VisualMostForwardCharacterOf(last_line, MoveDirection::kTowardsLeft); - // TODO(xiaochengh): Handle if the caret position is invalid. - return LeftEdgeOf(leftmost_character); -} - -NGCaretNavigator::Position NGCaretNavigator::RightmostPositionInLastLine() - const { - Line last_line = ContainingLineOf(GetText().length() - 1); - unsigned rightmost_character = - VisualMostForwardCharacterOf(last_line, MoveDirection::kTowardsRight); - // TODO(xiaochengh): Handle if the caret position is invalid. - return RightEdgeOf(rightmost_character); -} - -} // namespace blink
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_caret_navigator.h b/third_party/blink/renderer/core/layout/ng/inline/ng_caret_navigator.h deleted file mode 100644 index 6c60d7f..0000000 --- a/third_party/blink/renderer/core/layout/ng/inline/ng_caret_navigator.h +++ /dev/null
@@ -1,215 +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 THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_NG_CARET_NAVIGATOR_H_ -#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_NG_CARET_NAVIGATOR_H_ - -#include "base/optional.h" -#include "third_party/blink/renderer/core/core_export.h" -#include "third_party/blink/renderer/core/dom/document_lifecycle.h" -#include "third_party/blink/renderer/core/editing/text_affinity.h" -#include "third_party/blink/renderer/platform/text/text_direction.h" -#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" -#include "third_party/blink/renderer/platform/wtf/vector.h" - -#include <unicode/ubidi.h> - -namespace blink { - -class LayoutBlockFlow; -struct NGInlineNodeData; - -// Hosts the |text_content| of an inline formatting context and provides -// bidi-related utilities, including checking bidi levels, computing visual -// left/right characters and visual left/right caret movements. -// Design doc: http://bit.ly/2QVAwGq -class CORE_EXPORT NGCaretNavigator { - STACK_ALLOCATED(); - - public: - explicit NGCaretNavigator(const LayoutBlockFlow&); - ~NGCaretNavigator(); - - const String& GetText() const; - bool IsBidiEnabled() const; - - // Abstraction of a caret position in |text_|. - enum class PositionAnchorType { kBefore, kAfter }; - struct Position { - // |index| is character index the |text_| string. - unsigned index; - PositionAnchorType type; - - bool IsBeforeCharacter() const { - return type == PositionAnchorType::kBefore; - } - - bool IsAfterCharacter() const { return type == PositionAnchorType::kAfter; } - - bool operator==(const Position& other) const { - return index == other.index && type == other.type; - } - }; - - // Returns the bidi level or resolved direction of the character at the given - // logical |index|. - UBiDiLevel BidiLevelAt(unsigned index) const; - TextDirection TextDirectionAt(unsigned index) const; - - // Returns true if the characters at indexes |offset - 1| and |offset| both - // exist and are at different bidi levels. - bool OffsetIsBidiBoundary(unsigned offset) const; - - // Converts an (offset, affinity) pair into a |Position| type of this class. - // Intiontionally long name to indicate the hackiness for handling legacy - // callers. - Position CaretPositionFromTextContentOffsetAndAffinity( - unsigned offset, - TextAffinity affinity) const; - - // Returns the visual left/right edge caret position of the character at the - // given logical |index|. - Position LeftEdgeOf(unsigned index) const; - Position RightEdgeOf(unsigned index) const; - - // Left/right visual movements - // TODO(xiaochengh): Handle the following - // - Grapheme clusters - - enum class VisualMovementResultType { - kWithinContext, - kBeforeContext, - kAfterContext, - kEnteredChildContext - }; - - // Given the character at the logical |index|, returns the logical index of - // the character at its left/right side. - struct VisualCharacterMovementResult { - bool IsWithinContext() const { - return type == VisualMovementResultType::kWithinContext; - } - bool IsBeforeContext() const { - return type == VisualMovementResultType::kBeforeContext; - } - bool IsAfterContext() const { - return type == VisualMovementResultType::kAfterContext; - } - - VisualMovementResultType type; - base::Optional<unsigned> index; - }; - VisualCharacterMovementResult LeftCharacterOf(unsigned index) const; - VisualCharacterMovementResult RightCharacterOf(unsigned index) const; - - // Given a caret position, moves it left/right by one grapheme cluster and - // returns the result. - // Note: If we end up entering an inline block, the result |Position| is - // either before or after the inline block, depending on from which side the - // inline block is entered. For example: - // RightPositionOf(abc|<inline-block>def</inline-block>ghi) - // -> {inline-block, PositionAnchorType::kBefore} - // LeftPositionOf(abc<inline-block>def</inline-block>|ghi) - // -> {inline-block, PositionAnchorType::kAfter} - struct VisualCaretMovementResult { - bool IsWithinContext() const { - return type == VisualMovementResultType::kWithinContext; - } - bool IsBeforeContext() const { - return type == VisualMovementResultType::kBeforeContext; - } - bool IsAfterContext() const { - return type == VisualMovementResultType::kAfterContext; - } - bool HasEnteredChildContext() const { - return type == VisualMovementResultType::kEnteredChildContext; - } - - VisualMovementResultType type; - base::Optional<Position> position; - }; - VisualCaretMovementResult LeftPositionOf(const Position&) const; - VisualCaretMovementResult RightPositionOf(const Position&) const; - - // TODO(xiaochengh): Specify and implement the behavior in edge cases, e.g., - // when the leftmost character of the first line is CSS-generated. - Position LeftmostPositionInFirstLine() const; - Position RightmostPositionInFirstLine() const; - Position LeftmostPositionInLastLine() const; - Position RightmostPositionInLastLine() const; - - private: - // A caret position is invalid if it is: - // - kAfter to a line break character. - // - Anchored to a collapsible space that's removed by line wrap. - // - Anchored to a character that's ignored in caret movement. - bool IsValidCaretPosition(const Position&) const; - bool IsLineBreak(unsigned index) const; - bool IsCollapsibleWhitespace(unsigned index) const; - bool IsCollapsedSpaceByLineWrap(unsigned index) const; - bool IsIgnoredInCaretMovement(unsigned index) const; - - // Returns true if the character at |index| represents a child block - // formatting context that can be entered by caret navigation. Such contexts - // must be atomic inlines (inline block, inline table, ...) and must not host - // user agent shadow tree (which excludes, e.g., <input> and image alt text). - bool IsEnterableChildContext(unsigned index) const; - - enum class MoveDirection { kTowardsLeft, kTowardsRight }; - static MoveDirection OppositeDirectionOf(MoveDirection); - static bool TowardsSameDirection(MoveDirection, TextDirection); - - // ------ Line-related functions ------ - - // A line contains a consecutive substring of |GetText()|. The lines should - // not overlap, and should together cover the entire |GetText()|. - struct Line { - unsigned start_offset; - unsigned end_offset; - TextDirection base_direction; - }; - Line ContainingLineOf(unsigned index) const; - Vector<int32_t, 32> CharacterIndicesInVisualOrder(const Line&) const; - unsigned VisualMostForwardCharacterOf(const Line&, - MoveDirection direction) const; - unsigned VisualLastCharacterOf(const Line&) const; - unsigned VisualFirstCharacterOf(const Line&) const; - - // ------ Implementation of public visual movement functions ------ - - Position EdgeOfInternal(unsigned index, MoveDirection) const; - VisualCharacterMovementResult MoveCharacterInternal(unsigned index, - MoveDirection) const; - VisualCaretMovementResult MoveCaretInternal(const Position&, - MoveDirection) const; - - // Performs a "minimal" caret movement to the left/right without validating - // the result. The result might be invalid due to, e.g., anchored to an - // unallowed character, being visually the same as the input, etc. It's a - // subroutine of |MoveCaretInternal|, who keeps calling it until both of the - // folliwng are satisfied: - // - We've reached a valid caret position. - // - During the process, the caret has moved passing a character on which - // |IsIgnoredInCaretMovement| is false (indicated by |has_passed_character|). - struct UnvalidatedVisualCaretMovementResult { - VisualMovementResultType type; - base::Optional<Position> position; - bool has_passed_character = false; - }; - UnvalidatedVisualCaretMovementResult MoveCaretWithoutValidation( - const Position&, - MoveDirection) const; - - const NGInlineNodeData& GetData() const; - - const LayoutBlockFlow& context_; - DocumentLifecycle::DisallowTransitionScope disallow_transition_; -}; - -CORE_EXPORT std::ostream& operator<<(std::ostream&, - const NGCaretNavigator::Position&); - -} // namespace blink - -#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_NG_CARET_NAVIGATOR_H_
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_caret_navigator_test.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_caret_navigator_test.cc deleted file mode 100644 index 70c99450..0000000 --- a/third_party/blink/renderer/core/layout/ng/inline/ng_caret_navigator_test.cc +++ /dev/null
@@ -1,461 +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. - -#include "third_party/blink/renderer/core/layout/ng/inline/ng_caret_navigator.h" - -#include "third_party/blink/renderer/core/layout/ng/layout_ng_block_flow.h" -#include "third_party/blink/renderer/core/layout/ng/ng_layout_test.h" -#include "third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h" - -namespace blink { - -class NGCaretNavigatorTest : public RenderingTest, - private ScopedBidiCaretAffinityForTest { - public: - NGCaretNavigatorTest() : ScopedBidiCaretAffinityForTest(true) {} - - void SetupHtml(const char* id, String html) { - SetBodyInnerHTML(html); - - block_flow_ = To<LayoutBlockFlow>(GetLayoutObjectByElementId(id)); - DCHECK(block_flow_); - DCHECK(block_flow_->IsLayoutNGMixin()); - DCHECK(block_flow_->ChildrenInline()); - } - - UBiDiLevel BidiLevelAt(unsigned index) const { - return NGCaretNavigator(*block_flow_).BidiLevelAt(index); - } - - NGCaretNavigator::VisualCharacterMovementResult LeftCharacterOf( - unsigned index) const { - return NGCaretNavigator(*block_flow_).LeftCharacterOf(index); - } - - NGCaretNavigator::VisualCharacterMovementResult RightCharacterOf( - unsigned index) const { - return NGCaretNavigator(*block_flow_).RightCharacterOf(index); - } - - NGCaretNavigator::Position CaretBefore(unsigned index) const { - return {index, NGCaretNavigator::PositionAnchorType::kBefore}; - } - - NGCaretNavigator::Position CaretAfter(unsigned index) const { - return {index, NGCaretNavigator::PositionAnchorType::kAfter}; - } - - NGCaretNavigator::VisualCaretMovementResult LeftPositionOf( - const NGCaretNavigator::Position& position) const { - return NGCaretNavigator(*block_flow_).LeftPositionOf(position); - } - - NGCaretNavigator::VisualCaretMovementResult RightPositionOf( - const NGCaretNavigator::Position& position) const { - return NGCaretNavigator(*block_flow_).RightPositionOf(position); - } - - protected: - const LayoutBlockFlow* block_flow_; -}; - -TEST_F(NGCaretNavigatorTest, BidiLevelAtBasic) { - SetupHtml("container", - "<div id=container>abcאבג123</div>"); - - EXPECT_EQ(0u, BidiLevelAt(0)); - EXPECT_EQ(0u, BidiLevelAt(1)); - EXPECT_EQ(0u, BidiLevelAt(2)); - EXPECT_EQ(1u, BidiLevelAt(3)); - EXPECT_EQ(1u, BidiLevelAt(4)); - EXPECT_EQ(1u, BidiLevelAt(5)); - EXPECT_EQ(2u, BidiLevelAt(6)); - EXPECT_EQ(2u, BidiLevelAt(7)); - EXPECT_EQ(2u, BidiLevelAt(8)); -} - -TEST_F(NGCaretNavigatorTest, LeftCharacterOfBasic) { - SetupHtml("container", - "<div id=container>abcאבג123</div>"); - - EXPECT_TRUE(LeftCharacterOf(0).IsBeforeContext()); - - EXPECT_TRUE(LeftCharacterOf(1).IsWithinContext()); - EXPECT_EQ(0u, *LeftCharacterOf(1).index); - - EXPECT_TRUE(LeftCharacterOf(2).IsWithinContext()); - EXPECT_EQ(1u, *LeftCharacterOf(2).index); - - EXPECT_TRUE(LeftCharacterOf(3).IsWithinContext()); - EXPECT_EQ(4u, *LeftCharacterOf(3).index); - - EXPECT_TRUE(LeftCharacterOf(4).IsWithinContext()); - EXPECT_EQ(5u, *LeftCharacterOf(4).index); - - EXPECT_TRUE(LeftCharacterOf(5).IsWithinContext()); - EXPECT_EQ(8u, *LeftCharacterOf(5).index); - - EXPECT_TRUE(LeftCharacterOf(6).IsWithinContext()); - EXPECT_EQ(2u, *LeftCharacterOf(6).index); - - EXPECT_TRUE(LeftCharacterOf(7).IsWithinContext()); - EXPECT_EQ(6u, *LeftCharacterOf(7).index); - - EXPECT_TRUE(LeftCharacterOf(8).IsWithinContext()); - EXPECT_EQ(7u, *LeftCharacterOf(8).index); -} - -TEST_F(NGCaretNavigatorTest, RightCharacterOfBasic) { - SetupHtml("container", - "<div id=container>abcאבג123</div>"); - - EXPECT_TRUE(RightCharacterOf(0).IsWithinContext()); - EXPECT_EQ(1u, *RightCharacterOf(0).index); - - EXPECT_TRUE(RightCharacterOf(1).IsWithinContext()); - EXPECT_EQ(2u, *RightCharacterOf(1).index); - - EXPECT_TRUE(RightCharacterOf(2).IsWithinContext()); - EXPECT_EQ(6u, *RightCharacterOf(2).index); - - EXPECT_TRUE(RightCharacterOf(3).IsAfterContext()); - - EXPECT_TRUE(RightCharacterOf(4).IsWithinContext()); - EXPECT_EQ(3u, *RightCharacterOf(4).index); - - EXPECT_TRUE(RightCharacterOf(5).IsWithinContext()); - EXPECT_EQ(4u, *RightCharacterOf(5).index); - - EXPECT_TRUE(RightCharacterOf(6).IsWithinContext()); - EXPECT_EQ(7u, *RightCharacterOf(6).index); - - EXPECT_TRUE(RightCharacterOf(7).IsWithinContext()); - EXPECT_EQ(8u, *RightCharacterOf(7).index); - - EXPECT_TRUE(RightCharacterOf(8).IsWithinContext()); - EXPECT_EQ(5u, *RightCharacterOf(8).index); -} - -TEST_F(NGCaretNavigatorTest, LeftPositionOfBasic) { - SetupHtml("container", - "<div id=container>abcאבג123</div>"); - - EXPECT_TRUE(LeftPositionOf(CaretBefore(0)).IsBeforeContext()); - - EXPECT_TRUE(LeftPositionOf(CaretAfter(0)).IsWithinContext()); - EXPECT_EQ(CaretBefore(0), *LeftPositionOf(CaretAfter(0)).position); - - EXPECT_TRUE(LeftPositionOf(CaretBefore(1)).IsWithinContext()); - EXPECT_EQ(CaretBefore(0), *LeftPositionOf(CaretBefore(1)).position); - - EXPECT_TRUE(LeftPositionOf(CaretAfter(1)).IsWithinContext()); - EXPECT_EQ(CaretBefore(1), *LeftPositionOf(CaretAfter(1)).position); - - EXPECT_TRUE(LeftPositionOf(CaretBefore(2)).IsWithinContext()); - EXPECT_EQ(CaretBefore(1), *LeftPositionOf(CaretBefore(2)).position); - - EXPECT_TRUE(LeftPositionOf(CaretAfter(2)).IsWithinContext()); - EXPECT_EQ(CaretBefore(2), *LeftPositionOf(CaretAfter(2)).position); - - EXPECT_TRUE(LeftPositionOf(CaretBefore(3)).IsWithinContext()); - EXPECT_EQ(CaretAfter(3), *LeftPositionOf(CaretBefore(3)).position); - - EXPECT_TRUE(LeftPositionOf(CaretAfter(3)).IsWithinContext()); - EXPECT_EQ(CaretAfter(4), *LeftPositionOf(CaretAfter(3)).position); - - EXPECT_TRUE(LeftPositionOf(CaretBefore(4)).IsWithinContext()); - EXPECT_EQ(CaretAfter(4), *LeftPositionOf(CaretBefore(4)).position); - - EXPECT_TRUE(LeftPositionOf(CaretAfter(4)).IsWithinContext()); - EXPECT_EQ(CaretAfter(5), *LeftPositionOf(CaretAfter(4)).position); - - EXPECT_TRUE(LeftPositionOf(CaretBefore(5)).IsWithinContext()); - EXPECT_EQ(CaretAfter(5), *LeftPositionOf(CaretBefore(5)).position); - - EXPECT_TRUE(LeftPositionOf(CaretAfter(5)).IsWithinContext()); - EXPECT_EQ(CaretBefore(8), *LeftPositionOf(CaretAfter(5)).position); - - EXPECT_TRUE(LeftPositionOf(CaretBefore(6)).IsWithinContext()); - EXPECT_EQ(CaretBefore(2), *LeftPositionOf(CaretBefore(6)).position); - - EXPECT_TRUE(LeftPositionOf(CaretAfter(6)).IsWithinContext()); - EXPECT_EQ(CaretBefore(6), *LeftPositionOf(CaretAfter(6)).position); - - EXPECT_TRUE(LeftPositionOf(CaretBefore(7)).IsWithinContext()); - EXPECT_EQ(CaretBefore(6), *LeftPositionOf(CaretBefore(7)).position); - - EXPECT_TRUE(LeftPositionOf(CaretAfter(7)).IsWithinContext()); - EXPECT_EQ(CaretBefore(7), *LeftPositionOf(CaretAfter(7)).position); - - EXPECT_TRUE(LeftPositionOf(CaretBefore(8)).IsWithinContext()); - EXPECT_EQ(CaretBefore(7), *LeftPositionOf(CaretBefore(8)).position); - - EXPECT_TRUE(LeftPositionOf(CaretAfter(8)).IsWithinContext()); - EXPECT_EQ(CaretBefore(8), *LeftPositionOf(CaretAfter(8)).position); -} - -TEST_F(NGCaretNavigatorTest, RightPositionOfBasic) { - SetupHtml("container", - "<div id=container>abcאבג123</div>"); - - EXPECT_TRUE(RightPositionOf(CaretBefore(0)).IsWithinContext()); - EXPECT_EQ(CaretAfter(0), *RightPositionOf(CaretBefore(0)).position); - - EXPECT_TRUE(RightPositionOf(CaretAfter(0)).IsWithinContext()); - EXPECT_EQ(CaretAfter(1), *RightPositionOf(CaretAfter(0)).position); - - EXPECT_TRUE(RightPositionOf(CaretBefore(1)).IsWithinContext()); - EXPECT_EQ(CaretAfter(1), *RightPositionOf(CaretBefore(1)).position); - - EXPECT_TRUE(RightPositionOf(CaretAfter(1)).IsWithinContext()); - EXPECT_EQ(CaretAfter(2), *RightPositionOf(CaretAfter(1)).position); - - EXPECT_TRUE(RightPositionOf(CaretBefore(2)).IsWithinContext()); - EXPECT_EQ(CaretAfter(2), *RightPositionOf(CaretBefore(2)).position); - - EXPECT_TRUE(RightPositionOf(CaretAfter(2)).IsWithinContext()); - EXPECT_EQ(CaretAfter(6), *RightPositionOf(CaretAfter(2)).position); - - EXPECT_TRUE(RightPositionOf(CaretBefore(3)).IsAfterContext()); - - EXPECT_TRUE(RightPositionOf(CaretAfter(3)).IsWithinContext()); - EXPECT_EQ(CaretBefore(3), *RightPositionOf(CaretAfter(3)).position); - - EXPECT_TRUE(RightPositionOf(CaretBefore(4)).IsWithinContext()); - EXPECT_EQ(CaretBefore(3), *RightPositionOf(CaretBefore(4)).position); - - EXPECT_TRUE(RightPositionOf(CaretAfter(4)).IsWithinContext()); - EXPECT_EQ(CaretBefore(4), *RightPositionOf(CaretAfter(4)).position); - - EXPECT_TRUE(RightPositionOf(CaretBefore(5)).IsWithinContext()); - EXPECT_EQ(CaretBefore(4), *RightPositionOf(CaretBefore(5)).position); - - EXPECT_TRUE(RightPositionOf(CaretAfter(5)).IsWithinContext()); - EXPECT_EQ(CaretBefore(5), *RightPositionOf(CaretAfter(5)).position); - - EXPECT_TRUE(RightPositionOf(CaretBefore(6)).IsWithinContext()); - EXPECT_EQ(CaretAfter(6), *RightPositionOf(CaretBefore(6)).position); - - EXPECT_TRUE(RightPositionOf(CaretAfter(6)).IsWithinContext()); - EXPECT_EQ(CaretAfter(7), *RightPositionOf(CaretAfter(6)).position); - - EXPECT_TRUE(RightPositionOf(CaretBefore(7)).IsWithinContext()); - EXPECT_EQ(CaretAfter(7), *RightPositionOf(CaretBefore(7)).position); - - EXPECT_TRUE(RightPositionOf(CaretAfter(7)).IsWithinContext()); - EXPECT_EQ(CaretAfter(8), *RightPositionOf(CaretAfter(7)).position); - - EXPECT_TRUE(RightPositionOf(CaretBefore(8)).IsWithinContext()); - EXPECT_EQ(CaretAfter(8), *RightPositionOf(CaretBefore(8)).position); - - EXPECT_TRUE(RightPositionOf(CaretAfter(8)).IsWithinContext()); - EXPECT_EQ(CaretBefore(5), *RightPositionOf(CaretAfter(8)).position); -} - -// Tests below check caret movement crossing line boundaries - -TEST_F(NGCaretNavigatorTest, HardLineBreak) { - SetupHtml("container", "<div id=container>abc<br>def</div>"); - - EXPECT_TRUE(LeftPositionOf(CaretBefore(0)).IsBeforeContext()); - - EXPECT_TRUE(RightPositionOf(CaretAfter(2)).IsWithinContext()); - EXPECT_EQ(CaretBefore(4), *RightPositionOf(CaretAfter(2)).position); - - EXPECT_TRUE(RightPositionOf(CaretBefore(3)).IsWithinContext()); - EXPECT_EQ(CaretBefore(4), *RightPositionOf(CaretBefore(3)).position); - - EXPECT_TRUE(LeftPositionOf(CaretBefore(4)).IsWithinContext()); - EXPECT_EQ(CaretBefore(3), *LeftPositionOf(CaretBefore(4)).position); - - EXPECT_TRUE(RightPositionOf(CaretAfter(6)).IsAfterContext()); -} - -TEST_F(NGCaretNavigatorTest, SoftLineWrapAtSpace) { - SetupHtml("container", "<div id=container style=\"width:0\">abc def</div>"); - - EXPECT_TRUE(LeftPositionOf(CaretBefore(0)).IsBeforeContext()); - - EXPECT_TRUE(RightPositionOf(CaretAfter(2)).IsWithinContext()); - EXPECT_EQ(CaretBefore(4), *RightPositionOf(CaretAfter(2)).position); - - EXPECT_TRUE(RightPositionOf(CaretBefore(3)).IsWithinContext()); - EXPECT_EQ(CaretBefore(4), *RightPositionOf(CaretBefore(3)).position); - - EXPECT_TRUE(LeftPositionOf(CaretBefore(4)).IsWithinContext()); - EXPECT_EQ(CaretAfter(2), *LeftPositionOf(CaretBefore(4)).position); - - EXPECT_TRUE(RightPositionOf(CaretAfter(6)).IsAfterContext()); -} - -TEST_F(NGCaretNavigatorTest, BidiAndSoftLineWrapAtSpaceLtr) { - LoadAhem(); - SetupHtml("container", - "<div id=container style='font: 10px/10px Ahem; width: 100px'>" - "before אבגד " - "הוזחטי" - "ךכלםמן" - "נסעףפץ" - "</div>"); - - // Moving left from "|before DCBA" should be before context - EXPECT_TRUE(LeftPositionOf(CaretBefore(0)).IsBeforeContext()); - - // Moving right from "before |DCBA" should yield "before D|CBA" - EXPECT_TRUE(RightPositionOf(CaretAfter(10)).IsWithinContext()); - EXPECT_EQ(CaretBefore(10), *RightPositionOf(CaretAfter(10)).position); - EXPECT_TRUE(RightPositionOf(CaretAfter(6)).IsWithinContext()); - EXPECT_EQ(CaretBefore(10), *RightPositionOf(CaretAfter(6)).position); - - // Moving left from "before |DCBA" should yield "before| DCBA" - EXPECT_TRUE(LeftPositionOf(CaretAfter(10)).IsWithinContext()); - EXPECT_EQ(CaretBefore(6), *LeftPositionOf(CaretAfter(10)).position); - EXPECT_TRUE(LeftPositionOf(CaretAfter(6)).IsWithinContext()); - EXPECT_EQ(CaretBefore(6), *LeftPositionOf(CaretAfter(6)).position); - - // Moving right from "before DCBA|" should yield "V|UTSRQPONMLKJIHGFE" - EXPECT_TRUE(RightPositionOf(CaretBefore(7)).IsWithinContext()); - EXPECT_EQ(CaretBefore(29), *RightPositionOf(CaretBefore(7)).position); - - // Moving left from "|VUTSRQPONMLKJIHGFE" should yield "before DCB|A" - EXPECT_TRUE(LeftPositionOf(CaretAfter(29)).IsWithinContext()); - EXPECT_EQ(CaretAfter(7), *LeftPositionOf(CaretAfter(29)).position); - - // Moving right from "VUTSRQPONMLKJIHGFE|" should be after context - EXPECT_TRUE(RightPositionOf(CaretBefore(12)).IsAfterContext()); -} - -TEST_F(NGCaretNavigatorTest, BidiAndSoftLineWrapAtSpaceRtl) { - LoadAhem(); - SetupHtml( - "container", - "<div dir=rtl id=container style='font: 10px/10px Ahem; width: 120px'>" - "אבגד after encyclopedia" - "</div>"); - - // Moving right from "after DCBA|" should be before context - EXPECT_TRUE(RightPositionOf(CaretBefore(0)).IsBeforeContext()); - - // Moving left from "after| DCBA" should yield "afte|r DCBA" - EXPECT_TRUE(LeftPositionOf(CaretAfter(4)).IsWithinContext()); - EXPECT_EQ(CaretBefore(9), *LeftPositionOf(CaretAfter(4)).position); - EXPECT_TRUE(LeftPositionOf(CaretAfter(9)).IsWithinContext()); - EXPECT_EQ(CaretBefore(9), *LeftPositionOf(CaretAfter(9)).position); - - // Moving right from "after| DCBA" should yield "after |DCBA" - EXPECT_TRUE(RightPositionOf(CaretAfter(4)).IsWithinContext()); - EXPECT_EQ(CaretBefore(4), *RightPositionOf(CaretAfter(4)).position); - EXPECT_TRUE(RightPositionOf(CaretAfter(9)).IsWithinContext()); - EXPECT_EQ(CaretBefore(4), *RightPositionOf(CaretAfter(9)).position); - - // Moving left from "|after DCBA" should yield "encyclopedi|a" - EXPECT_TRUE(LeftPositionOf(CaretBefore(5)).IsWithinContext()); - EXPECT_EQ(CaretBefore(22), *LeftPositionOf(CaretBefore(5)).position); - - // Moving right from "encyclopedia|" should yield "a|fter DCBA" - EXPECT_TRUE(RightPositionOf(CaretAfter(22)).IsWithinContext()); - EXPECT_EQ(CaretAfter(5), *RightPositionOf(CaretAfter(22)).position); - - // Moving left from "|encyclopedia" should be after context - EXPECT_TRUE(LeftPositionOf(CaretBefore(11)).IsAfterContext()); -} - -TEST_F(NGCaretNavigatorTest, SoftLineWrapAtHyphen) { - SetupHtml("container", "<div id=container style=\"width:0\">abc-def</div>"); - - EXPECT_TRUE(LeftPositionOf(CaretBefore(0)).IsBeforeContext()); - - // 3 -> 4 - EXPECT_TRUE(RightPositionOf(CaretAfter(2)).IsWithinContext()); - EXPECT_EQ(CaretAfter(3), *RightPositionOf(CaretAfter(2)).position); - EXPECT_TRUE(RightPositionOf(CaretBefore(3)).IsWithinContext()); - EXPECT_EQ(CaretAfter(3), *RightPositionOf(CaretBefore(3)).position); - - // 4 -> 5 - EXPECT_TRUE(RightPositionOf(CaretAfter(3)).IsWithinContext()); - EXPECT_EQ(CaretAfter(4), *RightPositionOf(CaretAfter(3)).position); - EXPECT_TRUE(RightPositionOf(CaretBefore(4)).IsWithinContext()); - EXPECT_EQ(CaretAfter(4), *RightPositionOf(CaretBefore(4)).position); - - // 5 -> 4 - EXPECT_TRUE(LeftPositionOf(CaretBefore(5)).IsWithinContext()); - EXPECT_EQ(CaretBefore(4), *LeftPositionOf(CaretBefore(5)).position); - EXPECT_TRUE(LeftPositionOf(CaretAfter(4)).IsWithinContext()); - EXPECT_EQ(CaretBefore(4), *LeftPositionOf(CaretAfter(4)).position); - - // 4 -> 3 - EXPECT_TRUE(LeftPositionOf(CaretBefore(4)).IsWithinContext()); - EXPECT_EQ(CaretBefore(3), *LeftPositionOf(CaretBefore(4)).position); - EXPECT_TRUE(LeftPositionOf(CaretAfter(3)).IsWithinContext()); - EXPECT_EQ(CaretBefore(3), *LeftPositionOf(CaretAfter(3)).position); - - EXPECT_TRUE(RightPositionOf(CaretAfter(6)).IsAfterContext()); -} - -TEST_F(NGCaretNavigatorTest, MoveOverPseudoElementInBidi) { - SetupHtml("container", - "<style>.bidi::before,.bidi::after{content:'a\\05D0 b'}</style>" - "<div id=container>אב גד " - "<span class=bidi>הו</span>" - " זח טי</div>"); - - // Text: "AB CD aAbEFaAb GH IJ" - // Rendered as: "DC BA aAbFEaAb JI HG" - - // Moving right from "BA |" should arrive at "F|E" - EXPECT_TRUE(RightPositionOf(CaretAfter(5)).IsWithinContext()); - EXPECT_EQ(CaretBefore(10), *RightPositionOf(CaretAfter(5)).position); - - // Moving left from "|FE" should arrive at "BA| " - EXPECT_TRUE(LeftPositionOf(CaretAfter(10)).IsWithinContext()); - EXPECT_EQ(CaretBefore(5), *LeftPositionOf(CaretAfter(10)).position); - - // Moving right from "FE|" should arrive at " |JI" - EXPECT_TRUE(RightPositionOf(CaretBefore(9)).IsWithinContext()); - EXPECT_EQ(CaretAfter(14), *RightPositionOf(CaretBefore(9)).position); - - // Moving left from "| JI" should arrive at "F|E" - EXPECT_TRUE(LeftPositionOf(CaretBefore(14)).IsWithinContext()); - EXPECT_EQ(CaretAfter(9), *LeftPositionOf(CaretBefore(14)).position); -} - -TEST_F(NGCaretNavigatorTest, EnterableInlineBlock) { - SetupHtml("container", - "<div id=container>foo" - "<span style='display:inline-block'>bar</span>" - "baz</div>"); - - // Moving right from "foo|" should enter the span from front. - EXPECT_TRUE(RightPositionOf(CaretAfter(2)).HasEnteredChildContext()); - EXPECT_EQ(CaretBefore(3), *RightPositionOf(CaretAfter(2)).position); - EXPECT_TRUE(RightPositionOf(CaretBefore(3)).HasEnteredChildContext()); - EXPECT_EQ(CaretBefore(3), *RightPositionOf(CaretBefore(3)).position); - - // Moving left from "|baz" should enter the span from behind. - EXPECT_TRUE(LeftPositionOf(CaretBefore(4)).HasEnteredChildContext()); - EXPECT_EQ(CaretAfter(3), *LeftPositionOf(CaretBefore(4)).position); - EXPECT_TRUE(LeftPositionOf(CaretAfter(3)).HasEnteredChildContext()); - EXPECT_EQ(CaretAfter(3), *LeftPositionOf(CaretAfter(3)).position); -} - -TEST_F(NGCaretNavigatorTest, UnenterableInlineBlock) { - SetupHtml("container", - "<div id=container>foo" - "<input value=bar>" - "baz</div>"); - - // Moving right from "foo|" should reach "<input>|". - EXPECT_TRUE(RightPositionOf(CaretAfter(2)).IsWithinContext()); - EXPECT_EQ(CaretAfter(3), *RightPositionOf(CaretAfter(2)).position); - EXPECT_TRUE(RightPositionOf(CaretBefore(3)).IsWithinContext()); - EXPECT_EQ(CaretAfter(3), *RightPositionOf(CaretBefore(3)).position); - - // Moving left from "|baz" should reach "|<input>". - EXPECT_TRUE(LeftPositionOf(CaretBefore(4)).IsWithinContext()); - EXPECT_EQ(CaretBefore(3), *LeftPositionOf(CaretBefore(4)).position); - EXPECT_TRUE(LeftPositionOf(CaretAfter(3)).IsWithinContext()); - EXPECT_EQ(CaretBefore(3), *LeftPositionOf(CaretAfter(3)).position); -} - -} // namespace blink
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_offset_mapping.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_offset_mapping.cc index 9fcf8f39..a67c437 100644 --- a/third_party/blink/renderer/core/layout/ng/inline/ng_offset_mapping.cc +++ b/third_party/blink/renderer/core/layout/ng/inline/ng_offset_mapping.cc
@@ -12,7 +12,6 @@ #include "third_party/blink/renderer/core/editing/ephemeral_range.h" #include "third_party/blink/renderer/core/editing/position.h" #include "third_party/blink/renderer/core/layout/layout_text_fragment.h" -#include "third_party/blink/renderer/core/layout/ng/inline/ng_caret_navigator.h" #include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.h" #include "third_party/blink/renderer/core/layout/ng/ng_block_node.h" #include "third_party/blink/renderer/platform/text/character.h" @@ -509,16 +508,6 @@ return CreatePositionForOffsetMapping(node, dom_offset); } -PositionWithAffinity NGOffsetMapping::GetPositionWithAffinity( - const NGCaretNavigator::Position& position) const { - if (position.IsBeforeCharacter()) { - return PositionWithAffinity(GetLastPosition(position.index), - TextAffinity::kDownstream); - } - return PositionWithAffinity(GetFirstPosition(position.index + 1), - TextAffinity::kUpstream); -} - bool NGOffsetMapping::HasBidiControlCharactersOnly(unsigned start, unsigned end) const { DCHECK_LE(start, end);
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_offset_mapping.h b/third_party/blink/renderer/core/layout/ng/inline/ng_offset_mapping.h index a8b59f75..65961b9b 100644 --- a/third_party/blink/renderer/core/layout/ng/inline/ng_offset_mapping.h +++ b/third_party/blink/renderer/core/layout/ng/inline/ng_offset_mapping.h
@@ -9,7 +9,6 @@ #include "third_party/blink/renderer/core/core_export.h" #include "third_party/blink/renderer/core/dom/node.h" #include "third_party/blink/renderer/core/editing/forward.h" -#include "third_party/blink/renderer/core/layout/ng/inline/ng_caret_navigator.h" #include "third_party/blink/renderer/platform/heap/handle.h" #include "third_party/blink/renderer/platform/heap/persistent.h" #include "third_party/blink/renderer/platform/wtf/allocator.h" @@ -219,13 +218,6 @@ Position GetFirstPosition(unsigned) const; Position GetLastPosition(unsigned) const; - // Converts the given caret position on text content to a PositionWithAffinity - // in DOM. If |position| is before a character, the function creates a - // downstream position before |GetLastPosition()| of the character; otherwise, - // it returns an upstream position after |GetFirstPosition()| of the character - PositionWithAffinity GetPositionWithAffinity( - const NGCaretNavigator::Position& position) const; - // Returns all NGOffsetMappingUnits whose text content ranges has non-empty // (but possibly collapsed) intersection with (start, end). Note that units // that only "touch" |start| or |end| are excluded.
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_offset_mapping_builder.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_offset_mapping_builder.cc index 8969d67f..9524bfb 100644 --- a/third_party/blink/renderer/core/layout/ng/inline/ng_offset_mapping_builder.cc +++ b/third_party/blink/renderer/core/layout/ng/inline/ng_offset_mapping_builder.cc
@@ -7,7 +7,6 @@ #include <utility> #include "third_party/blink/renderer/core/layout/layout_text.h" #include "third_party/blink/renderer/core/layout/layout_text_fragment.h" -#include "third_party/blink/renderer/core/layout/ng/inline/ng_caret_navigator.h" #include "third_party/blink/renderer/core/layout/ng/inline/ng_offset_mapping.h" namespace blink {
diff --git a/third_party/blink/renderer/core/paint/README.md b/third_party/blink/renderer/core/paint/README.md index 24d44b67..9a823ceb 100644 --- a/third_party/blink/renderer/core/paint/README.md +++ b/third_party/blink/renderer/core/paint/README.md
@@ -1,12 +1,35 @@ -# `Source/core/paint` +<!--- + The live version of this document can be viewed at: + https://chromium.googlesource.com/chromium/src/+/master/third_party/blink/renderer/core/paint/README.md +--> -This directory contains implementation of painters of layout objects. It covers -the following document lifecycle phases: +# renderer/core/paint -* Layerization (`kInCompositingUpdate`, `kCompositingInputsClean` and `kCompositingClean`) -* PaintInvalidation (`InPaintInvalidation` and `PaintInvalidationClean`) -* PrePaint (`InPrePaint` and `PrePaintClean`) -* Paint (`InPaint` and `PaintClean`) +This directory contains implementation of painters of layout objects. It is +responsible for generating display item lists and property trees from the +layout object tree, and deciding how to group these for compositing. + +It covers the following document lifecycle phases: + +* Compositing update + * Decides layerization (GraphicsLayers). +* [PrePaint](#PrePaint) + * Invalidates display items. + * Builds paint property trees. +* [Paint](#Paint) + * Walks the LayoutObject tree and creates a display item list. + * Groups the display list into paint chunks which share the same + property tree state. + * Passes the display item list to the compositor in cc::Layers. + * Converts the blink property tree nodes into cc property tree nodes. + +For information about how the display list and paint property trees are +implemented, see +[the platform paint README file](../../platform/graphics/paint/README.md). + +This code is owned by the [rendering team](https://www.chromium.org/teams/rendering). + +[TOC] ## Glossaries @@ -187,13 +210,14 @@ of the nearest `LayoutObject`with a compositing trigger on its *compositing container chain* (except for squashed layers; see below). For historical, practical and implementation detail reasons, only `LayoutObject`s -with `PaintLayer`s can have a compositing trigger. See crbug.com/370604 for a -bug tracking this limitation, which is often referred to as the "fundamental -compositing bug". +with `PaintLayer`s can have a compositing trigger. See +[crbug.com/370604](https://crbug.com/370604) for a bug tracking this limitation, +which is often referred to as the **fundamental compositing bug**. The various compositing triggers are listed [here](../../platform/graphics/compositing_reasons.h). They fall in to several categories: + 1. Direct reasons due to CSS style (see `CompositingReason::kComboAllDirectStyleDeterminedReasons`) 2. Direct reasons due to other conditions (see `CompositingReason::kComboAllDirectNonStyleDeterminedReasons`) 3. Composited scrolling-dependent reasons (see `CompositingReason::kComboAllCompositedScrollingDeterminedReasons`) @@ -214,6 +238,7 @@ composited layer. Note that composited scrolling is special. Several ways it is special: + * Composited descendants do _not_ necessarily cause composited scrolling of an ancestor. * The presence of LCD text prevents composited scrolling in the @@ -227,6 +252,7 @@ reason from category (3) during the CompositingRequirementsUpdater Note that overlap triggers have two special behaviors: + * Any `LayoutObject` which may overlap a `LayoutObject` that uses composited scrolling or a transform animation, paints after it, and scrolls with respect to it, receives @@ -420,6 +446,7 @@ element's subtree. Example tree: +``` +----------------------+ | 1. Root LayoutObject | +----------------------+ @@ -448,11 +475,12 @@ +-----------------+ +-----------------+ | 7. LayoutObject | | 8. LayoutObject | +-----------------+ +-----------------+ - +``` Suppose that element 3's style changes to include a transform (e.g. "transform: translateX(10px);"). Typically, here is the order of the walk (depth first) and updates: + * Root element 1 is visited since some descendant needs updates * Element 2 is visited since it is one of the descendants, but it doesn't need updates. @@ -525,8 +553,8 @@ `PaintInvalidatorContext` passed from the parent object. It tracks the following information to provide O(1) complexity access to them if possible: -* Paint invalidation container (Slimming Paint v1 only): Since as indicated by - the definitions in [Glossaries](#other-glossaries), the paint invalidation +* Paint invalidation container (Slimming Paint v1 only): As described by + the definitions in [Other glossaries](#Other-glossaries), the paint invalidation container for stacked objects can differ from normal objects, we have to track both separately. Here is an example: @@ -541,7 +569,7 @@ * Painting layer: the layer which will initiate painting of the current object. It's the same value as `LayoutObject::PaintingLayer()`. -`PaintInvalidator`[PaintInvalidator.h] initializes `PaintInvalidatorContext` +[`PaintInvalidator`](PaintInvalidator.h) initializes `PaintInvalidatorContext` for the current object, then calls `LayoutObject::InvalidatePaint()` which calls the object's paint invalidator (e.g. `BoxPaintInvalidator`) to complete paint invalidation of the object. @@ -576,7 +604,8 @@ implementation, the combined first line style of `LayoutInline` is identified with `kPseudoIdFirstLineInherited`. -The normal paint invalidation of texts doesn't work for first line because +The normal paint invalidation of texts doesn't work for first line because: + * `ComputedStyle::VisualInvalidationDiff()` can't detect first line style changes; * The normal paint invalidation is based on whole LayoutObject's, not aware of
diff --git a/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.cc b/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.cc index 5d413627..42e3bb3 100644 --- a/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.cc +++ b/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.cc
@@ -3506,10 +3506,10 @@ scrollable_area->SetScrollbarsHiddenIfOverlay(hidden); } -void CompositedLayerMapping::SetPaintArtifactCompositorNeedsUpdate() const { +void CompositedLayerMapping::GraphicsLayersDidChange() { LocalFrameView* frame_view = GetLayoutObject().GetFrameView(); DCHECK(frame_view); - frame_view->SetPaintArtifactCompositorNeedsUpdate(); + frame_view->GraphicsLayersDidChange(); } #if DCHECK_IS_ON()
diff --git a/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.h b/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.h index 3f62979..cd139ff 100644 --- a/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.h +++ b/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.h
@@ -215,7 +215,7 @@ bool ShouldThrottleRendering() const override; bool IsTrackingRasterInvalidations() const override; void SetOverlayScrollbarsHidden(bool) override; - void SetPaintArtifactCompositorNeedsUpdate() const override; + void GraphicsLayersDidChange() override; #if DCHECK_IS_ON() void VerifyNotPainting() override;
diff --git a/third_party/blink/renderer/core/paint/image_paint_timing_detector.cc b/third_party/blink/renderer/core/paint/image_paint_timing_detector.cc index ab38f86..d4400031 100644 --- a/third_party/blink/renderer/core/paint/image_paint_timing_detector.cc +++ b/third_party/blink/renderer/core/paint/image_paint_timing_detector.cc
@@ -92,10 +92,9 @@ !frame_view_->GetFrame().LocalFrameRoot().IsMainFrame()); } -void ImagePaintTimingDetector::OnLargestImagePaintDetected( +void ImagePaintTimingDetector::ReportCandidateToTrace( ImageRecord& largest_image_record) { DCHECK(!largest_image_record.paint_time.is_null()); - largest_image_paint_ = &largest_image_record; auto value = std::make_unique<TracedValue>(); PopulateTraceValue(*value, largest_image_record, ++count_candidates_); TRACE_EVENT_MARK_WITH_TIMESTAMP2("loading", "LargestImagePaint::Candidate", @@ -107,33 +106,27 @@ void ImagePaintTimingDetector::UpdateCandidate() { ImageRecord* largest_image_record = records_manager_.FindLargestPaintCandidate(); - // These conditions represents the following scenarios: - // 1. candiate being nullptr: no image is found. We discard the candidate and - // wait for the next analysis. - // 2. candidate's first paint being null: largest image is still pending for - // timing. We discard the candidate and wait for the next analysis. - // 3. new candidate equals to old candidate: we don't need to update the - // result. - if (largest_image_record == largest_image_paint_) + const base::TimeTicks time = largest_image_record + ? largest_image_record->paint_time + : base::TimeTicks(); + const uint64_t size = + largest_image_record ? largest_image_record->first_size : 0; + bool changed = + frame_view_->GetPaintTimingDetector().HasLargestImagePaintChanged(time, + size); + if (!changed) return; - - if (!largest_image_record) { - largest_image_paint_ = nullptr; - frame_view_->GetPaintTimingDetector().DidChangePerformanceTiming(); - } else if (largest_image_record->loaded && - !largest_image_record->paint_time.is_null()) { - OnLargestImagePaintDetected(*largest_image_record); - frame_view_->GetPaintTimingDetector().DidChangePerformanceTiming(); + if (largest_image_record && !largest_image_record->paint_time.is_null()) { + // If an image has paint time, it must have been loaded. + DCHECK(largest_image_record->loaded); + // TODO(crbug.com/960365): we need to figure out how to communicate to the + // trace (devtools/trace-viewer/benchmarks) that the largest image is still + // loading (when paint_time is null). Before we decide how to handle it, we + // do not notify the trace about this specific case for now. + ReportCandidateToTrace(*largest_image_record); } - if (largest_image_paint_) { - frame_view_->GetPaintTimingDetector().NotifyLargestImage( - largest_image_paint_->paint_time, largest_image_paint_->first_size); - } else { - frame_view_->GetPaintTimingDetector().NotifyLargestImage(base::TimeTicks(), - 0); - } - // TODO(crbug/949974): when the largest image is still loading, we should - // update the result as the current time. + frame_view_->GetPaintTimingDetector().NotifyLargestImagePaintChange(time, + size); } void ImagePaintTimingDetector::OnPaintFinished() { @@ -242,6 +235,7 @@ !records_manager_.WasVisibleNodeLoaded(background_image_id) && cached_image.IsLoaded()) { records_manager_.OnImageLoaded(background_image_id, frame_index_); + need_update_timing_at_frame_end_ = true; return; } @@ -268,8 +262,10 @@ records_manager_.RecordInvisibleNode(node_id); } else { records_manager_.RecordVisibleNode(background_image_id, rect_size); - if (cached_image.IsLoaded()) + if (cached_image.IsLoaded()) { records_manager_.OnImageLoaded(background_image_id, frame_index_); + need_update_timing_at_frame_end_ = true; + } } if (records_manager_.RecordedTooManyNodes()) @@ -301,6 +297,7 @@ if (is_recored_visible_node && !records_manager_.WasVisibleNodeLoaded(node_id) && is_loaded) { records_manager_.OnImageLoaded(node_id, frame_index_); + need_update_timing_at_frame_end_ = true; return; } @@ -325,8 +322,10 @@ records_manager_.RecordInvisibleNode(node_id); } else { records_manager_.RecordVisibleNode(node_id, rect_size); - if (is_loaded) + if (is_loaded) { records_manager_.OnImageLoaded(node_id, frame_index_); + need_update_timing_at_frame_end_ = true; + } } if (records_manager_.RecordedTooManyNodes()) @@ -464,7 +463,7 @@ return !is_recording_ && num_pending_swap_callbacks_ == 0; } -ImageRecord* ImageRecordsManager::FindLargestPaintCandidate() { +ImageRecord* ImageRecordsManager::FindLargestPaintCandidate() const { DCHECK_EQ(visible_node_map_.size() + visible_background_image_map_.size(), size_ordered_set_.size()); for (auto it = size_ordered_set_.begin(); it != size_ordered_set_.end();
diff --git a/third_party/blink/renderer/core/paint/image_paint_timing_detector.h b/third_party/blink/renderer/core/paint/image_paint_timing_detector.h index 2ce61ec5..ed80031 100644 --- a/third_party/blink/renderer/core/paint/image_paint_timing_detector.h +++ b/third_party/blink/renderer/core/paint/image_paint_timing_detector.h
@@ -33,7 +33,7 @@ // |size_ordered_set_| since it's the sorting key. uint64_t first_size = 0; unsigned frame_index = 0; - // The time of the first paint after fully loaded. + // The time of the first paint after fully loaded. 0 means not painted yet. base::TimeTicks paint_time = base::TimeTicks(); WeakPersistent<const ImageResourceContent> cached_image; bool loaded = false; @@ -56,7 +56,7 @@ public: ImageRecordsManager(); - ImageRecord* FindLargestPaintCandidate(); + ImageRecord* FindLargestPaintCandidate() const; bool AreAllVisibleNodesDetached() const; void SetNodeDetached(const DOMNodeId& visible_node_id); @@ -182,7 +182,7 @@ void Trace(blink::Visitor*); private: - ImageRecord* FindLargestPaintCandidate(); + ImageRecord* FindLargestPaintCandidate() const; void PopulateTraceValue(TracedValue&, const ImageRecord& first_image_paint, @@ -192,7 +192,7 @@ WebWidgetClient::SwapResult, base::TimeTicks); void RegisterNotifySwapTime(); - void OnLargestImagePaintDetected(ImageRecord&); + void ReportCandidateToTrace(ImageRecord&); void Deactivate(); void HandleTooManyNodes(); @@ -216,9 +216,10 @@ // |is_recording|, helps determine whether this detector can be destroyed. int num_pending_swap_callbacks_ = 0; + // This need to be set whenever changes that can affect the output of + // |FindLargestPaintCandidate| occur during the paint tree walk. bool need_update_timing_at_frame_end_ = false; - ImageRecord* largest_image_paint_ = nullptr; ImageRecordsManager records_manager_; Member<LocalFrameView> frame_view_; };
diff --git a/third_party/blink/renderer/core/paint/image_paint_timing_detector_test.cc b/third_party/blink/renderer/core/paint/image_paint_timing_detector_test.cc index f3a0c98..5b31e5b 100644 --- a/third_party/blink/renderer/core/paint/image_paint_timing_detector_test.cc +++ b/third_party/blink/renderer/core/paint/image_paint_timing_detector_test.cc
@@ -7,6 +7,7 @@ #include "base/bind.h" #include "build/build_config.h" #include "third_party/blink/public/platform/web_url_loader_mock_factory.h" +#include "third_party/blink/public/web/web_performance.h" #include "third_party/blink/public/web/web_widget_client.h" #include "third_party/blink/renderer/core/html/html_image_element.h" #include "third_party/blink/renderer/core/html/media/html_video_element.h" @@ -14,6 +15,9 @@ #include "third_party/blink/renderer/core/scroll/scroll_types.h" #include "third_party/blink/renderer/core/svg/svg_image_element.h" #include "third_party/blink/renderer/core/testing/core_unit_test_helper.h" +#include "third_party/blink/renderer/core/timing/dom_window_performance.h" +#include "third_party/blink/renderer/core/timing/performance_timing.h" +#include "third_party/blink/renderer/core/timing/window_performance.h" #include "third_party/blink/renderer/platform/graphics/static_bitmap_image.h" #include "third_party/blink/renderer/platform/heap/heap.h" #include "third_party/blink/renderer/platform/runtime_enabled_features.h" @@ -57,6 +61,12 @@ return GetChildFrameView().GetPaintTimingDetector(); } + const PerformanceTiming& GetPerformanceTiming() { + PerformanceTiming* performance = + DOMWindowPerformance::performance(*GetFrame().DomWindow())->timing(); + return *performance; + } + IntRect GetViewportRect(LocalFrameView& view) { ScrollableArea* scrollable_area = view.GetScrollableArea(); DCHECK(scrollable_area); @@ -118,17 +128,13 @@ } TimeTicks LargestPaintStoredResult() { - ImageRecord* record = GetPaintTimingDetector() - .GetImagePaintTimingDetector() - ->largest_image_paint_; - return !record ? base::TimeTicks() : record->paint_time; + return GetPaintTimingDetector().largest_image_paint_time_; } void UpdateAllLifecyclePhasesAndInvokeCallbackIfAny() { UpdateAllLifecyclePhasesForTest(); - if (!callback_queue_.empty()) { + if (!callback_queue_.empty()) InvokeCallback(); - } } void InvokeCallback() { @@ -211,6 +217,48 @@ EXPECT_TRUE(record->loaded); } +TEST_F(ImagePaintTimingDetectorTest, UpdatePerformanceTiming) { + const PerformanceTiming& performance_timing = GetPerformanceTiming(); + EXPECT_EQ(performance_timing.LargestImagePaintSize(), 0u); + EXPECT_EQ(performance_timing.LargestImagePaint(), 0u); + SetBodyInnerHTML(R"HTML( + <img id="target"></img> + )HTML"); + SetImageAndPaint("target", 5, 5); + UpdateAllLifecyclePhasesAndInvokeCallbackIfAny(); + EXPECT_EQ(performance_timing.LargestImagePaintSize(), 25u); + EXPECT_GT(performance_timing.LargestImagePaint(), 0u); +} + +TEST_F(ImagePaintTimingDetectorTest, + PerformanceTimingHasZeroTimeNonZeroSizeWhenTheLargestIsNotPainted) { + const PerformanceTiming& performance_timing = GetPerformanceTiming(); + EXPECT_EQ(performance_timing.LargestImagePaintSize(), 0u); + EXPECT_EQ(performance_timing.LargestImagePaint(), 0u); + SetBodyInnerHTML(R"HTML( + <img id="target"></img> + )HTML"); + SetImageAndPaint("target", 5, 5); + UpdateAllLifecyclePhasesForTest(); + EXPECT_EQ(performance_timing.LargestImagePaintSize(), 25u); + EXPECT_EQ(performance_timing.LargestImagePaint(), 0u); +} + +TEST_F(ImagePaintTimingDetectorTest, UpdatePerformanceTimingToZero) { + SetBodyInnerHTML(R"HTML( + <img id="target"></img> + )HTML"); + SetImageAndPaint("target", 5, 5); + UpdateAllLifecyclePhasesAndInvokeCallbackIfAny(); + const PerformanceTiming& performance_timing = GetPerformanceTiming(); + EXPECT_EQ(performance_timing.LargestImagePaintSize(), 25u); + EXPECT_GT(performance_timing.LargestImagePaint(), 0u); + GetDocument().body()->RemoveChild(GetDocument().getElementById("target")); + UpdateAllLifecyclePhasesAndInvokeCallbackIfAny(); + EXPECT_EQ(performance_timing.LargestImagePaintSize(), 0u); + EXPECT_EQ(performance_timing.LargestImagePaint(), 0u); +} + TEST_F(ImagePaintTimingDetectorTest, LargestImagePaint_OpacityZero) { SetBodyInnerHTML(R"HTML( <style>
diff --git a/third_party/blink/renderer/core/paint/link_highlight_impl.cc b/third_party/blink/renderer/core/paint/link_highlight_impl.cc index 2e9393701..0de51b15 100644 --- a/third_party/blink/renderer/core/paint/link_highlight_impl.cc +++ b/third_party/blink/renderer/core/paint/link_highlight_impl.cc
@@ -514,8 +514,12 @@ void LinkHighlightImpl::SetPaintArtifactCompositorNeedsUpdate() { DCHECK(node_); - if (auto* frame_view = node_->GetDocument().View()) - frame_view->SetPaintArtifactCompositorNeedsUpdate(); + if (auto* frame_view = node_->GetDocument().View()) { + if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) + frame_view->SetPaintArtifactCompositorNeedsUpdate(); + else + frame_view->GraphicsLayersDidChange(); + } } } // namespace blink
diff --git a/third_party/blink/renderer/core/paint/paint_timing_detector.cc b/third_party/blink/renderer/core/paint/paint_timing_detector.cc index dd52bf6..e1d91a96 100644 --- a/third_party/blink/renderer/core/paint/paint_timing_detector.cc +++ b/third_party/blink/renderer/core/paint/paint_timing_detector.cc
@@ -181,10 +181,20 @@ image_paint_timing_detector_->IsRecording()); } -void PaintTimingDetector::NotifyLargestImage(base::TimeTicks image_paint_time, - uint64_t image_paint_size) { +void PaintTimingDetector::NotifyLargestImagePaintChange( + base::TimeTicks image_paint_time, + uint64_t image_paint_size) { + DCHECK(HasLargestImagePaintChanged(image_paint_time, image_paint_size)); largest_image_paint_time_ = image_paint_time; largest_image_paint_size_ = image_paint_size; + DidChangePerformanceTiming(); +} + +bool PaintTimingDetector::HasLargestImagePaintChanged( + base::TimeTicks largest_image_paint_time, + uint64_t largest_image_paint_size) { + return largest_image_paint_time != largest_image_paint_time_ || + largest_image_paint_size != largest_image_paint_size_; } void PaintTimingDetector::NotifyLargestText(base::TimeTicks text_paint_time,
diff --git a/third_party/blink/renderer/core/paint/paint_timing_detector.h b/third_party/blink/renderer/core/paint/paint_timing_detector.h index 541654f..5324b2d 100644 --- a/third_party/blink/renderer/core/paint/paint_timing_detector.h +++ b/third_party/blink/renderer/core/paint/paint_timing_detector.h
@@ -30,6 +30,8 @@ // https://docs.google.com/document/d/1DRVd4a2VU8-yyWftgOparZF-sf16daf0vfbsHuz2rws/edit class CORE_EXPORT PaintTimingDetector : public GarbageCollected<PaintTimingDetector> { + friend class ImagePaintTimingDetectorTest; + public: PaintTimingDetector(LocalFrameView*); @@ -52,8 +54,9 @@ void NotifyInputEvent(WebInputEvent::Type); bool NeedToNotifyInputOrScroll(); void NotifyScroll(ScrollType); - void NotifyLargestImage(base::TimeTicks, uint64_t size); + void NotifyLargestImagePaintChange(base::TimeTicks, uint64_t size); void NotifyLargestText(base::TimeTicks, uint64_t size); + bool HasLargestImagePaintChanged(base::TimeTicks, uint64_t size); void DidChangePerformanceTiming(); FloatRect CalculateVisualRect(const IntRect& visual_rect,
diff --git a/third_party/blink/renderer/core/scroll/scrollbar_theme_mac.mm b/third_party/blink/renderer/core/scroll/scrollbar_theme_mac.mm index 537fb1c..be8b87df 100644 --- a/third_party/blink/renderer/core/scroll/scrollbar_theme_mac.mm +++ b/third_party/blink/renderer/core/scroll/scrollbar_theme_mac.mm
@@ -52,6 +52,7 @@ blink::Scrollbar* _scrollbar; base::scoped_nsobject<ScrollbarPainter> _scrollbarPainter; BOOL _suppressSetScrollbarsHidden; + CGFloat _saved_knob_alpha; } - (id)initWithScrollbar:(blink::Scrollbar*)scrollbar painter:(const base::scoped_nsobject<ScrollbarPainter>&)painter; @@ -79,6 +80,12 @@ - (void)setSuppressSetScrollbarsHidden:(BOOL)value { _suppressSetScrollbarsHidden = value; + if (value) { + _saved_knob_alpha = [_scrollbarPainter knobAlpha]; + } else { + [_scrollbarPainter setKnobAlpha:_saved_knob_alpha]; + _scrollbar->SetScrollbarsHiddenIfOverlay(_saved_knob_alpha == 0); + } } - (void)dealloc { @@ -310,7 +317,6 @@ [scrollbar_painter setKnobProportion:1]; [observer setSuppressSetScrollbarsHidden:YES]; - CGFloat old_knob_alpha = [scrollbar_painter knobAlpha]; [scrollbar_painter setKnobAlpha:1]; if (scrollbar.Enabled()) @@ -321,7 +327,6 @@ // scrollbar area. [scrollbar_painter setBoundsSize:NSSizeFromCGSize(CGSize(scrollbar.FrameRect().Size()))]; - [scrollbar_painter setKnobAlpha:old_knob_alpha]; [observer setSuppressSetScrollbarsHidden:NO]; }
diff --git a/third_party/blink/renderer/modules/BUILD.gn b/third_party/blink/renderer/modules/BUILD.gn index 3bf64d9b7..1f31992 100644 --- a/third_party/blink/renderer/modules/BUILD.gn +++ b/third_party/blink/renderer/modules/BUILD.gn
@@ -323,6 +323,7 @@ "media_controls/media_controls_impl_test.cc", "media_controls/media_controls_orientation_lock_delegate_test.cc", "media_controls/media_controls_rotate_to_fullscreen_delegate_test.cc", + "mediacapturefromelement/canvas_capture_handler_unittest.cc", "mediastream/media_constraints_test.cc", "mediastream/media_devices_test.cc", "mediastream/media_stream_video_capturer_source_test.cc",
diff --git a/third_party/blink/renderer/modules/bluetooth/bluetooth_error.cc b/third_party/blink/renderer/modules/bluetooth/bluetooth_error.cc index 64a34fea..305c579 100644 --- a/third_party/blink/renderer/modules/bluetooth/bluetooth_error.cc +++ b/third_party/blink/renderer/modules/bluetooth/bluetooth_error.cc
@@ -92,6 +92,8 @@ MAP_ERROR(DESCRIPTOR_NO_LONGER_EXISTS, DOMExceptionCode::kInvalidStateError, "GATT Descriptor no longer exists."); + MAP_ERROR(PROMPT_CANCELED, DOMExceptionCode::kInvalidStateError, + "User canceled the permission prompt."); // NetworkErrors: MAP_ERROR(CONNECT_ALREADY_IN_PROGRESS, DOMExceptionCode::kNetworkError, @@ -193,6 +195,10 @@ DOMExceptionCode::kSecurityError, "requestDevice() called from cross-origin iframe."); + // NotAllowedErrors: + MAP_ERROR(SCANNING_BLOCKED, DOMExceptionCode::kNotAllowedError, + "requestLEScan() call is blocked by user."); + #undef MAP_ERROR }
diff --git a/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d.cc b/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d.cc index 5130c02..444e0fc 100644 --- a/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d.cc +++ b/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d.cc
@@ -557,7 +557,14 @@ Font resolved_font; if (!canvas_font_cache->GetFontUsingDefaultStyle(new_font, resolved_font)) return; - ModifiableState().SetFont(resolved_font, Host()->GetFontSelector()); + + // We need to reset Computed and Adjusted size so we skip zoom and + // minimum font size for detached canvas. + FontDescription final_description(resolved_font.GetFontDescription()); + final_description.SetComputedSize(final_description.SpecifiedSize()); + final_description.SetAdjustedSize(final_description.SpecifiedSize()); + Font final_font(final_description); + ModifiableState().SetFont(final_font, Host()->GetFontSelector()); } // The parse succeeded.
diff --git a/third_party/blink/renderer/modules/mediacapturefromelement/BUILD.gn b/third_party/blink/renderer/modules/mediacapturefromelement/BUILD.gn index 8a69c806..7778a4b 100644 --- a/third_party/blink/renderer/modules/mediacapturefromelement/BUILD.gn +++ b/third_party/blink/renderer/modules/mediacapturefromelement/BUILD.gn
@@ -8,6 +8,8 @@ sources = [ "auto_canvas_draw_listener.cc", "auto_canvas_draw_listener.h", + "canvas_capture_handler.cc", + "canvas_capture_handler.h", "canvas_capture_media_stream_track.cc", "canvas_capture_media_stream_track.h", "html_canvas_element_capture.cc", @@ -19,4 +21,11 @@ "timed_canvas_draw_listener.cc", "timed_canvas_draw_listener.h", ] + + deps = [ + "//components/viz/common", + "//media", + "//skia", + "//third_party/libyuv", + ] }
diff --git a/third_party/blink/renderer/modules/mediacapturefromelement/DEPS b/third_party/blink/renderer/modules/mediacapturefromelement/DEPS index 5eb0874..844e79cc 100644 --- a/third_party/blink/renderer/modules/mediacapturefromelement/DEPS +++ b/third_party/blink/renderer/modules/mediacapturefromelement/DEPS
@@ -3,4 +3,17 @@ "+third_party/blink/renderer/modules/encryptedmedia", "+third_party/blink/renderer/modules/mediacapturefromelement", "+third_party/blink/renderer/modules/mediastream", + "+third_party/blink/renderer/modules/modules_export.h", + + "+components/viz/common", + "+media/base", + "+media/capture", + "+third_party/libyuv", + "+ui/gfx/color_space.h", ] + +specific_include_rules = { + "canvas_capture_handler_unittest\.cc" : [ + "+base/run_loop.h", + ], +}
diff --git a/content/renderer/media_capture_from_element/canvas_capture_handler.cc b/third_party/blink/renderer/modules/mediacapturefromelement/canvas_capture_handler.cc similarity index 94% rename from content/renderer/media_capture_from_element/canvas_capture_handler.cc rename to third_party/blink/renderer/modules/mediacapturefromelement/canvas_capture_handler.cc index 9b995538..daec604 100644 --- a/content/renderer/media_capture_from_element/canvas_capture_handler.cc +++ b/third_party/blink/renderer/modules/mediacapturefromelement/canvas_capture_handler.cc
@@ -2,16 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "content/renderer/media_capture_from_element/canvas_capture_handler.h" +#include "third_party/blink/renderer/modules/mediacapturefromelement/canvas_capture_handler.h" #include <utility> -#include "base/base64.h" #include "base/bind.h" #include "base/bind_helpers.h" #include "base/macros.h" #include "base/rand_util.h" -#include "base/strings/utf_string_conversions.h" #include "components/viz/common/gl_helper.h" #include "media/base/limits.h" #include "third_party/blink/public/platform/modules/mediastream/webrtc_uma_histograms.h" @@ -22,6 +20,8 @@ #include "third_party/blink/public/web/modules/mediastream/media_stream_video_capturer_source.h" #include "third_party/blink/public/web/modules/mediastream/media_stream_video_source.h" #include "third_party/blink/public/web/modules/mediastream/media_stream_video_track.h" +#include "third_party/blink/renderer/platform/wtf/functional.h" +#include "third_party/blink/renderer/platform/wtf/text/base64.h" #include "third_party/libyuv/include/libyuv.h" #include "third_party/skia/include/core/SkImage.h" #include "third_party/skia/include/gpu/GrBackendSurface.h" @@ -29,7 +29,7 @@ using media::VideoFrame; -namespace content { +namespace blink { namespace { @@ -64,9 +64,9 @@ media::VideoCaptureFormats GetPreferredFormats() override { DCHECK_CALLED_ON_VALID_THREAD(main_render_thread_checker_); media::VideoCaptureFormats formats; - formats.push_back(media::VideoCaptureFormat(size_, frame_rate_, + formats.push_back(media::VideoCaptureFormat(gfx::Size(size_), frame_rate_, media::PIXEL_FORMAT_I420)); - formats.push_back(media::VideoCaptureFormat(size_, frame_rate_, + formats.push_back(media::VideoCaptureFormat(gfx::Size(size_), frame_rate_, media::PIXEL_FORMAT_I420A)); return formats; } @@ -185,7 +185,8 @@ SendFrame(ConvertToYUVFrame(image->isOpaque(), false, static_cast<const uint8_t*>(pixmap.addr(0, 0)), gfx::Size(pixmap.width(), pixmap.height()), - pixmap.rowBytes(), pixmap.colorType()), + static_cast<int>(pixmap.rowBytes()), + pixmap.colorType()), timestamp, GetImageYUVColorSpace(image)); return; } @@ -307,9 +308,9 @@ context_provider->GetGLHelper()->ReadbackTextureAsync( texture_info.fID, image_size, temp_argb_frame->visible_data(VideoFrame::kARGBPlane), kN32_SkColorType, - base::BindOnce(&CanvasCaptureHandler::OnARGBPixelsReadAsync, - weak_ptr_factory_.GetWeakPtr(), image, temp_argb_frame, - timestamp, surface_origin != kTopLeft_GrSurfaceOrigin)); + WTF::Bind(&CanvasCaptureHandler::OnARGBPixelsReadAsync, + weak_ptr_factory_.GetWeakPtr(), image, temp_argb_frame, + timestamp, surface_origin != kTopLeft_GrSurfaceOrigin)); } void CanvasCaptureHandler::ReadYUVPixelsAsync( @@ -346,9 +347,9 @@ output_frame->visible_data(media::VideoFrame::kUPlane), output_frame->stride(media::VideoFrame::kVPlane), output_frame->visible_data(media::VideoFrame::kVPlane), gfx::Point(0, 0), - base::BindOnce(&CanvasCaptureHandler::OnYUVPixelsReadAsync, - weak_ptr_factory_.GetWeakPtr(), image, output_frame, - timestamp)); + WTF::Bind(&CanvasCaptureHandler::OnYUVPixelsReadAsync, + weak_ptr_factory_.GetWeakPtr(), image, output_frame, + timestamp)); } void CanvasCaptureHandler::OnARGBPixelsReadAsync( @@ -479,9 +480,10 @@ void CanvasCaptureHandler::AddVideoCapturerSourceToVideoTrack( std::unique_ptr<media::VideoCapturerSource> source, blink::WebMediaStreamTrack* web_track) { - std::string str_track_id; - base::Base64Encode(base::RandBytesAsString(64), &str_track_id); - const blink::WebString track_id = blink::WebString::FromASCII(str_track_id); + Vector<char> base64_track_id; + Base64Encode(base::RandBytesAsString(64).c_str(), base64_track_id); + const auto track_id = + WebString::FromUTF8(base64_track_id.data(), base64_track_id.size()); media::VideoCaptureFormats preferred_formats = source->GetPreferredFormats(); blink::MediaStreamVideoSource* media_stream_source = new blink::MediaStreamVideoCapturerSource( @@ -502,4 +504,4 @@ true)); } -} // namespace content +} // namespace blink
diff --git a/content/renderer/media_capture_from_element/canvas_capture_handler.h b/third_party/blink/renderer/modules/mediacapturefromelement/canvas_capture_handler.h similarity index 90% rename from content/renderer/media_capture_from_element/canvas_capture_handler.h rename to third_party/blink/renderer/modules/mediacapturefromelement/canvas_capture_handler.h index b8d331a..d699e3f 100644 --- a/content/renderer/media_capture_from_element/canvas_capture_handler.h +++ b/third_party/blink/renderer/modules/mediacapturefromelement/canvas_capture_handler.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 CONTENT_RENDERER_MEDIA_CAPTURE_FROM_ELEMENT_CANVAS_CAPTURE_HANDLER_H_ -#define CONTENT_RENDERER_MEDIA_CAPTURE_FROM_ELEMENT_CANVAS_CAPTURE_HANDLER_H_ +#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIACAPTUREFROMELEMENT_CANVAS_CAPTURE_HANDLER_H_ +#define THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIACAPTUREFROMELEMENT_CANVAS_CAPTURE_HANDLER_H_ #include <stddef.h> #include <stdint.h> @@ -11,21 +11,21 @@ #include <memory> #include "base/macros.h" -#include "base/memory/ref_counted.h" +#include "base/memory/scoped_refptr.h" #include "base/memory/weak_ptr.h" #include "base/single_thread_task_runner.h" #include "base/threading/thread_checker.h" -#include "content/common/content_export.h" #include "media/base/video_frame_pool.h" #include "media/capture/video_capturer_source.h" #include "third_party/blink/public/platform/web_canvas_capture_handler.h" #include "third_party/blink/public/platform/web_media_stream_track.h" #include "third_party/blink/public/platform/web_size.h" +#include "third_party/blink/renderer/modules/modules_export.h" #include "third_party/skia/include/core/SkImageInfo.h" class SkImage; -namespace content { +namespace blink { // CanvasCaptureHandler acts as the link between Blink side HTMLCanvasElement // and Chrome side VideoCapturerSource. It is responsible for handling @@ -36,7 +36,7 @@ // All methods are called on the same thread as construction and destruction, // i.e. the Main Render thread. Note that a CanvasCaptureHandlerDelegate is // used to send back frames to |io_task_runner_|, i.e. IO thread. -class CONTENT_EXPORT CanvasCaptureHandler final +class MODULES_EXPORT CanvasCaptureHandler final : public blink::WebCanvasCaptureHandler { public: ~CanvasCaptureHandler() override; @@ -127,6 +127,6 @@ DISALLOW_COPY_AND_ASSIGN(CanvasCaptureHandler); }; -} // namespace content +} // namespace blink -#endif // CONTENT_RENDERER_MEDIA_CAPTURE_FROM_ELEMENT_CANVAS_CAPTURE_HANDLER_H_ +#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIACAPTUREFROMELEMENT_CANVAS_CAPTURE_HANDLER_H_
diff --git a/content/renderer/media_capture_from_element/canvas_capture_handler_unittest.cc b/third_party/blink/renderer/modules/mediacapturefromelement/canvas_capture_handler_unittest.cc similarity index 91% rename from content/renderer/media_capture_from_element/canvas_capture_handler_unittest.cc rename to third_party/blink/renderer/modules/mediacapturefromelement/canvas_capture_handler_unittest.cc index b59f4b4..a0445aa 100644 --- a/content/renderer/media_capture_from_element/canvas_capture_handler_unittest.cc +++ b/third_party/blink/renderer/modules/mediacapturefromelement/canvas_capture_handler_unittest.cc
@@ -2,12 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "content/renderer/media_capture_from_element/canvas_capture_handler.h" +#include "third_party/blink/renderer/modules/mediacapturefromelement/canvas_capture_handler.h" #include "base/bind.h" #include "base/run_loop.h" -#include "base/test/scoped_task_environment.h" -#include "content/child/child_process.h" #include "media/base/limits.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -17,6 +15,7 @@ #include "third_party/blink/public/platform/web_size.h" #include "third_party/blink/public/web/modules/mediastream/media_stream_video_capturer_source.h" #include "third_party/blink/public/web/web_heap.h" +#include "third_party/blink/renderer/platform/testing/io_task_runner_testing_platform_support.h" #include "third_party/skia/include/core/SkImage.h" #include "third_party/skia/include/core/SkRefCnt.h" @@ -27,7 +26,7 @@ using ::testing::Test; using ::testing::TestWithParam; -namespace content { +namespace blink { namespace { @@ -49,9 +48,7 @@ class CanvasCaptureHandlerTest : public TestWithParam<testing::tuple<bool, int, int>> { public: - CanvasCaptureHandlerTest() - : scoped_task_environment_( - base::test::ScopedTaskEnvironment::MainThreadType::UI) {} + CanvasCaptureHandlerTest() = default; void SetUp() override { canvas_capture_handler_ = CanvasCaptureHandler::CreateCanvasCaptureHandler( @@ -131,11 +128,7 @@ return ms_source->GetSourceForTesting(); } - // A ChildProcess is needed to fool the Tracks and Sources believing they are - // on the right threads. A ScopedTaskEnvironment must be instantiated before - // ChildProcess to prevent it from leaking a ThreadPool. - base::test::ScopedTaskEnvironment scoped_task_environment_; - ChildProcess child_process_; + ScopedTestingPlatformSupport<IOTaskRunnerTestingPlatformSupport> platform_; private: DISALLOW_COPY_AND_ASSIGN(CanvasCaptureHandlerTest); @@ -190,7 +183,8 @@ params, base::BindRepeating(&CanvasCaptureHandlerTest::OnDeliverFrame, base::Unretained(this)), - base::Bind(&CanvasCaptureHandlerTest::OnRunning, base::Unretained(this))); + base::BindRepeating(&CanvasCaptureHandlerTest::OnRunning, + base::Unretained(this))); canvas_capture_handler_->SendNewFrame( GenerateTestImage(testing::get<0>(GetParam()), testing::get<1>(GetParam()), @@ -247,4 +241,4 @@ ::testing::Values(kTestCanvasCaptureFrameEvenSize, kTestCanvasCaptureFrameOddSize))); -} // namespace content +} // namespace blink
diff --git a/third_party/blink/renderer/modules/mediacapturefromelement/html_canvas_element_capture.cc b/third_party/blink/renderer/modules/mediacapturefromelement/html_canvas_element_capture.cc index c4ca120..8097c9115 100644 --- a/third_party/blink/renderer/modules/mediacapturefromelement/html_canvas_element_capture.cc +++ b/third_party/blink/renderer/modules/mediacapturefromelement/html_canvas_element_capture.cc
@@ -6,10 +6,10 @@ #include <memory> #include "third_party/blink/public/platform/platform.h" -#include "third_party/blink/public/platform/web_canvas_capture_handler.h" #include "third_party/blink/public/platform/web_media_stream.h" #include "third_party/blink/public/platform/web_media_stream_track.h" #include "third_party/blink/renderer/core/html/canvas/html_canvas_element.h" +#include "third_party/blink/renderer/modules/mediacapturefromelement/canvas_capture_handler.h" #include "third_party/blink/renderer/modules/mediacapturefromelement/canvas_capture_media_stream_track.h" #include "third_party/blink/renderer/modules/mediastream/media_stream.h" @@ -57,11 +57,12 @@ const WebSize size(element.width(), element.height()); std::unique_ptr<WebCanvasCaptureHandler> handler; if (given_frame_rate) { - handler = Platform::Current()->CreateCanvasCaptureHandler(size, frame_rate, - &track); + handler = CanvasCaptureHandler::CreateCanvasCaptureHandler( + size, frame_rate, Platform::Current()->GetIOTaskRunner(), &track); } else { - handler = Platform::Current()->CreateCanvasCaptureHandler( - size, kDefaultFrameRate, &track); + handler = CanvasCaptureHandler::CreateCanvasCaptureHandler( + size, kDefaultFrameRate, Platform::Current()->GetIOTaskRunner(), + &track); } if (!handler) {
diff --git a/third_party/blink/renderer/modules/mediastream/media_stream_video_capturer_source_test.cc b/third_party/blink/renderer/modules/mediastream/media_stream_video_capturer_source_test.cc index 36ea3df7..c8b832d 100644 --- a/third_party/blink/renderer/modules/mediastream/media_stream_video_capturer_source_test.cc +++ b/third_party/blink/renderer/modules/mediastream/media_stream_video_capturer_source_test.cc
@@ -21,7 +21,7 @@ #include "third_party/blink/renderer/platform/cross_thread_functional.h" #include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h" #include "third_party/blink/renderer/platform/scheduler/public/thread.h" -#include "third_party/blink/renderer/platform/testing/testing_platform_support.h" +#include "third_party/blink/renderer/platform/testing/io_task_runner_testing_platform_support.h" #include "third_party/blink/renderer/platform/wtf/functional.h" using ::testing::_; @@ -31,19 +31,6 @@ namespace { -class IOTaskRunnerTestingPlatformSupport : public TestingPlatformSupport { - public: - IOTaskRunnerTestingPlatformSupport() - : io_thread_(Thread::CreateThread( - ThreadCreationParams(WebThreadType::kTestThread))) {} - scoped_refptr<base::SingleThreadTaskRunner> GetIOTaskRunner() const override { - return io_thread_->GetTaskRunner(); - } - - private: - std::unique_ptr<Thread> io_thread_; -}; - class MockVideoCapturerSource : public media::VideoCapturerSource { public: MockVideoCapturerSource() {}
diff --git a/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_stream_impl.cc b/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_stream_impl.cc index f2a2371..f0b6250 100644 --- a/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_stream_impl.cc +++ b/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_stream_impl.cc
@@ -25,7 +25,9 @@ quic::QuicSession* session, uint32_t delegate_read_buffer_size, uint32_t write_buffer_size) - : quic::QuicStream(std::move(pending), quic::BIDIRECTIONAL), + : quic::QuicStream(std::move(pending), + quic::BIDIRECTIONAL, + /*is_static=*/false), delegate_read_buffer_size_(delegate_read_buffer_size), write_buffer_size_(write_buffer_size) { DCHECK_GT(delegate_read_buffer_size_, 0u);
diff --git a/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_transport_test.cc b/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_transport_test.cc index 1ed70eb..7a08f57 100644 --- a/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_transport_test.cc +++ b/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_transport_test.cc
@@ -804,14 +804,14 @@ // Start the handshake with the remote fingerprints. std::vector<std::unique_ptr<rtc::SSLFingerprint>> server_fingerprints; - server_fingerprints.emplace_back(rtc::SSLFingerprint::Create( - "sha-256", server_peer()->certificate()->identity())); + server_fingerprints.push_back(rtc::SSLFingerprint::CreateUnique( + "sha-256", *server_peer()->certificate()->identity())); server_peer()->quic_transport()->Start( P2PQuicTransport::StartConfig(std::move(server_fingerprints))); std::vector<std::unique_ptr<rtc::SSLFingerprint>> client_fingerprints; - client_fingerprints.emplace_back(rtc::SSLFingerprint::Create( - "sha-256", client_peer()->certificate()->identity())); + client_fingerprints.push_back(rtc::SSLFingerprint::CreateUnique( + "sha-256", *client_peer()->certificate()->identity())); client_peer()->quic_transport()->Start( P2PQuicTransport::StartConfig(std::move(client_fingerprints)));
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_quic_transport.cc b/third_party/blink/renderer/modules/peerconnection/rtc_quic_transport.cc index 5b944b10..ca7c422 100644 --- a/third_party/blink/renderer/modules/peerconnection/rtc_quic_transport.cc +++ b/third_party/blink/renderer/modules/peerconnection/rtc_quic_transport.cc
@@ -265,8 +265,8 @@ const RTCDtlsFingerprint* dtls_fingerprint) { std::string algorithm = WebString(dtls_fingerprint->algorithm()).Utf8(); std::string value = WebString(dtls_fingerprint->value()).Utf8(); - std::unique_ptr<rtc::SSLFingerprint> rtc_fingerprint( - rtc::SSLFingerprint::CreateFromRfc4572(algorithm, value)); + std::unique_ptr<rtc::SSLFingerprint> rtc_fingerprint = + rtc::SSLFingerprint::CreateUniqueFromRfc4572(algorithm, value); DCHECK(rtc_fingerprint); return rtc_fingerprint; }
diff --git a/third_party/blink/renderer/platform/BUILD.gn b/third_party/blink/renderer/platform/BUILD.gn index 208e7f3..97ea3d35b 100644 --- a/third_party/blink/renderer/platform/BUILD.gn +++ b/third_party/blink/renderer/platform/BUILD.gn
@@ -1581,6 +1581,8 @@ "testing/fuzzed_data_provider.h", "testing/histogram_tester.cc", "testing/histogram_tester.h", + "testing/io_task_runner_testing_platform_support.cc", + "testing/io_task_runner_testing_platform_support.h", "testing/layer_tree_host_embedder.cc", "testing/layer_tree_host_embedder.h", "testing/message_loop_for_mojo.h",
diff --git a/third_party/blink/renderer/platform/animation/timing_function.cc b/third_party/blink/renderer/platform/animation/timing_function.cc index faeecda..72140b7 100644 --- a/third_party/blink/renderer/platform/animation/timing_function.cc +++ b/third_party/blink/renderer/platform/animation/timing_function.cc
@@ -135,27 +135,6 @@ return steps_->Clone(); } -String FramesTimingFunction::ToString() const { - StringBuilder builder; - builder.Append("frames("); - builder.Append(String::NumberToStringECMAScript(this->NumberOfFrames())); - builder.Append(")"); - return builder.ToString(); -} - -void FramesTimingFunction::Range(double* min_value, double* max_value) const { - *min_value = 0; - *max_value = 1; -} - -double FramesTimingFunction::Evaluate(double fraction, double) const { - return frames_->GetPreciseValue(fraction); -} - -std::unique_ptr<cc::TimingFunction> FramesTimingFunction::CloneToCC() const { - return frames_->Clone(); -} - scoped_refptr<TimingFunction> CreateCompositorTimingFunctionFromCC( const cc::TimingFunction* timing_function) { if (!timing_function) @@ -217,14 +196,6 @@ (lhs.GetStepPosition() == stf.GetStepPosition()); } -bool operator==(const FramesTimingFunction& lhs, const TimingFunction& rhs) { - if (rhs.GetType() != TimingFunction::Type::FRAMES) - return false; - - const FramesTimingFunction& ftf = ToFramesTimingFunction(rhs); - return lhs.NumberOfFrames() == ftf.NumberOfFrames(); -} - // The generic operator== *must* come after the // non-generic operator== otherwise it will end up calling itself. bool operator==(const TimingFunction& lhs, const TimingFunction& rhs) { @@ -241,10 +212,6 @@ const StepsTimingFunction& step = ToStepsTimingFunction(lhs); return (step == rhs); } - case TimingFunction::Type::FRAMES: { - const FramesTimingFunction& frame = ToFramesTimingFunction(lhs); - return (frame == rhs); - } default: NOTREACHED(); }
diff --git a/third_party/blink/renderer/platform/animation/timing_function.h b/third_party/blink/renderer/platform/animation/timing_function.h index 7ce54ce2..0923cb3 100644 --- a/third_party/blink/renderer/platform/animation/timing_function.h +++ b/third_party/blink/renderer/platform/animation/timing_function.h
@@ -192,32 +192,6 @@ std::unique_ptr<cc::StepsTimingFunction> steps_; }; -class PLATFORM_EXPORT FramesTimingFunction final : public TimingFunction { - public: - static scoped_refptr<FramesTimingFunction> Create(int frames) { - return base::AdoptRef(new FramesTimingFunction(frames)); - } - - ~FramesTimingFunction() override = default; - - // TimingFunction implementation. - String ToString() const override; - double Evaluate(double fraction, double) const override; - void Range(double* min_value, double* max_value) const override; - std::unique_ptr<cc::TimingFunction> CloneToCC() const override; - - int NumberOfFrames() const { return frames_->frames(); } - - private: - FramesTimingFunction(int frames) - : TimingFunction(Type::FRAMES), - frames_(cc::FramesTimingFunction::Create(frames)) { - DCHECK(RuntimeEnabledFeatures::FramesTimingFunctionEnabled()); - } - - std::unique_ptr<cc::FramesTimingFunction> frames_; -}; - PLATFORM_EXPORT scoped_refptr<TimingFunction> CreateCompositorTimingFunctionFromCC(const cc::TimingFunction*); @@ -227,8 +201,6 @@ const TimingFunction&); PLATFORM_EXPORT bool operator==(const StepsTimingFunction&, const TimingFunction&); -PLATFORM_EXPORT bool operator==(const FramesTimingFunction&, - const TimingFunction&); PLATFORM_EXPORT bool operator==(const TimingFunction&, const TimingFunction&); PLATFORM_EXPORT bool operator!=(const TimingFunction&, const TimingFunction&); @@ -241,7 +213,6 @@ DEFINE_TIMING_FUNCTION_TYPE_CASTS(Linear, LINEAR); DEFINE_TIMING_FUNCTION_TYPE_CASTS(CubicBezier, CUBIC_BEZIER); DEFINE_TIMING_FUNCTION_TYPE_CASTS(Steps, STEPS); -DEFINE_TIMING_FUNCTION_TYPE_CASTS(Frames, FRAMES); } // namespace blink
diff --git a/third_party/blink/renderer/platform/animation/timing_function_test.cc b/third_party/blink/renderer/platform/animation/timing_function_test.cc index 128fac8..f278e98 100644 --- a/third_party/blink/renderer/platform/animation/timing_function_test.cc +++ b/third_party/blink/renderer/platform/animation/timing_function_test.cc
@@ -50,10 +50,9 @@ namespace { -class TimingFunctionTest : public testing::Test, - private ScopedFramesTimingFunctionForTest { +class TimingFunctionTest : public testing::Test { public: - TimingFunctionTest() : ScopedFramesTimingFunctionForTest(true) {} + TimingFunctionTest() {} void NotEqualHelperLoop( Vector<std::pair<std::string, scoped_refptr<TimingFunction>>>& v) { @@ -114,11 +113,6 @@ EXPECT_EQ("steps(5)", step_timing_custom_end->ToString()); } -TEST_F(TimingFunctionTest, FrameToString) { - scoped_refptr<TimingFunction> frame_timing = FramesTimingFunction::Create(3); - EXPECT_EQ("frames(3)", frame_timing->ToString()); -} - TEST_F(TimingFunctionTest, BaseOperatorEq) { scoped_refptr<TimingFunction> linear_timing = LinearTimingFunction::Shared(); scoped_refptr<TimingFunction> cubic_timing1 = @@ -130,7 +124,6 @@ StepsTimingFunction::Preset(StepsTimingFunction::StepPosition::END); scoped_refptr<TimingFunction> steps_timing2 = StepsTimingFunction::Create(5, StepsTimingFunction::StepPosition::START); - scoped_refptr<TimingFunction> frames_timing = FramesTimingFunction::Create(5); Vector<std::pair<std::string, scoped_refptr<TimingFunction>>> v; v.push_back(std::make_pair("linearTiming", linear_timing)); @@ -138,7 +131,6 @@ v.push_back(std::make_pair("cubicTiming2", cubic_timing2)); v.push_back(std::make_pair("stepsTiming1", steps_timing1)); v.push_back(std::make_pair("stepsTiming2", steps_timing2)); - v.push_back(std::make_pair("framesTiming", frames_timing)); NotEqualHelperLoop(v); } @@ -258,21 +250,6 @@ EXPECT_EQ(*steps_b, *steps_a); } -TEST_F(TimingFunctionTest, FramesOperatorEq) { - scoped_refptr<TimingFunction> frames_timing1 = - FramesTimingFunction::Create(5); - scoped_refptr<TimingFunction> frames_timing2 = - FramesTimingFunction::Create(7); - - EXPECT_EQ(*FramesTimingFunction::Create(5), *frames_timing1); - EXPECT_EQ(*FramesTimingFunction::Create(7), *frames_timing2); - - Vector<std::pair<std::string, scoped_refptr<TimingFunction>>> v; - v.push_back(std::make_pair("framesTiming1", frames_timing1)); - v.push_back(std::make_pair("framesTiming2", frames_timing2)); - NotEqualHelperLoop(v); -} - TEST_F(TimingFunctionTest, LinearEvaluate) { scoped_refptr<TimingFunction> linear_timing = LinearTimingFunction::Shared(); EXPECT_EQ(0.2, linear_timing->Evaluate(0.2, 0)); @@ -311,21 +288,6 @@ EXPECT_NEAR(1, end, 0.01); } -TEST_F(TimingFunctionTest, FrameRange) { - double start = 0; - double end = 1; - scoped_refptr<TimingFunction> frames = FramesTimingFunction::Create(4); - frames->Range(&start, &end); - EXPECT_NEAR(0, start, 0.01); - EXPECT_NEAR(1, end, 0.01); - - start = -1; - end = 10; - frames->Range(&start, &end); - EXPECT_NEAR(0, start, 0.01); - EXPECT_NEAR(1, end, 0.01); -} - TEST_F(TimingFunctionTest, CubicRange) { double start = 0; double end = 1; @@ -497,22 +459,6 @@ EXPECT_EQ(2.00, steps_timing_custom_end->Evaluate(2.00, 0)); } -TEST_F(TimingFunctionTest, FramesEvaluate) { - scoped_refptr<TimingFunction> frames_timing = FramesTimingFunction::Create(5); - EXPECT_EQ(-2.50, frames_timing->Evaluate(-2.00, 0)); - EXPECT_EQ(0.00, frames_timing->Evaluate(0.00, 0)); - EXPECT_EQ(0.00, frames_timing->Evaluate(0.19, 0)); - EXPECT_EQ(0.25, frames_timing->Evaluate(0.20, 0)); - EXPECT_EQ(0.25, frames_timing->Evaluate(0.39, 0)); - EXPECT_EQ(0.50, frames_timing->Evaluate(0.40, 0)); - EXPECT_EQ(0.50, frames_timing->Evaluate(0.59, 0)); - EXPECT_EQ(0.75, frames_timing->Evaluate(0.60, 0)); - EXPECT_EQ(0.75, frames_timing->Evaluate(0.79, 0)); - EXPECT_EQ(1.00, frames_timing->Evaluate(0.80, 0)); - EXPECT_EQ(1.00, frames_timing->Evaluate(1.00, 0)); - EXPECT_EQ(3.75, frames_timing->Evaluate(3.00, 0)); -} - } // namespace } // namespace blink
diff --git a/third_party/blink/renderer/platform/exported/platform.cc b/third_party/blink/renderer/platform/exported/platform.cc index df15215a..1a373d0 100644 --- a/third_party/blink/renderer/platform/exported/platform.cc +++ b/third_party/blink/renderer/platform/exported/platform.cc
@@ -40,7 +40,6 @@ #include "services/service_manager/public/cpp/interface_provider.h" #include "third_party/blink/public/platform/interface_provider.h" #include "third_party/blink/public/platform/scheduler/web_thread_scheduler.h" -#include "third_party/blink/public/platform/web_canvas_capture_handler.h" #include "third_party/blink/public/platform/web_graphics_context_3d_provider.h" #include "third_party/blink/public/platform/web_media_recorder_handler.h" #include "third_party/blink/public/platform/web_media_stream_center.h" @@ -334,13 +333,6 @@ return nullptr; } -std::unique_ptr<WebCanvasCaptureHandler> Platform::CreateCanvasCaptureHandler( - const WebSize&, - double, - WebMediaStreamTrack*) { - return nullptr; -} - std::unique_ptr<webrtc::RtpCapabilities> Platform::GetRtpSenderCapabilities( const WebString& kind) { return nullptr;
diff --git a/third_party/blink/renderer/platform/graphics/graphics_layer.cc b/third_party/blink/renderer/platform/graphics/graphics_layer.cc index 48cf52e..6578103 100644 --- a/third_party/blink/renderer/platform/graphics/graphics_layer.cc +++ b/third_party/blink/renderer/platform/graphics/graphics_layer.cc
@@ -259,7 +259,7 @@ !RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) { CcLayer()->RemoveFromParent(); } else { - SetPaintArtifactCompositorNeedsUpdate(); + client_.GraphicsLayersDidChange(); } } @@ -323,10 +323,12 @@ return false; #endif - if (PaintWithoutCommit(disabled_mode)) + if (PaintWithoutCommit(disabled_mode)) { GetPaintController().CommitNewDisplayItems(); - else if (!needs_check_raster_invalidation_) + UpdateSafeOpaqueBackgroundColor(); + } else if (!needs_check_raster_invalidation_) { return false; + } #if DCHECK_IS_ON() if (VLOG_IS_ON(2)) { @@ -360,6 +362,15 @@ return true; } +void GraphicsLayer::UpdateSafeOpaqueBackgroundColor() { + if (!DrawsContent()) + return; + // Copy the first chunk's safe opaque background color over to the cc::Layer. + const auto& chunks = GetPaintController().GetPaintArtifact().PaintChunks(); + CcLayer()->SetSafeOpaqueBackgroundColor( + chunks.size() ? chunks[0].safe_opaque_background_color : SK_ColorWHITE); +} + bool GraphicsLayer::PaintWithoutCommitForTesting( const base::Optional<IntRect>& interest_rect) { return PaintWithoutCommit(GraphicsContext::kNothingDisabled, @@ -403,7 +414,7 @@ // When using layer lists, cc::Layers are created in PaintArtifactCompositor. if (RuntimeEnabledFeatures::BlinkGenPropertyTreesEnabled() || RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) { - SetPaintArtifactCompositorNeedsUpdate(); + client_.GraphicsLayersDidChange(); return; } @@ -740,10 +751,6 @@ UpdateLayerIsDrawable(); } -void GraphicsLayer::SetPaintArtifactCompositorNeedsUpdate() const { - client_.SetPaintArtifactCompositorNeedsUpdate(); -} - void GraphicsLayer::SetClipParent(cc::Layer* parent) { has_clip_parent_ = !!parent; CcLayer()->SetClipParent(parent); @@ -876,6 +883,7 @@ contents_rect_ = rect; UpdateContentsRect(); + client_.GraphicsLayersDidChange(); } void GraphicsLayer::SetContentsToImage( @@ -1055,7 +1063,7 @@ } if (RuntimeEnabledFeatures::BlinkGenPropertyTreesEnabled()) - SetPaintArtifactCompositorNeedsUpdate(); + client_.GraphicsLayersDidChange(); } void GraphicsLayer::SetContentsPropertyTreeState( @@ -1063,11 +1071,15 @@ DCHECK(ContentsLayer()); if (contents_property_tree_state_) { + if (*contents_property_tree_state_ == layer_state) + return; *contents_property_tree_state_ = layer_state; } else { contents_property_tree_state_ = std::make_unique<PropertyTreeState>(layer_state); } + if (RuntimeEnabledFeatures::BlinkGenPropertyTreesEnabled()) + client_.GraphicsLayersDidChange(); } scoped_refptr<cc::DisplayItemList> GraphicsLayer::PaintContentsToDisplayList(
diff --git a/third_party/blink/renderer/platform/graphics/graphics_layer.h b/third_party/blink/renderer/platform/graphics/graphics_layer.h index 05b8c15..e4a9c8fe 100644 --- a/third_party/blink/renderer/platform/graphics/graphics_layer.h +++ b/third_party/blink/renderer/platform/graphics/graphics_layer.h
@@ -171,8 +171,6 @@ void SetScrollParent(cc::Layer*); void SetClipParent(cc::Layer*); - void SetPaintArtifactCompositorNeedsUpdate() const; - // For special cases, e.g. drawing missing tiles on Android. // The compositor should never paint this color in normal cases because the // Layer will paint the background by itself. @@ -333,6 +331,7 @@ size_t GetApproximateUnsharedMemoryUsage() const final; void PaintRecursivelyInternal(Vector<GraphicsLayer*>& repainted_layers); + void UpdateSafeOpaqueBackgroundColor(); // Returns true if PaintController::PaintArtifact() changed and needs commit. bool PaintWithoutCommit(
diff --git a/third_party/blink/renderer/platform/graphics/graphics_layer_client.h b/third_party/blink/renderer/platform/graphics/graphics_layer_client.h index 83bc60b3..13f871f 100644 --- a/third_party/blink/renderer/platform/graphics/graphics_layer_client.h +++ b/third_party/blink/renderer/platform/graphics/graphics_layer_client.h
@@ -96,7 +96,7 @@ virtual void SetOverlayScrollbarsHidden(bool) {} - virtual void SetPaintArtifactCompositorNeedsUpdate() const {} + virtual void GraphicsLayersDidChange() {} virtual String DebugName(const GraphicsLayer*) const = 0;
diff --git a/third_party/blink/renderer/platform/graphics/paint/README.md b/third_party/blink/renderer/platform/graphics/paint/README.md index 2f2163bc..6d367c9d 100644 --- a/third_party/blink/renderer/platform/graphics/paint/README.md +++ b/third_party/blink/renderer/platform/graphics/paint/README.md
@@ -1,26 +1,27 @@ +<!--- + The live version of this document can be viewed at: + https://chromium.googlesource.com/chromium/src/+/master/third_party/blink/renderer/platform/graphics/paint/README.md +--> + # Platform paint code This directory contains the implementation of display lists and display list-based painting, except for code which requires knowledge of `core/` concepts, such as DOM elements and layout objects. -This code is owned by the [paint team][paint-team-site]. +For information about how the display list and paint property trees are +generated, see [the core paint README file](../../../core/paint/README.md). -CompositeAfterPaint is currently being implemented. Unlike Slimming Paint v1, -CompositeAfterPaint represents its paint artifact not as a flat display list, -but as a list of drawings, and a list of paint chunks, stored together. +This code is owned by the [rendering team](https://www.chromium.org/teams/rendering). -This document explains the CompositeAfterPaint (CAP) world as it develops, not -the SPv1 world it replaces. - -[paint-team-site]: https://www.chromium.org/teams/paint-team +[TOC] ## Paint artifact -The CAP [paint artifact](paint_artifact.h) consists of a list of display items -in paint order (ideally mostly or all drawings), partitioned into *paint chunks* -which define certain *paint properties* which affect how the content should be -drawn or composited. +The CompositeAfterPaint [paint artifact](paint_artifact.h) consists of a list of +display items in paint order (ideally mostly or all drawings), partitioned into +*paint chunks* which define certain *paint properties* which affect how the +content should be drawn or composited. ## Paint properties @@ -59,7 +60,7 @@ rendering context ID should sort together * other fields, see [the header file](transform_paint_property_node.h) -***promo +*** note The painting system may create transform nodes which don't affect the position of points in the xy-plane, but which have an apparent effect only when multiplied with other transformation matrices. In particular, a transform node @@ -222,7 +223,7 @@ It's done in two levels: -* Paint chunk level (`RasterInvalidator`](raster_invalidator.h): matches each +* Paint chunk level [`RasterInvalidator`](raster_invalidator.h): matches each paint chunk in the current paint artifact against the corresponding paint chunk in the previous paint artifact, by matching their ids. There are following cases: @@ -252,7 +253,7 @@ * Otherwise, check for changed display items within the paint chunk. -* Display item level (`DisplayItemRasterInvalidator`](display_item_raster_invalidator.h]: +* Display item level [`DisplayItemRasterInvalidator`](display_item_raster_invalidator.h): This is executed when a new chunk matches an old chunk in-order and paint properties didn't change. The algorithm checks changed display items within a paint chunk.
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5 index 2ca0c4b..9eaac54 100644 --- a/third_party/blink/renderer/platform/runtime_enabled_features.json5 +++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -604,10 +604,6 @@ name: "FractionalScrollOffsets", }, { - name: "FramesTimingFunction", - status: "experimental", - }, - { name: "FreezeFramesOnVisibility", status: "experimental", },
diff --git a/third_party/blink/renderer/platform/testing/io_task_runner_testing_platform_support.cc b/third_party/blink/renderer/platform/testing/io_task_runner_testing_platform_support.cc new file mode 100644 index 0000000..15bee95 --- /dev/null +++ b/third_party/blink/renderer/platform/testing/io_task_runner_testing_platform_support.cc
@@ -0,0 +1,21 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "third_party/blink/renderer/platform/testing/io_task_runner_testing_platform_support.h" + +#include "base/single_thread_task_runner.h" +#include "third_party/blink/renderer/platform/scheduler/public/thread.h" + +namespace blink { + +IOTaskRunnerTestingPlatformSupport::IOTaskRunnerTestingPlatformSupport() + : io_thread_(Thread::CreateThread( + ThreadCreationParams(WebThreadType::kTestThread))) {} + +scoped_refptr<base::SingleThreadTaskRunner> +IOTaskRunnerTestingPlatformSupport::GetIOTaskRunner() const { + return io_thread_->GetTaskRunner(); +} + +} // namespace blink
diff --git a/third_party/blink/renderer/platform/testing/io_task_runner_testing_platform_support.h b/third_party/blink/renderer/platform/testing/io_task_runner_testing_platform_support.h new file mode 100644 index 0000000..eede793f2 --- /dev/null +++ b/third_party/blink/renderer/platform/testing/io_task_runner_testing_platform_support.h
@@ -0,0 +1,32 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_TESTING_IO_TASK_RUNNER_TESTING_PLATFORM_SUPPORT_H_ +#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_TESTING_IO_TASK_RUNNER_TESTING_PLATFORM_SUPPORT_H_ + +#include "third_party/blink/renderer/platform/testing/testing_platform_support.h" + +#include "base/memory/scoped_refptr.h" + +namespace base { +class SingleThreadTaskRunner; +} + +namespace blink { + +class Thread; + +class IOTaskRunnerTestingPlatformSupport : public TestingPlatformSupport { + public: + IOTaskRunnerTestingPlatformSupport(); + + scoped_refptr<base::SingleThreadTaskRunner> GetIOTaskRunner() const override; + + private: + std::unique_ptr<Thread> io_thread_; +}; + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_TESTING_IO_TASK_RUNNER_TESTING_PLATFORM_SUPPORT_H_
diff --git a/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py b/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py index b859300..0dfea7d 100755 --- a/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py +++ b/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py
@@ -184,6 +184,7 @@ 'base::RandGenerator', 'base::RandDouble', 'base::RandBytes', + 'base::RandBytesAsString', # Feature list checking. 'base::Feature.*', @@ -550,6 +551,15 @@ }, { 'paths': [ + 'third_party/blink/renderer/modules/mediacapturefromelement/', + ], + 'allowed': [ + 'media::.+', + 'libyuv::.+', + ] + }, + { + 'paths': [ 'third_party/blink/renderer/modules/mediastream/', ], 'allowed': [
diff --git a/third_party/blink/web_tests/MSANExpectations b/third_party/blink/web_tests/MSANExpectations index 79cce992..26e643b0 100644 --- a/third_party/blink/web_tests/MSANExpectations +++ b/third_party/blink/web_tests/MSANExpectations
@@ -108,7 +108,7 @@ crbug.com/856601 [ Linux ] fast/css/visited-link-hang.html [ Pass Timeout ] crbug.com/856601 [ Linux ] http/tests/devtools/elements/styles-4/styles-inline-element-style-changes-should-not-force-style-recalc.js [ Pass Timeout ] -crbug.com/856601 [ Linux ] external/wpt/event-timing/event-timing-retrievability.html [ Pass Timeout ] +crbug.com/856601 [ Linux ] external/wpt/event-timing/retrievability.html [ Pass Timeout ] # Slow idlharness.js tests on MSAN crbug.com/856601 [ Linux ] external/wpt/BackgroundSync/interfaces.https.any.html [ Timeout Pass ]
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations index 873e025..7c86f4b 100644 --- a/third_party/blink/web_tests/TestExpectations +++ b/third_party/blink/web_tests/TestExpectations
@@ -2666,8 +2666,8 @@ # Skip the non-virtualized CORS-RFC1918 tests: crbug.com/763830 http/tests/security/cors-rfc1918/ [ Skip ] -crbug.com/831729 external/wpt/event-timing/event-timing-crossiframe.html [ Timeout ] -crbug.com/831729 external/wpt/event-timing/event-timing-observer-manual.html [ Skip ] +crbug.com/831729 external/wpt/event-timing/crossiframe.html [ Timeout ] +crbug.com/831729 external/wpt/event-timing/observer-manual.html [ Skip ] # Working on getting the CSP tests going: crbug.com/694525 external/wpt/content-security-policy/connect-src/worker-from-guid.sub.html [ Skip ] @@ -3076,9 +3076,9 @@ crbug.com/626703 external/wpt/html/semantics/embedded-content/media-elements/src_object_blob.html [ Timeout ] crbug.com/626703 external/wpt/css/css-lists/list-item-definition.html [ Failure ] crbug.com/626703 external/wpt/html/semantics/forms/the-textarea-element/multiline-placeholder-cr.html [ Failure ] -crbug.com/626703 [ Mac10.10 ] external/wpt/event-timing/event-timing-onloadthenobserve.html [ Timeout ] -crbug.com/626703 [ Mac10.11 ] external/wpt/event-timing/event-timing-onloadthenobserve.html [ Timeout ] -crbug.com/626703 [ Win7 ] external/wpt/event-timing/event-timing-onloadthenobserve.html [ Timeout ] +crbug.com/626703 [ Mac10.10 ] external/wpt/event-timing/onloadthenobserve.html [ Timeout ] +crbug.com/626703 [ Mac10.11 ] external/wpt/event-timing/onloadthenobserve.html [ Timeout ] +crbug.com/626703 [ Win7 ] external/wpt/event-timing/onloadthenobserve.html [ Timeout ] crbug.com/626703 [ Win7 ] external/wpt/webrtc/RTCPeerConnection-ondatachannel.html [ Failure Timeout ] crbug.com/626703 [ Mac10.10 ] external/wpt/content-security-policy/frame-ancestors/frame-ancestors-nested-cross-in-same-url-allow.html [ Timeout ] crbug.com/626703 [ Mac10.12 ] external/wpt/content-security-policy/frame-ancestors/frame-ancestors-nested-cross-in-same-url-allow.html [ Timeout ]
diff --git a/third_party/blink/web_tests/animations/animations-parsing-002.html b/third_party/blink/web_tests/animations/animations-parsing-002.html index 6e87fc41..2dc20fbb6 100644 --- a/third_party/blink/web_tests/animations/animations-parsing-002.html +++ b/third_party/blink/web_tests/animations/animations-parsing-002.html
@@ -125,12 +125,6 @@ assert_equals(style.webkitAnimationTimingFunction, 'steps(5, start)'); assert_equals(computedStyle.webkitAnimationTimingFunction, 'steps(5, start)'); - style.animationTimingFunction = "frames(5)"; - assert_equals(style.animationTimingFunction, 'frames(5)'); - assert_equals(computedStyle.animationTimingFunction, 'frames(5)'); - assert_equals(style.webkitAnimationTimingFunction, 'frames(5)'); - assert_equals(computedStyle.webkitAnimationTimingFunction, 'frames(5)'); - style.animationName = "anim1, anim2"; style.animationTimingFunction = "ease-in-out, ease-in";
diff --git a/third_party/blink/web_tests/animations/timing/timing-functions-expected.txt b/third_party/blink/web_tests/animations/timing/timing-functions-expected.txt index 0ad1749..de06d4c 100644 --- a/third_party/blink/web_tests/animations/timing/timing-functions-expected.txt +++ b/third_party/blink/web_tests/animations/timing/timing-functions-expected.txt
@@ -6,7 +6,6 @@ PASS - "left" property for "box6" element at 0.25s saw something close to: 100 PASS - "left" property for "box7" element at 0.25s saw something close to: 133 PASS - "left" property for "box8" element at 0.25s saw something close to: 100 -PASS - "left" property for "box9" element at 0.25s saw something close to: 100 PASS - "left" property for "box1" element at 0.5s saw something close to: 180 PASS - "left" property for "box2" element at 0.5s saw something close to: 180 PASS - "left" property for "box3" element at 0.5s saw something close to: 150 @@ -15,7 +14,6 @@ PASS - "left" property for "box6" element at 0.5s saw something close to: 133 PASS - "left" property for "box7" element at 0.5s saw something close to: 166 PASS - "left" property for "box8" element at 0.5s saw something close to: 133 -PASS - "left" property for "box9" element at 0.5s saw something close to: 150 PASS - "left" property for "box1" element at 0.75s saw something close to: 196 PASS - "left" property for "box2" element at 0.75s saw something close to: 196 PASS - "left" property for "box3" element at 0.75s saw something close to: 175 @@ -24,5 +22,4 @@ PASS - "left" property for "box6" element at 0.75s saw something close to: 166 PASS - "left" property for "box7" element at 0.75s saw something close to: 200 PASS - "left" property for "box8" element at 0.75s saw something close to: 166 -PASS - "left" property for "box9" element at 0.75s saw something close to: 200
diff --git a/third_party/blink/web_tests/animations/timing/timing-functions.html b/third_party/blink/web_tests/animations/timing/timing-functions.html index 29f035f..6efca1b2 100644 --- a/third_party/blink/web_tests/animations/timing/timing-functions.html +++ b/third_party/blink/web_tests/animations/timing/timing-functions.html
@@ -1,4 +1,4 @@ -<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" +<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html lang="en"> @@ -67,9 +67,6 @@ #box8 { animation-timing-function: steps(3, end); } - #box9 { - animation-timing-function: frames(3); - } </style> <script src="../resources/animation-test-helpers.js" type="text/javascript" charset="utf-8"></script> <script type="text/javascript" charset="utf-8"> @@ -100,9 +97,6 @@ [0.25, "box8", "left", 100, 5], [0.50, "box8", "left", 133, 5], [0.75, "box8", "left", 166, 5], - [0.25, "box9", "left", 100, 5], - [0.50, "box9", "left", 150, 5], - [0.75, "box9", "left", 200, 5], ]; runAnimationTest(expectedValues); @@ -128,8 +122,6 @@ </div> <div class="box" id="box8"> </div> -<div class="box" id="box9"> -</div> <div id="result"> </div> </body>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-timing/frames-timing-functions-syntax.html b/third_party/blink/web_tests/external/wpt/css/css-timing/frames-timing-functions-syntax.html deleted file mode 100644 index 1616bcff..0000000 --- a/third_party/blink/web_tests/external/wpt/css/css-timing/frames-timing-functions-syntax.html +++ /dev/null
@@ -1,31 +0,0 @@ -<!DOCTYPE html> -<meta charset=utf-8> -<meta name="assert" -content="This test checks the syntax output of frame timing functions" /> -<title>Frames timing function syntax tests</title> -<link rel="help" -href="https://drafts.csswg.org/css-timing/#frames-timing-functions"> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<script src="testcommon.js"></script> -<body> -<div id="log"></div> -<script> -"use strict"; - -test(function(t) { - const div = createDiv(t); - div.style.animation = 'abc 1s ease-in'; - div.style.animationTimingFunction = 'frames(1)'; - assert_equals(getComputedStyle(div).animationTimingFunction, 'ease-in'); -}, 'The number of frames must be a positive integer greater than 1, or we ' + - 'fallback to the previously-set easing'); - -test(function(t) { - const div = createDiv(t); - div.style.animation = 'abc 1s frames( 2 )'; - assert_equals(getComputedStyle(div).animationTimingFunction, 'frames(2)'); -}, 'The serialization of frames is \'frames(n)\', n is the number of frames'); - -</script> -</body>
diff --git a/third_party/blink/web_tests/external/wpt/event-timing/event-timing-bufferbeforeonload.html b/third_party/blink/web_tests/external/wpt/event-timing/bufferbeforeonload.html similarity index 98% rename from third_party/blink/web_tests/external/wpt/event-timing/event-timing-bufferbeforeonload.html rename to third_party/blink/web_tests/external/wpt/event-timing/bufferbeforeonload.html index c4be717..c91546a 100644 --- a/third_party/blink/web_tests/external/wpt/event-timing/event-timing-bufferbeforeonload.html +++ b/third_party/blink/web_tests/external/wpt/event-timing/bufferbeforeonload.html
@@ -9,7 +9,7 @@ <script src=/resources/testdriver.js></script> <script src=/resources/testdriver-vendor.js></script> -<script src=resources/event-timing-support.js></script> +<script src=resources/event-timing-test-utils.js></script> <img src=resources/slow-image.py> <script>
diff --git a/third_party/blink/web_tests/external/wpt/event-timing/event-timing-crossiframe.html b/third_party/blink/web_tests/external/wpt/event-timing/crossiframe.html similarity index 95% rename from third_party/blink/web_tests/external/wpt/event-timing/event-timing-crossiframe.html rename to third_party/blink/web_tests/external/wpt/event-timing/crossiframe.html index 4345f9e..c1a27a5 100644 --- a/third_party/blink/web_tests/external/wpt/event-timing/event-timing-crossiframe.html +++ b/third_party/blink/web_tests/external/wpt/event-timing/crossiframe.html
@@ -14,9 +14,9 @@ <script src=/resources/testdriver.js></script> <script src=/resources/testdriver-vendor.js></script> -<script src=resources/event-timing-support.js></script> +<script src=resources/event-timing-test-utils.js></script> <img src=./resources/slow-image.py> -<iframe src=resources/event-timing-crossiframe-childframe.html></iframe> +<iframe src=resources/crossiframe-childframe.html></iframe> <script> let clickTimeMin; let processingStartMin;
diff --git a/third_party/blink/web_tests/external/wpt/event-timing/event-timing-observer-manual.html b/third_party/blink/web_tests/external/wpt/event-timing/observer-manual.html similarity index 94% rename from third_party/blink/web_tests/external/wpt/event-timing/event-timing-observer-manual.html rename to third_party/blink/web_tests/external/wpt/event-timing/observer-manual.html index c0bd6f3..8b5b6ed 100644 --- a/third_party/blink/web_tests/external/wpt/event-timing/event-timing-observer-manual.html +++ b/third_party/blink/web_tests/external/wpt/event-timing/observer-manual.html
@@ -4,7 +4,7 @@ <meta charset=utf-8 /> <title>Event Timing: entries should be observable by its own frame. </title> - <script src=./resources/event-timing-support.js></script> + <script src=./resources/event-timing-test-utils.js></script> </head> <body> <h2>Description:</h2> @@ -37,7 +37,7 @@ </div> <h2>iframe:</h2> <div> - <iframe name='childframe' width="100%" height="30%" src=./resources/event-timing-observer-manual-childframe.html></iframe> + <iframe name='childframe' width="100%" height="30%" src=./resources/observer-manual-childframe.html></iframe> </div> <h2>Timeline:</h2> <p id='timeline'></p>
diff --git a/third_party/blink/web_tests/external/wpt/event-timing/event-timing-observethenonload.html b/third_party/blink/web_tests/external/wpt/event-timing/observethenonload.html similarity index 98% rename from third_party/blink/web_tests/external/wpt/event-timing/event-timing-observethenonload.html rename to third_party/blink/web_tests/external/wpt/event-timing/observethenonload.html index 3a6e849..e1c36e3 100644 --- a/third_party/blink/web_tests/external/wpt/event-timing/event-timing-observethenonload.html +++ b/third_party/blink/web_tests/external/wpt/event-timing/observethenonload.html
@@ -10,7 +10,7 @@ <script src=/resources/testdriver.js></script> <script src=/resources/testdriver-vendor.js></script> -<script src=resources/event-timing-support.js></script> +<script src=resources/event-timing-test-utils.js></script> <img src=resources/slow-image.py> <script>
diff --git a/third_party/blink/web_tests/external/wpt/event-timing/event-timing-onloadthenobserve-firstInput.html b/third_party/blink/web_tests/external/wpt/event-timing/onloadthenobserve-firstInput.html similarity index 97% rename from third_party/blink/web_tests/external/wpt/event-timing/event-timing-onloadthenobserve-firstInput.html rename to third_party/blink/web_tests/external/wpt/event-timing/onloadthenobserve-firstInput.html index e7ac287..1422cea 100644 --- a/third_party/blink/web_tests/external/wpt/event-timing/event-timing-onloadthenobserve-firstInput.html +++ b/third_party/blink/web_tests/external/wpt/event-timing/onloadthenobserve-firstInput.html
@@ -9,7 +9,7 @@ <script src=/resources/testdriver.js></script> <script src=/resources/testdriver-vendor.js></script> -<script src=resources/event-timing-support.js></script> +<script src=resources/event-timing-test-utils.js></script> <script> /* Timeline:
diff --git a/third_party/blink/web_tests/external/wpt/event-timing/event-timing-onloadthenobserve.html b/third_party/blink/web_tests/external/wpt/event-timing/onloadthenobserve.html similarity index 97% rename from third_party/blink/web_tests/external/wpt/event-timing/event-timing-onloadthenobserve.html rename to third_party/blink/web_tests/external/wpt/event-timing/onloadthenobserve.html index e83c290..e2f9c93 100644 --- a/third_party/blink/web_tests/external/wpt/event-timing/event-timing-onloadthenobserve.html +++ b/third_party/blink/web_tests/external/wpt/event-timing/onloadthenobserve.html
@@ -11,7 +11,7 @@ <script src=/resources/testdriver.js></script> <script src=/resources/testdriver-vendor.js></script> -<script src=resources/event-timing-support.js></script> +<script src=resources/event-timing-test-utils.js></script> <script> let callbackTime; let observerStart;
diff --git a/third_party/blink/web_tests/external/wpt/event-timing/event-timing-only-observe-firstInput.html b/third_party/blink/web_tests/external/wpt/event-timing/only-observe-firstInput.html similarity index 96% rename from third_party/blink/web_tests/external/wpt/event-timing/event-timing-only-observe-firstInput.html rename to third_party/blink/web_tests/external/wpt/event-timing/only-observe-firstInput.html index 2ab4894..dd6a18e 100644 --- a/third_party/blink/web_tests/external/wpt/event-timing/event-timing-only-observe-firstInput.html +++ b/third_party/blink/web_tests/external/wpt/event-timing/only-observe-firstInput.html
@@ -8,7 +8,7 @@ <script src=/resources/testdriver.js></script> <script src=/resources/testdriver-vendor.js></script> -<script src=resources/event-timing-support.js></script> +<script src=resources/event-timing-test-utils.js></script> <script> /* Test:
diff --git a/third_party/blink/web_tests/external/wpt/event-timing/programmatic-click-not-observed.html b/third_party/blink/web_tests/external/wpt/event-timing/programmatic-click-not-observed.html new file mode 100644 index 0000000..1324a17 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/event-timing/programmatic-click-not-observed.html
@@ -0,0 +1,39 @@ +<!DOCTYPE html> +<html> +<meta charset=utf-8 /> +<div id='div' onclick='delay()'>Click me</div> +<div id='div2'>No, click me!</div> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<script src=/resources/testdriver.js></script> +<script src=/resources/testdriver-vendor.js></script> + +<script src=resources/event-timing-support.js></script> +<script> + let delayCalled = false; + let beforeClick; + function delay() { + const end = performance.now() + 150; + while(performance.now() < end) {} + delayCalled = true; + } + async_test(function(t) { + const observer = new PerformanceObserver(t.step_func_done((entryList) => { + const entries = entryList.getEntries().filter(e => e.name === 'click'); + // There must only be one click entry: from the clickAndBlockMain() call. + assert_equals(entries.length, 1); + const entry = entries[0]; + // This ensures that the entry is exposing timing from the second click, i.e. + // the one from the clickAndBlockMain() call. + assert_greater_than_equal(entry.processingStart, beforeClick); + })); + observer.observe({entryTypes: ['firstInput', 'event']}); + document.getElementById('div').click(); + // Take the timestamp after the programmatic click but before the next click. + beforeClick = performance.now(); + // After the programmatic click, use another input to know when entries have been + // dispatched to the PerformanceObserver callback. + clickAndBlockMain('div2'); + }, "Event Timing: events from programmatic click are not observed"); +</script> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/event-timing/resources/event-timing-crossiframe-childframe.html b/third_party/blink/web_tests/external/wpt/event-timing/resources/crossiframe-childframe.html similarity index 95% rename from third_party/blink/web_tests/external/wpt/event-timing/resources/event-timing-crossiframe-childframe.html rename to third_party/blink/web_tests/external/wpt/event-timing/resources/crossiframe-childframe.html index b0fbdeb4..7aa4ace 100644 --- a/third_party/blink/web_tests/external/wpt/event-timing/resources/event-timing-crossiframe-childframe.html +++ b/third_party/blink/web_tests/external/wpt/event-timing/resources/crossiframe-childframe.html
@@ -1,6 +1,6 @@ <!DOCType html> <html> -<script src=event-timing-support.js></script> +<script src=event-timing-test-utils.js></script> <button id='button_child_frame'>Generate a 'click' event</button> <img src=slow-image.py> <script>
diff --git a/third_party/blink/web_tests/external/wpt/event-timing/resources/event-timing-support.js b/third_party/blink/web_tests/external/wpt/event-timing/resources/event-timing-test-utils.js similarity index 100% rename from third_party/blink/web_tests/external/wpt/event-timing/resources/event-timing-support.js rename to third_party/blink/web_tests/external/wpt/event-timing/resources/event-timing-test-utils.js
diff --git a/third_party/blink/web_tests/external/wpt/event-timing/resources/event-timing-observer-manual-childframe.html b/third_party/blink/web_tests/external/wpt/event-timing/resources/observer-manual-childframe.html similarity index 95% rename from third_party/blink/web_tests/external/wpt/event-timing/resources/event-timing-observer-manual-childframe.html rename to third_party/blink/web_tests/external/wpt/event-timing/resources/observer-manual-childframe.html index 9985366..a27272c 100644 --- a/third_party/blink/web_tests/external/wpt/event-timing/resources/event-timing-observer-manual-childframe.html +++ b/third_party/blink/web_tests/external/wpt/event-timing/resources/observer-manual-childframe.html
@@ -3,7 +3,7 @@ <head> <meta charset=utf-8 /> </head> -<script src=./event-timing-support.js></script> +<script src=./event-timing-test-utils.js></script> <script> function log(message) { const timestamp = performance.now();
diff --git a/third_party/blink/web_tests/external/wpt/event-timing/event-timing-retrievability.html b/third_party/blink/web_tests/external/wpt/event-timing/retrievability.html similarity index 96% rename from third_party/blink/web_tests/external/wpt/event-timing/event-timing-retrievability.html rename to third_party/blink/web_tests/external/wpt/event-timing/retrievability.html index dc3b6d6..3a762e7a 100644 --- a/third_party/blink/web_tests/external/wpt/event-timing/event-timing-retrievability.html +++ b/third_party/blink/web_tests/external/wpt/event-timing/retrievability.html
@@ -9,7 +9,7 @@ <script src=/resources/testdriver.js></script> <script src=/resources/testdriver-vendor.js></script> -<script src=resources/event-timing-support.js></script> +<script src=resources/event-timing-test-utils.js></script> <img src=resources/slow-image.py> <script>
diff --git a/third_party/blink/web_tests/external/wpt/event-timing/event-timing-retrieve-firstInput.html b/third_party/blink/web_tests/external/wpt/event-timing/retrieve-firstInput.html similarity index 95% rename from third_party/blink/web_tests/external/wpt/event-timing/event-timing-retrieve-firstInput.html rename to third_party/blink/web_tests/external/wpt/event-timing/retrieve-firstInput.html index 15729ca8..ae66fd9 100644 --- a/third_party/blink/web_tests/external/wpt/event-timing/event-timing-retrieve-firstInput.html +++ b/third_party/blink/web_tests/external/wpt/event-timing/retrieve-firstInput.html
@@ -8,7 +8,7 @@ <script src=/resources/testdriver.js></script> <script src=/resources/testdriver-vendor.js></script> -<script src=resources/event-timing-support.js></script> +<script src=resources/event-timing-test-utils.js></script> <script> async_test(function(t) {
diff --git a/third_party/blink/web_tests/external/wpt/event-timing/event-timing-timingconditions.html b/third_party/blink/web_tests/external/wpt/event-timing/timingconditions.html similarity index 97% rename from third_party/blink/web_tests/external/wpt/event-timing/event-timing-timingconditions.html rename to third_party/blink/web_tests/external/wpt/event-timing/timingconditions.html index b53af7b..a7847b3cc 100644 --- a/third_party/blink/web_tests/external/wpt/event-timing/event-timing-timingconditions.html +++ b/third_party/blink/web_tests/external/wpt/event-timing/timingconditions.html
@@ -11,7 +11,7 @@ <script src=/resources/testdriver.js></script> <script src=/resources/testdriver-vendor.js></script> -<script src=resources/event-timing-support.js></script> +<script src=resources/event-timing-test-utils.js></script> <script> let trustedClickStart; function trustedClickAndBlockMain(id) {
diff --git a/third_party/blink/web_tests/external/wpt/media-source/mediasource-is-type-supported.html b/third_party/blink/web_tests/external/wpt/media-source/mediasource-is-type-supported.html index a364693..05b2fc1 100644 --- a/third_party/blink/web_tests/external/wpt/media-source/mediasource-is-type-supported.html +++ b/third_party/blink/web_tests/external/wpt/media-source/mediasource-is-type-supported.html
@@ -66,6 +66,8 @@ 'video/webm;codecs="vorbis, vp8"', 'audio/webm;codecs="vorbis"', 'AUDIO/WEBM;CODECS="vorbis"', + 'audio/webm;codecs="opus"', + 'video/webm;codecs="opus"' ], true, 'Test valid WebM type'); test_type_support([ @@ -78,6 +80,8 @@ 'video/mp4;codecs="avc1.4d001e,mp4a.40.2"', 'video/mp4;codecs="mp4a.40.2 , avc1.4d001e "', 'video/mp4;codecs="avc1.4d001e,mp4a.40.5"', + 'audio/mp4;codecs="opus"', + 'video/mp4;codecs="opus"' ], true, 'Test valid MP4 type'); </script> </body>
diff --git a/third_party/blink/web_tests/transitions/transitions-parsing-003.html b/third_party/blink/web_tests/transitions/transitions-parsing-003.html index a063597b..0ff8cf4 100644 --- a/third_party/blink/web_tests/transitions/transitions-parsing-003.html +++ b/third_party/blink/web_tests/transitions/transitions-parsing-003.html
@@ -125,12 +125,6 @@ assert_equals(style.webkitTransitionTimingFunction, 'steps(5, start)'); assert_equals(computedStyle.webkitTransitionTimingFunction, 'steps(5, start)'); - style.transitionTimingFunction = "frames(5)"; - assert_equals(style.transitionTimingFunction, 'frames(5)'); - assert_equals(computedStyle.transitionTimingFunction, 'frames(5)'); - assert_equals(style.webkitTransitionTimingFunction, 'frames(5)'); - assert_equals(computedStyle.webkitTransitionTimingFunction, 'frames(5)'); - style.transitionProperty = "opacity, width"; style.transitionTimingFunction = "ease-in-out, ease-in"; @@ -222,30 +216,6 @@ assert_equals(style.webkitTransitionTimingFunction, ''); assert_equals(computedStyle.webkitTransitionTimingFunction, 'ease'); - style.transitionTimingFunction = "frame(5)"; - assert_equals(style.transitionTimingFunction, ''); - assert_equals(computedStyle.transitionTimingFunction, 'ease'); - assert_equals(style.webkitTransitionTimingFunction, ''); - assert_equals(computedStyle.webkitTransitionTimingFunction, 'ease'); - - style.transitionTimingFunction = "frames()"; - assert_equals(style.transitionTimingFunction, ''); - assert_equals(computedStyle.transitionTimingFunction, 'ease'); - assert_equals(style.webkitTransitionTimingFunction, ''); - assert_equals(computedStyle.webkitTransitionTimingFunction, 'ease'); - - style.transitionTimingFunction = "frames(1)"; - assert_equals(style.transitionTimingFunction, ''); - assert_equals(computedStyle.transitionTimingFunction, 'ease'); - assert_equals(style.webkitTransitionTimingFunction, ''); - assert_equals(computedStyle.webkitTransitionTimingFunction, 'ease'); - - style.transitionTimingFunction = "frames(5, end)"; - assert_equals(style.transitionTimingFunction, ''); - assert_equals(computedStyle.transitionTimingFunction, 'ease'); - assert_equals(style.webkitTransitionTimingFunction, ''); - assert_equals(computedStyle.webkitTransitionTimingFunction, 'ease'); - style.transitionTimingFunction = "red"; assert_equals(style.transitionTimingFunction, ''); assert_equals(computedStyle.transitionTimingFunction, 'ease');
diff --git a/third_party/closure_compiler/externs/networking_private.js b/third_party/closure_compiler/externs/networking_private.js index c4cc412..47575f3 100644 --- a/third_party/closure_compiler/externs/networking_private.js +++ b/third_party/closure_compiler/externs/networking_private.js
@@ -330,7 +330,10 @@ * @typedef {{ * Gateway: (string|undefined), * IPAddress: (string|undefined), + * ExcludedRoutes: (!Array<string>|undefined), + * kIncludedRoutes: (!Array<string>|undefined), * NameServers: (!Array<string>|undefined), + * SearchDomains: (!Array<string>|undefined), * RoutingPrefix: (number|undefined), * Type: (string|undefined), * WebProxyAutoDiscoveryUrl: (string|undefined) @@ -628,7 +631,6 @@ * ActivationType: (string|undefined), * ActivationState: (!chrome.networkingPrivate.ActivationStateType|undefined), * AllowRoaming: (boolean|undefined), - * Carrier: (string|undefined), * ESN: (string|undefined), * Family: (string|undefined), * FirmwareRevision: (string|undefined), @@ -652,7 +654,7 @@ * SIMLockStatus: (!chrome.networkingPrivate.SIMLockStatus|undefined), * SIMPresent: (boolean|undefined), * SignalStrength: (number|undefined), - * SupportNetworkScan: (boolean|undefined), + * SupportNetworkScan: (boolean|undefined) * }} */ chrome.networkingPrivate.CellularProperties; @@ -665,7 +667,6 @@ * ActivationType: (string|undefined), * ActivationState: (!chrome.networkingPrivate.ActivationStateType|undefined), * AllowRoaming: (boolean|undefined), - * Carrier: (!chrome.networkingPrivate.ManagedDOMString|undefined), * ESN: (string|undefined), * Family: (string|undefined), * FirmwareRevision: (string|undefined), @@ -689,7 +690,7 @@ * SIMLockStatus: (!chrome.networkingPrivate.SIMLockStatus|undefined), * SIMPresent: (boolean|undefined), * SignalStrength: (number|undefined), - * SupportNetworkScan: (boolean|undefined), + * SupportNetworkScan: (boolean|undefined) * }} */ chrome.networkingPrivate.ManagedCellularProperties; @@ -708,6 +709,13 @@ /** * @typedef {{ + * Outer: (string|undefined) + * }} + */ +chrome.networkingPrivate.EAPStateProperties; + +/** + * @typedef {{ * AutoConnect: (boolean|undefined), * Authentication: (string|undefined), * EAP: (!chrome.networkingPrivate.EAPProperties|undefined) @@ -791,7 +799,8 @@ * RoamThreshold: (number|undefined), * SSID: (string|undefined), * Security: (string|undefined), - * SignalStrength: (number|undefined) + * SignalStrength: (number|undefined), + * TetheringState: (string|undefined) * }} */ chrome.networkingPrivate.WiFiProperties; @@ -811,7 +820,8 @@ * RoamThreshold: (!chrome.networkingPrivate.ManagedLong|undefined), * SSID: (!chrome.networkingPrivate.ManagedDOMString|undefined), * Security: !chrome.networkingPrivate.ManagedDOMString, - * SignalStrength: (number|undefined) + * SignalStrength: (number|undefined), + * TetheringState: (string|undefined) * }} */ chrome.networkingPrivate.ManagedWiFiProperties; @@ -819,11 +829,13 @@ /** * @typedef {{ * BSSID: (string|undefined), + * EAP: (!chrome.networkingPrivate.EAPStateProperties|undefined), * Frequency: (number|undefined), * HexSSID: (string|undefined), * Security: string, * SignalStrength: (number|undefined), - * SSID: (string|undefined) + * SSID: (string|undefined), + * TetheringState: (string|undefined) * }} */ chrome.networkingPrivate.WiFiStateProperties; @@ -1192,19 +1204,6 @@ chrome.networkingPrivate.verifyDestination = function(properties, callback) {}; /** - * Verifies that the device is a trusted device and retrieves encrypted network - * credentials. - * @param {!chrome.networkingPrivate.VerificationProperties} properties - * Properties of the destination to use in verifying that it is a - * trusted device. - * @param {string} networkGuid The GUID of the Cellular network to activate. - * @param {function(string):void} callback A callback function that receives - * base64-encoded encrypted credential data to send to a trusted device. - * @deprecated Use networking.castPrivate API. - */ -chrome.networkingPrivate.verifyAndEncryptCredentials = function(properties, networkGuid, callback) {}; - -/** * Verifies that the device is a trusted device and encrypts supplied data with * device public key. * @param {!chrome.networkingPrivate.VerificationProperties} properties
diff --git a/third_party/sqlite/fuzz/README.md b/third_party/sqlite/fuzz/README.md index ec0ee56d..3be57b3 100644 --- a/third_party/sqlite/fuzz/README.md +++ b/third_party/sqlite/fuzz/README.md
@@ -11,7 +11,7 @@ # Simple automated repro TODO: Move to [here](https://google.github.io/clusterfuzz/using-clusterfuzz/)? -If just trying to verify that the bug still repros on the current trunk: +To verify that the bug still repros on the current master branch: 1. Open the relevant bug (ex. https://crbug.com/956851). 2. Open the clusterfuzz "Detailed report" (ex. https://clusterfuzz.com/testcase?key=5756437473656832). 3. Click on the "REDO TASK" button. @@ -29,9 +29,8 @@ # Local repro using clusterfuzz testcase id If the fuzzer that identified this bug is public (ex. dbfuzz2), reproduce locally using the [Reproduce Tool](https://github.com/google/clusterfuzz-tools). -1. Set ${TESTCASE_ID}, where TESTCASE_ID is the ID at the end of the clusterfuzz -link (ex. `export TESTCASE_ID=5756437473656832`). -2. `/google/data/ro/teams/clusterfuzz-tools/releases/clusterfuzz reproduce --current --skip-deps ${TESTCASE_ID}`, +1. `export TESTCASE_ID=5756437473656832 # Set ${TESTCASE_ID}, where TESTCASE_ID is the ID at the end of the clusterfuzz link` +2. `/google/data/ro/teams/clusterfuzz-tools/releases/clusterfuzz reproduce --current --skip-deps ${TESTCASE_ID}` # Local repro using clusterfuzz testcase If the fuzzer is not public (ex. LPM-based fuzzers, including fts_lpm), or if @@ -39,7 +38,7 @@ To build the target, first set .gn args to match those in the clusterfuzz link, then build and run the fuzzer. -1. `export FUZZER_NAME=sqlite3_fts3_lpm_fuzzer # FUZZER_NAME is listed in the crbug as the Fuzz target binary` +1. `export FUZZER_NAME=sqlite3_fts3_lpm_fuzzer # FUZZER_NAME is listed in the crbug as the "Fuzz target binary"` 2. Download the clusterfuzz minimized testcase. 3. `export CLUSTERFUZZ_TESTCASE=./clusterfuzz-testcase-minimized-sqlite3_fts3_lpm_fuzzer-5756437473656832 # Set the clusterfuzz testcase path to CLUSTERFUZZ_TESTCASE` 3. `gn args out/Fuzzer # Set arguments to matches those in the clusterfuzz "Detailed report"'s "GN CONFIG (ARGS.GN)" section` @@ -53,7 +52,7 @@ given filters placed in (7). # Local repro using SQL commands -Please have a SQL query ready, preferably in .sql format. For this context, -we'll refer to this query as repro.sql. +Please have a .sql file with SQL queries ready. We'll refer to this file as +repro.sql. 1. `autoninja -C out/Fuzzer/ sqlite_shell # Build the sqlite_shell` 2. `out/Fuzzer/sqlite_shell < repro.sql # Try running this sql query in sqlite` \ No newline at end of file
diff --git a/third_party/unrar/BUILD.gn b/third_party/unrar/BUILD.gn index 333a008..e64f9a8 100644 --- a/third_party/unrar/BUILD.gn +++ b/third_party/unrar/BUILD.gn
@@ -3,8 +3,9 @@ # found in the LICENSE file. import("//build/config/features.gni") +import("//testing/libfuzzer/fuzzer_test.gni") -if (safe_browsing_mode == 1) { +if (safe_browsing_mode == 1 || use_fuzzing_engine) { static_library("unrar") { sources = [ "src/archive.cpp", @@ -78,15 +79,33 @@ # The following is set to disable certain macro definitions in the unrar # source code. "CHROMIUM_UNRAR", - - # Disables exceptions in unrar, replaces them with process termination. - "UNRAR_NO_EXCEPTIONS", ] + if (!use_libfuzzer) { + # Disables exceptions in unrar, replaces them with process termination. + defines += [ "UNRAR_NO_EXCEPTIONS" ] + } else { + configs -= [ "//build/config/compiler:no_exceptions" ] + } + deps = [ "//base", ] } + + if (use_fuzzing_engine && !is_asan && !is_msan) { + fuzzer_test("unrar_fuzzer") { + sources = [ + "unrar_fuzzer.cc", + ] + deps = [ + ":unrar", + ] + include_dirs = [ "//third_party/unrar/src" ] + defines = [ "CHROMIUM_UNRAR" ] + configs_to_remove = [ "//build/config/compiler:no_exceptions" ] + } + } } config("unrar_warnings") {
diff --git a/third_party/unrar/unrar_fuzzer.cc b/third_party/unrar/unrar_fuzzer.cc new file mode 100644 index 0000000..fb8f776e --- /dev/null +++ b/third_party/unrar/unrar_fuzzer.cc
@@ -0,0 +1,74 @@ +// 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 <ftw.h> +#include <stddef.h> +#include <stdint.h> +#include <unistd.h> + +#include <fstream> +#include <memory> +#include <string> + +#include "rar.hpp" + +using third_party_unrar::CmdExtract; +using third_party_unrar::CommandData; + +static int removeFile(const char* fpath, + const struct stat* sb, + int typeflag, + struct FTW* ftwbuf) { + if (remove(fpath) != 0) + abort(); + return 0; +} + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + // unrar likes to create files in the current directory. + // So, the following few lines created and 'cd' to a directory named 'o' + // in the current working directory. + constexpr size_t kMaxCwdLength = 10000; + static char cwd[kMaxCwdLength]; + if (!getcwd(cwd, sizeof(cwd))) + abort(); + + std::string original_path = std::string(cwd, strlen(cwd)); + std::string out_path = original_path + "/o"; + + if (!(opendir(out_path.c_str()) || mkdir(out_path.c_str(), 0700) == 0)) + abort(); + if (chdir(out_path.c_str()) != 0) + abort(); + + static const std::string filename = "temp.rar"; + std::ofstream file(filename, + std::ios::binary | std::ios::out | std::ios::trunc); + if (!file.is_open()) + abort(); + file.write(reinterpret_cast<const char*>(data), size); + file.close(); + + std::unique_ptr<CommandData> cmd_data(new CommandData); + cmd_data->ParseArg(const_cast<wchar_t*>(L"-p")); + cmd_data->ParseArg(const_cast<wchar_t*>(L"x")); + cmd_data->ParseDone(); + std::wstring wide_filename(filename.begin(), filename.end()); + cmd_data->AddArcName(wide_filename.c_str()); + + try { + CmdExtract extractor(cmd_data.get()); + extractor.DoExtract(); + } catch (...) { + } + + // 'cd' back to the original directory and delete 'o' along with + // all its contents. + if (chdir(original_path.c_str()) != 0) + abort(); + if (nftw(out_path.c_str(), removeFile, 20, + FTW_DEPTH | FTW_MOUNT | FTW_PHYS) != 0) + abort(); + return 0; +}
diff --git a/third_party/webxr_test_pages/webxr-samples/js/cottontail/src/core/node.js b/third_party/webxr_test_pages/webxr-samples/js/cottontail/src/core/node.js index d4be6668..8fcd9c0 100644 --- a/third_party/webxr_test_pages/webxr-samples/js/cottontail/src/core/node.js +++ b/third_party/webxr_test_pages/webxr-samples/js/cottontail/src/core/node.js
@@ -329,9 +329,9 @@ return; } - let index = this._renderPrimitives._instances.indexOf(primitive); + let index = this._renderPrimitives.indexOf(primitive); if (index > -1) { - this._renderPrimitives._instances.splice(index, 1); + this._renderPrimitives.splice(index, 1); index = primitive._instances.indexOf(this); if (index > -1) {
diff --git a/third_party/webxr_test_pages/webxr-samples/js/cottontail/src/core/renderer.js b/third_party/webxr_test_pages/webxr-samples/js/cottontail/src/core/renderer.js index 661eb2bf..04ebf2d 100644 --- a/third_party/webxr_test_pages/webxr-samples/js/cottontail/src/core/renderer.js +++ b/third_party/webxr_test_pages/webxr-samples/js/cottontail/src/core/renderer.js
@@ -585,6 +585,13 @@ return renderPrimitive; } + removeRenderPrimitive(renderPrimitive) { + let index = this._renderPrimitives[renderPrimitive._material._renderOrder].indexOf(renderPrimitive); + if(index > -1) { + this._renderPrimitives[renderPrimitive._material._renderOrder].splice(index, 1); + } + } + createMesh(primitive, material) { let meshNode = new Node(); meshNode.addRenderPrimitive(this.createRenderPrimitive(primitive, material));
diff --git a/third_party/webxr_test_pages/webxr-samples/js/cottontail/src/nodes/drop-shadow.js b/third_party/webxr_test_pages/webxr-samples/js/cottontail/src/nodes/drop-shadow.js index 09db3f5..2922797 100644 --- a/third_party/webxr_test_pages/webxr-samples/js/cottontail/src/nodes/drop-shadow.js +++ b/third_party/webxr_test_pages/webxr-samples/js/cottontail/src/nodes/drop-shadow.js
@@ -25,17 +25,20 @@ const GL = WebGLRenderingContext; // For enums const SHADOW_SEGMENTS = 32; -const SHADOW_GROUND_OFFSET = 0.01; -const SHADOW_CENTER_ALPHA = 0.7; -const SHADOW_INNER_ALPHA = 0.3; -const SHADOW_OUTER_ALPHA = 0.0; -const SHADOW_INNER_RADIUS = 0.6; -const SHADOW_OUTER_RADIUS = 1.0; + +const DEFAULT_SHADOW_GROUND_OFFSET = 0.01; +const DEFAULT_SHADOW_INNER_ALPHA = 0.3; +const DEFAULT_SHADOW_CENTER_ALPHA = 0.7; +const DEFAULT_SHADOW_OUTER_ALPHA = 0.0; +const DEFAULT_SHADOW_INNER_RADIUS = 0.6; +const DEFAULT_SHADOW_OUTER_RADIUS = 1.0; class DropShadowMaterial extends Material { - constructor() { + constructor(options = {}) { super(); + this.baseColor = this.defineUniform('baseColor', options.baseColor); + this.state.blend = true; this.state.blendFuncSrc = GL.ONE; this.state.blendFuncDst = GL.ONE_MINUS_SRC_ALPHA; @@ -64,15 +67,29 @@ return ` varying float vShadow; + uniform vec3 baseColor; + vec4 fragment_main() { - return vec4(0.0, 0.0, 0.0, vShadow); + return vec4(baseColor, vShadow); }`; } } export class DropShadowNode extends Node { - constructor(iconTexture, callback) { + constructor(options = {}) { super(); + + if(!options.baseColor) + options.baseColor = [0,0,0]; + + this.material = new DropShadowMaterial(options); + + this.SHADOW_INNER_RADIUS = options.shadow_inner_radius || DEFAULT_SHADOW_INNER_RADIUS; + this.SHADOW_OUTER_RADIUS = options.shadow_outer_radius || DEFAULT_SHADOW_OUTER_RADIUS; + this.SHADOW_GROUND_OFFSET = options.shadow_ground_offset || DEFAULT_SHADOW_GROUND_OFFSET; + this.SHADOW_INNER_ALPHA = options.shadow_inner_alpha || DEFAULT_SHADOW_INNER_ALPHA; + this.SHADOW_CENTER_ALPHA = options.shadow_center_alpha || DEFAULT_SHADOW_CENTER_ALPHA; + this.SHADOW_OUTER_ALPHA = options.shadow_outer_alpha || DEFAULT_SHADOW_OUTER_ALPHA; } onRendererChanged(renderer) { @@ -81,7 +98,7 @@ stream.startGeometry(); // Shadow center - stream.pushVertex(0, SHADOW_GROUND_OFFSET, 0, SHADOW_CENTER_ALPHA); + stream.pushVertex(0, this.SHADOW_GROUND_OFFSET, 0, this.SHADOW_CENTER_ALPHA); let segRad = ((Math.PI * 2.0) / SHADOW_SEGMENTS); @@ -92,8 +109,18 @@ let rad = i * segRad; let x = Math.cos(rad); let y = Math.sin(rad); - stream.pushVertex(x * SHADOW_INNER_RADIUS, SHADOW_GROUND_OFFSET, y * SHADOW_INNER_RADIUS, SHADOW_INNER_ALPHA); - stream.pushVertex(x * SHADOW_OUTER_RADIUS, SHADOW_GROUND_OFFSET, y * SHADOW_OUTER_RADIUS, SHADOW_OUTER_ALPHA); + + stream.pushVertex( + x * this.SHADOW_INNER_RADIUS, + this.SHADOW_GROUND_OFFSET, + y * this.SHADOW_INNER_RADIUS, + this.SHADOW_INNER_ALPHA); + + stream.pushVertex( + x * this.SHADOW_OUTER_RADIUS, + this.SHADOW_GROUND_OFFSET, + y * this.SHADOW_OUTER_RADIUS, + this.SHADOW_OUTER_ALPHA); if (i > 0) { // Inner circle @@ -113,7 +140,7 @@ stream.endGeometry(); let shadowPrimitive = stream.finishPrimitive(renderer); - this._shadowRenderPrimitive = renderer.createRenderPrimitive(shadowPrimitive, new DropShadowMaterial()); + this._shadowRenderPrimitive = renderer.createRenderPrimitive(shadowPrimitive, this.material); this.addRenderPrimitive(this._shadowRenderPrimitive); } }
diff --git a/third_party/webxr_test_pages/webxr-samples/js/cottontail/src/nodes/plane-node.js b/third_party/webxr_test_pages/webxr-samples/js/cottontail/src/nodes/plane-node.js new file mode 100644 index 0000000..95d59e4 --- /dev/null +++ b/third_party/webxr_test_pages/webxr-samples/js/cottontail/src/nodes/plane-node.js
@@ -0,0 +1,139 @@ +// Copyright 2018 The Immersive Web Community Group +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +import {Material, RENDER_ORDER} from '../core/material.js'; +import {Node} from '../core/node.js'; +import {GeometryBuilderBase} from '../geometry/primitive-stream.js'; + +const GL = WebGLRenderingContext; // For enums + +class PlaneMaterial extends Material { + constructor(options = {}) { + super(); + + this.baseColor = this.defineUniform('baseColor', options.baseColor); + + this.renderOrder = RENDER_ORDER.TRANSPARENT; + this.state.blend = true; + this.state.blendFuncSrc = GL.ONE; + this.state.blendFuncDst = GL.ONE_MINUS_SRC_ALPHA; + this.state.depthFunc = GL.LEQUAL; + this.state.depthMask = false; + this.state.cullFace = false; + } + + get materialName() { + return 'PLANE'; + } + + get vertexSource() { + return ` + attribute vec3 POSITION; + attribute vec3 NORMAL; + + varying vec3 vLight; + + const vec3 lightDir = vec3(0.75, 0.5, 1.0); + const vec3 ambientColor = vec3(0.5, 0.5, 0.5); + const vec3 lightColor = vec3(0.75, 0.75, 0.75); + + vec4 vertex_main(mat4 proj, mat4 view, mat4 model) { + vec3 normalRotated = vec3(model * vec4(NORMAL, 0.0)); + float lightFactor = max(dot(normalize(lightDir), normalRotated), 0.0); + vLight = ambientColor + (lightColor * lightFactor); + return proj * view * model * vec4(POSITION, 1.0); + }`; + } + + get fragmentSource() { + return ` + precision mediump float; + + uniform vec4 baseColor; + + varying vec3 vLight; + + vec4 fragment_main() { + return vec4(vLight, 1.0) * baseColor; + }`; + } +} + +export class PlaneNode extends Node { + constructor(options = {}) { + super(); + if(!options.polygon) + throw new Error(`Plane polygon must be specified.`); + + if(!options.baseColor) + throw new Error(`Plane base color must be specified.`); + + this.baseColor = options.baseColor; + this.polygon = options.polygon; + + this._material = new PlaneMaterial({baseColor : options.baseColor}); + + this._renderer = null; + } + + createPlanePrimitive(polygon) { + // TODO: create new builder class for planes + let planeBuilder = new GeometryBuilderBase(); + + planeBuilder.primitiveStream.startGeometry(); + let numVertices = polygon.length; + let firstVertex = planeBuilder.primitiveStream.nextVertexIndex; + polygon.forEach(vertex => { + planeBuilder.primitiveStream.pushVertex(vertex.x, vertex.y, vertex.z); + }); + + for(let i = 0; i < numVertices - 2; i++) { + planeBuilder.primitiveStream.pushTriangle(firstVertex, firstVertex + i + 1, firstVertex + i + 2); + } + planeBuilder.primitiveStream.endGeometry(); + + return planeBuilder.finishPrimitive(this._renderer); + } + + onRendererChanged(renderer) { + if(!this.polygon) + throw new Error(`Polygon is not set on a plane where it should be!`); + + this._renderer = renderer; + + this.planeNode = this._renderer.createRenderPrimitive( + this.createPlanePrimitive(this.polygon), this._material); + this.addRenderPrimitive(this.planeNode); + + this.polygon = null; + + return this.waitForComplete(); + } + + onPlaneChanged(polygon) { + if(this.polygon) + throw new Error(`Polygon is set on a plane where it shouldn't be!`); + + let updatedPrimitive = this.createPlanePrimitive(polygon); + + this.planeNode.setPrimitive(updatedPrimitive); + return this.planeNode.waitForComplete(); + } +} +
diff --git a/third_party/webxr_test_pages/webxr-samples/js/cottontail/src/nodes/ray-node.js b/third_party/webxr_test_pages/webxr-samples/js/cottontail/src/nodes/ray-node.js new file mode 100644 index 0000000..3735b15 --- /dev/null +++ b/third_party/webxr_test_pages/webxr-samples/js/cottontail/src/nodes/ray-node.js
@@ -0,0 +1,105 @@ +// Copyright 2018 The Immersive Web Community Group +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +import {Material} from '../core/material.js'; +import {Node} from '../core/node.js'; +import {Primitive, PrimitiveAttribute} from '../core/primitive.js'; + +const GL = WebGLRenderingContext; // For enums + +class RayMaterial extends Material { + constructor(options = { baseColor : [1, 0, 0, 1] }) { + super(); + + this.baseColor = this.defineUniform('baseColor', options.baseColor); + } + + get materialName() { + return 'RAY_MATERIAL'; + } + + get vertexSource() { + return ` + attribute vec3 POSITION; + + vec4 vertex_main(mat4 proj, mat4 view, mat4 model) { + return proj * view * model * vec4(POSITION, 1.0); + }`; + } + + get fragmentSource() { + return ` + precision mediump float; + + uniform vec4 baseColor; + + vec4 fragment_main() { + return baseColor; + }`; + } +} + +export class RayNode extends Node { + constructor(options = {}) { + super(); + if(typeof options.direction === 'undefined') + this._ray_direction = [0, 0, -5]; + else + this._ray_direction = options.direction; + this.material = new RayMaterial(options); + } + + onRendererChanged(renderer) { + this.ray_direction = this._ray_direction; + } + + get ray_direction() { + return this._ray_direction; + } + + set ray_direction(ray_direction) { + if (this._ray_direction) { + this.clearRenderPrimitives(); + } + + this._ray_direction = ray_direction; + + let verts = []; + let indices = []; + + verts.push(0, 0, 0); + indices.push(0); + + verts.push(ray_direction[0], ray_direction[1], ray_direction[2]); + indices.push(1); + + let vertexBuffer = this._renderer.createRenderBuffer(GL.ARRAY_BUFFER, new Float32Array(verts)); + let indexBuffer = this._renderer.createRenderBuffer(GL.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices)); + + let attribs = [ + new PrimitiveAttribute('POSITION', vertexBuffer, 3, GL.FLOAT, 12, 0), + ]; + + let primitive = new Primitive(attribs, indices.length, GL.LINES); + primitive.setIndexBuffer(indexBuffer); + + let renderPrimitive = this._renderer.createRenderPrimitive(primitive, this.material); + this.addRenderPrimitive(renderPrimitive); + } +}
diff --git a/third_party/webxr_test_pages/webxr-samples/js/cottontail/src/scenes/scene.js b/third_party/webxr_test_pages/webxr-samples/js/cottontail/src/scenes/scene.js index 8477ab8..eadfdff 100644 --- a/third_party/webxr_test_pages/webxr-samples/js/cottontail/src/scenes/scene.js +++ b/third_party/webxr_test_pages/webxr-samples/js/cottontail/src/scenes/scene.js
@@ -24,7 +24,7 @@ import {Node} from '../core/node.js'; import {vec3, quat} from '../math/gl-matrix.js'; -import '/js/xrray-polyfill.js'; +import '../../../../js/xrray-polyfill.js' export class WebXRView extends RenderView { constructor(view, pose, layer) {
diff --git a/third_party/webxr_test_pages/webxr-samples/js/hit-test-unittests.js b/third_party/webxr_test_pages/webxr-samples/js/hit-test-unittests.js new file mode 100644 index 0000000..cdd47cf --- /dev/null +++ b/third_party/webxr_test_pages/webxr-samples/js/hit-test-unittests.js
@@ -0,0 +1,281 @@ +// Copyright 2018 The Immersive Web Community Group +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +import {hitTest, filterHitTestResults} from './hit-test.js'; + +const hittest_json = ` +[ + { + "polygon": [ + { + "x": -0.7949525117874146, + "y": 0, + "z": 0.09085708856582642, + "w": 1 + }, + { + "x": -0.7388008236885071, + "y": 0, + "z": 0.2163567692041397, + "w": 1 + }, + { + "x": -0.7257306575775146, + "y": 0, + "z": 0.24235095083713531, + "w": 1 + }, + { + "x": -0.6986311078071594, + "y": 0, + "z": 0.2608765661716461, + "w": 1 + }, + { + "x": -0.18674542009830475, + "y": 0, + "z": 0.49622973799705505, + "w": 1 + }, + { + "x": -0.059895534068346024, + "y": 0, + "z": 0.5397075414657593, + "w": 1 + }, + { + "x": 0.0341365709900856, + "y": 0, + "z": 0.5527538657188416, + "w": 1 + }, + { + "x": 0.28332310914993286, + "y": 0, + "z": 0.5463775992393494, + "w": 1 + }, + { + "x": 0.7734386324882507, + "y": 0, + "z": 0.5031757950782776, + "w": 1 + }, + { + "x": 0.8223313689231873, + "y": 0, + "z": 0.25600069761276245, + "w": 1 + }, + { + "x": 0.7012030482292175, + "y": 0, + "z": -0.04883747920393944, + "w": 1 + }, + { + "x": 0.4847647547721863, + "y": 0, + "z": -0.3673478960990906, + "w": 1 + }, + { + "x": 0.4113020598888397, + "y": 0, + "z": -0.4683343172073364, + "w": 1 + }, + { + "x": 0.30164092779159546, + "y": 0, + "z": -0.5527538657188416, + "w": 1 + }, + { + "x": -0.2830299437046051, + "y": 0, + "z": -0.5527538657188416, + "w": 1 + }, + { + "x": -0.6636397242546082, + "y": 0, + "z": -0.3377974033355713, + "w": 1 + }, + { + "x": -0.7396656274795532, + "y": 0, + "z": -0.285207599401474, + "w": 1 + }, + { + "x": -0.7742070555686951, + "y": 0, + "z": -0.1881212741136551, + "w": 1 + }, + { + "x": -0.8223313689231873, + "y": 0, + "z": 0.01371713262051344, + "w": 1 + }, + { + "x": -0.8136139512062073, + "y": 0, + "z": 0.03997987508773804, + "w": 1 + }, + { + "x": -0.8045119643211365, + "y": 0, + "z": 0.06563511490821838, + "w": 1 + } + ], + "pose": { + "0": 0.3692772388458252, + "1": 0, + "2": -0.9293193221092224, + "3": 0, + "4": 0, + "5": 1, + "6": 0, + "7": 0, + "8": 0.9293193221092224, + "9": 0, + "10": 0.3692772388458252, + "11": 0, + "12": 0.28132984042167664, + "13": -1.115093469619751, + "14": -1.0961706638336182, + "15": 1 + } + } +]`; + +const ray_json = `{ + "origin": { + "x": 0.03104975074529648, + "y": -0.02061435580253601, + "z": -0.06608150154352188, + "w": 1 + }, + "direction": { + "x": -0.22517916560173035, + "y": -0.6192044019699097, + "z": -0.7522501945495605, + "w": 0 + } +}`; + +function make_point(array) { + return { x : array[0], y : array[1], z : array[2], w : array[3] }; +} + + +function run_test(points_array, point, results_callback) { + const polygon = points_array.map(make_point); + const point_on_plane = make_point(point); + + const result = filterHitTestResults( + [ + { + plane : { polygon : polygon }, + point_on_plane : point_on_plane + } + ] + ); + + results_callback(result); +} + +function test1() { + console.info("-------------------- running test1 -------------------- "); + + let polygon = [ + [-1, 0, -1, 1], + [-1, 0, 1, 1], + [ 1, 0, 1, 1], + [ 1, 0, -1, 1], + ]; + + run_test(polygon, [0,0,0,1], result => { + if(result.length != 1) { + console.error("Expected one result!"); + debugger; + } + }); + + run_test(polygon, [2,0,0,1], result => { + if(result.length != 0) { + console.error("Expected no results!"); + debugger; + } + }); + + run_test(polygon, [1.01,0,0,1], result => { + if(result.length != 0) { + console.error("Expected no results!"); + debugger; + } + }); + + console.info("-------------------- test1 finished -------------------- "); +} + +class MockedPlane { + constructor(pose, polygon) { + this._pose = pose; + this._polygon = polygon; + } + + getPose(frame_of_reference_ignored) { + return { transform : { matrix : this._pose } }; + } + + get polygon() { + return this._polygon; + } +} + +function test2() { + let planes_raw = JSON.parse(hittest_json); + let ray_raw = JSON.parse(ray_json); + + let planes = planes_raw.map(plane_raw => new MockedPlane(plane_raw.pose, plane_raw.polygon)); + let ray = new XRRay(ray_raw.origin, ray_raw.direction); + + const result = hitTest(ray, planes, null); + const result_filtered = filterHitTestResults(result); + if(result_filtered.length != 0) { + console.error("Expected no results!"); + debugger; + } +} + +export function runUnitTests() { + console.info("-------------------- running unittests -------------------- "); + + test1(); + //test2(); + + console.info("-------------------- run finished -------------------- "); +}
diff --git a/third_party/webxr_test_pages/webxr-samples/js/hit-test.js b/third_party/webxr_test_pages/webxr-samples/js/hit-test.js new file mode 100644 index 0000000..e88a69d --- /dev/null +++ b/third_party/webxr_test_pages/webxr-samples/js/hit-test.js
@@ -0,0 +1,291 @@ +// Copyright 2018 The Immersive Web Community Group +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +let neg = function(vector) { + return {x : -vector.x, y : -vector.y, z : -vector.z, w : vector.w}; +} + +let sub = function(lhs, rhs) { + if(!((lhs.w == 1 && rhs.w == 1) || (lhs.w == 1 && rhs.w == 0) || (lhs.w == 0 && rhs.w == 0))) + console.error("only point - point, point - line or line - line subtraction is allowed"); + return {x : lhs.x - rhs.x, y : lhs.y - rhs.y, z : lhs.z - rhs.z, w : lhs.w - rhs.w}; +} + +let add = function(lhs, rhs) { + if(!((lhs.w == 0 && rhs.w == 1) || (lhs.w == 1 && rhs.w == 0))) + console.error("only line + point or point + line addition is allowed"); + + return {x : lhs.x + rhs.x, y : lhs.y + rhs.y, z : lhs.z + rhs.z, w : lhs.w + rhs.w}; +} + +let mul = function(vector, scalar) { + return {x : vector.x * scalar, y : vector.y * scalar, z : vector.z * scalar, w : vector.w}; +} + +// |matrix| - Float32Array, |input| - point-like dict (must have x, y, z, w) +export function transform_point_by_matrix (matrix, input) { + return { + x : matrix[0] * input.x + matrix[4] * input.y + matrix[8] * input.z + matrix[12] * input.w, + y : matrix[1] * input.x + matrix[5] * input.y + matrix[9] * input.z + matrix[13] * input.w, + z : matrix[2] * input.x + matrix[6] * input.y + matrix[10] * input.z + matrix[14] * input.w, + w : matrix[3] * input.x + matrix[7] * input.y + matrix[11] * input.z + matrix[15] * input.w, + }; +} + +// |point| - point-like dict (must have x, y, z, w) +let normalize_perspective = function(point) { + if(point.w == 0 || point.w == 1) return point; + + return { + x : point.x / point.w, + y : point.y / point.w, + z : point.z / point.w, + w : 1 + }; +} + +let dotProduct = function(lhs, rhs) { + return lhs.x * rhs.x + lhs.y * rhs.y + lhs.z * rhs.z; +} + +let crossProduct = function(lhs, rhs) { + return { + x : lhs.y * rhs.z - lhs.z * rhs.y, + y : lhs.z * rhs.x - lhs.x * rhs.z, + z : lhs.x * rhs.y - lhs.y * rhs.x, + w : 0 + } +} + +let length = function(vector) { + return Math.sqrt(dotProduct(vector, vector)); +} + +let normalize = function(vector) { + const l = length(vector); + return mul(vector, 1.0/l); +} + +let calculateHitMatrix = function(ray_vector, plane_normal, point) { + // projection of ray_vector onto a plane + const ray_vector_projection = sub(ray_vector, mul(plane_normal, dotProduct(ray_vector, plane_normal))); + + // new coordinate system axes + const y = plane_normal; + const z = normalize(neg(ray_vector_projection)); + const x = normalize(crossProduct(y, z)); + + let hitMatrix = new Float32Array(16); + + hitMatrix[0] = x.x; + hitMatrix[1] = x.y; + hitMatrix[2] = x.z; + hitMatrix[3] = 0; + + hitMatrix[4] = y.x; + hitMatrix[5] = y.y; + hitMatrix[6] = y.z; + hitMatrix[7] = 0; + + hitMatrix[8] = z.x; + hitMatrix[9] = z.y; + hitMatrix[10] = z.z; + hitMatrix[11] = 0; + + hitMatrix[12] = point.x; + hitMatrix[13] = point.y; + hitMatrix[14] = point.z; + hitMatrix[15] = 1; + + return hitMatrix; +} + +// single plane hit test - doesn't take into account the plane's polygon +function hitTestPlane(ray, plane, frameOfReference) { + const plane_pose = plane.getPose(frameOfReference); + const plane_normal = transform_point_by_matrix( + plane_pose.transform.matrix, {x : 0, y : 1.0, z : 0, w : 0}); + const plane_center = normalize_perspective( + transform_point_by_matrix( + plane_pose.transform.matrix, {x : 0, y : 0, z : 0, w : 1.0})); + + const ray_origin = ray.origin; + const ray_vector = ray.direction; + + const numerator = dotProduct( sub(plane_center, ray_origin), plane_normal); + const denominator = dotProduct(ray_vector, plane_normal); + + if(denominator < 0.0001 && denominator > -0.0001) { + // parallel planes + if(numerator < 0.0001 && numerator > -0.0001) { + // contained in the plane + console.debug("Ray contained in the plane", plane); + return { plane : plane }; + } else { + // no hit + console.debug("No hit", plane); + return null; + } + } else { + // single point of intersection + const d = numerator / denominator; + if(d < 0) { + // no hit - plane-line intersection exists but not for half-line + console.debug("No hit", d, plane); + return null; + } else { + const point = add(ray_origin, mul(ray_vector, d)); // hit test point coordinates in frameOfReference + + let point_on_plane = transform_point_by_matrix(plane_pose.transform.inverse.matrix, point); // hit test point coodinates relative to plane pose + console.assert(Math.abs(point_on_plane.y) < 0.0001, "Incorrect Y coordinate of mapped point"); + + let hitMatrix = calculateHitMatrix(ray_vector, plane_normal, point); + + return { + distance : d, + plane : plane, + ray : ray, + point : point, + point_on_plane : point_on_plane, + hitMatrix : hitMatrix, + pose_matrix : plane_pose.transform.matrix + }; + } + } + + console.error("Should never reach here"); + return null; +} + +// multiple planes hit test +export function hitTest(ray, planes, frameOfReference) { + const hit_test_results = planes.map(plane => hitTestPlane(ray, plane, frameOfReference)); + + // throw away all strange results (no intersection with plane, ray lies on plane) + let hit_test_results_with_points = hit_test_results.filter( + maybe_plane => maybe_plane && typeof maybe_plane.point != "undefined"); + + // sort results by distance + hit_test_results_with_points.sort((l, r) => l.distance - r.distance); + + // throw away the ones that don't fall within polygon bounds (except the bottommost plane) + // convert hittest results to something that the caller expects + + return hit_test_results_with_points; +} + +function simplifyPolygon(polygon) { + let result = []; + + let previous_point = polygon[polygon.length - 1]; + for(let i = 0; i < polygon.length; ++i) { + const current_point = polygon[i]; + + const segment = sub(current_point, previous_point); + if(length(segment) < 0.001) { + continue; + } + + result.push(current_point); + previous_point = current_point; + } + + return result; +} + +export function extendPolygon(polygon) { + return polygon.map(vertex => { + let center_to_vertex_normal = normalize(vertex); + center_to_vertex_normal.w = 0; + const addition = mul(center_to_vertex_normal, 0.2); + return add(vertex, addition); + }); +} + +// 2d "cross product" of 3d points lying on a 2d plane with Y = 0 +let crossProduct2d = function(lhs, rhs) { + return lhs.x * rhs.z - lhs.z * rhs.x; +} + +// Filters hit test results to keep only the planes for which the used ray falls +// within their polygon. Optionally, we can keep the last horizontal plane that +// was hit. +export function filterHitTestResults(hitTestResults, + keep_last_plane = false, + simplify_planes = false, + use_enlarged_polygon = false) { + console.assert(!(simplify_planes && use_enlarged_polygon), "Wait that's illegal.") + + let result = hitTestResults.filter(hitTestResult => { + + let polygon = simplify_planes ? simplifyPolygon(hitTestResult.plane.polygon) + : hitTestResult.plane.polygon; + + polygon = use_enlarged_polygon ? hitTestResult.plane.extended_polygon : polygon; + + const hit_test_point = hitTestResult.point_on_plane; + + // Check if the point is on the same side from all the segments: + // - if yes, then it's in the polygon + // - if no, then it's outside of the polygon + // This works only for convex polygons. + + let side = 0; // unknown, 1 = right, 2 = left + let previous_point = polygon[polygon.length - 1]; + for(let i = 0; i < polygon.length; ++i) { + const current_point = polygon[i]; + + const line_segment = sub(current_point, previous_point); + const segment_direction = normalize(line_segment); + + const turn_segment = sub(hit_test_point, current_point); + const turn_direction = normalize(turn_segment); + + const cosine_ray_segment = crossProduct2d(segment_direction, turn_direction); + if(side == 0) { + if(cosine_ray_segment > 0) { + side = 1; + } else { + side = 2; + } + } else { + if(cosine_ray_segment > 0 && side == 2) return false; + if(cosine_ray_segment < 0 && side == 1) return false; + } + + previous_point = current_point; + } + + return true; + }); + + if(keep_last_plane && hitTestResults.length > 0) { + const last_horizontal_plane_result = hitTestResults.slice().reverse().find( + element => { + return element.plane.orientation == "Horizontal"; + }); + + if(last_horizontal_plane_result + && result.findIndex(element => element === last_horizontal_plane_result) == -1) { + result.push(last_horizontal_plane_result); + } + } + + return result; +}
diff --git a/third_party/webxr_test_pages/webxr-samples/proposals/index.html b/third_party/webxr_test_pages/webxr-samples/proposals/index.html index 41310ae..6443f49 100644 --- a/third_party/webxr_test_pages/webxr-samples/proposals/index.html +++ b/third_party/webxr_test_pages/webxr-samples/proposals/index.html
@@ -109,6 +109,11 @@ { title: 'AR Hit Test', category: 'Phone AR', path: 'phone-ar-hit-test.html', description: 'Demonstrates using the Hit Test API to place virtual objects on real-world surfaces.' }, + + { title: 'AR Plane Detection & Hit-Test', category: 'Phone AR', + path: 'phone-ar-plane-detection.html', + description: 'Demonstrates using the Plane Detection feature, including implementation of' + + 'synchronous hit test in JavaScript leveraging obtained plane data.' }, ]; let mainElement = document.getElementById("main");
diff --git a/third_party/webxr_test_pages/webxr-samples/proposals/phone-ar-plane-detection.html b/third_party/webxr_test_pages/webxr-samples/proposals/phone-ar-plane-detection.html new file mode 100644 index 0000000..50712116 --- /dev/null +++ b/third_party/webxr_test_pages/webxr-samples/proposals/phone-ar-plane-detection.html
@@ -0,0 +1,495 @@ +<!doctype html> +<!-- +Copyright 2018 The Immersive Web Community Group + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +--> +<html> + <head> + <meta charset='utf-8'> + <meta name='viewport' content='width=device-width, initial-scale=1, user-scalable=no'> + <meta name='mobile-web-app-capable' content='yes'> + <meta name='apple-mobile-web-app-capable' content='yes'> + + <!-- Origin Trial Token, feature = WebXR Device API, origin = https://immersive-web.github.io, expires = 2018-08-28 --> +<meta http-equiv="origin-trial" data-feature="WebXR Device API" data-expires="2018-08-28" content="AnNpu7ceXvLew05ccD8Zr1OZsdZiB2hLQKK82kTTMDwF7oRKtP3QEJ4RzkeHrmB8Sq0vSV6ZNmszpBCZ0I8p9gAAAABceyJvcmlnaW4iOiJodHRwczovL2ltbWVyc2l2ZS13ZWIuZ2l0aHViLmlvOjQ0MyIsImZlYXR1cmUiOiJXZWJYUkRldmljZSIsImV4cGlyeSI6MTUzNTQxNDQwMH0="> + + <title>AR Hit Test</title> + + <link href='../css/common.css' rel='stylesheet'></link> + + <!--The polyfill is not needed for browser that have native API support, + but is linked by these samples for wider compatibility.--> + <!--script src='https://cdn.jsdelivr.net/npm/webxr-polyfill@latest/build/webxr-polyfill.js'></script--> + <script src='../js/xrray-polyfill.js' type='module'></script> + <script src='../js/webxr-polyfill.js'></script> + + <script src='../js/webxr-button.js'></script> + </head> + <body> + <header> + <details open> + <summary>AR Synchronous Hit Test</summary> + <p> + <input id="useReticle" type="checkbox" checked> + <label for="useReticle">Use reticle for placement</label><br/> + + <input id="useReticleRays" type="checkbox" checked> + <label for="useReticleRays">Hit-test rays visible</label><br/> + + <input id="useReticleOrigin" type="checkbox"> + <label for="useReticleOrigin">Reticle coordinate system visible</label><br/> + + <input id="usePlaneOrigin" type="checkbox"> + <label for="usePlaneOrigin">Plane coordinate system visible</label><br/> + + <input id="enlargedPlanesEnabled" type="checkbox" checked> + <label for="enlargedPlanesEnabled">Extend planes by 20cm</label><br/> + + <input id="extendPlanesEnabled" type="checkbox" checked> + <label for="extendPlanesEnabled">Extend bottom-most plane to infinity</label><br/> + <a class="back" href="./">Back</a> + </p> + </details> + </header> + <script type="module"> + import {hitTest, filterHitTestResults, extendPolygon, transform_point_by_matrix} from '../js/hit-test.js'; + import {Scene} from '../js/cottontail/src/scenes/scene.js'; + import {Renderer, createWebGLContext} from '../js/cottontail/src/core/renderer.js'; + import {Gltf2Node} from '../js/cottontail/src/nodes/gltf2.js'; + import {PlaneNode} from '../js/cottontail/src/nodes/plane-node.js'; + import {RayNode} from '../js/cottontail/src/nodes/ray-node.js'; + import {QueryArgs} from '../js/cottontail/src/util/query-args.js'; + import {FallbackHelper} from '../js/cottontail/src/util/fallback-helper.js'; + import {Node} from '../js/cottontail/src/core/node.js'; + import {DropShadowNode} from '../js/cottontail/src/nodes/drop-shadow.js'; + import {vec3, vec4} from '../js/cottontail/src/math/gl-matrix.js'; + import {runUnitTests} from '../js/hit-test-unittests.js'; + + runUnitTests(); + + // If requested, initialize the WebXR polyfill + if (QueryArgs.getBool('allowPolyfill', false)) { + var polyfill = new WebXRPolyfill(); + } + + const useReticle = document.getElementById('useReticle'); + const useReticleRays = document.getElementById('useReticleRays'); + const useReticleOrigin = document.getElementById('useReticleOrigin'); + const usePlaneOrigin = document.getElementById('usePlaneOrigin'); + const enlargedPlanesEnabled = document.getElementById('enlargedPlanesEnabled'); + const extendPlanesEnabled = document.getElementById('extendPlanesEnabled'); + + const flowerEnabled = true; + + let all_plane_origins = []; + let all_extended_planes = []; + + usePlaneOrigin.addEventListener('input', element =>{ + console.log("Changing state of plane origins, count:", all_plane_origins.length); + all_plane_origins.forEach(ray => { + ray.visible = usePlaneOrigin.checked + for (let child of ray.children) { + child.visible = usePlaneOrigin.checked; + } + }); + }); + + enlargedPlanesEnabled.addEventListener('input', element => { + console.log("Changing state of enlarged planes, count:", all_extended_planes.length); + all_extended_planes.forEach(plane => plane.visible = enlargedPlanesEnabled.checked); + }); + + // XR globals. + let xrButton = null; + let xrRefSpace = null; + + // WebGL scene globals. + let gl = null; + let renderer = null; + let scene = new Scene(); + scene.enableStats(false); + + // ------------------------------ + // Create "crosshair" out of 4 rays for debugging + let rayObject = new Node(); + rayObject.visible = useReticleRays.checked; + + // top + let ray1 = new RayNode({ baseColor : [0, 0, 1, 1] }); + vec3.set(ray1.translation, 0, 0.05, 0); + rayObject.addNode(ray1); + + // left + let ray2 = new RayNode({ baseColor : [0, 1, 0, 1] }); + vec3.set(ray2.translation, -0.05, 0, 0); + rayObject.addNode(ray2); + + // right + let ray3 = new RayNode({ baseColor : [1, 0, 0, 1] }); + vec3.set(ray3.translation, 0.05, 0, 0); + rayObject.addNode(ray3); + + // bottom + let ray4 = new RayNode({ baseColor : [1, 1, 0, 1] }); + vec3.set(ray4.translation, 0, -0.05, 0); + rayObject.addNode(ray4); + + scene.addNode(rayObject); + + useReticleRays.addEventListener('input', element => { + console.log("Changing state of reticle rays", useReticleRays.checked); + rayObject.visible = useReticleRays.checked; + for (let child of rayObject.children) { + child.visible = useReticleRays.checked; + } + }); + // ------------------------------ + + let arObject = new Node(); + arObject.visible = false; + + let reticle = new DropShadowNode({ + baseColor : [1, 0, 0], + shadow_inner_alpha : 0.6, + shadow_inner_radius : 0.2, + shadow_outer_radius : 0.4, + }); + vec3.set(reticle.scale, 0.3, 0.3, 0.3); + arObject.addNode(reticle); + + // Create reticle's frame of reference out of 3 rays for debugging + let reticleFrameOfReference = new Node(); + reticleFrameOfReference.visible = useReticleOrigin.checked; + + let xRay = new RayNode({direction : [5, 0, 0], baseColor : [0, 1, 1, 1]}); + let yRay = new RayNode({direction : [0, 5, 0], baseColor : [0, 1, 1, 1]}); + let zRay = new RayNode({direction : [0, 0, 5], baseColor : [0, 1, 1, 1]}); + + reticleFrameOfReference.addNode(xRay); + reticleFrameOfReference.addNode(yRay); + reticleFrameOfReference.addNode(zRay); + + arObject.addNode(reticleFrameOfReference); + scene.addNode(arObject); + + useReticleOrigin.addEventListener('input', element =>{ + console.log("Changing state of reticle origins", useReticleOrigin.checked); + reticleFrameOfReference.visible = useReticleOrigin.checked; + }); + + let flowerNode = new Node(); + flowerNode.visible = false; + + if(flowerEnabled) { + let flower = new Gltf2Node({url: '../../media/gltf/sunflower/sunflower.gltf'}); + flowerNode.addNode(flower); + + // Having a really simple drop shadow underneath an object helps ground + // it in the world without adding much complexity. + let shadow = new DropShadowNode(); + vec3.set(shadow.scale, 0.15, 0.15, 0.15); + flowerNode.addNode(shadow); + } + + arObject.addNode(flowerNode); + + const MAX_FLOWERS = 30; + let flowers = []; + + // Ensure the background is transparent for AR. + scene.clear = false; + + function initXR() { + xrButton = new XRDeviceButton({ + onRequestSession: onRequestSession, + onEndSession: onEndSession, + textEnterXRTitle: "START AR", + textXRNotFoundTitle: "AR NOT FOUND", + textExitXRTitle: "EXIT AR", + supportedSessionTypes: ['immersive-ar'], + height: 36, + }); + document.querySelector('header').appendChild(xrButton.domElement); + } + + function onRequestSession() { + navigator.xr.requestSession('immersive-ar').then((session) => { + session.mode = 'immersive-ar'; + xrButton.setSession(session); + onSessionStarted(session); + }); + } + + function onSessionStarted(session) { + session.addEventListener('end', onSessionEnded); + session.addEventListener('select', onSelect); + + if (!gl) { + gl = createWebGLContext({ + xrCompatible: true, + alpha : true, + }); + + renderer = new Renderer(gl); + gl.lineWidth(5); + + scene.setRenderer(renderer); + } + + session.updateRenderState({ + baseLayer: new XRWebGLLayer(session, gl) + }); + + session.updateWorldTrackingState({ + "planeDetectionState" : { "enabled" : true} + }); + + session.requestReferenceSpace({ type: 'stationary', subtype: 'eye-level' }).then((refSpace) => { + xrRefSpace = refSpace; + session.requestAnimationFrame(onXRFrame); + }); + } + + function onEndSession(session) { + session.end(); + } + + function onSessionEnded(event) { + xrButton.setSession(null); + } + + // Adds a new object to the scene at the + // specificed transform. + function addARObjectAt(matrix) { + let newFlower = flowerNode.clone(); + newFlower.visible = true; + newFlower.matrix = matrix; + scene.addNode(newFlower); + + flowers.push(newFlower); + + // For performance reasons if we add too many objects start + // removing the oldest ones to keep the scene complexity + // from growing too much. + if (flowers.length > MAX_FLOWERS) { + let oldFlower = flowers.shift(); + scene.removeNode(oldFlower); + } + } + + function DOMPointFromVec4(vector) { + return { x : vector[0], y : vector[1], z : vector[2], w : vector[3]} + } + + let rayOrigin = vec4.create(); + let rayDirection = vec4.create(); + function onSelect(event) { + if (useReticle.checked && arObject.visible) { + // If we're using the reticle then we've already got a mesh positioned + // at the latest hit point and we should just use it's matrix to save + // an unnecessary requestHitTest call. + addARObjectAt(arObject.matrix); + } else { + if(!event.frame.worldInformation.detectedPlanes) { + console.error("Not supported yet - no planes on frame!"); + return; + } + + console.log("Detected some planes, length:", event.frame.worldInformation.detectedPlanes.length); + + // Otherwise we'll use the target ray from the input source that generated + // this event to fire off a new hit test. + let inputPose = event.frame.getPose(event.inputSource.targetRaySpace, xrRefSpace); + if (inputPose) { + let targetRay = new XRRay(inputPose.transform); + vec4.set(rayOrigin, + targetRay.origin.x, + targetRay.origin.y, + targetRay.origin.z, + targetRay.origin.w); + vec4.set(rayDirection, + targetRay.direction.x, + targetRay.direction.y, + targetRay.direction.z, + targetRay.direction.w); + + let ray = new XRRay(DOMPointFromVec4(rayOrigin), DOMPointFromVec4(rayDirection)); + + const hitTestResults = hitTest(ray, event.frame.worldInformation.detectedPlanes, xrRefSpace); + const hitTestFiltered = filterHitTestResults(hitTestResults, + extendPlanesEnabled.checked, + false, + enlargedPlanesEnabled.checked); + + if (hitTestFiltered.length) { + addARObjectAt(hitTestFiltered[0].hitMatrix); + } + } + } + } + + function addPlaneToScene(plane) { + if(typeof XRPlane.counter == 'undefined') { + XRPlane.counter = 1; + XRPlane.colors = [ + [0.0, 0.0, 1.0, 0.2], // blue + [1.0, 0.0, 0.0, 0.2], // red + [0.0, 1.0, 0.0, 0.2], // green + [0.0, 1.0, 1.0, 0.2], // aqua + [1.0, 0.0, 1.0, 0.2], // fuchsia + [1.0, 1.0, 0.0, 0.2], // yellow + ]; + } + + if(typeof plane.id == 'undefined') { + // new plane + console.log("Adding plane, id:", XRPlane.counter); + + plane.id = XRPlane.counter; + XRPlane.counter++; + + let plane_node = new PlaneNode({ + polygon : plane.polygon, + baseColor : XRPlane.colors[(plane.id - 1) % XRPlane.colors.length], + }); + + let planeFrameOfReference = new Node(); + planeFrameOfReference.visible = usePlaneOrigin.checked; + + let xRay = new RayNode({direction : [5, 0, 0], baseColor : [1, 0, 1, 1]}); + let yRay = new RayNode({direction : [0, 5, 0], baseColor : [1, 0, 1, 1]}); + let zRay = new RayNode({direction : [0, 0, 5], baseColor : [1, 0, 1, 1]}); + + plane_node.origins = planeFrameOfReference; + all_plane_origins.push(planeFrameOfReference); + + planeFrameOfReference.addNode(xRay); + planeFrameOfReference.addNode(yRay); + planeFrameOfReference.addNode(zRay); + + plane_node.addNode(planeFrameOfReference); + + plane.scene_node = plane_node; + plane.scene_node.matrix = plane.getPose(xrRefSpace).transform.matrix; + + plane.extended_polygon = extendPolygon(plane.polygon); + plane.extended_polygon_node = new PlaneNode({ + polygon : plane.extended_polygon, + baseColor : plane_node.baseColor.map(element => element * 0.6) + }); + plane.extended_polygon_node.visible = enlargedPlanesEnabled.checked; + plane.scene_node.addNode(plane.extended_polygon_node); + all_extended_planes.push(plane.extended_polygon_node); + + scene.addNode(plane.scene_node); + } + else + { + // old plane + plane.scene_node.onPlaneChanged(plane.polygon); + plane.scene_node.matrix = plane.getPose(xrRefSpace).transform.matrix; + plane.extended_polygon = extendPolygon(plane.polygon); + plane.extended_polygon_node.onPlaneChanged(plane.extended_polygon); + } + } + + let all_planes = new Set(); + + // Called every time a XRSession requests that a new frame be drawn. + async function onXRFrame(t, frame) { + + let session = frame.session; + let pose = frame.getViewerPose(xrRefSpace); + + let previous_planes = new Set(all_planes); + let detected_planes = frame.worldInformation.detectedPlanes; + detected_planes.forEach(plane => { + addPlaneToScene(plane); + if(previous_planes.has(plane)) { + previous_planes.delete(plane); + } + }); + + previous_planes.forEach(plane => { + console.log("Removing plane, id:", plane.id); + + let index = all_plane_origins.findIndex(element => element === plane.scene_node.origins); + if(index != -1){ + all_plane_origins.splice(index, 1); + } + + index = all_extended_planes.findIndex(element => element === plane.extended_polygon_node); + if(index != -1){ + all_extended_planes.splice(index, 1); + } + + scene.removeNode(plane.scene_node); + }); + + all_planes = new Set(detected_planes); + + // If requested, use the pose to cast a reticle into the scene using a + // continuous hit test. For the moment we're just using the flower + // as the "reticle". + if (useReticle.checked && pose && pose.transform.matrix) { + vec4.set(rayOrigin, 0, 0, 0, 1); + vec4.transformMat4(rayOrigin, rayOrigin, pose.transform.matrix); + + vec4.set(rayDirection, 0, 0, -1, 0); + vec4.transformMat4(rayDirection, rayDirection, pose.transform.matrix); + vec4.normalize(rayDirection, rayDirection); + + const ray = new XRRay(DOMPointFromVec4(rayOrigin), DOMPointFromVec4(rayDirection)); + + rayObject.matrix = ray.matrix.slice(); + rayObject.visible = true; + + const hitTestResults = hitTest(ray, frame.worldInformation.detectedPlanes, xrRefSpace); + const hitTestFiltered = filterHitTestResults(hitTestResults, + extendPlanesEnabled.checked, + false, + enlargedPlanesEnabled.checked); + + if(hitTestFiltered && hitTestFiltered.length > 0) { + + let hitResult = hitTestFiltered[0]; + arObject.visible = true; + arObject.matrix = hitResult.hitMatrix; + } else { + arObject.visible = false; + } + } else { + arObject.visible = false; + rayObject.visible = false; + } + + await scene.waitForComplete(); + + scene.startFrame(); + scene.drawXRFrame(frame, pose); + scene.endFrame(); + + session.requestAnimationFrame(onXRFrame); + } + + // Start the XR application. + initXR(); + </script> + </body> +</html>
diff --git a/tools/clang/blink_gc_plugin/Config.h b/tools/clang/blink_gc_plugin/Config.h index ded4d84..f60594a 100644 --- a/tools/clang/blink_gc_plugin/Config.h +++ b/tools/clang/blink_gc_plugin/Config.h
@@ -68,10 +68,6 @@ return name == "unique_ptr"; } - static bool IsTraceWrapperMember(const std::string& name) { - return name == "TraceWrapperMember"; - } - static bool IsTraceWrapperV8Reference(const std::string& name) { return name == "TraceWrapperV8Reference"; }
diff --git a/tools/clang/blink_gc_plugin/Edge.h b/tools/clang/blink_gc_plugin/Edge.h index 25a1e07..c186f43 100644 --- a/tools/clang/blink_gc_plugin/Edge.h +++ b/tools/clang/blink_gc_plugin/Edge.h
@@ -104,7 +104,6 @@ virtual bool IsMember() { return false; } virtual bool IsWeakMember() { return false; } virtual bool IsCollection() { return false; } - virtual bool IsTraceWrapperMember() { return false; } virtual bool IsTraceWrapperV8Reference() { return false; } }; @@ -229,12 +228,6 @@ } }; -class TraceWrapperMember : public Member { - public: - explicit TraceWrapperMember(Edge* ptr) : Member(ptr) {} - bool IsTraceWrapperMember() override { return true; } -}; - class TraceWrapperV8Reference : public PtrEdge { public: explicit TraceWrapperV8Reference(Edge* ptr) : PtrEdge(ptr) {}
diff --git a/tools/clang/blink_gc_plugin/RecordInfo.cpp b/tools/clang/blink_gc_plugin/RecordInfo.cpp index 9e8f19f..b86bb37 100644 --- a/tools/clang/blink_gc_plugin/RecordInfo.cpp +++ b/tools/clang/blink_gc_plugin/RecordInfo.cpp
@@ -718,13 +718,6 @@ return edge; } - if (Config::IsTraceWrapperMember(info->name()) && - info->GetTemplateArgs(1, &args)) { - if (Edge* ptr = CreateEdge(args[0])) - return new TraceWrapperMember(ptr); - return 0; - } - if (Config::IsTraceWrapperV8Reference(info->name()) && info->GetTemplateArgs(1, &args)) { if (Edge* ptr = CreateEdge(args[0]))
diff --git a/tools/clang/blink_gc_plugin/tests/heap/stubs.h b/tools/clang/blink_gc_plugin/tests/heap/stubs.h index 81d824dd..722e33a 100644 --- a/tools/clang/blink_gc_plugin/tests/heap/stubs.h +++ b/tools/clang/blink_gc_plugin/tests/heap/stubs.h
@@ -256,9 +256,6 @@ bool operator!() const { return false; } }; -template <class T> -class TraceWrapperMember : public Member<T> {}; - template <typename T> class TraceWrapperV8Reference { public:
diff --git a/tools/clang/blink_gc_plugin/tests/trace_wrapper.h b/tools/clang/blink_gc_plugin/tests/trace_wrapper.h index b2daef1..d83e3ad 100644 --- a/tools/clang/blink_gc_plugin/tests/trace_wrapper.h +++ b/tools/clang/blink_gc_plugin/tests/trace_wrapper.h
@@ -16,12 +16,10 @@ class A : public GarbageCollected<A> { public: void Trace(Visitor*) { - // Missing visitor->Trace(a_); // Missing visitor->Trace(str_); } private: - TraceWrapperMember<A> a_; TraceWrapperV8Reference<v8::String> str_; }; @@ -34,12 +32,10 @@ class C : public B { public: void TraceAfterDispatch(Visitor*) { - // Missing visitor->Trace(a_); // Missing visitor->Trace(str_); } private: - TraceWrapperMember<A> a_; TraceWrapperV8Reference<v8::String> str_; };
diff --git a/tools/clang/blink_gc_plugin/tests/trace_wrapper.txt b/tools/clang/blink_gc_plugin/tests/trace_wrapper.txt index 40559996..e6c1076 100644 --- a/tools/clang/blink_gc_plugin/tests/trace_wrapper.txt +++ b/tools/clang/blink_gc_plugin/tests/trace_wrapper.txt
@@ -2,20 +2,14 @@ ./trace_wrapper.h:18:3: warning: [blink-gc] Class 'A' has untraced fields that require tracing. void Trace(Visitor*) { ^ -./trace_wrapper.h:24:3: note: [blink-gc] Untraced field 'a_' declared here: - TraceWrapperMember<A> a_; - ^ -./trace_wrapper.h:25:3: note: [blink-gc] Untraced field 'str_' declared here: +./trace_wrapper.h:23:3: note: [blink-gc] Untraced field 'str_' declared here: TraceWrapperV8Reference<v8::String> str_; ^ -./trace_wrapper.h:36:3: warning: [blink-gc] Base class 'B' of derived class 'C' requires tracing. +./trace_wrapper.h:34:3: warning: [blink-gc] Base class 'B' of derived class 'C' requires tracing. void TraceAfterDispatch(Visitor*) { ^ -./trace_wrapper.h:36:3: warning: [blink-gc] Class 'C' has untraced fields that require tracing. -./trace_wrapper.h:42:3: note: [blink-gc] Untraced field 'a_' declared here: - TraceWrapperMember<A> a_; - ^ -./trace_wrapper.h:43:3: note: [blink-gc] Untraced field 'str_' declared here: +./trace_wrapper.h:34:3: warning: [blink-gc] Class 'C' has untraced fields that require tracing. +./trace_wrapper.h:39:3: note: [blink-gc] Untraced field 'str_' declared here: TraceWrapperV8Reference<v8::String> str_; ^ 3 warnings generated.
diff --git a/tools/grit/grit/format/resource_map.py b/tools/grit/grit/format/resource_map.py index c34e4a2..12880c8 100644 --- a/tools/grit/grit/format/resource_map.py +++ b/tools/grit/grit/format/resource_map.py
@@ -165,7 +165,8 @@ real_path = item.ToRealPath(item.GetInputPath()) if (item.attrs.get('use_base_dir', 'true') != 'true' and _IsSubpath(os.path.curdir, real_path)): - path = os.path.join('@out_folder@', os.path.relpath(real_path)) + path = os.path.join( + '@out_folder@', os.path.relpath(real_path)).replace("\\", "/") assert '$' not in path, 'all variables should have been expanded' return path
diff --git a/tools/grit/grit/format/resource_map_unittest.py b/tools/grit/grit/format/resource_map_unittest.py index e1e456e..c39f4cf 100755 --- a/tools/grit/grit/format/resource_map_unittest.py +++ b/tools/grit/grit/format/resource_map_unittest.py
@@ -109,14 +109,13 @@ formatter = resource_map.GetFormatter('gzipped_resource_file_map_source') output = util.StripBlankLinesAndComments(''.join(formatter(grd, 'en', '.'))) - gen_path = os.path.join('@out_folder@', 'gen', 'foo', 'bar', 'baz.js') expected = '''\ #include "gzipped_resource_map_header.h" #include <stddef.h> #include "base/stl_util.h" #include "the_rc_header.h" const GzippedGritResourceMap kTheRcHeader[] = { - {"''' + gen_path + '''", IDR_FOO_BAR_BAZ_JS, true}, + {"@out_folder@/gen/foo/bar/baz.js", IDR_FOO_BAR_BAZ_JS, true}, }; const size_t kTheRcHeaderSize = base::size(kTheRcHeader);''' self.assertEqual(expected, output)
diff --git a/tools/gritsettings/resource_ids b/tools/gritsettings/resource_ids index 30f7e24..2db73252 100644 --- a/tools/gritsettings/resource_ids +++ b/tools/gritsettings/resource_ids
@@ -81,29 +81,36 @@ # START chrome/browser section. "chrome/browser/browser_resources.grd": { "includes": [11000], - "structures": [12000], + "structures": [11900], }, "chrome/browser/resources/chromeos/cellular_setup/cellular_setup_resources.grd": { - "structures": [12040], + "structures": [11940], }, "chrome/browser/resources/chromeos/multidevice_setup/multidevice_setup_resources.grd": { - "structures": [12045], + "structures": [11945], }, "chrome/browser/resources/component_extension_resources.grd": { - "includes": [12100], - "structures": [12350], + "includes": [12000], + "structures": [12250], }, - "chrome/browser/resources/invalidations_resources.grd": { - "includes": [12400], + "chrome/browser/resources/downloads/downloads_resources_vulcanized.grd": { + "includes": [12300], }, - "chrome/browser/resources/local_ntp/local_ntp_resources.grd": { - "includes": [12440], + "chrome/browser/resources/downloads/downloads_resources.grd": { + "includes": [12310], + "structures": [12320], }, "chrome/browser/resources/extensions/extensions_resources_vulcanized.grd": { - "includes": [12500], + "includes": [12400], }, "chrome/browser/resources/extensions/extensions_resources.grd": { - "structures": [12510], + "structures": [12410], + }, + "chrome/browser/resources/invalidations_resources.grd": { + "includes": [12500], + }, + "chrome/browser/resources/local_ntp/local_ntp_resources.grd": { + "includes": [12540], }, "chrome/browser/resources/net_internals/net_internals_resources.grd": { "includes": [12600],
diff --git a/tools/gritsettings/translation_expectations.pyl b/tools/gritsettings/translation_expectations.pyl index b5d575f1..2b955b17 100644 --- a/tools/gritsettings/translation_expectations.pyl +++ b/tools/gritsettings/translation_expectations.pyl
@@ -98,5 +98,7 @@ # not be checked by translation script. "internal_grds": [ "chrome/browser/resources/kiosk_next_internal_resources.grd", + # Test grd that contains a part file that doesn't exist. + "tools/translation/testdata/internal.grd", ], }
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index 7fffad1c..36ee60a4 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -28097,6 +28097,16 @@ <int value="2" label="Both devices, pointing and keyboard, detected."/> </enum> +<enum name="HintCacheStoreEntryType"> + <summary> + Possible store entry types contained within the HintCacheStore. + </summary> + <int value="0" label="Unknown"/> + <int value="1" label="Metadata"/> + <int value="2" label="Component Hint"/> + <int value="3" label="Fetched Hint"/> +</enum> + <enum name="HistogramActivityReport"> <int value="0" label="Reports created"/> <int value="1" label="Histograms created"/> @@ -33730,6 +33740,7 @@ <int value="-424701311" label="SignedHTTPExchange:disabled"/> <int value="-424544273" label="enable-experimental-accessibility-chromevox-rich-text-indication"/> + <int value="-424134004" label="WebPaymentsExperimentalFeatures:disabled"/> <int value="-418868128" label="enable-experimental-web-platform-features"/> <int value="-416660617" label="EnforceTLS13Downgrade:disabled"/> <int value="-415186532" label="AndroidSiteSettingsUIRefresh:enabled"/> @@ -33818,6 +33829,7 @@ label="CrossOriginMediaPlaybackRequiresUserGesture:disabled"/> <int value="-296179618" label="CookiesWithoutSameSiteMustBeSecure:enabled"/> <int value="-290672626" label="enable-asm-wasm"/> + <int value="-290329565" label="CrosVmCupsProxy:disabled"/> <int value="-288316828" label="enable-delegated-renderer"/> <int value="-286603268" label="hide-android-files-in-files-app"/> <int value="-284547865" label="UnifiedConsent:enabled"/> @@ -34107,6 +34119,7 @@ label="OmniboxUIExperimentHideSteadyStateUrlScheme:disabled"/> <int value="133482330" label="AppNotificationStatusMessaging:enabled"/> <int value="143725809" label="DownloadProgressInfoBar:enabled"/> + <int value="146229312" label="WebPaymentsExperimentalFeatures:enabled"/> <int value="147342055" label="ChromeHomeClearUrlOnOpen:disabled"/> <int value="147373243" label="enable-deferred-image-decoding"/> <int value="149914698" label="SearchReadyOmnibox:disabled"/> @@ -34119,6 +34132,7 @@ <int value="173288154" label="PrintPdfAsImage:enabled"/> <int value="178337215" label="enable-md-history"/> <int value="180074362" label="memory-pressure-thresholds"/> + <int value="181150000" label="CrosVmCupsProxy:enabled"/> <int value="183208826" label="TabGroups:enabled"/> <int value="185991204" label="enable-webrtc-srtp-encrypted-headers"/> <int value="188610022" label="NewMessageListView:enabled"/> @@ -38165,6 +38179,31 @@ <int value="4" label="ReturnedToOrigin"/> </enum> +<enum name="MobileMessagesModalEvent"> + <int value="0" label="Accepted"/> + <int value="1" label="Canceled"/> + <int value="2" label="Dismissed"/> + <int value="3" label="Presented"/> + <int value="4" label="SettingsOpened"/> +</enum> + +<enum name="MobileMessagesPasswordsModalDismiss"> + <int value="0" label="TappedNeverForThisSite"/> + <int value="1" label="SavedCredentials"/> + <int value="2" label="UpdatedCredentials"/> +</enum> + +<enum name="MobileMessagesPasswordsModalEvent"> + <int value="0" label="EditedUserName"/> + <int value="1" label="EditedPassword"/> + <int value="2" label="UnmaskedPassword"/> +</enum> + +<enum name="MobileMessagesPasswordsModalPresent"> + <int value="0" label="PresentedAfterSaveBanner"/> + <int value="1" label="PresentedAfterUpdateBanner"/> +</enum> + <enum name="MobileSessionCallerApp"> <int value="0" label="Google Search"/> <int value="1" label="Gmail"/> @@ -58765,6 +58804,70 @@ <int value="46" label="kXForwardedProto"/> </enum> +<enum name="WebRequest.ResponseHeader"> + <int value="0" label="kNone"/> + <int value="1" label="kOther"/> + <int value="2" label="kAcceptPatch"/> + <int value="3" label="kAcceptRanges"/> + <int value="4" label="kAccessControlAllowCredentials"/> + <int value="5" label="kAccessControlAllowHeaders"/> + <int value="6" label="kAccessControlAllowMethods"/> + <int value="7" label="kAccessControlAllowOrigin"/> + <int value="8" label="kAccessControlExposeHeaders"/> + <int value="9" label="kAccessControlMaxAge"/> + <int value="10" label="kAge"/> + <int value="11" label="kAllow"/> + <int value="12" label="kAltSvc"/> + <int value="13" label="kCacheControl"/> + <int value="14" label="kClearSiteData"/> + <int value="15" label="kConnection"/> + <int value="16" label="kContentDisposition"/> + <int value="17" label="kContentEncoding"/> + <int value="18" label="kContentLanguage"/> + <int value="19" label="kContentLength"/> + <int value="20" label="kContentLocation"/> + <int value="21" label="kContentRange"/> + <int value="22" label="kContentSecurityPolicy"/> + <int value="23" label="kContentSecurityPolicyReportOnly"/> + <int value="24" label="kContentType"/> + <int value="25" label="kDate"/> + <int value="26" label="kETag"/> + <int value="27" label="kExpectCT"/> + <int value="28" label="kExpires"/> + <int value="29" label="kFeaturePolicy"/> + <int value="30" label="kKeepAlive"/> + <int value="31" label="kLargeAllocation"/> + <int value="32" label="kLastModified"/> + <int value="33" label="kLocation"/> + <int value="34" label="kPragma"/> + <int value="35" label="kProxyAuthenticate"/> + <int value="36" label="kProxyConnection"/> + <int value="37" label="kPublicKeyPins"/> + <int value="38" label="kPublicKeyPinsReportOnly"/> + <int value="39" label="kReferrerPolicy"/> + <int value="40" label="kRefresh"/> + <int value="41" label="kRetryAfter"/> + <int value="42" label="kSecWebSocketAccept"/> + <int value="43" label="kServer"/> + <int value="44" label="kServerTiming"/> + <int value="45" label="kSetCookie"/> + <int value="46" label="kSourceMap"/> + <int value="47" label="kStrictTransportSecurity"/> + <int value="48" label="kTimingAllowOrigin"/> + <int value="49" label="kTk"/> + <int value="50" label="kTrailer"/> + <int value="51" label="kTransferEncoding"/> + <int value="52" label="kUpgrade"/> + <int value="53" label="kVary"/> + <int value="54" label="kVia"/> + <int value="55" label="kWarning"/> + <int value="56" label="kWWWAuthenticate"/> + <int value="57" label="kXContentTypeOptions"/> + <int value="58" label="kXDNSPrefetchControl"/> + <int value="59" label="kXFrameOptions"/> + <int value="60" label="kXXSSProtection"/> +</enum> + <enum name="WebRequestEventListenerFlag"> <int value="0" label="Total"/> <int value="1" label="None"/>
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index 4f531cc..0cb239f 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -3377,6 +3377,18 @@ </summary> </histogram> +<histogram name="AndroidSms.EffectivePWAInstallationSuccess" + enum="BooleanSuccess" expires_after="2020-05-10"> + <owner>azeemarshad@chromium.org</owner> + <owner>jonmann@chromium.org</owner> + <summary> + Records effective final success/failure when trying to install Android + Messages for Web PWA. This is recorded once when any one of the installation + attempts succeed or when all attempts fails, irrespective of number of + retries. + </summary> +</histogram> + <histogram name="AndroidSms.FcmMessageDispatchFailure" enum="AndroidSmsFcmMessageType"> <owner>azeemarshad@chromium.org</owner> @@ -3417,12 +3429,23 @@ </summary> </histogram> +<histogram name="AndroidSms.NumAttemptsForSuccessfulInstallation" + units="attempts" expires_after="2020-05-10"> + <owner>azeemarshad@chromium.org</owner> + <owner>jonmann@chromium.org</owner> + <summary> + Records the number of installations attempted for Android Messages for Web + PWA before succeeding. + </summary> +</histogram> + <histogram name="AndroidSms.PWAInstallationResult" enum="WebAppInstallResultCode"> <owner>azeemarshad@chromium.org</owner> <summary> - Records installation result code when Android Messages for Web PWA is - installed through Multidevice setup or settings. + Records installation result code for every installation attempt for Android + Messages for Web PWA initiated through Multidevice setup or settings. This + metric also includes installation result for every failed retry. </summary> </histogram> @@ -36846,6 +36869,9 @@ </histogram> <histogram name="Extensions.ExtensionCreationTime" units="microseconds"> + <obsolete> + Removed 2019-05. + </obsolete> <owner>rdevlin.cronin@chromium.org</owner> <summary> The amount of time taken to create a single extension object. This includes @@ -38066,7 +38092,7 @@ <histogram name="Extensions.Messaging.IncludeChannelIdBehavior" enum="ExtensionMessagingIncludeChannelIdBehavior" - expires_after="2018-12-01"> + expires_after="2019-12-01"> <owner>rdevlin.cronin@chromium.org</owner> <owner>nharper@chromium.org</owner> <summary> @@ -39001,6 +39027,9 @@ <histogram name="Extensions.ThrottledNetworkRequests" units="requests" expires_after="2018-08-30"> + <obsolete> + Expired 2018-08. + </obsolete> <owner>rdevlin.cronin@chromium.org</owner> <summary> The total number of network requests that were delayed by extension user @@ -39377,8 +39406,47 @@ </summary> </histogram> +<histogram name="Extensions.WebRequest.ResponseHeaderAdded" + enum="WebRequest.ResponseHeader" expires_after="2019-10-31"> + <owner>karandeepb@chromium.org</owner> + <owner>rdevlin.cronin@chromium.org</owner> + <summary> + Records the response header added by extensions using the WebRequest API. + This is logged for the cumulative delta across all the web request + extensions. Recorded for each network request during the OnHeadersReceived + stage. Multiple samples can be recorded per request. + </summary> +</histogram> + +<histogram name="Extensions.WebRequest.ResponseHeaderChanged" + enum="WebRequest.ResponseHeader" expires_after="2019-10-31"> + <owner>karandeepb@chromium.org</owner> + <owner>rdevlin.cronin@chromium.org</owner> + <summary> + Records the response header modified by extensions using the WebRequest API. + This is logged for the cumulative delta across all the web request + extensions. Recorded for each network request during the OnHeadersReceived + stage. Multiple samples can be recorded per request. + </summary> +</histogram> + +<histogram name="Extensions.WebRequest.ResponseHeaderRemoved" + enum="WebRequest.ResponseHeader" expires_after="2019-10-31"> + <owner>karandeepb@chromium.org</owner> + <owner>rdevlin.cronin@chromium.org</owner> + <summary> + Records the response header removed by extensions using the WebRequest API. + This is logged for the cumulative delta across all the web request + extensions. Recorded for each network request during the OnHeadersReceived + stage. Multiple samples can be recorded per request. + </summary> +</histogram> + <histogram name="Extensions.WebRequest.SetCookieResponseHeaderChanged" enum="BooleanChanged" expires_after="M73"> + <obsolete> + Removed May 2019. + </obsolete> <owner>cduvall@chromium.org</owner> <owner>karandeepb@chromium.org</owner> <summary> @@ -39394,6 +39462,9 @@ <histogram name="Extensions.WebRequest.SetCookieResponseHeaderRemoved" enum="BooleanRemoved" expires_after="M73"> + <obsolete> + Removed May 2019. + </obsolete> <owner>cduvall@chromium.org</owner> <owner>karandeepb@chromium.org</owner> <summary> @@ -59485,7 +59556,7 @@ <owner>sczs@chromium.org</owner> <owner>thegreenfrog@chromium.org</owner> - <summary>Records the reason why a Banner event was dismissed.</summary> + <summary>Records the reason why a Banner was dismissed.</summary> </histogram> <histogram name="Mobile.Messages.Banner.Event" enum="MobileMessagesBannerEvent" @@ -59497,6 +59568,42 @@ <summary>Records Infobar Banner events.</summary> </histogram> +<histogram name="Mobile.Messages.Modal.Event" enum="MobileMessagesModalEvent" + expires_after="2022-05-01"> +<!-- Name completed by histogram_suffixes name="Mobile.Messages.Type" --> + + <owner>sczs@chromium.org</owner> + <owner>thegreenfrog@chromium.org</owner> + <summary>Records generic Infobar Modal events.</summary> +</histogram> + +<histogram name="Mobile.Messages.Passwords.Modal.Dismiss" + enum="MobileMessagesPasswordsModalDismiss" expires_after="2022-05-01"> +<!-- Name completed by histogram_suffixes name="Mobile.Messages.Password.Type" --> + + <owner>sczs@chromium.org</owner> + <owner>thegreenfrog@chromium.org</owner> + <summary>Records the reason why a Password Modal was dismissed.</summary> +</histogram> + +<histogram name="Mobile.Messages.Passwords.Modal.Event" + enum="MobileMessagesPasswordsModalEvent" expires_after="2022-05-01"> +<!-- Name completed by histogram_suffixes name="Mobile.Messages.Password.Type" --> + + <owner>sczs@chromium.org</owner> + <owner>thegreenfrog@chromium.org</owner> + <summary>Records Password specific Infobar Modal events.</summary> +</histogram> + +<histogram name="Mobile.Messages.Passwords.Modal.Present" + enum="MobileMessagesPasswordsModalPresent" expires_after="2022-05-01"> +<!-- Name completed by histogram_suffixes name="Mobile.Messages.Password.Type" --> + + <owner>sczs@chromium.org</owner> + <owner>thegreenfrog@chromium.org</owner> + <summary>Records the context when a Password Modal was presented.</summary> +</histogram> + <histogram name="Mobile.RecentTabsManager.TotalTabsFromOtherDevicesOpenAll" units="count" expires_after="2022-04-19"> <owner>sczs@chromium.org</owner> @@ -77505,7 +77612,7 @@ </histogram> <histogram name="NewTabPage.SearchSuggestions.RequestStatusV2" - enum="NTPSearchSuggestionsRequestStatus" expires_after="M76"> + enum="NTPSearchSuggestionsRequestStatus" expires_after="M78"> <owner>kmilka@chromium.org</owner> <owner>ramyan@chromium.org</owner> <summary> @@ -94973,6 +95080,22 @@ </summary> </histogram> +<histogram name="Power.BatteryPercentDrop" units="%"> + <owner>ryansturm@chromium.org</owner> + <owner>tbansal@chromium.org</owner> + <summary> + The drop in battery since the last operating system battery update as a + percent of total device battery. If the drop is not a round percentage + point, the unreported amount will be carried over until the battery level + drops by a full percentage point. Recorded when the battery level drops by + more than a percentage point. If the user charges the device, the battery + tracking is reset (the amount carried over is reset). This histograms sum is + most likely the most useful figure when comparing experiments. Recorded even + when Chrome is in the background. Not recorded on Windows. TODO: record on + Windows: https://crbug.com/794105. + </summary> +</histogram> + <histogram name="Power.BatteryRemainingAtEndOfSessionOnAC" units="%"> <owner>derat@chromium.org</owner> <summary> @@ -97696,6 +97819,16 @@ </summary> </histogram> +<histogram name="Previews.OptimizationGuide.HintCache.HintType.Loaded" + enum="HintCacheStoreEntryType" expires_after="M79"> + <owner>mcrouse@chromium.org</owner> + <owner>dougarnett@chromium.org</owner> + <summary> + Records the store entry type of a hint when it is loaded from the hint cache + store. + </summary> +</histogram> + <histogram name="Previews.OptimizationGuide.HintCache.HostMatch.AtCommit" enum="NQEEffectiveConnectionType"> <owner>dougarnett@chromium.org</owner> @@ -149734,11 +149867,21 @@ <affected-histogram name="Mobile.DefaultBrowser.BrowserCount"/> </histogram_suffixes> +<histogram_suffixes name="Mobile.Messages.Password.Type" separator="."> + <suffix name="InfobarTypePasswordSave"/> + <suffix name="InfobarTypePasswordUpdate"/> + <affected-histogram name="Mobile.Messages.Passwords.Modal.Dismiss"/> + <affected-histogram name="Mobile.Messages.Passwords.Modal.Event"/> + <affected-histogram name="Mobile.Messages.Passwords.Modal.Present"/> +</histogram_suffixes> + <histogram_suffixes name="Mobile.Messages.Type" separator="."> <suffix name="InfobarTypeConfirm"/> - <suffix name="InfobarTypePassword"/> + <suffix name="InfobarTypePasswordSave"/> + <suffix name="InfobarTypePasswordUpdate"/> <affected-histogram name="Mobile.Messages.Banner.Dismiss"/> <affected-histogram name="Mobile.Messages.Banner.Event"/> + <affected-histogram name="Mobile.Messages.Modal.Event"/> </histogram_suffixes> <histogram_suffixes name="MobileDownloadBytesDownloadedTypes" separator="."> @@ -154292,6 +154435,9 @@ </histogram_suffixes> <histogram_suffixes name="ProcessType" separator="."> + <obsolete> + Removed 2019-05 + </obsolete> <suffix name="BrowserProcess" label="Browser Process"/> <suffix name="ExtensionProcess" label="Extension Process"/> <suffix name="RendererProcess"
diff --git a/tools/perf/expectations.config b/tools/perf/expectations.config index 2eaeb96..91ede4a2 100644 --- a/tools/perf/expectations.config +++ b/tools/perf/expectations.config
@@ -254,6 +254,7 @@ crbug.com/923116 [ Android ] system_health.common_mobile/browse:shopping:avito [ Skip ] crbug.com/923527 [ Android_Webview ] system_health.common_mobile/load:media:soundcloud:2018 [ Skip ] crbug.com/954949 [ Nexus5X_Webview ] system_health.common_mobile/browse:news:washingtonpost [ Skip ] +crbug.com/961417 [ Android_Go ] system_health.common_mobile/browse:social:tumblr_infinite_scroll:2018 [ Skip ] # Benchmark: system_health.memory_desktop crbug.com/649392 [ All ] system_health.memory_desktop/play:media:google_play_music [ Skip ] @@ -304,6 +305,9 @@ crbug.com/923527 [ Android_Webview ] system_health.memory_mobile/load:media:soundcloud:2018 [ Skip ] crbug.com/947267 [ Nexus_5X ] system_health.memory_mobile/background:media:imgur [ Skip ] crbug.com/954949 [ Nexus5X_Webview ] system_health.memory_mobile/browse:news:washingtonpost [ Skip ] +crbug.com/961434 [ Android_Go_Webview ] system_health.memory_mobile/browse:shopping:lazada [ Skip ] +crbug.com/961434 [ Android_Go_Webview ] system_health.memory_mobile/browse:shopping:amazon [ Skip ] +crbug.com/961417 [ Android_Go ] system_health.memory_mobile/browse:social:tumblr_infinite_scroll:2018 [ Skip ] # Benchmark: tab_switching.typical_25 crbug.com/747026 [ Mac ] tab_switching.typical_25/multitab:misc:typical24 [ Skip ] @@ -348,6 +352,8 @@ crbug.com/923116 [ Android ] v8.browsing_mobile/browse:shopping:avito [ Skip ] crbug.com/929839 [ Android_Go ] v8.browsing_mobile/browse:chrome:newtab [ Skip ] crbug.com/954949 [ Nexus5X_Webview ] v8.browsing_mobile/browse:news:washingtonpost [ Skip ] +crbug.com/961434 [ Android_Go ] v8.browsing_mobile/browse:shopping:lazada [ Skip ] +crbug.com/961417 [ Android_Go ] v8.browsing_mobile/browse:social:tumblr_infinite_scroll:2018 [ Skip ] # Benchmark: v8.browsing_mobile-future crbug.com/714650 [ Android ] v8.browsing_mobile-future/browse:news:globo [ Skip ]
diff --git a/ui/chromeos/events/event_rewriter_chromeos.cc b/ui/chromeos/events/event_rewriter_chromeos.cc index 9ec01ec..7722e2b 100644 --- a/ui/chromeos/events/event_rewriter_chromeos.cc +++ b/ui/chromeos/events/event_rewriter_chromeos.cc
@@ -1496,17 +1496,22 @@ {{ui::EF_NONE, ui::VKEY_ZOOM}, {ui::EF_NONE, ui::DomCode::ZOOM_TOGGLE, ui::DomKey::ZOOM_TOGGLE, ui::VKEY_MEDIA_LAUNCH_APP2}}, + // Next keyboard layout IME is through space + control + shift + {{ui::EF_NONE, ui::VKEY_MODECHANGE}, + {ui::EF_CONTROL_DOWN | ui::EF_SHIFT_DOWN, + ui::DomCode::KEYBOARD_LAYOUT_SELECT, ui::DomKey::MODE_CHANGE, + ui::VKEY_SPACE}}, }; - // Key codes KEY_SCALE and KEY_SWITCHVIDEOMODE have a Dom code but no VKEY - // value assigned. They're mapped to VKEY values here so that - // KEY_SCALE == "show all windows" and KEY_SWITCHVIDEOMODE == "display - // toggle int/ext". + // Some key codes have a Dom code but no VKEY value assigned. They're mapped + // to VKEY values here. if (state->key_code == ui::VKEY_UNKNOWN) { if (state->code == ui::DomCode::SHOW_ALL_WINDOWS) { + // Show all windows is through VKEY_MEDIA_LAUNCH_APP1. state->key_code = ui::VKEY_MEDIA_LAUNCH_APP1; state->key = ui::DomKey::F4; } else if (state->code == ui::DomCode::DISPLAY_TOGGLE_INT_EXT) { + // Display toggle is through control + VKEY_MEDIA_LAUNCH_APP2. state->flags |= ui::EF_CONTROL_DOWN; state->key_code = ui::VKEY_MEDIA_LAUNCH_APP2; state->key = ui::DomKey::F12; @@ -1517,10 +1522,9 @@ incoming_without_command.flags &= ~ui::EF_COMMAND_DOWN; // Map certain action keys to the right VKey and modifier. - if (RewriteWithKeyboardRemappings(kActionToActionKeys, - base::size(kActionToActionKeys), - incoming_without_command, state)) { - } + RewriteWithKeyboardRemappings(kActionToActionKeys, + base::size(kActionToActionKeys), + incoming_without_command, state); if ((state->key_code >= ui::VKEY_F1) && (state->key_code <= ui::VKEY_F12)) { // Incoming key code is a Fn key. Check if it needs to be mapped back to its
diff --git a/ui/events/keycodes/dom/keycode_converter_data.inc b/ui/events/keycodes/dom/keycode_converter_data.inc index e21aa333..65bd4e8e 100644 --- a/ui/events/keycodes/dom/keycode_converter_data.inc +++ b/ui/events/keycodes/dom/keycode_converter_data.inc
@@ -586,6 +586,9 @@ USB_KEYMAP(0x0c028b, 0x00e9, 0x00f1, 0x0000, 0xffff, "MailForward", MAIL_FORWARD), // USB#0x0c028c: AC_Send USB_KEYMAP(0x0c028c, 0x00e7, 0x00ef, 0x0000, 0xffff, "MailSend", MAIL_SEND), + // USB#0x0c029d: AC Next Keyboard Layout Select + USB_KEYMAP(0x0c029d, 0x0248, 0x0250, 0x0000, 0xffff, "KeyboardLayoutSelect", + KEYBOARD_LAYOUT_SELECT), USB_KEYMAP(0x0c029f, 0x0078, 0x0080, 0x0000, 0xffff, "ShowAllWindows", SHOW_ALL_WINDOWS), // AC Desktop Show All Windows };
diff --git a/ui/events/keycodes/dom/keycode_converter_unittest.cc b/ui/events/keycodes/dom/keycode_converter_unittest.cc index b82d525..db3ce82 100644 --- a/ui/events/keycodes/dom/keycode_converter_unittest.cc +++ b/ui/events/keycodes/dom/keycode_converter_unittest.cc
@@ -24,8 +24,8 @@ // These are in the same order as the columns in keycode_converter_data.inc // as reflected in the USB_KEYMAP() macro below. const size_t expected_mapped_key_count[] = { - 211, // evdev - 211, // xkb + 212, // evdev + 212, // xkb 157, // windows 118, // mac };
diff --git a/ui/events/keycodes/dom_us_layout_data.h b/ui/events/keycodes/dom_us_layout_data.h index d5a1516..1f625974 100644 --- a/ui/events/keycodes/dom_us_layout_data.h +++ b/ui/events/keycodes/dom_us_layout_data.h
@@ -170,6 +170,7 @@ {DomCode::INSERT, DomKey::INSERT}, // {DomCode::INTL_RO, DomKey::_} {DomCode::KANA_MODE, DomKey::KANA_MODE}, + {DomCode::KEYBOARD_LAYOUT_SELECT, DomKey::MODE_CHANGE}, {DomCode::LANG1, DomKey::HANGUL_MODE}, {DomCode::LANG2, DomKey::HANJA_MODE}, {DomCode::LANG3, DomKey::KATAKANA},
diff --git a/ui/gfx/canvas.cc b/ui/gfx/canvas.cc index a787710..b65334e 100644 --- a/ui/gfx/canvas.cc +++ b/ui/gfx/canvas.cc
@@ -358,17 +358,11 @@ ScopedCanvas scoper(this); canvas_->scale(SkFloatToScalar(1.0f / bitmap_scale), SkFloatToScalar(1.0f / bitmap_scale)); - if (base::FeatureList::IsEnabled(features::kUsePaintRecordForImageSkia)) { - canvas_->translate(std::round(x * bitmap_scale), - std::round(y * bitmap_scale)); - canvas_->saveLayer(nullptr, &flags); - canvas_->drawPicture(image_rep.GetPaintRecord()); - canvas_->restore(); - } else { - canvas_->drawImage(image_rep.paint_image(), - SkFloatToScalar(x * bitmap_scale), - SkFloatToScalar(y * bitmap_scale), &flags); - } + canvas_->translate(std::round(x * bitmap_scale), + std::round(y * bitmap_scale)); + canvas_->saveLayer(nullptr, &flags); + canvas_->drawPicture(image_rep.GetPaintRecord()); + canvas_->restore(); } void Canvas::DrawImageInt(const ImageSkia& image,
diff --git a/ui/gfx/image/canvas_image_source.cc b/ui/gfx/image/canvas_image_source.cc index c6ddb53c..f0768ed 100644 --- a/ui/gfx/image/canvas_image_source.cc +++ b/ui/gfx/image/canvas_image_source.cc
@@ -53,35 +53,29 @@ : size_(size), is_opaque_(is_opaque) {} ImageSkiaRep CanvasImageSource::GetImageForScale(float scale) { - if (base::FeatureList::IsEnabled(features::kUsePaintRecordForImageSkia)) { - scoped_refptr<cc::DisplayItemList> display_item_list = - base::MakeRefCounted<cc::DisplayItemList>( - cc::DisplayItemList::kToBeReleasedAsPaintOpBuffer); - display_item_list->StartPaint(); + scoped_refptr<cc::DisplayItemList> display_item_list = + base::MakeRefCounted<cc::DisplayItemList>( + cc::DisplayItemList::kToBeReleasedAsPaintOpBuffer); + display_item_list->StartPaint(); - SizeF size_in_pixel = ScaleSize(SizeF(size_), scale); - cc::RecordPaintCanvas record_canvas( - display_item_list.get(), - SkRect::MakeWH(SkFloatToScalar(size_in_pixel.width()), - SkFloatToScalar(size_in_pixel.height()))); - gfx::Canvas canvas(&record_canvas, scale); + SizeF size_in_pixel = ScaleSize(SizeF(size_), scale); + cc::RecordPaintCanvas record_canvas( + display_item_list.get(), + SkRect::MakeWH(SkFloatToScalar(size_in_pixel.width()), + SkFloatToScalar(size_in_pixel.height()))); + gfx::Canvas canvas(&record_canvas, scale); #if DCHECK_IS_ON() - Rect clip_rect; - DCHECK(canvas.GetClipBounds(&clip_rect)); - DCHECK(clip_rect.Contains(gfx::Rect(ToCeiledSize(size_in_pixel)))); + Rect clip_rect; + DCHECK(canvas.GetClipBounds(&clip_rect)); + DCHECK(clip_rect.Contains(gfx::Rect(ToCeiledSize(size_in_pixel)))); #endif - canvas.Scale(scale, scale); - Draw(&canvas); - - display_item_list->EndPaintOfPairedEnd(); - display_item_list->Finalize(); - return ImageSkiaRep(display_item_list->ReleaseAsRecord(), - gfx::ScaleToCeiledSize(size_, scale), scale); - } - - gfx::Canvas canvas(size_, scale, is_opaque_); + canvas.Scale(scale, scale); Draw(&canvas); - return ImageSkiaRep(canvas.GetBitmap(), scale); + + display_item_list->EndPaintOfPairedEnd(); + display_item_list->Finalize(); + return ImageSkiaRep(display_item_list->ReleaseAsRecord(), + gfx::ScaleToCeiledSize(size_, scale), scale); } } // namespace gfx
diff --git a/ui/gfx/render_text.cc b/ui/gfx/render_text.cc index 9c38cd6d..9d665b9 100644 --- a/ui/gfx/render_text.cc +++ b/ui/gfx/render_text.cc
@@ -1593,6 +1593,16 @@ // the preceding text using LTR or RTL markers. base::i18n::TextDirection trailing_text_direction = base::i18n::GetLastStrongCharacterDirection(new_text); + + // Ensures that the |new_text| will always be smaller or equal to the + // original text. There is a corner case when only one character is elided + // and two characters are added back (ellipsis and directional marker). + if (trailing_text_direction != text_direction && + new_text.length() + 2 > text.length() && guess >= 1) { + new_text = slicer.CutString(guess - 1, false); + } + + // Append the ellipsis and the optional directional marker characters. new_text.append(ellipsis); if (trailing_text_direction != text_direction) { if (trailing_text_direction == base::i18n::LEFT_TO_RIGHT) @@ -1601,6 +1611,10 @@ new_text += base::i18n::kRightToLeftMark; } } + + // The elided text must be smaller in bytes. Otherwise, break-lists are not + // consistent and the characters after the last range are not styled. + DCHECK_LE(new_text.size(), text.size()); render_text->SetText(new_text); // Restore styles and baselines without breaking multi-character graphemes.
diff --git a/ui/gfx/render_text_unittest.cc b/ui/gfx/render_text_unittest.cc index f78aab4..86f7f7f 100644 --- a/ui/gfx/render_text_unittest.cc +++ b/ui/gfx/render_text_unittest.cc
@@ -1097,6 +1097,46 @@ } } +TEST_F(RenderTextTest, ElidedStyledTextRtl) { + static const char* kInputTexts[] = { + "http://ar.wikipedia.com/فحص", + "testحص,", + "حص,test", + "…", + "…test", + "test…", + "حص,test…", + "ٱ", + "\uFEFF", // BOM: Byte Order Marker + "…\u200F", // Right to left marker. + }; + + for (const auto* raw_text : kInputTexts) { + SCOPED_TRACE( + base::StringPrintf("ElidedStyledTextRtl text = %s", raw_text)); + base::string16 input_text(UTF8ToUTF16(raw_text)); + + RenderText* render_text = GetRenderText(); + render_text->SetText(input_text); + render_text->SetElideBehavior(ELIDE_TAIL); + render_text->SetStyle(TEXT_STYLE_STRIKE, true); + render_text->SetDirectionalityMode(DIRECTIONALITY_FORCE_LTR); + + constexpr int kMaxContentWidth = 2000; + for (int i = 0; i < kMaxContentWidth; ++i) { + SCOPED_TRACE(base::StringPrintf("ElidedStyledTextRtl width = %d", i)); + render_text->SetDisplayRect(Rect(i, 20)); + render_text->GetStringSize(); + base::string16 display_text = render_text->GetDisplayText(); + EXPECT_LE(display_text.size(), input_text.size()); + + // Every size of content width was tried. + if (display_text == input_text) + break; + } + } +} // namespace gfx + TEST_F(RenderTextTest, ElidedEmail) { RenderText* render_text = GetRenderText(); render_text->SetText(UTF8ToUTF16("test@example.com"));
diff --git a/ui/gfx/skia_paint_util.cc b/ui/gfx/skia_paint_util.cc index 410048c..a7667a1 100644 --- a/ui/gfx/skia_paint_util.cc +++ b/ui/gfx/skia_paint_util.cc
@@ -43,11 +43,9 @@ // TODO(malaykeshav): The check for has_paint_image was only added here to // prevent generating a paint record in tests. Tests need an instance of // base::DiscardableMemoryAllocator to generate the PaintRecord. However most - // test suites dont have this set. Ensure that the check is removed before - // enabling the |kUsePaintRecordForImageSkia| feature by default. + // test suites don't have this set. // https://crbug.com/891469 - if (base::FeatureList::IsEnabled(features::kUsePaintRecordForImageSkia) && - !image_rep.has_paint_image()) { + if (!image_rep.has_paint_image()) { return cc::PaintShader::MakePaintRecord( image_rep.GetPaintRecord(), SkRect::MakeIWH(image_rep.pixel_width(), image_rep.pixel_height()),
diff --git a/ui/gfx/switches.cc b/ui/gfx/switches.cc index 53de8869..189e147e 100644 --- a/ui/gfx/switches.cc +++ b/ui/gfx/switches.cc
@@ -19,13 +19,3 @@ const char kEnableNativeGpuMemoryBuffers[] = "enable-native-gpu-memory-buffers"; } // namespace switches - -namespace features { - -// Enables or disables the use of cc::PaintRecords as a backing store for -// ImageSkiaReps. This may reduce load on the UI thread by moving rasterization -// of drawables away from this thread. -const base::Feature kUsePaintRecordForImageSkia{ - "UsePaintRecordForImageSkia", base::FEATURE_ENABLED_BY_DEFAULT}; - -} // namespace features
diff --git a/ui/gfx/switches.h b/ui/gfx/switches.h index 3b87320..c95989ae 100644 --- a/ui/gfx/switches.h +++ b/ui/gfx/switches.h
@@ -5,7 +5,6 @@ #ifndef UI_GFX_SWITCHES_H_ #define UI_GFX_SWITCHES_H_ -#include "base/feature_list.h" #include "build/build_config.h" #include "ui/gfx/switches_export.h" @@ -19,10 +18,4 @@ } // namespace switches -namespace features { - -GFX_SWITCHES_EXPORT extern const base::Feature kUsePaintRecordForImageSkia; - -} // namespace features - #endif // UI_GFX_SWITCHES_H_
diff --git a/ui/gl/BUILD.gn b/ui/gl/BUILD.gn index 1753dd48..70246bc 100644 --- a/ui/gl/BUILD.gn +++ b/ui/gl/BUILD.gn
@@ -297,6 +297,8 @@ "gl_wgl_api_implementation.h", "vsync_provider_win.cc", "vsync_provider_win.h", + "vsync_thread_win.cc", + "vsync_thread_win.h", ] libs = [ "dwmapi.lib" ]
diff --git a/ui/gl/gl_surface.cc b/ui/gl/gl_surface.cc index 23a60802..203553d 100644 --- a/ui/gl/gl_surface.cc +++ b/ui/gl/gl_surface.cc
@@ -242,6 +242,12 @@ return nullptr; } +bool GLSurface::SupportsGpuVSync() const { + return false; +} + +void GLSurface::SetGpuVSyncEnabled(bool enabled) {} + GLSurface* GLSurface::GetCurrent() { return current_surface_.Pointer()->Get(); } @@ -492,6 +498,14 @@ return surface_->SupportsPlaneGpuFences(); } +bool GLSurfaceAdapter::SupportsGpuVSync() const { + return surface_->SupportsGpuVSync(); +} + +void GLSurfaceAdapter::SetGpuVSyncEnabled(bool enabled) { + surface_->SetGpuVSyncEnabled(enabled); +} + GLSurfaceAdapter::~GLSurfaceAdapter() {} scoped_refptr<GLSurface> InitializeGLSurfaceWithFormat(
diff --git a/ui/gl/gl_surface.h b/ui/gl/gl_surface.h index e24062d..1642a87 100644 --- a/ui/gl/gl_surface.h +++ b/ui/gl/gl_surface.h
@@ -301,6 +301,10 @@ // Return the interface used for querying EGL timestamps. virtual EGLTimestampClient* GetEGLTimestampClient(); + virtual bool SupportsGpuVSync() const; + + virtual void SetGpuVSyncEnabled(bool enabled); + static GLSurface* GetCurrent(); protected: @@ -392,6 +396,8 @@ void SetEnableSwapTimestamps() override; bool SupportsPlaneGpuFences() const override; int GetBufferCount() const override; + bool SupportsGpuVSync() const override; + void SetGpuVSyncEnabled(bool enabled) override; GLSurface* surface() const { return surface_.get(); }
diff --git a/ui/gl/vsync_thread_win.cc b/ui/gl/vsync_thread_win.cc new file mode 100644 index 0000000..98460e34 --- /dev/null +++ b/ui/gl/vsync_thread_win.cc
@@ -0,0 +1,119 @@ +// 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 "ui/gl/vsync_thread_win.h" + +#include "base/bind.h" + +namespace gl { +namespace { +Microsoft::WRL::ComPtr<IDXGIOutput> DXGIOutputFromMonitor( + HMONITOR monitor, + const Microsoft::WRL::ComPtr<ID3D11Device>& d3d11_device) { + Microsoft::WRL::ComPtr<IDXGIDevice> dxgi_device; + if (FAILED(d3d11_device.As(&dxgi_device))) { + DLOG(ERROR) << "Failed to retrieve DXGI device"; + return nullptr; + } + + Microsoft::WRL::ComPtr<IDXGIAdapter> dxgi_adapter; + if (FAILED(dxgi_device->GetAdapter(&dxgi_adapter))) { + DLOG(ERROR) << "Failed to retrieve DXGI adapter"; + return nullptr; + } + + size_t i = 0; + while (true) { + Microsoft::WRL::ComPtr<IDXGIOutput> output; + if (FAILED(dxgi_adapter->EnumOutputs(i++, &output))) + break; + + DXGI_OUTPUT_DESC desc = {}; + if (FAILED(output->GetDesc(&desc))) { + DLOG(ERROR) << "DXGI output GetDesc failed"; + return nullptr; + } + + if (desc.Monitor == monitor) + return output; + } + + return nullptr; +} +} // namespace + +VSyncThreadWin::VSyncThreadWin( + HWND window, + Microsoft::WRL::ComPtr<ID3D11Device> d3d11_device, + VSyncCallback callback) + : vsync_thread_("GpuVSyncThread"), + window_(window), + d3d11_device_(std::move(d3d11_device)), + callback_(std::move(callback)) { + DCHECK(window_); + DCHECK(callback_); + vsync_thread_.Start(); +} + +VSyncThreadWin::~VSyncThreadWin() { + vsync_thread_.Stop(); +} + +void VSyncThreadWin::SetEnabled(bool enabled) { + base::AutoLock auto_lock(lock_); + if (enabled_ == enabled) + return; + enabled_ = enabled; + if (enabled_ && !started_) { + started_ = true; + vsync_thread_.task_runner()->PostTask( + FROM_HERE, + base::BindOnce(&VSyncThreadWin::WaitForVSync, base::Unretained(this))); + } +} + +void VSyncThreadWin::WaitForVSync() { + HMONITOR monitor = MonitorFromWindow(window_, MONITOR_DEFAULTTONEAREST); + if (window_monitor_ != monitor) { + window_monitor_ = monitor; + window_output_ = DXGIOutputFromMonitor(monitor, d3d11_device_); + } + + MONITORINFOEX monitor_info; + monitor_info.cbSize = sizeof(MONITORINFOEX); + base::TimeDelta interval = base::TimeDelta::FromSecondsD(1.0 / 60); + if (GetMonitorInfo(monitor, &monitor_info)) { + DEVMODE display_info; + display_info.dmSize = sizeof(DEVMODE); + display_info.dmDriverExtra = 0; + if (EnumDisplaySettings(monitor_info.szDevice, ENUM_CURRENT_SETTINGS, + &display_info) && + display_info.dmDisplayFrequency > 1) { + interval = + base::TimeDelta::FromSecondsD(1.0 / display_info.dmDisplayFrequency); + } + } + + if (window_output_) { + window_output_->WaitForVBlank(); + } else { + Sleep(static_cast<DWORD>(interval.InMilliseconds())); + } + + base::AutoLock auto_lock(lock_); + DCHECK(started_); + if (enabled_) { + vsync_thread_.task_runner()->PostTask( + FROM_HERE, + base::BindOnce(&VSyncThreadWin::WaitForVSync, base::Unretained(this))); + // Release lock before running callback to guard against any reentracny + // deadlock. + base::AutoUnlock auto_unlock(lock_); + callback_.Run(base::TimeTicks::Now(), interval); + } else { + started_ = false; + } +} + +} // namespace gl
diff --git a/ui/gl/vsync_thread_win.h b/ui/gl/vsync_thread_win.h new file mode 100644 index 0000000..f540f75 --- /dev/null +++ b/ui/gl/vsync_thread_win.h
@@ -0,0 +1,56 @@ +// 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 UI_GL_VSYNC_THREAD_WIN_H_ +#define UI_GL_VSYNC_THREAD_WIN_H_ + +#include <d3d11.h> +#include <windows.h> +#include <wrl/client.h> + +#include "base/threading/thread.h" +#include "ui/gl/gl_export.h" + +namespace gl { + +// Helper class that manages a thread for calling IDXGIOutput::WaitForVBlank() +// for the output corresponding to the given |window|, and runs |callback| on +// the same thread. The callback can be enabled or disabled via SetEnabled(). +// This is used by DirectCompositionSurfaceWin to plumb vsync signal back to the +// display compositor's BeginFrameSource. +class GL_EXPORT VSyncThreadWin { + public: + using VSyncCallback = + base::RepeatingCallback<void(base::TimeTicks, base::TimeDelta)>; + VSyncThreadWin(HWND window, + Microsoft::WRL::ComPtr<ID3D11Device> d3d11_device, + VSyncCallback callback); + ~VSyncThreadWin(); + + void SetEnabled(bool enabled); + + private: + void WaitForVSync(); + + base::Thread vsync_thread_; + + // Used on vsync thread only after initialization. + const HWND window_; + const Microsoft::WRL::ComPtr<ID3D11Device> d3d11_device_; + const VSyncCallback callback_; + + // Used on vsync thread exclusively. + HMONITOR window_monitor_ = nullptr; + Microsoft::WRL::ComPtr<IDXGIOutput> window_output_; + + base::Lock lock_; + bool GUARDED_BY(lock_) enabled_ = false; + bool GUARDED_BY(lock_) started_ = false; + + DISALLOW_COPY_AND_ASSIGN(VSyncThreadWin); +}; + +} // namespace gl + +#endif // UI_GL_VSYNC_THREAD_WIN_H_
diff --git a/ui/keyboard/public/keyboard_switches.cc b/ui/keyboard/public/keyboard_switches.cc index 247b92a..539094a0 100644 --- a/ui/keyboard/public/keyboard_switches.cc +++ b/ui/keyboard/public/keyboard_switches.cc
@@ -7,7 +7,6 @@ namespace keyboard { namespace switches { -const char kDisableGestureTyping[] = "disable-gesture-typing"; const char kEnableVirtualKeyboard[] = "enable-virtual-keyboard"; } // namespace switches
diff --git a/ui/keyboard/public/keyboard_switches.h b/ui/keyboard/public/keyboard_switches.h index 6931e7c..772fb27 100644 --- a/ui/keyboard/public/keyboard_switches.h +++ b/ui/keyboard/public/keyboard_switches.h
@@ -10,9 +10,6 @@ namespace keyboard { namespace switches { -// Flag which disables gesture typing for the virtual keyboard. -KEYBOARD_EXPORT extern const char kDisableGestureTyping[]; - // Enables the virtual keyboard. KEYBOARD_EXPORT extern const char kEnableVirtualKeyboard[];
diff --git a/ui/views/controls/button/label_button.cc b/ui/views/controls/button/label_button.cc index 4462c920..a49bfc11 100644 --- a/ui/views/controls/button/label_button.cc +++ b/ui/views/controls/button/label_button.cc
@@ -59,8 +59,6 @@ SetTextInternal(text); AddChildView(ink_drop_container_); - ink_drop_container_->SetPaintToLayer(); - ink_drop_container_->layer()->SetFillsBoundsOpaquely(false); ink_drop_container_->SetVisible(false); AddChildView(image_);
diff --git a/ui/views/metadata/metadata_types.h b/ui/views/metadata/metadata_types.h index 87427de..b35c197 100644 --- a/ui/views/metadata/metadata_types.h +++ b/ui/views/metadata/metadata_types.h
@@ -185,8 +185,8 @@ ~ClassPropertyMetaData() override = default; void SetValueAsString(void* obj, const base::string16& new_value) override { - (static_cast<TClass*>(obj)->*Set)( - Convert<base::string16, TValue>(new_value)); + (static_cast<TClass*>(obj)->*Set)(Convert<base::string16, TValue>( + new_value, (static_cast<TClass*>(obj)->*Get)())); } PropertyFlags GetPropertyFlags() const override {
diff --git a/ui/views/metadata/type_conversion.cc b/ui/views/metadata/type_conversion.cc index e992d145..63a0473 100644 --- a/ui/views/metadata/type_conversion.cc +++ b/ui/views/metadata/type_conversion.cc
@@ -84,81 +84,97 @@ } template <> -int8_t ConvertFromString<int8_t>(const base::string16& source_value) { +int8_t ConvertFromString<int8_t>(const base::string16& source_value, + int8_t default_value) { int32_t ret = 0; return base::StringToInt(source_value, &ret) && base::IsValueInRangeForNumericType<int8_t>(ret) ? static_cast<int8_t>(ret) - : 0; + : default_value; } template <> -int16_t ConvertFromString<int16_t>(const base::string16& source_value) { +int16_t ConvertFromString<int16_t>(const base::string16& source_value, + int16_t default_value) { int32_t ret = 0; return base::StringToInt(source_value, &ret) && base::IsValueInRangeForNumericType<int16_t>(ret) ? static_cast<int16_t>(ret) - : 0; + : default_value; } template <> -int32_t ConvertFromString<int32_t>(const base::string16& source_value) { +int32_t ConvertFromString<int32_t>(const base::string16& source_value, + int32_t default_value) { int32_t ret = 0; - return base::StringToInt(source_value, &ret) ? static_cast<int32_t>(ret) : 0; + return base::StringToInt(source_value, &ret) ? static_cast<int32_t>(ret) + : default_value; } template <> -int64_t ConvertFromString<int64_t>(const base::string16& source_value) { +int64_t ConvertFromString<int64_t>(const base::string16& source_value, + int64_t default_value) { int64_t ret = 0; - return base::StringToInt64(source_value, &ret) ? ret : 0; + return base::StringToInt64(source_value, &ret) ? ret : default_value; } template <> -uint8_t ConvertFromString<uint8_t>(const base::string16& source_value) { +uint8_t ConvertFromString<uint8_t>(const base::string16& source_value, + uint8_t default_value) { uint32_t ret = 0; return base::StringToUint(source_value, &ret) && base::IsValueInRangeForNumericType<uint8_t>(ret) ? static_cast<uint8_t>(ret) - : 0; + : default_value; } template <> -uint16_t ConvertFromString<uint16_t>(const base::string16& source_value) { +uint16_t ConvertFromString<uint16_t>(const base::string16& source_value, + uint16_t default_value) { uint32_t ret = 0; return base::StringToUint(source_value, &ret) && base::IsValueInRangeForNumericType<uint16_t>(ret) ? static_cast<uint16_t>(ret) - : 0; + : default_value; } template <> -uint32_t ConvertFromString<uint32_t>(const base::string16& source_value) { +uint32_t ConvertFromString<uint32_t>(const base::string16& source_value, + uint32_t default_value) { uint32_t ret = 0; return base::StringToUint(source_value, &ret) ? static_cast<uint32_t>(ret) - : 0; + : default_value; } template <> -uint64_t ConvertFromString<uint64_t>(const base::string16& source_value) { +uint64_t ConvertFromString<uint64_t>(const base::string16& source_value, + uint64_t default_value) { uint64_t ret = 0; - return base::StringToUint64(source_value, &ret) ? ret : 0; + return base::StringToUint64(source_value, &ret) ? ret : default_value; } template <> -float ConvertFromString<float>(const base::string16& source_value) { - return static_cast<float>(ConvertFromString<double>(source_value)); +float ConvertFromString<float>(const base::string16& source_value, + float default_value) { + return static_cast<float>( + ConvertFromString<double>(source_value, default_value)); } template <> -double ConvertFromString<double>(const base::string16& source_value) { +double ConvertFromString<double>(const base::string16& source_value, + double default_value) { double ret = 0; - return base::StringToDouble(base::UTF16ToUTF8(source_value), &ret) ? ret - : 0.0; + return base::StringToDouble(base::UTF16ToUTF8(source_value), &ret) + ? ret + : default_value; } template <> -bool ConvertFromString<bool>(const base::string16& source_value) { - return source_value == base::ASCIIToUTF16("true"); +bool ConvertFromString<bool>(const base::string16& source_value, + bool default_value) { + if (source_value == base::ASCIIToUTF16("false")) + return false; + return source_value == base::ASCIIToUTF16("true") || default_value; } } // namespace metadata
diff --git a/ui/views/metadata/type_conversion.h b/ui/views/metadata/type_conversion.h index 72700e3..a37ceae 100644 --- a/ui/views/metadata/type_conversion.h +++ b/ui/views/metadata/type_conversion.h
@@ -33,17 +33,23 @@ class TypeConverter { public: static TTarget Convert(ArgType<TSource>) = delete; + static TTarget Convert(ArgType<TSource>, ArgType<TTarget>) = delete; private: TypeConverter(); }; -// Master Type Conversion Function -------------------------------------------- +// Master Type Conversion Functions -------------------------------------------- template <typename TSource, typename TTarget> TTarget Convert(ArgType<TSource> source_value) { return TypeConverter<TSource, TTarget>::Convert(source_value); } +template <typename TSource, typename TTarget> +TTarget Convert(ArgType<TSource> source_value, ArgType<TTarget> default_value) { + return TypeConverter<TSource, TTarget>::Convert(source_value, default_value); +} + // String Conversions --------------------------------------------------------- template <typename TSource> @@ -106,58 +112,74 @@ static base::string16 Convert(const base::string16& source_val) { return ConvertToString<base::string16>(source_val); } + static base::string16 Convert(const base::string16& source_val, + const base::string16& default_value) { + return ConvertToString<base::string16>(source_val); + } }; template <typename TTarget> -TTarget ConvertFromString(const base::string16& source_value) = delete; +TTarget ConvertFromString(const base::string16&, ArgType<TTarget>) = delete; template <> VIEWS_EXPORT int8_t -ConvertFromString<int8_t>(const base::string16& source_value); +ConvertFromString<int8_t>(const base::string16& source_value, + int8_t default_value); template <> VIEWS_EXPORT int16_t -ConvertFromString<int16_t>(const base::string16& source_value); +ConvertFromString<int16_t>(const base::string16& source_value, + int16_t default_value); template <> VIEWS_EXPORT int32_t -ConvertFromString<int32_t>(const base::string16& source_value); +ConvertFromString<int32_t>(const base::string16& source_value, + int32_t default_value); template <> VIEWS_EXPORT int64_t -ConvertFromString<int64_t>(const base::string16& source_value); +ConvertFromString<int64_t>(const base::string16& source_value, + int64_t default_value); template <> VIEWS_EXPORT uint8_t -ConvertFromString<uint8_t>(const base::string16& source_value); +ConvertFromString<uint8_t>(const base::string16& source_value, + uint8_t default_value); template <> VIEWS_EXPORT uint16_t -ConvertFromString<uint16_t>(const base::string16& source_value); +ConvertFromString<uint16_t>(const base::string16& source_value, + uint16_t default_value); template <> VIEWS_EXPORT uint32_t -ConvertFromString<uint32_t>(const base::string16& source_value); +ConvertFromString<uint32_t>(const base::string16& source_value, + uint32_t default_value); template <> VIEWS_EXPORT uint64_t -ConvertFromString<uint64_t>(const base::string16& source_value); +ConvertFromString<uint64_t>(const base::string16& source_value, + uint64_t default_value); template <> VIEWS_EXPORT double ConvertFromString<double>( - const base::string16& source_value); + const base::string16& source_value, + double default_value); template <> -VIEWS_EXPORT float ConvertFromString<float>(const base::string16& source_value); +VIEWS_EXPORT float ConvertFromString<float>(const base::string16& source_value, + float default_value); template <> -VIEWS_EXPORT bool ConvertFromString<bool>(const base::string16& source_value); +VIEWS_EXPORT bool ConvertFromString<bool>(const base::string16& source_value, + bool default_value); template <typename TTarget> class TypeConverter<base::string16, TTarget> { public: - static TTarget Convert(const base::string16& source_value) { - return ConvertFromString<TTarget>(source_value); + static TTarget Convert(const base::string16& source_value, + ArgType<TTarget> default_value) { + return ConvertFromString<TTarget>(source_value, default_value); } };
diff --git a/ui/views/metadata/type_conversion_unittest.cc b/ui/views/metadata/type_conversion_unittest.cc index b80d90c..7c7d432 100644 --- a/ui/views/metadata/type_conversion_unittest.cc +++ b/ui/views/metadata/type_conversion_unittest.cc
@@ -9,20 +9,30 @@ #include "testing/platform_test.h" #include "ui/gfx/geometry/rect.h" -namespace TC = views::metadata; +namespace VM = views::metadata; using TypeConversionTest = PlatformTest; TEST_F(TypeConversionTest, TestConversion_IntToString) { int from_int = 5; - base::string16 to_string = TC::Convert<int, base::string16>(from_int); + base::string16 to_string = VM::Convert<int, base::string16>(from_int); EXPECT_EQ(to_string, base::ASCIIToUTF16("5")); } TEST_F(TypeConversionTest, TestConversion_StringToInt) { base::string16 from_string = base::ASCIIToUTF16("10"); - int to_int = TC::Convert<base::string16, int>(from_string); + int to_int = VM::Convert<base::string16, int>(from_string, 0); EXPECT_EQ(to_int, 10); } + +// This tests whether the converter handles a bogus input string, in which case +// the default value should be returned. +TEST_F(TypeConversionTest, TestConversion_StringToIntDefault) { + const int default_value = 1000; + base::string16 from_string = base::ASCIIToUTF16("Foo"); + int to_int = VM::Convert<base::string16, int>(from_string, default_value); + + EXPECT_EQ(to_int, default_value); +}